From feff2fbf9b938174cf7aa006313c6ae71d41b06b Mon Sep 17 00:00:00 2001 From: Tang Jinyang Date: Thu, 16 Nov 2023 11:08:55 +0800 Subject: [PATCH 01/24] anolis: sw64: remove useless current_policy ANBZ: #4688 This variable is no longer needed and can be removed. Signed-off-by: Tang Jinyang Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/cpufreq.h | 2 -- arch/sw_64/platform/cpufreq_xuelang.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/arch/sw_64/include/asm/cpufreq.h b/arch/sw_64/include/asm/cpufreq.h index cf47f1fc6866..e6f1d16e5620 100644 --- a/arch/sw_64/include/asm/cpufreq.h +++ b/arch/sw_64/include/asm/cpufreq.h @@ -11,8 +11,6 @@ struct clk; -extern char curruent_policy[CPUFREQ_NAME_LEN]; - struct clk_ops { void (*init)(struct clk *clk); void (*enable)(struct clk *clk); diff --git a/arch/sw_64/platform/cpufreq_xuelang.c b/arch/sw_64/platform/cpufreq_xuelang.c index 1259e58dc874..e639fdc34fb9 100644 --- a/arch/sw_64/platform/cpufreq_xuelang.c +++ b/arch/sw_64/platform/cpufreq_xuelang.c @@ -70,8 +70,6 @@ static int __init sw64_cpufreq_init(void) } arch_initcall(sw64_cpufreq_init); -char curruent_policy[CPUFREQ_NAME_LEN]; - static struct clk cpu_clk = { .name = "cpu_clk", .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, -- Gitee From 3244f6a8a0eac57ac78cb81ff1a056cc4057b711 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 15 Nov 2023 14:12:45 +0800 Subject: [PATCH 02/24] anolis: sw64: extern vdso_start and vdso_end as char[] ANBZ: #4688 Extern vdso_start and vdso_end as char[] to avoid gcc warning '__builtin_memcmp_eq' specified bound 4 exceeds source size 1 [-Wstringop-overread] | if (memcmp(&vdso_start, "\177ELF", 4)) { Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/vdso.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/sw_64/kernel/vdso.c b/arch/sw_64/kernel/vdso.c index b4126cbaa4bd..15f1f244a82f 100644 --- a/arch/sw_64/kernel/vdso.c +++ b/arch/sw_64/kernel/vdso.c @@ -21,7 +21,7 @@ #include -extern char vdso_start, vdso_end; +extern char vdso_start[], vdso_end[]; static unsigned long vdso_pages; static struct page **vdso_pagelist; @@ -40,14 +40,14 @@ static int __init vdso_init(void) { int i; - if (memcmp(&vdso_start, "\177ELF", 4)) { + if (memcmp(vdso_start, "\177ELF", 4)) { pr_err("vDSO is not a valid ELF object!\n"); return -EINVAL; } - vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT; + vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT; pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n", - vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data); + vdso_pages + 1, vdso_pages, vdso_start, 1L, vdso_data); /* Allocate the vDSO pagelist, plus a page for the data. */ vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *), @@ -60,7 +60,7 @@ static int __init vdso_init(void) /* Grab the vDSO code pages. */ for (i = 0; i < vdso_pages; i++) - vdso_pagelist[i + 1] = virt_to_page(&vdso_start + i * PAGE_SIZE); + vdso_pagelist[i + 1] = virt_to_page(vdso_start + i * PAGE_SIZE); /* Populate the special mapping structures */ vdso_spec[0] = (struct vm_special_mapping) { -- Gitee From 34759967cba379f79b7bddb449a7d04e65f8e759 Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Mon, 20 Nov 2023 09:22:27 +0800 Subject: [PATCH 03/24] anolis: sw64: fix hugepage support ANBZ: #4688 Add missing pud_write() and more hugepage granularity support. Signed-off-by: Wu Liliu Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/page.h | 2 +- arch/sw_64/include/asm/pgtable.h | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/include/asm/page.h b/arch/sw_64/include/asm/page.h index 68b4f2fc1b48..3a95151b67f8 100644 --- a/arch/sw_64/include/asm/page.h +++ b/arch/sw_64/include/asm/page.h @@ -15,7 +15,7 @@ #define HPAGE_MASK (~(HPAGE_SIZE - 1)) #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) -#define HUGE_MAX_HSTATE 2 +#define HUGE_MAX_HSTATE 3 #ifdef __KERNEL__ #ifndef __ASSEMBLY__ diff --git a/arch/sw_64/include/asm/pgtable.h b/arch/sw_64/include/asm/pgtable.h index 0b1f825eb74c..a7741a67e687 100644 --- a/arch/sw_64/include/asm/pgtable.h +++ b/arch/sw_64/include/asm/pgtable.h @@ -233,6 +233,18 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) } } +static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pteval) +{ + set_pte(ptep, pteval); +} + +#define pud_write pud_write +static inline int pud_write(pud_t pud) +{ + return !(pud_val(pud) & _PAGE_FOW); +} + static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) { pte_t pte; -- Gitee From 4a877ebb851ed25f45f40e0fb8b8b6d422e3eb15 Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Mon, 20 Nov 2023 16:35:37 +0800 Subject: [PATCH 04/24] anolis: sw64: perf: hide hardware performance events in guest os ANBZ: #4688 Hardware performance events are not supported in guest os, and software performance events are used by default. Signed-off-by: He Chuyue Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/perf_event.c | 57 +++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/arch/sw_64/kernel/perf_event.c b/arch/sw_64/kernel/perf_event.c index 83bb051be9de..855f4246433c 100644 --- a/arch/sw_64/kernel/perf_event.c +++ b/arch/sw_64/kernel/perf_event.c @@ -729,6 +729,38 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, walk_stackframe(NULL, regs, callchain_trace, entry); } +/* + * Init call to initialise performance events at kernel startup. + */ +int __init init_hw_perf_events(void) +{ + pr_info("Performance Events: "); + + if (!supported_cpu()) { + pr_cont("Unsupported CPU type!\n"); + return 0; + } + + 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 */ + + perf_irq = sw64_perf_event_irq_handler; + + /* And set up PMU specification */ + sw64_pmu = &core3_pmu; + + perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); + + return 0; +} +early_initcall(init_hw_perf_events); + /* * Gets the perf_instruction_pointer and perf_misc_flags for guest os. */ @@ -760,28 +792,3 @@ unsigned long perf_misc_flags(struct pt_regs *regs) return misc; } - -/* - * Init call to initialise performance events at kernel startup. - */ -int __init init_hw_perf_events(void) -{ - if (!supported_cpu()) { - pr_info("Performance events: Unsupported CPU type!\n"); - return 0; - } - - pr_info("Performance events: Supported CPU type!\n"); - - /* Override performance counter IRQ vector */ - - perf_irq = sw64_perf_event_irq_handler; - - /* And set up PMU specification */ - sw64_pmu = &core3_pmu; - - perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); - - return 0; -} -early_initcall(init_hw_perf_events); -- Gitee From 52650012df6acd642b6a3e51e055ae121d51fa30 Mon Sep 17 00:00:00 2001 From: Gu Zitao Date: Mon, 20 Nov 2023 14:14:42 +0800 Subject: [PATCH 05/24] anolis: sw64: uapi: fix a compile error for headers_install ANBZ: #4688 The following error was reported in uapi/asm/fpu.h when make headers_install: - error: arch/sw_64/include/uapi/asm/fpu.h: - leak CONFIG_SUBARCH_C3B to user-space Fix it based on the error information. Signed-off-by: Gu Zitao Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/uapi/asm/fpu.h | 8 -------- arch/sw_64/kernel/process.c | 4 ++++ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/sw_64/include/uapi/asm/fpu.h b/arch/sw_64/include/uapi/asm/fpu.h index 8945816c542b..7a1514c978b9 100644 --- a/arch/sw_64/include/uapi/asm/fpu.h +++ b/arch/sw_64/include/uapi/asm/fpu.h @@ -6,11 +6,7 @@ * SW-64 floating-point control register defines: */ #define FPCR_DNOD (1UL << 47) /* denorm INV trap disable */ -#ifdef CONFIG_SUBARCH_C3B -#define FPCR_DNZ (1UL << 48) /* denorms to zero */ -#else #define FPCR_DNOE (1UL << 48) /* hardware denormal support */ -#endif #define FPCR_INVD (1UL << 49) /* invalid op disable (opt.) */ #define FPCR_DZED (1UL << 50) /* division by zero disable (opt.) */ #define FPCR_OVFD (1UL << 51) /* overflow disable (optional) */ @@ -34,11 +30,7 @@ #define FPCR_MASK 0xffff800000000000L -#ifdef CONFIG_SUBARCH_C3B #define FPCR_INIT FPCR_DYN_NORMAL -#else -#define FPCR_INIT (FPCR_DYN_NORMAL | FPCR_DNOE) -#endif /* status bit coming from hardware fpcr . definde by fire3 */ #define FPCR_STATUS_INV0 (1UL << 52) diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index 9a887140edef..beaed17334ea 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -35,7 +35,11 @@ flush_thread(void) * with respect to the FPU. This is all exceptions disabled. */ current_thread_info()->ieee_state = 0; +#ifdef CONFIG_SUBARCH_C3B wrfpcr(FPCR_INIT | ieee_swcr_to_fpcr(0)); +#else + wrfpcr(FPCR_INIT | FPCR_DNOE | ieee_swcr_to_fpcr(0)); +#endif /* Clean slate for TLS. */ current_thread_info()->pcb.tp = 0; -- Gitee From ea41a29eed1eb95105e54936d217c822d8b1b912 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Mon, 4 Dec 2023 13:41:08 +0800 Subject: [PATCH 06/24] anolis: sw64: pci: export some pci functions ANBZ: #4688 Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/pci/controller/pci-sunway.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pci/controller/pci-sunway.c b/drivers/pci/controller/pci-sunway.c index 036994ffde38..e9314e4cb86e 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -377,6 +377,7 @@ struct pci_controller *bus_num_to_pci_controller(unsigned long bus_num) return NULL; } +EXPORT_SYMBOL(bus_num_to_pci_controller); struct pci_controller *pci_bus_to_pci_controller(const struct pci_bus *bus) { @@ -391,6 +392,7 @@ struct pci_controller *pci_bus_to_pci_controller(const struct pci_bus *bus) cfg = (struct pci_config_window *)bus->sysdata; return (struct pci_controller *)(cfg->priv); } +EXPORT_SYMBOL(pci_bus_to_pci_controller); /** * PCIe Root Complex read config space operations -- Gitee From 4556248ff2fa39e054f5023dcde9f31d16ba46f7 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Mon, 4 Dec 2023 15:55:49 +0800 Subject: [PATCH 07/24] anolis: sw64: numa: fix compile error when CONFIG_ACPI_NUMA=n ANBZ: #4688 Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/mm/numa.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/mm/numa.c b/arch/sw_64/mm/numa.c index fcf1f97a7840..e46372f3ac77 100644 --- a/arch/sw_64/mm/numa.c +++ b/arch/sw_64/mm/numa.c @@ -344,10 +344,30 @@ static int __init manual_numa_init(void) return 0; } +#ifdef CONFIG_ACPI_NUMA +static int __init sw64_acpi_numa_init(void) +{ + int ret; + + ret = acpi_numa_init(); + if (ret) { + pr_info("Failed to initialise from firmware\n"); + return ret; + } + + return srat_disabled() ? -EINVAL : 0; +} +#else +static int __init sw64_acpi_numa_init(void) +{ + return -EOPNOTSUPP; +} +#endif + void __init sw64_numa_init(void) { if (!numa_off) { - if (!acpi_disabled && !numa_init(acpi_numa_init)) + if (!acpi_disabled && !numa_init(sw64_acpi_numa_init)) return; if (acpi_disabled && !numa_init(of_numa_init)) return; -- Gitee From 90999707980d3c3ba202c7b286ff44b90b03a8f3 Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Mon, 20 Nov 2023 15:45:02 +0800 Subject: [PATCH 08/24] anolis: sw64: perf: do all event checks in sw64_pmu_event_init() ANBZ: #4688 It used to check perf events in two functions. To make the code clear, merge these checks into sw64_pmu_event_init(). BTW, configure PMC with `hwc->config` instead of `hwc->event_base`, and this will makes no functional changes intended. Signed-off-by: He Chuyue Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/perf_event.c | 101 ++++++++++++++++----------------- 1 file changed, 48 insertions(+), 53 deletions(-) diff --git a/arch/sw_64/kernel/perf_event.c b/arch/sw_64/kernel/perf_event.c index 855f4246433c..3c6a8283b1e6 100644 --- a/arch/sw_64/kernel/perf_event.c +++ b/arch/sw_64/kernel/perf_event.c @@ -378,7 +378,7 @@ static void sw64_pmu_start(struct perf_event *event, int flags) /* counting in selected modes, for both counters */ wrperfmon(PMC_CMD_PM, hwc->config_base); - wrperfmon(PMC_CMD_EVENT_BASE + hwc->idx, hwc->event_base); + wrperfmon(PMC_CMD_EVENT_BASE + hwc->idx, hwc->config); wrperfmon(PMC_CMD_ENABLE, PMC_ENABLE_BASE + hwc->idx); } @@ -474,49 +474,10 @@ 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 perf_event_attr *attr = &event->attr; struct hw_perf_event *hwc = &event->hw; - const struct sw64_perf_event *event_type; - - - /* - * SW64 does not have per-counter usr/os/guest/host bits, - * we can distinguish exclude_user and exclude_kernel by - * sample mode. - */ - if (event->attr.exclude_hv || event->attr.exclude_idle || - event->attr.exclude_host || event->attr.exclude_guest) - return -EINVAL; - - /* - * SW64 does not support precise ip feature, and system hang when - * detecting precise_ip by perf_event_attr__set_max_precise_ip - * in userspace - */ - if (attr->precise_ip != 0) - return -EOPNOTSUPP; - - /* SW64 has fixed counter for given event type */ - if (attr->type == PERF_TYPE_HARDWARE) { - if (attr->config >= sw64_pmu->max_events) - return -EINVAL; - event_type = sw64_pmu->map_hw_event(attr->config); - hwc->idx = event_type->counter; - hwc->event_base = event_type->event; - } else if (attr->type == PERF_TYPE_HW_CACHE) { - event_type = sw64_pmu->map_cache_event(attr->config); - if (IS_ERR(event_type)) /* */ - return PTR_ERR(event_type); - hwc->idx = event_type->counter; - hwc->event_base = event_type->event; - } else { /* PERF_TYPE_RAW */ - if (!sw64_pmu->raw_event_valid(attr->config)) - return -EINVAL; - hwc->idx = attr->config >> 8; /* counter selector */ - hwc->event_base = attr->config & 0xff; /* event selector */ - } hwc->config_base = SW64_PERFCTRL_AM; @@ -525,8 +486,6 @@ static int __hw_perf_event_init(struct perf_event *event) if (attr->exclude_kernel) hwc->config_base = SW64_PERFCTRL_UM; - hwc->config = attr->config; - if (!is_sampling_event(event)) pr_debug("not sampling event\n"); @@ -537,8 +496,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; } /* @@ -546,28 +503,66 @@ static int __hw_perf_event_init(struct perf_event *event) */ static int sw64_pmu_event_init(struct perf_event *event) { - int err; + struct perf_event_attr *attr = &event->attr; + struct hw_perf_event *hwc = &event->hw; + const struct sw64_perf_event *event_type; + + if (!sw64_pmu) + return -ENODEV; /* does not support taken branch sampling */ if (has_branch_stack(event)) return -EOPNOTSUPP; - switch (event->attr.type) { - case PERF_TYPE_RAW: + /* + * SW64 does not have per-counter usr/os/guest/host bits, + * we can distinguish exclude_user and exclude_kernel by + * sample mode. + */ + if (attr->exclude_hv || attr->exclude_idle || + attr->exclude_host || attr->exclude_guest) + return -EINVAL; + + if (attr->exclude_user && attr->exclude_kernel) + return -EOPNOTSUPP; + /* + * SW64 does not support precise ip feature, and system hang when + * detecting precise_ip by perf_event_attr__set_max_precise_ip + * in userspace + */ + if (attr->precise_ip != 0) + return -EOPNOTSUPP; + + /* SW64 has fixed counter for given event type */ + switch (attr->type) { case PERF_TYPE_HARDWARE: + if (attr->config >= sw64_pmu->max_events) + return -EINVAL; + event_type = sw64_pmu->map_hw_event(attr->config); + hwc->idx = event_type->counter; + hwc->config = event_type->event; + break; case PERF_TYPE_HW_CACHE: + event_type = sw64_pmu->map_cache_event(attr->config); + if (IS_ERR(event_type)) + return PTR_ERR(event_type); + hwc->idx = event_type->counter; + hwc->config = event_type->event; + break; + case PERF_TYPE_RAW: + if (!sw64_pmu->raw_event_valid(attr->config)) + return -EINVAL; + hwc->idx = attr->config >> 8; /* counter selector */ + hwc->config = attr->config & 0xff; /* event selector */ break; default: return -ENOENT; } - if (!sw64_pmu) - return -ENODEV; - /* Do the real initialisation work. */ - err = __hw_perf_event_init(event); + __hw_perf_event_init(event); - return err; + return 0; } static struct pmu pmu = { -- Gitee From 9627398f4b5f103a447e935432ee6eb7d6212b58 Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Tue, 5 Dec 2023 09:17:26 +0800 Subject: [PATCH 09/24] anolis: sw64: fix lockdep error ANBZ: #4688 Initialize a dynamically allocated struct bin_attribute so we can make lockdep happy. This is a new requirement for attributes and initially this is only needed when lockdep is enabled. Lockdep gives a nice error when your attribute is added to sysfs if you don't have this. Signed-off-by: He Chuyue Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/pci/pci-sysfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sw_64/pci/pci-sysfs.c b/arch/sw_64/pci/pci-sysfs.c index 5b52a534fa80..fd097d52b16a 100644 --- a/arch/sw_64/pci/pci-sysfs.c +++ b/arch/sw_64/pci/pci-sysfs.c @@ -200,6 +200,7 @@ static int pci_create_attr(struct pci_dev *pdev, int num) return -ENOMEM; attr_name = (char *)(attr + res_count); + sysfs_bin_attr_init(attr); pdev->res_attr[num] = attr; retval = pci_create_one_attr(pdev, num, attr_name, suffix, attr, sparse_base); -- Gitee From 5ad7113a0deb907eccbd9231d7d71bd8873a9f02 Mon Sep 17 00:00:00 2001 From: Zhi Tongze Date: Tue, 21 Nov 2023 14:58:49 +0800 Subject: [PATCH 10/24] anolis: sw64: kgdb: add single-step debug support ANBZ: #4688 kgdb single-step debug relies on gdb tool, and unexpected exceptions will occur if single-step debug is interrupted. This patch adds kgdb single-step debugging to solve this problem. This patch also adds support for detach and kill commands. Signed-off-by: Zhi Tongze Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/kgdb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/sw_64/kernel/kgdb.c b/arch/sw_64/kernel/kgdb.c index 833f72a1577c..a9b2db81c494 100644 --- a/arch/sw_64/kernel/kgdb.c +++ b/arch/sw_64/kernel/kgdb.c @@ -160,11 +160,21 @@ int kgdb_arch_handle_exception(int exception_vector, int signo, unsigned long address = -1; switch (remcom_in_buffer[0]) { + case 'D': + case 'k': case 'c': ptr = &remcom_in_buffer[1]; if (kgdb_hex2long(&ptr, &address)) kgdb_arch_set_pc(linux_regs, address); return 0; + case 's': + ptr = &remcom_in_buffer[1]; + atomic_set(&kgdb_cpu_doing_single_step, -1); + if (kgdb_hex2long(&ptr, &address)) + kgdb_arch_set_pc(linux_regs, address); + atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id()); + kgdb_single_step = 1; + return 0; } return -1; } -- Gitee From 7ca2cbac68ae22907190a2b3bebbdf6c93b6d08b Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Sun, 19 Nov 2023 18:38:19 +0800 Subject: [PATCH 11/24] anolis: sw64: use rvpcr() to setup run mode ANBZ: #4688 Use rvpcr() to read CSR__VPCR instead of MMSIZE to get the system mode. Signed-off-by: Wu Liliu Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/hmcall.h | 1 + arch/sw_64/include/asm/hw_init.h | 1 + arch/sw_64/kernel/setup.c | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/include/asm/hmcall.h b/arch/sw_64/include/asm/hmcall.h index e3bac3016740..0bcd901f671d 100644 --- a/arch/sw_64/include/asm/hmcall.h +++ b/arch/sw_64/include/asm/hmcall.h @@ -159,6 +159,7 @@ __CALL_HMC_VOID(wrktp); #define save_ktp() wrktp() __CALL_HMC_R0(rdps, unsigned long); +__CALL_HMC_R0(rvpcr, unsigned long); __CALL_HMC_R0(rdusp, unsigned long); __CALL_HMC_W1(wrusp, unsigned long); diff --git a/arch/sw_64/include/asm/hw_init.h b/arch/sw_64/include/asm/hw_init.h index 2078c66d1c4f..4710f15a9a56 100644 --- a/arch/sw_64/include/asm/hw_init.h +++ b/arch/sw_64/include/asm/hw_init.h @@ -7,6 +7,7 @@ #include #define MMSIZE __va(0x2040) +#define VPCR_SHIFT 44 /* * Descriptor for a cache diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 0c1ddb9b46d7..412710b17a80 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -674,7 +674,7 @@ static void __init setup_cpu_info(void) static void __init setup_run_mode(void) { - if (*(unsigned long *)MMSIZE) { + if (rvpcr() >> VPCR_SHIFT) { static_branch_disable(&run_mode_host_key); if (*(unsigned long *)MMSIZE & EMUL_FLAG) { pr_info("run mode: emul\n"); -- Gitee From a7074733d977ad8be4962dffae494de5359f0f0f Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Wed, 27 Dec 2023 01:10:08 +0000 Subject: [PATCH 12/24] anolis: sw64: iommu: fix the bug when vfio_iommu unpin pages ANBZ: #4688 When the page granularity is 8K, iova_to_phys return the wrong page address, so fix it. Signed-off-by: Zheng Chongzhen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/iommu/sw64/iommu_v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/sw64/iommu_v2.c b/drivers/iommu/sw64/iommu_v2.c index f3e19e524210..4a8b576c2530 100644 --- a/drivers/iommu/sw64/iommu_v2.c +++ b/drivers/iommu/sw64/iommu_v2.c @@ -1569,7 +1569,7 @@ sunway_iommu_iova_to_phys(struct iommu_domain *dom, dma_addr_t iova) return 0; paddr &= ~PTE_FLAGS_MASK; - paddr += iova & PAGE_MASK; + paddr += iova & ~PAGE_MASK; return paddr; } -- Gitee From fa1acbc183fb0c2752078647db7b81aa7b99f0a9 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Fri, 8 Dec 2023 17:22:31 +0800 Subject: [PATCH 13/24] anolis: sw64: pci: synchronize the OEM table ID of MCFG with BIOS ANBZ: #4688 Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/acpi/pci_mcfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c index 98bbb01981c5..667eb2d65432 100644 --- a/drivers/acpi/pci_mcfg.c +++ b/drivers/acpi/pci_mcfg.c @@ -198,7 +198,7 @@ static struct mcfg_fixup mcfg_quirks[] = { #ifdef CONFIG_SW64 #define _SW64_ECAM_QUIRK(rev, seg) \ - { "SUNWAY", "SUNWAY. ", rev, seg, MCFG_BUS_ANY, &sw64_pci_ecam_ops } + { "SUNWAY", "MCFG", rev, seg, MCFG_BUS_ANY, &sw64_pci_ecam_ops } #define SW64_ECAM_QUIRK(rev, node) _SW64_ECAM_QUIRK(rev, node * 8 + 0),\ _SW64_ECAM_QUIRK(rev, node * 8 + 1),\ _SW64_ECAM_QUIRK(rev, node * 8 + 2),\ -- Gitee From 8beece4cd3aaf61c08b48de47737d6affd4ed764 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 6 Dec 2023 14:18:51 +0800 Subject: [PATCH 14/24] anolis: sw64: smp: modify function smp_rcb_init() to receive base address ANBZ: #4688 We can pass the base address of smp_rcb via firmware instead of hardcoding it. For the convenience of receiving the base address passed by the firmware, this commit modify the function smp_rcb_init(). Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/smp.h | 2 +- arch/sw_64/kernel/smp.c | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/sw_64/include/asm/smp.h b/arch/sw_64/include/asm/smp.h index 3a2fcf62b30c..103f16ca64a7 100644 --- a/arch/sw_64/include/asm/smp.h +++ b/arch/sw_64/include/asm/smp.h @@ -43,7 +43,7 @@ struct smp_rcb_struct { }; #define INIT_SMP_RCB ((struct smp_rcb_struct *) __va(0x820000UL)) - +extern void __init smp_rcb_init(struct smp_rcb_struct *smp_rcb_base_addr); #ifdef GENERATING_ASM_OFFSETS #define raw_smp_processor_id() (0) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 6d1aab4be1c0..8df4a200a422 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -20,7 +20,7 @@ #include "proto.h" -struct smp_rcb_struct *smp_rcb; +struct smp_rcb_struct *smp_rcb = NULL; extern struct cpuinfo_sw64 cpu_data[NR_CPUS]; @@ -167,9 +167,12 @@ static void __init process_nr_cpu_ids(void) nr_cpu_ids = num_possible_cpus(); } -void __init smp_rcb_init(void) +void __init smp_rcb_init(struct smp_rcb_struct *smp_rcb_base_addr) { - smp_rcb = INIT_SMP_RCB; + if (smp_rcb != NULL) + return; + + smp_rcb = smp_rcb_base_addr; memset(smp_rcb, 0, sizeof(struct smp_rcb_struct)); /* Setup SMP_RCB fields that uses to activate secondary CPU */ smp_rcb->restart_entry = __smp_callin; @@ -203,7 +206,7 @@ void __init setup_smp(void) pr_info("Detected %u possible CPU(s), %u CPU(s) are present\n", nr_cpu_ids, num_present_cpus()); - smp_rcb_init(); + smp_rcb_init(INIT_SMP_RCB); } /* * Called by smp_init prepare the secondaries -- Gitee From d7dbe5605b335ea6f801f84e1dd224ac3482040c Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 6 Dec 2023 15:39:01 +0800 Subject: [PATCH 15/24] anolis: sw64: smp: add new structure to record rcid information ANBZ: #4688 The SW CINTC in ACPI MADT table of SW64 include some core related information. To record this information, a new structure named rcid_information has been added. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/smp.h | 22 ++++++++++++ arch/sw_64/kernel/smp.c | 68 ++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/arch/sw_64/include/asm/smp.h b/arch/sw_64/include/asm/smp.h index 103f16ca64a7..590d4391bdea 100644 --- a/arch/sw_64/include/asm/smp.h +++ b/arch/sw_64/include/asm/smp.h @@ -58,6 +58,11 @@ extern int __cpu_to_rcid[NR_CPUS]; #define cpu_to_rcid(cpu) __cpu_to_rcid[cpu] #define cpu_physical_id(cpu) __cpu_to_rcid[cpu] +static inline void set_rcid_map(unsigned int logical, int rcid) +{ + __cpu_to_rcid[logical] = rcid; +} + extern unsigned long tidle_pcb[NR_CPUS]; extern void arch_send_call_function_single_ipi(int cpu); extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); @@ -67,6 +72,23 @@ int __cpu_disable(void); void __cpu_die(unsigned int cpu); #endif /* CONFIG_HOTPLUG_CPU */ +struct rcid_infomation { + unsigned long thread_bits : 8; /* which thread */ + unsigned long thread_shift : 8; + unsigned long core_bits : 8; /* which core */ + unsigned long core_shift : 8; + unsigned long domain_bits : 8; /* which node */ + unsigned long domain_shift : 8; + unsigned long initialized : 1; +}; + +extern struct rcid_infomation rcid_info; +extern void rcid_infomation_init(int core_version); + +extern int get_core_id_from_rcid(int rcid); +extern int get_thread_id_from_rcid(int rcid); +extern int get_domain_id_from_rcid(int rcid); + #else /* CONFIG_SMP */ #define hard_smp_processor_id() 0 #define smp_call_function_on_cpu(func, info, wait, cpu) ({ 0; }) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 8df4a200a422..3e0d6a980e52 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -45,9 +45,18 @@ enum ipi_message_type { int smp_num_cpus = 1; /* Number that came online. */ EXPORT_SYMBOL(smp_num_cpus); +struct rcid_infomation rcid_info = { 0 }; + #define send_sleep_interrupt(cpu) send_ipi((cpu), II_SLEEP) #define send_wakeup_interrupt(cpu) send_ipi((cpu), II_WAKE) +enum core_version { + CORE_VERSION_NONE = 0, + CORE_VERSION_C3B = 1, + CORE_VERSION_C4 = 2, + CORE_VERSION_RESERVED = 3 /* 3 and greater are reserved */ +}; + /* * Where secondaries begin a life of C. */ @@ -208,6 +217,65 @@ void __init setup_smp(void) smp_rcb_init(INIT_SMP_RCB); } + +void rcid_infomation_init(int core_version) +{ + if (rcid_info.initialized) + return; + + switch (core_version) { + case CORE_VERSION_C3B: + rcid_info.thread_bits = 1; + rcid_info.thread_shift = 31; + rcid_info.core_bits = 5; + rcid_info.core_shift = 0; + rcid_info.domain_bits = 2; + rcid_info.domain_shift = 5; + break; + case CORE_VERSION_C4: + rcid_info.thread_bits = 1; + rcid_info.thread_shift = 8; + rcid_info.core_bits = 6; + rcid_info.core_shift = 0; + rcid_info.domain_bits = 2; + rcid_info.domain_shift = 12; + break; + default: + rcid_info.initialized = 0; + return; + } + + rcid_info.initialized = 1; +} + +static int get_rcid_field(int rcid, unsigned int shift, unsigned int bits) +{ + unsigned int h, l; + + if (WARN_ON_ONCE(!rcid_info.initialized)) + return -1; + + h = shift + bits - 1; + l = shift; + + return (rcid & GENMASK(h, l)) >> shift; +} + +int get_core_id_from_rcid(int rcid) +{ + return get_rcid_field(rcid, rcid_info.core_shift, rcid_info.core_bits); +} + +int get_thread_id_from_rcid(int rcid) +{ + return get_rcid_field(rcid, rcid_info.thread_shift, rcid_info.thread_bits); +} + +int get_domain_id_from_rcid(int rcid) +{ + return get_rcid_field(rcid, rcid_info.domain_shift, rcid_info.domain_bits); +} + /* * Called by smp_init prepare the secondaries */ -- Gitee From 1cd6cf457d31f3ae9576ebc458f02c2008b8f2b7 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 6 Dec 2023 16:40:55 +0800 Subject: [PATCH 16/24] anolis: sw64: acpi: add ACPI-style structures for SW CINTC ANBZ: #4688 Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- include/acpi/actbl2.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 8104c262bbae..986cf4a32f65 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -899,6 +899,18 @@ enum acpi_madt_type { ACPI_MADT_TYPE_RESERVED = 28, /* 28 to 0x7F are reserved */ ACPI_MADT_TYPE_OEM_RESERVED = 0x80, /* 0x80 to 0xFF are reserved for OEM use */ ACPI_MADT_TYPE_PHYTIUM_2500 = 128 + +#ifdef CONFIG_SW64 + , + /** + * Add for SW64 + * Due to the fact that the interrupt controller structures + * of SW64 have not yet been added to the ACPI specification, + * interrupt controller structure types reserved for OEM are + * used(start from 0x80). + */ + ACPI_MADT_TYPE_SW_CINTC = 0x80, +#endif }; /* @@ -1326,6 +1338,30 @@ struct acpi_madt_oem_data { ACPI_FLEX_ARRAY(u8, oem_data); }; +#ifdef CONFIG_SW64 +/* 0x80: Sunway Core Interrupt Controller (To be added to ACPI spec) */ + +struct acpi_madt_sw_cintc { + struct acpi_subtable_header header; + u8 version; + u8 reserved0; + u32 flags; + u32 reserved1; + u32 hardware_id; + u32 uid; + u64 boot_flag_address; +}; + +/* Values for version field above */ + +enum acpi_madt_sw_cintc_version { + ACPI_MADT_SW_CINTC_VERSION_NONE = 0, + ACPI_MADT_SW_CINTC_VERSION_V1 = 1, + ACPI_MADT_SW_CINTC_VERSION_V2 = 2, + ACPI_MADT_SW_CINTC_VERSION_RESERVED = 3 /* 3 and greater are reserved */ +}; +#endif + /* * Common flags fields for MADT subtables */ -- Gitee From 56baf76a81ba594f2b5fc8105e338df0ee2a1da4 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 6 Dec 2023 17:20:08 +0800 Subject: [PATCH 17/24] anolis: sw64: acpi: support MADT entry print for SW CINTC ANBZ: #4688 Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/acpi/tables.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 94cb47d740c9..6c3a5ab15750 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -230,6 +230,17 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) } break; +#ifdef CONFIG_SW64 + case ACPI_MADT_TYPE_SW_CINTC: + { + struct acpi_madt_sw_cintc *p = + (struct acpi_madt_sw_cintc *)header; + pr_debug("SW CINTC (version[%u] flags[0x%x] hardware_id[0x%x])\n", + p->version, p->flags, p->hardware_id); + } + break; +#endif + default: pr_warn("Found unsupported MADT entry (type = 0x%x)\n", header->type); -- Gitee From 84537cbbe6972380f9ff2e6e8f062c441ad431ff Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 6 Dec 2023 17:22:36 +0800 Subject: [PATCH 18/24] anolis: sw64: acpi: parse SW CINTC for SMP initialization ANBZ: #4688 We create SW CINTC in MADT table for SW64. This type of table entry can carry some core related information, which can help SMP initialization and reduce hard coding in the kernel of SW64. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/smp.h | 24 +++-- arch/sw_64/kernel/acpi.c | 183 +++++++++++++++++++++++++++++++++-- 2 files changed, 193 insertions(+), 14 deletions(-) diff --git a/arch/sw_64/include/asm/smp.h b/arch/sw_64/include/asm/smp.h index 590d4391bdea..0ca636b29dde 100644 --- a/arch/sw_64/include/asm/smp.h +++ b/arch/sw_64/include/asm/smp.h @@ -28,12 +28,6 @@ read_vpcr(void) return __r0; } -#ifdef CONFIG_SMP -/* SMP initialization hook for setup_arch */ -void __init setup_smp(void); - -#include - /* smp reset control block */ struct smp_rcb_struct { void (*restart_entry)(unsigned long args); @@ -42,6 +36,12 @@ struct smp_rcb_struct { unsigned long init_done; }; +#ifdef CONFIG_SMP +/* SMP initialization hook for setup_arch */ +void __init setup_smp(void); + +#include + #define INIT_SMP_RCB ((struct smp_rcb_struct *) __va(0x820000UL)) extern void __init smp_rcb_init(struct smp_rcb_struct *smp_rcb_base_addr); @@ -96,6 +96,18 @@ extern int get_domain_id_from_rcid(int rcid); extern int __cpu_to_rcid[NR_CPUS]; #define cpu_to_rcid(cpu) __cpu_to_rcid[0] #define cpu_physical_id(cpu) __cpu_to_rcid[0] + +static inline void smp_rcb_init(struct smp_rcb_struct *smp_rcb_base_addr) { } + +static inline void set_rcid_map(unsigned int logical, int rcid) +{ + __cpu_to_rcid[0] = 0; +} + +static inline void rcid_infomation_init(int core_version) { } +static inline int get_core_id_from_rcid(int rcid) { return 0; } +static inline int get_thread_id_from_rcid(int rcid) { return 0; } +static inline int get_domain_id_from_rcid(int rcid) { return 0; } #endif /* CONFIG_SMP */ #define NO_PROC_ID (-1) diff --git a/arch/sw_64/kernel/acpi.c b/arch/sw_64/kernel/acpi.c index 9779d4bdea0d..4c1243c95c95 100644 --- a/arch/sw_64/kernel/acpi.c +++ b/arch/sw_64/kernel/acpi.c @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -21,10 +22,24 @@ EXPORT_SYMBOL(acpi_pci_disabled); static bool param_acpi_on __initdata; static bool param_acpi_off __initdata; +static unsigned int possible_cores = 1; /* number of possible cores(at least boot core) */ +static unsigned int present_cores = 1; /* number of present cores(at least boot core) */ +static unsigned int disabled_cores; /* number of disabled cores */ + int acpi_strict; u64 arch_acpi_wakeup_start; u64 acpi_saved_sp_s3; +#define SW_CINTC_FLAG_ENABLED ACPI_MADT_ENABLED /* 0x1 */ +#define SW_CINTC_FLAG_ONLINE_CAPABLE 0x2 /* hotplug capable */ +#define SW_CINTC_FLAG_HT_CAPABLE 0x4 /* hyper thread capable */ +#define SW_CINTC_FLAG_HT_ENABLED 0x8 /* hyper thread enabled */ + +#define is_core_enabled(flags) ((flags) & SW_CINTC_FLAG_ENABLED) +#define is_core_online_capable(flags) ((flags) & SW_CINTC_FLAG_ONLINE_CAPABLE) +#define is_core_ht_capable(flags) ((flags) & SW_CINTC_FLAG_HT_CAPABLE) +#define is_core_ht_enabled(flags) ((flags) & SW_CINTC_FLAG_HT_ENABLED) + #define MAX_LOCAL_APIC 256 #define PREFIX "ACPI: " @@ -271,7 +286,7 @@ int acpi_unmap_cpu(int cpu) set_cpuid_to_node(cpu, NUMA_NO_NODE); #endif set_cpu_present(cpu, false); - num_processors--; + present_cores--; pr_info("cpu%d hot remove!\n", cpu); @@ -280,6 +295,143 @@ int acpi_unmap_cpu(int cpu) EXPORT_SYMBOL(acpi_unmap_cpu); #endif /* CONFIG_ACPI_HOTPLUG_CPU */ +static bool __init is_rcid_duplicate(int rcid) +{ + unsigned int i; + + for (i = 0; (i < possible_cores) && (i < NR_CPUS); i++) { + if (cpu_to_rcid(i) == rcid) + return true; + } + + return false; +} + +static int __init +setup_rcid_and_core_mask(struct acpi_madt_sw_cintc *sw_cintc) +{ + unsigned int logical_core_id; + int rcid = sw_cintc->hardware_id; + + /** + * The initial value of nr_cpu_ids is NR_CPUS, which + * represents the maximum number of cores in the system. + */ + if (possible_cores >= nr_cpu_ids) { + pr_err(PREFIX "Max core num [%u] reached, core [0x%x] ignored." + " Please check the firmware or CONFIG_NR_CPUS!\n", + nr_cpu_ids, rcid); + return -ENODEV; + } + + /* The rcid of each core is unique */ + if (is_rcid_duplicate(rcid)) { + pr_err(PREFIX "Duplicate core [0x%x] in MADT." + " Please check the firmware!\n", rcid); + return -EINVAL; + } + + /* We can never disable the boot core, whose rcid is 0 */ + if ((rcid == 0) && !is_core_enabled(sw_cintc->flags)) { + pr_err(PREFIX "Boot core disabled in MADT." + " Please check the firmware!\n"); + return -EINVAL; + } + + /* Online capable makes core possible */ + if (!is_core_enabled(sw_cintc->flags) && \ + !is_core_online_capable(sw_cintc->flags)) { + disabled_cores++; + return 0; + } + + rcid_infomation_init(sw_cintc->version); + + /* The logical core ID of the boot core must be 0 */ + if (rcid == 0) + logical_core_id = 0; + else + logical_core_id = possible_cores++; + + set_rcid_map(logical_core_id, rcid); + set_cpu_possible(logical_core_id, true); + store_cpu_data(logical_core_id); + + /** + * Whether the core will finally be online + * depends on two conditions: + * 1. core is enabled via firmware + * 2. core is not disabled by cmdline param(offline) + */ + if (is_core_enabled(sw_cintc->flags) && \ + !cpumask_test_cpu(logical_core_id, &cpu_offline)) { + set_cpu_present(logical_core_id, true); + if (logical_core_id != 0) + present_cores++; + } + + return 0; +} + +static int __init acpi_parse_sw_cintc(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_sw_cintc *sw_cintc = NULL; + struct smp_rcb_struct *smp_rcb_base_addr = NULL; + int ret; + + sw_cintc = (struct acpi_madt_sw_cintc *)header; + if (BAD_MADT_ENTRY(sw_cintc, end)) { + pr_err(PREFIX "SW CINTC entry error." + " Please check the firmware!\n"); + return -EINVAL; + } + + acpi_table_print_madt_entry(&header->common); + + ret = setup_rcid_and_core_mask(sw_cintc); + if (ret) + return ret; + + /** + * We use smp_rcb to help SMP boot. Its base + * address is hold in the MADT entry of SW CINTC. + */ + smp_rcb_base_addr = __va(sw_cintc->boot_flag_address); + smp_rcb_init(smp_rcb_base_addr); + + return 0; +} + +static int __init acpi_process_madt_sw_cintc(void) +{ + int logical_core, ret; + + /* Clean the map from logical core ID to physical core ID */ + for (logical_core = 0; logical_core < NR_CPUS; ++logical_core) + set_rcid_map(logical_core, -1); + + /* Clean core mask */ + init_cpu_possible(cpu_none_mask); + init_cpu_present(cpu_none_mask); + + /* Parse SW CINTC entries one by one */ + ret = acpi_table_parse_madt(ACPI_MADT_TYPE_SW_CINTC, + acpi_parse_sw_cintc, 0); + if (ret < 0) + return ret; + +#if NR_CPUS > 1 + /* It's time to update nr_cpu_ids */ + nr_cpu_ids = possible_cores; +#endif + + pr_info(PREFIX "Detected %u possible CPU(s), %u CPU(s) are present\n", + possible_cores, present_cores); + + return 0; +} + void __init acpi_boot_table_init(void) { /** @@ -293,12 +445,27 @@ void __init acpi_boot_table_init(void) /* * If acpi_disabled, bail out */ - if (!acpi_disabled) { - pr_warn("Currently, ACPI is an experimental feature!\n"); - if (acpi_table_init()) { - pr_err("Failed to init ACPI tables\n"); - disable_acpi(); - } else - pr_info("Successfully parsed ACPI table\n"); + if (acpi_disabled) + return; + + pr_warn("Currently, ACPI is an experimental feature!\n"); + if (acpi_table_init()) { + pr_err("Failed to init ACPI tables\n"); + disable_acpi(); + return; + } else + pr_info("Successfully parsed ACPI table\n"); + + /** + * Process SW64 Core Interrupt Controller(SW CINTC) in MADT table. + * No initialization of the interrupt controller here, mainly used + * to establish the mapping from logical core IDs to physical core + * IDs and set cpu mask. + */ + if (acpi_process_madt_sw_cintc()) { + /* May be fatal error in MADT table */ + pr_err("Failed to parse SW CINTC\n"); + disable_acpi(); + return; } } -- Gitee From d8efc0ba495c133c854f46fd9c8efc3f326ce1e8 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Fri, 8 Dec 2023 17:12:39 +0800 Subject: [PATCH 19/24] anolis: sw64: smp: suppress function setup_smp() when ACPI enabled ANBZ: #4688 When ACPI enabled, we setup rcid and cpu mask via SW CINTC entry in ACPI MADT table. At this point, function setup_smp() is no longer needed. This function is only used to keep compatibility with legacy codes. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/setup.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 412710b17a80..87324cd2268b 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -839,11 +839,13 @@ setup_arch(char **cmdline_p) /* Parse the ACPI tables for possible boot-time configuration */ acpi_boot_table_init(); + if (acpi_disabled) { #ifdef CONFIG_SMP - setup_smp(); + setup_smp(); #else - store_cpu_data(0); + store_cpu_data(0); #endif + } sw64_numa_init(); -- Gitee From 70c11ae366f946af5b05f54e78631883588aa87e Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 27 Dec 2023 17:03:25 +0800 Subject: [PATCH 20/24] anolis: sw64: pci: fix compile error when CONFIG_ACPI=n ANBZ: #4688 Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/pci/controller/pci-sunway.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/controller/pci-sunway.c b/drivers/pci/controller/pci-sunway.c index e9314e4cb86e..32e850f63a32 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -598,12 +598,12 @@ static void __iomem *sw64_pcie_map_bus(struct pci_bus *bus, return cfg_iobase; } -#ifdef CONFIG_ACPI int sw64_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { return map_irq(dev, slot, pin); } +#ifdef CONFIG_ACPI static void setup_intx_irqs(struct pci_controller *hose) { unsigned long int_conf, node, val_node; -- Gitee From 781788147ee21fe967c2412f9a228e1cf21297f8 Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Wed, 27 Sep 2023 13:47:48 +0800 Subject: [PATCH 21/24] anolis: USB: xHCI: fix resume issue of some ZHAOXIN hosts ANBZ: #4688 On ZHAOXIN ZX-100 and ZX-200 project, xHCI can't work normally after resume from system Sx state. To fix this issue, when resume from system Sx state, reinitialize xHCI instead of restore. So, Add XHCI_RESET_ON_RESUME quirk for ZX-100 or ZX-200 to fix issue of resuming from system Sx state. Signed-off-by: Zheng Chongzhen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/usb/host/xhci-pci.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 5e6521323c3f..0bedd0c06e7c 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -476,6 +476,13 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) xhci->quirks |= XHCI_RESET_ON_RESUME; xhci->quirks |= XHCI_ZERO_64B_REGS; } + + if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) { + if (pdev->device == 0x9202 || + pdev->device == 0x9203) + xhci->quirks |= XHCI_RESET_ON_RESUME; + } + if (pdev->vendor == PCI_VENDOR_ID_VIA) xhci->quirks |= XHCI_RESET_ON_RESUME; -- Gitee From c759c32195e02dd91ab6dad0b1cdfed68c766dfa Mon Sep 17 00:00:00 2001 From: Tang Jinyang Date: Tue, 26 Dec 2023 17:04:43 +0800 Subject: [PATCH 22/24] anolis: sw64: fix macro definition compilation error ANBZ: #4688 Signed-off-by: Tang Jinyang Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/csr.h | 34 +++++--- arch/sw_64/kernel/irq_sw64.c | 8 +- arch/sw_64/kernel/match.c | 46 +++++----- arch/sw_64/kernel/ptrace.c | 114 ++++++++++++------------- arch/sw_64/kernel/smp.c | 8 +- arch/sw_64/kernel/vdso/vgettimeofday.c | 2 +- arch/sw_64/kvm/emulate.c | 4 +- arch/sw_64/kvm/kvm_core4.c | 6 +- arch/sw_64/kvm/mmio.c | 2 +- arch/sw_64/kvm/mmu.c | 10 +-- drivers/clocksource/timer-sw64.c | 4 +- 11 files changed, 122 insertions(+), 116 deletions(-) diff --git a/arch/sw_64/include/asm/csr.h b/arch/sw_64/include/asm/csr.h index 0610384208a4..dc400069a771 100644 --- a/arch/sw_64/include/asm/csr.h +++ b/arch/sw_64/include/asm/csr.h @@ -61,30 +61,36 @@ #ifdef CONFIG_HAVE_CSRRW -#define read_csr(x) \ - ({ unsigned long __val; \ - __asm__ __volatile__("csrr %0,%1" : "=r"(__val) : "i"(x)); \ - __val; }) - -#define write_csr(x, y) \ - ({ __asm__ __volatile__("csrw %0,%1" ::"r"(x), "i"(y)); }) +#ifndef __ASSEMBLY__ +static inline unsigned long sw64_read_csr(unsigned long x) +{ + unsigned long __val; + __asm__ __volatile__("csrr %0,%1" : "=r"(__val) : "i"(x)); + return __val; +} -#define write_csr_imb(x, y) \ - ({ __asm__ __volatile__("csrw %0,%1; imemb" ::"r"(x), "i"(y)); }) +static inline void sw64_write_csr(unsigned long x, unsigned long y) +{ + __asm__ __volatile__("csrw %0,%1" ::"r"(x), "i"(y)); +} +static inline void sw64_write_csr_imb(unsigned long x, unsigned long y) +{ + __asm__ __volatile__("csrw %0,%1; imemb" ::"r"(x), "i"(y)); +} -#ifndef __ASSEMBLY__ #include static inline void update_ptbr_sys(unsigned long ptbr) { imemb(); - write_csr_imb(ptbr, CSR_PTBR_SYS); + sw64_write_csr_imb(ptbr, CSR_PTBR_SYS); } + #endif #else -#define read_csr(x) (0) -#define write_csr(x, y) do { } while (0) -#define write_csr_imb(x, y) do { } while (0) +#define sw64_read_csr(x) (0) +#define sw64_write_csr(x, y) do { } while (0) +#define sw64_write_csr_imb(x, y) do { } while (0) #ifndef __ASSEMBLY__ static inline void update_ptbr_sys(unsigned long ptbr) diff --git a/arch/sw_64/kernel/irq_sw64.c b/arch/sw_64/kernel/irq_sw64.c index 989d55ee1b1b..03aef463ec05 100644 --- a/arch/sw_64/kernel/irq_sw64.c +++ b/arch/sw_64/kernel/irq_sw64.c @@ -17,10 +17,10 @@ init_IRQ(void) * (as is the case with RAWHIDE, at least). */ if (is_in_host()) { - write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI0_INTEN); - write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI1_INTEN); - write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI2_INTEN); - write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI3_INTEN); + sw64_write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI0_INTEN); + sw64_write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI1_INTEN); + sw64_write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI2_INTEN); + sw64_write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI3_INTEN); } wrent(entInt, 0); diff --git a/arch/sw_64/kernel/match.c b/arch/sw_64/kernel/match.c index 3926391270da..9ecd5d838846 100644 --- a/arch/sw_64/kernel/match.c +++ b/arch/sw_64/kernel/match.c @@ -97,14 +97,14 @@ write_da_match(void *i) { unsigned long dc_ctl; - write_csr(da_match_cf1, CSR_DA_MATCH); - write_csr(da_match_cf2, CSR_DA_MASK); - dc_ctl = read_csr(CSR_DC_CTLP); + sw64_write_csr(da_match_cf1, CSR_DA_MATCH); + sw64_write_csr(da_match_cf2, CSR_DA_MASK); + dc_ctl = sw64_read_csr(CSR_DC_CTLP); dc_ctl &= ~((0x1UL << 3) | (0x3UL << DA_MATCH_EN_S) | (0x1UL << DAV_MATCH_EN_S) | (0x1UL << DPM_MATCH_EN_S) | (0x3UL << DPM_MATCH)); dc_ctl |= da_match_cf3; - write_csr(dc_ctl, CSR_DC_CTLP); + sw64_write_csr(dc_ctl, CSR_DC_CTLP); } static void @@ -112,13 +112,13 @@ write_dv_match(void *i) { unsigned long dc_ctl; - write_csr(dv_match_cf1, CSR_DV_MATCH); - write_csr(dv_match_cf2, CSR_DV_MASK); - dc_ctl = read_csr(CSR_DC_CTLP); + sw64_write_csr(dv_match_cf1, CSR_DV_MATCH); + sw64_write_csr(dv_match_cf2, CSR_DV_MASK); + dc_ctl = sw64_read_csr(CSR_DC_CTLP); dc_ctl &= ~((0x1UL << DAV_MATCH_EN_S) | (0x1UL << DPM_MATCH_EN_S) | (0x3UL << DPM_MATCH)); dc_ctl |= ((0x1UL << DV_MATCH_EN_S) | dv_match_cf3); - write_csr(dc_ctl, CSR_DC_CTLP); + sw64_write_csr(dc_ctl, CSR_DC_CTLP); } static void @@ -126,26 +126,26 @@ write_dav_match(void *i) { unsigned long dc_ctl; - write_csr(dav_match_cf1, CSR_DA_MATCH); - write_csr(dav_match_cf2, CSR_DA_MASK); - write_csr(dav_match_cf3, CSR_DV_MATCH); - write_csr(dav_match_cf4, CSR_DV_MASK); - dc_ctl = read_csr(CSR_DC_CTLP); + sw64_write_csr(dav_match_cf1, CSR_DA_MATCH); + sw64_write_csr(dav_match_cf2, CSR_DA_MASK); + sw64_write_csr(dav_match_cf3, CSR_DV_MATCH); + sw64_write_csr(dav_match_cf4, CSR_DV_MASK); + dc_ctl = sw64_read_csr(CSR_DC_CTLP); dc_ctl &= ~((0x1UL << 3) | (0x3UL << DA_MATCH_EN_S) | (0x1UL << DPM_MATCH_EN_S) | (0x3UL << DPM_MATCH)); dc_ctl |= ((0x1UL << DV_MATCH_EN_S) | (0x1UL << DAV_MATCH_EN_S) | dav_match_cf5); - write_csr(dc_ctl, CSR_DC_CTLP); + sw64_write_csr(dc_ctl, CSR_DC_CTLP); } static void write_ia_match(void *i) { ia_match_cf1 |= (0x1UL << IA_MATCH_EN_S); - write_csr_imb(ia_match_cf1, CSR_IA_MATCH); - write_csr_imb(ia_match_cf2, CSR_IA_MASK); - write_csr(((0x3ffUL << 18) | ia_match_cf3), CSR_IA_VPNMATCH); - write_csr(((0x3ffUL << 18) | ia_match_cf4), CSR_IA_UPNMATCH); + sw64_write_csr_imb(ia_match_cf1, CSR_IA_MATCH); + sw64_write_csr_imb(ia_match_cf2, CSR_IA_MASK); + sw64_write_csr(((0x3ffUL << 18) | ia_match_cf3), CSR_IA_VPNMATCH); + sw64_write_csr(((0x3ffUL << 18) | ia_match_cf4), CSR_IA_UPNMATCH); } static void @@ -153,12 +153,12 @@ write_iv_match(void *i) { unsigned long ia_match_tmp; - ia_match_tmp = read_csr(CSR_IA_MATCH); + ia_match_tmp = sw64_read_csr(CSR_IA_MATCH); ia_match_tmp &= ~(0x1UL << IV_PM_EN_S); ia_match_tmp |= ((((iv_match_cf2 >> IV_PM_EN_S) & 0x1) << IV_PM_EN_S) | (iv_match_cf2 & 0x3) | (0x1UL << IV_MATCH_EN_S)); - write_csr_imb(iv_match_cf1, CSR_IV_MATCH); - write_csr_imb(ia_match_tmp, CSR_IA_MATCH); + sw64_write_csr_imb(iv_match_cf1, CSR_IV_MATCH); + sw64_write_csr_imb(ia_match_tmp, CSR_IA_MATCH); } static void @@ -166,8 +166,8 @@ write_ida_match(void *i) { ida_match_cf1 |= (0x1UL << IDA_MATCH_EN_S); - write_csr(ida_match_cf1, CSR_IDA_MATCH); - write_csr(ida_match_cf2, CSR_IDA_MASK); + sw64_write_csr(ida_match_cf1, CSR_IDA_MATCH); + sw64_write_csr(ida_match_cf2, CSR_IDA_MASK); } static ssize_t da_match_set(struct file *file, const char __user *user_buf, diff --git a/arch/sw_64/kernel/ptrace.c b/arch/sw_64/kernel/ptrace.c index 070e27ee2567..0af3d35163f9 100644 --- a/arch/sw_64/kernel/ptrace.c +++ b/arch/sw_64/kernel/ptrace.c @@ -545,49 +545,49 @@ int do_match(unsigned long address, unsigned long mmcsr, long cause, struct pt_r if (!(current->ptrace & PT_PTRACED)) { pr_notice(" pid %d %s not be ptraced, return\n", current->pid, current->comm); if (mmcsr == MMCSR__DA_MATCH) { - match_ctl = read_csr(CSR_DC_CTLP); + match_ctl = sw64_read_csr(CSR_DC_CTLP); match_ctl &= ~(0x3UL << DA_MATCH_EN_S); - write_csr(match_ctl, CSR_DC_CTLP); - write_csr(0, CSR_DA_MATCH); // clear da_match + sw64_write_csr(match_ctl, CSR_DC_CTLP); + sw64_write_csr(0, CSR_DA_MATCH); // clear da_match task_thread_info(current)->pcb.match_ctl &= ~0x1; task_thread_info(current)->pcb.da_match = 0; } if (mmcsr == MMCSR__DV_MATCH) { - match_ctl = read_csr(CSR_DC_CTLP); + match_ctl = sw64_read_csr(CSR_DC_CTLP); match_ctl &= ~(0x1UL << DV_MATCH_EN_S); - write_csr(match_ctl, CSR_DC_CTLP); - write_csr(0, CSR_DV_MATCH); // clear dv_match + sw64_write_csr(match_ctl, CSR_DC_CTLP); + sw64_write_csr(0, CSR_DV_MATCH); // clear dv_match task_thread_info(current)->pcb.match_ctl &= ~(0x1 << 1); task_thread_info(current)->pcb.dv_match = 0; } if (mmcsr == MMCSR__DAV_MATCH) { - match_ctl = read_csr(CSR_DC_CTLP); + match_ctl = sw64_read_csr(CSR_DC_CTLP); match_ctl &= ~((0x3UL << DA_MATCH_EN_S) | (0x1UL << DV_MATCH_EN_S) | (0x1UL << DAV_MATCH_EN_S)); - write_csr(match_ctl, CSR_DC_CTLP); - write_csr(0, CSR_DA_MATCH); // clear da_match - write_csr(0, CSR_DV_MATCH); // clear dv_match + sw64_write_csr(match_ctl, CSR_DC_CTLP); + sw64_write_csr(0, CSR_DA_MATCH); // clear da_match + sw64_write_csr(0, CSR_DV_MATCH); // clear dv_match task_thread_info(current)->pcb.match_ctl &= ~(0x1 | (0x1 << 1) | (0x1 << 2)); task_thread_info(current)->pcb.da_match = 0; task_thread_info(current)->pcb.dv_match = 0; } if (mmcsr == MMCSR__IA_MATCH) { - ia_match = read_csr(CSR_IA_MATCH); + ia_match = sw64_read_csr(CSR_IA_MATCH); ia_match &= ~((0x1UL << IA_MATCH_EN_S) | (0x7ffffffffffffUL << 2)); - write_csr(ia_match, CSR_IA_MATCH); // clear ia_match + sw64_write_csr(ia_match, CSR_IA_MATCH); // clear ia_match task_thread_info(current)->pcb.match_ctl &= ~(0x1 << 3); task_thread_info(current)->pcb.ia_match = 0; } if (mmcsr == MMCSR__IV_MATCH) { - ia_match = read_csr(CSR_IA_MATCH); + ia_match = sw64_read_csr(CSR_IA_MATCH); ia_match &= ~((0x1UL << IV_MATCH_EN_S) | (0x1UL << IV_PM_EN_S)); - write_csr(ia_match, CSR_IA_MATCH); // clear ia_match - write_csr(0, CSR_IV_MATCH); // clear iv_match + sw64_write_csr(ia_match, CSR_IA_MATCH); // clear ia_match + sw64_write_csr(0, CSR_IV_MATCH); // clear iv_match task_thread_info(current)->pcb.match_ctl &= ~(0x1 << 4); task_thread_info(current)->pcb.ia_match &= ~((0x1UL << IV_MATCH_EN_S) | (0x1UL << IV_PM_EN_S)); task_thread_info(current)->pcb.iv_match = 0; } if (mmcsr == MMCSR__IDA_MATCH) { - write_csr(0, CSR_IDA_MATCH); // clear ida_match + sw64_write_csr(0, CSR_IDA_MATCH); // clear ida_match task_thread_info(current)->pcb.match_ctl &= ~(0x1 << 5); task_thread_info(current)->pcb.ida_match = 0; } @@ -602,54 +602,54 @@ int do_match(unsigned long address, unsigned long mmcsr, long cause, struct pt_r if (mmcsr == MMCSR__DA_MATCH) { info.si_errno = 1; - match_ctl = read_csr(CSR_DC_CTLP); + match_ctl = sw64_read_csr(CSR_DC_CTLP); match_ctl &= ~(0x3UL << DA_MATCH_EN_S); - write_csr(match_ctl, CSR_DC_CTLP); - write_csr(0, CSR_DA_MATCH); // clear da_match + sw64_write_csr(match_ctl, CSR_DC_CTLP); + sw64_write_csr(0, CSR_DA_MATCH); // clear da_match task_thread_info(current)->pcb.match_ctl &= ~0x1; task_thread_info(current)->pcb.da_match = 0; } if (mmcsr == MMCSR__DV_MATCH) { info.si_errno = 2; - match_ctl = read_csr(CSR_DC_CTLP); + match_ctl = sw64_read_csr(CSR_DC_CTLP); match_ctl &= ~(0x1UL << DV_MATCH_EN_S); - write_csr(match_ctl, CSR_DC_CTLP); - write_csr(0, CSR_DV_MATCH); // clear dv_match + sw64_write_csr(match_ctl, CSR_DC_CTLP); + sw64_write_csr(0, CSR_DV_MATCH); // clear dv_match task_thread_info(current)->pcb.match_ctl &= ~(0x1 << 1); task_thread_info(current)->pcb.dv_match = 0; } if (mmcsr == MMCSR__DAV_MATCH) { info.si_errno = 3; - match_ctl = read_csr(CSR_DC_CTLP); + match_ctl = sw64_read_csr(CSR_DC_CTLP); match_ctl &= ~((0x3UL << DA_MATCH_EN_S) | (0x1UL << DV_MATCH_EN_S) | (0x1UL << DAV_MATCH_EN_S)); - write_csr(match_ctl, CSR_DC_CTLP); - write_csr(0, CSR_DA_MATCH); // clear da_match - write_csr(0, CSR_DV_MATCH); // clear dv_match + sw64_write_csr(match_ctl, CSR_DC_CTLP); + sw64_write_csr(0, CSR_DA_MATCH); // clear da_match + sw64_write_csr(0, CSR_DV_MATCH); // clear dv_match task_thread_info(current)->pcb.match_ctl &= ~(0x1 | (0x1 << 1) | (0x1 << 2)); task_thread_info(current)->pcb.da_match = 0; task_thread_info(current)->pcb.dv_match = 0; } if (mmcsr == MMCSR__IA_MATCH) { info.si_errno = 4; - ia_match = read_csr(CSR_IA_MATCH); + ia_match = sw64_read_csr(CSR_IA_MATCH); ia_match &= ~((0x1UL << IA_MATCH_EN_S) | (0x7ffffffffffffUL << 2)); - write_csr(ia_match, CSR_IA_MATCH); // clear ia_match + sw64_write_csr(ia_match, CSR_IA_MATCH); // clear ia_match task_thread_info(current)->pcb.match_ctl &= ~(0x1 << 3); task_thread_info(current)->pcb.ia_match = 0; } if (mmcsr == MMCSR__IV_MATCH) { info.si_errno = 5; - ia_match = read_csr(CSR_IA_MATCH); + ia_match = sw64_read_csr(CSR_IA_MATCH); ia_match &= ~((0x1UL << IV_MATCH_EN_S) | (0x1UL << IV_PM_EN_S)); - write_csr(ia_match, CSR_IA_MATCH); // clear ia_match - write_csr(0, CSR_IV_MATCH); // clear iv_match + sw64_write_csr(ia_match, CSR_IA_MATCH); // clear ia_match + sw64_write_csr(0, CSR_IV_MATCH); // clear iv_match task_thread_info(current)->pcb.match_ctl &= ~(0x1 << 4); task_thread_info(current)->pcb.ia_match &= ~((0x1UL << IV_MATCH_EN_S) | (0x1UL << IV_PM_EN_S)); task_thread_info(current)->pcb.iv_match = 0; } if (mmcsr == MMCSR__IDA_MATCH) { info.si_errno = 6; - write_csr(0, CSR_IDA_MATCH); // clear ida_match + sw64_write_csr(0, CSR_IDA_MATCH); // clear ida_match task_thread_info(current)->pcb.match_ctl &= ~(0x1 << 5); task_thread_info(current)->pcb.ida_match = 0; } @@ -691,39 +691,39 @@ void restore_da_match_after_sched(void) pr_info("Restroe MATCH status, pid: %d\n", current->pid); if (pcb->match_ctl & DA_MATCH) { - write_csr(pcb->da_match, CSR_DA_MATCH); - write_csr(pcb->da_mask, CSR_DA_MASK); + sw64_write_csr(pcb->da_match, CSR_DA_MATCH); + sw64_write_csr(pcb->da_mask, CSR_DA_MASK); match_ctl_mode = (pcb->match_ctl >> 8) & 0x3; - match_ctl = read_csr(CSR_DC_CTLP); + match_ctl = sw64_read_csr(CSR_DC_CTLP); match_ctl &= ~((0x1UL << 3) | (0x3UL << DA_MATCH_EN_S) | (0x1UL << DV_MATCH_EN_S) | (0x1UL << DAV_MATCH_EN_S)); match_ctl |= (match_ctl_mode << DA_MATCH_EN_S) | (0x1UL << DPM_MATCH_EN_S) | (0x3UL << DPM_MATCH); - write_csr(match_ctl, CSR_DC_CTLP); + sw64_write_csr(match_ctl, CSR_DC_CTLP); pr_info("da_match:%#lx da_mask:%#lx match_ctl:%#lx\n", pcb->da_match, pcb->da_mask, match_ctl); } if (pcb->match_ctl & DV_MATCH) { - write_csr(pcb->dv_match, CSR_DV_MATCH); - write_csr(pcb->dv_mask, CSR_DV_MASK); - match_ctl = read_csr(CSR_DC_CTLP); + sw64_write_csr(pcb->dv_match, CSR_DV_MATCH); + sw64_write_csr(pcb->dv_mask, CSR_DV_MASK); + match_ctl = sw64_read_csr(CSR_DC_CTLP); match_ctl &= ~((0x1UL << 3) | (0x3UL << DA_MATCH_EN_S) | (0x1UL << DV_MATCH_EN_S) | (0x1UL << DAV_MATCH_EN_S)); match_ctl |= (0x1UL << DV_MATCH_EN_S) | (0x1UL << DPM_MATCH_EN_S) | (0x3UL << DPM_MATCH); - write_csr(match_ctl, CSR_DC_CTLP); + sw64_write_csr(match_ctl, CSR_DC_CTLP); pr_info("dv_match:%#lx dv_mask:%#lx match_ctl:%#lx\n", pcb->dv_match, pcb->dv_mask, match_ctl); } if (pcb->match_ctl & DAV_MATCH) { - write_csr(pcb->da_match, CSR_DA_MATCH); - write_csr(pcb->da_mask, CSR_DA_MASK); - write_csr(pcb->dv_match, CSR_DV_MATCH); - write_csr(pcb->dv_mask, CSR_DV_MASK); - write_csr(0xfffffffff, CSR_DA_MATCH_MODE); + sw64_write_csr(pcb->da_match, CSR_DA_MATCH); + sw64_write_csr(pcb->da_mask, CSR_DA_MASK); + sw64_write_csr(pcb->dv_match, CSR_DV_MATCH); + sw64_write_csr(pcb->dv_mask, CSR_DV_MASK); + sw64_write_csr(0xfffffffff, CSR_DA_MATCH_MODE); match_ctl_mode = (pcb->match_ctl >> 8) & 0x3; - match_ctl = read_csr(CSR_DC_CTLP); + match_ctl = sw64_read_csr(CSR_DC_CTLP); match_ctl &= ~((0x3UL << DA_MATCH_EN_S) | (0x1UL << DV_MATCH_EN_S) | (0x1UL << DAV_MATCH_EN_S)); match_ctl |= (match_ctl_mode << DA_MATCH_EN_S) | (0x1UL << DV_MATCH_EN_S) | (0x1UL << DAV_MATCH_EN_S) | (0x1UL << DPM_MATCH_EN_S) | (0x3UL << DPM_MATCH); - write_csr(match_ctl, CSR_DC_CTLP); + sw64_write_csr(match_ctl, CSR_DC_CTLP); pr_info("da_match:%#lx da_mask:%#lx dv_match:%#lx dv_mask:%#lx match_ctl:%#lx\n", pcb->da_match, pcb->da_mask, pcb->dv_match, pcb->dv_mask, match_ctl); } @@ -731,27 +731,27 @@ void restore_da_match_after_sched(void) if (pcb->match_ctl & IA_MATCH) { pcb->ia_match |= (0x1UL << IA_MATCH_EN_S) | 0x3; pcb->ia_mask |= 0x3; - write_csr(pcb->ia_match, CSR_IA_MATCH); - write_csr(pcb->ia_mask, CSR_IA_MASK); - vpn = read_csr(CSR_VPCR) >> 44; + sw64_write_csr(pcb->ia_match, CSR_IA_MATCH); + sw64_write_csr(pcb->ia_mask, CSR_IA_MASK); + vpn = sw64_read_csr(CSR_VPCR) >> 44; vpn &= 0x3ff; - upn = read_csr(CSR_UPCR); + upn = sw64_read_csr(CSR_UPCR); upn &= 0x3ff; - write_csr(((0x3ff << 18) | vpn), CSR_IA_VPNMATCH); - write_csr(((0x3ff << 18) | upn), CSR_IA_UPNMATCH); + sw64_write_csr(((0x3ff << 18) | vpn), CSR_IA_VPNMATCH); + sw64_write_csr(((0x3ff << 18) | upn), CSR_IA_UPNMATCH); pr_info("ia_match:%#lx ia_mask:%#lx\n", pcb->ia_match, pcb->ia_mask); } if (pcb->match_ctl & IV_MATCH) { pcb->ia_match |= (0x1UL << IV_MATCH_EN_S) | (0x1UL << IV_PM_EN_S) | 0x3; - write_csr(pcb->ia_match, CSR_IA_MATCH); - write_csr(pcb->iv_match, CSR_IV_MATCH); + sw64_write_csr(pcb->ia_match, CSR_IA_MATCH); + sw64_write_csr(pcb->iv_match, CSR_IV_MATCH); pr_info("ia_match:%#lx iv_match:%#lx\n", pcb->ia_match, pcb->iv_match); } if (pcb->match_ctl & IDA_MATCH) { pcb->ida_match |= (0x1UL << IDA_MATCH_EN_S) | 0x3; pcb->ida_mask |= 0x3; - write_csr(pcb->ida_match, CSR_IDA_MATCH); - write_csr(pcb->ida_mask, CSR_IDA_MASK); + sw64_write_csr(pcb->ida_match, CSR_IDA_MATCH); + sw64_write_csr(pcb->ida_mask, CSR_IDA_MASK); pr_info("ida_match:%#lx ida_mask:%#lx\n", pcb->ida_match, pcb->ida_mask); } } diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 3e0d6a980e52..42450119ea7d 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -81,10 +81,10 @@ void smp_callin(void) /* Set interrupt vector. */ if (is_in_host()) { - write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI0_INTEN); - write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI1_INTEN); - write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI2_INTEN); - write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI3_INTEN); + sw64_write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI0_INTEN); + sw64_write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI1_INTEN); + sw64_write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI2_INTEN); + sw64_write_csr(0xffffffffffffffffUL, CSR_PCIE_MSI3_INTEN); } wrent(entInt, 0); diff --git a/arch/sw_64/kernel/vdso/vgettimeofday.c b/arch/sw_64/kernel/vdso/vgettimeofday.c index 0aa16e988e88..07e023d3d64b 100644 --- a/arch/sw_64/kernel/vdso/vgettimeofday.c +++ b/arch/sw_64/kernel/vdso/vgettimeofday.c @@ -88,7 +88,7 @@ static __always_inline u64 read_longtime(void) #elif defined(CONFIG_SUBARCH_C4) static __always_inline u64 read_longtime(void) { - return read_csr(CSR_SHTCLOCK); + return sw64_read_csr(CSR_SHTCLOCK); } #endif diff --git a/arch/sw_64/kvm/emulate.c b/arch/sw_64/kvm/emulate.c index fc37461b97a0..66e6335d9cce 100644 --- a/arch/sw_64/kvm/emulate.c +++ b/arch/sw_64/kvm/emulate.c @@ -19,8 +19,8 @@ void sw64_decode(struct kvm_vcpu *vcpu, unsigned int insn, struct kvm_run *run) #elif defined(CONFIG_SUBARCH_C4) unsigned long ds_stat, exc_sum; - ds_stat = read_csr(CSR_DS_STAT); - exc_sum = read_csr(CSR_EXC_SUM); + ds_stat = sw64_read_csr(CSR_DS_STAT); + exc_sum = sw64_read_csr(CSR_EXC_SUM); opc = (ds_stat >> 4) & 0x3f; ra = (exc_sum >> 8) & 0x1f; diff --git a/arch/sw_64/kvm/kvm_core4.c b/arch/sw_64/kvm/kvm_core4.c index 08d28a365a3b..3c52b0d7776c 100644 --- a/arch/sw_64/kvm/kvm_core4.c +++ b/arch/sw_64/kvm/kvm_core4.c @@ -25,7 +25,7 @@ static unsigned long shtclock_offset; void update_aptp(unsigned long pgd) { imemb(); - write_csr_imb(pgd, CSR_APTP); + sw64_write_csr_imb(pgd, CSR_APTP); } void kvm_sw64_update_vpn(struct kvm_vcpu *vcpu, unsigned long vpn) @@ -69,7 +69,7 @@ long kvm_sw64_get_vcb(struct file *filp, unsigned long arg) struct kvm_vcpu *vcpu = filp->private_data; if (vcpu->arch.migration_mark) - vcpu->arch.shtclock = read_csr(CSR_SHTCLOCK) + vcpu->arch.shtclock = sw64_read_csr(CSR_SHTCLOCK) + vcpu->arch.vcb.shtclock_offset; if (copy_to_user((void __user *)arg, &(vcpu->arch.vcb), sizeof(struct vcpucb))) return -EINVAL; @@ -88,7 +88,7 @@ long kvm_sw64_set_vcb(struct file *filp, unsigned long arg) if (vcpu->arch.migration_mark) { /* synchronize the longtime of source and destination */ if (vcpu->arch.vcb.soft_cid == 0) - shtclock_offset = vcpu->arch.shtclock - read_csr(CSR_SHTCLOCK); + shtclock_offset = vcpu->arch.shtclock - sw64_read_csr(CSR_SHTCLOCK); vcpu->arch.vcb.shtclock_offset = shtclock_offset; set_timer(vcpu, 200000000); vcpu->arch.migration_mark = 0; diff --git a/arch/sw_64/kvm/mmio.c b/arch/sw_64/kvm/mmio.c index 21ad89722f9a..0bde3406eb89 100644 --- a/arch/sw_64/kvm/mmio.c +++ b/arch/sw_64/kvm/mmio.c @@ -68,7 +68,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, run->mmio.phys_addr = hargs->arg1 & 0xfffffffffffffUL; sw64_decode(vcpu, hargs->arg2, run); #elif defined(CONFIG_SUBARCH_C4) - run->mmio.phys_addr = read_csr(CSR_DVA) & 0xfffffffffffffUL; + run->mmio.phys_addr = sw64_read_csr(CSR_DVA) & 0xfffffffffffffUL; sw64_decode(vcpu, 0, run); #endif if (run->mmio.is_write) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index b0b492a4fbff..23e035aa4e6c 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -790,8 +790,8 @@ static int apt_set_pte_fast(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, pmd_t *pmd; pte_t *pte, old_pte; bool logging_active = flags & KVM_APT_FLAG_LOGGING_ACTIVE; - int inv_level = ((read_csr(CSR_AS_INFO)) >> AF_INV_LEVEL_SHIFT) & AF_INV_LEVEL_MASK; - unsigned long inv_hpa = read_csr(CSR_AS_INFO) & AF_ENTRY_ADDR_MASK; + int inv_level = ((sw64_read_csr(CSR_AS_INFO)) >> AF_INV_LEVEL_SHIFT) & AF_INV_LEVEL_MASK; + unsigned long inv_hpa = sw64_read_csr(CSR_AS_INFO) & AF_ENTRY_ADDR_MASK; VM_BUG_ON(logging_active && !cache); @@ -1148,7 +1148,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_gpa, unsigned long as_info, access_type; unsigned int vma_shift; - as_info = read_csr(CSR_AS_INFO); + as_info = sw64_read_csr(CSR_AS_INFO); access_type = (as_info >> AF_ACCESS_TYPE_SHIFT) & AF_ACCESS_TYPE_MASK; write_fault = kvm_is_write_fault(access_type); exec_fault = kvm_is_exec_fault(access_type); @@ -1352,13 +1352,13 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) int ret, idx; - as_info = read_csr(CSR_AS_INFO); + as_info = sw64_read_csr(CSR_AS_INFO); access_type = (as_info >> AF_ACCESS_TYPE_SHIFT) & AF_ACCESS_TYPE_MASK; inv_level = (as_info >> AF_INV_LEVEL_SHIFT) & AF_INV_LEVEL_MASK; fault_status = (as_info >> AF_FAULT_STATUS_SHIFT) & AF_FAULT_STATUS_MASK; fault_entry_addr = (as_info & AF_ENTRY_ADDR_MASK) >> 3; - fault_gpa = read_csr(CSR_EXC_GPA); + fault_gpa = sw64_read_csr(CSR_EXC_GPA); idx = srcu_read_lock(&vcpu->kvm->srcu); gfn = fault_gpa >> PAGE_SHIFT; diff --git a/drivers/clocksource/timer-sw64.c b/drivers/clocksource/timer-sw64.c index a124b6d8fed9..615e8a2ed63a 100644 --- a/drivers/clocksource/timer-sw64.c +++ b/drivers/clocksource/timer-sw64.c @@ -19,7 +19,7 @@ #if defined(CONFIG_SUBARCH_C4) static u64 read_longtime(struct clocksource *cs) { - return read_csr(CSR_SHTCLOCK); + return sw64_read_csr(CSR_SHTCLOCK); } static struct clocksource clocksource_longtime = { @@ -34,7 +34,7 @@ static struct clocksource clocksource_longtime = { static u64 notrace read_sched_clock(void) { - return read_csr(CSR_SHTCLOCK); + return sw64_read_csr(CSR_SHTCLOCK); } void __init sw64_setup_clocksource(void) -- Gitee From fec7add2c691447b620187c2c031f6004c82c5d6 Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Mon, 11 Dec 2023 07:15:22 +0000 Subject: [PATCH 23/24] anolis: sw64: refactor device interrupt domain ANBZ: #4688 Refactor device interrupt domain code to support sw64 interrupt controller redesign. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/hw_irq.h | 2 + arch/sw_64/include/asm/uncore_io_junzhang.h | 2 + arch/sw_64/include/asm/uncore_io_xuelang.h | 2 + drivers/gpio/gpio-sunway.c | 1 + drivers/irqchip/Kconfig | 15 +- drivers/irqchip/Makefile | 4 +- drivers/irqchip/irq-sunway-cpu.c | 5 +- ...-sw64-lpc-intc.c => irq-sunway-lpc-intc.c} | 153 ++++++---- drivers/irqchip/irq-sunway-pintc.c | 287 ++++++++++++++++++ drivers/irqchip/irq-sw64-intc-v2.c | 89 ------ 10 files changed, 396 insertions(+), 164 deletions(-) rename drivers/irqchip/{irq-sw64-lpc-intc.c => irq-sunway-lpc-intc.c} (34%) create mode 100644 drivers/irqchip/irq-sunway-pintc.c delete mode 100644 drivers/irqchip/irq-sw64-intc-v2.c diff --git a/arch/sw_64/include/asm/hw_irq.h b/arch/sw_64/include/asm/hw_irq.h index 3cfc725f7517..e0f8ee91c43a 100644 --- a/arch/sw_64/include/asm/hw_irq.h +++ b/arch/sw_64/include/asm/hw_irq.h @@ -9,6 +9,8 @@ DECLARE_PER_CPU(unsigned long, irq_pmi_count); #define ACTUAL_NR_IRQS NR_IRQS +extern struct irq_domain *mcu_irq_domain; + #ifdef CONFIG_PCI_MSI typedef unsigned int vector_irq_t[PERCPU_MSI_IRQS]; DECLARE_PER_CPU(vector_irq_t, vector_irq); diff --git a/arch/sw_64/include/asm/uncore_io_junzhang.h b/arch/sw_64/include/asm/uncore_io_junzhang.h index 37cfe1fd6807..ac37d186a29f 100644 --- a/arch/sw_64/include/asm/uncore_io_junzhang.h +++ b/arch/sw_64/include/asm/uncore_io_junzhang.h @@ -70,6 +70,8 @@ #define PIUCONFIG0_INIT_VAL 0x38016 +#define DEV_INT_TARGET(phy_cpu) ((((phy_cpu) >> 5) << 7) | ((phy_cpu) & 0x3f)) + /*-----------------------addr-----------------------*/ /* INTPU REG */ enum { diff --git a/arch/sw_64/include/asm/uncore_io_xuelang.h b/arch/sw_64/include/asm/uncore_io_xuelang.h index aeaadec5be16..873f7e86f83b 100644 --- a/arch/sw_64/include/asm/uncore_io_xuelang.h +++ b/arch/sw_64/include/asm/uncore_io_xuelang.h @@ -74,6 +74,8 @@ #define PIUCONFIG0_INIT_VAL 0x38056 +#define DEV_INT_TARGET(phy_cpu) ((((phy_cpu) >> 5) << 6) | ((phy_cpu) & 0x1f)) + /*-----------------------addr-----------------------*/ /* CAB0 REG */ enum { diff --git a/drivers/gpio/gpio-sunway.c b/drivers/gpio/gpio-sunway.c index b9c6848317db..11581dded64f 100644 --- a/drivers/gpio/gpio-sunway.c +++ b/drivers/gpio/gpio-sunway.c @@ -425,6 +425,7 @@ static void sunway_configure_irqs(struct sunway_gpio *gpio, for (i = 0; i < 2; i++) { ct = &irq_gc->chip_types[i]; + ct->chip.name = "GPIO-INT"; ct->chip.irq_ack = irq_gc_ack_set_bit; ct->chip.irq_mask = irq_gc_mask_set_bit; ct->chip.irq_unmask = irq_gc_mask_clr_bit; diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 027df575d57f..9810922df2fd 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -11,20 +11,21 @@ config ARM_GIC select IRQ_DOMAIN_HIERARCHY select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP -config SW64_INTC_V2 - bool "SW64 Interrupt Controller V2" - depends on UNCORE_XUELANG +config SW64_PINTC + bool "SW64 Interrupt Controller" + depends on SW64 default y select GENERIC_IRQ_CHIP select IRQ_DOMAIN help - This enables support for the INTC chip found in SW CHIP3 systems. - The INTC controls devices interrupts and connects them to each - core's local interrupt controller. + This enables support for the pINTC chip found in SW systems. + The PINTC receives all platform devices' interrupts and passes + them to certain core's local interrupt controller for further + interrupt handling. config SW64_LPC_INTC bool "SW64 cpu builtin LPC Interrupt Controller" - depends on SW64_INTC_V2 + depends on SW64_PINTC help Say yes here to add support for the SW64 cpu builtin LPC IRQ controller. diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 787206e166fc..6b90d7ce01f4 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -27,8 +27,8 @@ obj-$(CONFIG_SUN6I_R_INTC) += irq-sun6i-r.o obj-$(CONFIG_SUNXI_NMI_INTC) += irq-sunxi-nmi.o obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o -obj-$(CONFIG_SW64_INTC_V2) += irq-sw64-intc-v2.o -obj-$(CONFIG_SW64_LPC_INTC) += irq-sw64-lpc-intc.o +obj-$(CONFIG_SW64_PINTC) += irq-sunway-pintc.o +obj-$(CONFIG_SW64_LPC_INTC) += irq-sunway-lpc-intc.o obj-$(CONFIG_SW64_IRQ_CPU) += irq-sunway-cpu.o ifeq ($(CONFIG_UNCORE_XUELANG),y) diff --git a/drivers/irqchip/irq-sunway-cpu.c b/drivers/irqchip/irq-sunway-cpu.c index ff7455c0f3ec..09addf73e132 100644 --- a/drivers/irqchip/irq-sunway-cpu.c +++ b/drivers/irqchip/irq-sunway-cpu.c @@ -115,10 +115,9 @@ static void handle_dev_int(struct pt_regs *regs) while (stat) { hwirq = ffs(stat) - 1; - generic_handle_domain_irq(NULL, hwirq); + generic_handle_domain_irq(mcu_irq_domain, hwirq); stat &= ~(1UL << hwirq); } - /*do handle irq */ sw64_io_write(node, DEV_INT_CONFIG, config_val); } @@ -186,9 +185,7 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, perf_irq(PMC_PC1, regs); return; case INT_DEV: - old_regs = set_irq_regs(regs); handle_dev_int(regs); - set_irq_regs(old_regs); return; case INT_FAULT: old_regs = set_irq_regs(regs); diff --git a/drivers/irqchip/irq-sw64-lpc-intc.c b/drivers/irqchip/irq-sunway-lpc-intc.c similarity index 34% rename from drivers/irqchip/irq-sw64-lpc-intc.c rename to drivers/irqchip/irq-sunway-lpc-intc.c index 1cbf87478242..b594ddb6eb24 100644 --- a/drivers/irqchip/irq-sw64-lpc-intc.c +++ b/drivers/irqchip/irq-sunway-lpc-intc.c @@ -11,65 +11,125 @@ #define LPC_IRQ 0x4 #define LPC_IRQ_MASK 0x8 -struct lpc_intc_data { - struct irq_domain *domain; - struct irq_chip_generic *gc; -}; +static DEFINE_RAW_SPINLOCK(lpc_lock); + +static int parent_irq; + +static unsigned int cached_irq_mask = 0xffffffff; +static void lpc_irq_mask(struct irq_data *irq_data) +{ + void __iomem *base = irq_data->domain->host_data; + unsigned long flags; + u32 mask = 1 << (irq_data->irq); + + raw_spin_lock_irqsave(&lpc_lock, flags); + cached_irq_mask |= mask; + writel(cached_irq_mask, base + LPC_IRQ_MASK); + raw_spin_unlock_irqrestore(&lpc_lock, flags); +} + +static void lpc_irq_unmask(struct irq_data *irq_data) +{ + void __iomem *base = irq_data->domain->host_data; + unsigned long flags; + u32 mask = 1 << (irq_data->irq); + + raw_spin_lock_irqsave(&lpc_lock, flags); + cached_irq_mask &= ~mask; + writel(cached_irq_mask, base + LPC_IRQ_MASK); + raw_spin_unlock_irqrestore(&lpc_lock, flags); +} -static void lpc_irq_mask_ack(struct irq_data *data) +static void lpc_irq_mask_ack(struct irq_data *irq_data) { - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); - struct irq_chip_type *ct = irq_data_get_chip_type(data); - unsigned int mask = data->mask; - - irq_gc_lock(gc); - *ct->mask_cache |= mask; - irq_reg_writel(gc, *ct->mask_cache, ct->regs.mask); - irq_reg_writel(gc, mask, ct->regs.ack); - irq_gc_unlock(gc); + void __iomem *base = irq_data->domain->host_data; + unsigned long flags; + u32 mask = 1 << (irq_data->irq); + + raw_spin_lock_irqsave(&lpc_lock, flags); + cached_irq_mask |= mask; + writel(cached_irq_mask, base + LPC_IRQ_MASK); + writel(mask, base + LPC_IRQ); + raw_spin_unlock_irqrestore(&lpc_lock, flags); } +static struct irq_chip sw64_lpc_chip = { + .name = "LPC-INT", + .irq_mask = lpc_irq_mask, + .irq_unmask = lpc_irq_unmask, + .irq_mask_ack = lpc_irq_mask_ack, + .irq_set_affinity = irq_chip_set_affinity_parent, +}; + static void lpc_irq_handler(struct irq_desc *desc) { - struct lpc_intc_data *b = irq_desc_get_handler_data(desc); + struct irq_domain *domain = irq_desc_get_handler_data(desc); struct irq_chip *chip = irq_desc_get_chip(desc); + void __iomem *base = domain->host_data; unsigned int irq; u32 status; chained_irq_enter(chip, desc); - status = irq_reg_readl(b->gc, LPC_IRQ); + status = readl(base + LPC_IRQ); if (status == 0) { - raw_spin_lock(&desc->lock); handle_bad_irq(desc); - raw_spin_unlock(&desc->lock); goto out; } while (status) { irq = __ffs(status); status &= ~BIT(irq); - generic_handle_irq(irq_find_mapping(b->domain, irq)); + generic_handle_irq(irq_find_mapping(domain, irq)); } out: chained_irq_exit(chip, desc); } +static int sw64_lpc_domain_map(struct irq_domain *d, unsigned int virq, + irq_hw_number_t hw) +{ + struct irq_data *irq_data, *parent_data; + + irq_data = irq_domain_get_irq_data(d, virq); + parent_data = irq_get_irq_data(parent_irq); + if (!parent_data) { + pr_warn("Failed to get lpc parent irq data!\n"); + return -EFAULT; + } + + irq_data->parent_data = parent_data; + + irq_set_chip_and_handler(virq, &sw64_lpc_chip, handle_level_irq); + irq_set_probe(virq); + irq_set_status_flags(virq, IRQ_LEVEL); + + return 0; +} + +static const struct irq_domain_ops sw64_lpc_domain_ops = { + .map = sw64_lpc_domain_map, + .xlate = irq_domain_xlate_onecell, +}; + +struct device_node *sw_lpc_intc_node; +EXPORT_SYMBOL(sw_lpc_intc_node); + static int __init lpc_intc_of_init(struct device_node *np, struct device_node *parent) { - unsigned int set = IRQ_NOPROBE | IRQ_LEVEL; - struct lpc_intc_data *data; - struct irq_chip_type *ct; - int parent_irq, ret; + struct irq_domain *lpc_domain; + int ret; void __iomem *base; - int hwirq = 0; - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; + sw_lpc_intc_node = np; + + if (!parent) { + pr_err("no parent intc found\n"); + return -ENXIO; + } base = of_iomap(np, 0); if (!base) { @@ -85,53 +145,22 @@ static int __init lpc_intc_of_init(struct device_node *np, goto out_unmap; } - data->domain = irq_domain_add_linear(np, LPC_NR_IRQS, - &irq_generic_chip_ops, NULL); - if (!data->domain) { + lpc_domain = irq_domain_add_legacy(np, LPC_NR_IRQS, + 0, 0, &sw64_lpc_domain_ops, base); + if (!lpc_domain) { ret = -ENOMEM; goto out_unmap; } - /* Allocate a single Generic IRQ chip for this node */ - ret = irq_alloc_domain_generic_chips(data->domain, 16, 1, np->name, - handle_level_irq, 0, set, - IRQ_GC_INIT_MASK_CACHE); - if (ret) { - pr_err("failed to allocate generic irq chip\n"); - goto out_free_domain; - } - /* Set the IRQ chaining logic */ irq_set_chained_handler_and_data(parent_irq, - lpc_irq_handler, data); - - data->gc = irq_get_domain_generic_chip(data->domain, 0); - data->gc->reg_base = base; - data->gc->private = data; - - ct = data->gc->chip_types; - - ct->regs.ack = LPC_IRQ; - ct->regs.mask = LPC_IRQ_MASK; - ct->chip.irq_mask = irq_gc_mask_set_bit; - ct->chip.irq_unmask = irq_gc_mask_clr_bit; - ct->chip.irq_ack = irq_gc_ack_set_bit; - ct->chip.irq_mask_ack = lpc_irq_mask_ack; - - for (hwirq = 0 ; hwirq < 16 ; hwirq++) - irq_create_mapping(data->domain, hwirq); - - /* Enable LPC interrupts */ - writel(0xffffebdd, base + LPC_IRQ_MASK); + lpc_irq_handler, lpc_domain); return 0; -out_free_domain: - irq_domain_remove(data->domain); out_unmap: iounmap(base); out_free: - kfree(data); return ret; } IRQCHIP_DECLARE(sw_lpc_intc, "sw64,lpc_intc", lpc_intc_of_init); diff --git a/drivers/irqchip/irq-sunway-pintc.c b/drivers/irqchip/irq-sunway-pintc.c new file mode 100644 index 000000000000..8d789fd255c8 --- /dev/null +++ b/drivers/irqchip/irq-sunway-pintc.c @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include + +/* + * Multi-node platform device implementation hasn't been thought through yet, + * which means how to obtain CPU node is ambiguous here. It is highly likely + * that this will be passed through ACPI or DTS. Leave node with 0 as default + * for now and wait for platform guys to check this later. + */ +#define DEFAULT_CPU_NODE 0 +static int cpu_node = DEFAULT_CPU_NODE; + +struct devint_chipdata { + int node; +}; + +static DEFINE_RAW_SPINLOCK(devint_lock); +static void lock_dev_lock(void) +{ + raw_spin_lock(&devint_lock); +} + +static void unlock_dev_lock(void) +{ + raw_spin_unlock(&devint_lock); +} + +static void mcu_irq_mask(struct irq_data *data) +{ + struct devint_chipdata *chip_data = data->chip_data; + unsigned int mask; + int hwirq = data->hwirq; + int node; + + node = chip_data->node; + + mask = sw64_io_read(node, MCU_DVC_INT_EN); + mask &= ~(0x1UL << hwirq); + sw64_io_write(node, MCU_DVC_INT_EN, mask); +} + +static void mcu_irq_unmask(struct irq_data *data) +{ + struct devint_chipdata *chip_data = data->chip_data; + unsigned int mask; + int hwirq = data->hwirq; + int node; + + node = chip_data->node; + + mask = sw64_io_read(node, MCU_DVC_INT_EN); + mask |= (0x1UL << hwirq); + sw64_io_write(node, MCU_DVC_INT_EN, mask); +} + +static void mcu_irq_enable(struct irq_data *irq_data) +{ + struct devint_chipdata *data = irq_data->chip_data; + unsigned long devint_conf; + int node; + + node = data->node; + + devint_conf = sw64_io_read(node, DEV_INT_CONFIG); + devint_conf |= (1UL << 8); + sw64_io_write(node, DEV_INT_CONFIG, devint_conf); + mcu_irq_unmask(irq_data); +} + +static void mcu_irq_disable(struct irq_data *irq_data) +{ + struct devint_chipdata *data = irq_data->chip_data; + unsigned long devint_conf; + int node; + + node = data->node; + + devint_conf = sw64_io_read(node, DEV_INT_CONFIG); + devint_conf &= ~(1UL << 8); + sw64_io_write(node, DEV_INT_CONFIG, devint_conf); + mcu_irq_mask(irq_data); +} + +static int __assign_mcu_irq_config(int node, cpumask_t *targets) +{ + unsigned long dev_int_tar, val; + unsigned int cpu; + int phy_cpu; + + for_each_cpu(cpu, targets) { + /* + * Hardware requires dev ints be redirected to on-node + * cores only. Thus, we remove all off-node cpu in the + * target mask. + */ + if (cpu_to_node(cpu) != node) + cpumask_clear_cpu(cpu, targets); + } + + /* Use the last one in valid cpus to avoid core 0. */ + cpu = cpumask_last(targets); + if (cpu >= nr_cpu_ids) + return -EPERM; + + phy_cpu = cpu_to_rcid(cpu); + + val = sw64_io_read(node, DEV_INT_CONFIG); + dev_int_tar = DEV_INT_TARGET(phy_cpu); + val &= 0xffff; + val |= dev_int_tar << 16; + sw64_io_write(node, DEV_INT_CONFIG, val); + + return 0; +} + +static int assign_mcu_irq_config(int node, cpumask_t *targets) +{ + int ret; + + lock_dev_lock(); + ret = __assign_mcu_irq_config(node, targets); + unlock_dev_lock(); + + return ret; +} + +static int mcu_irq_set_affinity(struct irq_data *irq_data, + const struct cpumask *dest, bool force) +{ + struct devint_chipdata *chip_data = irq_data->chip_data; + cpumask_t targets; + int node, ret = 0; + + if (cpumask_any_and(dest, cpu_online_mask) >= nr_cpu_ids) + return -EINVAL; + + cpumask_and(&targets, dest, cpu_online_mask); + + node = chip_data->node; + + mcu_irq_disable(irq_data); + ret = assign_mcu_irq_config(node, &targets); + mcu_irq_enable(irq_data); + + return ret; +} + +static struct irq_chip onchip_intc = { + .name = "MCU-INT", + .irq_enable = mcu_irq_enable, + .irq_disable = mcu_irq_disable, + .irq_mask = mcu_irq_mask, + .irq_unmask = mcu_irq_unmask, + .irq_set_affinity = mcu_irq_set_affinity, +}; + +static struct devint_chipdata * +alloc_sw64_devint_chip_data(struct irq_data *irq_data) +{ + struct devint_chipdata *chip_data; + int node; + + node = irq_data_get_node(irq_data); + chip_data = kzalloc_node(sizeof(*chip_data), GFP_KERNEL, node); + if (!chip_data) + return NULL; + + return chip_data; +} + +static void sw64_intc_free_irqs(struct irq_domain *irq_domain, + unsigned int virq, unsigned int nr_irqs) +{ + struct irq_data *irq_data; + struct devint_chipdata *chip_data; + int i = 0; + + for (i = 0; i < nr_irqs; i++) { + irq_data = irq_domain_get_irq_data(irq_domain, virq + i); + if (irq_data && irq_data->chip_data) { + lock_dev_lock(); + chip_data = irq_data->chip_data; + irq_domain_reset_irq_data(irq_data); + kfree(chip_data); + unlock_dev_lock(); + } + } +} + +static int sw64_intc_alloc_irqs(struct irq_domain *irq_domain, + unsigned int virq, + unsigned int nr_irqs, + void *arg) +{ + struct irq_data *irq_data; + struct devint_chipdata *chip_data; + struct irq_fwspec *fwspec = arg; + int default_node = cpu_node, i = 0, hwirq; + + for (i = 0; i < nr_irqs; i++) { + irq_data = irq_domain_get_irq_data(irq_domain, virq + i); + hwirq = fwspec->param[0]; + irq_data->hwirq = hwirq; + + chip_data = alloc_sw64_devint_chip_data(irq_data); + if (!chip_data) + goto out_free; + + chip_data->node = default_node; + irq_data->chip_data = chip_data; + irq_set_chip_and_handler(virq, &onchip_intc, handle_level_irq); + irq_set_status_flags(virq, IRQ_LEVEL); + } + + return 0; + +out_free: + sw64_intc_free_irqs(irq_domain, virq, nr_irqs); + return -ENOMEM; +} + +static const struct irq_domain_ops sw64_intc_domain_ops = { + .xlate = irq_domain_xlate_onecell, + .alloc = sw64_intc_alloc_irqs, + .free = sw64_intc_free_irqs, +}; + +struct irq_domain *mcu_irq_domain; +EXPORT_SYMBOL(mcu_irq_domain); + +#ifdef CONFIG_OF +static int __init +init_mcu_IRQ(struct device_node *intc, struct device_node *parent) +{ + if (parent) { + pr_warn("DeviceTree incore intc not a root irq controller\n"); + return -ENODEV; + } + + mcu_irq_domain = irq_domain_add_linear(intc, 8, + &sw64_intc_domain_ops, NULL); + + if (!mcu_irq_domain) { + pr_warn("root irq domain not avail\n"); + return -ENODEV; + } + + /* with this we don't need to export root_domain */ + irq_set_default_host(mcu_irq_domain); + + /* mask all interrupts for now */ + sw64_io_write(cpu_node, MCU_DVC_INT_EN, 0x0); + + return 0; +} + +IRQCHIP_DECLARE(sw64_intc, "sw64,sw6_irq_controller", init_mcu_IRQ); + +static int __init +init_mcu_vt_IRQ(struct device_node *intc, struct device_node *parent) +{ + if (parent) { + pr_warn("DeviceTree incore intc not a root irq controller\n"); + return -ENODEV; + } + + mcu_irq_domain = irq_domain_add_legacy(intc, 16, 0, 0, + &sw64_intc_domain_ops, NULL); + + if (!mcu_irq_domain) { + pr_warn("root irq domain not avail\n"); + return -ENODEV; + } + + /* with this we don't need to export root_domain */ + irq_set_default_host(mcu_irq_domain); + + return 0; +} + +IRQCHIP_DECLARE(sw64_vt_intc, "sw64,sw6_irq_vt_controller", init_mcu_vt_IRQ); +#endif diff --git a/drivers/irqchip/irq-sw64-intc-v2.c b/drivers/irqchip/irq-sw64-intc-v2.c deleted file mode 100644 index bc2c8ef3ed2f..000000000000 --- a/drivers/irqchip/irq-sw64-intc-v2.c +++ /dev/null @@ -1,89 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include -#include - -static void fake_irq_mask(struct irq_data *data) -{ -} - -static void fake_irq_unmask(struct irq_data *data) -{ -} - -static struct irq_chip onchip_intc = { - .name = "SW fake Intc", - .irq_mask = fake_irq_mask, - .irq_unmask = fake_irq_unmask, -}; - -static int sw64_intc_domain_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hw) -{ - - irq_set_chip_and_handler(irq, &onchip_intc, handle_level_irq); - irq_set_status_flags(irq, IRQ_LEVEL); - return 0; -} - -static const struct irq_domain_ops sw64_intc_domain_ops = { - .xlate = irq_domain_xlate_onecell, - .map = sw64_intc_domain_map, -}; - -#ifdef CONFIG_OF -static struct irq_domain *root_domain; - -static int __init -init_onchip_IRQ(struct device_node *intc, struct device_node *parent) -{ - - int node = 0; - int hwirq = 0, nirq = 8; - - if (parent) - panic("DeviceTree incore intc not a root irq controller\n"); - - root_domain = irq_domain_add_linear(intc, 8, - &sw64_intc_domain_ops, NULL); - - if (!root_domain) - panic("root irq domain not avail\n"); - - /* with this we don't need to export root_domain */ - irq_set_default_host(root_domain); - - for (hwirq = 0 ; hwirq < nirq ; hwirq++) - irq_create_mapping(root_domain, hwirq); - - /*enable MCU_DVC_INT_EN*/ - sw64_io_write(node, MCU_DVC_INT_EN, 0xff); - - return 0; -} - -IRQCHIP_DECLARE(sw64_intc, "sw64,sw6_irq_controller", init_onchip_IRQ); - -static int __init -init_onchip_vt_IRQ(struct device_node *intc, struct device_node *parent) -{ - if (parent) - panic("DeviceTree incore intc not a root irq controller\n"); - - root_domain = irq_domain_add_legacy(intc, 16, 0, 0, - &sw64_intc_domain_ops, NULL); - - if (!root_domain) - panic("root irq domain not avail\n"); - - /* with this we don't need to export root_domain */ - irq_set_default_host(root_domain); - - return 0; -} - -IRQCHIP_DECLARE(sw64_vt_intc, "sw64,sw6_irq_vt_controller", init_onchip_vt_IRQ); -#endif -- Gitee From 72f81d5144b81cb8e56fa46eb1911d1a0bc7f1d8 Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Fri, 5 Jan 2024 14:24:31 +0800 Subject: [PATCH 24/24] anolis: sw64: fix rd_f compatibility issue for C4 ANBZ: #4688 To maintain binary compatibility with existing programs, this patch replaces `rd_f` instruction when the specific exception is caught. Signed-off-by: He Chuyue Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/traps.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index a30e18ad1f00..133ad318edb6 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -193,6 +193,32 @@ void simd_emulate(unsigned int inst, unsigned long va) } } +static int try_fix_rd_f(unsigned int inst, struct pt_regs *regs) +{ + int copied; + unsigned int prev_inst, new_inst; + unsigned int ra, prev_ra; + + /* not rd_f */ + if ((inst & 0xfc00ffffU) != 0x18001000) + return -1; + + get_user(prev_inst, (__u32 *)(regs->pc - 8)); + if ((prev_inst & 0xfc00e000U) == 0x20008000) { /* lstw/lstl */ + ra = (inst >> 21) & 0x1f; + prev_ra = (prev_inst >> 21) & 0x1f; + /* ldi ra, 0(prev_ra) */ + new_inst = (0x3e << 26) | (ra << 21) | (prev_ra << 16); + copied = access_process_vm(current, regs->pc - 4, &new_inst, + sizeof(unsigned int), FOLL_FORCE | FOLL_WRITE); + if (copied != sizeof(unsigned int)) + return -1; + regs->pc -= 4; + return 0; + } + return -1; +} + /* * BPT/GENTRAP/OPDEC make regs->pc = exc_pc + 4. debugger should * do something necessary to handle it correctly. @@ -294,6 +320,8 @@ do_entIF(unsigned long inst_type, unsigned long va, struct pt_regs *regs) return; case IF_OPDEC: + if (try_fix_rd_f(inst, regs) == 0) + return; switch (inst) { #ifdef CONFIG_KPROBES case BREAK_KPROBE: -- Gitee