From 3d8ed9efa2855f93b1e92415a32a35f36997bbda Mon Sep 17 00:00:00 2001 From: Jing Li Date: Mon, 2 Sep 2024 18:37:19 +0800 Subject: [PATCH 01/66] anolis: sw64: spi: convert SPI_MASTER_GPIO_SS to SPI_CONTROLLER_GPIO_SS ANBZ: #4688 SPI_MASTER_GPIO_SS is renamed to SPI_CONTROLLER_GPIO_SS. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/spi/spi-sunway.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-sunway.c b/drivers/spi/spi-sunway.c index 6133173ea09a..37de04209c3b 100644 --- a/drivers/spi/spi-sunway.c +++ b/drivers/spi/spi-sunway.c @@ -350,7 +350,7 @@ int spi_chip_add_host(struct device *dev, struct spi_chip *spi_chip) master->handle_err = spi_chip_handle_err; master->max_speed_hz = spi_chip->max_freq; master->dev.of_node = dev->of_node; - master->flags = SPI_MASTER_GPIO_SS; + master->flags = SPI_CONTROLLER_GPIO_SS; master->max_transfer_size = spi_chip_max_length; master->max_message_size = spi_chip_max_length; -- Gitee From 002dbab797ec2bf470e45178a412402b5e3259cf Mon Sep 17 00:00:00 2001 From: Jing Li Date: Sat, 20 Jul 2024 09:52:34 +0800 Subject: [PATCH 02/66] anolis: sw64: topology: support initializing topology via DT or ACPI ANBZ: #4688 Implement functions parse_acpi_topology() and parse_dt_topology() to support getting topology information from device tree or ACPI PPTT table. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 2 + arch/sw_64/include/asm/acpi.h | 7 + arch/sw_64/include/asm/topology.h | 13 -- arch/sw_64/kernel/topology.c | 356 ++++++++++++++++++++++-------- 4 files changed, 276 insertions(+), 102 deletions(-) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 30e63a5616fa..b0ca94497d24 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -5,6 +5,7 @@ config SW64 select ACPI select ACPI_GENERIC_GSI if ACPI select ACPI_MCFG if (ACPI && PCI) + select ACPI_PPTT if ACPI select ACPI_REDUCED_HARDWARE_ONLY select ARCH_ATOMIC select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI @@ -59,6 +60,7 @@ config SW64 select AUDIT_ARCH select COMMON_CLK select DMA_OPS if PCI + select GENERIC_ARCH_TOPOLOGY select GENERIC_CLOCKEVENTS select GENERIC_IRQ_LEGACY select GENERIC_IRQ_MIGRATION if SMP diff --git a/arch/sw_64/include/asm/acpi.h b/arch/sw_64/include/asm/acpi.h index ef46f481e1fd..7c3310168798 100644 --- a/arch/sw_64/include/asm/acpi.h +++ b/arch/sw_64/include/asm/acpi.h @@ -7,6 +7,7 @@ #include #include #include +#include #ifdef CONFIG_ACPI extern int acpi_noirq; @@ -105,6 +106,12 @@ static inline bool arch_has_acpi_pdc(void) static inline void arch_acpi_set_pdc_bits(u32 *buf) { } + +static inline u32 get_acpi_id_for_cpu(unsigned int cpu) +{ + /* We take rcid as processor _UID */ + return cpu_physical_id(cpu); +} #else /* !CONFIG_ACPI */ static inline void acpi_noirq_set(void) { } diff --git a/arch/sw_64/include/asm/topology.h b/arch/sw_64/include/asm/topology.h index c4da0cfcceff..48e66c51cfc9 100644 --- a/arch/sw_64/include/asm/topology.h +++ b/arch/sw_64/include/asm/topology.h @@ -9,19 +9,6 @@ #include #include -extern struct cpu_topology cpu_topology[NR_CPUS]; - -#define topology_physical_package_id(cpu) (cpu_topology[cpu].package_id) -#define topology_core_id(cpu) (cpu_topology[cpu].core_id) -#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) -#define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) -#define topology_llc_cpumask(cpu) (&cpu_topology[cpu].llc_sibling) - -void init_cpu_topology(void); -void store_cpu_topology(int cpuid); -void remove_cpu_topology(int cpuid); -const struct cpumask *cpu_coregroup_mask(int cpu); - static inline int rcid_to_thread_id(int rcid) { return (rcid & THREAD_ID_MASK) >> THREAD_ID_SHIFT; diff --git a/arch/sw_64/kernel/topology.c b/arch/sw_64/kernel/topology.c index b00f083517c3..2758b563b119 100644 --- a/arch/sw_64/kernel/topology.c +++ b/arch/sw_64/kernel/topology.c @@ -3,22 +3,14 @@ #include #include #include +#include +#include + #include #include #define OFFSET_SMP_INFO 0x80UL -static int __init parse_dt_topology(void) -{ - return 0; -} - -/* - * cpu topology table - */ -struct cpu_topology cpu_topology[NR_CPUS]; -EXPORT_SYMBOL_GPL(cpu_topology); - int topo_nr_threads, topo_nr_cores, topo_nr_maxcpus; static int topo_nr_cpus; @@ -91,126 +83,312 @@ static void __init init_topology_array(void) init_topo_packages(); } -const struct cpumask *cpu_coregroup_mask(int cpu) +/* + * This function returns the logic cpu number of the node. + * There are basically three kinds of return values: + * (1) logic cpu number which is > 0. + * (2) -ENODEV when the device tree(DT) node is valid and found in the DT but + * there is no possible logical CPU in the kernel to match. This happens + * when CONFIG_NR_CPUS is configure to be smaller than the number of + * CPU nodes in DT. We need to just ignore this case. + * (3) -1 if the node does not exist in the device tree + */ +static int __init get_cpu_for_node(struct device_node *node) { - return topology_llc_cpumask(cpu); -} + struct device_node *cpu_node; + int cpu; -static void update_siblings_masks(int cpu) -{ - struct cpu_topology *cpu_topo = &cpu_topology[cpu]; - int sib; + cpu_node = of_parse_phandle(node, "cpu", 0); + if (!cpu_node) + return -1; - /* update core and thread sibling masks */ - for_each_online_cpu(sib) { - struct cpu_topology *sib_topo = &cpu_topology[sib]; + cpu = of_cpu_node_to_id(cpu_node); + if (cpu >= 0) + topology_parse_cpu_capacity(cpu_node, cpu); + else + pr_info("CPU node for %pOF exist but the possible cpu range is :%*pbl\n", + cpu_node, cpumask_pr_args(cpu_possible_mask)); - if (cpu_topo->package_id == sib_topo->package_id) { - cpumask_set_cpu(cpu, &sib_topo->core_sibling); - cpumask_set_cpu(sib, &cpu_topo->core_sibling); - cpumask_set_cpu(cpu, &sib_topo->llc_sibling); - cpumask_set_cpu(sib, &cpu_topo->llc_sibling); + of_node_put(cpu_node); + return cpu; +} - if (cpu_topo->core_id == sib_topo->core_id) { - cpumask_set_cpu(cpu, &sib_topo->thread_sibling); - cpumask_set_cpu(sib, &cpu_topo->thread_sibling); +static int __init parse_core(struct device_node *core, int package_id, + int cluster_id, int core_id) +{ + char name[20]; + bool leaf = true; + int i = 0; + int cpu; + struct device_node *t; + + do { + snprintf(name, sizeof(name), "thread%d", i); + t = of_get_child_by_name(core, name); + if (t) { + leaf = false; + cpu = get_cpu_for_node(t); + if (cpu >= 0) { + cpu_topology[cpu].package_id = package_id; + cpu_topology[cpu].cluster_id = cluster_id; + cpu_topology[cpu].core_id = core_id; + cpu_topology[cpu].thread_id = i; + } else if (cpu != -ENODEV) { + pr_err("%pOF: Can't get CPU for thread\n", t); + of_node_put(t); + return -EINVAL; } + of_node_put(t); + } + i++; + } while (t); + + cpu = get_cpu_for_node(core); + if (cpu >= 0) { + if (!leaf) { + pr_err("%pOF: Core has both threads and CPU\n", + core); + return -EINVAL; } + + cpu_topology[cpu].package_id = package_id; + cpu_topology[cpu].cluster_id = cluster_id; + cpu_topology[cpu].core_id = core_id; + } else if (leaf && cpu != -ENODEV) { + pr_err("%pOF: Can't get CPU for leaf core\n", core); + return -EINVAL; } + + return 0; } -void store_cpu_topology(int cpu) +static int __init parse_cluster(struct device_node *cluster, int package_id, + int cluster_id, int depth) { - struct cpu_topology *cpu_topo = &cpu_topology[cpu]; + char name[20]; + bool leaf = true; + bool has_cores = false; + struct device_node *c; + int core_id = 0; + int i, ret; - if (cpu_topo->package_id != -1) - goto topology_populated; + /* + * First check for child clusters; we currently ignore any + * information about the nesting of clusters and present the + * scheduler with a flat list of them. + */ + i = 0; + do { + snprintf(name, sizeof(name), "cluster%d", i); + c = of_get_child_by_name(cluster, name); + if (c) { + leaf = false; + ret = parse_cluster(c, package_id, i, depth + 1); + if (depth > 0) + pr_warn("Topology for clusters of clusters not yet supported\n"); + of_node_put(c); + if (ret != 0) + return ret; + } + i++; + } while (c); + + /* Now check for cores */ + i = 0; + do { + snprintf(name, sizeof(name), "core%d", i); + c = of_get_child_by_name(cluster, name); + if (c) { + has_cores = true; + + if (depth == 0) { + pr_err("%pOF: cpu-map children should be clusters\n", + c); + of_node_put(c); + return -EINVAL; + } - if (is_guest_or_emul()) { - cpu_topo->package_id = topo_packages[cpu]; - cpu_topo->core_id = topo_cores[cpu]; - cpu_topo->thread_id = topo_threads[cpu]; - goto topology_populated; - } + if (leaf) { + ret = parse_core(c, package_id, cluster_id, + core_id++); + } else { + pr_err("%pOF: Non-leaf cluster with core %s\n", + cluster, name); + ret = -EINVAL; + } - cpu_topo->package_id = rcid_to_domain_id(cpu_to_rcid(cpu)); - cpu_topo->core_id = rcid_to_core_id(cpu_to_rcid(cpu)); - cpu_topo->thread_id = rcid_to_thread_id(cpu_to_rcid(cpu)); + of_node_put(c); + if (ret != 0) + return ret; + } + i++; + } while (c); - pr_debug("CPU%u: socket %d core %d thread %d\n", - cpu, cpu_topo->package_id, cpu_topo->core_id, - cpu_topo->thread_id); + if (leaf && !has_cores) + pr_warn("%pOF: empty cluster\n", cluster); -topology_populated: - update_siblings_masks(cpu); + return 0; } -static void clear_cpu_topology(int cpu) +static int __init parse_socket(struct device_node *socket) { - struct cpu_topology *cpu_topo = &cpu_topology[cpu]; + char name[20]; + struct device_node *c; + bool has_socket = false; + int package_id = 0, ret; + + do { + snprintf(name, sizeof(name), "socket%d", package_id); + c = of_get_child_by_name(socket, name); + if (c) { + has_socket = true; + ret = parse_cluster(c, package_id, -1, 0); + of_node_put(c); + if (ret != 0) + return ret; + } + package_id++; + } while (c); - cpumask_clear(&cpu_topo->llc_sibling); - cpumask_set_cpu(cpu, &cpu_topo->llc_sibling); + if (!has_socket) + ret = parse_cluster(socket, 0, -1, 0); - cpumask_clear(&cpu_topo->core_sibling); - cpumask_set_cpu(cpu, &cpu_topo->core_sibling); - cpumask_clear(&cpu_topo->thread_sibling); - cpumask_set_cpu(cpu, &cpu_topo->thread_sibling); + return ret; } -static void __init reset_cpu_topology(void) +static int __init parse_dt_topology(void) { + struct device_node *cn, *map; + int ret = 0; int cpu; - for_each_possible_cpu(cpu) { - struct cpu_topology *cpu_topo = &cpu_topology[cpu]; + cn = of_find_node_by_path("/cpus"); + if (!cn) { + pr_err("No CPU information found in DT\n"); + return 0; + } - cpu_topo->thread_id = -1; - cpu_topo->core_id = 0; - cpu_topo->package_id = -1; + /* + * When topology is provided cpu-map is essentially a root + * cluster with restricted subnodes. + */ + map = of_get_child_by_name(cn, "cpu-map"); + if (!map) + goto out; - clear_cpu_topology(cpu); - } -} + ret = parse_socket(map); + if (ret != 0) + goto out_map; -void remove_cpu_topology(int cpu) -{ - int sibling; + topology_normalize_cpu_scale(); - for_each_cpu(sibling, topology_core_cpumask(cpu)) - cpumask_clear_cpu(cpu, topology_core_cpumask(sibling)); - for_each_cpu(sibling, topology_sibling_cpumask(cpu)) - cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling)); - for_each_cpu(sibling, topology_llc_cpumask(cpu)) - cpumask_clear_cpu(cpu, topology_llc_cpumask(sibling)); + /* + * Check that all cores are in the topology; the SMP code will + * only mark cores described in the DT as possible. + */ + for_each_possible_cpu(cpu) + if (cpu_topology[cpu].package_id < 0) { + ret = -EINVAL; + break; + } - clear_cpu_topology(cpu); +out_map: + of_node_put(map); +out: + of_node_put(cn); + return ret; } #ifdef CONFIG_ACPI -static int __init parse_acpi_topology(void) +/* + * Propagate the topology information of the processor_topology_node tree to the + * cpu_topology array. + */ +int __init parse_acpi_topology(void) { + int cpu, topology_id; + + if (acpi_disabled) + return 0; + + for_each_possible_cpu(cpu) { + topology_id = find_acpi_cpu_topology(cpu, 0); + if (topology_id < 0) + return topology_id; + + if (acpi_pptt_cpu_is_thread(cpu) == 1) { + cpu_topology[cpu].thread_id = topology_id; + topology_id = find_acpi_cpu_topology(cpu, 1); + cpu_topology[cpu].core_id = topology_id; + } else { + cpu_topology[cpu].thread_id = -1; + cpu_topology[cpu].core_id = topology_id; + } + topology_id = find_acpi_cpu_topology_cluster(cpu); + cpu_topology[cpu].cluster_id = topology_id; + topology_id = find_acpi_cpu_topology_package(cpu); + cpu_topology[cpu].package_id = topology_id; + } + return 0; } -#else -static inline int __init parse_acpi_topology(void) -{ - return -EINVAL; -} #endif void __init init_cpu_topology(void) { + struct cpu_topology *boot_cpu_topo = &cpu_topology[0]; + int cpu, ret; + reset_cpu_topology(); + ret = parse_acpi_topology(); + if (!ret) + ret = of_have_populated_dt() && parse_dt_topology(); + + if (ret) { + /* + * Discard anything that was parsed if we hit an error so we + * don't use partial information. But do not return yet to give + * arch-specific early cache level detection a chance to run. + */ + reset_cpu_topology(); + } - if (is_guest_or_emul()) + /* Backward compatibility */ + if (is_guest_or_emul() && (boot_cpu_topo->package_id == -1)) init_topology_array(); - /* - * Discard anything that was parsed if we hit an error so we - * don't use partial information. - */ - if (!acpi_disabled && parse_acpi_topology()) - reset_cpu_topology(); - else if (of_have_populated_dt() && parse_dt_topology()) - reset_cpu_topology(); + + for_each_possible_cpu(cpu) { + ret = fetch_cache_info(cpu); + if (!ret) + continue; + else if (ret != -ENOENT) + pr_err("Early cacheinfo failed, ret = %d\n", ret); + return; + } +} + +void store_cpu_topology(unsigned int cpu) +{ + struct cpu_topology *cpu_topo = &cpu_topology[cpu]; + + if (cpu_topo->package_id != -1) + goto topology_populated; + + if (is_guest_or_emul()) { + cpu_topo->package_id = topo_packages[cpu]; + cpu_topo->core_id = topo_cores[cpu]; + cpu_topo->thread_id = topo_threads[cpu]; + goto topology_populated; + } + + cpu_topo->package_id = rcid_to_domain_id(cpu_to_rcid(cpu)); + cpu_topo->core_id = rcid_to_core_id(cpu_to_rcid(cpu)); + cpu_topo->thread_id = rcid_to_thread_id(cpu_to_rcid(cpu)); + + pr_debug("CPU%u: socket %d core %d thread %d\n", + cpu, cpu_topo->package_id, cpu_topo->core_id, + cpu_topo->thread_id); + +topology_populated: + update_siblings_masks(cpu); } -- Gitee From b523b89f0188be441c9869db7b26fbb00a2edaf6 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Mon, 22 Jul 2024 19:20:23 +0800 Subject: [PATCH 03/66] anolis: sw64: cpu: move cpu related code to the newly created cpu.c ANBZ: #4688 To improve the code structure, create the source file cpu.c to store cpu related code. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/cache.h | 28 ++++- arch/sw_64/include/asm/cpu.h | 99 +++++++++++++++++ arch/sw_64/include/asm/hw_init.h | 111 ------------------- arch/sw_64/include/asm/kvm_host.h | 1 + arch/sw_64/include/asm/mmu_context.h | 2 +- arch/sw_64/include/asm/sw64_init.h | 2 +- arch/sw_64/kernel/Makefile | 2 +- arch/sw_64/kernel/acpi.c | 1 + arch/sw_64/kernel/cacheinfo.c | 1 + arch/sw_64/kernel/chip_setup.c | 4 +- arch/sw_64/kernel/cpu.c | 154 +++++++++++++++++++++++++++ arch/sw_64/kernel/irq.c | 1 + arch/sw_64/kernel/setup.c | 152 -------------------------- arch/sw_64/kernel/smp.c | 2 +- arch/sw_64/kernel/time.c | 1 + arch/sw_64/kvm/sw64.c | 1 + arch/sw_64/lib/udelay.c | 2 + arch/sw_64/platform/cpufreq.c | 2 +- drivers/clocksource/timer-sw64.c | 2 +- 19 files changed, 293 insertions(+), 275 deletions(-) create mode 100644 arch/sw_64/kernel/cpu.c diff --git a/arch/sw_64/include/asm/cache.h b/arch/sw_64/include/asm/cache.h index 6a6ce4e99265..5848ebc23ffc 100644 --- a/arch/sw_64/include/asm/cache.h +++ b/arch/sw_64/include/asm/cache.h @@ -1,13 +1,33 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* - * include/asm/cache.h - */ + #ifndef _ASM_SW64_CACHE_H #define _ASM_SW64_CACHE_H #define L1_CACHE_SHIFT 7 #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) -#define SMP_CACHE_BYTES L1_CACHE_BYTES +#define CACHE_SIZE_SHIFT 0 +#define CACHE_SIZE_MASK (0xffffffffUL << CACHE_SIZE_SHIFT) +#define CACHE_SIZE(val) \ + (((val) & CACHE_SIZE_MASK) >> CACHE_SIZE_SHIFT) +#define CACHE_LINE_BITS_SHIFT 32 +#define CACHE_LINE_BITS_MASK (0xfUL << CACHE_LINE_BITS_SHIFT) +#define CACHE_LINE_BITS(val) \ + (((val) & CACHE_LINE_BITS_MASK) >> CACHE_LINE_BITS_SHIFT) +#define CACHE_INDEX_BITS_SHIFT 36 +#define CACHE_INDEX_BITS_MASK (0x3fUL << CACHE_INDEX_BITS_SHIFT) +#define CACHE_INDEX_BITS(val) \ + (((val) & CACHE_INDEX_BITS_MASK) >> CACHE_INDEX_BITS_SHIFT) + +#ifndef __ASSEMBLY__ + +enum sunway_cache_type { + L1_ICACHE = 0, + L1_DCACHE = 1, + L2_CACHE = 2, + L3_CACHE = 3 +}; + +#endif #endif /* _ASM_SW64_CACHE_H */ diff --git a/arch/sw_64/include/asm/cpu.h b/arch/sw_64/include/asm/cpu.h index 4da30bb91d89..962b2957bc03 100644 --- a/arch/sw_64/include/asm/cpu.h +++ b/arch/sw_64/include/asm/cpu.h @@ -1,5 +1,104 @@ /* SPDX-License-Identifier: GPL-2.0 */ + #ifndef _ASM_SW64_CPU_H #define _ASM_SW64_CPU_H +#include +#include + +#define TABLE_ENTRY_MAX 32 +#define VENDOR_ID_MAX 2 +#define MODEL_MAX 8 + +#define CPUID_ARCH_REV_MASK 0xf +#define CPUID_ARCH_REV(val) ((val) & CPUID_ARCH_REV_MASK) +#define CPUID_ARCH_VAR_SHIFT 4 +#define CPUID_ARCH_VAR_MASK (0xf << CPUID_ARCH_VAR_SHIFT) +#define CPUID_ARCH_VAR(val) \ + (((val) & CPUID_ARCH_VAR_MASK) >> CPUID_ARCH_VAR_SHIFT) +#define CPUID_CHIP_VAR_SHIFT 8 +#define CPUID_CHIP_VAR_MASK (0xf << CPUID_CHIP_VAR_SHIFT) +#define CPUID_CHIP_VAR(val) \ + (((val) & CPUID_CHIP_VAR_MASK) >> CPUID_CHIP_VAR_SHIFT) +#define CPUID_FAMILY_SHIFT 12 +#define CPUID_FAMILY_MASK (0xf << CPUID_FAMILY_SHIFT) +#define CPUID_FAMILY(val) \ + (((val) & CPUID_FAMILY_MASK) >> CPUID_FAMILY_SHIFT) +#define CPUID_MODEL_SHIFT 24 +#define CPUID_MODEL_MASK (0xff << CPUID_MODEL_SHIFT) +#define CPUID_MODEL(val) \ + (((val) & CPUID_MODEL_MASK) >> CPUID_MODEL_SHIFT) +#define CPUID_PA_BITS_SHIFT 32 +#define CPUID_PA_BITS_MASK (0x7fUL << CPUID_PA_BITS_SHIFT) +#define CPUID_PA_BITS(val) \ + (((val) & CPUID_PA_BITS_MASK) >> CPUID_PA_BITS_SHIFT) +#define CPUID_VA_BITS_SHIFT 39 +#define CPUID_VA_BITS_MASK (0x7fUL << CPUID_VA_BITS_SHIFT) +#define CPUID_VA_BITS(val) \ + (((val) & CPUID_VA_BITS_MASK) >> CPUID_VA_BITS_SHIFT) + +#define current_cpu_data cpu_data[smp_processor_id()] + +enum hmcall_cpuid_cmd { + GET_TABLE_ENTRY = 1, + GET_VENDOR_ID = 2, + GET_MODEL = 3, + GET_CPU_FREQ = 4, + GET_CACHE_INFO = 5 +}; + +enum sunway_cpu_model { + CPU_SW3231 = 0x31, + CPU_SW831 = 0x32, + CPU_SW8A = 0x41 +}; + +struct cache_desc { + unsigned int size; /* Bytes per way */ + unsigned int sets; /* Number of lines per set */ + unsigned char ways; /* Number of ways */ + unsigned char linesz; /* Size of line in bytes */ + unsigned char flags; /* Flags describing cache properties */ +}; + +struct cpuinfo_sw64 { + unsigned long last_asid; + unsigned long last_vpn; + unsigned long ipi_count; + struct cache_desc icache; /* Primary I-cache */ + struct cache_desc dcache; /* Primary D or combined I/D cache */ + struct cache_desc scache; /* Secondary cache */ + struct cache_desc tcache; /* Tertiary/split secondary cache */ +} __aligned(SMP_CACHE_BYTES); + +struct cpu_desc_t { + __u8 model; + __u8 family; + __u8 chip_var; + __u8 arch_var; + __u8 arch_rev; + __u8 pa_bits; + __u8 va_bits; + char vendor_id[16]; + char model_id[64]; + unsigned long frequency; +} __randomize_layout; + +extern struct cpuinfo_sw64 cpu_data[NR_CPUS]; +extern struct cpu_desc_t cpu_desc; +extern cpumask_t cpu_offline; + +extern void store_cpu_data(int cpu); +extern void __init setup_cpu_info(void); + +static inline unsigned long get_cpu_freq(void) +{ + return cpu_desc.frequency; +} + +static inline void update_cpu_freq(unsigned long khz) +{ + cpu_desc.frequency = khz * 1000; +} + #endif /* _ASM_SW64_CPU_H */ diff --git a/arch/sw_64/include/asm/hw_init.h b/arch/sw_64/include/asm/hw_init.h index 5af3336d5fd6..b2d36df86bf2 100644 --- a/arch/sw_64/include/asm/hw_init.h +++ b/arch/sw_64/include/asm/hw_init.h @@ -10,40 +10,6 @@ #define MM_SIZE __va(0x2040) #define VPCR_SHIFT 44 -/* - * Descriptor for a cache - */ -struct cache_desc { - unsigned int size; /* Bytes per way */ - unsigned int sets; /* Number of lines per set */ - unsigned char ways; /* Number of ways */ - unsigned char linesz; /* Size of line in bytes */ - unsigned char flags; /* Flags describing cache properties */ -}; - -struct cpuinfo_sw64 { - unsigned long last_asid; - unsigned long last_vpn; - unsigned long ipi_count; - struct cache_desc icache; /* Primary I-cache */ - struct cache_desc dcache; /* Primary D or combined I/D cache */ - struct cache_desc scache; /* Secondary cache */ - struct cache_desc tcache; /* Tertiary/split secondary cache */ -} __aligned(SMP_CACHE_BYTES); - -struct cpu_desc_t { - __u8 model; - __u8 family; - __u8 chip_var; - __u8 arch_var; - __u8 arch_rev; - __u8 pa_bits; - __u8 va_bits; - char vendor_id[16]; - char model_id[64]; - unsigned long frequency; -} __randomize_layout; - #define MAX_NUMSOCKETS 8 struct socket_desc_t { bool is_online; /* 1 for online, 0 for offline */ @@ -69,29 +35,14 @@ struct memmap_entry { enum memmap_types type; }; -extern struct cpuinfo_sw64 cpu_data[NR_CPUS]; -extern void store_cpu_data(int cpu); - -extern struct cpu_desc_t cpu_desc; extern struct socket_desc_t socket_desc[MAX_NUMSOCKETS]; extern int memmap_nr; extern struct memmap_entry memmap_map[MAX_NUMMEMMAPS]; -extern cpumask_t cpu_offline; extern bool memblock_initialized; int __init add_memmap_region(u64 addr, u64 size, enum memmap_types type); void __init process_memmap(void); -static inline unsigned long get_cpu_freq(void) -{ - return cpu_desc.frequency; -} - -static inline void update_cpu_freq(unsigned long khz) -{ - cpu_desc.frequency = khz * 1000; -} - #define EMUL_FLAG (0x1UL << 63) #define MM_SIZE_MASK (EMUL_FLAG - 1) @@ -106,66 +57,4 @@ DECLARE_STATIC_KEY_FALSE(hw_una_enabled); #define is_in_emul() static_branch_unlikely(&run_mode_emul_key) #define is_guest_or_emul() !static_branch_likely(&run_mode_host_key) -#define CPU_SW3231 0x31 -#define CPU_SW831 0x32 -#define CPU_SW8A 0x41 - -#define GET_TABLE_ENTRY 1 -#define GET_VENDOR_ID 2 -#define GET_MODEL 3 -#define GET_CPU_FREQ 4 -#define GET_CACHE_INFO 5 - -#define TABLE_ENTRY_MAX 32 -#define VENDOR_ID_MAX 2 -#define MODEL_MAX 8 -#define CACHE_INFO_MAX 4 - -#define L1_ICACHE 0 -#define L1_DCACHE 1 -#define L2_CACHE 2 -#define L3_CACHE 3 - -#define CPUID_ARCH_REV_MASK 0xf -#define CPUID_ARCH_REV(val) ((val) & CPUID_ARCH_REV_MASK) -#define CPUID_ARCH_VAR_SHIFT 4 -#define CPUID_ARCH_VAR_MASK (0xf << CPUID_ARCH_VAR_SHIFT) -#define CPUID_ARCH_VAR(val) \ - (((val) & CPUID_ARCH_VAR_MASK) >> CPUID_ARCH_VAR_SHIFT) -#define CPUID_CHIP_VAR_SHIFT 8 -#define CPUID_CHIP_VAR_MASK (0xf << CPUID_CHIP_VAR_SHIFT) -#define CPUID_CHIP_VAR(val) \ - (((val) & CPUID_CHIP_VAR_MASK) >> CPUID_CHIP_VAR_SHIFT) -#define CPUID_FAMILY_SHIFT 12 -#define CPUID_FAMILY_MASK (0xf << CPUID_FAMILY_SHIFT) -#define CPUID_FAMILY(val) \ - (((val) & CPUID_FAMILY_MASK) >> CPUID_FAMILY_SHIFT) -#define CPUID_MODEL_SHIFT 24 -#define CPUID_MODEL_MASK (0xff << CPUID_MODEL_SHIFT) -#define CPUID_MODEL(val) \ - (((val) & CPUID_MODEL_MASK) >> CPUID_MODEL_SHIFT) -#define CPUID_PA_BITS_SHIFT 32 -#define CPUID_PA_BITS_MASK (0x7fUL << CPUID_PA_BITS_SHIFT) -#define CPUID_PA_BITS(val) \ - (((val) & CPUID_PA_BITS_MASK) >> CPUID_PA_BITS_SHIFT) -#define CPUID_VA_BITS_SHIFT 39 -#define CPUID_VA_BITS_MASK (0x7fUL << CPUID_VA_BITS_SHIFT) -#define CPUID_VA_BITS(val) \ - (((val) & CPUID_VA_BITS_MASK) >> CPUID_VA_BITS_SHIFT) - - -#define CACHE_SIZE_SHIFT 0 -#define CACHE_SIZE_MASK (0xffffffffUL << CACHE_SIZE_SHIFT) -#define CACHE_SIZE(val) \ - (((val) & CACHE_SIZE_MASK) >> CACHE_SIZE_SHIFT) -#define CACHE_LINE_BITS_SHIFT 32 -#define CACHE_LINE_BITS_MASK (0xfUL << CACHE_LINE_BITS_SHIFT) -#define CACHE_LINE_BITS(val) \ - (((val) & CACHE_LINE_BITS_MASK) >> CACHE_LINE_BITS_SHIFT) -#define CACHE_INDEX_BITS_SHIFT 36 -#define CACHE_INDEX_BITS_MASK (0x3fUL << CACHE_INDEX_BITS_SHIFT) -#define CACHE_INDEX_BITS(val) \ - (((val) & CACHE_INDEX_BITS_MASK) >> CACHE_INDEX_BITS_SHIFT) -#define current_cpu_data cpu_data[smp_processor_id()] - #endif /* _ASM_SW64_HW_INIT_H */ diff --git a/arch/sw_64/include/asm/kvm_host.h b/arch/sw_64/include/asm/kvm_host.h index e2f367003509..221a7db26f0f 100644 --- a/arch/sw_64/include/asm/kvm_host.h +++ b/arch/sw_64/include/asm/kvm_host.h @@ -27,6 +27,7 @@ #include #include +#include #define last_vpn(cpu) (cpu_data[cpu].last_vpn) diff --git a/arch/sw_64/include/asm/mmu_context.h b/arch/sw_64/include/asm/mmu_context.h index 1ff7df9539c5..84dfb15b43bf 100644 --- a/arch/sw_64/include/asm/mmu_context.h +++ b/arch/sw_64/include/asm/mmu_context.h @@ -15,7 +15,7 @@ #define ASID_BITS 10 #endif -#include +#include #define last_asid(cpu) (cpu_data[cpu].last_asid) #define ASID_FIRST_VERSION (1UL << ASID_BITS) diff --git a/arch/sw_64/include/asm/sw64_init.h b/arch/sw_64/include/asm/sw64_init.h index 34a28e365ec6..20901ede574c 100644 --- a/arch/sw_64/include/asm/sw64_init.h +++ b/arch/sw_64/include/asm/sw64_init.h @@ -8,7 +8,7 @@ #include struct sw64_early_init_ops { - void (*setup_core_map)(struct cpumask *cpumask); + void (*setup_core_map)(void); unsigned long (*get_node_mem)(int nodeid); void (*get_smp_info)(void); }; diff --git a/arch/sw_64/kernel/Makefile b/arch/sw_64/kernel/Makefile index b5756003776f..18a3cab6a9b6 100644 --- a/arch/sw_64/kernel/Makefile +++ b/arch/sw_64/kernel/Makefile @@ -13,7 +13,7 @@ CFLAGS_REMOVE_insn.o = -pg CFLAGS_REMOVE_printk.o = -pg endif -obj-y := fpu.o traps.o process.o sys_sw64.o irq.o \ +obj-y := fpu.o traps.o process.o sys_sw64.o irq.o cpu.o \ signal.o setup.o ptrace.o time.o \ systbls.o dup_print.o chip_setup.o \ insn.o early_init.o topology.o cacheinfo.o \ diff --git a/arch/sw_64/kernel/acpi.c b/arch/sw_64/kernel/acpi.c index 515728920cfd..ebe344752035 100644 --- a/arch/sw_64/kernel/acpi.c +++ b/arch/sw_64/kernel/acpi.c @@ -6,6 +6,7 @@ #include #include +#include #include #ifdef CONFIG_ACPI_HOTPLUG_CPU diff --git a/arch/sw_64/kernel/cacheinfo.c b/arch/sw_64/kernel/cacheinfo.c index e340c53690a9..d56ba4d6b909 100644 --- a/arch/sw_64/kernel/cacheinfo.c +++ b/arch/sw_64/kernel/cacheinfo.c @@ -16,6 +16,7 @@ */ #include +#include #include /* Populates leaf and increments to next leaf */ diff --git a/arch/sw_64/kernel/chip_setup.c b/arch/sw_64/kernel/chip_setup.c index 211d673250c7..efc07f0d0cab 100644 --- a/arch/sw_64/kernel/chip_setup.c +++ b/arch/sw_64/kernel/chip_setup.c @@ -3,7 +3,7 @@ #include #include -#include +#include #include #define OFFSET_CORE_ONLINE 0x780UL @@ -38,7 +38,7 @@ static unsigned long __init get_node_mem(int nodeid) return __get_node_mem(nodeid); } -static void __init setup_core_map(struct cpumask *cpumask) +static void __init setup_core_map(void) { int i, j, cpu_num, cpuid, max_cores_per_cpu; unsigned long coreonline; diff --git a/arch/sw_64/kernel/cpu.c b/arch/sw_64/kernel/cpu.c new file mode 100644 index 000000000000..41c90c9391fd --- /dev/null +++ b/arch/sw_64/kernel/cpu.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include + +#include +#include +#include + +/* Map logical to physical */ +int __cpu_to_rcid[NR_CPUS]; +EXPORT_SYMBOL(__cpu_to_rcid); + +/* A collection of per-processor data. */ +struct cpuinfo_sw64 cpu_data[NR_CPUS]; +EXPORT_SYMBOL(cpu_data); + +struct cpu_desc_t cpu_desc; + +cpumask_t cpu_offline = CPU_MASK_NONE; + +/* Move global data into per-processor storage */ +void store_cpu_data(int cpu) +{ + cpu_data[cpu].last_asid = ASID_FIRST_VERSION; +} + +void __init setup_cpu_info(void) +{ + int i; + struct cache_desc *c; + unsigned long val; + + val = cpuid(GET_TABLE_ENTRY, 0); + cpu_desc.model = CPUID_MODEL(val); + cpu_desc.family = CPUID_FAMILY(val); + cpu_desc.chip_var = CPUID_CHIP_VAR(val); + cpu_desc.arch_var = CPUID_ARCH_VAR(val); + cpu_desc.arch_rev = CPUID_ARCH_REV(val); + cpu_desc.pa_bits = CPUID_PA_BITS(val); + cpu_desc.va_bits = CPUID_VA_BITS(val); + + for (i = 0; i < VENDOR_ID_MAX; i++) { + val = cpuid(GET_VENDOR_ID, i); + memcpy(cpu_desc.vendor_id + (i * 8), &val, 8); + } + + for (i = 0; i < MODEL_MAX; i++) { + val = cpuid(GET_MODEL, i); + memcpy(cpu_desc.model_id + (i * 8), &val, 8); + } + + cpu_desc.frequency = cpuid(GET_CPU_FREQ, 0) * 1000UL * 1000UL; + + for (i = 0; i < NR_CPUS; i++) { + c = &(cpu_data[i].icache); + val = cpuid(GET_CACHE_INFO, L1_ICACHE); + c->size = CACHE_SIZE(val); + c->linesz = 1 << (CACHE_LINE_BITS(val)); + c->sets = 1 << (CACHE_INDEX_BITS(val)); + c->ways = c->size / c->sets / c->linesz; + + c = &(cpu_data[i].dcache); + val = cpuid(GET_CACHE_INFO, L1_DCACHE); + c->size = CACHE_SIZE(val); + c->linesz = 1 << (CACHE_LINE_BITS(val)); + c->sets = 1 << (CACHE_INDEX_BITS(val)); + c->ways = c->size / c->sets / c->linesz; + + c = &(cpu_data[i].scache); + val = cpuid(GET_CACHE_INFO, L2_CACHE); + c->size = CACHE_SIZE(val); + c->linesz = 1 << (CACHE_LINE_BITS(val)); + c->sets = 1 << (CACHE_INDEX_BITS(val)); + c->ways = c->size / c->sets / c->linesz; + + c = &(cpu_data[i].tcache); + val = cpuid(GET_CACHE_INFO, L3_CACHE); + c->size = CACHE_SIZE(val); + c->linesz = 1 << (CACHE_LINE_BITS(val)); + c->sets = 1 << (CACHE_INDEX_BITS(val)); + c->ways = c->size / c->sets / c->linesz; + } +} + +static int show_cpuinfo(struct seq_file *f, void *slot) +{ + int i; + unsigned long freq; + + freq = cpuid(GET_CPU_FREQ, 0); + + for_each_online_cpu(i) { + /* + * glibc reads /proc/cpuinfo to determine the number of + * online processors, looking for lines beginning with + * "processor". Give glibc what it expects. + */ + seq_printf(f, "processor\t: %u\n" + "vendor_id\t: %s\n" + "cpu family\t: %d\n" + "model\t\t: %u\n" + "model name\t: %s CPU @ %lu.%lu%luGHz\n" + "cpu variation\t: %u\n" + "cpu revision\t: %u\n", + i, cpu_desc.vendor_id, cpu_desc.family, + cpu_desc.model, cpu_desc.model_id, + freq / 1000, (freq % 1000) / 100, + (freq % 100) / 10, + cpu_desc.arch_var, cpu_desc.arch_rev); + seq_printf(f, "cpu MHz\t\t: %lu.00\n" + "cache size\t: %u KB\n" + "physical id\t: %d\n" + "bogomips\t: %lu.%02lu\n", + get_cpu_freq() / 1000 / 1000, cpu_data[i].tcache.size >> 10, + cpu_topology[i].package_id, + loops_per_jiffy / (500000/HZ), + (loops_per_jiffy / (5000/HZ)) % 100); + + seq_printf(f, "flags\t\t: fpu simd vpn upn cpuid\n"); + seq_printf(f, "page size\t: %d\n", 8192); + seq_printf(f, "cache_alignment\t: %d\n", cpu_data[i].tcache.linesz); + seq_printf(f, "address sizes\t: %u bits physical, %u bits virtual\n\n", + cpu_desc.pa_bits, cpu_desc.va_bits); + } + + return 0; +} + +/* + * We show only CPU #0 info. + */ +static void *c_start(struct seq_file *f, loff_t *pos) +{ + return *pos < 1 ? (void *)1 : NULL; +} + +static void *c_next(struct seq_file *f, void *v, loff_t *pos) +{ + (*pos)++; + return NULL; +} + +static void c_stop(struct seq_file *f, void *v) +{ +} + +const struct seq_operations cpuinfo_op = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_cpuinfo, +}; diff --git a/arch/sw_64/kernel/irq.c b/arch/sw_64/kernel/irq.c index 5706df471a8d..d916a484b2fb 100644 --- a/arch/sw_64/kernel/irq.c +++ b/arch/sw_64/kernel/irq.c @@ -17,6 +17,7 @@ #include #include +#include #include volatile unsigned long irq_err_count; diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index b735fe0e3e59..c7712c9eca06 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -39,9 +39,6 @@ #define DBGDCONT(args...) #endif -int __cpu_to_rcid[NR_CPUS]; /* Map logical to physical */ -EXPORT_SYMBOL(__cpu_to_rcid); - DEFINE_PER_CPU(unsigned long, hard_node_id) = { 0 }; static DEFINE_PER_CPU(struct cpu, cpu_devices); @@ -63,9 +60,6 @@ static struct notifier_block sw64_panic_block = { INT_MAX /* try to do it first */ }; -/* the value is IOR: CORE_ONLIE*/ -cpumask_t core_start = CPU_MASK_NONE; - static struct resource data_resource = { .name = "Kernel data", .start = 0, @@ -87,24 +81,17 @@ static struct resource bss_resource = { .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; -/* A collection of per-processor data. */ -struct cpuinfo_sw64 cpu_data[NR_CPUS]; -EXPORT_SYMBOL(cpu_data); - DEFINE_STATIC_KEY_TRUE(run_mode_host_key); DEFINE_STATIC_KEY_FALSE(run_mode_guest_key); DEFINE_STATIC_KEY_FALSE(run_mode_emul_key); DEFINE_STATIC_KEY_FALSE(hw_una_enabled); -struct cpu_desc_t cpu_desc; struct socket_desc_t socket_desc[MAX_NUMSOCKETS]; int memmap_nr; struct memmap_entry memmap_map[MAX_NUMMEMMAPS]; bool memblock_initialized; -cpumask_t cpu_offline = CPU_MASK_NONE; - /* boot_params */ /** * Keep sunway_boot_params for backward compatibility. All related code @@ -140,14 +127,6 @@ struct screen_info screen_info = { }; EXPORT_SYMBOL(screen_info); -/* - * Move global data into per-processor storage. - */ -void store_cpu_data(int cpu) -{ - cpu_data[cpu].last_asid = ASID_FIRST_VERSION; -} - #ifdef CONFIG_HARDLOCKUP_DETECTOR_PERF u64 hw_nmi_get_sample_period(int watchdog_thresh) { @@ -613,64 +592,6 @@ static void __init device_tree_init(void) unflatten_device_tree(); } -static void __init setup_cpu_info(void) -{ - int i; - struct cache_desc *c; - unsigned long val; - - val = cpuid(GET_TABLE_ENTRY, 0); - cpu_desc.model = CPUID_MODEL(val); - cpu_desc.family = CPUID_FAMILY(val); - cpu_desc.chip_var = CPUID_CHIP_VAR(val); - cpu_desc.arch_var = CPUID_ARCH_VAR(val); - cpu_desc.arch_rev = CPUID_ARCH_REV(val); - cpu_desc.pa_bits = CPUID_PA_BITS(val); - cpu_desc.va_bits = CPUID_VA_BITS(val); - - for (i = 0; i < VENDOR_ID_MAX; i++) { - val = cpuid(GET_VENDOR_ID, i); - memcpy(cpu_desc.vendor_id + (i * 8), &val, 8); - } - - for (i = 0; i < MODEL_MAX; i++) { - val = cpuid(GET_MODEL, i); - memcpy(cpu_desc.model_id + (i * 8), &val, 8); - } - - cpu_desc.frequency = cpuid(GET_CPU_FREQ, 0) * 1000UL * 1000UL; - - for (i = 0; i < NR_CPUS; i++) { - c = &(cpu_data[i].icache); - val = cpuid(GET_CACHE_INFO, L1_ICACHE); - c->size = CACHE_SIZE(val); - c->linesz = 1 << (CACHE_LINE_BITS(val)); - c->sets = 1 << (CACHE_INDEX_BITS(val)); - c->ways = c->size / c->sets / c->linesz; - - c = &(cpu_data[i].dcache); - val = cpuid(GET_CACHE_INFO, L1_DCACHE); - c->size = CACHE_SIZE(val); - c->linesz = 1 << (CACHE_LINE_BITS(val)); - c->sets = 1 << (CACHE_INDEX_BITS(val)); - c->ways = c->size / c->sets / c->linesz; - - c = &(cpu_data[i].scache); - val = cpuid(GET_CACHE_INFO, L2_CACHE); - c->size = CACHE_SIZE(val); - c->linesz = 1 << (CACHE_LINE_BITS(val)); - c->sets = 1 << (CACHE_INDEX_BITS(val)); - c->ways = c->size / c->sets / c->linesz; - - c = &(cpu_data[i].tcache); - val = cpuid(GET_CACHE_INFO, L3_CACHE); - c->size = CACHE_SIZE(val); - c->linesz = 1 << (CACHE_LINE_BITS(val)); - c->sets = 1 << (CACHE_INDEX_BITS(val)); - c->ways = c->size / c->sets / c->linesz; - } -} - #ifdef CONFIG_SUBARCH_C3B static void __init setup_run_mode(void) { @@ -821,79 +742,6 @@ setup_arch(char **cmdline_p) } } -static int -show_cpuinfo(struct seq_file *f, void *slot) -{ - int i; - unsigned long cpu_freq; - - cpu_freq = cpuid(GET_CPU_FREQ, 0); - - for_each_online_cpu(i) { - /* - * glibc reads /proc/cpuinfo to determine the number of - * online processors, looking for lines beginning with - * "processor". Give glibc what it expects. - */ - seq_printf(f, "processor\t: %u\n" - "vendor_id\t: %s\n" - "cpu family\t: %d\n" - "model\t\t: %u\n" - "model name\t: %s CPU @ %lu.%lu%luGHz\n" - "cpu variation\t: %u\n" - "cpu revision\t: %u\n", - i, cpu_desc.vendor_id, cpu_desc.family, - cpu_desc.model, cpu_desc.model_id, - cpu_freq / 1000, (cpu_freq % 1000) / 100, - (cpu_freq % 100) / 10, - cpu_desc.arch_var, cpu_desc.arch_rev); - seq_printf(f, "cpu MHz\t\t: %lu.00\n" - "cache size\t: %u KB\n" - "physical id\t: %d\n" - "bogomips\t: %lu.%02lu\n", - get_cpu_freq() / 1000 / 1000, cpu_data[i].tcache.size >> 10, - cpu_topology[i].package_id, - loops_per_jiffy / (500000/HZ), - (loops_per_jiffy / (5000/HZ)) % 100); - - seq_printf(f, "flags\t\t: fpu simd vpn upn cpuid\n"); - seq_printf(f, "page size\t: %d\n", 8192); - seq_printf(f, "cache_alignment\t: %d\n", cpu_data[i].tcache.linesz); - seq_printf(f, "address sizes\t: %u bits physical, %u bits virtual\n\n", - cpu_desc.pa_bits, cpu_desc.va_bits); - } - return 0; -} - -/* - * We show only CPU #0 info. - */ -static void * -c_start(struct seq_file *f, loff_t *pos) -{ - return *pos < 1 ? (void *)1 : NULL; -} - -static void * -c_next(struct seq_file *f, void *v, loff_t *pos) -{ - (*pos)++; - return NULL; -} - -static void -c_stop(struct seq_file *f, void *v) -{ -} - -const struct seq_operations cpuinfo_op = { - .start = c_start, - .next = c_next, - .stop = c_stop, - .show = show_cpuinfo, -}; - - static int sw64_panic_event(struct notifier_block *this, unsigned long event, void *ptr) { diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index a9577cd91515..b85e3af028d7 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -397,7 +397,7 @@ void __init setup_smp(void) init_cpu_present(cpu_none_mask); /* Legacy core detect */ - sw64_chip_init->early_init.setup_core_map(&core_start); + sw64_chip_init->early_init.setup_core_map(); /* For unified kernel, NR_CPUS is the maximum possible value */ for (i = 0; i < NR_CPUS; i++) { diff --git a/arch/sw_64/kernel/time.c b/arch/sw_64/kernel/time.c index 533a6a14c200..6eaf8fab4f28 100644 --- a/arch/sw_64/kernel/time.c +++ b/arch/sw_64/kernel/time.c @@ -5,6 +5,7 @@ #include #include +#include #include #include diff --git a/arch/sw_64/kvm/sw64.c b/arch/sw_64/kvm/sw64.c index d0510e567c32..99f7df5468fe 100644 --- a/arch/sw_64/kvm/sw64.c +++ b/arch/sw_64/kvm/sw64.c @@ -15,6 +15,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include "trace.h" diff --git a/arch/sw_64/lib/udelay.c b/arch/sw_64/lib/udelay.c index 59ca8a97d748..c60601d56b0e 100644 --- a/arch/sw_64/lib/udelay.c +++ b/arch/sw_64/lib/udelay.c @@ -7,6 +7,8 @@ #include +#include + /* * Use only for very small delays (< 1 msec). * diff --git a/arch/sw_64/platform/cpufreq.c b/arch/sw_64/platform/cpufreq.c index 69d7611a2fb0..0d552d9a753d 100644 --- a/arch/sw_64/platform/cpufreq.c +++ b/arch/sw_64/platform/cpufreq.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/clocksource/timer-sw64.c b/drivers/clocksource/timer-sw64.c index 5dad3496c0a0..e3720a3a1df4 100644 --- a/drivers/clocksource/timer-sw64.c +++ b/drivers/clocksource/timer-sw64.c @@ -8,9 +8,9 @@ #include #include +#include #include #include -#include #include #define DEFAULT_MCLK 25000 /* Khz */ -- Gitee From f17de6627f442b6a94b9d57de0ce3ba29dae871f Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 23 Jul 2024 16:50:04 +0800 Subject: [PATCH 04/66] anolis: sw64: cache: refactor cacheinfo related code ANBZ: #4688 Remove struct cache_desc and separate the initialization of cache information from the initialization of cpu information to improve code readability. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/cache.h | 13 ---- arch/sw_64/include/asm/cpu.h | 16 ++--- arch/sw_64/kernel/cacheinfo.c | 117 ++++++++++++++++++++++----------- arch/sw_64/kernel/cpu.c | 40 ++--------- 4 files changed, 91 insertions(+), 95 deletions(-) diff --git a/arch/sw_64/include/asm/cache.h b/arch/sw_64/include/asm/cache.h index 5848ebc23ffc..411218f5eb0e 100644 --- a/arch/sw_64/include/asm/cache.h +++ b/arch/sw_64/include/asm/cache.h @@ -6,19 +6,6 @@ #define L1_CACHE_SHIFT 7 #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) -#define CACHE_SIZE_SHIFT 0 -#define CACHE_SIZE_MASK (0xffffffffUL << CACHE_SIZE_SHIFT) -#define CACHE_SIZE(val) \ - (((val) & CACHE_SIZE_MASK) >> CACHE_SIZE_SHIFT) -#define CACHE_LINE_BITS_SHIFT 32 -#define CACHE_LINE_BITS_MASK (0xfUL << CACHE_LINE_BITS_SHIFT) -#define CACHE_LINE_BITS(val) \ - (((val) & CACHE_LINE_BITS_MASK) >> CACHE_LINE_BITS_SHIFT) -#define CACHE_INDEX_BITS_SHIFT 36 -#define CACHE_INDEX_BITS_MASK (0x3fUL << CACHE_INDEX_BITS_SHIFT) -#define CACHE_INDEX_BITS(val) \ - (((val) & CACHE_INDEX_BITS_MASK) >> CACHE_INDEX_BITS_SHIFT) - #ifndef __ASSEMBLY__ enum sunway_cache_type { diff --git a/arch/sw_64/include/asm/cpu.h b/arch/sw_64/include/asm/cpu.h index 962b2957bc03..77341687f99e 100644 --- a/arch/sw_64/include/asm/cpu.h +++ b/arch/sw_64/include/asm/cpu.h @@ -5,6 +5,7 @@ #include #include +#include #define TABLE_ENTRY_MAX 32 #define VENDOR_ID_MAX 2 @@ -53,22 +54,10 @@ enum sunway_cpu_model { CPU_SW8A = 0x41 }; -struct cache_desc { - unsigned int size; /* Bytes per way */ - unsigned int sets; /* Number of lines per set */ - unsigned char ways; /* Number of ways */ - unsigned char linesz; /* Size of line in bytes */ - unsigned char flags; /* Flags describing cache properties */ -}; - struct cpuinfo_sw64 { unsigned long last_asid; unsigned long last_vpn; unsigned long ipi_count; - struct cache_desc icache; /* Primary I-cache */ - struct cache_desc dcache; /* Primary D or combined I/D cache */ - struct cache_desc scache; /* Secondary cache */ - struct cache_desc tcache; /* Tertiary/split secondary cache */ } __aligned(SMP_CACHE_BYTES); struct cpu_desc_t { @@ -101,4 +90,7 @@ static inline void update_cpu_freq(unsigned long khz) cpu_desc.frequency = khz * 1000; } +extern unsigned int get_cpu_cache_size(int cpu, int level, enum cache_type type); +extern unsigned int get_cpu_cacheline_size(int cpu, int level, enum cache_type type); + #endif /* _ASM_SW64_CPU_H */ diff --git a/arch/sw_64/kernel/cacheinfo.c b/arch/sw_64/kernel/cacheinfo.c index d56ba4d6b909..69a32554e255 100644 --- a/arch/sw_64/kernel/cacheinfo.c +++ b/arch/sw_64/kernel/cacheinfo.c @@ -14,28 +14,75 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + #include #include #include +#include + +#define get_cache_info(type) cpuid(GET_CACHE_INFO, (type)) +#define get_cache_size(info) ((info) & 0xffffffffUL) +#define get_cacheline_size(info) (1 << (((info) >> 32) & 0xfUL)) +#define get_cache_sets(info) (1 << (((info) >> 36) & 0x3fUL)) +#define get_cache_ways(info) (get_cache_size(info) / get_cache_sets(info) / get_cacheline_size(info)) +#define cache_size(type) get_cache_size(get_cache_info((type))) +#define cache_level(type) ((type) < L2_CACHE ? 1 : (type)) /* Populates leaf and increments to next leaf */ -#define populate_cache(cache, leaf, c_level, c_type, c_id) \ -do { \ - leaf->id = c_id; \ - leaf->attributes = CACHE_ID; \ - leaf->type = c_type; \ - leaf->level = c_level; \ - leaf->coherency_line_size = c->cache.linesz; \ - leaf->number_of_sets = c->cache.sets; \ - leaf->ways_of_associativity = c->cache.ways; \ - leaf->size = c->cache.size; \ - leaf++; \ +#define populate_cache(cache_info, leaf, c_level, c_type, c_id) \ +do { \ + leaf->id = c_id; \ + leaf->attributes = CACHE_ID; \ + leaf->type = c_type; \ + leaf->level = c_level; \ + leaf->coherency_line_size = get_cacheline_size(cache_info); \ + leaf->number_of_sets = get_cache_sets(cache_info); \ + leaf->ways_of_associativity = get_cache_ways(cache_info); \ + leaf->size = get_cache_size(cache_info); \ + leaf++; \ } while (0) +static struct cacheinfo *get_cacheinfo(int cpu, int level, enum cache_type type) +{ + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); + struct cacheinfo *leaf; + int index; + + for (index = 0; index < this_cpu_ci->num_leaves; index++) { + leaf = this_cpu_ci->info_list + index; + if ((leaf->level == level) && (leaf->type == type)) + return leaf; + } + + return NULL; +} + +unsigned int get_cpu_cache_size(int cpu, int level, enum cache_type type) +{ + struct cacheinfo *leaf = get_cacheinfo(cpu, level, type); + + return leaf ? leaf->size : 0; +} + +unsigned int get_cpu_cacheline_size(int cpu, int level, enum cache_type type) +{ + struct cacheinfo *leaf = get_cacheinfo(cpu, level, type); + + return leaf ? leaf->coherency_line_size : 0; +} + + +static inline enum cache_type kernel_cache_type(enum sunway_cache_type type) +{ + if ((type > L1_DCACHE) || !cache_size(L1_ICACHE)) + return CACHE_TYPE_UNIFIED; + + return (type == L1_DCACHE) ? CACHE_TYPE_DATA : CACHE_TYPE_INST; +} + int init_cache_level(unsigned int cpu) { - struct cpuinfo_sw64 *c = &cpu_data[cpu]; struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); int levels = 0, leaves = 0; @@ -43,55 +90,51 @@ int init_cache_level(unsigned int cpu) * If Dcache is not set, we assume the cache structures * are not properly initialized. */ - if (c->dcache.size) + if (cache_size(L1_DCACHE)) levels += 1; else return -ENOENT; + leaves += cache_size(L1_ICACHE) ? 2 : 1; - leaves += (c->icache.size) ? 2 : 1; - - if (c->scache.size) { + if (cache_size(L2_CACHE)) { levels++; leaves++; } - if (c->tcache.size) { + if (cache_size(L3_CACHE)) { levels++; leaves++; } this_cpu_ci->num_levels = levels; this_cpu_ci->num_leaves = leaves; + return 0; } int populate_cache_leaves(unsigned int cpu) { - struct cpuinfo_sw64 *c = &cpu_data[cpu]; + enum sunway_cache_type type; struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cacheinfo *this_leaf = this_cpu_ci->info_list; struct cpu_topology *topo = &cpu_topology[cpu]; - if (c->icache.size) { - cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map); - populate_cache(dcache, this_leaf, 1, CACHE_TYPE_DATA, cpu); - cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map); - populate_cache(icache, this_leaf, 1, CACHE_TYPE_INST, cpu); - - } else { - cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map); - populate_cache(dcache, this_leaf, 1, CACHE_TYPE_UNIFIED, cpu); - } - - if (c->scache.size) { - cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map); - populate_cache(scache, this_leaf, 2, CACHE_TYPE_UNIFIED, cpu); - } - - if (c->tcache.size) { - cpumask_copy(&this_leaf->shared_cpu_map, topology_llc_cpumask(cpu)); - populate_cache(tcache, this_leaf, 3, CACHE_TYPE_UNIFIED, topo->package_id); + for (type = L1_ICACHE; type <= L3_CACHE; type++) { + if (!cache_size(type)) + continue; + + /* L3 Cache is shared */ + if (type == L3_CACHE) { + cpumask_copy(&this_leaf->shared_cpu_map, + topology_llc_cpumask(cpu)); + populate_cache(get_cache_info(type), this_leaf, cache_level(type), + kernel_cache_type(type), topo->package_id); + } else { + cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map); + populate_cache(get_cache_info(type), this_leaf, cache_level(type), + kernel_cache_type(type), cpu); + } } this_cpu_ci->cpu_map_populated = true; diff --git a/arch/sw_64/kernel/cpu.c b/arch/sw_64/kernel/cpu.c index 41c90c9391fd..574d70e4ed8c 100644 --- a/arch/sw_64/kernel/cpu.c +++ b/arch/sw_64/kernel/cpu.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include #include #include @@ -29,7 +30,6 @@ void store_cpu_data(int cpu) void __init setup_cpu_info(void) { int i; - struct cache_desc *c; unsigned long val; val = cpuid(GET_TABLE_ENTRY, 0); @@ -52,46 +52,20 @@ void __init setup_cpu_info(void) } cpu_desc.frequency = cpuid(GET_CPU_FREQ, 0) * 1000UL * 1000UL; - - for (i = 0; i < NR_CPUS; i++) { - c = &(cpu_data[i].icache); - val = cpuid(GET_CACHE_INFO, L1_ICACHE); - c->size = CACHE_SIZE(val); - c->linesz = 1 << (CACHE_LINE_BITS(val)); - c->sets = 1 << (CACHE_INDEX_BITS(val)); - c->ways = c->size / c->sets / c->linesz; - - c = &(cpu_data[i].dcache); - val = cpuid(GET_CACHE_INFO, L1_DCACHE); - c->size = CACHE_SIZE(val); - c->linesz = 1 << (CACHE_LINE_BITS(val)); - c->sets = 1 << (CACHE_INDEX_BITS(val)); - c->ways = c->size / c->sets / c->linesz; - - c = &(cpu_data[i].scache); - val = cpuid(GET_CACHE_INFO, L2_CACHE); - c->size = CACHE_SIZE(val); - c->linesz = 1 << (CACHE_LINE_BITS(val)); - c->sets = 1 << (CACHE_INDEX_BITS(val)); - c->ways = c->size / c->sets / c->linesz; - - c = &(cpu_data[i].tcache); - val = cpuid(GET_CACHE_INFO, L3_CACHE); - c->size = CACHE_SIZE(val); - c->linesz = 1 << (CACHE_LINE_BITS(val)); - c->sets = 1 << (CACHE_INDEX_BITS(val)); - c->ways = c->size / c->sets / c->linesz; - } } static int show_cpuinfo(struct seq_file *f, void *slot) { int i; + unsigned int l3_cache_size, l3_cachline_size; unsigned long freq; freq = cpuid(GET_CPU_FREQ, 0); for_each_online_cpu(i) { + l3_cache_size = get_cpu_cache_size(i, 3, CACHE_TYPE_UNIFIED); + l3_cachline_size = get_cpu_cacheline_size(i, 3, CACHE_TYPE_UNIFIED); + /* * glibc reads /proc/cpuinfo to determine the number of * online processors, looking for lines beginning with @@ -113,14 +87,14 @@ static int show_cpuinfo(struct seq_file *f, void *slot) "cache size\t: %u KB\n" "physical id\t: %d\n" "bogomips\t: %lu.%02lu\n", - get_cpu_freq() / 1000 / 1000, cpu_data[i].tcache.size >> 10, + get_cpu_freq() / 1000 / 1000, l3_cache_size >> 10, cpu_topology[i].package_id, loops_per_jiffy / (500000/HZ), (loops_per_jiffy / (5000/HZ)) % 100); seq_printf(f, "flags\t\t: fpu simd vpn upn cpuid\n"); seq_printf(f, "page size\t: %d\n", 8192); - seq_printf(f, "cache_alignment\t: %d\n", cpu_data[i].tcache.linesz); + seq_printf(f, "cache_alignment\t: %d\n", l3_cachline_size); seq_printf(f, "address sizes\t: %u bits physical, %u bits virtual\n\n", cpu_desc.pa_bits, cpu_desc.va_bits); } -- Gitee From c32dded0ab2241c7e418225954982c2ef369a25b Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 24 Jul 2024 09:07:35 +0800 Subject: [PATCH 05/66] anolis: sw64: cpu: refactor cpuinfo related code ANBZ: #4688 Remove struct cpu_desc_t to improve code readability. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/cpu.h | 61 +++------------------ arch/sw_64/kernel/chip_setup.c | 4 +- arch/sw_64/kernel/cpu.c | 93 +++++++++++++++++++++++++------- arch/sw_64/kernel/setup.c | 3 +- drivers/clocksource/timer-sw64.c | 2 +- 5 files changed, 86 insertions(+), 77 deletions(-) diff --git a/arch/sw_64/include/asm/cpu.h b/arch/sw_64/include/asm/cpu.h index 77341687f99e..e6f5cfdbaa3a 100644 --- a/arch/sw_64/include/asm/cpu.h +++ b/arch/sw_64/include/asm/cpu.h @@ -7,37 +7,6 @@ #include #include -#define TABLE_ENTRY_MAX 32 -#define VENDOR_ID_MAX 2 -#define MODEL_MAX 8 - -#define CPUID_ARCH_REV_MASK 0xf -#define CPUID_ARCH_REV(val) ((val) & CPUID_ARCH_REV_MASK) -#define CPUID_ARCH_VAR_SHIFT 4 -#define CPUID_ARCH_VAR_MASK (0xf << CPUID_ARCH_VAR_SHIFT) -#define CPUID_ARCH_VAR(val) \ - (((val) & CPUID_ARCH_VAR_MASK) >> CPUID_ARCH_VAR_SHIFT) -#define CPUID_CHIP_VAR_SHIFT 8 -#define CPUID_CHIP_VAR_MASK (0xf << CPUID_CHIP_VAR_SHIFT) -#define CPUID_CHIP_VAR(val) \ - (((val) & CPUID_CHIP_VAR_MASK) >> CPUID_CHIP_VAR_SHIFT) -#define CPUID_FAMILY_SHIFT 12 -#define CPUID_FAMILY_MASK (0xf << CPUID_FAMILY_SHIFT) -#define CPUID_FAMILY(val) \ - (((val) & CPUID_FAMILY_MASK) >> CPUID_FAMILY_SHIFT) -#define CPUID_MODEL_SHIFT 24 -#define CPUID_MODEL_MASK (0xff << CPUID_MODEL_SHIFT) -#define CPUID_MODEL(val) \ - (((val) & CPUID_MODEL_MASK) >> CPUID_MODEL_SHIFT) -#define CPUID_PA_BITS_SHIFT 32 -#define CPUID_PA_BITS_MASK (0x7fUL << CPUID_PA_BITS_SHIFT) -#define CPUID_PA_BITS(val) \ - (((val) & CPUID_PA_BITS_MASK) >> CPUID_PA_BITS_SHIFT) -#define CPUID_VA_BITS_SHIFT 39 -#define CPUID_VA_BITS_MASK (0x7fUL << CPUID_VA_BITS_SHIFT) -#define CPUID_VA_BITS(val) \ - (((val) & CPUID_VA_BITS_MASK) >> CPUID_VA_BITS_SHIFT) - #define current_cpu_data cpu_data[smp_processor_id()] enum hmcall_cpuid_cmd { @@ -55,12 +24,6 @@ enum sunway_cpu_model { }; struct cpuinfo_sw64 { - unsigned long last_asid; - unsigned long last_vpn; - unsigned long ipi_count; -} __aligned(SMP_CACHE_BYTES); - -struct cpu_desc_t { __u8 model; __u8 family; __u8 chip_var; @@ -68,27 +31,19 @@ struct cpu_desc_t { __u8 arch_rev; __u8 pa_bits; __u8 va_bits; - char vendor_id[16]; - char model_id[64]; - unsigned long frequency; -} __randomize_layout; + const char *vendor_id; + const char *model_id; + unsigned long last_asid; + unsigned long last_vpn; + unsigned long ipi_count; +} __aligned(SMP_CACHE_BYTES); extern struct cpuinfo_sw64 cpu_data[NR_CPUS]; -extern struct cpu_desc_t cpu_desc; extern cpumask_t cpu_offline; extern void store_cpu_data(int cpu); -extern void __init setup_cpu_info(void); - -static inline unsigned long get_cpu_freq(void) -{ - return cpu_desc.frequency; -} - -static inline void update_cpu_freq(unsigned long khz) -{ - cpu_desc.frequency = khz * 1000; -} +extern unsigned long get_cpu_freq(void); +extern void update_cpu_freq(unsigned long khz); extern unsigned int get_cpu_cache_size(int cpu, int level, enum cache_type type); extern unsigned int get_cpu_cacheline_size(int cpu, int level, enum cache_type type); diff --git a/arch/sw_64/kernel/chip_setup.c b/arch/sw_64/kernel/chip_setup.c index efc07f0d0cab..732943cb1859 100644 --- a/arch/sw_64/kernel/chip_setup.c +++ b/arch/sw_64/kernel/chip_setup.c @@ -196,7 +196,7 @@ static inline void intpu_save(void) { void __iomem *intpu_base = misc_platform_get_intpu_base(0); - switch (cpu_desc.model) { + switch (current_cpu_data.model) { case CPU_SW831: saved_long_time = readq(intpu_base + OFFSET_LONG_TIME); default: @@ -210,7 +210,7 @@ static inline void intpu_restore(void) void __iomem *spbu_base = misc_platform_get_spbu_base(0); void __iomem *gpio_base = misc_platform_get_gpio_base(0); - switch (cpu_desc.model) { + switch (current_cpu_data.model) { case CPU_SW831: writeq(saved_long_time, intpu_base + OFFSET_LONG_TIME); writeq(0x1, spbu_base + OFFSET_LONG_TIME_START_EN); diff --git a/arch/sw_64/kernel/cpu.c b/arch/sw_64/kernel/cpu.c index 574d70e4ed8c..339bef13366a 100644 --- a/arch/sw_64/kernel/cpu.c +++ b/arch/sw_64/kernel/cpu.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include #include @@ -9,6 +10,18 @@ #include #include +#define TABLE_ENTRY_MAX 32 +#define VENDOR_ID_MAX 2 +#define MODEL_MAX 8 + +#define cpuinfo_arch_rev(cpu_info) ((cpu_info) & 0xf) +#define cpuinfo_arch_var(cpu_info) (((cpu_info) >> 4) & 0xf) +#define cpuinfo_chip_var(cpu_info) (((cpu_info) >> 8) & 0xf) +#define cpuinfo_family(cpu_info) (((cpu_info) >> 12) & 0xf) +#define cpuinfo_model(cpu_info) (((cpu_info) >> 24) & 0xff) +#define cpuinfo_pa_bits(cpu_info) (((cpu_info) >> 32) & 0x7fUL) +#define cpuinfo_va_bits(cpu_info) (((cpu_info) >> 39) & 0x7fUL) + /* Map logical to physical */ int __cpu_to_rcid[NR_CPUS]; EXPORT_SYMBOL(__cpu_to_rcid); @@ -17,42 +30,79 @@ EXPORT_SYMBOL(__cpu_to_rcid); struct cpuinfo_sw64 cpu_data[NR_CPUS]; EXPORT_SYMBOL(cpu_data); -struct cpu_desc_t cpu_desc; - cpumask_t cpu_offline = CPU_MASK_NONE; +static unsigned long cpu_freq; +static unsigned long cpu_info; +static char vendor_id[16]; +static char model_id[64]; + +unsigned long get_cpu_freq(void) +{ + if (likely(cpu_freq)) + return cpu_freq; + + return cpuid(GET_CPU_FREQ, 0) * 1000UL * 1000UL; +} + +void update_cpu_freq(unsigned long khz) +{ + cpu_freq = khz * 1000; +} + /* Move global data into per-processor storage */ void store_cpu_data(int cpu) { cpu_data[cpu].last_asid = ASID_FIRST_VERSION; } -void __init setup_cpu_info(void) +static int cpuinfo_cpu_online(unsigned int cpu) { - int i; + /* Currently, cpu info is shared by all cores */ + cpu_data[cpu].model = cpuinfo_model(cpu_info); + cpu_data[cpu].family = cpuinfo_family(cpu_info); + cpu_data[cpu].chip_var = cpuinfo_chip_var(cpu_info); + cpu_data[cpu].arch_var = cpuinfo_arch_var(cpu_info); + cpu_data[cpu].arch_rev = cpuinfo_arch_rev(cpu_info); + cpu_data[cpu].pa_bits = cpuinfo_pa_bits(cpu_info); + cpu_data[cpu].va_bits = cpuinfo_va_bits(cpu_info); + + cpu_data[cpu].vendor_id = vendor_id; + cpu_data[cpu].model_id = model_id; + + return 0; +} + +static int __init sw64_cpuinfo_init(void) +{ + int i, ret; unsigned long val; - val = cpuid(GET_TABLE_ENTRY, 0); - cpu_desc.model = CPUID_MODEL(val); - cpu_desc.family = CPUID_FAMILY(val); - cpu_desc.chip_var = CPUID_CHIP_VAR(val); - cpu_desc.arch_var = CPUID_ARCH_VAR(val); - cpu_desc.arch_rev = CPUID_ARCH_REV(val); - cpu_desc.pa_bits = CPUID_PA_BITS(val); - cpu_desc.va_bits = CPUID_VA_BITS(val); + /* Get cpu info */ + cpu_info = cpuid(GET_TABLE_ENTRY, 0); + /* Get vendor name in string format */ for (i = 0; i < VENDOR_ID_MAX; i++) { val = cpuid(GET_VENDOR_ID, i); - memcpy(cpu_desc.vendor_id + (i * 8), &val, 8); + memcpy(vendor_id + (i * 8), &val, 8); } + /* Get model name in string format */ for (i = 0; i < MODEL_MAX; i++) { val = cpuid(GET_MODEL, i); - memcpy(cpu_desc.model_id + (i * 8), &val, 8); + memcpy(model_id + (i * 8), &val, 8); } - cpu_desc.frequency = cpuid(GET_CPU_FREQ, 0) * 1000UL * 1000UL; + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "sw64/cpuinfo:online", + cpuinfo_cpu_online, NULL); + if (ret < 0) { + pr_err("cpuinfo: failed to register cpuinfo_cpu_online\n"); + return ret; + } + + return 0; } +arch_initcall(sw64_cpuinfo_init); static int show_cpuinfo(struct seq_file *f, void *slot) { @@ -78,11 +128,11 @@ static int show_cpuinfo(struct seq_file *f, void *slot) "model name\t: %s CPU @ %lu.%lu%luGHz\n" "cpu variation\t: %u\n" "cpu revision\t: %u\n", - i, cpu_desc.vendor_id, cpu_desc.family, - cpu_desc.model, cpu_desc.model_id, + i, vendor_id, cpu_data[i].family, + cpu_data[i].model, model_id, freq / 1000, (freq % 1000) / 100, (freq % 100) / 10, - cpu_desc.arch_var, cpu_desc.arch_rev); + cpu_data[i].arch_var, cpu_data[i].arch_rev); seq_printf(f, "cpu MHz\t\t: %lu.00\n" "cache size\t: %u KB\n" "physical id\t: %d\n" @@ -96,7 +146,7 @@ static int show_cpuinfo(struct seq_file *f, void *slot) seq_printf(f, "page size\t: %d\n", 8192); seq_printf(f, "cache_alignment\t: %d\n", l3_cachline_size); seq_printf(f, "address sizes\t: %u bits physical, %u bits virtual\n\n", - cpu_desc.pa_bits, cpu_desc.va_bits); + cpu_data[i].pa_bits, cpu_data[i].va_bits); } return 0; @@ -126,3 +176,8 @@ const struct seq_operations cpuinfo_op = { .stop = c_stop, .show = show_cpuinfo, }; + +bool arch_match_cpu_phys_id(int cpu, u64 phys_id) +{ + return phys_id == cpu_physical_id(cpu); +} diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index c7712c9eca06..6c36fedfa6e3 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -49,7 +49,7 @@ static inline int phys_addr_valid(unsigned long addr) * and other physical address variables cannot be used, so let's * roughly judge physical address based on arch specific bit. */ - return !(addr >> (cpu_desc.pa_bits - 1)); + return !(addr >> (current_cpu_data.pa_bits - 1)); } extern struct atomic_notifier_head panic_notifier_list; @@ -648,7 +648,6 @@ setup_arch(char **cmdline_p) trap_init(); jump_label_init(); - setup_cpu_info(); setup_run_mode(); setup_chip_ops(); diff --git a/drivers/clocksource/timer-sw64.c b/drivers/clocksource/timer-sw64.c index e3720a3a1df4..8b022f455c78 100644 --- a/drivers/clocksource/timer-sw64.c +++ b/drivers/clocksource/timer-sw64.c @@ -94,7 +94,7 @@ static int longtime_enable(struct clocksource *cs) void __iomem *spbu_base = misc_platform_get_spbu_base(0); void __iomem *gpio_base = misc_platform_get_gpio_base(0); - switch (cpu_desc.model) { + switch (current_cpu_data.model) { case CPU_SW3231: writeq(0, gpio_base + OFFSET_GPIO_SWPORTA_DR); writeq(0xff, gpio_base + OFFSET_GPIO_SWPORTA_DDR); -- Gitee From e3abc8db63f22ecf25ae708ca725d368bff1f7a3 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 4 Sep 2024 18:26:51 +0800 Subject: [PATCH 06/66] anolis: sw64: cache: fix shared_cpu_map of cacheinfo ANBZ: #4688 Currently, L1 and L2 caches are privately owned by the physical core, which has two hardware threads in the JunZhang series. This means that two logical cores belonging to the same physical core share L1 and L2 caches. Besides, in the generic update_siblings_masks(), cache information is initialized before cpu siblings. Therefore, we cannot initialize shared_cpu_map with topology_llc_cpumask. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/cacheinfo.c | 49 ++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/arch/sw_64/kernel/cacheinfo.c b/arch/sw_64/kernel/cacheinfo.c index 69a32554e255..da24b0e5b989 100644 --- a/arch/sw_64/kernel/cacheinfo.c +++ b/arch/sw_64/kernel/cacheinfo.c @@ -18,7 +18,6 @@ #include #include -#include #include #define get_cache_info(type) cpuid(GET_CACHE_INFO, (type)) @@ -113,30 +112,56 @@ int init_cache_level(unsigned int cpu) return 0; } +static void setup_shared_cpu_map(unsigned int cpu) +{ + unsigned int index; + unsigned int rcid = cpu_to_rcid(cpu); + struct cacheinfo *this_leaf; + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); + + for (index = 0; index < this_cpu_ci->num_leaves; index++) { + unsigned int i; + + this_leaf = this_cpu_ci->info_list + index; + + cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map); + + for_each_possible_cpu(i) { + unsigned int sib_rcid = cpu_to_rcid(i); + + if ((rcid_to_domain_id(sib_rcid) != rcid_to_domain_id(rcid)) || + (i == cpu)) + continue; + + if ((rcid_to_core_id(rcid) == rcid_to_core_id(sib_rcid)) || + (this_leaf->level == 3)) + cpumask_set_cpu(i, &this_leaf->shared_cpu_map); + } + } +} + int populate_cache_leaves(unsigned int cpu) { enum sunway_cache_type type; + unsigned int cache_id; struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cacheinfo *this_leaf = this_cpu_ci->info_list; - struct cpu_topology *topo = &cpu_topology[cpu]; for (type = L1_ICACHE; type <= L3_CACHE; type++) { if (!cache_size(type)) continue; /* L3 Cache is shared */ - if (type == L3_CACHE) { - cpumask_copy(&this_leaf->shared_cpu_map, - topology_llc_cpumask(cpu)); - populate_cache(get_cache_info(type), this_leaf, cache_level(type), - kernel_cache_type(type), topo->package_id); - } else { - cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map); - populate_cache(get_cache_info(type), this_leaf, cache_level(type), - kernel_cache_type(type), cpu); - } + cache_id = (type == L3_CACHE) ? rcid_to_domain_id(cpu_to_rcid(cpu)) : + rcid_to_core_id(cpu_to_rcid(cpu)); + + populate_cache(get_cache_info(type), this_leaf, cache_level(type), + kernel_cache_type(type), cache_id); + } + setup_shared_cpu_map(cpu); + this_cpu_ci->cpu_map_populated = true; return 0; -- Gitee From 2395725371d155e5a0dc45f2e7597eb31e51591e Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 4 Sep 2024 19:50:08 +0800 Subject: [PATCH 07/66] anolis: sw64: cacheinfo: give preference to cache information from PPTT table ANBZ: #4688 We prefer the cache information provided by the firmware in ACPI PPTT table. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/cacheinfo.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/arch/sw_64/kernel/cacheinfo.c b/arch/sw_64/kernel/cacheinfo.c index da24b0e5b989..c8528cf9f3ba 100644 --- a/arch/sw_64/kernel/cacheinfo.c +++ b/arch/sw_64/kernel/cacheinfo.c @@ -16,6 +16,7 @@ */ #include +#include #include #include @@ -39,7 +40,6 @@ do { \ leaf->number_of_sets = get_cache_sets(cache_info); \ leaf->ways_of_associativity = get_cache_ways(cache_info); \ leaf->size = get_cache_size(cache_info); \ - leaf++; \ } while (0) static struct cacheinfo *get_cacheinfo(int cpu, int level, enum cache_type type) @@ -140,14 +140,32 @@ static void setup_shared_cpu_map(unsigned int cpu) } } +static bool is_pptt_cache_info_valid(void) +{ + struct acpi_table_header *table; + acpi_status status; + + if (is_guest_or_emul() || acpi_disabled) + return false; + + status = acpi_get_table(ACPI_SIG_PPTT, 0, &table); + if (ACPI_FAILURE(status)) + return false; + + acpi_put_table(table); + + return true; +} + int populate_cache_leaves(unsigned int cpu) { enum sunway_cache_type type; unsigned int cache_id; struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cacheinfo *this_leaf = this_cpu_ci->info_list; + bool pptt_valid = is_pptt_cache_info_valid(); - for (type = L1_ICACHE; type <= L3_CACHE; type++) { + for (type = L1_ICACHE; type <= L3_CACHE; type++, this_leaf++) { if (!cache_size(type)) continue; @@ -158,11 +176,15 @@ int populate_cache_leaves(unsigned int cpu) populate_cache(get_cache_info(type), this_leaf, cache_level(type), kernel_cache_type(type), cache_id); - } + if (pptt_valid) + this_leaf->attributes &= ~CACHE_ID; - setup_shared_cpu_map(cpu); + } - this_cpu_ci->cpu_map_populated = true; + if (!pptt_valid) { + setup_shared_cpu_map(cpu); + this_cpu_ci->cpu_map_populated = true; + } return 0; } -- Gitee From 468f08ebb785836197a13912a704d05b65697431 Mon Sep 17 00:00:00 2001 From: Deng Xiaoyun Date: Thu, 29 Aug 2024 15:43:54 +0800 Subject: [PATCH 08/66] anolis: sw64: fix judgements about legacy pci support ANBZ: #4688 Starting with junzhang-v2, the host kernel gets pci controller information from the device tree. Starting with junzhang, the guest kernel gets pci controller information from the device tree. In order to be compatible with traditional pci information acquisition method, we add relevant judgments. Signed-off-by: Deng Xiaoyun Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/pci/pci-legacy.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/pci/pci-legacy.c b/arch/sw_64/pci/pci-legacy.c index 8a9ac6f1146b..417852cbfe95 100644 --- a/arch/sw_64/pci/pci-legacy.c +++ b/arch/sw_64/pci/pci-legacy.c @@ -227,6 +227,20 @@ static bool __init is_any_rc_linkup_one_node(unsigned long node) return false; } +static bool __init is_sunway_legacy_pci(void) +{ + if (IS_ENABLED(CONFIG_SUBARCH_C3B)) + return true; + + if (sunway_machine_is_compatible("sunway,chip4")) + return true; + + if (is_in_host() && sunway_machine_is_compatible("sunway,junzhang")) + return true; + + return false; +} + void __init sw64_init_arch(void) { if (IS_ENABLED(CONFIG_PCI)) { @@ -238,8 +252,7 @@ void __init sw64_init_arch(void) if (!acpi_disabled) return; - if (!sunway_machine_is_compatible("sunway,chip3") && - !sunway_machine_is_compatible("sunway,junzhang")) + if (!is_sunway_legacy_pci()) return; sunway_legacy_pci = true; -- Gitee From a2e7744833bf174eca51da8724859b722732b8b3 Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Fri, 13 Sep 2024 07:20:49 +0000 Subject: [PATCH 09/66] anolis: sw64: iommu: fix NULL hose check ANBZ: #4688 Fix an oops issue of encountering NULL hose when using IOMMU ACPI initialization method. Fixes: 40c93f0b54f9 ("anolis: sw64: iommu: improve iommu initialization"). Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/iommu/sw64/iommu_v2.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/sw64/iommu_v2.c b/drivers/iommu/sw64/iommu_v2.c index d9e3b75e6c9e..bf4ff7d16d2a 100644 --- a/drivers/iommu/sw64/iommu_v2.c +++ b/drivers/iommu/sw64/iommu_v2.c @@ -971,6 +971,10 @@ static int sunway_iommu_acpi_init(void) return ret; for_each_iommu(iommu) { + hose = find_hose_by_rcid(iommu->node, iommu->index); + if (!hose) + continue; + if (!iommu->enabled || hose->iommu_enable) continue; @@ -978,7 +982,6 @@ static int sunway_iommu_acpi_init(void) iommu_index); iommu_device_register(&iommu->iommu, &sunway_iommu_ops, NULL); iommu_index++; - hose = find_hose_by_rcid(iommu->node, iommu->index); sunway_enable_iommu_func(hose); hose->iommu_enable = true; piu_flush_all(iommu); -- Gitee From c702d20acf50bbf4a62d49bac203dcfeb1a03c54 Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Sat, 14 Sep 2024 06:19:47 +0000 Subject: [PATCH 10/66] anolis: sw64: move handle_intx() into pci-intx handle ANBZ: #4688 Move handle_intx() function into pci_intx handle code. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/irq.h | 9 +++++ drivers/irqchip/irq-sunway-cpu.c | 53 --------------------------- drivers/irqchip/irq-sunway-pci-intx.c | 53 +++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 53 deletions(-) diff --git a/arch/sw_64/include/asm/irq.h b/arch/sw_64/include/asm/irq.h index de3530b687e0..6a2bc75ffe3f 100644 --- a/arch/sw_64/include/asm/irq.h +++ b/arch/sw_64/include/asm/irq.h @@ -38,6 +38,15 @@ struct acpi_madt_sw_lpc_intc; extern int __init sw64_add_gsi_domain_map(u32 gsi_base, u32 gsi_count, struct fwnode_handle *handle); +#ifdef CONFIG_SW64_PCI_INTX +extern void handle_intx(unsigned int offset); +#else +static inline void handle_intx(unsigned int offset) +{ + pr_crit("Enter PCI INTx, but no handle configured!\n"); +} +#endif + #ifdef CONFIG_SW64_PINTC extern int __init pintc_acpi_init(struct irq_domain *parent, struct acpi_madt_sw_pintc *pintc); diff --git a/drivers/irqchip/irq-sunway-cpu.c b/drivers/irqchip/irq-sunway-cpu.c index 4947805c33ab..9dddf6786eab 100644 --- a/drivers/irqchip/irq-sunway-cpu.c +++ b/drivers/irqchip/irq-sunway-cpu.c @@ -39,59 +39,6 @@ struct fwnode_handle *cintc_handle; -static void handle_intx(unsigned int offset) -{ - struct pci_controller *hose; - unsigned long value; - void __iomem *piu_ior0_base; - - hose = hose_head; - offset <<= 7; - for (hose = hose_head; hose; hose = hose->next) { - piu_ior0_base = hose->piu_ior0_base; - - value = readq(piu_ior0_base + INTACONFIG + offset); - if (value >> 63) { - value = value & (~(1UL << 62)); - writeq(value, (piu_ior0_base + INTACONFIG + offset)); - handle_irq(hose->int_irq); - value = value | (1UL << 62); - writeq(value, (piu_ior0_base + INTACONFIG + offset)); - } - - if (IS_ENABLED(CONFIG_PCIE_PME)) { - value = readq(piu_ior0_base + PMEINTCONFIG); - if (value >> 63) { - handle_irq(hose->service_irq); - writeq(value, (piu_ior0_base + PMEINTCONFIG)); - } - } - - if (IS_ENABLED(CONFIG_PCIEAER)) { - value = readq(piu_ior0_base + AERERRINTCONFIG); - if (value >> 63) { - handle_irq(hose->service_irq); - writeq(value, (piu_ior0_base + AERERRINTCONFIG)); - } - } - - if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE_SUNWAY)) { - value = readq(piu_ior0_base + HPINTCONFIG); - if (value >> 63) { - handle_irq(hose->service_irq); - writeq(value, (piu_ior0_base + HPINTCONFIG)); - } - - } - - if (hose->iommu_enable) { - value = readq(piu_ior0_base + IOMMUEXCPT_STATUS); - if (value >> 63) - handle_irq(hose->int_irq); - } - } -} - static void handle_device_interrupt(unsigned long irq_info) { unsigned int i; diff --git a/drivers/irqchip/irq-sunway-pci-intx.c b/drivers/irqchip/irq-sunway-pci-intx.c index a60262fafeb3..2d7df695bf49 100644 --- a/drivers/irqchip/irq-sunway-pci-intx.c +++ b/drivers/irqchip/irq-sunway-pci-intx.c @@ -7,6 +7,7 @@ #include #include #include +#include static DEFINE_RAW_SPINLOCK(legacy_lock); static void lock_legacy_lock(void) @@ -196,3 +197,55 @@ void __init sw64_init_irq(void) for (hose = hose_head; hose; hose = hose->next) setup_intx_irqs(hose); } + +void handle_intx(unsigned int offset) +{ + struct pci_controller *hose; + unsigned long value; + void __iomem *piu_ior0_base; + + hose = hose_head; + offset <<= 7; + for (hose = hose_head; hose; hose = hose->next) { + piu_ior0_base = hose->piu_ior0_base; + + value = readq(piu_ior0_base + INTACONFIG + offset); + if (value & PCI_INTX_VALID) { + value &= PCI_INTX_DISABLE; + writeq(value, (piu_ior0_base + INTACONFIG + offset)); + handle_irq(hose->int_irq); + value |= PCI_INTX_ENABLE; + writeq(value, (piu_ior0_base + INTACONFIG + offset)); + } + + if (IS_ENABLED(CONFIG_PCIE_PME)) { + value = readq(piu_ior0_base + PMEINTCONFIG); + if (value & PCI_INTX_VALID) { + handle_irq(hose->service_irq); + writeq(value, (piu_ior0_base + PMEINTCONFIG)); + } + } + + if (IS_ENABLED(CONFIG_PCIEAER)) { + value = readq(piu_ior0_base + AERERRINTCONFIG); + if (value & PCI_INTX_VALID) { + handle_irq(hose->service_irq); + writeq(value, (piu_ior0_base + AERERRINTCONFIG)); + } + } + + if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE_SUNWAY)) { + value = readq(piu_ior0_base + HPINTCONFIG); + if (value & PCI_INTX_VALID) { + handle_irq(hose->service_irq); + writeq(value, (piu_ior0_base + HPINTCONFIG)); + } + } + + if (hose->iommu_enable) { + value = readq(piu_ior0_base + IOMMUEXCPT_STATUS); + if (value & PCI_INTX_VALID) + handle_irq(hose->int_irq); + } + } +} -- Gitee From 8ebb50e52d1c54a1cc480eff0bca595d9f4de788 Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Wed, 25 Sep 2024 08:44:38 +0000 Subject: [PATCH 11/66] anolis: sw64: introduce a fine-grained intx mask/unmask system ANBZ: #4688 We have recently discovered an unexpected shutdown failure that if an intx irq arrived RC after removing its registered action, but before disabling the RC's INTxCONFIG, handle_intx() may accidentally re-enable it and keep sending it to CPU, causing CPU hang up and shutdown failure. This is because we are following a non-standard handle_irq procedure of not registering proper irq_mask/unmask callbacks. The kernel's handle_irq procedure provides an irq state check to return directly if an irq is relieved from its actions or is marked as disabled before actually handling the irq. This can avoid the re-enabling problem we've encountered easily and thoroughly. This patch introduces a more fine-grained irq_mask/unmask, which is capable of disabling a designated INTxCONFIG instead of enabling/disabling all 4 INTxCONFIGs every time to improve the efficiency. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/pci.h | 1 + drivers/irqchip/irq-sunway-pci-intx.c | 229 ++++++++++++++++---------- 2 files changed, 147 insertions(+), 83 deletions(-) diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index 9662fdd87cb1..3527b4a92413 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -236,6 +236,7 @@ extern int chip_pcie_configure(struct pci_controller *hose); #define PCI_INTX_ENABLE ((1UL) << 62) #define PCI_INTX_DISABLE ~((1UL) << 62) #define PCI_INTX_VALID (1UL << 63) +#define PCI_INTX_INTDST_MASK 0x3ffUL #define PCI_VENDOR_ID_JN 0x5656 #define PCI_DEVICE_ID_SW64_ROOT_BRIDGE 0x3231 diff --git a/drivers/irqchip/irq-sunway-pci-intx.c b/drivers/irqchip/irq-sunway-pci-intx.c index 2d7df695bf49..d6f23c666237 100644 --- a/drivers/irqchip/irq-sunway-pci-intx.c +++ b/drivers/irqchip/irq-sunway-pci-intx.c @@ -10,6 +10,13 @@ #include static DEFINE_RAW_SPINLOCK(legacy_lock); + +struct intx_chip_data { + struct pci_controller *hose; + unsigned long intxconfig[4]; + unsigned int offset; +}; + static void lock_legacy_lock(void) { raw_spin_lock(&legacy_lock); @@ -20,33 +27,34 @@ static void unlock_legacy_lock(void) raw_spin_unlock(&legacy_lock); } -static void set_intx(struct pci_controller *hose, unsigned long intx_conf) +struct intx_chip_data *alloc_intx_chip_data(u32 node) { - void __iomem *piu_ior0_base; + struct intx_chip_data *chip_data; - if (is_guest_or_emul()) - return; + if (WARN_ON(node >= MAX_NUMNODES)) + return NULL; - piu_ior0_base = hose->piu_ior0_base; + chip_data = kzalloc_node(sizeof(struct intx_chip_data), + GFP_KERNEL, node); + if (!chip_data) + chip_data = kzalloc(sizeof(struct intx_chip_data), + GFP_KERNEL); - if (IS_ENABLED(CONFIG_SUBARCH_C3B)) { - writeq(intx_conf | (0x8UL << 10), (piu_ior0_base + INTACONFIG)); - writeq(intx_conf | (0x4UL << 10), (piu_ior0_base + INTBCONFIG)); - writeq(intx_conf | (0x2UL << 10), (piu_ior0_base + INTCCONFIG)); - writeq(intx_conf | (0x1UL << 10), (piu_ior0_base + INTDCONFIG)); - } else { - writeq(intx_conf | (0x8UL << 10), (piu_ior0_base + INTDCONFIG)); - writeq(intx_conf | (0x4UL << 10), (piu_ior0_base + INTCCONFIG)); - writeq(intx_conf | (0x2UL << 10), (piu_ior0_base + INTBCONFIG)); - writeq(intx_conf | (0x1UL << 10), (piu_ior0_base + INTACONFIG)); - } + return chip_data; } -static int __assign_piu_intx_config(struct pci_controller *hose, cpumask_t *targets) +static int __assign_piu_intx_config(struct intx_chip_data *chip_data, + cpumask_t *targets) { - unsigned long intx_conf; + struct pci_controller *hose; + unsigned long intxconfig; + void __iomem *piu_ior0_base; unsigned int cpu; int thread, node, core, rcid; + unsigned int i; + + if (is_guest_or_emul()) + return 0; /* Use the last cpu in valid cpus to avoid core 0. */ cpu = cpumask_last(targets); @@ -56,89 +64,80 @@ static int __assign_piu_intx_config(struct pci_controller *hose, cpumask_t *targ node = rcid_to_domain_id(rcid); core = rcid_to_core_id(rcid); - if (IS_ENABLED(CONFIG_SUBARCH_C3B)) - intx_conf = core | (node << 6); - else - intx_conf = core | (thread << 6) | (node << 7); + hose = chip_data->hose; + piu_ior0_base = hose->piu_ior0_base; - set_intx(hose, intx_conf); + for (i = 0; i < 4; i++) { + intxconfig = chip_data->intxconfig[i]; + intxconfig &= ~PCI_INTX_INTDST_MASK; + if (IS_ENABLED(CONFIG_SUBARCH_C3B)) + intxconfig |= core | (node << 6); + else + intxconfig |= core | (thread << 6) | (node << 7); + + writeq(intxconfig, piu_ior0_base + INTACONFIG + (i << 7)); + chip_data->intxconfig[i] = intxconfig; + } return 0; } -static int assign_piu_intx_config(struct pci_controller *hose, cpumask_t *targets) +static int assign_piu_intx_config(struct intx_chip_data *chip_data, + cpumask_t *targets) { int ret; lock_legacy_lock(); - ret = __assign_piu_intx_config(hose, targets); + ret = __assign_piu_intx_config(chip_data, targets); unlock_legacy_lock(); return ret; } -static void intx_irq_enable(struct irq_data *irq_data) +static void set_intx_enable(struct irq_data *irq_data, u32 flag) { - struct pci_controller *hose = irq_data->chip_data; - unsigned long intx_conf; + struct intx_chip_data *chip_data = irq_data->chip_data; + struct pci_controller *hose; void __iomem *piu_ior0_base; + unsigned long intxconfig; + unsigned int i; - if (is_guest_or_emul()) + if (!chip_data) return; - BUG_ON(!hose); + hose = chip_data->hose; piu_ior0_base = hose->piu_ior0_base; - intx_conf = readq(piu_ior0_base + INTACONFIG); - intx_conf |= PCI_INTX_ENABLE; - writeq(intx_conf, (piu_ior0_base + INTACONFIG)); - - intx_conf = readq(piu_ior0_base + INTBCONFIG); - intx_conf |= PCI_INTX_ENABLE; - writeq(intx_conf, (piu_ior0_base + INTBCONFIG)); + for (i = 0; i < 4; i++) { + intxconfig = chip_data->intxconfig[i]; + if (flag) + intxconfig |= PCI_INTX_ENABLE; + else + intxconfig &= PCI_INTX_DISABLE; + writeq(intxconfig, piu_ior0_base + INTACONFIG + (i << 7)); + } +} - intx_conf = readq(piu_ior0_base + INTCCONFIG); - intx_conf |= PCI_INTX_ENABLE; - writeq(intx_conf, (piu_ior0_base + INTCCONFIG)); +static void intx_irq_enable(struct irq_data *irq_data) +{ + if (is_guest_or_emul()) + return; - intx_conf = readq(piu_ior0_base + INTDCONFIG); - intx_conf |= PCI_INTX_ENABLE; - writeq(intx_conf, (piu_ior0_base + INTDCONFIG)); + set_intx_enable(irq_data, 1); } static void intx_irq_disable(struct irq_data *irq_data) { - struct pci_controller *hose = irq_data->chip_data; - unsigned long intx_conf; - void __iomem *piu_ior0_base; - if (is_guest_or_emul()) return; - BUG_ON(!hose); - piu_ior0_base = hose->piu_ior0_base; - - intx_conf = readq(piu_ior0_base + INTACONFIG); - intx_conf &= PCI_INTX_DISABLE; - writeq(intx_conf, (piu_ior0_base + INTACONFIG)); - - intx_conf = readq(piu_ior0_base + INTBCONFIG); - intx_conf &= PCI_INTX_DISABLE; - writeq(intx_conf, (piu_ior0_base + INTBCONFIG)); - - intx_conf = readq(piu_ior0_base + INTCCONFIG); - intx_conf &= PCI_INTX_DISABLE; - writeq(intx_conf, (piu_ior0_base + INTCCONFIG)); - - intx_conf = readq(piu_ior0_base + INTDCONFIG); - intx_conf &= PCI_INTX_DISABLE; - writeq(intx_conf, (piu_ior0_base + INTDCONFIG)); + set_intx_enable(irq_data, 0); } static int intx_set_affinity(struct irq_data *irq_data, const struct cpumask *dest, bool force) { - struct pci_controller *hose = irq_data->chip_data; + struct intx_chip_data *chip_data = irq_data->chip_data; cpumask_t targets; int ret = 0; @@ -148,20 +147,62 @@ static int intx_set_affinity(struct irq_data *irq_data, cpumask_copy(&targets, dest); intx_irq_disable(irq_data); - ret = assign_piu_intx_config(hose, &targets); + ret = assign_piu_intx_config(chip_data, &targets); intx_irq_enable(irq_data); return ret; } +static void intx_mask_irq(struct irq_data *irq_data, u32 flag) +{ + struct intx_chip_data *chip_data = irq_data->chip_data; + struct pci_controller *hose; + void __iomem *piu_ior0_base; + unsigned long intxconfig; + unsigned int offset; + + if (!chip_data) + return; + + hose = chip_data->hose; + piu_ior0_base = hose->piu_ior0_base; + offset = chip_data->offset; + intxconfig = chip_data->intxconfig[offset]; + + if (flag) + intxconfig &= PCI_INTX_DISABLE; + else + intxconfig |= PCI_INTX_ENABLE; + + writeq(intxconfig, piu_ior0_base + INTACONFIG + (offset << 7)); +} + +static void intx_irq_mask(struct irq_data *irq_data) +{ + if (is_guest_or_emul()) + return; + + intx_mask_irq(irq_data, 1); +} + +static void intx_irq_unmask(struct irq_data *irq_data) +{ + if (is_guest_or_emul()) + return; + + intx_mask_irq(irq_data, 0); +} + static void noop(struct irq_data *d) {} static struct irq_chip sw64_intx_chip = { .name = "PCI_INTX", .irq_enable = intx_irq_enable, .irq_disable = intx_irq_disable, - .irq_set_affinity = intx_set_affinity, - .irq_ack = noop, + .irq_mask = intx_irq_mask, + .irq_unmask = intx_irq_unmask, + .irq_set_affinity = intx_set_affinity, + .irq_ack = noop, .flags = IRQCHIP_SKIP_SET_WAKE, }; @@ -170,8 +211,12 @@ void __weak set_pcieport_service_irq(struct pci_controller *hose) {} void setup_intx_irqs(struct pci_controller *hose) { unsigned long irq, node, val_node; + struct intx_chip_data *chip_data; + void __iomem *piu_ior0_base; + int i = 0; node = hose->node; + piu_ior0_base = hose->piu_ior0_base; if (!node_online(node)) val_node = next_node_in(node, node_online_map); @@ -182,8 +227,23 @@ void setup_intx_irqs(struct pci_controller *hose) WARN_ON(irq < 0); irq_set_chip_and_handler(irq, &sw64_intx_chip, handle_level_irq); irq_set_status_flags(irq, IRQ_LEVEL); - irq_set_chip_data(irq, hose); + + chip_data = alloc_intx_chip_data(val_node); + if (!chip_data) + return; + + chip_data->hose = hose; + + for (i = 0; i < 4; i++) { + if (IS_ENABLED(CONFIG_SUBARCH_C3B)) + chip_data->intxconfig[i] = (0x1UL << (3 - i)) << 10; + else + chip_data->intxconfig[i] = (0x1UL << i) << 10; + } + + irq_set_chip_data(irq, chip_data); hose->int_irq = irq; + irq_set_chip_and_handler(irq + 1, &dummy_irq_chip, handle_level_irq); hose->service_irq = irq + 1; @@ -200,22 +260,31 @@ void __init sw64_init_irq(void) void handle_intx(unsigned int offset) { + struct irq_data *irq_data; + struct intx_chip_data *chip_data; struct pci_controller *hose; unsigned long value; void __iomem *piu_ior0_base; hose = hose_head; - offset <<= 7; for (hose = hose_head; hose; hose = hose->next) { piu_ior0_base = hose->piu_ior0_base; - value = readq(piu_ior0_base + INTACONFIG + offset); - if (value & PCI_INTX_VALID) { - value &= PCI_INTX_DISABLE; - writeq(value, (piu_ior0_base + INTACONFIG + offset)); + value = readq(piu_ior0_base + INTACONFIG + (offset << 7)); + if ((value & (PCI_INTX_VALID)) && (value & PCI_INTX_ENABLE)) { + irq_data = irq_get_irq_data(hose->int_irq); + if (irq_data) { + chip_data = irq_data->chip_data; + if (chip_data) + chip_data->offset = offset; + } handle_irq(hose->int_irq); - value |= PCI_INTX_ENABLE; - writeq(value, (piu_ior0_base + INTACONFIG + offset)); + } + + if (hose->iommu_enable) { + value = readq(piu_ior0_base + IOMMUEXCPT_STATUS); + if (value & PCI_INTX_VALID) + handle_irq(hose->int_irq); } if (IS_ENABLED(CONFIG_PCIE_PME)) { @@ -241,11 +310,5 @@ void handle_intx(unsigned int offset) writeq(value, (piu_ior0_base + HPINTCONFIG)); } } - - if (hose->iommu_enable) { - value = readq(piu_ior0_base + IOMMUEXCPT_STATUS); - if (value & PCI_INTX_VALID) - handle_irq(hose->int_irq); - } } } -- Gitee From 0f75a9b06265b05f2ed491280c404bc4105b2d71 Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Fri, 27 Sep 2024 09:08:59 +0000 Subject: [PATCH 12/66] anolis: sw64: remove deprecated annotation in irq.h ANBZ: #4688 Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/irq.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/sw_64/include/asm/irq.h b/arch/sw_64/include/asm/irq.h index 6a2bc75ffe3f..ae837f19b2d8 100644 --- a/arch/sw_64/include/asm/irq.h +++ b/arch/sw_64/include/asm/irq.h @@ -2,12 +2,6 @@ #ifndef _ASM_SW64_IRQ_H #define _ASM_SW64_IRQ_H -/* - * arch/sw/include/asm/irq.h - * - * (C) 2012 OSKernel JN - */ - #include #define NR_VECTORS_PERCPU 256 -- Gitee From 8556d1950bd19d943772c169414845e65495dbd4 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Fri, 13 Sep 2024 09:04:12 +0800 Subject: [PATCH 13/66] anolis: sw64: provide a cleaner raw_smp_processor_id() ANBZ: #4688 Use cpu in thread_info directly. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/smp.h | 3 +-- arch/sw_64/kernel/asm-offsets.c | 3 --- arch/sw_64/kernel/process.c | 1 + 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/sw_64/include/asm/smp.h b/arch/sw_64/include/asm/smp.h index 33a73ca25a6b..4249b10dc550 100644 --- a/arch/sw_64/include/asm/smp.h +++ b/arch/sw_64/include/asm/smp.h @@ -50,8 +50,7 @@ extern void __init smp_rcb_init(struct smp_rcb_struct *smp_rcb_base_addr); #ifdef GENERATING_ASM_OFFSETS #define raw_smp_processor_id() (0) #else -#include -#define raw_smp_processor_id() (*((unsigned int *)((void *)current + TASK_CPU))) +#define raw_smp_processor_id() (current_thread_info()->cpu) #endif #define hard_smp_processor_id() cpu_to_rcid(raw_smp_processor_id()) diff --git a/arch/sw_64/kernel/asm-offsets.c b/arch/sw_64/kernel/asm-offsets.c index d865caffd014..c4e4e40a03d5 100644 --- a/arch/sw_64/kernel/asm-offsets.c +++ b/arch/sw_64/kernel/asm-offsets.c @@ -30,9 +30,6 @@ void foo(void) DEFINE(TASK_GROUP_LEADER, offsetof(struct task_struct, group_leader)); DEFINE(TASK_TGID, offsetof(struct task_struct, tgid)); DEFINE(TASK_STACK, offsetof(struct task_struct, stack)); -#ifdef CONFIG_SMP - DEFINE(TASK_CPU, offsetof(struct task_struct, thread_info.cpu)); -#endif BLANK(); OFFSET(PSTATE_REGS, processor_state, regs); diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index 1867abfe3380..eac26883cf69 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include -- Gitee From 3b4679451085f569db9f448d69fa08c7e617b4ca Mon Sep 17 00:00:00 2001 From: Jing Li Date: Fri, 13 Sep 2024 17:21:17 +0800 Subject: [PATCH 14/66] anolis: sw64: mm: support fdt memory reservation ANBZ: #4688 Now we can reserve memory via the device tree. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/mm/init.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sw_64/mm/init.c b/arch/sw_64/mm/init.c index 6e976d7b20e4..29ee809c3ac5 100644 --- a/arch/sw_64/mm/init.c +++ b/arch/sw_64/mm/init.c @@ -385,6 +385,8 @@ void __init sw64_memblock_init(void) } } + early_init_fdt_scan_reserved_mem(); + /* end of DRAM range may have been changed */ max_pfn = max_low_pfn = PFN_DOWN(memblock_end_of_DRAM()); } -- Gitee From 1d19f29f638c937ce7ff3e6993bbc5b38227183f Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Tue, 15 Oct 2024 14:16:40 +0800 Subject: [PATCH 15/66] anolis: sw64: perf: add core4 pmu support ANBZ: #4688 This patch introduces core4 pmu support to make perf work, and moves common callchain code into a standalone file. Signed-off-by: He Chuyue Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/csr.h | 4 + arch/sw_64/include/asm/perf_event.h | 17 ++++ arch/sw_64/include/asm/pmc_c4.h | 52 ++++++++++ arch/sw_64/kernel/Makefile | 7 +- arch/sw_64/kernel/perf_callchain.c | 142 ++++++++++++++++++++++++++++ arch/sw_64/kernel/perf_event.c | 138 --------------------------- arch/sw_64/kernel/perf_event_c4.c | 15 +-- 7 files changed, 230 insertions(+), 145 deletions(-) create mode 100644 arch/sw_64/include/asm/pmc_c4.h create mode 100644 arch/sw_64/kernel/perf_callchain.c diff --git a/arch/sw_64/include/asm/csr.h b/arch/sw_64/include/asm/csr.h index 9101e4c91fe1..dac5b6a29b47 100644 --- a/arch/sw_64/include/asm/csr.h +++ b/arch/sw_64/include/asm/csr.h @@ -29,6 +29,10 @@ #define CSR_PTBR_SYS 0x68 #define CSR_PTBR_USR 0x69 #define CSR_APTP 0x6a +#define CSR_IDR_PCCTL 0x7a +#define CSR_IACC 0x7b +#define CSR_IMISC 0x7c +#define CSR_RETIC 0x7f #define CSR_CID 0xc4 #define CSR_WR_FREGS 0xc8 #define CSR_SHTCLOCK 0xca diff --git a/arch/sw_64/include/asm/perf_event.h b/arch/sw_64/include/asm/perf_event.h index dc55a361babd..a92545694c65 100644 --- a/arch/sw_64/include/asm/perf_event.h +++ b/arch/sw_64/include/asm/perf_event.h @@ -2,8 +2,14 @@ #ifndef _ASM_SW64_PERF_EVENT_H #define _ASM_SW64_PERF_EVENT_H +#if defined(CONFIG_SUBARCH_C3B) #include +#elif defined(CONFIG_SUBARCH_C4) +#include +#endif #include +#include +#include #ifdef CONFIG_PERF_EVENTS struct pt_regs; @@ -13,4 +19,15 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs); #define perf_arch_bpf_user_pt_regs(regs) ®s->user_regs #endif +/* For tracking PMCs and the hw events they monitor on each CPU. */ +struct cpu_hw_events { + /* + * Set the bit (indexed by the counter number) when the counter + * is used for an event. + */ + unsigned long used_mask[BITS_TO_LONGS(MAX_HWEVENTS)]; + /* Array of events current scheduled on this cpu. */ + struct perf_event *event[MAX_HWEVENTS]; +}; + #endif /* _ASM_SW64_PERF_EVENT_H */ diff --git a/arch/sw_64/include/asm/pmc_c4.h b/arch/sw_64/include/asm/pmc_c4.h new file mode 100644 index 000000000000..cdee1041ce3b --- /dev/null +++ b/arch/sw_64/include/asm/pmc_c4.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Definitions for use with the sw64 wrperfmon HMCODE call. + */ + +#ifndef _ASM_SW64_WRPMC_H +#define _ASM_SW64_WRPMC_H + +/* Following commands are implemented on all CPUs */ +/* core4 */ +#define PMC_CMD_READ_PC0 5 +#define PMC_CMD_READ_PC1 6 +#define PMC_CMD_READ_PC2 7 +#define PMC_CMD_READ_PC3 8 +#define PMC_CMD_READ_PC4 9 +#define PMC_CMD_ENABLE 11 +#define PMC_CMD_DISABLE 12 +#define PMC_CMD_WRITE_BASE 16 + +#define PC_RAW_BASE 0x0 +#define PC_MAX 0x8D + +#define SW64_PERFCTRL_AM 0x0 +#define SW64_PERFCTRL_VM 0x3 +#define SW64_PERFCTRL_KM 0x5 +#define SW64_PERFCTRL_UM 0x7 + +/* pc0-4 events */ +#define SW64_PMU_INSTRUCTIONS 0x3 +#define SW64_PMU_BRANCH 0x4 +#define SW64_PMU_BRANCH_MISSES 0x5 +#define SW64_L1I_CACHE 0x6 +#define SW64_L1I_CACHE_MISSES 0x7 +#define SW64_PMU_CYCLE 0x30 +#define SW64_DTB 0x31 +#define SW64_DTB_MISSES 0x32 +#define SW64_L1D_CACHE 0x3D +#define SW64_L1D_CACHE_MISSES 0x3E +#define SW64_PMU_L2_REFERENCES 0x50 +#define SW64_PMU_L2_MISSES 0x53 + +#define PC_ALL_PM_SET 3 +#define MAX_HWEVENTS 5 +#define PMC_COUNT_MASK (-1UL) + +#define IACC_EN 0x4 +#define IMISC_EN 0x8 +#define RETIC_EN 0x10 +#define BRRETC_EN 0x20 +#define BRFAILC_EN 0x40 + +#endif /* _ASM_SW64_WRPMC_H */ diff --git a/arch/sw_64/kernel/Makefile b/arch/sw_64/kernel/Makefile index 18a3cab6a9b6..6b5172f50056 100644 --- a/arch/sw_64/kernel/Makefile +++ b/arch/sw_64/kernel/Makefile @@ -28,7 +28,7 @@ obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_SUSPEND) += suspend_asm.o suspend.o -obj-$(CONFIG_PERF_EVENTS) += perf_event.o +obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o obj-$(CONFIG_HIBERNATION) += hibernate_asm.o hibernate.o obj-$(CONFIG_AUDIT) += audit.o obj-$(CONFIG_RELOCATABLE) += relocate.o @@ -36,6 +36,11 @@ obj-$(CONFIG_DEBUG_FS) += segvdbg.o unaligned.o obj-$(CONFIG_JUMP_LABEL) += jump_label.o obj-$(CONFIG_DEBUG_MATCH) += match.o +ifdef CONFIG_PERF_EVENTS +obj-$(CONFIG_SUBARCH_C3B) += perf_event.o +obj-$(CONFIG_SUBARCH_C4) += perf_event_c4.o +endif + ifndef CONFIG_PCI obj-y += pci-noop.o endif diff --git a/arch/sw_64/kernel/perf_callchain.c b/arch/sw_64/kernel/perf_callchain.c new file mode 100644 index 000000000000..0c0a4c180919 --- /dev/null +++ b/arch/sw_64/kernel/perf_callchain.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * sw64 callchain support + * + * Copyright (C) 2023 SW64 Limited + */ +#include +#include + +#include + +bool valid_utext_addr(unsigned long addr) +{ + return addr >= current->mm->start_code && addr <= current->mm->end_code; +} + +bool valid_dy_addr(unsigned long addr) +{ + bool ret = false; + struct vm_area_struct *vma; + struct mm_struct *mm = current->mm; + + if (addr > TASK_SIZE || addr < TASK_UNMAPPED_BASE) + return ret; + vma = find_vma(mm, addr); + if (vma && vma->vm_start <= addr && (vma->vm_flags & VM_EXEC)) + ret = true; + return ret; +} + +#ifdef CONFIG_FRAME_POINTER +void perf_callchain_user(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) +{ + + struct stack_frame frame; + unsigned long __user *fp; + int err; + + perf_callchain_store(entry, regs->pc); + + fp = (unsigned long __user *)regs->regs[15]; + + while (entry->nr < entry->max_stack && + (unsigned long)fp < current->mm->start_stack) { + if (!access_ok(fp, sizeof(frame))) + break; + + pagefault_disable(); + err = __copy_from_user_inatomic(&frame, fp, sizeof(frame)); + pagefault_enable(); + + if (err) + break; + + if (valid_utext_addr(frame.return_address) || + valid_dy_addr(frame.return_address)) + perf_callchain_store(entry, frame.return_address); + else + break; + fp = (void __user *)frame.next_frame; + } +} +#else /* !CONFIG_FRAME_POINTER */ +void perf_callchain_user(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) +{ + unsigned long usp = current_user_stack_pointer(); + unsigned long user_addr; + int err; + + perf_callchain_store(entry, regs->pc); + + while (entry->nr < entry->max_stack && usp < current->mm->start_stack) { + if (!access_ok((const void __user *)usp, 8)) + break; + + pagefault_disable(); + err = __get_user(user_addr, (unsigned long *)usp); + pagefault_enable(); + + if (err) + break; + + if (valid_utext_addr(user_addr) || valid_dy_addr(user_addr)) + perf_callchain_store(entry, user_addr); + usp = usp + 8; + } +} +#endif/* CONFIG_FRAME_POINTER */ + +/* + * Gets called by walk_stackframe() for every stackframe. This will be called + * whist unwinding the stackframe and is like a subroutine return so we use + * the PC. + */ +static int callchain_trace(unsigned long pc, void *data) +{ + struct perf_callchain_entry_ctx *entry = data; + + perf_callchain_store(entry, pc); + return 0; +} + +void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) +{ + walk_stackframe(NULL, regs, callchain_trace, entry); +} + +/* + * Gets the perf_instruction_pointer and perf_misc_flags for guest os. + */ +#undef is_in_guest + +unsigned long perf_instruction_pointer(struct pt_regs *regs) +{ + if (perf_guest_state()) + return perf_guest_get_ip(); + + return instruction_pointer(regs); +} + +unsigned long perf_misc_flags(struct pt_regs *regs) +{ + unsigned int guest_state = perf_guest_state(); + int misc = 0; + + if (guest_state) { + if (guest_state & PERF_GUEST_USER) + misc |= PERF_RECORD_MISC_GUEST_USER; + else + misc |= PERF_RECORD_MISC_GUEST_KERNEL; + } else { + if (user_mode(regs)) + misc |= PERF_RECORD_MISC_USER; + else + misc |= PERF_RECORD_MISC_KERNEL; + } + + return misc; +} diff --git a/arch/sw_64/kernel/perf_event.c b/arch/sw_64/kernel/perf_event.c index 7544814615a8..c0aede9321b4 100644 --- a/arch/sw_64/kernel/perf_event.c +++ b/arch/sw_64/kernel/perf_event.c @@ -8,17 +8,6 @@ #include #include -/* For tracking PMCs and the hw events they monitor on each CPU. */ -struct cpu_hw_events { - /* - * Set the bit (indexed by the counter number) when the counter - * is used for an event. - */ - unsigned long used_mask[BITS_TO_LONGS(MAX_HWEVENTS)]; - /* Array of events current scheduled on this cpu. */ - struct perf_event *event[MAX_HWEVENTS]; -}; - DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); struct sw64_perf_event { @@ -629,101 +618,6 @@ static void sw64_perf_event_irq_handler(unsigned long idx, } } -bool valid_utext_addr(unsigned long addr) -{ - return addr >= current->mm->start_code && addr <= current->mm->end_code; -} - -bool valid_dy_addr(unsigned long addr) -{ - bool ret = false; - struct vm_area_struct *vma; - struct mm_struct *mm = current->mm; - - if (addr > TASK_SIZE || addr < TASK_UNMAPPED_BASE) - return ret; - vma = find_vma(mm, addr); - if (vma && vma->vm_start <= addr && (vma->vm_flags & VM_EXEC)) - ret = true; - return ret; -} - -#ifdef CONFIG_FRAME_POINTER -void perf_callchain_user(struct perf_callchain_entry_ctx *entry, - struct pt_regs *regs) -{ - - struct stack_frame frame; - unsigned long __user *fp; - int err; - - perf_callchain_store(entry, regs->pc); - - fp = (unsigned long __user *)regs->regs[15]; - - while (entry->nr < entry->max_stack && (unsigned long)fp < current->mm->start_stack) { - if (!access_ok(fp, sizeof(frame))) - break; - - pagefault_disable(); - err = __copy_from_user_inatomic(&frame, fp, sizeof(frame)); - pagefault_enable(); - - if (err) - break; - - if (valid_utext_addr(frame.return_address) || valid_dy_addr(frame.return_address)) - perf_callchain_store(entry, frame.return_address); - fp = (void __user *)frame.next_frame; - } -} -#else /* !CONFIG_FRAME_POINTER */ -void perf_callchain_user(struct perf_callchain_entry_ctx *entry, - struct pt_regs *regs) -{ - unsigned long usp = rdusp(); - unsigned long user_addr; - int err; - - perf_callchain_store(entry, regs->pc); - - while (entry->nr < entry->max_stack && usp < current->mm->start_stack) { - if (!access_ok((const void __user *)usp, 8)) - break; - - pagefault_disable(); - err = __get_user(user_addr, (unsigned long *)usp); - pagefault_enable(); - - if (err) - break; - - if (valid_utext_addr(user_addr) || valid_dy_addr(user_addr)) - perf_callchain_store(entry, user_addr); - usp = usp + 8; - } -} -#endif/* CONFIG_FRAME_POINTER */ - -/* - * Gets called by walk_stackframe() for every stackframe. This will be called - * whist unwinding the stackframe and is like a subroutine return so we use - * the PC. - */ -static int callchain_trace(unsigned long pc, void *data) -{ - struct perf_callchain_entry_ctx *entry = data; - - perf_callchain_store(entry, pc); - return 0; -} - -void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, - struct pt_regs *regs) -{ - walk_stackframe(NULL, regs, callchain_trace, entry); -} - /* * Init call to initialise performance events at kernel startup. */ @@ -755,35 +649,3 @@ int __init init_hw_perf_events(void) return 0; } early_initcall(init_hw_perf_events); - -/* - * Gets the perf_instruction_pointer and perf_misc_flags for guest os. - */ - -unsigned long perf_instruction_pointer(struct pt_regs *regs) -{ - if (perf_guest_state()) - return perf_guest_get_ip(); - - return instruction_pointer(regs); -} - -unsigned long perf_misc_flags(struct pt_regs *regs) -{ - unsigned int guest_state = perf_guest_state(); - int misc = 0; - - if (guest_state) { - if (guest_state & PERF_GUEST_USER) - misc |= PERF_RECORD_MISC_GUEST_USER; - else - misc |= PERF_RECORD_MISC_GUEST_KERNEL; - } else { - if (user_mode(regs)) - misc |= PERF_RECORD_MISC_USER; - else - misc |= PERF_RECORD_MISC_KERNEL; - } - - return misc; -} diff --git a/arch/sw_64/kernel/perf_event_c4.c b/arch/sw_64/kernel/perf_event_c4.c index 7a5e8deba0ee..302d3c65b61f 100644 --- a/arch/sw_64/kernel/perf_event_c4.c +++ b/arch/sw_64/kernel/perf_event_c4.c @@ -507,7 +507,7 @@ static void hw_perf_event_destroy(struct perf_event *event) /* Nothing to be done! */ } -static int __hw_perf_event_init(struct perf_event *event) +static void __hw_perf_event_init(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; @@ -523,8 +523,6 @@ static int __hw_perf_event_init(struct perf_event *event) hwc->last_period = hwc->sample_period; local64_set(&hwc->period_left, hwc->sample_period); } - - return 0; } /* @@ -632,6 +630,7 @@ static void sw64_perf_event_irq_handler(unsigned long perfmon_num, int idx; u64 val; + __this_cpu_inc(irq_pmi_count); cpuc = this_cpu_ptr(&cpu_hw_events); for (idx = 0; idx < sw64_pmu->num_pmcs; ++idx) { @@ -660,8 +659,6 @@ static void sw64_perf_event_irq_handler(unsigned long perfmon_num, if (perf_event_overflow(event, &data, regs)) sw64_pmu_stop(event, 0); } - - } /* @@ -669,12 +666,18 @@ static void sw64_perf_event_irq_handler(unsigned long perfmon_num, */ int __init init_hw_perf_events(void) { + pr_info("Performance Events: "); if (!supported_cpu()) { pr_info("Performance events: Unsupported CPU type!\n"); return 0; } - pr_info("Performance events: Supported CPU type!\n"); + if (is_in_guest()) { + pr_cont("No PMU driver, software events only.\n"); + return 0; + } + + pr_cont("Supported CPU type!\n"); /* Override performance counter IRQ vector */ -- Gitee From 07ac4ba74139e90a5207c9032153cabb2e56f602 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Fri, 18 Oct 2024 16:59:02 +0800 Subject: [PATCH 16/66] anolis: sw64: pci: fix incorrect pointer of struct pci_controller ANBZ: #4688 In any case, we should get pointer of struct pci_controller via function pci_bus_to_pci_controller(). Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/pci/pci-sysfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/pci/pci-sysfs.c b/arch/sw_64/pci/pci-sysfs.c index fd097d52b16a..4b9a29f2f348 100644 --- a/arch/sw_64/pci/pci-sysfs.c +++ b/arch/sw_64/pci/pci-sysfs.c @@ -58,6 +58,7 @@ static int pci_mmap_resource(struct kobject *kobj, struct vm_area_struct *vma, int sparse) { struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); + struct pci_controller *hose = pci_bus_to_pci_controller(pdev->bus); struct resource *res = attr->private; enum pci_mmap_state mmap_type; struct pci_bus_region bar; @@ -79,7 +80,7 @@ static int pci_mmap_resource(struct kobject *kobj, vma->vm_pgoff += bar.start >> (PAGE_SHIFT - (sparse ? 5 : 0)); mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io; - return hose_mmap_page_range(pdev->sysdata, vma, mmap_type, sparse); + return hose_mmap_page_range(hose, vma, mmap_type, sparse); } static int pci_mmap_resource_sparse(struct file *filp, struct kobject *kobj, -- Gitee From 03b18b31202b784a38d1ed2b82c886ccdb7ce6a6 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Tue, 24 Sep 2024 10:54:54 +0800 Subject: [PATCH 17/66] anolis: sw64: kvm: add KVM_CAP_READONLY_MEM support ANBZ: #4688 When KVM_CAP_READONLY_MEM is enabled, we can access ROM device such as pflash device. But Writing pflash device needs to be treated as mmio write, so we adds this write request handling in kvm. Signed-off-by: Chen Wang Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/uapi/asm/kvm.h | 1 + arch/sw_64/kvm/mmu.c | 2 +- arch/sw_64/kvm/sw64.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/include/uapi/asm/kvm.h b/arch/sw_64/include/uapi/asm/kvm.h index 430e82acee3e..1949e106563d 100644 --- a/arch/sw_64/include/uapi/asm/kvm.h +++ b/arch/sw_64/include/uapi/asm/kvm.h @@ -19,6 +19,7 @@ enum SW64_KVM_IRQ { }; #define __KVM_HAVE_IRQ_LINE +#define __KVM_HAVE_READONLY_MEM #define KVM_NR_IRQCHIPS 1 diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index b161b2ed8c8c..d69b42171d1a 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -1404,7 +1404,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, * needs emulation. */ - if (hva == KVM_HVA_ERR_BAD) { + if (hva == KVM_HVA_ERR_BAD || (write_fault && !writable)) { hargs->arg1 = fault_gpa | (hargs->arg1 & 0x1fffUL); ret = io_mem_abort(vcpu, run, hargs); goto out_unlock; diff --git a/arch/sw_64/kvm/sw64.c b/arch/sw_64/kvm/sw64.c index 99f7df5468fe..a2d2b1739dca 100644 --- a/arch/sw_64/kvm/sw64.c +++ b/arch/sw_64/kvm/sw64.c @@ -232,6 +232,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_IRQCHIP: case KVM_CAP_IOEVENTFD: case KVM_CAP_SYNC_MMU: + case KVM_CAP_READONLY_MEM: r = 1; break; case KVM_CAP_NR_VCPUS: -- Gitee From 50a81c3b1e627bef314fb1c0e4eb362ad5213e52 Mon Sep 17 00:00:00 2001 From: Gao Chen Date: Tue, 25 Jun 2024 16:44:44 +0800 Subject: [PATCH 18/66] anolis: sw64: reset the CSR:PTBR_USR ANBZ: #4688 In the initalization phase, the value of CSR:PTBR_USR is pointed to ZERO_PAGE to avoid address substitutions that cause errors. Signed-off-by: Gao Chen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/csr.h | 6 ++++++ arch/sw_64/kernel/smp.c | 3 +++ arch/sw_64/mm/init.c | 3 +++ 3 files changed, 12 insertions(+) diff --git a/arch/sw_64/include/asm/csr.h b/arch/sw_64/include/asm/csr.h index dac5b6a29b47..e205c3f1427e 100644 --- a/arch/sw_64/include/asm/csr.h +++ b/arch/sw_64/include/asm/csr.h @@ -108,6 +108,12 @@ static inline void update_ptbr_sys(unsigned long ptbr) sw64_write_csr_imb(ptbr, CSR_PTBR_SYS); } +static inline void update_ptbr_usr(unsigned long ptbr) +{ + imemb(); + sw64_write_csr_imb(ptbr, CSR_PTBR_USR); +} + #endif #else #define sw64_read_csr(x) (0) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index b85e3af028d7..b95201e93ebe 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -155,6 +155,9 @@ void smp_callin(void) current->active_mm = &init_mm; /* update csr:ptbr */ update_ptbr_sys(virt_to_phys(init_mm.pgd)); +#ifdef CONFIG_SUBARCH_C4 + update_ptbr_usr(__pa_symbol(empty_zero_page)); +#endif if (IS_ENABLED(CONFIG_SUBARCH_C4) && is_in_host()) { nmi_stack_page = alloc_pages_node( diff --git a/arch/sw_64/mm/init.c b/arch/sw_64/mm/init.c index 29ee809c3ac5..c13abbbe26f3 100644 --- a/arch/sw_64/mm/init.c +++ b/arch/sw_64/mm/init.c @@ -109,6 +109,9 @@ switch_to_system_map(void) { memset(swapper_pg_dir, 0, PAGE_SIZE); update_ptbr_sys(virt_to_phys(swapper_pg_dir)); +#ifdef CONFIG_SUBARCH_C4 + update_ptbr_usr(__pa_symbol(empty_zero_page)); +#endif tbiv(); } -- Gitee From 22784a5ca6d4e4b7b388bfe57cd9cbbe739469e9 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 25 Jun 2024 09:19:54 +0800 Subject: [PATCH 19/66] anolis: sw64: fix irq work ANBZ: #4688 Send an IPI to the cpu itself when trying to raise a irq_work and call irq_work_run() when handling this IPI. Clear the abandoned code. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/irq_work.h | 12 ++++++++++++ arch/sw_64/kernel/smp.c | 13 +++++++++++++ arch/sw_64/kernel/time.c | 20 -------------------- 3 files changed, 25 insertions(+), 20 deletions(-) create mode 100644 arch/sw_64/include/asm/irq_work.h diff --git a/arch/sw_64/include/asm/irq_work.h b/arch/sw_64/include/asm/irq_work.h new file mode 100644 index 000000000000..f4d0cd857be7 --- /dev/null +++ b/arch/sw_64/include/asm/irq_work.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_SW64_IRQ_WORK_H +#define __ASM_SW64_IRQ_WORK_H + +extern void arch_irq_work_raise(void); + +static inline bool arch_irq_work_has_interrupt(void) +{ + return IS_ENABLED(CONFIG_SMP); +} + +#endif /* __ASM_SW64_IRQ_WORK_H */ diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index b95201e93ebe..321f727fe706 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ enum ipi_message_type { IPI_RESCHEDULE, IPI_CALL_FUNC, IPI_CPU_STOP, + IPI_IRQ_WORK, }; int smp_num_cpus = 1; /* Number that came online. */ @@ -587,6 +589,13 @@ static void ipi_cpu_stop(int cpu) wait_for_interrupt(); } +#ifdef CONFIG_IRQ_WORK +void arch_irq_work_raise(void) +{ + send_ipi_message(cpumask_of(smp_processor_id()), IPI_IRQ_WORK); +} +#endif + void handle_ipi(struct pt_regs *regs) { int cpu = smp_processor_id(); @@ -616,6 +625,10 @@ void handle_ipi(struct pt_regs *regs) ipi_cpu_stop(cpu); break; + case IPI_IRQ_WORK: + irq_work_run(); + break; + default: pr_crit("Unknown IPI on CPU %d: %lu\n", cpu, which); break; diff --git a/arch/sw_64/kernel/time.c b/arch/sw_64/kernel/time.c index 6eaf8fab4f28..c6957d70a551 100644 --- a/arch/sw_64/kernel/time.c +++ b/arch/sw_64/kernel/time.c @@ -25,26 +25,6 @@ EXPORT_SYMBOL(rtc_lock); unsigned long est_cycle_freq; -#ifdef CONFIG_IRQ_WORK - -DEFINE_PER_CPU(u8, irq_work_pending); - -#define set_irq_work_pending_flag() __this_cpu_write(irq_work_pending, 1) -#define test_irq_work_pending() __this_cpu_read(irq_work_pending) -#define clear_irq_work_pending() __this_cpu_write(irq_work_pending, 0) - -void arch_irq_work_raise(void) -{ - set_irq_work_pending_flag(); -} - -#else /* CONFIG_IRQ_WORK */ - -#define test_irq_work_pending() 0 -#define clear_irq_work_pending() - -#endif /* CONFIG_IRQ_WORK */ - void __init time_init(void) { -- Gitee From 9c01c970024388dc7ef1acc6ae1bd6afd236d732 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 3 Jul 2024 16:48:09 +0800 Subject: [PATCH 20/66] anolis: sw64: bpf: fix BPF_CALL address ANBZ: #4688 Use the new bpf_jit_get_func_addr() helper for properly fetching the address through prog->aux->func[off]->bpf_func. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/net/bpf_jit_comp.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/arch/sw_64/net/bpf_jit_comp.c b/arch/sw_64/net/bpf_jit_comp.c index 31202dd0f9cf..64ed06693924 100644 --- a/arch/sw_64/net/bpf_jit_comp.c +++ b/arch/sw_64/net/bpf_jit_comp.c @@ -661,7 +661,8 @@ static int add_exception_handler(const struct bpf_insn *insn, * >0 - successfully JITed a 16-byte eBPF instruction. * <0 - failed to JIT. */ -static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) +static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, + bool extra_pass) { const u8 code = insn->code; u8 dst = bpf2sw64[insn->dst_reg]; @@ -672,7 +673,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) const s32 imm = insn->imm; const int bpf_idx = insn - ctx->prog->insnsi; s32 jmp_offset; - u64 func; struct bpf_insn insn1; u64 imm64; int ret; @@ -1142,13 +1142,18 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) break; case BPF_JMP | BPF_CALL: - func = (u64)__bpf_call_base + imm; - if ((func & ~(KERNEL_IMAGE_SIZE - 1)) != __START_KERNEL_map) - /* calling bpf program, switch to vmalloc addr */ - func = (func & U32_MAX) | VMALLOC_START; + { + bool fixed; + u64 func; + + ret = bpf_jit_get_func_addr(ctx->prog, insn, extra_pass, &func, &fixed); + if (ret < 0) + return ret; + emit_sw64_ldu64(SW64_BPF_REG_PV, func, ctx); emit(SW64_BPF_CALL(SW64_BPF_REG_RA, SW64_BPF_REG_PV), ctx); break; + } case BPF_JMP | BPF_TAIL_CALL: if (emit_bpf_tail_call(ctx)) @@ -1269,7 +1274,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) return 0; } -static int build_body(struct jit_ctx *ctx) +static int build_body(struct jit_ctx *ctx, bool extra_pass) { const struct bpf_prog *prog = ctx->prog; int i; @@ -1280,7 +1285,7 @@ static int build_body(struct jit_ctx *ctx) if (ctx->image == NULL) ctx->insn_offset[i] = ctx->idx; - ret = build_insn(insn, ctx); + ret = build_insn(insn, ctx, extra_pass); if (ret < 0) return ret; while (ret > 0) { @@ -1371,7 +1376,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) /* Fake pass to fill in ctx->offset. */ build_prologue(&ctx, was_classic); - if (build_body(&ctx)) { + if (build_body(&ctx, extra_pass)) { prog = orig_prog; goto out_off; } @@ -1405,7 +1410,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) build_prologue(&ctx, was_classic); - if (build_body(&ctx)) { + if (build_body(&ctx, extra_pass)) { bpf_jit_binary_free(header); prog = orig_prog; goto out_off; -- Gitee From f3a35f143156864466143af0a447bc641f301b34 Mon Sep 17 00:00:00 2001 From: Gu Zitao Date: Mon, 8 Jul 2024 17:19:42 +0800 Subject: [PATCH 21/66] anolis: sw64: kexec: fix kernel crashdump bugs ANBZ: #4688 This patch: - Remove the max_addr limit for memblock_alloc_base(), because alloc can now be performed in any memory space. - Delete kernel_restart_prepare(NULL) in order to prevent both 0 and panic cores from entering machine_kexec(). - fix the check for crash_base. Signed-off-by: Gu Zitao Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/machine_kexec.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/sw_64/kernel/machine_kexec.c b/arch/sw_64/kernel/machine_kexec.c index f0a2338ddcbd..4ef59d6022fc 100644 --- a/arch/sw_64/kernel/machine_kexec.c +++ b/arch/sw_64/kernel/machine_kexec.c @@ -54,7 +54,7 @@ void __init kexec_control_page_init(void) phys_addr_t addr; addr = memblock_phys_alloc_range(KEXEC_CONTROL_PAGE_SIZE, PAGE_SIZE, - 0, KTEXT_MAX); + 0, 0); kexec_control_page = (void *)(__START_KERNEL_map + addr); } @@ -105,8 +105,8 @@ void __init reserve_crashkernel(void) pr_warn("Add crash kernel area [mem %#018llx-%#018llx] to memmap region failed.\n", crash_base, crash_base + crash_size - 1); - if (crash_base >= KERNEL_IMAGE_SIZE) - pr_warn("Crash base should be less than %#x\n", KERNEL_IMAGE_SIZE); + if (crash_base < PCI_LEGACY_IO_SIZE) + pr_warn("Crash base should be greater than or equal to %#lx\n", PCI_LEGACY_IO_SIZE); crashk_res.start = crash_base; crashk_res.end = crash_base + crash_size - 1; @@ -192,7 +192,6 @@ void machine_crash_shutdown(struct pt_regs *regs) cpu = smp_processor_id(); local_irq_disable(); - kernel_restart_prepare(NULL); atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); smp_call_function(machine_crash_nonpanic_core, NULL, false); msecs = 1000; /* Wait at most a second for the other cpus to stop */ -- Gitee From 7ee45c8923d44dbd99fd0c4fc5c17b8f3a4dcfce Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Tue, 25 Jun 2024 15:23:18 +0800 Subject: [PATCH 22/66] anolis: sw64: add __vdso_getcpu support ANBZ: #4688 This patch implement getcpu() through vDSO. For C3, there is no way to get logical cpu id from userspace, so we have to maintain mappings from whami to cpu id and node id. Signed-off-by: Wu Liliu Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/hmcall.h | 2 ++ arch/sw_64/include/asm/vdso.h | 7 +++++ arch/sw_64/kernel/hmcall.c | 9 ++++++ arch/sw_64/kernel/vdso.c | 37 ++++++++++++++++++++++++ arch/sw_64/kernel/vdso/Makefile | 4 ++- arch/sw_64/kernel/vdso/vdso.lds.S | 1 + arch/sw_64/kernel/vdso/vgetcpu.c | 47 +++++++++++++++++++++++++++++++ 7 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 arch/sw_64/kernel/vdso/vgetcpu.c diff --git a/arch/sw_64/include/asm/hmcall.h b/arch/sw_64/include/asm/hmcall.h index 574144eab22b..60f68e31c568 100644 --- a/arch/sw_64/include/asm/hmcall.h +++ b/arch/sw_64/include/asm/hmcall.h @@ -54,6 +54,7 @@ /* Following will be deprecated from user level invocation */ #define HMC_rwreg 0x87 #define HMC_sz_uflush 0xA8 +#define HMC_uwhami 0xA0 #define HMC_longtime 0xB1 #ifdef __KERNEL__ @@ -162,6 +163,7 @@ __CALL_HMC_VOID(wrktp); __CALL_HMC_R0(rdps, unsigned long); __CALL_HMC_R0(rvpcr, unsigned long); +__CALL_HMC_R0(uwhami, unsigned long); __CALL_HMC_R0(rdusp, unsigned long); __CALL_HMC_W1(wrusp, unsigned long); diff --git a/arch/sw_64/include/asm/vdso.h b/arch/sw_64/include/asm/vdso.h index 7a2e23c648f3..3f6ba2d72b62 100644 --- a/arch/sw_64/include/asm/vdso.h +++ b/arch/sw_64/include/asm/vdso.h @@ -50,6 +50,13 @@ struct vdso_data { s32 tz_minuteswest; s32 tz_dsttime; u32 seq_count; +#ifdef CONFIG_SUBARCH_C3B + u8 vdso_whami_to_cpu[NR_CPUS]; + u8 vdso_whami_to_node[NR_CPUS]; +#endif +#ifdef CONFIG_SUBARCH_C4 + u8 vdso_cpu_to_node[NR_CPUS]; +#endif }; static inline unsigned long get_vdso_base(void) diff --git a/arch/sw_64/kernel/hmcall.c b/arch/sw_64/kernel/hmcall.c index d2054a930bd7..50aaa2b9b5b4 100644 --- a/arch/sw_64/kernel/hmcall.c +++ b/arch/sw_64/kernel/hmcall.c @@ -108,6 +108,14 @@ static inline void fixup_wrusp(void) entry[1] = 0x1ee00000; /* pri_ret $23 */ } +static inline void fixup_uwhami(void) +{ + unsigned int *entry = __va(HMCALL_ENTRY(uwhami)); + + entry[0] = 0x94161078; /* pri_ldl/p r0, VC__WHAMI(vcpucb) */ + entry[1] = 0x1ef00000; /* pri_ret/b $23 */ +} + void __init fixup_hmcall(void) { #if defined(CONFIG_SUBARCH_C3B) @@ -119,6 +127,7 @@ void __init fixup_hmcall(void) fixup_wrktp(); fixup_rdusp(); fixup_wrusp(); + fixup_uwhami(); imemb(); #endif } diff --git a/arch/sw_64/kernel/vdso.c b/arch/sw_64/kernel/vdso.c index 15f1f244a82f..0d0ca5d0a38b 100644 --- a/arch/sw_64/kernel/vdso.c +++ b/arch/sw_64/kernel/vdso.c @@ -36,6 +36,41 @@ struct vdso_data *vdso_data = &vdso_data_store.data; static struct vm_special_mapping vdso_spec[2]; +#ifdef CONFIG_SUBARCH_C3B +#define V_NODE_SHIFT 6 +static void init_cpu_map(void) +{ + + int i, whami, domain; + unsigned int shift, mask; + + if (is_in_host()) + shift = DOMAIN_ID_SHIFT; + else + shift = V_NODE_SHIFT; + mask = (1 << shift) - 1; + + vdso_data_write_begin(vdso_data); + for (i = 0; i < num_possible_cpus(); i++) { + domain = cpu_to_rcid(i) >> shift; + whami = (domain << DOMAIN_ID_SHIFT) | (cpu_to_rcid(i) & mask); + vdso_data->vdso_whami_to_cpu[whami] = i; + vdso_data->vdso_whami_to_node[whami] = domain; + } + vdso_data_write_end(vdso_data); +} +#else +static void init_cpu_map(void) +{ + int i; + + vdso_data_write_begin(vdso_data); + for (i = 0; i < num_possible_cpus(); i++) + vdso_data->vdso_cpu_to_node[i] = (cpu_to_rcid(i) & DOMAIN_ID_MASK) >> DOMAIN_ID_SHIFT; + vdso_data_write_end(vdso_data); +} +#endif + static int __init vdso_init(void) { int i; @@ -73,6 +108,8 @@ static int __init vdso_init(void) .pages = &vdso_pagelist[1], }; + init_cpu_map(); + return 0; } arch_initcall(vdso_init); diff --git a/arch/sw_64/kernel/vdso/Makefile b/arch/sw_64/kernel/vdso/Makefile index 190cc345dbb9..e5640abbd727 100644 --- a/arch/sw_64/kernel/vdso/Makefile +++ b/arch/sw_64/kernel/vdso/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 # Symbols present in the vdso -vdso-syms = rt_sigreturn gettimeofday +vdso-syms = rt_sigreturn gettimeofday getcpu # Files to link into the vdso obj-vdso = $(patsubst %, v%.o, $(vdso-syms)) @@ -17,12 +17,14 @@ CPPFLAGS_vdso.lds += -P -C -U$(ARCH) CFLAGS_REMOVE_vdso.o = -pg CFLAGS_REMOVE_vrt_sigreturn.o = -pg CFLAGS_REMOVE_vgettimeofday.o = -pg +CFLAGS_REMOVE_vgetcpu = -pg ifdef CONFIG_FEEDBACK_COLLECT # vDSO code runs in userspace, not collecting feedback data. CFLAGS_REMOVE_vdso.o = -ffeedback-generate CFLAGS_REMOVE_vrt_sigreturn.o = -ffeedback-generate CFLAGS_REMOVE_vgettimeofday.o = -ffeedback-generate +CFLAGS_REMOVE_vgetcpu.o = -ffeedback-generate endif # Disable gcov profiling for VDSO code diff --git a/arch/sw_64/kernel/vdso/vdso.lds.S b/arch/sw_64/kernel/vdso/vdso.lds.S index de1782ccb7b6..08134a86f66c 100644 --- a/arch/sw_64/kernel/vdso/vdso.lds.S +++ b/arch/sw_64/kernel/vdso/vdso.lds.S @@ -84,6 +84,7 @@ VERSION __vdso_rt_sigreturn; __vdso_gettimeofday; __vdso_clock_gettime; + __vdso_getcpu; local: *; }; } diff --git a/arch/sw_64/kernel/vdso/vgetcpu.c b/arch/sw_64/kernel/vdso/vgetcpu.c new file mode 100644 index 000000000000..6437ac6f94d5 --- /dev/null +++ b/arch/sw_64/kernel/vdso/vgetcpu.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include + +static void __getcpu(unsigned int *cpu, unsigned int *node, + const struct vdso_data *data) +{ + unsigned int cpuid; +#ifdef CONFIG_SUBARCH_C3B + asm volatile ("sys_call %1\n" + "mov $0, %0\n" + : "=&r"(cpuid) + : "i"(HMC_uwhami)); + *cpu = data->vdso_whami_to_cpu[cpuid]; + *node = data->vdso_whami_to_node[cpuid]; +#else + asm volatile ("csrr %0, %1" : "=&r"(cpuid) : "i"(CSR_SOFTCID)); + *cpu = cpuid; + *node = data->vdso_cpu_to_node[*cpu]; +#endif +} + + +long __vdso_getcpu(unsigned int *cpu, unsigned int *node, + struct getcpu_cache *unused) +{ + const struct vdso_data *data = get_vdso_data(); + + __getcpu(cpu, node, data); + return 0; +} -- Gitee From 6f1369cb37d5dd8b8377e570b27912c0ea73a671 Mon Sep 17 00:00:00 2001 From: Gu Zitao Date: Tue, 23 Jul 2024 14:45:05 +0800 Subject: [PATCH 23/66] anolis: sw64: remove unnecessary parameter passing ANBZ: #4688 Compiler has already prepared parameters for reboot_code_buffer(), so there is no need to get parameters through these four kexec_args. Signed-off-by: Gu Zitao Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/relocate_kernel.S | 38 ----------------------------- 1 file changed, 38 deletions(-) diff --git a/arch/sw_64/kernel/relocate_kernel.S b/arch/sw_64/kernel/relocate_kernel.S index f1a160636212..a4b0d27778b9 100644 --- a/arch/sw_64/kernel/relocate_kernel.S +++ b/arch/sw_64/kernel/relocate_kernel.S @@ -16,11 +16,6 @@ relocate_new_kernel: .prologue 0 - ldl a0, arg0 - ldl a1, arg1 - ldl a2, arg2 - ldl a3, arg3 - ldl s0, kexec_indirection_page ldl s1, kexec_start_address @@ -100,10 +95,6 @@ done: .globl kexec_smp_wait .ent kexec_smp_wait kexec_smp_wait: - ldl a0, s_arg0 - ldl a1, s_arg1 - ldl a2, s_arg2 - ldl a3, s_arg3 ldl s1, kexec_start_address /* Non-relocated address works for args and kexec_start_address (old @@ -124,35 +115,6 @@ kexec_smp_wait: jmp ra, (s1) .end kexec_smp_wait .size kexec_smp_wait, .-kexec_smp_wait -#endif - - .align 3 - - /* All parameters to new kernel are passed in registers a0-a3. - * kexec_args[0..3] are uses to prepare register values. - */ - -kexec_args: - .globl kexec_args -arg0: .quad 0x0 -arg1: .quad 0x0 -arg2: .quad 0x0 -arg3: .quad 0x0 - .size kexec_args, 8*4 - -#ifdef CONFIG_CRASH_SMP - /* - * Secondary CPUs may have different kernel parameters in - * their registers a0-a3. secondary_kexec_args[0..3] are used - * to prepare register values. - */ -secondary_kexec_args: - .globl secondary_kexec_args -s_arg0: .quad 0x0 -s_arg1: .quad 0x0 -s_arg2: .quad 0x0 -s_arg3: .quad 0x0 - .size secondary_kexec_args, 8*4 kexec_flag: .quad 0x1 -- Gitee From 912288f8acd5f37f88d395954292b340bbc6e868 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Thu, 4 Jul 2024 17:29:43 +0800 Subject: [PATCH 24/66] anolis: sw64: improve lib performance for new archs ANBZ: #4688 Always use cached memory write instead of non-cache memory write for architectures other than the old C3B. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/lib/copy_simd_align_template.S | 6 ++++++ arch/sw_64/lib/set_simd_align_template.S | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/arch/sw_64/lib/copy_simd_align_template.S b/arch/sw_64/lib/copy_simd_align_template.S index fbb5912e1213..aa648b7c822a 100644 --- a/arch/sw_64/lib/copy_simd_align_template.S +++ b/arch/sw_64/lib/copy_simd_align_template.S @@ -15,7 +15,9 @@ * */ +#ifdef CONFIG_SUBARCH_C3B #define NC_STORE_THRESHOLD 2048 +#endif #define SAVE_SIMD_REGS \ ldi $sp, -0x60($sp); \ @@ -97,6 +99,7 @@ $dest_aligned_32: $prep_simd_loop: SAVE_SIMD_REGS +#ifdef CONFIG_SUBARCH_C3B ldi $1, NC_STORE_THRESHOLD($31) cmple $18, $1, $1 bne $1, $simd_loop @@ -114,6 +117,7 @@ $simd_loop_nc: beq $1, $simd_loop_nc memb # required for _nc store instructions br $31, $simd_loop_end +#endif .align 4 $simd_loop: @@ -207,6 +211,7 @@ $prep_simd_u_loop: ifmovd $1, $f1 ifmovd $2, $f2 FIXUP_LDST( vldd $f4, 0($3) ) +#ifdef CONFIG_SUBARCH_C3B ldi $1, NC_STORE_THRESHOLD($31) cmple $18, $1, $1 bne $1, $simd_u_loop @@ -230,6 +235,7 @@ $simd_u_loop_nc: beq $1, $simd_u_loop_nc memb # required for _nc store instructions br $31, $simd_u_loop_end +#endif .align 4 $simd_u_loop: diff --git a/arch/sw_64/lib/set_simd_align_template.S b/arch/sw_64/lib/set_simd_align_template.S index fa77cacf684f..6a8b4118f2a0 100644 --- a/arch/sw_64/lib/set_simd_align_template.S +++ b/arch/sw_64/lib/set_simd_align_template.S @@ -13,7 +13,9 @@ * */ +#ifdef CONFIG_SUBARCH_C3B #define NC_STORE_THRESHOLD 2048 +#endif #define SAVE_SIMD_REGS \ ldi $sp, -0x40($sp); \ @@ -65,6 +67,7 @@ $prep_simd_loop: SAVE_SIMD_REGS ifmovd $17, $f1 vcpyf $f1, $f1 +#ifdef CONFIG_SUBARCH_C3B ldi $1, NC_STORE_THRESHOLD($31) cmple $18, $1, $1 bne $1, $simd_loop @@ -79,6 +82,7 @@ $simd_loop_nc: beq $1, $simd_loop_nc memb # required for _nc store instructions br $31, $simd_loop_end +#endif .align 3 $simd_loop: -- Gitee From ca9e82e77fcb94361b7898c8c0479381ccf885e5 Mon Sep 17 00:00:00 2001 From: Xu Chenjiao Date: Fri, 26 Jul 2024 11:22:20 +0000 Subject: [PATCH 25/66] anolis: sw64: lpc: fix ast2400 driver error for C4 ANBZ: #4688 Port ast2400 driver to work around the hardware flaws of Low Pin Count controller of C4, since the address passed in is 48 bit length, so we change address type from unsigned int to unsigned long. Besides the resource index should be 0 to get the valid resource of super I/O. Signed-off-by: Xu Chenjiao Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/ast2400.h | 19 +++++++++++++------ drivers/mfd/lpc_sunway.c | 4 ++++ drivers/mfd/sunway_ast2400.c | 6 +++--- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/arch/sw_64/include/asm/ast2400.h b/arch/sw_64/include/asm/ast2400.h index 5f4cc84ff3a8..30d45eff62a2 100644 --- a/arch/sw_64/include/asm/ast2400.h +++ b/arch/sw_64/include/asm/ast2400.h @@ -49,9 +49,17 @@ #define SUPERIO_PNP_PORT 0x2E #define SUPERIO_CHIPID 0xC333 +#ifdef CONFIG_SUBARCH_C3B +#define PORT_OFFSET 0 +#endif + +#ifdef CONFIG_SUBARCH_C4 +#define PORT_OFFSET 12 +#endif + struct device_operations; typedef struct pnp_device { - unsigned int port; + unsigned long port; unsigned int device; struct device_operations *ops; @@ -100,8 +108,8 @@ typedef struct superio_ast2400_device { struct device *dev; const char *name; unsigned int enabled : 1; /* set if we should enable the device */ - unsigned int superio_ast2400_efir; /* extended function index register */ - unsigned int superio_ast2400_efdr; /* extended function data register */ + unsigned long superio_ast2400_efir; /* extended function index register */ + unsigned long superio_ast2400_efdr; /* extended function data register */ struct chip_operations *chip_ops; const void *chip_info; } *superio_device_t; @@ -136,19 +144,18 @@ static inline void pnp_exit_conf_mode(device_t dev) static inline u8 pnp_read_config(device_t dev, u8 reg) { outb(reg, dev->port); - return inb(dev->port + 1); + return inb(dev->port + (1 << PORT_OFFSET)); } static inline void pnp_write_config(device_t dev, u8 reg, u8 value) { outb(reg, dev->port); - outb(value, dev->port + 1); + outb(value, dev->port + (1 << PORT_OFFSET)); } static inline void pnp_set_logical_device(device_t dev) { pnp_write_config(dev, 0x07, dev->device & 0xff); -// pnp_write_config(dev, 0x07, 0x3); } static inline void pnp_set_enable(device_t dev, int enable) diff --git a/drivers/mfd/lpc_sunway.c b/drivers/mfd/lpc_sunway.c index a70971e7912d..ebad6f202145 100644 --- a/drivers/mfd/lpc_sunway.c +++ b/drivers/mfd/lpc_sunway.c @@ -78,6 +78,10 @@ struct lpc_chip3_adapter { static struct resource superio_chip3_resources[] = { { .flags = IORESOURCE_IO, +#ifdef CONFIG_SUBARCH_C4 + .start = LPC_MEM_IO, + .end = LPC_MEM_IO + 0x10, +#endif } }; diff --git a/drivers/mfd/sunway_ast2400.c b/drivers/mfd/sunway_ast2400.c index 4e1e3e3d21e2..5fd7fc951c96 100644 --- a/drivers/mfd/sunway_ast2400.c +++ b/drivers/mfd/sunway_ast2400.c @@ -163,7 +163,7 @@ static int superio_ast2400_probe(struct platform_device *pdev) return err; } - res = platform_get_resource(pdev, IORESOURCE_IO, 1); + res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (res) { physaddr = res->start; dev_info(&pdev->dev, "request memory region %pR\n", res); @@ -171,8 +171,8 @@ static int superio_ast2400_probe(struct platform_device *pdev) superio_device->dev = &pdev->dev; superio_device->enabled = 1; - superio_device->superio_ast2400_efir = physaddr + SUPERIO_PNP_PORT; - superio_device->superio_ast2400_efdr = physaddr + SUPERIO_PNP_PORT + 1; + superio_device->superio_ast2400_efir = physaddr + (SUPERIO_PNP_PORT << PORT_OFFSET); + superio_device->superio_ast2400_efdr = physaddr + ((SUPERIO_PNP_PORT + 1) << PORT_OFFSET); superio_uart0_irq = platform_get_irq_byname(pdev, "uart0_irq"); superio_uart1_irq = platform_get_irq_byname(pdev, "uart1_irq"); -- Gitee From fbb105203d9abb1ca0543d1c51f0e85a08157f4f Mon Sep 17 00:00:00 2001 From: Zhi Tongze Date: Thu, 22 Aug 2024 09:22:01 +0800 Subject: [PATCH 26/66] anolis: sw64: select different MUX to read cpu frequency ANBZ: #4688 MUX will not be fixed to use pll2, so we need to check current MUX before reading CPU frequency. Signed-off-by: Zhi Tongze Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/cpufreq.h | 4 +++- arch/sw_64/platform/cpufreq.c | 12 ++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/sw_64/include/asm/cpufreq.h b/arch/sw_64/include/asm/cpufreq.h index 93244b3b18c6..0d3e794b16ea 100644 --- a/arch/sw_64/include/asm/cpufreq.h +++ b/arch/sw_64/include/asm/cpufreq.h @@ -51,7 +51,8 @@ struct clk { #define CORE_CLK2_VALID (0x1UL << 33) #define CORE_CLK2_RESET (0x1UL << 34) #define CORE_CLK2_LOCK (0x1UL << 35) -#define CORE_PLL0_CFG_SHIFT 20 +#define CORE_PLL0_CFG_SHIFT 4 +#define CORE_PLL1_CFG_SHIFT 20 #define CORE_PLL2_CFG_SHIFT 36 #define CORE_PLL2_CFG_MASK 0x1f #define STARTUP_RATE (2000UL * 1000 * 1000) @@ -65,6 +66,7 @@ struct clk { #define CORE_CLK2_RESET (0x1UL << 16) #define CORE_CLK2_LOCK (0x1UL << 17) #define CORE_PLL0_CFG_SHIFT 4 +#define CORE_PLL1_CFG_SHIFT 11 #define CORE_PLL2_CFG_SHIFT 18 #define CORE_PLL2_CFG_MASK 0xf #define STARTUP_RATE (2400UL * 1000 * 1000) diff --git a/arch/sw_64/platform/cpufreq.c b/arch/sw_64/platform/cpufreq.c index 0d552d9a753d..e18201069f67 100644 --- a/arch/sw_64/platform/cpufreq.c +++ b/arch/sw_64/platform/cpufreq.c @@ -136,12 +136,20 @@ EXPORT_SYMBOL(sw64_clk_get); unsigned int __sw64_cpufreq_get(struct cpufreq_policy *policy) { - int i; + int i, clu_lv1_sel; u64 val; void __iomem *spbu_base = misc_platform_get_spbu_base(0); struct cpufreq_frequency_table *ft = policy->freq_table; - val = readq(spbu_base + OFFSET_CLK_CTL) >> CORE_PLL2_CFG_SHIFT; + clu_lv1_sel = (readq(spbu_base + OFFSET_CLU_LV1_SEL) >> 2) & 0x3; + + if (clu_lv1_sel == 0) + val = readq(spbu_base + OFFSET_CLK_CTL) >> CORE_PLL0_CFG_SHIFT; + else if (clu_lv1_sel == 2) + val = readq(spbu_base + OFFSET_CLK_CTL) >> CORE_PLL1_CFG_SHIFT; + else + val = readq(spbu_base + OFFSET_CLK_CTL) >> CORE_PLL2_CFG_SHIFT; + val &= CORE_PLL2_CFG_MASK; for (i = 0; ft[i].frequency != CPUFREQ_TABLE_END; i++) { -- Gitee From d5133bc07e073587b378f4f13d4dc1315ee00404 Mon Sep 17 00:00:00 2001 From: Gu Yuchen Date: Tue, 27 Aug 2024 08:54:28 +0800 Subject: [PATCH 27/66] anolis: sw64: add unaligned access handling code for SIMD in kernel mode (5.10) ANBZ: #4688 The current kernel does not support unaligned access handling for SIMD. Unaligned access handling code for SIMD in kernel mode is added. Signed-off-by: Gu Yuchen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/traps.c | 528 +++++++++++++++++++++++++++++++++++++- 1 file changed, 527 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index e54db9a41be6..bc7bb4c04456 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -392,7 +392,8 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, { long error, disp; unsigned int insn, fncode, rb; - unsigned long tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; + unsigned long tmp, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, vb; + unsigned long fp[4]; unsigned long pc = regs->pc - 4; /* @@ -402,6 +403,531 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, */ switch (opcode) { + + case 0x0c: /* vlds */ + if ((unsigned long)va<<61 == 0) { + __asm__ __volatile__( + "1: ldl %1, 0(%5)\n" + "2: ldl %2, 8(%5)\n" + "3:\n" + ".section __ex_table, \"a\"\n" + " .long 1b - .\n" + " ldi %1, 3b-1b(%0)\n" + " .long 2b - .\n" + " ldi %2, 3b-2b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4) + : "r"(va), "0"(0)); + + if (error) + goto got_exception; + + sw64_write_simd_fp_reg_s(reg, tmp1, tmp2); + + return; + } else { + __asm__ __volatile__( + "1: ldl_u %1, 0(%6)\n" + "2: ldl_u %2, 7(%6)\n" + "3: ldl_u %3, 15(%6)\n" + " extll %1, %6, %1\n" + " extll %2, %6, %5\n" + " exthl %2, %6, %4\n" + " exthl %3, %6, %3\n" + "4:\n" + ".section __ex_table, \"a\"\n" + " .long 1b - .\n" + " ldi %1, 4b-1b(%0)\n" + " .long 2b - .\n" + " ldi %2, 4b-2b(%0)\n" + " .long 3b - .\n" + " ldi %3, 4b-3b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), + "=&r"(tmp4), "=&r"(tmp5) + : "r"(va), "0"(0)); + + if (error) + goto got_exception; + + tmp1 = tmp1 | tmp4; + tmp2 = tmp5 | tmp3; + + sw64_write_simd_fp_reg_s(reg, tmp1, tmp2); + + return; + } + + case 0x0d: /* vldd */ + if ((unsigned long)va<<61 == 0) { + __asm__ __volatile__( + "1: ldl %1, 0(%5)\n" + "2: ldl %2, 8(%5)\n" + "3: ldl %3, 16(%5)\n" + "4: ldl %4, 24(%5)\n" + "5:\n" + ".section __ex_table, \"a\"\n" + " .long 1b - .\n" + " ldi %1, 5b-1b(%0)\n" + " .long 2b - .\n" + " ldi %2, 5b-2b(%0)\n" + " .long 3b - .\n" + " ldi %3, 5b-3b(%0)\n" + " .long 4b - .\n" + " ldi %4, 5b-4b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4) + : "r"(va), "0"(0)); + + if (error) + goto got_exception; + + sw64_write_simd_fp_reg_d(reg, tmp1, tmp2, tmp3, tmp4); + + return; + } else { + __asm__ __volatile__( + "1: ldl_u %1, 0(%6)\n" + "2: ldl_u %2, 7(%6)\n" + "3: ldl_u %3, 15(%6)\n" + " extll %1, %6, %1\n" + " extll %2, %6, %5\n" + " exthl %2, %6, %4\n" + " exthl %3, %6, %3\n" + "4:\n" + ".section __ex_table, \"a\"\n" + " .long 1b - .\n" + " ldi %1, 4b-1b(%0)\n" + " .long 2b - .\n" + " ldi %2, 4b-2b(%0)\n" + " .long 3b - .\n" + " ldi %3, 4b-3b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), + "=&r"(tmp4), "=&r"(tmp5) + : "r"(va), "0"(0)); + + if (error) + goto got_exception; + + tmp7 = tmp1 | tmp4; //f0 + tmp8 = tmp5 | tmp3; //f1 + + vb = ((unsigned long)(va))+16; + + __asm__ __volatile__( + "1: ldl_u %1, 0(%6)\n" + "2: ldl_u %2, 7(%6)\n" + "3: ldl_u %3, 15(%6)\n" + " extll %1, %6, %1\n" + " extll %2, %6, %5\n" + " exthl %2, %6, %4\n" + " exthl %3, %6, %3\n" + "4:\n" + ".section __ex_table, \"a\"\n" + " .long 1b - .\n" + " ldi %1, 4b-1b(%0)\n" + " .long 2b - .\n" + " ldi %2, 4b-2b(%0)\n" + " .long 3b - .\n" + " ldi %3, 4b-3b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), + "=&r"(tmp4), "=&r"(tmp5) + : "r"(vb), "0"(0)); + + if (error) + goto got_exception; + + tmp = tmp1 | tmp4; // f2 + tmp2 = tmp5 | tmp3; // f3 + + sw64_write_simd_fp_reg_d(reg, tmp7, tmp8, tmp, tmp2); + return; + } + + case 0x0e: /* vsts */ + sw64_read_simd_fp_m_s(reg, fp); + if ((unsigned long)va<<61 == 0) { + __asm__ __volatile__( + " bis %4, %4, %1\n" + " bis %5, %5, %2\n" + "1: stl %1, 0(%3)\n" + "2: stl %2, 8(%3)\n" + "3:\n" + ".section __ex_table, \"a\"\n\t" + " .long 1b - .\n" + " ldi $31, 3b-1b(%0)\n" + " .long 2b - .\n" + " ldi $31, 3b-2b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2) + : "r"(va), "r"(fp[0]), "r"(fp[1]), "0"(0)); + + if (error) + goto got_exception; + + return; + } else { + __asm__ __volatile__( + " zapnot %10, 0x1, %1\n" + " srl %10, 8, %2\n" + " zapnot %2, 0x1, %2\n" + " srl %10, 16, %3\n" + " zapnot %3, 0x1, %3\n" + " srl %10, 24, %4\n" + " zapnot %4, 0x1, %4\n" + " srl %10, 32, %5\n" + " zapnot %5, 0x1, %5\n" + " srl %10, 40, %6\n" + " zapnot %6, 0x1, %6\n" + " srl %10, 48, %7\n" + " zapnot %7, 0x1, %7\n" + " srl %10, 56, %8\n" + " zapnot %8, 0x1, %8\n" + "1: stb %1, 0(%9)\n" + "2: stb %2, 1(%9)\n" + "3: stb %3, 2(%9)\n" + "4: stb %4, 3(%9)\n" + "5: stb %5, 4(%9)\n" + "6: stb %6, 5(%9)\n" + "7: stb %7, 6(%9)\n" + "8: stb %8, 7(%9)\n" + "9:\n" + ".section __ex_table, \"a\"\n\t" + " .long 1b - .\n" + " ldi $31, 9b-1b(%0)\n" + " .long 2b - .\n" + " ldi $31, 9b-2b(%0)\n" + " .long 3b - .\n" + " ldi $31, 9b-3b(%0)\n" + " .long 4b - .\n" + " ldi $31, 9b-4b(%0)\n" + " .long 5b - .\n" + " ldi $31, 9b-5b(%0)\n" + " .long 6b - .\n" + " ldi $31, 9b-6b(%0)\n" + " .long 7b - .\n" + " ldi $31, 9b-7b(%0)\n" + " .long 8b - .\n" + " ldi $31, 9b-8b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), + "=&r"(tmp4), "=&r"(tmp5), "=&r"(tmp6), "=&r"(tmp7), "=&r"(tmp8) + : "r"(va), "r"(fp[0]), "0"(0)); + + if (error) + goto got_exception; + + + vb = ((unsigned long)va) + 8; + + __asm__ __volatile__( + " zapnot %10, 0x1, %1\n" + " srl %10, 8, %2\n" + " zapnot %2, 0x1, %2\n" + " srl %10, 16, %3\n" + " zapnot %3, 0x1, %3\n" + " srl %10, 24, %4\n" + " zapnot %4, 0x1, %4\n" + " srl %10, 32, %5\n" + " zapnot %5, 0x1, %5\n" + " srl %10, 40, %6\n" + " zapnot %6, 0x1, %6\n" + " srl %10, 48, %7\n" + " zapnot %7, 0x1, %7\n" + " srl %10, 56, %8\n" + " zapnot %8, 0x1, %8\n" + "1: stb %1, 0(%9)\n" + "2: stb %2, 1(%9)\n" + "3: stb %3, 2(%9)\n" + "4: stb %4, 3(%9)\n" + "5: stb %5, 4(%9)\n" + "6: stb %6, 5(%9)\n" + "7: stb %7, 6(%9)\n" + "8: stb %8, 7(%9)\n" + "9:\n" + ".section __ex_table, \"a\"\n\t" + " .long 1b - .\n" + " ldi $31, 9b-1b(%0)\n" + " .long 2b - .\n" + " ldi $31, 9b-2b(%0)\n" + " .long 3b - .\n" + " ldi $31, 9b-3b(%0)\n" + " .long 4b - .\n" + " ldi $31, 9b-4b(%0)\n" + " .long 5b - .\n" + " ldi $31, 9b-5b(%0)\n" + " .long 6b - .\n" + " ldi $31, 9b-6b(%0)\n" + " .long 7b - .\n" + " ldi $31, 9b-7b(%0)\n" + " .long 8b - .\n" + " ldi $31, 9b-8b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), + "=&r"(tmp4), "=&r"(tmp5), "=&r"(tmp6), "=&r"(tmp7), "=&r"(tmp8) + : "r"(vb), "r"(fp[1]), "0"(0)); + + if (error) + goto got_exception; + + return; + } + + case 0x0f: /* vstd */ + sw64_read_simd_fp_m_d(reg, fp); + if ((unsigned long)va<<61 == 0) { + __asm__ __volatile__( + " bis %4, %4, %1\n" + " bis %5, %5, %2\n" + "1: stl %1, 0(%3)\n" + "2: stl %2, 8(%3)\n" + "3:\n" + ".section __ex_table, \"a\"\n\t" + " .long 1b - .\n" + " ldi $31, 3b-1b(%0)\n" + " .long 2b - .\n" + " ldi $31, 3b-2b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2) + : "r"(va), "r"(fp[0]), "r"(fp[1]), "0"(0)); + + if (error) + goto got_exception; + + vb = ((unsigned long)va)+16; + + + __asm__ __volatile__( + " bis %4, %4, %1\n" + " bis %5, %5, %2\n" + "1: stl %1, 0(%3)\n" + "2: stl %2, 8(%3)\n" + "3:\n" + ".section __ex_table, \"a\"\n\t" + " .long 1b - .\n" + " ldi $31, 3b-1b(%0)\n" + " .long 2b - .\n" + " ldi $31, 3b-2b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2) + : "r"(vb), "r"(fp[2]), "r"(fp[3]), "0"(0)); + + if (error) + goto got_exception; + + return; + } else { + __asm__ __volatile__( + " zapnot %10, 0x1, %1\n" + " srl %10, 8, %2\n" + " zapnot %2, 0x1, %2\n" + " srl %10, 16, %3\n" + " zapnot %3, 0x1, %3\n" + " srl %10, 24, %4\n" + " zapnot %4, 0x1, %4\n" + " srl %10, 32, %5\n" + " zapnot %5, 0x1, %5\n" + " srl %10, 40, %6\n" + " zapnot %6, 0x1, %6\n" + " srl %10, 48, %7\n" + " zapnot %7, 0x1, %7\n" + " srl %10, 56, %8\n" + " zapnot %8, 0x1, %8\n" + "1: stb %1, 0(%9)\n" + "2: stb %2, 1(%9)\n" + "3: stb %3, 2(%9)\n" + "4: stb %4, 3(%9)\n" + "5: stb %5, 4(%9)\n" + "6: stb %6, 5(%9)\n" + "7: stb %7, 6(%9)\n" + "8: stb %8, 7(%9)\n" + "9:\n" + ".section __ex_table, \"a\"\n\t" + " .long 1b - .\n" + " ldi $31, 9b-1b(%0)\n" + " .long 2b - .\n" + " ldi $31, 9b-2b(%0)\n" + " .long 3b - .\n" + " ldi $31, 9b-3b(%0)\n" + " .long 4b - .\n" + " ldi $31, 9b-4b(%0)\n" + " .long 5b - .\n" + " ldi $31, 9b-5b(%0)\n" + " .long 6b - .\n" + " ldi $31, 9b-6b(%0)\n" + " .long 7b - .\n" + " ldi $31, 9b-7b(%0)\n" + " .long 8b - .\n" + " ldi $31, 9b-8b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), + "=&r"(tmp4), "=&r"(tmp5), "=&r"(tmp6), "=&r"(tmp7), "=&r"(tmp8) + : "r"(va), "r"(fp[0]), "0"(0)); + + if (error) + goto got_exception; + + vb = ((unsigned long)va) + 8; + + __asm__ __volatile__( + " zapnot %10, 0x1, %1\n" + " srl %10, 8, %2\n" + " zapnot %2, 0x1, %2\n" + " srl %10, 16, %3\n" + " zapnot %3, 0x1, %3\n" + " srl %10, 24, %4\n" + " zapnot %4, 0x1, %4\n" + " srl %10, 32, %5\n" + " zapnot %5, 0x1, %5\n" + " srl %10, 40, %6\n" + " zapnot %6, 0x1, %6\n" + " srl %10, 48, %7\n" + " zapnot %7, 0x1, %7\n" + " srl %10, 56, %8\n" + " zapnot %8, 0x1, %8\n" + "1: stb %1, 0(%9)\n" + "2: stb %2, 1(%9)\n" + "3: stb %3, 2(%9)\n" + "4: stb %4, 3(%9)\n" + "5: stb %5, 4(%9)\n" + "6: stb %6, 5(%9)\n" + "7: stb %7, 6(%9)\n" + "8: stb %8, 7(%9)\n" + "9:\n" + ".section __ex_table, \"a\"\n\t" + " .long 1b - .\n" + " ldi $31, 9b-1b(%0)\n" + " .long 2b - .\n" + " ldi $31, 9b-2b(%0)\n" + " .long 3b - .\n" + " ldi $31, 9b-3b(%0)\n" + " .long 4b - .\n" + " ldi $31, 9b-4b(%0)\n" + " .long 5b - .\n" + " ldi $31, 9b-5b(%0)\n" + " .long 6b - .\n" + " ldi $31, 9b-6b(%0)\n" + " .long 7b - .\n" + " ldi $31, 9b-7b(%0)\n" + " .long 8b - .\n" + " ldi $31, 9b-8b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), + "=&r"(tmp4), "=&r"(tmp5), "=&r"(tmp6), "=&r"(tmp7), "=&r"(tmp8) + : "r"(vb), "r"(fp[1]), "0"(0)); + + if (error) + goto got_exception; + + vb = vb + 8; + + __asm__ __volatile__( + " zapnot %10, 0x1, %1\n" + " srl %10, 8, %2\n" + " zapnot %2, 0x1, %2\n" + " srl %10, 16, %3\n" + " zapnot %3, 0x1, %3\n" + " srl %10, 24, %4\n" + " zapnot %4, 0x1, %4\n" + " srl %10, 32, %5\n" + " zapnot %5, 0x1, %5\n" + " srl %10, 40, %6\n" + " zapnot %6, 0x1, %6\n" + " srl %10, 48, %7\n" + " zapnot %7, 0x1, %7\n" + " srl %10, 56, %8\n" + " zapnot %8, 0x1, %8\n" + "1: stb %1, 0(%9)\n" + "2: stb %2, 1(%9)\n" + "3: stb %3, 2(%9)\n" + "4: stb %4, 3(%9)\n" + "5: stb %5, 4(%9)\n" + "6: stb %6, 5(%9)\n" + "7: stb %7, 6(%9)\n" + "8: stb %8, 7(%9)\n" + "9:\n" + ".section __ex_table, \"a\"\n\t" + " .long 1b - .\n" + " ldi $31, 9b-1b(%0)\n" + " .long 2b - .\n" + " ldi $31, 9b-2b(%0)\n" + " .long 3b - .\n" + " ldi $31, 9b-3b(%0)\n" + " .long 4b - .\n" + " ldi $31, 9b-4b(%0)\n" + " .long 5b - .\n" + " ldi $31, 9b-5b(%0)\n" + " .long 6b - .\n" + " ldi $31, 9b-6b(%0)\n" + " .long 7b - .\n" + " ldi $31, 9b-7b(%0)\n" + " .long 8b - .\n" + " ldi $31, 9b-8b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), + "=&r"(tmp4), "=&r"(tmp5), "=&r"(tmp6), "=&r"(tmp7), "=&r"(tmp8) + : "r"(vb), "r"(fp[2]), "0"(0)); + + if (error) + goto got_exception; + + vb = vb + 8; + + __asm__ __volatile__( + " zapnot %10, 0x1, %1\n" + " srl %10, 8, %2\n" + " zapnot %2, 0x1, %2\n" + " srl %10, 16, %3\n" + " zapnot %3, 0x1, %3\n" + " srl %10, 24, %4\n" + " zapnot %4, 0x1, %4\n" + " srl %10, 32, %5\n" + " zapnot %5, 0x1, %5\n" + " srl %10, 40, %6\n" + " zapnot %6, 0x1, %6\n" + " srl %10, 48, %7\n" + " zapnot %7, 0x1, %7\n" + " srl %10, 56, %8\n" + " zapnot %8, 0x1, %8\n" + "1: stb %1, 0(%9)\n" + "2: stb %2, 1(%9)\n" + "3: stb %3, 2(%9)\n" + "4: stb %4, 3(%9)\n" + "5: stb %5, 4(%9)\n" + "6: stb %6, 5(%9)\n" + "7: stb %7, 6(%9)\n" + "8: stb %8, 7(%9)\n" + "9:\n" + ".section __ex_table, \"a\"\n\t" + " .long 1b - .\n" + " ldi $31, 9b-1b(%0)\n" + " .long 2b - .\n" + " ldi $31, 9b-2b(%0)\n" + " .long 3b - .\n" + " ldi $31, 9b-3b(%0)\n" + " .long 4b - .\n" + " ldi $31, 9b-4b(%0)\n" + " .long 5b - .\n" + " ldi $31, 9b-5b(%0)\n" + " .long 6b - .\n" + " ldi $31, 9b-6b(%0)\n" + " .long 7b - .\n" + " ldi $31, 9b-7b(%0)\n" + " .long 8b - .\n" + " ldi $31, 9b-8b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), + "=&r"(tmp4), "=&r"(tmp5), "=&r"(tmp6), "=&r"(tmp7), "=&r"(tmp8) + : "r"(vb), "r"(fp[3]), "0"(0)); + + if (error) + goto got_exception; + + return; + } + case 0x1e: insn = *(unsigned int *)pc; fncode = (insn >> 12) & 0xf; -- Gitee From 4abca94b5c9e30d5555c495a232b04bd0659689e Mon Sep 17 00:00:00 2001 From: Gu Yuchen Date: Tue, 27 Aug 2024 17:19:55 +0800 Subject: [PATCH 28/66] anolis: sw64: fix the register bug in do_entUna ANBZ: #4688 The position is not reserved for $31 in pt_regs. An overflow will occur during storing in do_entUna, which could corrupt PC. A judgement statement is used to set reg_addr, and (reg->regs[reg]) has been changed to *reg_addr. Signed-off-by: Gu Yuchen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/traps.c | 47 ++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index bc7bb4c04456..9a9b43c13286 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -386,6 +386,16 @@ do_entIF(unsigned long inst_type, unsigned long va, struct pt_regs *regs) force_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)regs->pc); } +#define OP_INT_MASK (1L << 0x22 | 1L << 0x2a | /* ldw stw */ \ + 1L << 0x23 | 1L << 0x2b | /* ldl stl */ \ + 1L << 0x21 | 1L << 0x29 | /* ldhu sth */ \ + 1L << 0x20 | 1L << 0x28) /* ldbu stb */ + +#define FN_INT_MASK (1L << 0x0 | 1L << 0x6 | /* ldbu_a stb_a */ \ + 1L << 0x1 | 1L << 0x7 | /* ldhu_a sth_a */ \ + 1L << 0x2 | 1L << 0x8 | /* ldw_a stw_a */ \ + 1L << 0x3 | 1L << 0x9) /* ldl_a stl_a */ + asmlinkage void do_entUna(void *va, unsigned long opcode, unsigned long reg, struct pt_regs *regs) @@ -394,8 +404,23 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, unsigned int insn, fncode, rb; unsigned long tmp, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, vb; unsigned long fp[4]; + unsigned long fake_reg, *reg_addr = &fake_reg; unsigned long pc = regs->pc - 4; + insn = *(unsigned int *)pc; + fncode = (insn >> 12) & 0xf; + + if (((1L << opcode) & OP_INT_MASK) || + ((opcode == 0x1e) && ((1L << fncode) & FN_INT_MASK))) { + /* it's an integer load/store */ + if (reg < 31) { + reg_addr = ®s->regs[reg]; + } else { + /* zero "register" */ + fake_reg = 0; + } + } + /* * We don't want to use the generic get/put unaligned macros as * we want to trap exceptions. Only if we actually get an @@ -1017,7 +1042,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, ".previous" : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4) - : "r"(va), "r"(regs->regs[reg]), "0"(0)); + : "r"(va), "r"(*reg_addr), "0"(0)); if (error) goto got_exception; @@ -1050,7 +1075,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, ".previous" : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4) - : "r"(va), "r"(regs->regs[reg]), "0"(0)); + : "r"(va), "r"(*reg_addr), "0"(0)); if (error) goto got_exception; @@ -1103,7 +1128,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, ".previous" : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4), "=&r"(tmp5), "=&r"(tmp6), "=&r"(tmp7), "=&r"(tmp8) - : "r"(va), "r"(regs->regs[reg]), "0"(0)); + : "r"(va), "r"(*reg_addr), "0"(0)); if (error) goto got_exception; @@ -1190,7 +1215,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, ".previous" : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4) - : "r"(va), "r"(regs->regs[reg]), "0"(0)); + : "r"(va), "r"(*reg_addr), "0"(0)); if (error) goto got_exception; @@ -1222,7 +1247,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, ".previous" : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4) - : "r"(va), "r"(regs->regs[reg]), "0"(0)); + : "r"(va), "r"(*reg_addr), "0"(0)); if (error) goto got_exception; @@ -1274,7 +1299,7 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, ".previous" : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), "=&r"(tmp3), "=&r"(tmp4), "=&r"(tmp5), "=&r"(tmp6), "=&r"(tmp7), "=&r"(tmp8) - : "r"(va), "r"(regs->regs[reg]), "0"(0)); + : "r"(va), "r"(*reg_addr), "0"(0)); if (error) goto got_exception; @@ -1322,16 +1347,6 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, * uses them as temporary storage for integer memory to memory copies. * However, we need to deal with stt/ldt and sts/lds only. */ -#define OP_INT_MASK (1L << 0x22 | 1L << 0x2a | /* ldw stw */ \ - 1L << 0x23 | 1L << 0x2b | /* ldl stl */ \ - 1L << 0x21 | 1L << 0x29 | /* ldhu sth */ \ - 1L << 0x20 | 1L << 0x28) /* ldbu stb */ - -#define FN_INT_MASK (1L << 0x0 | 1L << 0x6 | /* ldbu_a stb_a */ \ - 1L << 0x1 | 1L << 0x7 | /* ldhu_a sth_a */ \ - 1L << 0x2 | 1L << 0x8 | /* ldw_a stw_a */ \ - 1L << 0x3 | 1L << 0x9) /* ldl_a stl_a */ - asmlinkage void do_entUnaUser(void __user *va, unsigned long opcode, unsigned long reg, struct pt_regs *regs) -- Gitee From c583bad436097af851b09b74063cbd9864c4f7dd Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Mon, 26 Aug 2024 10:03:37 +0800 Subject: [PATCH 29/66] anolis: sw64: fix setup_mem_size() ANBZ: #4688 Recalculate mem_size_limit before mem_start is updated, otherwise the min() will always return 0; Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/mm/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/mm/init.c b/arch/sw_64/mm/init.c index c13abbbe26f3..f01d2ebef70f 100644 --- a/arch/sw_64/mm/init.c +++ b/arch/sw_64/mm/init.c @@ -68,9 +68,9 @@ static int __init setup_mem_size(char *p) mem_size_limit = size; if (mem_start < NODE0_START) { - mem_start = NODE0_START; mem_size_limit -= min(mem_size_limit, NODE0_START - mem_start); + mem_start = NODE0_START; } return 0; -- Gitee From a96e21722032bfd397a6b19df33314896d2c2500 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Mon, 12 Aug 2024 17:15:36 +0800 Subject: [PATCH 30/66] anolis: sw64: fix numa setup when acpi is disabled ANBZ: #4688 If acpi is disabled and there's no memory on 2nd node, the 2nd node would not be registered and all cpus would be registered to the 1st node. Fix this issue by moving cpu_set_node() inside numa_init() and make it set numa_nodes_parsed. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/setup.c | 10 ------- arch/sw_64/mm/numa.c | 55 +++++++++++++++++---------------------- 2 files changed, 24 insertions(+), 41 deletions(-) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 6c36fedfa6e3..1cb42570c0d1 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -382,10 +382,6 @@ static int __init request_standard_resources(void) } subsys_initcall(request_standard_resources); -#ifdef CONFIG_NUMA -extern void cpu_set_node(void); -#endif - static int __init topology_init(void) { int i, ret; @@ -733,12 +729,6 @@ setup_arch(char **cmdline_p) /* Default root filesystem to sda2. */ ROOT_DEV = MKDEV(SCSI_DISK0_MAJOR, 2); - - if (acpi_disabled) { -#ifdef CONFIG_NUMA - cpu_set_node(); -#endif - } } static int diff --git a/arch/sw_64/mm/numa.c b/arch/sw_64/mm/numa.c index 2793718c66f6..8736a49e54ee 100644 --- a/arch/sw_64/mm/numa.c +++ b/arch/sw_64/mm/numa.c @@ -289,6 +289,28 @@ static void __init get_numa_info_socket(void) } } +static void cpu_set_node(void) +{ + int i; + + if (numa_off) { + for (i = 0; i < nr_cpu_ids; i++) + cpu_to_node_map[i] = 0; + } else { + for (i = 0; i < nr_cpu_ids; i++) { + int nid = rcid_to_domain_id(cpu_to_rcid(i)); + + cpu_to_node_map[i] = nid; + node_set(nid, numa_nodes_parsed); + } + } + /* + * Setup numa_node for cpu 0 before per_cpu area for booting. + * Actual setup of numa_node will be done in native_smp_prepare_cpus(). + */ + set_cpu_numa_node(0, cpu_to_node_map[0]); +} + static int __init manual_numa_init(void) { int ret, nid; @@ -350,6 +372,8 @@ static int __init manual_numa_init(void) } } + cpu_set_node(); + return 0; } @@ -385,37 +409,6 @@ void __init sw64_numa_init(void) numa_init(manual_numa_init); } -void cpu_set_node(void) -{ - int i; - - if (numa_off) { - for (i = 0; i < nr_cpu_ids; i++) - cpu_to_node_map[i] = 0; - } else { - int rr, default_node, cid; - - rr = first_node(node_online_map); - for (i = 0; i < nr_cpu_ids; i++) { - cid = cpu_to_rcid(i); - default_node = rcid_to_domain_id(cid); - if (node_online(default_node)) { - cpu_to_node_map[i] = default_node; - } else { - cpu_to_node_map[i] = rr; - rr = next_node(rr, node_online_map); - if (rr == MAX_NUMNODES) - rr = first_node(node_online_map); - } - } - } - /* - * Setup numa_node for cpu 0 before per_cpu area for booting. - * Actual setup of numa_node will be done in native_smp_prepare_cpus(). - */ - set_cpu_numa_node(0, cpu_to_node_map[0]); -} - void numa_store_cpu_info(unsigned int cpu) { set_cpu_numa_node(cpu, cpu_to_node_map[cpu]); -- Gitee From e49f585826870f60e161c922bc7327567c3042ac Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Wed, 14 Aug 2024 18:50:13 +0800 Subject: [PATCH 31/66] anolis: sw64: add junzhang_v1/2/3_key ANBZ: #4688 Add junzhang_v1_key/junzhang_v2_key/junzhang_v3_key to identify firmware junzhang/junzhang_v2/junzhang_v3. Signed-off-by: Wu Liliu Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/hw_init.h | 6 ++++++ arch/sw_64/kernel/setup.c | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/arch/sw_64/include/asm/hw_init.h b/arch/sw_64/include/asm/hw_init.h index b2d36df86bf2..c13fbb4d620e 100644 --- a/arch/sw_64/include/asm/hw_init.h +++ b/arch/sw_64/include/asm/hw_init.h @@ -51,10 +51,16 @@ DECLARE_STATIC_KEY_FALSE(run_mode_guest_key); DECLARE_STATIC_KEY_FALSE(run_mode_emul_key); DECLARE_STATIC_KEY_FALSE(hw_una_enabled); +DECLARE_STATIC_KEY_FALSE(junzhang_v1_key); +DECLARE_STATIC_KEY_FALSE(junzhang_v2_key); +DECLARE_STATIC_KEY_FALSE(junzhang_v3_key); #define is_in_host() static_branch_likely(&run_mode_host_key) #define is_in_guest() static_branch_unlikely(&run_mode_guest_key) #define is_in_emul() static_branch_unlikely(&run_mode_emul_key) #define is_guest_or_emul() !static_branch_likely(&run_mode_host_key) +#define is_junzhang_v1() static_branch_unlikely(&junzhang_v1_key) +#define is_junzhang_v2() static_branch_likely(&junzhang_v2_key) +#define is_junzhang_v3() static_branch_unlikely(&junzhang_v3_key) #endif /* _ASM_SW64_HW_INIT_H */ diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 1cb42570c0d1..e3608c601cba 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -86,6 +86,9 @@ DEFINE_STATIC_KEY_FALSE(run_mode_guest_key); DEFINE_STATIC_KEY_FALSE(run_mode_emul_key); DEFINE_STATIC_KEY_FALSE(hw_una_enabled); +DEFINE_STATIC_KEY_FALSE(junzhang_v1_key); +DEFINE_STATIC_KEY_FALSE(junzhang_v2_key); +DEFINE_STATIC_KEY_FALSE(junzhang_v3_key); struct socket_desc_t socket_desc[MAX_NUMSOCKETS]; int memmap_nr; @@ -500,6 +503,20 @@ static void __init setup_firmware_fdt(void) pr_info("EXTCLK: %llu Hz\n", sunway_extclk_hz); } + if (sunway_machine_is_compatible("sunway,junzhang")) { + static_branch_enable(&junzhang_v1_key); + static_branch_disable(&junzhang_v2_key); + static_branch_disable(&junzhang_v3_key); + } else if (sunway_machine_is_compatible("sunway,junzhang_v2")) { + static_branch_enable(&junzhang_v2_key); + static_branch_disable(&junzhang_v1_key); + static_branch_disable(&junzhang_v3_key); + } else if (sunway_machine_is_compatible("sunway,junzhang_v3")) { + static_branch_enable(&junzhang_v3_key); + static_branch_disable(&junzhang_v1_key); + static_branch_disable(&junzhang_v2_key); + } + name = of_flat_dt_get_machine_name(); if (name) pr_info("DTB(from firmware): Machine model: %s\n", name); -- Gitee From 765246abd8ce690223b8783ecdeceef71b4bd668 Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Wed, 14 Aug 2024 19:08:29 +0800 Subject: [PATCH 32/66] anolis: sw64: compatible with suspend implementation ANBZ: #4688 Modify the suspend function to adapt to different firmware. Signed-off-by: Wu Liliu Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/smp.c | 33 ++++++++++++++++---------------- arch/sw_64/kernel/suspend.c | 16 ++++++++-------- drivers/irqchip/irq-sunway-cpu.c | 18 ++++++++--------- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 321f727fe706..900a32747cfb 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -100,10 +100,11 @@ static void downshift_freq(void) struct cpu_topology *sib_topo = &cpu_topology[cpu]; if ((cpu_topo->package_id == sib_topo->package_id) && - (cpu_topo->core_id == sib_topo->core_id)) + (cpu_topo->core_id == sib_topo->core_id)) return; } + core_id = rcid_to_core_id(cpu_to_rcid(cpuid)); node_id = rcid_to_domain_id(cpu_to_rcid(cpuid)); @@ -540,10 +541,11 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle) wmb(); smp_rcb->ready = 0; -#ifdef CONFIG_SUBARCH_C3B - /* send wake up signal */ - send_wakeup_interrupt(cpu); -#endif + if (!is_junzhang_v1()) { + /* send wake up signal */ + send_wakeup_interrupt(cpu); + } + smp_boot_one_cpu(cpu, tidle); #ifdef CONFIG_SUBARCH_C3B @@ -839,17 +841,16 @@ void arch_cpu_idle_dead(void) } #ifdef CONFIG_SUSPEND - -#ifdef CONFIG_SUBARCH_C3B - sleepen(); - send_sleep_interrupt(smp_processor_id()); - while (1) - asm("nop"); -#else - asm volatile("halt"); - while (1) - asm("nop"); -#endif + if (!is_junzhang_v1()) { + sleepen(); + send_sleep_interrupt(smp_processor_id()); + while (1) + asm("nop"); + } else { + asm volatile("halt"); + while (1) + asm("nop"); + } #else asm volatile("memb"); diff --git a/arch/sw_64/kernel/suspend.c b/arch/sw_64/kernel/suspend.c index 97e5478a678f..955cf41fd8c9 100644 --- a/arch/sw_64/kernel/suspend.c +++ b/arch/sw_64/kernel/suspend.c @@ -38,14 +38,14 @@ void sw64_suspend_enter(void) disable_local_timer(); current_thread_info()->pcb.tp = rtid(); -#ifdef CONFIG_SUBARCH_C3B - sw64_suspend_deep_sleep(&suspend_state); -#else - pme_state = PME_WFW; - sw64_write_csr_imb(PME_EN, CSR_INT_EN); - asm("halt"); - local_irq_disable(); -#endif + if (!is_junzhang_v1()) + sw64_suspend_deep_sleep(&suspend_state); + else { + pme_state = PME_WFW; + sw64_write_csr_imb(PME_EN, CSR_INT_EN); + asm("halt"); + local_irq_disable(); + } wrtp(current_thread_info()->pcb.tp); diff --git a/drivers/irqchip/irq-sunway-cpu.c b/drivers/irqchip/irq-sunway-cpu.c index 9dddf6786eab..6a3db0dc183d 100644 --- a/drivers/irqchip/irq-sunway-cpu.c +++ b/drivers/irqchip/irq-sunway-cpu.c @@ -91,17 +91,17 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, nmi_enter(); old_regs = set_irq_regs(regs); -#ifdef CONFIG_SUBARCH_C4 - if (pme_state == PME_WFW) { - pme_state = PME_PENDING; - goto out; - } + if (is_junzhang_v1()) { + if (pme_state == PME_WFW) { + pme_state = PME_PENDING; + goto out; + } - if (pme_state == PME_PENDING) { - handle_device_interrupt(vector); - pme_state = PME_CLEAR; + if (pme_state == PME_PENDING) { + handle_device_interrupt(vector); + pme_state = PME_CLEAR; + } } -#endif if (is_guest_or_emul()) { if ((type & 0xffff) > 15) { -- Gitee From 188191a51443886e45c8db3d262439dde6ba6fe2 Mon Sep 17 00:00:00 2001 From: Xu Linqin Date: Fri, 16 Aug 2024 10:14:17 +0800 Subject: [PATCH 33/66] anolis: sw64: kvm: adjust interrupt priority for guest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ANBZ: #4688 According to architecture manual, adjust interrupt priority of guest in descending order as follows: RTC, IPI, MSI, INTx and VT_SERIAL. It does not follow manual completely due to flat interrupt management in sw64 kvm. The previous priorities were not appropriate, which may cause system lag when numerous IPIs are generated by applications like mariadb within a short period of time. This patch has no negative effect on the performance of Unixbench and fio. Signed-off-by: Xu Linqin Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/emulate.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/sw_64/kvm/emulate.c b/arch/sw_64/kvm/emulate.c index 9f2ededd5a1e..f103a5f3b9d4 100644 --- a/arch/sw_64/kvm/emulate.c +++ b/arch/sw_64/kvm/emulate.c @@ -4,6 +4,7 @@ * Author: fire3 yangzh * linhn */ +#include #include #include #include @@ -75,6 +76,12 @@ unsigned int interrupt_pending(struct kvm_vcpu *vcpu, bool *more) bitmap_copy(blk, vcpu->arch.irqs_pending, SWVM_IRQS); + if (test_bit(INT_RTC, blk)) + return INT_RTC; + + if (test_bit(INT_IPI, blk)) + return INT_IPI; + irq = find_last_bit(blk, SWVM_IRQS); return irq; -- Gitee From b5f59926d433d836d6ae98e42b9b003c19288101 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 3 Sep 2024 16:36:27 +0800 Subject: [PATCH 34/66] anolis: sw64: add arch_hugetlb_valid_size for C4 ANBZ: #4688 Add arch_hugetlb_valid_size routine used to validate passed huge page size. Remove hugepagesz= command line parsing which has been moved into an arch independent routine. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/mm/hugetlbpage_c4.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/arch/sw_64/mm/hugetlbpage_c4.c b/arch/sw_64/mm/hugetlbpage_c4.c index 913389cd2577..b3649e19bff1 100644 --- a/arch/sw_64/mm/hugetlbpage_c4.c +++ b/arch/sw_64/mm/hugetlbpage_c4.c @@ -433,20 +433,14 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, } #endif /* CONFIG_HUGETLB_PAGE */ -static __init int setup_hugepagesz(char *opt) +bool __init arch_hugetlb_valid_size(unsigned long size) { - unsigned long ps = memparse(opt, &opt); - - switch (ps) { + switch (size) { case PUD_SIZE: case PMD_SIZE * CONT_PMDS: case PMD_SIZE: - hugetlb_add_hstate(ilog2(ps) - PAGE_SHIFT); - return 1; + return true; } - pr_err("hugepagesz: Unsupported page size %lu M\n", - ps >> 20); - return 0; + return false; } -__setup("hugepagesz=", setup_hugepagesz); -- Gitee From b0389a813c2568f2797b71e661b5f4bc094ffb47 Mon Sep 17 00:00:00 2001 From: Wang Yicheng Date: Wed, 4 Sep 2024 09:34:23 +0800 Subject: [PATCH 35/66] anolis: sw64: fix compilation issues ANBZ: #4688 Current code causes a compilation error when the CONFIG_PM is not selected. This commit modifies the relevant code logic to fix this issue. Signed-off-by: Wang Yicheng Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/cpufreq.h | 1 + drivers/irqchip/irq-sunway-cpu.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/arch/sw_64/include/asm/cpufreq.h b/arch/sw_64/include/asm/cpufreq.h index 0d3e794b16ea..d89db83b42a6 100644 --- a/arch/sw_64/include/asm/cpufreq.h +++ b/arch/sw_64/include/asm/cpufreq.h @@ -8,6 +8,7 @@ #include #include #include +#include struct clk; diff --git a/drivers/irqchip/irq-sunway-cpu.c b/drivers/irqchip/irq-sunway-cpu.c index 6a3db0dc183d..406db782e763 100644 --- a/drivers/irqchip/irq-sunway-cpu.c +++ b/drivers/irqchip/irq-sunway-cpu.c @@ -91,6 +91,7 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, nmi_enter(); old_regs = set_irq_regs(regs); +#ifdef CONFIG_PM if (is_junzhang_v1()) { if (pme_state == PME_WFW) { pme_state = PME_PENDING; @@ -102,6 +103,7 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, pme_state = PME_CLEAR; } } +#endif if (is_guest_or_emul()) { if ((type & 0xffff) > 15) { -- Gitee From d18e64b814c99093d529f505259089bc837732ed Mon Sep 17 00:00:00 2001 From: Gao Chen Date: Tue, 22 Oct 2024 09:37:01 +0800 Subject: [PATCH 36/66] anolis: sw64: add the missed clear_flush() ANBZ: #4688 This patch adds clear_flush() back, which was deleted by mistake. Signed-off-by: Gao Chen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/mm/hugetlbpage_c4.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/sw_64/mm/hugetlbpage_c4.c b/arch/sw_64/mm/hugetlbpage_c4.c index b3649e19bff1..07ec95b734d4 100644 --- a/arch/sw_64/mm/hugetlbpage_c4.c +++ b/arch/sw_64/mm/hugetlbpage_c4.c @@ -88,6 +88,19 @@ static pte_t get_and_clear(struct mm_struct *mm, return orig_pte; } +static void clear_flush(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, unsigned long pgsize, + unsigned long ncontig) +{ + struct vm_area_struct vma = TLB_FLUSH_VMA(mm, 0); + unsigned long i, saddr = addr; + + for (i = 0; i < ncontig; i++, addr += pgsize, ptep++) + pte_clear(mm, addr, ptep); + + flush_tlb_range(&vma, saddr, addr); +} + static pte_t get_clear_contig_flush(struct mm_struct *mm, unsigned long addr, pte_t *ptep, unsigned long pgsize, unsigned long ncontig) -- Gitee From 2119b773c1487c78f2b54ea7cb1f34ecf7961e5b Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 3 Sep 2024 16:49:04 +0800 Subject: [PATCH 37/66] anolis: sw64: fix set_huge_pte_at for C4 ANBZ: #4688 Use clear_flush instead of get_and_clear to make sure tlb would be flushd. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/mm/hugetlbpage_c4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/mm/hugetlbpage_c4.c b/arch/sw_64/mm/hugetlbpage_c4.c index 07ec95b734d4..ce3f5168f561 100644 --- a/arch/sw_64/mm/hugetlbpage_c4.c +++ b/arch/sw_64/mm/hugetlbpage_c4.c @@ -233,7 +233,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pfn = pte_pfn(pte); hugeprot = pte_pgprot(pte); - get_and_clear(mm, addr, ptep, pgsize, ncontig); + clear_flush(mm, addr, ptep, pgsize, ncontig); for (i = 0; i < ncontig; i++, ptep++, addr += pgsize) set_pte_at(mm, addr, ptep, pfn_pte(pfn, hugeprot)); -- Gitee From 299fe4da435506b202a116821d523de19e18ca72 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 10 Sep 2024 08:49:08 +0800 Subject: [PATCH 38/66] anolis: sw64: modify sys_pfh_ops ANBZ: #4688 In order to be compatible with new chip which extends each field in CSR:PFH_CNT, assign a unique id for each field the user may want to modify, and let the user modify each field individually. Since this syscall has not been widely used, we will abandon the old one directly, and assign a new number for this new version. Only root on host machine is allowed to use this syscall. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/sys_sw64.c | 187 ++++++++++++++++++++----- arch/sw_64/kernel/syscalls/syscall.tbl | 4 +- 2 files changed, 157 insertions(+), 34 deletions(-) diff --git a/arch/sw_64/kernel/sys_sw64.c b/arch/sw_64/kernel/sys_sw64.c index 31e6a8d65cf9..7efebce4af11 100644 --- a/arch/sw_64/kernel/sys_sw64.c +++ b/arch/sw_64/kernel/sys_sw64.c @@ -154,53 +154,176 @@ SYSCALL_DEFINE0(sw64_pipe) #ifdef CONFIG_SUBARCH_C4 -struct pfh_val { - unsigned long pfh_ctl; - unsigned long pfh_cnt; -}; +static void local_set_pfh_ctl(void *info) +{ + unsigned long *kcsr = info; -static void local_set_pfh(void *info) + sw64_write_csr(*kcsr, CSR_PFH_CTL); +} + +static void local_set_pfh_cnt(void *info) { - struct pfh_val *kbuf = info; + unsigned long *kcsr = info; - if (kbuf->pfh_ctl) - sw64_write_csr(kbuf->pfh_ctl, CSR_PFH_CTL); - if (kbuf->pfh_cnt) - sw64_write_csr(kbuf->pfh_cnt, CSR_PFH_CNT); + sw64_write_csr(*kcsr, CSR_PFH_CNT); } -SYSCALL_DEFINE3(pfh_ops, unsigned long, op, - unsigned long __user *, pfh_ctl_p, - unsigned long __user *, pfh_cnt_p) +enum pfh_field_id { + L1_CCNT, + L1_RCNT, + L1_MCNT, + L2_CCNT, + L2_RCNT, + L2_MCNT, + L2_RAMP, + L3_CCNT, + L3_RCNT, + L3_MCNT, + L3_RAMP, + L1PFH_EN = 0x10, + L2PFH_EN, + L3PFH_EN, + PFH_FIELD_MAX +}; + +struct pfh_field { + unsigned long shift; + unsigned long mask; +}; + +struct pfh_field pfh_fields_c4[PFH_FIELD_MAX] = { + [L1_CCNT] = {0, 0x0f}, + [L1_RCNT] = {4, 0x0f}, + [L1_MCNT] = {8, 0x0f}, + [L2_CCNT] = {12, 0x0f}, + [L2_RCNT] = {16, 0x0f}, + [L2_MCNT] = {20, 0x0f}, + [L2_RAMP] = {24, 0x03}, + [L3_CCNT] = {26, 0x1f}, + [L3_RCNT] = {31, 0x1f}, + [L3_MCNT] = {36, 0x1f}, + [L3_RAMP] = {41, 0x03}, + [L1PFH_EN] = {0, 0x01}, + [L2PFH_EN] = {1, 0x01}, + [L3PFH_EN] = {2, 0x01} +}; + +struct pfh_field pfh_fields_c4b[PFH_FIELD_MAX] = { + [L1_CCNT] = {0, 0x3f}, + [L1_RCNT] = {6, 0x3f}, + [L1_MCNT] = {12, 0x3f}, + [L2_CCNT] = {18, 0x3f}, + [L2_RCNT] = {24, 0x3f}, + [L2_MCNT] = {30, 0x3f}, + [L2_RAMP] = {36, 0x03}, + [L3_CCNT] = {38, 0x7f}, + [L3_RCNT] = {45, 0x7f}, + [L3_MCNT] = {52, 0x7f}, + [L3_RAMP] = {59, 0x03}, + [L1PFH_EN] = {0, 0x01}, + [L2PFH_EN] = {1, 0x01}, + [L3PFH_EN] = {2, 0x01} +}; + +/* + * id: + * 0x00: PFH_CNT: L1_CCNT + * 0x01: PFH_CNT: L1_RCNT + * 0x02: PFH_CNT: L1_MCNT + * 0x03: PFH_CNT: L2_CCNT + * 0x04: PFH_CNT: L2_RCNT + * 0x05: PFH_CNT: L2_MCNT + * 0x06: PFH_CNT: L2_RAMP + * 0x07: PFH_CNT: L3_CCNT + * 0x08: PFH_CNT: L3_RCNT + * 0x09: PFH_CNT: L3_MCNT + * 0x0a: PFH_CNT: L3_RAMP + * 0x10: PFH_CTL: L1PFH_EN + * 0x11: PFH_CTL: L2PFH_EN + * 0x12: PFH_CTL: L3PFH_EN + * op: 0 for get, 1 for set + */ +SYSCALL_DEFINE3(pfh_ops, unsigned long, id, unsigned long, op, + unsigned long __user *, buf) { - struct pfh_val kbuf = {0, 0}; + unsigned long kcsr = 0; + unsigned long kbuf = 0; + unsigned long field_shift; + unsigned long field_mask; + unsigned long csr_idx; long error = 0; + struct pfh_field *pfh_fields_arr; + + if (!is_in_host()) + return -EPERM; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (op) { // op != 0, set - if (pfh_ctl_p) - error |= get_user(kbuf.pfh_ctl, pfh_ctl_p); - if (pfh_cnt_p) - error |= get_user(kbuf.pfh_cnt, pfh_cnt_p); + switch (id & 0xf0) { + case 0x00: + csr_idx = CSR_PFH_CNT; + break; + case 0x10: + csr_idx = CSR_PFH_CTL; + break; + default: + error = -EINVAL; + goto out; + } - if (!error && (kbuf.pfh_ctl || kbuf.pfh_cnt)) { - smp_call_function(local_set_pfh, &kbuf, 1); - local_set_pfh(&kbuf); - } - } else { // op == 0, get - if (pfh_ctl_p) { - kbuf.pfh_ctl = sw64_read_csr(CSR_PFH_CTL); - error |= put_user(kbuf.pfh_ctl, pfh_ctl_p); - } + if (!is_junzhang_v3()) + pfh_fields_arr = pfh_fields_c4; + else + pfh_fields_arr = pfh_fields_c4b; - if (pfh_cnt_p) { - kbuf.pfh_cnt = sw64_read_csr(CSR_PFH_CNT); - error |= put_user(kbuf.pfh_cnt, pfh_cnt_p); - } + field_shift = pfh_fields_arr[id].shift; + field_mask = pfh_fields_arr[id].mask << field_shift; + + switch (csr_idx) { + case CSR_PFH_CTL: + kcsr = sw64_read_csr(CSR_PFH_CTL); + break; + case CSR_PFH_CNT: + kcsr = sw64_read_csr(CSR_PFH_CNT); + break; + default: + /* should never reach here */ + BUG(); + } + + switch (op) { + case 0: // get + kbuf = (kcsr & field_mask) >> field_shift; + error = put_user(kbuf, buf); + goto out; + case 1: // set + error = get_user(kbuf, buf); + if (error) + goto out; + kcsr = (kcsr & (~field_mask)) | + ((kbuf << field_shift) & field_mask); + break; + default: + error = -EINVAL; + goto out; + } + + switch (csr_idx) { + case CSR_PFH_CTL: + smp_call_function(local_set_pfh_ctl, &kcsr, 1); + local_set_pfh_ctl(&kcsr); + break; + case CSR_PFH_CNT: + smp_call_function(local_set_pfh_cnt, &kcsr, 1); + local_set_pfh_cnt(&kcsr); + break; + default: + /* should never reach here */ + BUG(); } +out: return error; } diff --git a/arch/sw_64/kernel/syscalls/syscall.tbl b/arch/sw_64/kernel/syscalls/syscall.tbl index 3acd8b5ea7db..fe75af3652e3 100644 --- a/arch/sw_64/kernel/syscalls/syscall.tbl +++ b/arch/sw_64/kernel/syscalls/syscall.tbl @@ -116,8 +116,8 @@ 106 common listen sys_listen #107 is unused #108 is unused -#109 is unused -110 common pfh_ops sys_pfh_ops +109 common pfh_ops sys_pfh_ops +110 common old_pfh_ops sys_ni_syscall 111 common sigsuspend sys_sigsuspend #112 is unused 113 common recvmsg sys_recvmsg -- Gitee From f14a846d3cd7210f056650525705434952ddbc7a Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Tue, 10 Sep 2024 09:21:17 +0800 Subject: [PATCH 39/66] anolis: sw64: kvm: fix an error when unmapping 512M hugepages ANBZ: #4688 In sw64 architecture, 512M hugepage consist of 64 consecutive 8M hugepages. Therefore, at the time of unmapping, we should get the address of the next 512M hugepage. Current code get the address of the next 8M hugepage, it will be out of range when we unmap the page, so we fix it. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index d69b42171d1a..d59438b0c9fd 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -146,8 +146,10 @@ static void unmap_apt_pmds(struct kvm *kvm, pud_t *pud, if (!pmd_none(*pmd)) { if (pmd_trans_huge(*pmd)) { if (pmd_cont(*pmd)) { - for (i = 0; i < CONT_PMDS; i++, pmd++) - pmd_clear(pmd); + for (i = 0; i < CONT_PMDS; i++) + pmd_clear(pmd + i); + pmd += CONT_PMDS - 1; + next += CONT_PMD_SIZE - PMD_SIZE; } else pmd_clear(pmd); /* Do we need flush tlb???? edited by lff */ -- Gitee From 25fef10e108bb1d0580128c2157eb73078cbd9f0 Mon Sep 17 00:00:00 2001 From: Wang Yuanheng Date: Thu, 19 Sep 2024 17:05:52 +0800 Subject: [PATCH 40/66] anolis: sw64: mm: fix PFN of PMDs for 512M hugepage ANBZ: #4688 A 512M hugepage is composed of 64 contiguous 8M hugepages. When setting up the page table entries, it assigned the PFN of first 8M hugepage to all the 64 contiguous PMDs and set the HPFN bit. This caused incorrect page in gup_huge_pmd() because of PMD_MASK, and resulted in incorrect address access in some scenarios when 512M hugepages were used. This patch fixes the page table setup to ensure that each PMD's PFN corresponds to an individual 8M hugepage. For kvm, although the original code works fine, this patch makes similar modifications to Additional Page Table(APT) to maintain consistency in the 512M hugepage setup method. Signed-off-by: Wang Yuanheng Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 8 ++++++-- arch/sw_64/mm/hugetlbpage_c4.c | 15 +++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index d59438b0c9fd..91745f61c9b0 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -956,10 +956,11 @@ static int apt_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, static int apt_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache - *cache, phys_addr_t addr, const pmd_t *new_pmd, unsigned long sz) + *cache, phys_addr_t addr, pmd_t *new_pmd, unsigned long sz) { pmd_t *pmd, old_pmd, *ori_pmd; int i; + unsigned long dpfn; retry: pmd = apt_get_pmd(kvm, cache, addr, sz); VM_BUG_ON(!pmd); @@ -1022,8 +1023,11 @@ static int apt_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache /* Do we need WRITE_ONCE(pmd, new_pmd)? */ if (sz == CONT_PMD_SIZE) { - for (i = 0; i < CONT_PMDS; i++, ori_pmd++) + dpfn = 1UL << (_PFN_SHIFT + PMD_SHIFT - PAGE_SHIFT); + for (i = 0; i < CONT_PMDS; i++, ori_pmd++) { set_pmd(ori_pmd, *new_pmd); + new_pmd->pmd += dpfn; + } } else set_pmd(pmd, *new_pmd); return 0; diff --git a/arch/sw_64/mm/hugetlbpage_c4.c b/arch/sw_64/mm/hugetlbpage_c4.c index ce3f5168f561..2611af9cf780 100644 --- a/arch/sw_64/mm/hugetlbpage_c4.c +++ b/arch/sw_64/mm/hugetlbpage_c4.c @@ -215,7 +215,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, size_t pgsize; int i; int ncontig; - unsigned long pfn; + unsigned long pfn, dpfn; pgprot_t hugeprot; /* @@ -231,11 +231,12 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, ncontig = num_contig_ptes(sz, &pgsize); pfn = pte_pfn(pte); + dpfn = PMD_SIZE >> PAGE_SHIFT; hugeprot = pte_pgprot(pte); clear_flush(mm, addr, ptep, pgsize, ncontig); - for (i = 0; i < ncontig; i++, ptep++, addr += pgsize) + for (i = 0; i < ncontig; i++, ptep++, addr += pgsize, pfn += dpfn) set_pte_at(mm, addr, ptep, pfn_pte(pfn, hugeprot)); } @@ -254,7 +255,7 @@ void set_huge_swap_pte_at(struct mm_struct *mm, unsigned long addr, void huge_ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - unsigned long pfn; + unsigned long pfn, dpfn; pgprot_t hugeprot; int ncontig, i; size_t pgsize; @@ -266,6 +267,7 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm, } ncontig = CONT_PMDS; + dpfn = PMD_SIZE >> PAGE_SHIFT; pte = get_and_clear(mm, addr, ptep, pgsize, ncontig); pte = pte_wrprotect(pte); @@ -273,7 +275,7 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm, hugeprot = pte_pgprot(pte); pfn = pte_pfn(pte); - for (i = 0; i < ncontig; i++, ptep++, addr += pgsize) + for (i = 0; i < ncontig; i++, ptep++, addr += pgsize, pfn += dpfn) set_pte_at(mm, addr, ptep, pfn_pte(pfn, hugeprot)); } @@ -332,7 +334,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma, { int ncontig, i; size_t pgsize = 0; - unsigned long pfn = pte_pfn(pte); + unsigned long pfn = pte_pfn(pte), dpfn; pgprot_t hugeprot; pte_t orig_pte; @@ -340,6 +342,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma, return ptep_set_access_flags(vma, addr, ptep, pte, dirty); ncontig = CONT_PMDS; + dpfn = PMD_SIZE >> PAGE_SHIFT; if (!__cont_access_flags_changed(ptep, pte, ncontig)) return 0; @@ -355,7 +358,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma, pte = pte_mkyoung(pte); hugeprot = pte_pgprot(pte); - for (i = 0; i < ncontig; i++, ptep++, addr += pgsize) + for (i = 0; i < ncontig; i++, ptep++, addr += pgsize, pfn += dpfn) set_pte_at(vma->vm_mm, addr, ptep, pfn_pte(pfn, hugeprot)); return 1; -- Gitee From 7cdccf96c9ddd11c648b0596088bca871012b5af Mon Sep 17 00:00:00 2001 From: Gu Yuchen Date: Wed, 25 Sep 2024 11:36:49 +0800 Subject: [PATCH 41/66] anolis: sw64: fix compilation issues on match.c ANBZ: #4688 The current code has a compilation error in the match.c file on Core3 environment. The DEBUG_MATCH option relies on Core4. This commit modifies the relevant code to fix this issue. Signed-off-by: Gu Yuchen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig.debug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/Kconfig.debug b/arch/sw_64/Kconfig.debug index 6cb3c2488b36..985fe68c29b9 100644 --- a/arch/sw_64/Kconfig.debug +++ b/arch/sw_64/Kconfig.debug @@ -47,7 +47,7 @@ config SW64_RRK config DEBUG_MATCH bool "instruction-flow and data-flow match debugfs interface" - depends on DEBUG_FS + depends on DEBUG_FS && SUBARCH_C4 default n help Turns on the DebugFS interface for instruction-flow and data-flow match. -- Gitee From e64ea73f73dd8c11d2b9cc8446a500801f6859f6 Mon Sep 17 00:00:00 2001 From: Zhi Tongze Date: Sat, 12 Oct 2024 09:18:08 +0800 Subject: [PATCH 42/66] anolis: sw64: fix the error of cpufreq update ANBZ: #4688 When adjusting the cpu frequency, if 0 is returned, it is a correct execution return. if a non-zero value is returned, it is an incorrect execution return. the current logic is wrong and has been fixed. Signed-off-by: Zhi Tongze Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/cpufreq/sw64_cpufreq.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/sw64_cpufreq.c b/drivers/cpufreq/sw64_cpufreq.c index f4bf5f3cc550..93163da904a2 100644 --- a/drivers/cpufreq/sw64_cpufreq.c +++ b/drivers/cpufreq/sw64_cpufreq.c @@ -66,13 +66,16 @@ static unsigned int sw64_cpufreq_get(unsigned int cpu) static int sw64_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { + int ret; unsigned int cpu = policy->cpu; if (!cpu_online(cpu)) return -ENODEV; /* setting the cpu frequency */ - sw64_set_rate(index); + ret = sw64_set_rate(index); + if (ret) + return ret; update_cpu_freq(freq_table[index].frequency); return 0; -- Gitee From 497db317aff155748de33ebe1b0a1ea3f5bcc0f6 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 15 Oct 2024 08:59:15 +0800 Subject: [PATCH 43/66] anolis: sw64: show CPU feature UNA in /proc/cpuinfo ANBZ: #4688 Show whether the cpu hardware support unaligned memory access in cpuinfo. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/cpu.h | 7 ++++++- arch/sw_64/kernel/cpu.c | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/include/asm/cpu.h b/arch/sw_64/include/asm/cpu.h index e6f5cfdbaa3a..37a588fe12d9 100644 --- a/arch/sw_64/include/asm/cpu.h +++ b/arch/sw_64/include/asm/cpu.h @@ -14,9 +14,14 @@ enum hmcall_cpuid_cmd { GET_VENDOR_ID = 2, GET_MODEL = 3, GET_CPU_FREQ = 4, - GET_CACHE_INFO = 5 + GET_CACHE_INFO = 5, + GET_FEATURES = 6 }; +#define CPU_FEAT_FPU 0x1 +#define CPU_FEAT_SIMD 0x2 +#define CPU_FEAT_UNA 0x4 + enum sunway_cpu_model { CPU_SW3231 = 0x31, CPU_SW831 = 0x32, diff --git a/arch/sw_64/kernel/cpu.c b/arch/sw_64/kernel/cpu.c index 339bef13366a..030b33405873 100644 --- a/arch/sw_64/kernel/cpu.c +++ b/arch/sw_64/kernel/cpu.c @@ -142,7 +142,8 @@ static int show_cpuinfo(struct seq_file *f, void *slot) loops_per_jiffy / (500000/HZ), (loops_per_jiffy / (5000/HZ)) % 100); - seq_printf(f, "flags\t\t: fpu simd vpn upn cpuid\n"); + seq_printf(f, "flags\t\t: fpu simd vpn upn cpuid%s\n", + (cpuid(GET_FEATURES, 0) & CPU_FEAT_UNA) ? " una" : ""); seq_printf(f, "page size\t: %d\n", 8192); seq_printf(f, "cache_alignment\t: %d\n", l3_cachline_size); seq_printf(f, "address sizes\t: %u bits physical, %u bits virtual\n\n", -- Gitee From 05778cfa3663f2e387c050097b74e6fa144e7a70 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Mon, 14 Oct 2024 14:42:03 +0800 Subject: [PATCH 44/66] anolis: sw64: fix mmap protection_map ANBZ: #4688 Set FOW bit for shared writable page so the software could set dirty-bit in exception handling. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/pgtable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/include/asm/pgtable.h b/arch/sw_64/include/asm/pgtable.h index b9f98b9af33e..e9843b19916e 100644 --- a/arch/sw_64/include/asm/pgtable.h +++ b/arch/sw_64/include/asm/pgtable.h @@ -207,7 +207,7 @@ static inline void set_p4d(p4d_t *p4dp, p4d_t p4d) #define _PAGE_CHG_MASK (_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS | _PAGE_SPECIAL | _PAGE_LEAF | _PAGE_CONT) #define _PAGE_P(x) _PAGE_NORMAL((x) | _PAGE_FOW) -#define _PAGE_S(x) _PAGE_NORMAL(x) +#define _PAGE_S(x) _PAGE_NORMAL((x) | _PAGE_FOW) /* * pgprot_noncached() is only for infiniband pci support, and a real -- Gitee From 77cd50f7659811fdf38ec6169d2c151719522659 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 12 Sep 2024 14:55:40 +0800 Subject: [PATCH 45/66] anolis: sw64: pci: remove function fix_jm585_reset() ANBZ: #4688 Remove function fix_jm585_reset() and add a PCI quirk to fix the issue of JMicron 585 SATA card when reboot. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/platform.h | 1 - arch/sw_64/kernel/reset.c | 26 +++------------------ arch/sw_64/pci/pci.c | 30 +++++++++++++++++++++++++ drivers/platform/sw64/legacy_junzhang.c | 5 ++--- drivers/platform/sw64/legacy_xuelang.c | 5 ++--- 5 files changed, 37 insertions(+), 30 deletions(-) diff --git a/arch/sw_64/include/asm/platform.h b/arch/sw_64/include/asm/platform.h index c44116df8e16..3fbe9362c568 100644 --- a/arch/sw_64/include/asm/platform.h +++ b/arch/sw_64/include/asm/platform.h @@ -29,7 +29,6 @@ extern void (*pm_restart)(void); extern void (*pm_halt)(void); extern int i2c_set_adapter(void); extern void cpld_write(uint8_t slave_addr, uint8_t reg, uint8_t data); -extern void fix_jm585_reset(void); extern void early_parse_fdt_property(const void *fdt, const char *path, const char *prop_name, u64 *property, int size); diff --git a/arch/sw_64/kernel/reset.c b/arch/sw_64/kernel/reset.c index 3f1961ce85de..7bbd6ce8e07a 100644 --- a/arch/sw_64/kernel/reset.c +++ b/arch/sw_64/kernel/reset.c @@ -8,32 +8,13 @@ #include #include #include -#include #include #include #include #include #include -#include -void fix_jm585_reset(void) -{ - struct pci_dev *pdev; - struct pci_controller *hose; - int val; - - pdev = pci_get_device(PCI_VENDOR_ID_JMICRON, - 0x0585, NULL); - if (pdev) { - hose = pci_bus_to_pci_controller(pdev->bus); - val = readl(hose->rc_config_space_base + RC_PORT_LINK_CTL); - writel((val | 0x8), (hose->rc_config_space_base + RC_PORT_LINK_CTL)); - writel(val, (hose->rc_config_space_base + RC_PORT_LINK_CTL)); - - } - -} static void default_halt(void) { local_irq_disable(); @@ -57,10 +38,6 @@ static void default_poweroff(void) static void default_restart(void) { - /* No point in taking interrupts anymore. */ - local_irq_disable(); - - fix_jm585_reset(); #ifdef CONFIG_EFI if (efi_capsule_pending(NULL)) efi_reboot(REBOOT_WARM, NULL); @@ -103,6 +80,9 @@ void machine_restart(char *command) preempt_disable(); smp_send_stop(); #endif + /* No point in taking interrupts anymore. */ + local_irq_disable(); + do_kernel_restart(command); pm_restart(); } diff --git a/arch/sw_64/pci/pci.c b/arch/sw_64/pci/pci.c index 841ec3ea9f75..de0c7c4a45c1 100644 --- a/arch/sw_64/pci/pci.c +++ b/arch/sw_64/pci/pci.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -265,6 +266,35 @@ static void enable_sw_dca(struct pci_dev *dev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, enable_sw_dca); #endif +static int jm585_restart_notify(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct pci_dev *pdev; + struct pci_controller *hose; + int val; + + pdev = pci_get_device(PCI_VENDOR_ID_JMICRON, 0x0585, NULL); + if (pdev) { + hose = pci_bus_to_pci_controller(pdev->bus); + val = readl(hose->rc_config_space_base + RC_PORT_LINK_CTL); + writel((val | 0x8), (hose->rc_config_space_base + RC_PORT_LINK_CTL)); + writel(val, (hose->rc_config_space_base + RC_PORT_LINK_CTL)); + } + + return NOTIFY_DONE; +} + +static void quirk_jm585_restart(struct pci_dev *dev) +{ + static struct notifier_block jm585_restart_nb = { + .notifier_call = jm585_restart_notify, + .priority = 128, + }; + + register_restart_handler(&jm585_restart_nb); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_JMICRON, 0x0585, quirk_jm585_restart); + /** * There are some special aspects to the Root Complex of Sunway: * 1. Root Complex config space base addr is different diff --git a/drivers/platform/sw64/legacy_junzhang.c b/drivers/platform/sw64/legacy_junzhang.c index 17d6d151d0b8..56fc57d46923 100644 --- a/drivers/platform/sw64/legacy_junzhang.c +++ b/drivers/platform/sw64/legacy_junzhang.c @@ -41,10 +41,9 @@ void sw64_poweroff(void) void sw64_restart(void) { - if (is_in_host()) { - fix_jm585_reset(); + if (is_in_host()) cpld_write(0x64, 0x00, 0xc3); - } else + else vt_mode_kill_arch(LINUX_REBOOT_CMD_RESTART); } diff --git a/drivers/platform/sw64/legacy_xuelang.c b/drivers/platform/sw64/legacy_xuelang.c index 8a63d9edf9f2..67b4436b5a55 100644 --- a/drivers/platform/sw64/legacy_xuelang.c +++ b/drivers/platform/sw64/legacy_xuelang.c @@ -42,10 +42,9 @@ void sw64_poweroff(void) void sw64_restart(void) { - if (is_in_host()) { - fix_jm585_reset(); + if (is_in_host()) cpld_write(0x64, 0x00, 0xc3); - } else + else vt_mode_kill_arch(LINUX_REBOOT_CMD_RESTART); } -- Gitee From 72fdd011145249e9c6a34c723db6bc5da98f9ce6 Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Fri, 11 Oct 2024 08:51:39 +0000 Subject: [PATCH 46/66] anolis: sw64: irqchip: improve intx implementation ANBZ: #4688 Improve INTx implementation by applying the following modifications: - Replace number with macros in irq-sunway-pci-intx.c. - Rename some ambiguous functions. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/irq_impl.h | 2 +- arch/sw_64/include/asm/pci.h | 2 +- arch/sw_64/kernel/irq.c | 2 +- arch/sw_64/kernel/pci-noop.c | 2 +- drivers/irqchip/irq-sunway-cpu.c | 8 ++--- drivers/irqchip/irq-sunway-pci-intx.c | 45 ++++++++++++++++++--------- 6 files changed, 39 insertions(+), 22 deletions(-) diff --git a/arch/sw_64/include/asm/irq_impl.h b/arch/sw_64/include/asm/irq_impl.h index c4f2690bca2e..0e31aaf37ac6 100644 --- a/arch/sw_64/include/asm/irq_impl.h +++ b/arch/sw_64/include/asm/irq_impl.h @@ -44,7 +44,7 @@ extern struct irqaction timer_irqaction; extern void init_rtc_irq(irq_handler_t handler); extern void handle_irq(int irq); extern void handle_ipi(struct pt_regs *regs); -extern void __init sw64_init_irq(void); +extern void __init sunway_init_pci_intx(void); extern irqreturn_t timer_interrupt(int irq, void *dev); #endif /* _ASM_SW64_IRQ_IMPL_H */ diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index 3527b4a92413..a1acda1c166c 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -153,7 +153,7 @@ struct pci_controller { extern void __init sw64_init_pci(void); extern void __init sw64_device_interrupt(unsigned long vector); extern void setup_intx_irqs(struct pci_controller *hose); -extern void __init sw64_init_irq(void); +extern void __init sunway_init_pci_intx(void); extern void __init sw64_init_arch(void); extern int sw64_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); extern struct pci_controller *hose_head; diff --git a/arch/sw_64/kernel/irq.c b/arch/sw_64/kernel/irq.c index d916a484b2fb..82854ba75a94 100644 --- a/arch/sw_64/kernel/irq.c +++ b/arch/sw_64/kernel/irq.c @@ -128,7 +128,7 @@ void __init init_IRQ(void) set_nmi(INT_PC); } - sw64_init_irq(); + sunway_init_pci_intx(); irqchip_init(); } diff --git a/arch/sw_64/kernel/pci-noop.c b/arch/sw_64/kernel/pci-noop.c index abfba92fa6a9..9fc6bb373605 100644 --- a/arch/sw_64/kernel/pci-noop.c +++ b/arch/sw_64/kernel/pci-noop.c @@ -135,4 +135,4 @@ void __init common_init_pci(void) } void __init sw64_init_arch(void) { } -void __init sw64_init_irq(void) { } +void __init sunway_init_pci_intx(void) { } diff --git a/drivers/irqchip/irq-sunway-cpu.c b/drivers/irqchip/irq-sunway-cpu.c index 406db782e763..5aeda6a673aa 100644 --- a/drivers/irqchip/irq-sunway-cpu.c +++ b/drivers/irqchip/irq-sunway-cpu.c @@ -39,7 +39,7 @@ struct fwnode_handle *cintc_handle; -static void handle_device_interrupt(unsigned long irq_info) +static void handle_pci_intx_interrupt(unsigned long irq_info) { unsigned int i; @@ -48,7 +48,7 @@ static void handle_device_interrupt(unsigned long irq_info) return; } - for (i = 0; i < 4; i++) { + for (i = 0; i < PCI_NUM_INTX; i++) { if ((irq_info >> i) & 0x1) handle_intx(i); } @@ -99,7 +99,7 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, } if (pme_state == PME_PENDING) { - handle_device_interrupt(vector); + handle_pci_intx_interrupt(vector); pme_state = PME_CLEAR; } } @@ -123,7 +123,7 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, handle_pci_msi_interrupt(type, vector, irq_arg); goto out; case INT_INTx: - handle_device_interrupt(vector); + handle_pci_intx_interrupt(vector); goto out; case INT_IPI: diff --git a/drivers/irqchip/irq-sunway-pci-intx.c b/drivers/irqchip/irq-sunway-pci-intx.c index d6f23c666237..89eb6ca86d26 100644 --- a/drivers/irqchip/irq-sunway-pci-intx.c +++ b/drivers/irqchip/irq-sunway-pci-intx.c @@ -9,11 +9,22 @@ #include #include +#define PCI_INTXCONFIG_OFFSET 7 +#define PCI_INTTYPE_OFFSET 10 + +#if defined(CONFIG_SUBARCH_C3B) + #define PCI_INTDST_DOMAIN_ID_SHIFT 6 +#elif defined(CONFIG_SUBARCH_C4) + #define PCI_INTDST_DOMAIN_ID_SHIFT 7 +#endif + +#define PCI_INTDST_THREAD_ID_SHIFT 6 + static DEFINE_RAW_SPINLOCK(legacy_lock); struct intx_chip_data { struct pci_controller *hose; - unsigned long intxconfig[4]; + unsigned long intxconfig[PCI_NUM_INTX]; unsigned int offset; }; @@ -67,16 +78,18 @@ static int __assign_piu_intx_config(struct intx_chip_data *chip_data, hose = chip_data->hose; piu_ior0_base = hose->piu_ior0_base; - for (i = 0; i < 4; i++) { + for (i = 0; i < PCI_NUM_INTX; i++) { intxconfig = chip_data->intxconfig[i]; intxconfig &= ~PCI_INTX_INTDST_MASK; if (IS_ENABLED(CONFIG_SUBARCH_C3B)) - intxconfig |= core | (node << 6); + intxconfig |= core | (node << PCI_INTDST_DOMAIN_ID_SHIFT); else - intxconfig |= core | (thread << 6) | (node << 7); + intxconfig |= core | (thread << PCI_INTDST_THREAD_ID_SHIFT) + | (node << PCI_INTDST_DOMAIN_ID_SHIFT); - writeq(intxconfig, piu_ior0_base + INTACONFIG + (i << 7)); + writeq(intxconfig, piu_ior0_base + INTACONFIG + + (i << PCI_INTXCONFIG_OFFSET)); chip_data->intxconfig[i] = intxconfig; } return 0; @@ -108,13 +121,14 @@ static void set_intx_enable(struct irq_data *irq_data, u32 flag) hose = chip_data->hose; piu_ior0_base = hose->piu_ior0_base; - for (i = 0; i < 4; i++) { + for (i = 0; i < PCI_NUM_INTX; i++) { intxconfig = chip_data->intxconfig[i]; if (flag) intxconfig |= PCI_INTX_ENABLE; else intxconfig &= PCI_INTX_DISABLE; - writeq(intxconfig, piu_ior0_base + INTACONFIG + (i << 7)); + writeq(intxconfig, piu_ior0_base + INTACONFIG + + (i << PCI_INTXCONFIG_OFFSET)); } } @@ -174,7 +188,8 @@ static void intx_mask_irq(struct irq_data *irq_data, u32 flag) else intxconfig |= PCI_INTX_ENABLE; - writeq(intxconfig, piu_ior0_base + INTACONFIG + (offset << 7)); + writeq(intxconfig, piu_ior0_base + INTACONFIG + + (offset << PCI_INTXCONFIG_OFFSET)); } static void intx_irq_mask(struct irq_data *irq_data) @@ -196,7 +211,7 @@ static void intx_irq_unmask(struct irq_data *irq_data) static void noop(struct irq_data *d) {} static struct irq_chip sw64_intx_chip = { - .name = "PCI_INTX", + .name = "PCI-INTX", .irq_enable = intx_irq_enable, .irq_disable = intx_irq_disable, .irq_mask = intx_irq_mask, @@ -234,11 +249,11 @@ void setup_intx_irqs(struct pci_controller *hose) chip_data->hose = hose; - for (i = 0; i < 4; i++) { + for (i = 0; i < PCI_NUM_INTX; i++) { if (IS_ENABLED(CONFIG_SUBARCH_C3B)) - chip_data->intxconfig[i] = (0x1UL << (3 - i)) << 10; + chip_data->intxconfig[i] = (0x1UL << (3 - i)) << PCI_INTTYPE_OFFSET; else - chip_data->intxconfig[i] = (0x1UL << i) << 10; + chip_data->intxconfig[i] = (0x1UL << i) << PCI_INTTYPE_OFFSET; } irq_set_chip_data(irq, chip_data); @@ -250,7 +265,7 @@ void setup_intx_irqs(struct pci_controller *hose) set_pcieport_service_irq(hose); } -void __init sw64_init_irq(void) +void __init sunway_init_pci_intx(void) { struct pci_controller *hose = hose_head; @@ -270,7 +285,9 @@ void handle_intx(unsigned int offset) for (hose = hose_head; hose; hose = hose->next) { piu_ior0_base = hose->piu_ior0_base; - value = readq(piu_ior0_base + INTACONFIG + (offset << 7)); + value = readq(piu_ior0_base + INTACONFIG + + (offset << PCI_INTXCONFIG_OFFSET)); + if ((value & (PCI_INTX_VALID)) && (value & PCI_INTX_ENABLE)) { irq_data = irq_get_irq_data(hose->int_irq); if (irq_data) { -- Gitee From 19f1acd571b0aeb799afef881037599b7302a2cf Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Fri, 11 Oct 2024 08:56:41 +0000 Subject: [PATCH 47/66] anolis: sw64: irqchip: remove fallback after kzalloc_node() ANBZ: #4688 Following similar changes of commit 4beaacc6fea5 ("net/mlx4_en: remove fallback after kzalloc_node()"). Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/irqchip/irq-sunway-pci-intx.c | 3 --- drivers/irqchip/irq-sunway-pintc.c | 3 --- 2 files changed, 6 deletions(-) diff --git a/drivers/irqchip/irq-sunway-pci-intx.c b/drivers/irqchip/irq-sunway-pci-intx.c index 89eb6ca86d26..bd108d58ff53 100644 --- a/drivers/irqchip/irq-sunway-pci-intx.c +++ b/drivers/irqchip/irq-sunway-pci-intx.c @@ -47,9 +47,6 @@ struct intx_chip_data *alloc_intx_chip_data(u32 node) chip_data = kzalloc_node(sizeof(struct intx_chip_data), GFP_KERNEL, node); - if (!chip_data) - chip_data = kzalloc(sizeof(struct intx_chip_data), - GFP_KERNEL); return chip_data; } diff --git a/drivers/irqchip/irq-sunway-pintc.c b/drivers/irqchip/irq-sunway-pintc.c index eb7128b79c6f..6e883a060d85 100644 --- a/drivers/irqchip/irq-sunway-pintc.c +++ b/drivers/irqchip/irq-sunway-pintc.c @@ -97,9 +97,6 @@ static struct pintc_chip_data *pintc_alloc_chip_data(u32 node) chip_data = kzalloc_node(sizeof(struct pintc_chip_data), GFP_KERNEL, node); - if (!chip_data) - chip_data = kzalloc(sizeof(struct pintc_chip_data), - GFP_KERNEL); chip_datas[node] = chip_data; -- Gitee From f9f74e73116909ffe4d7f1efe94e933c0e952cae Mon Sep 17 00:00:00 2001 From: Yu Jiayi Date: Wed, 16 Oct 2024 17:18:54 +0800 Subject: [PATCH 48/66] anolis: sw64: kvm: optimize the calling and implementation of functions in mmu.c ANBZ: #4688 This patch: - The kvm_set_pfn_accessed() calls kvm_set_page_accessed(), and the kvm_release_pfn_clean() eventually calls kvm_set_page_accessed() too. So, remove the redundant call to kvm_set_pfn_accessed(). - Move the functionality of kvm_mmu_write_protect_pt_masked() into its caller, kvm_arch_mmu_enable_log_dirty_pt_masked(). This will be used to share some of the code. Signed-off-by: Yu Jiayi Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 91745f61c9b0..2ff865646522 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -1358,7 +1358,6 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, out_unlock: spin_unlock(&kvm->mmu_lock); - kvm_set_pfn_accessed(pfn); kvm_release_pfn_clean(pfn); return ret; } @@ -1513,18 +1512,19 @@ bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range) return false; } -/** - * kvm_mmu_write_protect_pt_masked() - write protect dirty pages + +/* + * kvm_arch_mmu_enable_log_dirty_pt_masked - enable dirty logging for selected pages. * @kvm: The KVM pointer * @slot: The memory slot associated with mask * @gfn_offset: The gfn offset in memory slot - * @mask: The mask of dirty pages at offset 'gfn_offset' in this memory - * slot to be write protected + * @mask: The mask of pages at offset 'gfn_offset' in this memory + * slot to enable dirty logging on * - * Walks bits set in mask write protects the associated pte's. Caller must + * Write protect selected pages to enable dirty logging for them. Caller must * acquire kvm_mmu_lock. */ -static void kvm_mmu_write_protect_pt_masked(struct kvm *kvm, +void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm, struct kvm_memory_slot *slot, gfn_t gfn_offset, unsigned long mask) { @@ -1534,17 +1534,3 @@ static void kvm_mmu_write_protect_pt_masked(struct kvm *kvm, apt_wp_range(kvm, start, end); } - -/* - * kvm_arch_mmu_enable_log_dirty_pt_masked - enable dirty logging for selected - * dirty pages. - * - * It calls kvm_mmu_write_protect_pt_masked to write protect selected pages to - * enable dirty logging for them. - */ -void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm, - struct kvm_memory_slot *slot, - gfn_t gfn_offset, unsigned long mask) -{ - kvm_mmu_write_protect_pt_masked(kvm, slot, gfn_offset, mask); -} -- Gitee From c2263259fca186d58cf64c4f4d2bdc8334c92bda Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Wed, 30 Oct 2024 16:11:28 +0800 Subject: [PATCH 49/66] anolis: sw64: kvm: remove unused kvm_arch_flush_remote_tlbs_memslot() ANBZ: #4688 The kvm_arch_flush_remote_tlbs_memslot() has been moved to common code, so delete it. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/sw64.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/sw_64/kvm/sw64.c b/arch/sw_64/kvm/sw64.c index a2d2b1739dca..1213121728c4 100644 --- a/arch/sw_64/kvm/sw64.c +++ b/arch/sw_64/kvm/sw64.c @@ -607,13 +607,6 @@ vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf) return VM_FAULT_SIGBUS; } -void kvm_arch_flush_remote_tlbs_memslot(struct kvm *kvm, - struct kvm_memory_slot *memslot) -{ - /* Let implementation handle TLB/GVA invalidation */ - kvm_arch_flush_shadow_memslot(kvm, memslot); -} - int kvm_dev_ioctl_check_extension(long ext) { int r; -- Gitee From cf4929be8b3317a8cab57deafd57faaf85aaac4b Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 19 Sep 2024 10:23:13 +0800 Subject: [PATCH 50/66] anolis: sw64: refactor reset routines with new API ANBZ: #4688 Refactor reset routines by using new do_kernel_power_off() instead of old pm_power_off(), simplifying the source file (reset.c). In addition, the routines of virtual and physical machine are separated, and the legacy routines (legacy_xuelang.c and legacy_junzhang.c) are removed. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/efi.h | 10 +- arch/sw_64/include/asm/platform.h | 16 +--- arch/sw_64/kernel/Makefile | 1 + arch/sw_64/kernel/efi.c | 19 ++++ arch/sw_64/kernel/reset.c | 118 ++++++++++++++---------- drivers/firmware/efi/sunway-init.c | 6 +- drivers/platform/sw64/Makefile | 2 - drivers/platform/sw64/legacy_junzhang.c | 61 ------------ drivers/platform/sw64/legacy_xuelang.c | 62 ------------- 9 files changed, 101 insertions(+), 194 deletions(-) create mode 100644 arch/sw_64/kernel/efi.c delete mode 100644 drivers/platform/sw64/legacy_junzhang.c delete mode 100644 drivers/platform/sw64/legacy_xuelang.c diff --git a/arch/sw_64/include/asm/efi.h b/arch/sw_64/include/asm/efi.h index 34d5637e23c2..ef2eda461f94 100644 --- a/arch/sw_64/include/asm/efi.h +++ b/arch/sw_64/include/asm/efi.h @@ -4,16 +4,22 @@ #include #include + #ifdef CONFIG_EFI + extern void efi_init(void); extern unsigned long entSuspend; -#define SLEEP_ENTRY_GUID EFI_GUID(0x59cb76bb, 0x9c3a, 0x4c8f, 0xbd, 0x5c, 0xc0, 0x0f, 0x20, 0x61, 0x18, 0x4b) +#define SLEEP_ENTRY_GUID EFI_GUID(0x59cb76bb, 0x9c3a, 0x4c8f, 0xbd, 0x5c, 0xc0, 0x0f, 0x20, 0x61, 0x18, 0x4b) +#define BIOS_VERSION_GUID EFI_GUID(0xc47a23c3, 0xcebb, 0x4cc9, 0xa5, 0xe2, 0xde, 0xd0, 0x8f, 0xe4, 0x20, 0xb5) + +extern unsigned long sunway_bios_version; #else #define efi_init() #define efi_idmap_init() -#endif +#define sunway_bios_version (0) +#endif /* CONFIG_EFI */ #define arch_efi_call_virt_setup() #define arch_efi_call_virt_teardown() diff --git a/arch/sw_64/include/asm/platform.h b/arch/sw_64/include/asm/platform.h index 3fbe9362c568..96656f112c40 100644 --- a/arch/sw_64/include/asm/platform.h +++ b/arch/sw_64/include/asm/platform.h @@ -9,26 +9,12 @@ #include #endif -#ifdef CONFIG_EFI -#define BIOS_VERSION_GUID EFI_GUID(0xc47a23c3, 0xcebb, 0x4cc9, 0xa5, 0xe2, 0xde, 0xd0, 0x8f, 0xe4, 0x20, 0xb5) - -#define BIOS_SUPPORT_RESET_CLALLBACK(bios_version) ((bios_version) != NULL) - -extern unsigned long bios_version; - -#endif - extern struct boot_params *sunway_boot_params; extern unsigned long sunway_boot_magic; extern unsigned long sunway_dtb_address; -extern void sw64_halt(void); -extern void sw64_poweroff(void); -extern void sw64_restart(void); -extern void (*pm_restart)(void); -extern void (*pm_halt)(void); -extern int i2c_set_adapter(void); extern void cpld_write(uint8_t slave_addr, uint8_t reg, uint8_t data); + extern void early_parse_fdt_property(const void *fdt, const char *path, const char *prop_name, u64 *property, int size); diff --git a/arch/sw_64/kernel/Makefile b/arch/sw_64/kernel/Makefile index 6b5172f50056..0b0012462517 100644 --- a/arch/sw_64/kernel/Makefile +++ b/arch/sw_64/kernel/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_RELOCATABLE) += relocate.o obj-$(CONFIG_DEBUG_FS) += segvdbg.o unaligned.o obj-$(CONFIG_JUMP_LABEL) += jump_label.o obj-$(CONFIG_DEBUG_MATCH) += match.o +obj-$(CONFIG_EFI) += efi.o ifdef CONFIG_PERF_EVENTS obj-$(CONFIG_SUBARCH_C3B) += perf_event.o diff --git a/arch/sw_64/kernel/efi.c b/arch/sw_64/kernel/efi.c new file mode 100644 index 000000000000..8bf80b271581 --- /dev/null +++ b/arch/sw_64/kernel/efi.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include + +#include + +bool efi_poweroff_required(void) +{ + /* VM has its own poweroff interface */ + if (!is_in_host()) + return false; + + /* Prefer ACPI S5 */ + if (acpi_sleep_state_supported(ACPI_STATE_S5)) + return false; + + return efi_enabled(EFI_RUNTIME_SERVICES); +} diff --git a/arch/sw_64/kernel/reset.c b/arch/sw_64/kernel/reset.c index 7bbd6ce8e07a..a7f332fa31ee 100644 --- a/arch/sw_64/kernel/reset.c +++ b/arch/sw_64/kernel/reset.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2020-2022 Sunway Technology Corporation Limited + * Copyright (C) 2020-2024 Sunway Technology Corporation Limited */ + #include #include #include @@ -14,10 +15,16 @@ #include #include +#include + +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); -static void default_halt(void) +void machine_halt(void) { + preempt_disable(); local_irq_disable(); + smp_send_stop(); pr_notice("\n\n** You can safely turn off the power now **\n\n"); @@ -25,74 +32,87 @@ static void default_halt(void) arch_cpu_idle(); } -static void default_poweroff(void) +void machine_power_off(void) { - /* No point in taking interrupts anymore. */ + preempt_disable(); local_irq_disable(); -#ifdef CONFIG_EFI - efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL); -#endif - while (true) - arch_cpu_idle(); -} + smp_send_stop(); -static void default_restart(void) -{ -#ifdef CONFIG_EFI - if (efi_capsule_pending(NULL)) - efi_reboot(REBOOT_WARM, NULL); - else - efi_reboot(REBOOT_COLD, NULL); -#endif + do_kernel_power_off(); + + /* VM cannot reach here */ + WARN_ON(!is_in_host()); + + /** + * Compatibility with old firmware, can be removed + * when no longer support SW3231. + */ + if (!sunway_bios_version) + cpld_write(0x64, 0x00, 0xf0); while (true) arch_cpu_idle(); } -void (*pm_restart)(void); - -void (*pm_power_off)(void); -EXPORT_SYMBOL(pm_power_off); - -void (*pm_halt)(void); - -void machine_halt(void) +void machine_restart(char *command) { -#ifdef CONFIG_SMP preempt_disable(); + local_irq_disable(); smp_send_stop(); -#endif - pm_halt(); + + do_kernel_restart(command); + + /* VM cannot reach here */ + WARN_ON(!is_in_host()); + + /** + * Compatibility with old firmware, can be removed + * when no longer support SW3231. + */ + if (!sunway_bios_version) + cpld_write(0x64, 0x00, 0xc3); + else if (efi_enabled(EFI_RUNTIME_SERVICES)) + efi_reboot(reboot_mode, NULL); + + while (true) + arch_cpu_idle(); } -void machine_power_off(void) +static int vm_restart(struct sys_off_data *data) { -#ifdef CONFIG_SMP - preempt_disable(); - smp_send_stop(); -#endif - pm_power_off(); + hcall(HCALL_SET_CLOCKEVENT, 0, 0, 0); + hcall(HCALL_RESTART, 0, 0, 0); + mb(); + + return NOTIFY_DONE; } -void machine_restart(char *command) +static int vm_power_off(struct sys_off_data *data) { -#ifdef CONFIG_SMP - preempt_disable(); - smp_send_stop(); -#endif - /* No point in taking interrupts anymore. */ - local_irq_disable(); + hcall(HCALL_SET_CLOCKEVENT, 0, 0, 0); + hcall(HCALL_SHUTDOWN, 0, 0, 0); + mb(); - do_kernel_restart(command); - pm_restart(); + return NOTIFY_DONE; } -static int __init sw64_reboot_setup(void) +static int __init vm_power_init(void) { - pm_restart = default_restart; - pm_power_off = default_poweroff; - pm_halt = default_halt; + struct sys_off_handler *handler; + + if (is_in_host()) + return 0; + + handler = register_sys_off_handler(SYS_OFF_MODE_RESTART, + SYS_OFF_PRIO_DEFAULT, vm_restart, NULL); + if (WARN_ON(IS_ERR(handler))) + return PTR_ERR(handler); + + handler = register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, + SYS_OFF_PRIO_DEFAULT, vm_power_off, NULL); + if (WARN_ON(IS_ERR(handler))) + return PTR_ERR(handler); return 0; } -arch_initcall(sw64_reboot_setup); +arch_initcall(vm_power_init); diff --git a/drivers/firmware/efi/sunway-init.c b/drivers/firmware/efi/sunway-init.c index 8557c181c28c..ec678b403270 100644 --- a/drivers/firmware/efi/sunway-init.c +++ b/drivers/firmware/efi/sunway-init.c @@ -27,7 +27,7 @@ #include unsigned long entSuspend; -unsigned long bios_version; +unsigned long sunway_bios_version; static int __init is_memory(efi_memory_desc_t *md) { @@ -38,7 +38,7 @@ static int __init is_memory(efi_memory_desc_t *md) static efi_config_table_type_t arch_tables[] __initdata = { {SMBIOS3_TABLE_GUID, NULL, ""}, {SLEEP_ENTRY_GUID, &entSuspend, "SLEEP ENTRY"}, - {BIOS_VERSION_GUID, &bios_version, "BIOS VERSION"}, + {BIOS_VERSION_GUID, &sunway_bios_version, "BIOS VERSION"}, {}, }; @@ -107,7 +107,7 @@ static int __init uefi_init(u64 efi_system_table) out: early_memunmap(systab, sizeof(efi_system_table_t)); - if (!bios_version) + if (!sunway_bios_version) retval = -EINVAL; return retval; diff --git a/drivers/platform/sw64/Makefile b/drivers/platform/sw64/Makefile index 84ba9957a9ce..65dead29600e 100644 --- a/drivers/platform/sw64/Makefile +++ b/drivers/platform/sw64/Makefile @@ -1,4 +1,2 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_PLATFORM_XUELANG) += legacy_xuelang.o -obj-$(CONFIG_PLATFORM_JUNZHANG) += legacy_junzhang.o obj-y += misc-platform.o diff --git a/drivers/platform/sw64/legacy_junzhang.c b/drivers/platform/sw64/legacy_junzhang.c deleted file mode 100644 index 56fc57d46923..000000000000 --- a/drivers/platform/sw64/legacy_junzhang.c +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include - -static void vt_mode_kill_arch(int mode) -{ - hcall(HCALL_SET_CLOCKEVENT, 0, 0, 0); - - switch (mode) { - case LINUX_REBOOT_CMD_RESTART: - hcall(HCALL_RESTART, 0, 0, 0); - mb(); - break; - case LINUX_REBOOT_CMD_HALT: - case LINUX_REBOOT_CMD_POWER_OFF: - hcall(HCALL_SHUTDOWN, 0, 0, 0); - mb(); - break; - default: - break; - } -} - -void sw64_halt(void) -{ - if (is_in_host()) - cpld_write(0x64, 0x00, 0xf0); - else - vt_mode_kill_arch(LINUX_REBOOT_CMD_HALT); -} - -void sw64_poweroff(void) -{ - if (is_in_host()) - cpld_write(0x64, 0x00, 0xf0); - else - vt_mode_kill_arch(LINUX_REBOOT_CMD_POWER_OFF); -} - -void sw64_restart(void) -{ - if (is_in_host()) - cpld_write(0x64, 0x00, 0xc3); - else - vt_mode_kill_arch(LINUX_REBOOT_CMD_RESTART); -} - -static int sw64_reset_init(void) -{ -#ifdef CONFIG_EFI - if (BIOS_SUPPORT_RESET_CLALLBACK((void *)bios_version)) - return 0; -#endif - pm_restart = sw64_restart; - pm_power_off = sw64_poweroff; - pm_halt = sw64_halt; - return 0; -} -subsys_initcall(sw64_reset_init); diff --git a/drivers/platform/sw64/legacy_xuelang.c b/drivers/platform/sw64/legacy_xuelang.c deleted file mode 100644 index 67b4436b5a55..000000000000 --- a/drivers/platform/sw64/legacy_xuelang.c +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include - -#include -#include - -static void vt_mode_kill_arch(int mode) -{ - hcall(HCALL_SET_CLOCKEVENT, 0, 0, 0); - - switch (mode) { - case LINUX_REBOOT_CMD_RESTART: - hcall(HCALL_RESTART, 0, 0, 0); - mb(); - break; - case LINUX_REBOOT_CMD_HALT: - case LINUX_REBOOT_CMD_POWER_OFF: - hcall(HCALL_SHUTDOWN, 0, 0, 0); - mb(); - break; - default: - break; - } -} - -void sw64_halt(void) -{ - if (is_in_host()) - cpld_write(0x64, 0x00, 0xf0); - else - vt_mode_kill_arch(LINUX_REBOOT_CMD_HALT); -} - -void sw64_poweroff(void) -{ - if (is_in_host()) - cpld_write(0x64, 0x00, 0xf0); - else - vt_mode_kill_arch(LINUX_REBOOT_CMD_POWER_OFF); -} - -void sw64_restart(void) -{ - if (is_in_host()) - cpld_write(0x64, 0x00, 0xc3); - else - vt_mode_kill_arch(LINUX_REBOOT_CMD_RESTART); -} - -static int sw64_reset_init(void) -{ -#ifdef CONFIG_EFI - if (BIOS_SUPPORT_RESET_CLALLBACK((void *)bios_version)) - return 0; -#endif - pm_restart = sw64_restart; - pm_power_off = sw64_poweroff; - pm_halt = sw64_halt; - return 0; -} -subsys_initcall(sw64_reset_init); -- Gitee From d87752f67d93dcd190acc0ceb9ec804c438c1faa Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Mon, 5 Aug 2024 10:53:19 +0800 Subject: [PATCH 51/66] anolis: sw64: kvm: use vma_lookup() instead of find_vma_intersection() ANBZ: #4688 vma_lookup() finds the vma of a specific address with a cleaner interface and is more readable. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 2ff865646522..e3af6a76cd5c 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -1197,7 +1197,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, /* Let's check if we will get back a huge page backed by hugetlbfs */ down_read(¤t->mm->mmap_lock); - vma = find_vma_intersection(current->mm, hva, hva + 1); + vma = vma_lookup(current->mm, hva); if (unlikely(!vma)) { kvm_err("Failed to find VMA for hva 0x%lx\n", hva); up_read(¤t->mm->mmap_lock); -- Gitee From acb543e23562fc7375376af2a8d01f943285d324 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 26 Sep 2024 13:44:34 +0800 Subject: [PATCH 52/66] anolis: sw64: acpi: support reset and S5 ANBZ: #4688 Now acpi_power_off() and acpi_reboot() can work if the firmware provides necessary information. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 1 + arch/sw_64/include/asm/acpi.h | 12 ++++++++++++ arch/sw_64/kernel/reset.c | 2 ++ 3 files changed, 15 insertions(+) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index b0ca94497d24..2413bab9c5de 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -7,6 +7,7 @@ config SW64 select ACPI_MCFG if (ACPI && PCI) select ACPI_PPTT if ACPI select ACPI_REDUCED_HARDWARE_ONLY + select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI select ARCH_ATOMIC select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI select ARCH_HAS_ELF_RANDOMIZE diff --git a/arch/sw_64/include/asm/acpi.h b/arch/sw_64/include/asm/acpi.h index 7c3310168798..e386d07d1e73 100644 --- a/arch/sw_64/include/asm/acpi.h +++ b/arch/sw_64/include/asm/acpi.h @@ -112,6 +112,18 @@ static inline u32 get_acpi_id_for_cpu(unsigned int cpu) /* We take rcid as processor _UID */ return cpu_physical_id(cpu); } + +static inline unsigned long acpi_get_wakeup_address(void) +{ + return 0; +} + +static inline bool acpi_skip_set_wakeup_address(void) +{ + return true; +} + +#define acpi_skip_set_wakeup_address acpi_skip_set_wakeup_address #else /* !CONFIG_ACPI */ static inline void acpi_noirq_set(void) { } diff --git a/arch/sw_64/kernel/reset.c b/arch/sw_64/kernel/reset.c index a7f332fa31ee..8181923e676e 100644 --- a/arch/sw_64/kernel/reset.c +++ b/arch/sw_64/kernel/reset.c @@ -65,6 +65,8 @@ void machine_restart(char *command) /* VM cannot reach here */ WARN_ON(!is_in_host()); + acpi_reboot(); + /** * Compatibility with old firmware, can be removed * when no longer support SW3231. -- Gitee From 0aeb1cd06d1fcd73218944c421e851ad4ae42f62 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Mon, 11 Nov 2024 02:57:49 -0500 Subject: [PATCH 53/66] anolis: sw64: kvm: remove unused argument 'addr' of apt_dissolve_pud/pmd() ANBZ: #4688 Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 54 ++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index e3af6a76cd5c..24f6bc3545b4 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -70,21 +70,35 @@ enum { * * Function clears a PMD entry, flushes TLBs. */ -static void apt_dissolve_pmd(struct kvm *kvm, phys_addr_t addr, pmd_t *pmd) +static void apt_dissolve_pmd(struct kvm *kvm, pmd_t *pmd) { - int i; - if (!pmd_trans_huge(*pmd)) return; - if (pmd_cont(*pmd)) { - for (i = 0; i < CONT_PMDS; i++, pmd++) - pmd_clear(pmd); - } else + pmd_clear(pmd); + kvm_flush_remote_tlbs(kvm); + put_page(virt_to_page(pmd)); +} + +/** + * apt_dissolve_cont_pmd() - clear and flush huge cont PMD entry + * @kvm: pointer to kvm structure. + * @addr: IPA + * @pmd: pmd pointer for IPA + * + * Function clears a cont PMD entry, flushes TLBs. + */ +static void apt_dissolve_cont_pmd(struct kvm *kvm, pmd_t *pmd) +{ + int i; + pmd_t *start_pmd; + + start_pmd = pmd; + for (i = 0; i < CONT_PMDS; i++, pmd++) pmd_clear(pmd); kvm_flush_remote_tlbs(kvm); - put_page(virt_to_page(pmd)); + put_page(virt_to_page(start_pmd)); } /** @@ -95,7 +109,7 @@ static void apt_dissolve_pmd(struct kvm *kvm, phys_addr_t addr, pmd_t *pmd) * * Function clears a PUD entry, flushes TLBs. */ -static void apt_dissolve_pud(struct kvm *kvm, phys_addr_t addr, pud_t *pudp) +static void apt_dissolve_pud(struct kvm *kvm, pud_t *pudp) { if (!pud_huge(*pudp)) return; @@ -804,7 +818,7 @@ static int apt_set_pte_fast(struct kvm_vcpu *vcpu, * on to allocate page. */ if (logging_active) - apt_dissolve_pud(kvm, addr, pud); + apt_dissolve_pud(kvm, pud); find_pud: if (pud_none(*pud)) { @@ -828,8 +842,13 @@ static int apt_set_pte_fast(struct kvm_vcpu *vcpu, * While dirty page logging - dissolve huge PMD, then continue on to * allocate page. */ - if (logging_active) - apt_dissolve_pmd(kvm, addr, pmd); + if (logging_active) { + if (pmd_cont(*pmd)) + apt_dissolve_cont_pmd(kvm, + pmd_offset(pud, addr & CONT_PMD_MASK)); + else + apt_dissolve_pmd(kvm, pmd); + } find_pmd: /* Create stage-2 page mappings - Level 2 */ @@ -893,7 +912,7 @@ static int apt_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, * on to allocate page. */ if (logging_active) - apt_dissolve_pud(kvm, addr, pud); + apt_dissolve_pud(kvm, pud); if (pud_none(*pud)) { if (!cache) @@ -916,8 +935,13 @@ static int apt_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, * While dirty page logging - dissolve huge PMD, then continue on to * allocate page. */ - if (logging_active) - apt_dissolve_pmd(kvm, addr, pmd); + if (logging_active) { + if (pmd_cont(*pmd)) + apt_dissolve_cont_pmd(kvm, + pmd_offset(pud, addr & CONT_PMD_MASK)); + else + apt_dissolve_pmd(kvm, pmd); + } /* Create stage-2 page mappings - Level 2 */ if (pmd_none(*pmd)) { -- Gitee From 4073f5080a0cd6b30715d803b9d32b8d0dcee7d2 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 30 Oct 2024 19:41:46 +0800 Subject: [PATCH 54/66] anolis: sw64: irqchip: fix irq_enable/disable callback for MCU controller ANBZ: #4688 Enable or disable the corresponding IRQ instead of all IRQs in irq_enable/disable callback of MCU controller. In addition, spin locks are added to protect access to registers. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/irqchip/irq-sunway-pintc.c | 150 +++++++++++++++++------------ 1 file changed, 89 insertions(+), 61 deletions(-) diff --git a/drivers/irqchip/irq-sunway-pintc.c b/drivers/irqchip/irq-sunway-pintc.c index 6e883a060d85..934ad3d60607 100644 --- a/drivers/irqchip/irq-sunway-pintc.c +++ b/drivers/irqchip/irq-sunway-pintc.c @@ -84,6 +84,8 @@ struct pintc_chip_data { void __iomem *mcu_base; /* MCU/SPBU base address */ struct irq_chip *mcu_chip; u32 mcu_irq_num; + raw_spinlock_t pintc_lock; + raw_spinlock_t mcu_lock; }; static struct pintc_chip_data *chip_datas[MAX_NUMNODES]; @@ -116,59 +118,82 @@ static void pintc_free_chip_data(struct pintc_chip_data *chip_data) kfree(chip_data); } -static DEFINE_RAW_SPINLOCK(pintc_lock); -static void lock_dev_lock(void) -{ - raw_spin_lock(&pintc_lock); -} - -static void unlock_dev_lock(void) -{ - raw_spin_unlock(&pintc_lock); -} - -static void mcu_irq_mask(struct irq_data *data) +static void mcu_irq_disable(struct irq_data *data) { struct pintc_chip_data *chip_data = data->chip_data; - unsigned long mask; + unsigned long mask, flags; int hwirq = data->hwirq; + raw_spin_lock_irqsave(&chip_data->mcu_lock, flags); + mask = readq(chip_data->mcu_base + OFFSET_MCU_DVC_INT_EN); mask &= ~(0x1UL << hwirq); writeq(mask, chip_data->mcu_base + OFFSET_MCU_DVC_INT_EN); + + raw_spin_unlock_irqrestore(&chip_data->mcu_lock, flags); } -static void mcu_irq_unmask(struct irq_data *data) +static void mcu_irq_enable(struct irq_data *data) { struct pintc_chip_data *chip_data = data->chip_data; - unsigned long mask; + unsigned long mask, flags; int hwirq = data->hwirq; + raw_spin_lock_irqsave(&chip_data->mcu_lock, flags); + mask = readq(chip_data->mcu_base + OFFSET_MCU_DVC_INT_EN); mask |= (0x1UL << hwirq); writeq(mask, chip_data->mcu_base + OFFSET_MCU_DVC_INT_EN); + + raw_spin_unlock_irqrestore(&chip_data->mcu_lock, flags); } -static void mcu_irq_enable(struct irq_data *irq_data) +static void pintc_mcu_enable(void __iomem *pintc_base) { - struct pintc_chip_data *chip_data = irq_data->chip_data; unsigned long devint_conf; - devint_conf = readq(chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); + devint_conf = readq(pintc_base + OFFSET_DEV_INT_CONFIG); devint_conf |= (1UL << 8); - writeq(devint_conf, chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); - mcu_irq_unmask(irq_data); + writeq(devint_conf, pintc_base + OFFSET_DEV_INT_CONFIG); } -static void mcu_irq_disable(struct irq_data *irq_data) +static void pintc_mcu_disable(void __iomem *pintc_base) { - struct pintc_chip_data *chip_data = irq_data->chip_data; unsigned long devint_conf; - devint_conf = readq(chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); + devint_conf = readq(pintc_base + OFFSET_DEV_INT_CONFIG); devint_conf &= ~(1UL << 8); - writeq(devint_conf, chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); - mcu_irq_mask(irq_data); + writeq(devint_conf, pintc_base + OFFSET_DEV_INT_CONFIG); +} + +static unsigned long +pintc_mcu_disable_and_save(struct pintc_chip_data *chip_data) +{ + unsigned long val; + + raw_spin_lock(&chip_data->pintc_lock); + + val = readq(chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); + pintc_mcu_disable(chip_data->pintc_base); + + raw_spin_unlock(&chip_data->pintc_lock); + + return val & (1UL << 8); +} + +static void +pintc_mcu_restore(struct pintc_chip_data *chip_data, unsigned long val) +{ + unsigned long current_val; + + raw_spin_lock(&chip_data->pintc_lock); + + current_val = readq(chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); + current_val &= ~(1UL << 8); + current_val |= val; + writeq(current_val, chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); + + raw_spin_unlock(&chip_data->pintc_lock); } static unsigned long make_pintc_int_target(u32 version, int rcid) @@ -195,10 +220,30 @@ static unsigned long make_pintc_int_target(u32 version, int rcid) return target; } -static int __assign_mcu_irq_config(const struct pintc_chip_data *chip_data, +static void update_pintc_mcu_target(struct pintc_chip_data *chip_data, + unsigned long target) +{ + unsigned long val, flags; + + raw_spin_lock_irqsave(&chip_data->pintc_lock, flags); + + val = readq(chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); + + /* Disable MCU irqs until affinity setting is completed */ + pintc_mcu_disable(chip_data->pintc_base); + + val &= 0xffff; + val |= (target << 16); + + writeq(val, chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); + + raw_spin_unlock_irqrestore(&chip_data->pintc_lock, flags); +} + +static int assign_mcu_irq_config(struct pintc_chip_data *chip_data, cpumask_t *targets) { - unsigned long dev_int_tar, val; + unsigned long dev_int_tar; unsigned int cpu; int rcid; @@ -219,52 +264,32 @@ static int __assign_mcu_irq_config(const struct pintc_chip_data *chip_data, rcid = cpu_to_rcid(cpu); - val = readq(chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); dev_int_tar = make_pintc_int_target(chip_data->version, rcid); - val &= 0xffff; - val |= dev_int_tar << 16; - writeq(val, chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); + update_pintc_mcu_target(chip_data, dev_int_tar); return 0; } -static int assign_mcu_irq_config(const struct pintc_chip_data *chip_data, - cpumask_t *targets) -{ - int ret; - - lock_dev_lock(); - ret = __assign_mcu_irq_config(chip_data, targets); - unlock_dev_lock(); - - return ret; -} - static int mcu_irq_set_affinity(struct irq_data *irq_data, const struct cpumask *dest, bool force) { struct pintc_chip_data *chip_data = irq_data->chip_data; cpumask_t targets; - int ret = 0; if (cpumask_any_and(dest, cpu_online_mask) >= nr_cpu_ids) return -EINVAL; cpumask_and(&targets, dest, cpu_online_mask); - mcu_irq_disable(irq_data); - ret = assign_mcu_irq_config(chip_data, &targets); - mcu_irq_enable(irq_data); - - return ret; + return assign_mcu_irq_config(chip_data, &targets); } static struct irq_chip pintc_mcu_chip = { .name = "MCU-INT", .irq_enable = mcu_irq_enable, .irq_disable = mcu_irq_disable, - .irq_mask = mcu_irq_mask, - .irq_unmask = mcu_irq_unmask, + .irq_mask = mcu_irq_disable, + .irq_unmask = mcu_irq_enable, .irq_set_affinity = mcu_irq_set_affinity, }; @@ -378,6 +403,10 @@ static int __init pintc_init_mcu(struct pintc_chip_data *chip_data, &pintc_mcu_domain_ops, chip_data); /* Mask all interrupts for now */ writeq(0x0, chip_data->mcu_base + OFFSET_MCU_DVC_INT_EN); + + /* When building the root domain, move it to a better location */ + if (mcu_irq_domain) + pintc_mcu_enable(chip_data->pintc_base); } if (!mcu_irq_domain) { @@ -385,26 +414,25 @@ static int __init pintc_init_mcu(struct pintc_chip_data *chip_data, return -ENOMEM; } + raw_spin_lock_init(&chip_data->pintc_lock); + raw_spin_lock_init(&chip_data->mcu_lock); + pr_info(PREFIX "MCU version [%u] on node [%u] initialized\n", chip_data->version, chip_data->node); return 0; } +/* Currently, only MCU controller on node 0 is supported */ void handle_dev_int(struct pt_regs *regs) { - void __iomem *mcu_base, *intpu_base; - unsigned long config_val, val, stat; + unsigned long stat, val; unsigned int hwirq; - /* Currently, only MCU controller on node 0 is supported */ - mcu_base = chip_datas[0]->mcu_base; - intpu_base = chip_datas[0]->pintc_base; + /* Disable global irq of MCU due to some hardware reasons */ + val = pintc_mcu_disable_and_save(chip_datas[0]); - config_val = readq(intpu_base + OFFSET_DEV_INT_CONFIG); - val = config_val & (~(1UL << 8)); - writeq(val, intpu_base + OFFSET_DEV_INT_CONFIG); - stat = readq(mcu_base + OFFSET_MCU_DVC_INT); + stat = readq(chip_datas[0]->mcu_base + OFFSET_MCU_DVC_INT); while (stat) { hwirq = ffs(stat) - 1; @@ -412,7 +440,7 @@ void handle_dev_int(struct pt_regs *regs) stat &= ~(1UL << hwirq); } - writeq(config_val, intpu_base + OFFSET_DEV_INT_CONFIG); + pintc_mcu_restore(chip_datas[0], val); } void handle_fault_int(void) -- Gitee From 7a8928cec72a87b9e2219a380b18d1ead1f452e7 Mon Sep 17 00:00:00 2001 From: Gu Yuchen Date: Mon, 18 Nov 2024 14:06:03 +0800 Subject: [PATCH 55/66] anolis: sw64: implementing VDSO with generic code ANBZ: #4688 The vdso has been changed to a generic code implementation, adapting to the GENERIC_GETTIMEOFDAY, HAVE_GENERIC_VDSO, and ARCH_CLOCKSOURCE_INIT options. Signed-off-by: Gu Yuchen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 3 + arch/sw_64/Makefile | 4 + arch/sw_64/include/asm/clocksource.h | 7 + arch/sw_64/include/asm/vdso/clocksource.h | 8 + arch/sw_64/include/asm/vdso/gettimeofday.h | 105 +++++++++++ arch/sw_64/include/asm/vdso/processor.h | 7 + arch/sw_64/include/asm/vdso/vsyscall.h | 27 +++ arch/sw_64/kernel/time.c | 6 + arch/sw_64/kernel/vdso.c | 23 --- arch/sw_64/kernel/vdso/Makefile | 8 +- arch/sw_64/kernel/vdso/vgettimeofday.c | 191 ++------------------- 11 files changed, 186 insertions(+), 203 deletions(-) create mode 100644 arch/sw_64/include/asm/clocksource.h create mode 100644 arch/sw_64/include/asm/vdso/clocksource.h create mode 100644 arch/sw_64/include/asm/vdso/gettimeofday.h create mode 100644 arch/sw_64/include/asm/vdso/processor.h create mode 100644 arch/sw_64/include/asm/vdso/vsyscall.h diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 2413bab9c5de..130a177a7536 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -9,6 +9,7 @@ config SW64 select ACPI_REDUCED_HARDWARE_ONLY select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI select ARCH_ATOMIC + select ARCH_CLOCKSOURCE_INIT select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI select ARCH_HAS_ELF_RANDOMIZE select ARCH_HAS_PHYS_TO_DMA @@ -63,6 +64,7 @@ config SW64 select DMA_OPS if PCI select GENERIC_ARCH_TOPOLOGY select GENERIC_CLOCKEVENTS + select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO select GENERIC_IRQ_LEGACY select GENERIC_IRQ_MIGRATION if SMP select GENERIC_IRQ_PROBE @@ -92,6 +94,7 @@ config SW64 select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACER + select HAVE_GENERIC_VDSO if MMU && 64BIT select HAVE_IDE select HAVE_KPROBES select HAVE_KPROBES_ON_FTRACE diff --git a/arch/sw_64/Makefile b/arch/sw_64/Makefile index cfea96316c94..ccf2f5d6e378 100644 --- a/arch/sw_64/Makefile +++ b/arch/sw_64/Makefile @@ -49,6 +49,10 @@ export LIBS_Y boot := arch/sw_64/boot +PHONY += vdso_install +vdso_install: + $(Q)$(MAKE) $(build)=arch/sw64/kernel/vdso $@ + #Default target when executing make with no arguments all: $(boot)/vmlinux.bin.gz diff --git a/arch/sw_64/include/asm/clocksource.h b/arch/sw_64/include/asm/clocksource.h new file mode 100644 index 000000000000..482185566b0c --- /dev/null +++ b/arch/sw_64/include/asm/clocksource.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_CLOCKSOURCE_H +#define _ASM_CLOCKSOURCE_H + +#include + +#endif diff --git a/arch/sw_64/include/asm/vdso/clocksource.h b/arch/sw_64/include/asm/vdso/clocksource.h new file mode 100644 index 000000000000..df6ea65c1dec --- /dev/null +++ b/arch/sw_64/include/asm/vdso/clocksource.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_VDSOCLOCKSOURCE_H +#define __ASM_VDSOCLOCKSOURCE_H + +#define VDSO_ARCH_CLOCKMODES \ + VDSO_CLOCKMODE_ARCHTIMER + +#endif diff --git a/arch/sw_64/include/asm/vdso/gettimeofday.h b/arch/sw_64/include/asm/vdso/gettimeofday.h new file mode 100644 index 000000000000..57eb602550c7 --- /dev/null +++ b/arch/sw_64/include/asm/vdso/gettimeofday.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_VDSO_GETTIMEOFDAY_H +#define __ASM_VDSO_GETTIMEOFDAY_H + +#ifndef __ASSEMBLY__ + +#include +#include +#include +#include +#include +#include +#define VDSO_HAS_CLOCK_GETRES 1 + +static __always_inline +int gettimeofday_fallback(struct __kernel_old_timeval *_tv, + struct timezone *_tz) +{ + long retval; + long error; + asm volatile( + " mov %2, $16\n" + " mov %3, $17\n" + " ldi $0, %4\n" + " sys_call %5\n" + " mov $0, %0\n" + " mov $19, %1" + : "=r"(retval), "=r"(error) + : "r"(_tv), "r"(_tz), "i"(__NR_gettimeofday), "i"(HMC_callsys) + : "$0", "$16", "$17", "$19"); + if (unlikely(error)) + return -retval; + else + return retval; +} + +static __always_inline +long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) +{ + long retval; + long error; + asm volatile( + " mov %2, $16\n" + " mov %3, $17\n" + " ldi $0, %4\n" + " sys_call %5\n" + " mov $0, %0\n" + " mov $19, %1" + : "=r"(retval), "=r"(error) + : "r"(_clkid), "r"(_ts), "i"(__NR_clock_gettime), "i"(HMC_callsys) + : "$0", "$16", "$17", "$19"); + if (unlikely(error)) + return -retval; + else + return retval; +} + +static __always_inline +int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) +{ + long retval; + long error; + asm volatile( + " mov %2, $16\n" + " mov %3, $17\n" + " ldi $0, %4\n" + " sys_call %5\n" + " mov $0, %0\n" + " mov $19, %1" + : "=r"(retval), "=r"(error) + : "r"(_clkid), "r"(_ts), "i"(__NR_clock_getres), "i"(HMC_callsys) + : "$0", "$16", "$17", "$19"); + if (unlikely(error)) + return -retval; + else + return retval; +} + +#if defined(CONFIG_SUBARCH_C3B) +static __always_inline u64 __arch_get_hw_counter(s32 clock_mode, + const struct vdso_data *vd) +{ + register unsigned long __r0 __asm__("$0"); + + __asm__ __volatile__( + "sys_call %1" : "=r"(__r0) : "i" (HMC_longtime)); + + return __r0; +} +#elif defined(CONFIG_SUBARCH_C4) +static __always_inline u64 __arch_get_hw_counter(s32 clock_mode, + const struct vdso_data *vd) +{ + return sw64_read_csr(CSR_SHTCLOCK); +} +#endif + +static __always_inline const struct vdso_data *__arch_get_vdso_data(void) +{ + return _vdso_data; +} + +#endif /* !__ASSEMBLY__ */ + +#endif /* __ASM_VDSO_GETTIMEOFDAY_H */ diff --git a/arch/sw_64/include/asm/vdso/processor.h b/arch/sw_64/include/asm/vdso/processor.h new file mode 100644 index 000000000000..8bd332e1db87 --- /dev/null +++ b/arch/sw_64/include/asm/vdso/processor.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __ASM_VDSO_PROCESSOR_H +#define __ASM_VDSO_PROCESSOR_H + +#include + +#endif /* __ASM_VDSO_PROCESSOR_H */ diff --git a/arch/sw_64/include/asm/vdso/vsyscall.h b/arch/sw_64/include/asm/vdso/vsyscall.h new file mode 100644 index 000000000000..edd710ccd851 --- /dev/null +++ b/arch/sw_64/include/asm/vdso/vsyscall.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_VDSO_VSYSCALL_H +#define __ASM_VDSO_VSYSCALL_H + +#ifndef __ASSEMBLY__ + +#include +#include + +extern struct vdso_data *vdso_data; + +/* + * Update the vDSO data page to keep in sync with kernel timekeeping. + */ +static __always_inline struct vdso_data *__sw64_get_k_vdso_data(void) +{ + return vdso_data; +} + +#define __arch_get_k_vdso_data __sw64_get_k_vdso_data + +/* The asm-generic header needs to be included after the definitions above */ +#include + +#endif /* !__ASSEMBLY__ */ + +#endif /* __ASM_VDSO_VSYSCALL_H */ diff --git a/arch/sw_64/kernel/time.c b/arch/sw_64/kernel/time.c index c6957d70a551..503f9e1beb43 100644 --- a/arch/sw_64/kernel/time.c +++ b/arch/sw_64/kernel/time.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "proto.h" @@ -42,3 +43,8 @@ time_init(void) /* Calibrate the delay loop directly */ lpj_fine = cycle_freq / HZ; } + +void clocksource_arch_init(struct clocksource *cs) +{ + cs->vdso_clock_mode = VDSO_CLOCKMODE_ARCHTIMER; +} diff --git a/arch/sw_64/kernel/vdso.c b/arch/sw_64/kernel/vdso.c index 0d0ca5d0a38b..7e8030d32e15 100644 --- a/arch/sw_64/kernel/vdso.c +++ b/arch/sw_64/kernel/vdso.c @@ -155,26 +155,3 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, up_write(&mm->mmap_lock); return PTR_ERR(ret); } - -void update_vsyscall(struct timekeeper *tk) -{ - vdso_data_write_begin(vdso_data); - - vdso_data->xtime_sec = tk->xtime_sec; - vdso_data->xtime_nsec = tk->tkr_mono.xtime_nsec; - vdso_data->wall_to_mono_sec = tk->wall_to_monotonic.tv_sec; - vdso_data->wall_to_mono_nsec = tk->wall_to_monotonic.tv_nsec; - vdso_data->cs_shift = tk->tkr_mono.shift; - - vdso_data->cs_mult = tk->tkr_mono.mult; - vdso_data->cs_cycle_last = tk->tkr_mono.cycle_last; - vdso_data->cs_mask = tk->tkr_mono.mask; - - vdso_data_write_end(vdso_data); -} - -void update_vsyscall_tz(void) -{ - vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; - vdso_data->tz_dsttime = sys_tz.tz_dsttime; -} diff --git a/arch/sw_64/kernel/vdso/Makefile b/arch/sw_64/kernel/vdso/Makefile index e5640abbd727..8ae5bf3d1770 100644 --- a/arch/sw_64/kernel/vdso/Makefile +++ b/arch/sw_64/kernel/vdso/Makefile @@ -1,10 +1,16 @@ # SPDX-License-Identifier: GPL-2.0 # Symbols present in the vdso +ARCH_REL_TYPE_ABS := R_SW64_REFLONG|R_SW64_REFQUAD|R_SW64_JMP_SLOT +include $(srctree)/lib/vdso/Makefile vdso-syms = rt_sigreturn gettimeofday getcpu # Files to link into the vdso obj-vdso = $(patsubst %, v%.o, $(vdso-syms)) +ifneq ($(c-gettimeofday-y),) + CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y) +endif + # Build rules targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds vdso-syms.S obj-vdso := $(addprefix $(obj)/, $(obj-vdso)) @@ -35,7 +41,7 @@ $(obj)/vdso.o: $(obj)/vdso.so # link rule for the .so file, .lds has to be first SYSCFLAGS_vdso.so.dbg = $(c_flags) -$(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) FORCE +$(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) $(call if_changed,vdsold) SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \ $(call cc-ldoption, -Wl$(comma)--hash-style=both) diff --git a/arch/sw_64/kernel/vdso/vgettimeofday.c b/arch/sw_64/kernel/vdso/vgettimeofday.c index 69dcab66cb10..ae40d4e5b68e 100644 --- a/arch/sw_64/kernel/vdso/vgettimeofday.c +++ b/arch/sw_64/kernel/vdso/vgettimeofday.c @@ -13,192 +13,25 @@ */ #include +#include -#include -#include -#include -#include - -static __always_inline int syscall_fallback(clockid_t clkid, struct timespec64 *ts) -{ - long retval; - long error; - asm volatile( - " mov %2, $16\n" - " mov %3, $17\n" - " ldi $0, %4\n" - " sys_call %5\n" - " mov $0, %0\n" - " mov $19, %1" - : "=r"(retval), "=r"(error) - : "r"(clkid), "r"(ts), "i"(__NR_clock_gettime), "i"(HMC_callsys) - : "$0", "$16", "$17", "$19"); - if (unlikely(error)) - return -retval; - else - return retval; -} - -static __always_inline int do_realtime_coarse(struct timespec64 *ts, - const struct vdso_data *data) -{ - u32 start_seq; - - do { - start_seq = vdso_data_read_begin(data); - - ts->tv_sec = data->xtime_sec; - ts->tv_nsec = data->xtime_nsec >> data->cs_shift; - } while (vdso_data_read_retry(data, start_seq)); - - return 0; -} - - -static __always_inline int do_monotonic_coarse(struct timespec64 *ts, - const struct vdso_data *data) -{ - u32 start_seq; - u64 to_mono_sec; - u64 to_mono_nsec; - - do { - start_seq = vdso_data_read_begin(data); - - ts->tv_sec = data->xtime_sec; - ts->tv_nsec = data->xtime_nsec >> data->cs_shift; - - to_mono_sec = data->wall_to_mono_sec; - to_mono_nsec = data->wall_to_mono_nsec; - } while (vdso_data_read_retry(data, start_seq)); - - ts->tv_sec += to_mono_sec; - timespec64_add_ns(ts, to_mono_nsec); - - return 0; -} - -#if defined(CONFIG_SUBARCH_C3B) -static __always_inline u64 read_longtime(void) -{ - register unsigned long __r0 __asm__("$0"); - - __asm__ __volatile__( - "sys_call %1" : "=r"(__r0) : "i" (HMC_longtime)); - - return __r0; -} -#elif defined(CONFIG_SUBARCH_C4) -static __always_inline u64 read_longtime(void) -{ - return sw64_read_csr(CSR_SHTCLOCK); -} -#endif - -static __always_inline u64 get_ns(const struct vdso_data *data) +extern +int __vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts); +int __vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts) { - u64 cycle_now, delta, nsec; - - cycle_now = read_longtime(); - delta = (cycle_now - data->cs_cycle_last) & data->cs_mask; - - nsec = (delta * data->cs_mult) + data->xtime_nsec; - nsec >>= data->cs_shift; - - return nsec; -} - - -static __always_inline int do_realtime(struct timespec64 *ts, - const struct vdso_data *data) -{ - u32 start_seq; - u64 ns; - - do { - start_seq = vdso_data_read_begin(data); - - ts->tv_sec = data->xtime_sec; - ns = get_ns(data); - } while (vdso_data_read_retry(data, start_seq)); - - ts->tv_nsec = 0; - timespec64_add_ns(ts, ns); - - return 0; -} - -static __always_inline int do_monotonic(struct timespec64 *ts, - const struct vdso_data *data) -{ - u32 start_seq; - u64 ns; - u64 to_mono_sec; - u64 to_mono_nsec; - - do { - start_seq = vdso_data_read_begin(data); - - ts->tv_sec = data->xtime_sec; - ns = get_ns(data); - - to_mono_sec = data->wall_to_mono_sec; - to_mono_nsec = data->wall_to_mono_nsec; - } while (vdso_data_read_retry(data, start_seq)); - - ts->tv_sec += to_mono_sec; - ts->tv_nsec = 0; - timespec64_add_ns(ts, ns + to_mono_nsec); - - return 0; + return __cvdso_clock_gettime(clock, ts); } - +extern +int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz); int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) { - const struct vdso_data *data = get_vdso_data(); - struct timespec64 ts; - int ret; - - ret = do_realtime(&ts, data); - if (ret) - return ret; - - if (tv) { - tv->tv_sec = ts.tv_sec; - tv->tv_usec = ts.tv_nsec / 1000; - } - - if (tz) { - tz->tz_minuteswest = data->tz_minuteswest; - tz->tz_dsttime = data->tz_dsttime; - } - - return 0; + return __cvdso_gettimeofday(tv, tz); } -int __vdso_clock_gettime(clockid_t clkid, struct timespec64 *ts) +extern +int __vdso_clock_getres(clockid_t clock_id, struct __kernel_timespec *res); +int __vdso_clock_getres(clockid_t clock_id, struct __kernel_timespec *res) { - const struct vdso_data *data = get_vdso_data(); - int ret; - - switch (clkid) { - case CLOCK_REALTIME_COARSE: - ret = do_realtime_coarse(ts, data); - break; - case CLOCK_MONOTONIC_COARSE: - ret = do_monotonic_coarse(ts, data); - break; - case CLOCK_REALTIME: - ret = do_realtime(ts, data); - break; - case CLOCK_MONOTONIC: - ret = do_monotonic(ts, data); - break; - default: - /* fall back to a syscall */ - ret = syscall_fallback(clkid, ts); - } - - return ret; + return __cvdso_clock_getres(clock_id, res); } -- Gitee From 56d984aafaa7bbe3bf69b82e7d7f9d3d22c9d8d3 Mon Sep 17 00:00:00 2001 From: Deng Xiaoyun Date: Wed, 16 Oct 2024 17:06:10 +0800 Subject: [PATCH 56/66] anolis: sw64: kvm: declare KVM_CAP_SET_GUEST_DEBUG ANBZ: #4688 Because QEMU 8.2.0 needs this feature support, so we fix it according to the upstream community. Signed-off-by: Deng Xiaoyun Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/uapi/asm/kvm.h | 1 + arch/sw_64/kvm/sw64.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/sw_64/include/uapi/asm/kvm.h b/arch/sw_64/include/uapi/asm/kvm.h index 1949e106563d..8cc5f752bc6b 100644 --- a/arch/sw_64/include/uapi/asm/kvm.h +++ b/arch/sw_64/include/uapi/asm/kvm.h @@ -20,6 +20,7 @@ enum SW64_KVM_IRQ { #define __KVM_HAVE_IRQ_LINE #define __KVM_HAVE_READONLY_MEM +#define __KVM_HAVE_GUEST_DEBUG #define KVM_NR_IRQCHIPS 1 diff --git a/arch/sw_64/kvm/sw64.c b/arch/sw_64/kvm/sw64.c index 1213121728c4..b70f50e5610f 100644 --- a/arch/sw_64/kvm/sw64.c +++ b/arch/sw_64/kvm/sw64.c @@ -233,6 +233,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_IOEVENTFD: case KVM_CAP_SYNC_MMU: case KVM_CAP_READONLY_MEM: + case KVM_CAP_SET_GUEST_DEBUG: r = 1; break; case KVM_CAP_NR_VCPUS: -- Gitee From e237099cdef303f9eab1c3580b69e7e1660a0d94 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 12 Nov 2024 14:43:39 +0800 Subject: [PATCH 57/66] anolis: sw64: update defconfig ANBZ: #4688 Enable NO_HZ_IDLE and disable UDF_FS by default. Recreate defconfig by `make savedefconfig`. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/configs/junzhang_defconfig | 7 +++---- arch/sw_64/configs/xuelang_defconfig | 5 +++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/sw_64/configs/junzhang_defconfig b/arch/sw_64/configs/junzhang_defconfig index 2073cb0fecdb..06e792cd8662 100644 --- a/arch/sw_64/configs/junzhang_defconfig +++ b/arch/sw_64/configs/junzhang_defconfig @@ -3,6 +3,7 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y # CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_USELIB=y +CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_BPF_SYSCALL=y CONFIG_BPF_JIT=y @@ -28,7 +29,6 @@ CONFIG_DEBUG_PERF_USE_VMALLOC=y CONFIG_SUBARCH_C4=y CONFIG_SMP=y CONFIG_SCHED_SMT=y -CONFIG_NR_CPUS=512 CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_NUMA=y CONFIG_HZ=100 @@ -521,10 +521,9 @@ CONFIG_SERIAL_OF_PLATFORM=y CONFIG_VIRTIO_CONSOLE=y # CONFIG_HW_RANDOM is not set # CONFIG_I2C_COMPAT is not set -CONFIG_I2C=y CONFIG_I2C_CHARDEV=y -CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_I2C_MUX=y +CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_SPI=y CONFIG_SPI_SUNWAY=y CONFIG_SPI_SUNWAY_MMIO=y @@ -574,7 +573,6 @@ CONFIG_FSCACHE=y CONFIG_ISO9660_FS=y CONFIG_JOLIET=y CONFIG_ZISOFS=y -CONFIG_UDF_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_UTF8=y @@ -665,6 +663,7 @@ CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_HW is not set +CONFIG_CRC_ITU_T=y CONFIG_CONSOLE_LOGLEVEL_QUIET=7 # CONFIG_ENABLE_MUST_CHECK is not set CONFIG_SCHEDSTATS=y diff --git a/arch/sw_64/configs/xuelang_defconfig b/arch/sw_64/configs/xuelang_defconfig index 2272d99db00c..15110ecdce89 100644 --- a/arch/sw_64/configs/xuelang_defconfig +++ b/arch/sw_64/configs/xuelang_defconfig @@ -3,6 +3,7 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y # CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_USELIB=y +CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_BPF_SYSCALL=y CONFIG_BPF_JIT=y @@ -25,6 +26,7 @@ CONFIG_EXPERT=y CONFIG_KALLSYMS_ALL=y CONFIG_PERF_EVENTS=y CONFIG_DEBUG_PERF_USE_VMALLOC=y +# CONFIG_COMPAT_BRK is not set CONFIG_SMP=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_NUMA=y @@ -557,7 +559,6 @@ CONFIG_VIRTIO_MMIO=y CONFIG_STAGING=y CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y CONFIG_SUNWAY_IOMMU=y -CONFIG_SW64_LPC_INTC=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y @@ -571,7 +572,6 @@ CONFIG_FSCACHE=y CONFIG_ISO9660_FS=y CONFIG_JOLIET=y CONFIG_ZISOFS=y -CONFIG_UDF_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_UTF8=y @@ -662,6 +662,7 @@ CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_HW is not set +CONFIG_CRC_ITU_T=y CONFIG_CONSOLE_LOGLEVEL_QUIET=7 # CONFIG_FRAME_POINTER is not set CONFIG_SCHEDSTATS=y -- Gitee From 4c53bae65661aa0550d66739e2d93efc8ee5726d Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 3 Jul 2024 16:31:28 +0800 Subject: [PATCH 58/66] anolis: sw64: rename _PFN_BITS to __PFN_BITS ANBZ: #4688 Rename _PFN_BITS to __PFN_BITS to avoid "_PFN_BITS" redefined when CONFIG_ZSMALLOC is enabled. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/pgtable.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/include/asm/pgtable.h b/arch/sw_64/include/asm/pgtable.h index e9843b19916e..ddabb9e1774f 100644 --- a/arch/sw_64/include/asm/pgtable.h +++ b/arch/sw_64/include/asm/pgtable.h @@ -200,8 +200,8 @@ static inline void set_p4d(p4d_t *p4dp, p4d_t p4d) #define PFN_PTE_SHIFT _PFN_SHIFT -#define _PFN_BITS (MAX_PHYSMEM_BITS - PAGE_SHIFT) -#define _PFN_MASK (GENMASK(_PFN_BITS - 1, 0) << _PFN_SHIFT) +#define __PFN_BITS (MAX_PHYSMEM_BITS - PAGE_SHIFT) +#define _PFN_MASK (GENMASK(__PFN_BITS - 1, 0) << _PFN_SHIFT) #define _PAGE_TABLE (_PAGE_VALID | __DIRTY_BITS | __ACCESS_BITS) #define _PAGE_CHG_MASK (_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS | _PAGE_SPECIAL | _PAGE_LEAF | _PAGE_CONT) -- Gitee From 25d370d6c97372d1ff3dcf15e72529d3d15f0e48 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Thu, 14 Nov 2024 14:36:50 +0800 Subject: [PATCH 59/66] anolis: sw64: bpf: add BPF_NOSPEC jit ANBZ: #4688 Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/net/bpf_jit_comp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/sw_64/net/bpf_jit_comp.c b/arch/sw_64/net/bpf_jit_comp.c index 64ed06693924..477ec889d217 100644 --- a/arch/sw_64/net/bpf_jit_comp.c +++ b/arch/sw_64/net/bpf_jit_comp.c @@ -1217,6 +1217,13 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, return ret; break; + /* speculation barrier */ + case BPF_ST | BPF_NOSPEC: + /* + * Nothing required here. + */ + break; + /* ST: *(size *)(dst + off) = imm */ case BPF_ST | BPF_MEM | BPF_W: case BPF_ST | BPF_MEM | BPF_H: -- Gitee From 01845f35d2ac5663ceb035234934f1038292a852 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 3 Jul 2024 17:01:32 +0800 Subject: [PATCH 60/66] anolis: sw64: bpf: Add missing uapi header for BPF_PROG_TYPE_PERF_EVENT programs ANBZ: #4688 Add missing uapi header for BPF_PROG_TYPE_PERF_EVENT programs by exporting struct user_regs_struct instead of struct pt_regs which is in-kernel only. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- tools/arch/sw_64/include/uapi/asm/bpf_perf_event.h | 9 +++++++++ tools/include/uapi/asm/bpf_perf_event.h | 2 ++ 2 files changed, 11 insertions(+) create mode 100644 tools/arch/sw_64/include/uapi/asm/bpf_perf_event.h diff --git a/tools/arch/sw_64/include/uapi/asm/bpf_perf_event.h b/tools/arch/sw_64/include/uapi/asm/bpf_perf_event.h new file mode 100644 index 000000000000..52f6f1e555f1 --- /dev/null +++ b/tools/arch/sw_64/include/uapi/asm/bpf_perf_event.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_ASM_SW64_BPF_PERF_EVENT_H +#define _UAPI_ASM_SW64_BPF_PERF_EVENT_H + +#include + +typedef struct user_pt_regs bpf_user_pt_regs_t; + +#endif /* _UAPI_ASM_SW64_BPF_PERF_EVENT_H */ diff --git a/tools/include/uapi/asm/bpf_perf_event.h b/tools/include/uapi/asm/bpf_perf_event.h index ff52668abf8c..8f95170bf4d5 100644 --- a/tools/include/uapi/asm/bpf_perf_event.h +++ b/tools/include/uapi/asm/bpf_perf_event.h @@ -8,6 +8,8 @@ #include "../../arch/riscv/include/uapi/asm/bpf_perf_event.h" #elif defined(__loongarch__) #include "../../arch/loongarch/include/uapi/asm/bpf_perf_event.h" +#elif defined(__sw_64__) +#include "../../arch/sw_64/include/uapi/asm/bpf_perf_event.h" #else #include #endif -- Gitee From c4b8b338d3f77f638917bba4e27420259a8d45ea Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 10 Oct 2023 10:59:33 +0800 Subject: [PATCH 61/66] anolis: sw64: ptrace: add NT_SW64_SYSTEM_CALL regset ANBZ: #4688 This regeset is intended to be used to get and set a system call number while tracing. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/ptrace.c | 32 ++++++++++++++++++++++++++++++++ include/uapi/linux/elf.h | 1 + 2 files changed, 33 insertions(+) diff --git a/arch/sw_64/kernel/ptrace.c b/arch/sw_64/kernel/ptrace.c index 0af3d35163f9..9c5539f58ded 100644 --- a/arch/sw_64/kernel/ptrace.c +++ b/arch/sw_64/kernel/ptrace.c @@ -290,9 +290,33 @@ static int fpr_set(struct task_struct *target, sizeof(struct user_fpsimd_state)); } +static int syscall_get(struct task_struct *target, + const struct user_regset *regset, + struct membuf to) +{ + return membuf_store(&to, task_pt_regs(target)->orig_r0); +} + +static int syscall_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + unsigned long nr = task_pt_regs(target)->orig_r0; + int ret; + + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &nr, 0, -1); + if (ret) + return ret; + + task_pt_regs(target)->orig_r0 = nr; + return ret; +} + enum sw64_regset { REGSET_GPR, REGSET_FPR, + REGSET_SYSCALL, }; static const struct user_regset sw64_regsets[] = { @@ -312,6 +336,14 @@ static const struct user_regset sw64_regsets[] = { .regset_get = fpr_get, .set = fpr_set }, + [REGSET_SYSCALL] = { + .core_note_type = NT_SW64_SYSTEM_CALL, + .n = 1, + .size = sizeof(u64), + .align = sizeof(u64), + .regset_get = syscall_get, + .set = syscall_set + } }; static const struct user_regset_view user_sw64_view = { diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h index 9b731976ce2f..52a2ea81256e 100644 --- a/include/uapi/linux/elf.h +++ b/include/uapi/linux/elf.h @@ -454,6 +454,7 @@ typedef struct elf64_shdr { #define NT_LOONGARCH_LBT 0xa04 /* LoongArch Loongson Binary Translation registers */ #define NT_LOONGARCH_HW_BREAK 0xa05 /* LoongArch hardware breakpoint registers */ #define NT_LOONGARCH_HW_WATCH 0xa06 /* LoongArch hardware watchpoint registers */ +#define NT_SW64_SYSTEM_CALL 0x7f00 /* SW64 system call number */ /* Note types with note name "GNU" */ #define NT_GNU_PROPERTY_TYPE_0 5 -- Gitee From acb74246307a30e397110224914dd9e1ca7cfcaa Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Mon, 14 Oct 2024 14:42:03 +0800 Subject: [PATCH 62/66] anolis: sw64: rename mmap protection_map ANBZ: #4688 Rename mmap protection_map based on their functions. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/pgtable.h | 50 +++++++++++++++++++++++++++----- arch/sw_64/mm/init.c | 34 ++++++++++------------ 2 files changed, 58 insertions(+), 26 deletions(-) diff --git a/arch/sw_64/include/asm/pgtable.h b/arch/sw_64/include/asm/pgtable.h index ddabb9e1774f..0b9b65685e74 100644 --- a/arch/sw_64/include/asm/pgtable.h +++ b/arch/sw_64/include/asm/pgtable.h @@ -142,9 +142,6 @@ static inline void set_p4d(p4d_t *p4dp, p4d_t p4d) * the page is accessed. They are cleared only by the page-out routines */ #define PAGE_NONE __pgprot(__ACCESS_BITS | _PAGE_FOR | _PAGE_FOW | _PAGE_FOE | _PAGE_PROTNONE) -#define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS) -#define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW) -#define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW) #define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE) #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x)) @@ -189,9 +186,6 @@ static inline void set_p4d(p4d_t *p4dp, p4d_t p4d) * the page is accessed. They are cleared only by the page-out routines */ #define PAGE_NONE __pgprot(__ACCESS_BITS | _PAGE_FOR | _PAGE_FOW | _PAGE_FOE | _PAGE_LEAF | _PAGE_PROTNONE) -#define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_LEAF) -#define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_LEAF) -#define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_LEAF) #define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_KERN | _PAGE_LEAF) #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_LEAF | (x)) @@ -206,8 +200,48 @@ static inline void set_p4d(p4d_t *p4dp, p4d_t p4d) #define _PAGE_TABLE (_PAGE_VALID | __DIRTY_BITS | __ACCESS_BITS) #define _PAGE_CHG_MASK (_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS | _PAGE_SPECIAL | _PAGE_LEAF | _PAGE_CONT) -#define _PAGE_P(x) _PAGE_NORMAL((x) | _PAGE_FOW) -#define _PAGE_S(x) _PAGE_NORMAL((x) | _PAGE_FOW) +#define PAGE_READONLY_NOEXEC _PAGE_NORMAL(_PAGE_FOE | _PAGE_FOW) +#define PAGE_EXEC _PAGE_NORMAL(_PAGE_FOW | _PAGE_FOR) +#define PAGE_READONLY_EXEC _PAGE_NORMAL(_PAGE_FOW) +#define PAGE_COPY_NOEXEC PAGE_READONLY_NOEXEC +#define PAGE_COPY_EXEC PAGE_READONLY_EXEC +/* + * Since we don't have hardware dirty-bit management yet, shared + * writable page has FOW bit set to make sure dirty-bit could be + * set properly. + */ +#define PAGE_SHARED_NOEXEC PAGE_READONLY_NOEXEC +#define PAGE_SHARED_EXEC PAGE_READONLY_EXEC + +/* For backward compatibility */ +#define PAGE_READONLY PAGE_READONLY_EXEC +#define PAGE_COPY PAGE_COPY_EXEC +#define PAGE_SHARED PAGE_SHARED_EXEC + +/* + * The hardware can handle write-only mappings, but as the sw64 + * architecture does byte-wide writes with a read-modify-write + * sequence, it's not practical to have write-without-read privs. + * Thus the "-w- -> rw-" and "-wx -> rwx" mapping here (and in + * arch/sw_64/mm/fault.c) + */ +#define __P000 PAGE_NONE +#define __P001 PAGE_READONLY_NOEXEC +#define __P010 PAGE_COPY_NOEXEC +#define __P011 PAGE_COPY_NOEXEC +#define __P100 PAGE_EXEC +#define __P101 PAGE_READONLY_EXEC +#define __P110 PAGE_COPY_EXEC +#define __P111 PAGE_COPY_EXEC + +#define __S000 PAGE_NONE +#define __S001 PAGE_READONLY_NOEXEC +#define __S010 PAGE_SHARED_NOEXEC +#define __S011 PAGE_SHARED_NOEXEC +#define __S100 PAGE_EXEC +#define __S101 PAGE_READONLY_EXEC +#define __S110 PAGE_SHARED_EXEC +#define __S111 PAGE_SHARED_EXEC /* * pgprot_noncached() is only for infiniband pci support, and a real diff --git a/arch/sw_64/mm/init.c b/arch/sw_64/mm/init.c index f01d2ebef70f..d5e1baf23f72 100644 --- a/arch/sw_64/mm/init.c +++ b/arch/sw_64/mm/init.c @@ -473,23 +473,21 @@ void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap) #endif static const pgprot_t protection_map[16] = { - [VM_NONE] = _PAGE_P(_PAGE_FOE | _PAGE_FOW | - _PAGE_FOR), - [VM_READ] = _PAGE_P(_PAGE_FOE | _PAGE_FOW), - [VM_WRITE] = _PAGE_P(_PAGE_FOE), - [VM_WRITE | VM_READ] = _PAGE_P(_PAGE_FOE), - [VM_EXEC] = _PAGE_P(_PAGE_FOW | _PAGE_FOR), - [VM_EXEC | VM_READ] = _PAGE_P(_PAGE_FOW), - [VM_EXEC | VM_WRITE] = _PAGE_P(0), - [VM_EXEC | VM_WRITE | VM_READ] = _PAGE_P(0), - [VM_SHARED] = _PAGE_S(_PAGE_FOE | _PAGE_FOW | - _PAGE_FOR), - [VM_SHARED | VM_READ] = _PAGE_S(_PAGE_FOE | _PAGE_FOW), - [VM_SHARED | VM_WRITE] = _PAGE_S(_PAGE_FOE), - [VM_SHARED | VM_WRITE | VM_READ] = _PAGE_S(_PAGE_FOE), - [VM_SHARED | VM_EXEC] = _PAGE_S(_PAGE_FOW | _PAGE_FOR), - [VM_SHARED | VM_EXEC | VM_READ] = _PAGE_S(_PAGE_FOW), - [VM_SHARED | VM_EXEC | VM_WRITE] = _PAGE_S(0), - [VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] = _PAGE_S(0) + [VM_NONE] = PAGE_NONE, + [VM_READ] = PAGE_READONLY_NOEXEC, + [VM_WRITE] = PAGE_COPY_NOEXEC, + [VM_WRITE | VM_READ] = PAGE_COPY_NOEXEC, + [VM_EXEC] = PAGE_EXEC, + [VM_EXEC | VM_READ] = PAGE_READONLY_EXEC, + [VM_EXEC | VM_WRITE] = PAGE_COPY_EXEC, + [VM_EXEC | VM_WRITE | VM_READ] = PAGE_COPY_EXEC, + [VM_SHARED] = PAGE_NONE, + [VM_SHARED | VM_READ] = PAGE_READONLY_NOEXEC, + [VM_SHARED | VM_WRITE] = PAGE_SHARED_NOEXEC, + [VM_SHARED | VM_WRITE | VM_READ] = PAGE_SHARED_NOEXEC, + [VM_SHARED | VM_EXEC] = PAGE_EXEC, + [VM_SHARED | VM_EXEC | VM_READ] = PAGE_READONLY_EXEC, + [VM_SHARED | VM_EXEC | VM_WRITE] = PAGE_SHARED_EXEC, + [VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] = PAGE_SHARED_EXEC }; DECLARE_VM_GET_PAGE_PROT -- Gitee From c27e5ef245ef27d6fc58b6e575ca22c64b9975ca Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 3 Jul 2024 17:03:05 +0800 Subject: [PATCH 63/66] anolis: libbpf: add sw64 support ANBZ: #4688 Add __NR_bpf, bpf_target_sw64, PT_REGS_xxx and libbpf_smp barriers for sw64. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- tools/lib/bpf/bpf.c | 2 ++ tools/lib/bpf/bpf_tracing.h | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index af46488e4ea9..04ccbd5b2d0d 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -59,6 +59,8 @@ # define __NR_bpf 6319 # elif defined(__mips__) && defined(_ABI64) # define __NR_bpf 5315 +# elif defined(__sw_64__) +# define __NR_bpf 170 # else # error __NR_bpf not defined. libbpf does not support your arch. # endif diff --git a/tools/lib/bpf/bpf_tracing.h b/tools/lib/bpf/bpf_tracing.h index 1c13f8e88833..8d34cb534ca6 100644 --- a/tools/lib/bpf/bpf_tracing.h +++ b/tools/lib/bpf/bpf_tracing.h @@ -35,6 +35,9 @@ #elif defined(__TARGET_ARCH_loongarch) #define bpf_target_loongarch #define bpf_target_defined +#elif defined(__TARGET_ARCH_sw_64) + #define bpf_target_sw64 + #define bpf_target_defined #else /* Fall back to what the compiler says */ @@ -68,6 +71,9 @@ #elif defined(__loongarch__) #define bpf_target_loongarch #define bpf_target_defined +#elif defined(__sw_64__) + #define bpf_target_sw64 + #define bpf_target_defined #endif /* no compiler target */ #endif @@ -441,6 +447,34 @@ struct pt_regs___arm64 { #define __PT_SP_REG regs[3] #define __PT_IP_REG csr_era +#elif defined(bpf_target_sw64) + +/* sw64 provides struct user_pt_regs instead of struct pt_regs to userspace */ +struct pt_regs; +#define PT_REGS_SW64 const volatile struct user_pt_regs +#define PT_REGS_PARM1(x) (((PT_REGS_SW64 *)(x))->regs[16]) +#define PT_REGS_PARM2(x) (((PT_REGS_SW64 *)(x))->regs[17]) +#define PT_REGS_PARM3(x) (((PT_REGS_SW64 *)(x))->regs[18]) +#define PT_REGS_PARM4(x) (((PT_REGS_SW64 *)(x))->regs[19]) +#define PT_REGS_PARM5(x) (((PT_REGS_SW64 *)(x))->regs[20]) +#define PT_REGS_RET(x) (((PT_REGS_SW64 *)(x))->regs[26]) +/* Works only with CONFIG_FRAME_POINTER */ +#define PT_REGS_FP(x) (((PT_REGS_SW64 *)(x))->regs[15]) +#define PT_REGS_RC(x) (((PT_REGS_SW64 *)(x))->regs[0]) +#define PT_REGS_SP(x) (((PT_REGS_SW64 *)(x))->regs[30]) +#define PT_REGS_IP(x) (((PT_REGS_SW64 *)(x))->pc) + +#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[16]) +#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[17]) +#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[18]) +#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[19]) +#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[20]) +#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[26]) +#define PT_REGS_FP_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[15]) +#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[0]) +#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[30]) +#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), pc) + #endif #if defined(bpf_target_defined) -- Gitee From 420e5081c1ab0e898ed7de171771501d7d23e798 Mon Sep 17 00:00:00 2001 From: Gu Zitao Date: Mon, 2 Dec 2024 14:39:33 +0800 Subject: [PATCH 64/66] anolis: sw64: work around gcc bugs with 'asm goto' with output ANBZ: #4688 Signed-off-by: Gu Zitao Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/jump_label.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/sw_64/include/asm/jump_label.h b/arch/sw_64/include/asm/jump_label.h index 32fbf7573b20..27898e8e2c75 100644 --- a/arch/sw_64/include/asm/jump_label.h +++ b/arch/sw_64/include/asm/jump_label.h @@ -12,12 +12,12 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool branch) { - asm_volatile_goto("1: nop\n\t" - ".pushsection __jump_table, \"aw\"\n\t" - ".align 3\n\t" - ".quad 1b, %l[l_yes], %0\n\t" - ".popsection\n\t" - : : "i"(&((char *)key)[branch]) : : l_yes); + asm goto("1: nop\n\t" + ".pushsection __jump_table, \"aw\"\n\t" + ".align 3\n\t" + ".quad 1b, %l[l_yes], %0\n\t" + ".popsection\n\t" + : : "i"(&((char *)key)[branch]) : : l_yes); return false; l_yes: @@ -26,12 +26,12 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) { - asm_volatile_goto("1: br %l[l_yes]\n\t" - ".pushsection __jump_table, \"aw\"\n\t" - ".align 3\n\t" - ".quad 1b, %l[l_yes], %0\n\t" - ".popsection\n\t" - : : "i"(&((char *)key)[branch]) : : l_yes); + asm goto("1: br %l[l_yes]\n\t" + ".pushsection __jump_table, \"aw\"\n\t" + ".align 3\n\t" + ".quad 1b, %l[l_yes], %0\n\t" + ".popsection\n\t" + : : "i"(&((char *)key)[branch]) : : l_yes); return false; l_yes: -- Gitee From c19278d9bcc691e63fe5ca794ae88a0ca1fc73c5 Mon Sep 17 00:00:00 2001 From: Gu Zitao Date: Tue, 27 Aug 2024 09:27:14 +0800 Subject: [PATCH 65/66] anolis: sw64: fix compile warnings for redefinitions in mman.h ANBZ: #4688 A recent merged patch introduced redefined compile warnings in mman.h, so fix it. Fixes: 44d40e7a3975 ("anolis: anolis: sw64: fix compile errors for CONFIG_ADVISE_SYSCALLS=y") Signed-off-by: Gu Zitao Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/uapi/asm/mman.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/include/uapi/asm/mman.h b/arch/sw_64/include/uapi/asm/mman.h index c83c4b50662a..0214e6eda384 100644 --- a/arch/sw_64/include/uapi/asm/mman.h +++ b/arch/sw_64/include/uapi/asm/mman.h @@ -2,8 +2,6 @@ #ifndef _UAPI_ASM_SW64_MMAN_H #define _UAPI_ASM_SW64_MMAN_H -#include - #define PROT_READ 0x1 /* page can be read */ #define PROT_WRITE 0x2 /* page can be written */ #define PROT_EXEC 0x4 /* page can be executed */ @@ -79,6 +77,9 @@ #define MADV_COLLAPSE 25 /* Synchronous hugepage collapse */ +#define MADV_HWPOISON 100 /* poison a page for testing */ +#define MADV_SOFT_OFFLINE 101 /* soft offline page for testing */ + /* compatibility flags */ #define MAP_FILE 0 -- Gitee From f12d6f0bb85e701fcf9abc05b0a1a91b58934240 Mon Sep 17 00:00:00 2001 From: Gu Zitao Date: Tue, 3 Dec 2024 09:33:24 +0800 Subject: [PATCH 66/66] anolis: sw64: use generic vdso_install rule according upstream ANBZ: #4688 The upstream has introduced a generic vdso_install rule for all architectures, use it on sw64. Signed-off-by: Gu Zitao Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Makefile | 4 +--- arch/sw_64/kernel/vdso/Makefile | 11 ----------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/arch/sw_64/Makefile b/arch/sw_64/Makefile index ccf2f5d6e378..bae64bdfd7af 100644 --- a/arch/sw_64/Makefile +++ b/arch/sw_64/Makefile @@ -49,9 +49,7 @@ export LIBS_Y boot := arch/sw_64/boot -PHONY += vdso_install -vdso_install: - $(Q)$(MAKE) $(build)=arch/sw64/kernel/vdso $@ +vdso-install-y += arch/sw_64/kernel/vdso.so.dbg #Default target when executing make with no arguments all: $(boot)/vmlinux.bin.gz diff --git a/arch/sw_64/kernel/vdso/Makefile b/arch/sw_64/kernel/vdso/Makefile index 8ae5bf3d1770..899f57aba588 100644 --- a/arch/sw_64/kernel/vdso/Makefile +++ b/arch/sw_64/kernel/vdso/Makefile @@ -69,14 +69,3 @@ quiet_cmd_vdsold = VDSOLD $@ # that contains the same symbols at the same offsets. quiet_cmd_so2s = SO2S $@ cmd_so2s = $(NM) -D $< | $(srctree)/$(src)/so2s.sh > $@ - -# install commands for the unstripped file -quiet_cmd_vdso_install = INSTALL $@ - cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@ - -vdso.so: $(obj)/vdso.so.dbg - @mkdir -p $(MODLIB)/vdso - $(call cmd,vdso_install) - - -vdso_install: vdso.so -- Gitee