From 80a44074b5805b69d14f6c3ffc0917e8101318ef Mon Sep 17 00:00:00 2001 From: Gu Zitao Date: Tue, 16 Apr 2024 08:51:51 +0800 Subject: [PATCH 01/98] sw64: add arch-specific SYM_END definition Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Redefine SYM_END to make low version compiler work. Signed-off-by: Gu Zitao Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/linkage.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/sw_64/include/asm/linkage.h b/arch/sw_64/include/asm/linkage.h index 85b279f6211e..b0703086e902 100644 --- a/arch/sw_64/include/asm/linkage.h +++ b/arch/sw_64/include/asm/linkage.h @@ -6,4 +6,8 @@ #define SYSCALL_ALIAS(alias, name) \ asm (#alias " = " #name "\n\t.globl " #alias) +#define SYM_END(name, sym_type) \ + .type name sym_type ASM_NL \ + .size name, .-name + #endif /* _ASM_SW64_LINKAGE_H */ -- Gitee From aa50461a49f98de6b93121af5142f9e1e27af93f Mon Sep 17 00:00:00 2001 From: Tang Jinyang Date: Thu, 16 Nov 2023 11:08:55 +0800 Subject: [PATCH 02/98] sw64: remove useless current_policy Sunway inclusion category: performance bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 60a537d84ecf5c9771eb881e5c6900f3af407ccd Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 15 Nov 2023 14:12:45 +0800 Subject: [PATCH 03/98] sw64: extern vdso_start and vdso_end as char[] Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 fc111133e8e79022c72bf426be111ff0a12e27ad Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Mon, 20 Nov 2023 09:22:27 +0800 Subject: [PATCH 04/98] sw64: fix hugepage support Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 a5012a4d543fd14216a44086a80fd445a4b7ad36 Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Mon, 20 Nov 2023 16:35:37 +0800 Subject: [PATCH 05/98] sw64: perf: hide hardware performance events in guest os Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 3e14e4675e53f1e7720c10d6e3516c7cfa4537a8 Mon Sep 17 00:00:00 2001 From: Gu Zitao Date: Mon, 20 Nov 2023 14:14:42 +0800 Subject: [PATCH 06/98] sw64: uapi: fix a compile error for headers_install Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 fa58a0de4368..4f3a3a8b4123 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 414df643165d9dd7485ae6429ca72b4e417031f1 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Mon, 4 Dec 2023 13:41:08 +0800 Subject: [PATCH 07/98] sw64: pci: export some pci functions Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 9320c6c95c1afcfba500d6a870b5e1fe93a49d11 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Mon, 4 Dec 2023 15:55:49 +0800 Subject: [PATCH 08/98] sw64: numa: fix compile error when CONFIG_ACPI_NUMA=n Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 fb922706e8b0dbbc9a1d5b935a0112f8eb86ff89 Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Mon, 20 Nov 2023 15:45:02 +0800 Subject: [PATCH 09/98] sw64: perf: do all event checks in sw64_pmu_event_init() Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 c983b9d56c643539580cfd5f014eeab24ea88b97 Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Tue, 5 Dec 2023 09:17:26 +0800 Subject: [PATCH 10/98] sw64: fix lockdep error Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 a47b9d78dfbc2d70c22bd7a809cbcb3133226749 Mon Sep 17 00:00:00 2001 From: Zhi Tongze Date: Tue, 21 Nov 2023 14:58:49 +0800 Subject: [PATCH 11/98] sw64: kgdb: add single-step debug support Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 975133814ca6bf24fd13c5aa37175d7a71f88526 Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Sun, 19 Nov 2023 18:38:19 +0800 Subject: [PATCH 12/98] sw64: use rvpcr() to setup run mode Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 4d4f600b3f262f849e8bec4dc45a153eb4b3342b Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Wed, 27 Dec 2023 01:10:08 +0000 Subject: [PATCH 13/98] sw64: iommu: fix the bug when vfio_iommu unpin pages Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 86453344ec004866ab9303f0c3b5d1fa32d822a0 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Fri, 8 Dec 2023 17:22:31 +0800 Subject: [PATCH 14/98] sw64: pci: synchronize the OEM table ID of MCFG with BIOS Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 70ceb6905c0a..db8c4a6f837c 100644 --- a/drivers/acpi/pci_mcfg.c +++ b/drivers/acpi/pci_mcfg.c @@ -202,7 +202,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 dfbb23a844cea045752d5524346be3bbcd4feb74 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 6 Dec 2023 14:18:51 +0800 Subject: [PATCH 15/98] sw64: smp: modify function smp_rcb_init() to receive base address Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 | 9 ++++++--- 2 files changed, 7 insertions(+), 4 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..ebbb8e069d09 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -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 d18e2b8e354edc102cf1ec3a79036c91163b585c Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 6 Dec 2023 15:39:01 +0800 Subject: [PATCH 16/98] sw64: smp: add new structure to record rcid information Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 ebbb8e069d09..f669943cc2ac 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 faaa19c603e933b34edf8264f3f7e1c20c391e1e Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 6 Dec 2023 16:40:55 +0800 Subject: [PATCH 17/98] sw64: acpi: add ACPI-style structures for SW CINTC Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 f805bc581003..b6eb68b951da 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 }; /* @@ -1327,6 +1339,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 4fccaf8e250e4fa4c522ef3078afab16fb11ed4b Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 6 Dec 2023 17:20:08 +0800 Subject: [PATCH 18/98] sw64: acpi: support MADT entry print for SW CINTC Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 9321bda8904f3fd3492836585ee01547702ba12b Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 6 Dec 2023 17:22:36 +0800 Subject: [PATCH 19/98] sw64: acpi: parse SW CINTC for SMP initialization Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 fe075b9bdc6d349a0d6873143318200b6db463f5 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Fri, 8 Dec 2023 17:12:39 +0800 Subject: [PATCH 20/98] sw64: smp: suppress function setup_smp() when ACPI enabled Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 f3c1cc377fe832df80fa7ff4bbb577001075fb70 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 27 Dec 2023 17:03:25 +0800 Subject: [PATCH 21/98] sw64: pci: fix compile error when CONFIG_ACPI=n Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 66025ca41029d67fcd07775415401bb4268d97ba Mon Sep 17 00:00:00 2001 From: Zhou Xuemei Date: Tue, 15 Aug 2023 02:07:56 +0000 Subject: [PATCH 22/98] USB: Fix ehci infinite suspend-resume loop issue in zhaoxin Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- This is backport of commit f085bd4bfe09 ("USB: Fix ehci infinite suspend-resume loop issue in zhaoxin"). Signed-off-by: Zhou Xuemei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/usb/host/ehci-hcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 802bfafb1012..d2f2e7db78f6 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1110,8 +1110,8 @@ static void ehci_remove_device(struct usb_hcd *hcd, struct usb_device *udev) /* Clear wakeup signal locked in zhaoxin platform when device plug in. */ static void ehci_zx_wakeup_clear(struct ehci_hcd *ehci) { - u32 __iomem *reg = &ehci->regs->port_status[4]; - u32 t1 = ehci_readl(ehci, reg); + u32 __iomem *reg = &ehci->regs->port_status[4]; + u32 t1 = ehci_readl(ehci, reg); t1 &= (u32)~0xf0000; t1 |= PORT_TEST_FORCE; -- Gitee From 90b600fcf48236dc2755d98b38a8829eff649b63 Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Wed, 27 Sep 2023 13:47:48 +0800 Subject: [PATCH 23/98] USB: xHCI: fix resume issue of some ZHAOXIN hosts Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 dbad516262ef..b23ee4e9bde0 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -482,6 +482,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 be4533b64b3d2f29e356ed1279629f02b1e8d23e Mon Sep 17 00:00:00 2001 From: Tang Jinyang Date: Tue, 26 Dec 2023 17:04:43 +0800 Subject: [PATCH 24/98] sw64: fix macro definition compilation error Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 f669943cc2ac..2bd0796c65e0 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 f7bb07e5982e018030a1986e07b721019255e9ee Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Mon, 11 Dec 2023 07:15:22 +0000 Subject: [PATCH 25/98] sw64: refactor device interrupt domain Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 6ffcdad8b131..5934939c8496 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 6293ccf1013474107e4f9e0581027944a7020681 Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Fri, 5 Jan 2024 14:24:31 +0800 Subject: [PATCH 26/98] sw64: fix rd_f compatibility issue for C4 Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- 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 From d0eecd5b777fb30fd18d8e6586f3da3690f16dc5 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 17 Jan 2024 17:01:55 +0800 Subject: [PATCH 27/98] sw64: acpi: fix coding style and typos Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Make the coding style conform to linux style without any functional changes. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/pci.h | 3 +- arch/sw_64/include/asm/smp.h | 8 +- arch/sw_64/kernel/acpi.c | 47 ++++++------ arch/sw_64/kernel/smp.c | 7 +- arch/sw_64/pci/acpi.c | 112 +++++++++++++++------------- arch/sw_64/pci/pci.c | 33 ++++---- drivers/pci/controller/pci-sunway.c | 56 +++++++++----- 7 files changed, 148 insertions(+), 118 deletions(-) diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index 21bfcef21c5f..689a65e63517 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -91,7 +91,8 @@ extern void __init setup_chip_pci_ops(void); #define setup_chip_pci_ops() do { } while (0) #endif -extern struct pci_controller *pci_bus_to_pci_controller(const struct pci_bus *bus); +extern struct pci_controller * +pci_bus_to_pci_controller(const struct pci_bus *bus); extern struct pci_controller *bus_num_to_pci_controller(unsigned long bus_num); extern void sw64_pci_root_bridge_prepare(struct pci_host_bridge *bridge); diff --git a/arch/sw_64/include/asm/smp.h b/arch/sw_64/include/asm/smp.h index 0ca636b29dde..097f22b72c25 100644 --- a/arch/sw_64/include/asm/smp.h +++ b/arch/sw_64/include/asm/smp.h @@ -72,7 +72,7 @@ int __cpu_disable(void); void __cpu_die(unsigned int cpu); #endif /* CONFIG_HOTPLUG_CPU */ -struct rcid_infomation { +struct rcid_information { unsigned long thread_bits : 8; /* which thread */ unsigned long thread_shift : 8; unsigned long core_bits : 8; /* which core */ @@ -82,8 +82,8 @@ struct rcid_infomation { unsigned long initialized : 1; }; -extern struct rcid_infomation rcid_info; -extern void rcid_infomation_init(int core_version); +extern struct rcid_information rcid_info; +extern void rcid_information_init(int core_version); extern int get_core_id_from_rcid(int rcid); extern int get_thread_id_from_rcid(int rcid); @@ -104,7 +104,7 @@ 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 void rcid_information_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; } diff --git a/arch/sw_64/kernel/acpi.c b/arch/sw_64/kernel/acpi.c index 4c1243c95c95..20c6e851254b 100644 --- a/arch/sw_64/kernel/acpi.c +++ b/arch/sw_64/kernel/acpi.c @@ -173,10 +173,9 @@ static int rcid_to_cpu(int physical_id) { int i; - for (i = 0; i < NR_CPUS; ++i) { + for (i = 0; i < ARRAY_SIZE(__cpu_to_rcid); ++i) if (__cpu_to_rcid[i] == physical_id) return i; - } /* physical id not found */ return -1; @@ -212,21 +211,24 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) } if (pa->apic_id >= CONFIG_NR_CPUS) { - pr_err("SRAT: PXM %u -> CPU 0x%02x -> Node %u skipped apicid that is too big\n", pxm, pa->apic_id, node); + pr_err("SRAT: PXM %u -> CPU 0x%02x -> Node %u skipped apicid that is too big\n", + pxm, pa->apic_id, node); return; } /* Record the mapping from logical core id to node id */ cpu = rcid_to_cpu(pa->apic_id); if (cpu < 0) { - pr_err("SRAT: Can not find the logical id for physical Core 0x%02x\n", pa->apic_id); + pr_err("SRAT: Can not find the logical id for physical Core 0x%02x\n", + pa->apic_id); return; } early_map_cpu_to_node(cpu, node); node_set(node, numa_nodes_parsed); - pr_info("SRAT: PXM %u -> CPU 0x%02x -> Node %u\n", pxm, pa->apic_id, node); + pr_info("SRAT: PXM %u -> CPU 0x%02x -> Node %u\n", + pxm, pa->apic_id, node); } #ifdef CONFIG_MEMORY_HOTPLUG @@ -297,9 +299,9 @@ EXPORT_SYMBOL(acpi_unmap_cpu); static bool __init is_rcid_duplicate(int rcid) { - unsigned int i; + int i; - for (i = 0; (i < possible_cores) && (i < NR_CPUS); i++) { + for_each_possible_cpu(i) { if (cpu_to_rcid(i) == rcid) return true; } @@ -318,34 +320,31 @@ setup_rcid_and_core_mask(struct acpi_madt_sw_cintc *sw_cintc) * 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", + pr_err(PREFIX "Max core num [%u] reached, core [0x%x] ignored\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); + pr_err(PREFIX "Duplicate core [0x%x] in MADT\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"); + pr_err(PREFIX "Boot core disabled in MADT\n"); return -EINVAL; } /* Online capable makes core possible */ - if (!is_core_enabled(sw_cintc->flags) && \ + if (!is_core_enabled(sw_cintc->flags) && !is_core_online_capable(sw_cintc->flags)) { disabled_cores++; return 0; } - rcid_infomation_init(sw_cintc->version); + rcid_information_init(sw_cintc->version); /* The logical core ID of the boot core must be 0 */ if (rcid == 0) @@ -363,8 +362,8 @@ setup_rcid_and_core_mask(struct acpi_madt_sw_cintc *sw_cintc) * 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)) { + 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++; @@ -382,8 +381,7 @@ static int __init acpi_parse_sw_cintc(union acpi_subtable_headers *header, 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"); + pr_err(PREFIX "SW CINTC entry error\n"); return -EINVAL; } @@ -405,11 +403,11 @@ static int __init acpi_parse_sw_cintc(union acpi_subtable_headers *header, static int __init acpi_process_madt_sw_cintc(void) { - int logical_core, ret; + int i, 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); + for (i = 0; i < ARRAY_SIZE(__cpu_to_rcid); ++i) + set_rcid_map(i, -1); /* Clean core mask */ init_cpu_possible(cpu_none_mask); @@ -453,8 +451,9 @@ void __init acpi_boot_table_init(void) pr_err("Failed to init ACPI tables\n"); disable_acpi(); return; - } else - pr_info("Successfully parsed ACPI table\n"); + } + + pr_info("Successfully parsed ACPI table\n"); /** * Process SW64 Core Interrupt Controller(SW CINTC) in MADT table. diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 2bd0796c65e0..c198e0510996 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -1,7 +1,4 @@ // SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/sw_64/kernel/smp.c - */ #include #include @@ -45,7 +42,7 @@ enum ipi_message_type { int smp_num_cpus = 1; /* Number that came online. */ EXPORT_SYMBOL(smp_num_cpus); -struct rcid_infomation rcid_info = { 0 }; +struct rcid_information rcid_info = { 0 }; #define send_sleep_interrupt(cpu) send_ipi((cpu), II_SLEEP) #define send_wakeup_interrupt(cpu) send_ipi((cpu), II_WAKE) @@ -218,7 +215,7 @@ void __init setup_smp(void) smp_rcb_init(INIT_SMP_RCB); } -void rcid_infomation_init(int core_version) +void rcid_information_init(int core_version) { if (rcid_info.initialized) return; diff --git a/arch/sw_64/pci/acpi.c b/arch/sw_64/pci/acpi.c index 1353994320b3..2f446116e69e 100644 --- a/arch/sw_64/pci/acpi.c +++ b/arch/sw_64/pci/acpi.c @@ -42,6 +42,7 @@ pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root) struct resource *bus_res = &root->secondary; struct resource cfg_res; struct acpi_device *adev = NULL; + resource_size_t bus_res_size; int ret = 0, bus_shift = 0; u16 seg = root->segment; @@ -53,11 +54,12 @@ pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root) /** * Do the quirk of bus shift here, since we can not - * know the ECAM addr in MCFG table when fill mcfg_quirks + * get the ECAM addr when fill mcfg_quirks. */ bus_shift = ecam_ops->bus_shift; cfg_res.start = root->mcfg_addr + (bus_res->start << bus_shift); - cfg_res.end = cfg_res.start + ((resource_size(bus_res)) << bus_shift) - 1; + bus_res_size = resource_size(bus_res); + cfg_res.end = cfg_res.start + (bus_res_size << bus_shift) - 1; cfg_res.flags = IORESOURCE_MEM; /** @@ -87,66 +89,66 @@ static int pci_acpi_prepare_root_resources(struct acpi_pci_root_info *ci) { int status = 0; acpi_status rc; - unsigned long long mem_space_base = 0; + unsigned long long memh = 0; struct resource_entry *entry = NULL, *tmp = NULL; struct acpi_device *device = ci->bridge; + /** + * To distinguish between mem and pre_mem, firmware + * only pass the lower 32bits of mem via acpi and + * use vendor specific "MEMH" to record the upper + * 32 bits of mem. + * + * Get the upper 32 bits here. + */ + rc = acpi_evaluate_integer(ci->bridge->handle, "MEMH", NULL, &memh); + if (rc != AE_OK) { + dev_err(&device->dev, "unable to retrieve MEMH\n"); + return -EEXIST; + } + /** * Get host bridge resources via _CRS method, the return value * is the num of resource parsed. */ status = acpi_pci_probe_root_resources(ci); - if (status > 0) { + if (status <= 0) { /** - * To distinguish between mem and pre_mem, firmware only pass the - * lower 32bits of mem via acpi and use vendor specific "MEMH" to - * record the upper 32 bits of mem. - * - * Get the upper 32 bits here. + * If not successfully parse resources, destroy + * resources which have been parsed. */ - rc = acpi_evaluate_integer(ci->bridge->handle, - "MEMH", NULL, &mem_space_base); - if (rc != AE_OK) { - dev_err(&device->dev, "unable to retrieve MEMH\n"); - return -EEXIST; - } - resource_list_for_each_entry_safe(entry, tmp, &ci->resources) { - if (entry->res->flags & IORESOURCE_MEM) { - if (!(entry->res->end & 0xFFFFFFFF00000000ULL)) { - /* Patch the mem resource with upper 32 bits */ - entry->res->start |= (mem_space_base << 32); - entry->res->end |= (mem_space_base << 32); - } else { - /** - * Add PREFETCH and MEM_64 flags for pre_mem, - * so that we can distinguish between mem and - * pre_mem. - */ - entry->res->flags |= IORESOURCE_PREFETCH; - entry->res->flags |= IORESOURCE_MEM_64; - } - } - - dev_dbg(&device->dev, - "host bridge resource: 0x%llx-0x%llx flags [0x%lx]\n", - entry->res->start, entry->res->end, entry->res->flags); + dev_info(&device->dev, + "host bridge resource(ignored): %pR\n", + entry->res); + resource_list_destroy_entry(entry); } - return status; + + return 0; } - /** - * If not successfully parse resources, destroy - * resources which have been parsed. - */ resource_list_for_each_entry_safe(entry, tmp, &ci->resources) { - dev_info(&device->dev, - "host bridge resource(ignored): 0x%llx-0x%llx flags [0x%lx]\n", - entry->res->start, entry->res->end, entry->res->flags); - resource_list_destroy_entry(entry); + if (entry->res->flags & IORESOURCE_MEM) { + if (!(entry->res->end & 0xFFFFFFFF00000000ULL)) { + /* Patch mem res with upper 32 bits */ + entry->res->start |= (memh << 32); + entry->res->end |= (memh << 32); + } else { + /** + * Add PREFETCH and MEM_64 flags for + * pre_mem, so that we can distinguish + * between mem and pre_mem. + */ + entry->res->flags |= IORESOURCE_PREFETCH; + entry->res->flags |= IORESOURCE_MEM_64; + } + } + + dev_dbg(&device->dev, + "host bridge resource: %pR\n", entry->res); } - return 0; + return status; } /** @@ -179,21 +181,26 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) bus = pci_find_bus(domain, busnum); if (bus) { - memcpy(bus->sysdata, pci_ri->cfg, sizeof(struct pci_config_window)); + memcpy(bus->sysdata, pci_ri->cfg, + sizeof(struct pci_config_window)); kfree(pci_ri->cfg); kfree(pci_ri); kfree(root_ops); } else { - bus = acpi_pci_root_create(root, root_ops, &pci_ri->info, pci_ri->cfg); + bus = acpi_pci_root_create(root, root_ops, + &pci_ri->info, pci_ri->cfg); /** - * No need to do kfree here, because acpi_pci_root_create will free - * mem alloced when it cannot create pci_bus. + * No need to do kfree here, because acpi_pci_root_create + * will free mem alloced when it cannot create pci_bus. */ if (!bus) return NULL; - /* Some quirks for pci controller of Sunway after scanning Root Complex */ + /** + * Some quirks for pci controller of Sunway + * after scanning Root Complex + */ sw64_pci_root_bridge_scan_finish_up(pci_find_host_bridge(bus)); pci_bus_size_bridges(bus); @@ -227,7 +234,10 @@ int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) ACPI_COMPANION_SET(&bridge->dev, adev); set_dev_node(bus_dev, hose->node); - /* Some quirks for pci controller of Sunway before scanning Root Complex */ + /** + * Some quirks for pci controller of Sunway + * before scanning Root Complex + */ sw64_pci_root_bridge_prepare(bridge); } diff --git a/arch/sw_64/pci/pci.c b/arch/sw_64/pci/pci.c index 3db9816e19f1..87930a62595a 100644 --- a/arch/sw_64/pci/pci.c +++ b/arch/sw_64/pci/pci.c @@ -130,7 +130,8 @@ void pcibios_fixup_bus(struct pci_bus *bus) * Provide information on locations of various I/O regions in physical * memory. Do this on a per-card basis so that we choose the right hose. */ -asmlinkage long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn) +asmlinkage long +sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn) { struct pci_controller *hose; @@ -172,7 +173,8 @@ void __init reserve_mem_for_pci(void) return; } - pr_info("reserved pages for pcie memory space %lx:%lx\n", base >> PAGE_SHIFT, + pr_info("reserved pages for pcie memory space %lx:%lx\n", + base >> PAGE_SHIFT, (base + PCI_32BIT_MEMIO_SIZE) >> PAGE_SHIFT); } @@ -184,7 +186,8 @@ static void quirk_isa_bridge(struct pci_dev *dev) { dev->class = PCI_CLASS_BRIDGE_ISA << 8; } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_isa_bridge); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, + quirk_isa_bridge); /* * Early fix up the Root Complex settings @@ -251,8 +254,10 @@ static void enable_sw_dca(struct pci_dev *dev) continue; else { dca_conf = (1UL << 63) | (dev->bus->number << 8) | dev->devfn; - pr_info("dca device index %d, dca_conf = %#lx\n", i, dca_conf); - write_piu_ior1(node, rc_index, DEVICEID0 + (i << 7), dca_conf); + pr_info("dca device index %d, dca_conf = %#lx\n", + i, dca_conf); + write_piu_ior1(node, rc_index, + DEVICEID0 + (i << 7), dca_conf); break; } } @@ -324,7 +329,8 @@ void sw64_pci_root_bridge_prepare(struct pci_host_bridge *bridge) * So, need to update bus num of pci host bridge here. */ bridge->busnr = last_bus; - dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(bus), last_bus); + dev_set_name(&bridge->dev, "pci%04x:%02x", + pci_domain_nr(bus), last_bus); /** * At this point, pci_bus has been created and use old @@ -343,7 +349,8 @@ void sw64_pci_root_bridge_prepare(struct pci_host_bridge *bridge) pci_add_flags(PCI_REASSIGN_ALL_BUS); } -static void sw64_pci_root_bridge_reserve_legacy_io(struct pci_host_bridge *bridge) +static void +sw64_pci_root_bridge_reserve_legacy_io(struct pci_host_bridge *bridge) { struct pci_bus *bus = bridge->bus; struct resource_entry *entry = NULL; @@ -354,10 +361,8 @@ static void sw64_pci_root_bridge_reserve_legacy_io(struct pci_host_bridge *bridg continue; res = kzalloc(sizeof(struct resource), GFP_KERNEL); - if (res == NULL) { - pr_err("alloc resource for legacy io out of mem\n"); + if (WARN_ON(!res)) return; - } res->name = "legacy io"; res->flags = IORESOURCE_IO; @@ -426,11 +431,11 @@ void sw64_pci_root_bridge_scan_finish_up(struct pci_host_bridge *bridge) * * > echo 1 > /sys/bus/pci/rescan * - * Unexpected errors may occur on the endpoint devices due to the re-assign - * bus numbers of upstream bridges. + * Unexpected errors may occur on the endpoint devices due to the + * re-assign bus numbers of upstream bridges. * - * To work around this problem, the flag PCI_REASSIGN_ALL_BUS is set before - * scanning Root Complex and cleared after scanning Root Complex. + * To work around this problem, the flag PCI_REASSIGN_ALL_BUS is set + * before scanning Root Complex and cleared after scanning Root Complex. */ pci_clear_flags(PCI_REASSIGN_ALL_BUS); } diff --git a/drivers/pci/controller/pci-sunway.c b/drivers/pci/controller/pci-sunway.c index 32e850f63a32..4e6a12765bf3 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -2,6 +2,7 @@ #include #include #include +#include #include @@ -26,10 +27,12 @@ void set_adr_int(int node) void set_pcieport_service_irq(int node, int index) { if (IS_ENABLED(CONFIG_PCIE_PME)) - write_piu_ior0(node, index, PMEINTCONFIG, PME_ENABLE_INTD_CORE0); + write_piu_ior0(node, index, + PMEINTCONFIG, PME_ENABLE_INTD_CORE0); if (IS_ENABLED(CONFIG_PCIEAER)) - write_piu_ior0(node, index, AERERRINTCONFIG, AER_ENABLE_INTD_CORE0); + write_piu_ior0(node, index, + AERERRINTCONFIG, AER_ENABLE_INTD_CORE0); } int chip_pcie_configure(struct pci_controller *hose) @@ -161,10 +164,12 @@ int chip_pcie_configure(struct pci_controller *hose) if (pcie_caps_offset == 0) continue; - pci_read_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL, &devctl); + pci_read_config_word(dev, + pcie_caps_offset + PCI_EXP_DEVCTL, &devctl); devctl &= ~(PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ); devctl |= new_values; - pci_write_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL, devctl); + pci_write_config_word(dev, + pcie_caps_offset + PCI_EXP_DEVCTL, devctl); } return bus_max_num; @@ -212,7 +217,8 @@ static void set_rc_piu(unsigned long node, unsigned long index) /* set PCI-E root class code */ value = read_rc_conf(node, index, RC_REVISION_ID); - write_rc_conf(node, index, RC_REVISION_ID, (PCI_CLASS_BRIDGE_HOST << 16) | value); + write_rc_conf(node, index, RC_REVISION_ID, + (PCI_CLASS_BRIDGE_HOST << 16) | value); /* disable DBI_RO_WR_EN */ write_rc_conf(node, index, RC_MISC_CONTROL_1, rc_misc_ctrl); @@ -228,8 +234,8 @@ static void set_rc_piu(unsigned long node, unsigned long index) if (IS_ENABLED(CONFIG_PCI_MSI)) { write_piu_ior0(node, index, MSIADDR, MSIX_MSG_ADDR); #ifdef CONFIG_UNCORE_XUELANG - for (i = 0; i < 256; i++) - write_piu_ior0(node, index, MSICONFIG0 + (i << 7), 0); + for (i = 0; i < 256; i++) + write_piu_ior0(node, index, MSICONFIG0 + (i << 7), 0); #endif } } @@ -302,7 +308,8 @@ static void hose_init(struct pci_controller *hose) hose->pre_mem_space->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_MEM_64; if (request_resource(&iomem_resource, hose->pre_mem_space) < 0) - pr_err("Failed to request 64bit MEM on hose %ld\n", hose->index); + pr_err("Failed to request 64bit MEM on hose %ld\n", + hose->index); hose->io_space->start = pci_io_base | PCI_LEGACY_IO; hose->io_space->end = hose->io_space->start + PCI_LEGACY_IO_SIZE - 1; hose->io_space->name = "pci io space"; @@ -406,7 +413,9 @@ static int sw64_pcie_read_rc_cfg(struct pci_bus *bus, unsigned int devfn, if (IS_ENABLED(CONFIG_PCI_DEBUG)) pr_debug("rc read addr:%px bus %d, devfn %#x, where %#x size=%d\t", - cfg_iobase + ((where & ~3) << 5), bus->number, devfn, where, size); + cfg_iobase + ((where & ~3) << 5), + bus->number, + devfn, where, size); if ((uintptr_t)where & (size - 1)) { *val = 0; @@ -474,7 +483,9 @@ int sw64_pcie_write_rc_cfg(struct pci_bus *bus, unsigned int devfn, if (IS_ENABLED(CONFIG_PCI_DEBUG)) pr_debug("rc write addr:%px bus %d, devfn %#x, where %#x *val %#x size %d\n", - cfg_iobase + ((where & ~3) << 5), bus->number, devfn, where, val, size); + cfg_iobase + ((where & ~3) << 5), + bus->number, + devfn, where, val, size); writel(data, cfg_iobase + ((where & ~3) << 5)); @@ -482,7 +493,9 @@ int sw64_pcie_write_rc_cfg(struct pci_bus *bus, unsigned int devfn, } /** - * sw64_pcie_valid_device - check if a valid device is present on bus + * sw64_pcie_valid_device - check if a valid device is present + * on bus + * * @bus : PCI bus structure * @devfn: device/function * @@ -502,7 +515,9 @@ static bool sw64_pcie_valid_device(struct pci_bus *bus, unsigned int devfn) } /** - * sw64_pcie_config_read - read val from config space of PCI host controller or device + * sw64_pcie_config_read - read val from config space of + * PCI host controller or device + * * @bus : PCI bus structure * @devfn: device/function * @where: offset from base @@ -534,7 +549,9 @@ static int sw64_pcie_config_read(struct pci_bus *bus, unsigned int devfn, } /** - * sw64_pcie_config_write - write val to config space of PCI host controller or device + * sw64_pcie_config_write - write val to config space of PCI + * host controller or device + * * @bus : PCI bus structure * @devfn: device/function * @where: offset from base @@ -666,21 +683,24 @@ static int sw64_pci_prepare_controller(struct pci_controller *hose, * pass Endpoint config space base address, and define Root Complex * config space base address("RCCB") separately in the ACPI namespace. */ - rc = acpi_evaluate_integer(adev->handle, "RCCB", NULL, &rc_config_base_addr); + rc = acpi_evaluate_integer(adev->handle, + "RCCB", NULL, &rc_config_base_addr); if (rc != AE_OK) { dev_err(&adev->dev, "unable to retrieve RCCB\n"); return -EEXIST; } /* Get Root Complex I/O space base addr from ACPI namespace */ - rc = acpi_evaluate_integer(adev->handle, "RCIO", NULL, &pci_io_base_addr); + rc = acpi_evaluate_integer(adev->handle, + "RCIO", NULL, &pci_io_base_addr); if (rc != AE_OK) { dev_err(&adev->dev, "unable to retrieve RCIO\n"); return -EEXIST; } /* Get Endpoint I/O space base addr from ACPI namespace */ - rc = acpi_evaluate_integer(adev->handle, "EPIO", NULL, &ep_io_base_addr); + rc = acpi_evaluate_integer(adev->handle, + "EPIO", NULL, &ep_io_base_addr); if (rc != AE_OK) { dev_err(&adev->dev, "unable to retrieve EPIO\n"); return -EEXIST; @@ -768,10 +788,8 @@ static int sw64_pci_ecam_init(struct pci_config_window *cfg) } hose = kzalloc(sizeof(*hose), GFP_KERNEL); - if (!hose) { - dev_err(dev, "out of memory when alloc mem for pci_controller\n"); + if (!hose) return -ENOMEM; - } /* Get Endpoint config space base address from MCFG table */ mcfg_addr = cfg->res.start - (cfg->busr.start << cfg->ops->bus_shift); -- Gitee From 3b52620aea250bb55fad3b26ee13307ce830e763 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 10 Jan 2024 16:45:32 +0800 Subject: [PATCH 28/98] sw64: dts: fix properties for spi controller device node Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Fix #address-cells and #size-cells. Remove unused properties and related code in driver. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/boot/dts/chip3.dts | 24 ++++++++---------------- drivers/spi/spi-chip3-mmio.c | 6 ------ 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/arch/sw_64/boot/dts/chip3.dts b/arch/sw_64/boot/dts/chip3.dts index 082506393ac9..502903040bbd 100644 --- a/arch/sw_64/boot/dts/chip3.dts +++ b/arch/sw_64/boot/dts/chip3.dts @@ -127,24 +127,20 @@ pvt: pvt@0x8030 { }; spi: spi@0x8032 { - #address-cells = <2>; - #size-cells = <2>; + #address-cells = <1>; + #size-cells = <0>; compatible = "sunway,chip3-spi"; reg = <0x8032 0x0 0x0 0x8000>; clocks = <&spiclk>; - interrupt-parent=<&intc>; - interrupts = <4>; + poll_mode = <1>; /* poll_mode:1 interrupt mode: 0 */ + reg-io-width = <2>; status = "okay"; flash@0 { - compatible = "winbond,w25q32dw", "jedec,spi-flash"; + compatible = "winbond,w25q32dw", "jedec,spi-nor"; spi-max-frequency = <25000000>; m25p,fast-read; - spi-cpha; - spi-cpol; - poll_mode = <1>; /* poll_mode:1 interrupt mode: 0 */ - reg-io-width = <2>; - reg = <0 0 0 0 >; /* 0: flash chip selected bit */ + reg = <0>; /* 0: flash chip selected bit */ partitions { compatible = "fixed-partitions"; @@ -159,14 +155,10 @@ partition@0 { }; flash@1 { - compatible = "winbond,w25q32dw", "jedec,spi-flash"; + compatible = "winbond,w25q32dw", "jedec,spi-nor"; spi-max-frequency = <25000000>; m25p,fast-read; - spi-cpha; - spi-cpol; - poll_mode = <1>; /* poll_mode:1 interrupt mode: 0 */ - reg-io-width = <2>; - reg = <1 0 0 0 >; /* 1: flash chip selected bit */ + reg = <1>; /* 1: flash chip selected bit */ partitions { compatible = "fixed-partitions"; diff --git a/drivers/spi/spi-chip3-mmio.c b/drivers/spi/spi-chip3-mmio.c index a907f13d4ae5..5e366457ddc8 100644 --- a/drivers/spi/spi-chip3-mmio.c +++ b/drivers/spi/spi-chip3-mmio.c @@ -53,12 +53,6 @@ static int chip3_spi_mmio_probe(struct platform_device *pdev) return PTR_ERR(dws->regs); } - dws->irq = platform_get_irq(pdev, 0); - if (dws->irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); - return dws->irq; /* -ENXIO */ - } - dwsmmio->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dwsmmio->clk)) return PTR_ERR(dwsmmio->clk); -- Gitee From cb30946f38323321e1a34eb8f62240ba85b55976 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Mon, 15 Jan 2024 09:27:28 +0800 Subject: [PATCH 29/98] sw64: dts: add chosen node Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- It is better to have a chosen node in the device tree. If not present, the newer kernel will give a warning. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/boot/dts/chip3.dts | 11 +++++++---- arch/sw_64/boot/dts/chip_vt.dts | 11 +++++++---- arch/sw_64/boot/dts/empty.dts | 11 +++++++---- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/arch/sw_64/boot/dts/chip3.dts b/arch/sw_64/boot/dts/chip3.dts index 502903040bbd..587f9427cbf6 100644 --- a/arch/sw_64/boot/dts/chip3.dts +++ b/arch/sw_64/boot/dts/chip3.dts @@ -5,10 +5,13 @@ /dts-v1/; / { - compatible = "sunway,chip3"; - model = "chip3"; - #address-cells = <2>; - #size-cells = <2>; + compatible = "sunway,chip3"; + model = "chip3"; + #address-cells = <2>; + #size-cells = <2>; + + chosen { + }; soc { compatible = "simple-bus"; diff --git a/arch/sw_64/boot/dts/chip_vt.dts b/arch/sw_64/boot/dts/chip_vt.dts index f26285367f98..0c7227755b1c 100644 --- a/arch/sw_64/boot/dts/chip_vt.dts +++ b/arch/sw_64/boot/dts/chip_vt.dts @@ -5,10 +5,13 @@ /dts-v1/; / { - compatible = "sunway,chip3"; - model = "chip3"; - #address-cells = <2>; - #size-cells = <2>; + compatible = "sunway,chip3"; + model = "chip3"; + #address-cells = <2>; + #size-cells = <2>; + + chosen { + }; soc { compatible = "simple-bus"; diff --git a/arch/sw_64/boot/dts/empty.dts b/arch/sw_64/boot/dts/empty.dts index f8fe34e29641..367f75d43107 100644 --- a/arch/sw_64/boot/dts/empty.dts +++ b/arch/sw_64/boot/dts/empty.dts @@ -5,10 +5,13 @@ /dts-v1/; / { - compatible = "sunway,chip3"; - model = "chip3"; - #address-cells = <2>; - #size-cells = <2>; + compatible = "sunway,chip3"; + model = "chip3"; + #address-cells = <2>; + #size-cells = <2>; + + chosen { + }; soc { }; -- Gitee From 79fd692c7254ef1dd0d21d62656624bd42b52921 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Mon, 15 Jan 2024 09:28:41 +0800 Subject: [PATCH 30/98] sw64: dts: fix interrupt related properties for GPIO Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- The GPIO controller can send two interrupts to the parent interrupt controller. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/boot/dts/chip3.dts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/sw_64/boot/dts/chip3.dts b/arch/sw_64/boot/dts/chip3.dts index 587f9427cbf6..0a1ef5305351 100644 --- a/arch/sw_64/boot/dts/chip3.dts +++ b/arch/sw_64/boot/dts/chip3.dts @@ -226,10 +226,9 @@ porta: gpio-contraller@0 { reg = <0 0 0 0>; interrupt-controller; #interrupt-cells = <2>; - interrupt-parent=<&intc>; - interrupts = <0>; - }; + interrupts-extended = <&intc 0>, <&intc 1>; }; + }; }; }; -- Gitee From ce4cac2d1598b2c45f370bc8749000bacb907597 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Mon, 15 Jan 2024 11:14:21 +0800 Subject: [PATCH 31/98] sw64: dts: improve properties for LPC-INTC Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Add some SW64 specific properties: sw64,node : interrupt controller on which node sw64,irq-num : number of interrupts supported sw64,ver : hardware version It should be noted that the LPC-INTC device node will no longer maintain backward compatibility after this commit. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/boot/dts/chip3.dts | 3 ++ drivers/irqchip/irq-sunway-lpc-intc.c | 40 ++++++++++++++++++++------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/arch/sw_64/boot/dts/chip3.dts b/arch/sw_64/boot/dts/chip3.dts index 0a1ef5305351..c60c84074dfc 100644 --- a/arch/sw_64/boot/dts/chip3.dts +++ b/arch/sw_64/boot/dts/chip3.dts @@ -45,6 +45,9 @@ lpc_intc: interrupt-controller@0x8037 { compatible = "sw64,lpc_intc"; reg = <0x8037 0x40000000 0x0 0x8000>; interrupt-controller; + sw64,node = <0>; + sw64,irq-num = <16>; + sw64,ver = <1>; #interrupt-cells = <1>; interrupt-parent = <&intc>; interrupts = <2>; diff --git a/drivers/irqchip/irq-sunway-lpc-intc.c b/drivers/irqchip/irq-sunway-lpc-intc.c index b594ddb6eb24..bc69d1647aed 100644 --- a/drivers/irqchip/irq-sunway-lpc-intc.c +++ b/drivers/irqchip/irq-sunway-lpc-intc.c @@ -7,7 +7,8 @@ #include #include -#define LPC_NR_IRQS 16 +#define PREFIX "LPC-INTC: " + #define LPC_IRQ 0x4 #define LPC_IRQ_MASK 0x8 @@ -122,36 +123,56 @@ static int __init lpc_intc_of_init(struct device_node *np, { struct irq_domain *lpc_domain; int ret; + u32 nr_irqs, node, version; void __iomem *base; + if (WARN_ON(!np || !parent)) + return -ENODEV; + sw_lpc_intc_node = np; - if (!parent) { - pr_err("no parent intc found\n"); - return -ENXIO; + ret = of_property_read_u32(np, "sw64,node", &node); + if (ret) { + pr_err(PREFIX "\"sw64,node\" not found\n"); + return -EINVAL; + } + + ret = of_property_read_u32(np, "sw64,irq-num", &nr_irqs); + if (ret) { + pr_err(PREFIX "\"sw64,irq-num\" not found\n"); + return -EINVAL; + } + + ret = of_property_read_u32(np, "sw64,ver", &version); + if (ret) { + pr_err(PREFIX "\"sw64,ver\" not found\n"); + return -EINVAL; } base = of_iomap(np, 0); if (!base) { - pr_err("failed to remap lpc intc registers\n"); - ret = -ENOMEM; - goto out_free; + pr_err(PREFIX "failed to remap lpc intc registers\n"); + return -ENXIO; } parent_irq = irq_of_parse_and_map(np, 0); if (!parent_irq) { - pr_err("failed to find parent interrupt\n"); + pr_err(PREFIX "failed to find parent interrupt\n"); ret = -EINVAL; goto out_unmap; } - lpc_domain = irq_domain_add_legacy(np, LPC_NR_IRQS, + lpc_domain = irq_domain_add_legacy(np, nr_irqs, 0, 0, &sw64_lpc_domain_ops, base); if (!lpc_domain) { + pr_err(PREFIX "failed to create irq domain\n"); ret = -ENOMEM; goto out_unmap; } + pr_info(PREFIX "version [%u] on node [%u] initialized\n", + version, node); + /* Set the IRQ chaining logic */ irq_set_chained_handler_and_data(parent_irq, lpc_irq_handler, lpc_domain); @@ -160,7 +181,6 @@ static int __init lpc_intc_of_init(struct device_node *np, out_unmap: iounmap(base); -out_free: return ret; } IRQCHIP_DECLARE(sw_lpc_intc, "sw64,lpc_intc", lpc_intc_of_init); -- Gitee From a71a425547a5d26b8b87b96442f69ae1b6165335 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 16 Jan 2024 10:16:37 +0800 Subject: [PATCH 32/98] sw64: dts: improve properties for PINTC Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Firstly, add some SW64 specific properties: sw64,node : interrupt controller on which node sw64,irq-num : number of interrupts supported sw64,ver : hardware version Secondly, the "reg" property is added to pass the base address of PINTC registers, decoupling the driver code and hardware. Thirdly, some refactoring is done, making each PINTC chip a chip data instead of each irq a chip data. It should be noted that the PINTC device node will no longer maintain backward compatibility after this commit. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/boot/dts/chip3.dts | 21 +- arch/sw_64/boot/dts/chip_vt.dts | 13 +- arch/sw_64/include/asm/uncore_io_junzhang.h | 2 - arch/sw_64/include/asm/uncore_io_xuelang.h | 2 - drivers/irqchip/irq-sunway-pintc.c | 306 +++++++++++--------- 5 files changed, 193 insertions(+), 151 deletions(-) diff --git a/arch/sw_64/boot/dts/chip3.dts b/arch/sw_64/boot/dts/chip3.dts index c60c84074dfc..0e9ad8f5d464 100644 --- a/arch/sw_64/boot/dts/chip3.dts +++ b/arch/sw_64/boot/dts/chip3.dts @@ -35,9 +35,14 @@ spiclk: spiclk { }; - intc: interrupt-controller { - compatible = "sw64,sw6_irq_controller"; + pintc: interrupt-controller { + compatible = "sw64,pintc"; interrupt-controller; + sw64,node = <0>; + sw64,irq-num = <8>; + sw64,ver = <1>; + reg = <0x802a 0x0 0x0 0x1680>, + <0x8030 0x0 0x0 0x8f00>; #interrupt-cells = <1>; }; @@ -49,7 +54,7 @@ lpc_intc: interrupt-controller@0x8037 { sw64,irq-num = <16>; sw64,ver = <1>; #interrupt-cells = <1>; - interrupt-parent = <&intc>; + interrupt-parent = <&pintc>; interrupts = <2>; }; @@ -58,7 +63,7 @@ uart: serial0@8033 { #size-cells = <2>; compatible = "sw6,sunway-apb-uart"; reg = <0x8033 0x0 0x0 0x1000>; - interrupt-parent=<&intc>; + interrupt-parent=<&pintc>; interrupts = <3>; reg-shift = <9>; reg-io-width = <4>; @@ -85,7 +90,7 @@ i2c0@0x8031 { reg = <0x8031 0x0 0x0 0x8000>; clock-frequency = <100000>; clocks = <&i2cclk>; - interrupt-parent=<&intc>; + interrupt-parent = <&pintc>; interrupts = <5>; status = "okay"; }; @@ -97,7 +102,7 @@ i2c1@0x8034 { reg = <0x8034 0x0 0x0 0x8000>; clock-frequency = <100000>; clocks = <&i2cclk>; - interrupt-parent=<&intc>; + interrupt-parent = <&pintc>; interrupts = <6>; status = "okay"; }; @@ -109,7 +114,7 @@ i2c2@0x8035 { reg = <0x8035 0x0 0x0 0x8000>; clock-frequency = <100000>; clocks = <&i2cclk>; - interrupt-parent=<&intc>; + interrupt-parent = <&pintc>; interrupts = <7>; status = "okay"; @@ -229,7 +234,7 @@ porta: gpio-contraller@0 { reg = <0 0 0 0>; interrupt-controller; #interrupt-cells = <2>; - interrupts-extended = <&intc 0>, <&intc 1>; + interrupts-extended = <&pintc 0>, <&pintc 1>; }; }; diff --git a/arch/sw_64/boot/dts/chip_vt.dts b/arch/sw_64/boot/dts/chip_vt.dts index 0c7227755b1c..9889fcae7a5c 100644 --- a/arch/sw_64/boot/dts/chip_vt.dts +++ b/arch/sw_64/boot/dts/chip_vt.dts @@ -19,9 +19,12 @@ soc { #size-cells = <2>; ranges; - intc: interrupt-controller{ - compatible = "sw64,sw6_irq_vt_controller"; + pintc: interrupt-controller { + compatible = "sw64,pintc_vt"; interrupt-controller; + sw64,node = <0>; + sw64,irq-num = <16>; + sw64,ver = <1>; #interrupt-cells = <1>; }; @@ -30,25 +33,27 @@ uart: serial0@8801 { #size-cells = <2>; compatible = "ns16550a"; reg = <0x8801 0x3f8 0x0 0x10>; - interrupt-parent=<&intc>; + interrupt-parent = <&pintc>; interrupts = <12>; reg-shift = <0>; reg-io-width = <1>; clock-frequency = <24000000>; status = "okay"; }; + misc: misc0@8036 { #address-cells = <2>; #size-cells = <2>; compatible = "sw6,sunway-ged"; reg = <0x8036 0x0 0x0 0x20>; - interrupt-parent=<&intc>; + interrupt-parent = <&pintc>; interrupts = <13>; reg-shift = <0>; reg-io-width = <8>; clock-frequency = <24000000>; status = "okay"; }; + fw_cfg: fw_cfg@8049 { dma-coherent; reg = <0x8049 0x20000000 0x0 0x18>; diff --git a/arch/sw_64/include/asm/uncore_io_junzhang.h b/arch/sw_64/include/asm/uncore_io_junzhang.h index ac37d186a29f..37cfe1fd6807 100644 --- a/arch/sw_64/include/asm/uncore_io_junzhang.h +++ b/arch/sw_64/include/asm/uncore_io_junzhang.h @@ -70,8 +70,6 @@ #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 873f7e86f83b..aeaadec5be16 100644 --- a/arch/sw_64/include/asm/uncore_io_xuelang.h +++ b/arch/sw_64/include/asm/uncore_io_xuelang.h @@ -74,8 +74,6 @@ #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/irqchip/irq-sunway-pintc.c b/drivers/irqchip/irq-sunway-pintc.c index 8d789fd255c8..d65c788e354e 100644 --- a/drivers/irqchip/irq-sunway-pintc.c +++ b/drivers/irqchip/irq-sunway-pintc.c @@ -4,93 +4,107 @@ #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; +#include +#include + +#define PREFIX "PINTC: " + +#define OFFSET_MCU_DVC_INT_EN 0x3080UL + +#define OFFSET_DEV_INT_CONFIG 0x480UL + +struct pintc_chip_data { + bool vt; /* virtual pintc */ + u32 node; /* node ID */ + u32 version; /* PINTC version */ + void __iomem *pintc_base; /* INTPU base address */ + void __iomem *mcu_base; /* MCU/SPBU base address */ }; -static DEFINE_RAW_SPINLOCK(devint_lock); +static DEFINE_RAW_SPINLOCK(pintc_lock); static void lock_dev_lock(void) { - raw_spin_lock(&devint_lock); + raw_spin_lock(&pintc_lock); } static void unlock_dev_lock(void) { - raw_spin_unlock(&devint_lock); + raw_spin_unlock(&pintc_lock); } static void mcu_irq_mask(struct irq_data *data) { - struct devint_chipdata *chip_data = data->chip_data; - unsigned int mask; + struct pintc_chip_data *chip_data = data->chip_data; + unsigned long mask; int hwirq = data->hwirq; - int node; - node = chip_data->node; - - mask = sw64_io_read(node, MCU_DVC_INT_EN); + mask = readq(chip_data->mcu_base + OFFSET_MCU_DVC_INT_EN); mask &= ~(0x1UL << hwirq); - sw64_io_write(node, MCU_DVC_INT_EN, mask); + writeq(mask, chip_data->mcu_base + OFFSET_MCU_DVC_INT_EN); } static void mcu_irq_unmask(struct irq_data *data) { - struct devint_chipdata *chip_data = data->chip_data; - unsigned int mask; + struct pintc_chip_data *chip_data = data->chip_data; + unsigned long mask; int hwirq = data->hwirq; - int node; - - node = chip_data->node; - mask = sw64_io_read(node, MCU_DVC_INT_EN); + mask = readq(chip_data->mcu_base + OFFSET_MCU_DVC_INT_EN); mask |= (0x1UL << hwirq); - sw64_io_write(node, MCU_DVC_INT_EN, mask); + writeq(mask, chip_data->mcu_base + OFFSET_MCU_DVC_INT_EN); } static void mcu_irq_enable(struct irq_data *irq_data) { - struct devint_chipdata *data = irq_data->chip_data; + struct pintc_chip_data *chip_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 = readq(chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); devint_conf |= (1UL << 8); - sw64_io_write(node, DEV_INT_CONFIG, devint_conf); + writeq(devint_conf, chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); mcu_irq_unmask(irq_data); } static void mcu_irq_disable(struct irq_data *irq_data) { - struct devint_chipdata *data = irq_data->chip_data; + struct pintc_chip_data *chip_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 = readq(chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); devint_conf &= ~(1UL << 8); - sw64_io_write(node, DEV_INT_CONFIG, devint_conf); + writeq(devint_conf, chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); mcu_irq_mask(irq_data); } -static int __assign_mcu_irq_config(int node, cpumask_t *targets) +static unsigned long make_mcu_int_target(u32 version, int rcid) +{ + int node, core, thread; + unsigned long target = 0; + + thread = rcid_to_thread_id(rcid); + core = rcid_to_core_id(rcid); + node = rcid_to_domain_id(rcid); + + switch (version) { + case 0x1: /* PINTC v1 */ + target = core | (thread << 5) | (node << 6); + break; + case 0x2: /* PINTC v2 */ + target = core | (thread << 6) | (node << 7); + break; + default: + break; + } + + return target; +} + +static int __assign_mcu_irq_config(const struct pintc_chip_data *chip_data, + cpumask_t *targets) { unsigned long dev_int_tar, val; unsigned int cpu; - int phy_cpu; + int rcid; for_each_cpu(cpu, targets) { /* @@ -98,7 +112,7 @@ static int __assign_mcu_irq_config(int node, cpumask_t *targets) * cores only. Thus, we remove all off-node cpu in the * target mask. */ - if (cpu_to_node(cpu) != node) + if (cpu_to_node(cpu) != chip_data->node) cpumask_clear_cpu(cpu, targets); } @@ -107,23 +121,24 @@ static int __assign_mcu_irq_config(int node, cpumask_t *targets) if (cpu >= nr_cpu_ids) return -EPERM; - phy_cpu = cpu_to_rcid(cpu); + rcid = cpu_to_rcid(cpu); - val = sw64_io_read(node, DEV_INT_CONFIG); - dev_int_tar = DEV_INT_TARGET(phy_cpu); + val = readq(chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); + dev_int_tar = make_mcu_int_target(chip_data->version, rcid); val &= 0xffff; val |= dev_int_tar << 16; - sw64_io_write(node, DEV_INT_CONFIG, val); + writeq(val, chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); return 0; } -static int assign_mcu_irq_config(int node, cpumask_t *targets) +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(node, targets); + ret = __assign_mcu_irq_config(chip_data, targets); unlock_dev_lock(); return ret; @@ -132,25 +147,23 @@ static int assign_mcu_irq_config(int node, cpumask_t *targets) 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; + struct pintc_chip_data *chip_data = irq_data->chip_data; cpumask_t targets; - int node, ret = 0; + int 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); + ret = assign_mcu_irq_config(chip_data, &targets); mcu_irq_enable(irq_data); return ret; } -static struct irq_chip onchip_intc = { +static struct irq_chip pintc_mcu_chip = { .name = "MCU-INT", .irq_enable = mcu_irq_enable, .irq_disable = mcu_irq_disable, @@ -159,75 +172,40 @@ static struct irq_chip onchip_intc = { .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, +static void pintc_mcu_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(); - } - } + irq_domain_free_irqs_top(irq_domain, virq, nr_irqs); + + for (i = 0; i < nr_irqs; i++) + irq_clear_status_flags(virq + i, IRQ_LEVEL); } -static int sw64_intc_alloc_irqs(struct irq_domain *irq_domain, +static int pintc_mcu_alloc_irqs(struct irq_domain *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; + irq_hw_number_t hwirq = fwspec->param[0]; + int i; 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); + irq_domain_set_info(domain, virq + i, hwirq + i, + &pintc_mcu_chip, domain->host_data, + handle_level_irq, NULL, NULL); + irq_set_status_flags(virq + i, 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 = { +static const struct irq_domain_ops pintc_mcu_domain_ops = { .xlate = irq_domain_xlate_onecell, - .alloc = sw64_intc_alloc_irqs, - .free = sw64_intc_free_irqs, + .alloc = pintc_mcu_alloc_irqs, + .free = pintc_mcu_free_irqs, }; struct irq_domain *mcu_irq_domain; @@ -235,53 +213,111 @@ EXPORT_SYMBOL(mcu_irq_domain); #ifdef CONFIG_OF static int __init -init_mcu_IRQ(struct device_node *intc, struct device_node *parent) +pintc_of_init_common(struct device_node *pintc, + struct device_node *parent, bool vt) { - if (parent) { - pr_warn("DeviceTree incore intc not a root irq controller\n"); + int ret; + u32 nr_irqs, node, version; + void __iomem *pintc_base; + void __iomem *mcu_base; + struct pintc_chip_data *chip_data; + + if (WARN_ON(!pintc)) return -ENODEV; - } - mcu_irq_domain = irq_domain_add_linear(intc, 8, - &sw64_intc_domain_ops, NULL); + if (vt && parent) { + pr_err(PREFIX "virtual pintc has no parent controller\n"); + return -EINVAL; + } - if (!mcu_irq_domain) { - pr_warn("root irq domain not avail\n"); - return -ENODEV; + ret = of_property_read_u32(pintc, "sw64,node", &node); + if (ret) { + pr_err(PREFIX "\"sw64,node\" not found\n"); + return -EINVAL; } - /* with this we don't need to export root_domain */ - irq_set_default_host(mcu_irq_domain); + ret = of_property_read_u32(pintc, "sw64,irq-num", &nr_irqs); + if (ret) { + pr_err(PREFIX "\"sw64,irq-num\" not found\n"); + return -EINVAL; + } - /* mask all interrupts for now */ - sw64_io_write(cpu_node, MCU_DVC_INT_EN, 0x0); + ret = of_property_read_u32(pintc, "sw64,ver", &version); + if (ret) { + pr_err(PREFIX "\"sw64,ver\" not found\n"); + return -EINVAL; + } - return 0; -} + pintc_base = of_iomap(pintc, 0); + if (!pintc_base) { + pr_err(PREFIX "failed to map pintc base address\n"); + return -ENXIO; + } -IRQCHIP_DECLARE(sw64_intc, "sw64,sw6_irq_controller", init_mcu_IRQ); + mcu_base = of_iomap(pintc, 1); + if (!mcu_base) { + pr_err(PREFIX "failed to map mcu base address\n"); + ret = -ENXIO; + goto out_unmap0; + } -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; + chip_data = kzalloc_node(sizeof(*chip_data), GFP_KERNEL, node); + if (!chip_data) { + ret = -ENOMEM; + goto out_unmap1; } - mcu_irq_domain = irq_domain_add_legacy(intc, 16, 0, 0, - &sw64_intc_domain_ops, NULL); + chip_data->vt = vt; + chip_data->node = node; + chip_data->version = version; + chip_data->pintc_base = pintc_base; + chip_data->mcu_base = mcu_base; + + if (vt) + mcu_irq_domain = irq_domain_add_legacy(pintc, nr_irqs, 0, 0, + &pintc_mcu_domain_ops, chip_data); + else { + mcu_irq_domain = irq_domain_add_linear(pintc, nr_irqs, + &pintc_mcu_domain_ops, chip_data); + /* mask all interrupts for now */ + writeq(0x0, mcu_base + OFFSET_MCU_DVC_INT_EN); + } if (!mcu_irq_domain) { - pr_warn("root irq domain not avail\n"); - return -ENODEV; + pr_err(PREFIX "failed to create irq domain\n"); + ret = -ENOMEM; + goto out_free_mem; } - /* with this we don't need to export root_domain */ + pr_info(PREFIX "version [%u] on node [%u] initialized\n", + version, node); + irq_set_default_host(mcu_irq_domain); return 0; + +out_free_mem: + kfree(chip_data); +out_unmap1: + iounmap(mcu_base); +out_unmap0: + iounmap(pintc_base); + return ret; +} + +static int __init +pintc_of_init(struct device_node *pintc, struct device_node *parent) +{ + return pintc_of_init_common(pintc, parent, false); +} + +IRQCHIP_DECLARE(sw64_pintc, "sw64,pintc", pintc_of_init); + +static int __init +pintc_vt_of_init(struct device_node *pintc, struct device_node *parent) +{ + return pintc_of_init_common(pintc, parent, true); } -IRQCHIP_DECLARE(sw64_vt_intc, "sw64,sw6_irq_vt_controller", init_mcu_vt_IRQ); +IRQCHIP_DECLARE(sw64_pintc_vt, "sw64,pintc_vt", pintc_vt_of_init); #endif -- Gitee From e20bb849c2044010743b41937a63d8baf33d2d54 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 1 Feb 2024 15:35:31 +0800 Subject: [PATCH 33/98] sw64: irqchip: fix virtual PINTC not working properly Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Virtual PINTC is different from the physical one in the following aspects: - Virtual PINTC does not have the registers used in physical PINTC - The topology of virtual interrupt controllers containing virtual PINTC is a flat structure, which is different from the physical one Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/irqchip/irq-sunway-pintc.c | 37 ++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/drivers/irqchip/irq-sunway-pintc.c b/drivers/irqchip/irq-sunway-pintc.c index d65c788e354e..41c52f9fb09b 100644 --- a/drivers/irqchip/irq-sunway-pintc.c +++ b/drivers/irqchip/irq-sunway-pintc.c @@ -19,6 +19,7 @@ struct pintc_chip_data { u32 version; /* PINTC version */ void __iomem *pintc_base; /* INTPU base address */ void __iomem *mcu_base; /* MCU/SPBU base address */ + struct irq_chip *mcu_chip; }; static DEFINE_RAW_SPINLOCK(pintc_lock); @@ -172,6 +173,10 @@ static struct irq_chip pintc_mcu_chip = { .irq_set_affinity = mcu_irq_set_affinity, }; +static struct irq_chip pintc_mcu_vt_chip = { + .name = "VMCU-INT", +}; + static void pintc_mcu_free_irqs(struct irq_domain *irq_domain, unsigned int virq, unsigned int nr_irqs) { @@ -183,6 +188,19 @@ static void pintc_mcu_free_irqs(struct irq_domain *irq_domain, irq_clear_status_flags(virq + i, IRQ_LEVEL); } +static int pintc_mcu_map_irq(struct irq_domain *domain, + unsigned int virq, irq_hw_number_t hwirq) +{ + struct pintc_chip_data *chip_data = domain->host_data; + + irq_domain_set_info(domain, virq, hwirq, + chip_data->mcu_chip, chip_data, + handle_level_irq, NULL, NULL); + irq_set_status_flags(virq, IRQ_LEVEL); + + return 0; +} + static int pintc_mcu_alloc_irqs(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, @@ -192,17 +210,14 @@ static int pintc_mcu_alloc_irqs(struct irq_domain *domain, irq_hw_number_t hwirq = fwspec->param[0]; int i; - for (i = 0; i < nr_irqs; i++) { - irq_domain_set_info(domain, virq + i, hwirq + i, - &pintc_mcu_chip, domain->host_data, - handle_level_irq, NULL, NULL); - irq_set_status_flags(virq + i, IRQ_LEVEL); - } + for (i = 0; i < nr_irqs; i++) + pintc_mcu_map_irq(domain, virq + i, hwirq + i); return 0; } static const struct irq_domain_ops pintc_mcu_domain_ops = { + .map = pintc_mcu_map_irq, .xlate = irq_domain_xlate_onecell, .alloc = pintc_mcu_alloc_irqs, .free = pintc_mcu_free_irqs, @@ -249,13 +264,13 @@ pintc_of_init_common(struct device_node *pintc, } pintc_base = of_iomap(pintc, 0); - if (!pintc_base) { + if (!vt && !pintc_base) { pr_err(PREFIX "failed to map pintc base address\n"); return -ENXIO; } mcu_base = of_iomap(pintc, 1); - if (!mcu_base) { + if (!vt && !mcu_base) { pr_err(PREFIX "failed to map mcu base address\n"); ret = -ENXIO; goto out_unmap0; @@ -273,10 +288,12 @@ pintc_of_init_common(struct device_node *pintc, chip_data->pintc_base = pintc_base; chip_data->mcu_base = mcu_base; - if (vt) + if (vt) { + chip_data->mcu_chip = &pintc_mcu_vt_chip; mcu_irq_domain = irq_domain_add_legacy(pintc, nr_irqs, 0, 0, &pintc_mcu_domain_ops, chip_data); - else { + } else { + chip_data->mcu_chip = &pintc_mcu_chip; mcu_irq_domain = irq_domain_add_linear(pintc, nr_irqs, &pintc_mcu_domain_ops, chip_data); /* mask all interrupts for now */ -- Gitee From ca13c5b1c0987b96229c5761c0aa8e5e651f96ff Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Fri, 2 Feb 2024 18:02:05 +0000 Subject: [PATCH 34/98] sw64: pci: change pci transaction ordering rule settings Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Due to the risk of commit da4d8d735527 ("sw_64: pci: change pci transaction ordering rule settings"), running ltpstress on SW8A virtual machine cause IOMMU to report an error that the AHCI device level-3 page table is invalid. The AHCI driver reads the IO register to learn that the command has completed and then releases the dma address corresponding to the command. However, since Completion is permitted to pass a Posted Request, IO response has come back but the DMA write is not actually finished. To solve this problem, on SW8A platform, we change PCI transaction ordering settings by disabling CPL_PASS_P bit in RC's ORDER_RULE_CTRL register to ensure that a Completion must not pass a Posted Request. Signed-off-by: Zheng Chongzhen 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 4e6a12765bf3..7cd612bb82bb 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -205,7 +205,9 @@ static void set_rc_piu(unsigned long node, unsigned long index) write_rc_conf(node, index, RC_PORT_LINK_CTL, 0x1f0020); write_rc_conf(node, index, RC_EXP_DEVCTL, 0x2850); write_rc_conf(node, index, RC_EXP_DEVCTL2, 0x6); +#ifdef CONFIG_UNCORE_XUELANG write_rc_conf(node, index, RC_ORDER_RULE_CTL, 0x0100); +#endif /* enable DBI_RO_WR_EN */ rc_misc_ctrl = read_rc_conf(node, index, RC_MISC_CONTROL_1); -- Gitee From bdceaa50cf1a903cb0eb9d95ff103bd4cfa98e09 Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Tue, 6 Feb 2024 14:28:23 +0000 Subject: [PATCH 35/98] sw64: msi: fix bugs in multi-msi interrupts allocation and release Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- First, according to the definition of the PCI bus specification (Rev. 4.0 Version 1.0, 7.7.1.5 "Message Data Register for MSI"), the first vector assigned to multi-msi interrupts must be aligned to the number of allocation. Second, since each irq_data of multi-msi interrupts corresponds to the same chip_data, it can only be released when all multi-msi interrupts have been released. Signed-off-by: Zheng Chongzhen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/irqchip/irq-sunway-msi-v2.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/irqchip/irq-sunway-msi-v2.c b/drivers/irqchip/irq-sunway-msi-v2.c index 36790dfedb33..698c5c86408a 100644 --- a/drivers/irqchip/irq-sunway-msi-v2.c +++ b/drivers/irqchip/irq-sunway-msi-v2.c @@ -90,7 +90,7 @@ static bool find_free_cpu_vectors(const struct cpumask *search_mask, int *found_ cpu = cpumask_first(search_mask); try_again: - for (vector = 0; vector < 256; vector++) { + for (vector = 0; vector < 256; vector += nr_irqs) { for (i = 0; i < nr_irqs; i++) if (per_cpu(vector_irq, cpu)[vector + i]) break; @@ -101,8 +101,6 @@ static bool find_free_cpu_vectors(const struct cpumask *search_mask, int *found_ *found_vector = vector; return found; } - - vector += i; } cpu = cpumask_next(cpu, search_mask); @@ -211,7 +209,6 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs, struct sw64_msi_chip_data *cdata; int node; int i, vector, cpu; - unsigned long msiaddr; if (unlikely((nr_irqs > 1) && (!is_power_of_2(nr_irqs)))) nr_irqs = __roundup_pow_of_two(nr_irqs); @@ -307,10 +304,9 @@ static int assign_irq_vector(int irq, unsigned int nr_irqs, static void sw64_vector_free_irqs(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs) { - int i, j; + int i; struct irq_data *irq_data; unsigned long flags; - unsigned int multi_msi; for (i = 0; i < nr_irqs; i++) { irq_data = irq_domain_get_irq_data(domain, virq + i); @@ -320,13 +316,15 @@ static void sw64_vector_free_irqs(struct irq_domain *domain, raw_spin_lock_irqsave(&vector_lock, flags); cdata = irq_data->chip_data; irq_domain_reset_irq_data(irq_data); - multi_msi = cdata->multi_msi; - for (j = 0; j < multi_msi; j++) - per_cpu(vector_irq, cdata->dst_cpu)[cdata->vector + j] = 0; - kfree(cdata); + cdata->multi_msi--; + per_cpu(vector_irq, cdata->dst_cpu)[cdata->vector] = 0; + + if (cdata->multi_msi) + cdata->vector++; + + if (cdata->multi_msi == 0) + kfree(cdata); raw_spin_unlock_irqrestore(&vector_lock, flags); - if (multi_msi > 1) - break; } } } -- Gitee From ead876033c482d687ce1088bf42bf3b5210058b7 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 20 Feb 2024 14:31:53 +0800 Subject: [PATCH 36/98] sw64: improve sw64_printk() Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Skip printk headers before writing into sw64_printk_buf, so we won't have unprintable characters in it. Make sw64_printk() void since the return value is never used. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/dup_print.c | 34 ++++++++++++++++++++-------------- kernel/printk/printk.c | 2 +- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/arch/sw_64/kernel/dup_print.c b/arch/sw_64/kernel/dup_print.c index 439ac75feb01..eef31527dc13 100644 --- a/arch/sw_64/kernel/dup_print.c +++ b/arch/sw_64/kernel/dup_print.c @@ -15,33 +15,39 @@ static DEFINE_SPINLOCK(printk_lock); unsigned long sw64_printk_offset; #define PRINTK_SIZE 0x100000UL -int sw64_printk(const char *fmt, va_list args) +void sw64_printk(const char *fmt, va_list args) { char *sw64_printk_buf; - int printed_len = 0; unsigned long flags; + char textbuf[1024]; + const char *text; + size_t text_len; spin_lock_irqsave(&printk_lock, flags); sw64_printk_buf = (char *)(KERNEL_PRINTK_BUFF_BASE + sw64_printk_offset); - if (sw64_printk_offset >= (PRINTK_SIZE-1024)) { //printk wrapped + text_len = vscnprintf(textbuf, sizeof(textbuf), fmt, args); + text = printk_skip_headers(textbuf); + text_len -= text - textbuf; + + if (sw64_printk_offset >= (PRINTK_SIZE - 1024)) { sw64_printk_offset = 0; sw64_printk_buf = (char *)(KERNEL_PRINTK_BUFF_BASE + sw64_printk_offset); memset(sw64_printk_buf, 0, PRINTK_SIZE); - printed_len += vscnprintf(sw64_printk_buf, 1024, fmt, args); - } else { - printed_len += vscnprintf(sw64_printk_buf, 1024, fmt, args); - if (is_in_emul()) { - void __iomem *addr = __va(QEMU_PRINTF_BUFF_BASE); - u64 data = ((u64)sw64_printk_buf & 0xffffffffUL) - | ((u64)printed_len << 32); - *(u64 *)addr = data; - } } - sw64_printk_offset += printed_len; + + memcpy(sw64_printk_buf, text, text_len); + sw64_printk_offset += text_len; + + if (is_in_emul()) { + void __iomem *addr = __va(QEMU_PRINTF_BUFF_BASE); + u64 data = ((u64)sw64_printk_buf & 0xffffffffUL) + | ((u64)text_len << 32); + *(u64 *)addr = data; + } + spin_unlock_irqrestore(&printk_lock, flags); - return printed_len; } #endif diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index b4e390e0b4bd..8b04d093263f 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2203,7 +2203,7 @@ int vprintk_store(int facility, int level, int ret = 0; u64 ts_nsec; #ifdef CONFIG_SW64_RRK - extern int sw64_printk(const char *fmt, va_list args); + extern void sw64_printk(const char *fmt, va_list args); #endif if (!printk_enter_irqsave(recursion_ptr, irqflags)) -- Gitee From 163cacecd0ceb892d3d1386cb6d6071700c0ef5f Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 20 Feb 2024 16:10:20 +0800 Subject: [PATCH 37/98] sw64: add a new kernel parameter to override mclk Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Add a new cmdline parameter to override the mclk we have got. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/clocksource/timer-sw64.c | 40 +++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/clocksource/timer-sw64.c b/drivers/clocksource/timer-sw64.c index 615e8a2ed63a..a2f4caced0a3 100644 --- a/drivers/clocksource/timer-sw64.c +++ b/drivers/clocksource/timer-sw64.c @@ -13,8 +13,7 @@ #include #include -#define SHTCLK_RATE_KHZ 25000 -#define SHTCLK_RATE (SHTCLK_RATE_KHZ * 1000) +#define DEFAULT_MCLK 25000 /* Khz */ #if defined(CONFIG_SUBARCH_C4) static u64 read_longtime(struct clocksource *cs) @@ -37,10 +36,31 @@ static u64 notrace read_sched_clock(void) return sw64_read_csr(CSR_SHTCLOCK); } +static int override_mclk_khz; +static int __init setup_mclk(char *str) +{ + get_option(&str, &override_mclk_khz); + + return 0; +} +early_param("mclk_khz", setup_mclk); + void __init sw64_setup_clocksource(void) { - clocksource_register_khz(&clocksource_longtime, SHTCLK_RATE_KHZ); - sched_clock_register(read_sched_clock, BITS_PER_LONG, SHTCLK_RATE); + unsigned long mclk_khz = *((unsigned char *)__va(MB_MCLK)) * 1000; + + if (override_mclk_khz) { + mclk_khz = override_mclk_khz; + pr_info("Override mclk by cmdline.\n"); + } + + if (!mclk_khz) + mclk_khz = DEFAULT_MCLK; + + pr_info("mclk: %ldKhz\n", mclk_khz); + + clocksource_register_khz(&clocksource_longtime, mclk_khz); + sched_clock_register(read_sched_clock, BITS_PER_LONG, mclk_khz * 1000); } void __init setup_sched_clock(void) { } @@ -122,20 +142,18 @@ static struct clocksource clocksource_tc = { }; #endif /* SMP */ -#define DEFAULT_MCLK 25 /* Mhz */ - void __init sw64_setup_clocksource(void) { - unsigned int mclk = *((unsigned char *)__va(MB_MCLK)); + unsigned long mclk_khz = *((unsigned char *)__va(MB_MCLK)) * 1000; - if (!mclk) - mclk = DEFAULT_MCLK; + if (!mclk_khz) + mclk_khz = DEFAULT_MCLK; #ifdef CONFIG_SMP if (is_in_host()) - clocksource_register_khz(&clocksource_longtime, mclk * 1000); + clocksource_register_khz(&clocksource_longtime, mclk_khz); else - clocksource_register_khz(&clocksource_vtime, DEFAULT_MCLK * 1000); + clocksource_register_khz(&clocksource_vtime, mclk_khz); #else clocksource_register_hz(&clocksource_tc, get_cpu_freq()); pr_info("Setup clocksource TC, mult = %d\n", clocksource_tc.mult); -- Gitee From dac7a0cdd884b7bccb0ae9b92204e5ce5bfce610 Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Mon, 15 Jan 2024 17:09:59 +0800 Subject: [PATCH 38/98] sw64: add four-socket system support Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Allow a maximum of 512 cpus to support 4-socket servers. Signed-off-by: Wu Liliu Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 7 ++++--- arch/sw_64/configs/junzhang_defconfig | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 0fd1be7195cc..bc85bebde3be 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -396,12 +396,13 @@ config SCHED_SMT places. If unsure say N here. config NR_CPUS - int "Maximum number of CPUs (2-256)" - range 2 256 + int "Maximum number of CPUs (2-512)" + range 2 512 depends on SMP default "64" if UNCORE_XUELANG + default "512" if UNCORE_JUNZHANG help - SW6 support can handle a maximum of 256 CPUs. + SW64 support can handle a maximum of 512 CPUs. config HOTPLUG_CPU bool "Support for hot-pluggable CPUs" diff --git a/arch/sw_64/configs/junzhang_defconfig b/arch/sw_64/configs/junzhang_defconfig index 4f25770ca193..0459d08fd40d 100644 --- a/arch/sw_64/configs/junzhang_defconfig +++ b/arch/sw_64/configs/junzhang_defconfig @@ -28,7 +28,7 @@ CONFIG_DEBUG_PERF_USE_VMALLOC=y CONFIG_SUBARCH_C4=y CONFIG_SMP=y CONFIG_SCHED_SMT=y -CONFIG_NR_CPUS=64 +CONFIG_NR_CPUS=512 CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_NUMA=y CONFIG_HZ=100 -- Gitee From a35f6a3021fa32d31999416287a8db47fa4158c2 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 12 Dec 2023 16:27:59 +0800 Subject: [PATCH 39/98] sw64: enable hardware denorm by default Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Enable hardware denormalized number processing by default to improve performance. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/uapi/asm/fpu.h | 2 ++ arch/sw_64/kernel/process.c | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/sw_64/include/uapi/asm/fpu.h b/arch/sw_64/include/uapi/asm/fpu.h index 7a1514c978b9..7f88cfb9399d 100644 --- a/arch/sw_64/include/uapi/asm/fpu.h +++ b/arch/sw_64/include/uapi/asm/fpu.h @@ -6,6 +6,7 @@ * SW-64 floating-point control register defines: */ #define FPCR_DNOD (1UL << 47) /* denorm INV trap disable */ +#define FPCR_DNZ (1UL << 48) /* denorms to zero */ #define FPCR_DNOE (1UL << 48) /* hardware denormal support */ #define FPCR_INVD (1UL << 49) /* invalid op disable (opt.) */ #define FPCR_DZED (1UL << 50) /* division by zero disable (opt.) */ @@ -96,6 +97,7 @@ /* Denorm and Underflow flushing */ #define IEEE_MAP_DMZ (1UL << 12) /* Map denorm inputs to zero */ +#define IEEE_HARD_DM (1UL << 12) /* Hardware denorm processing */ #define IEEE_MAP_UMZ (1UL << 13) /* Map underflowed outputs to zero */ #define IEEE_MAP_MASK (IEEE_MAP_DMZ | IEEE_MAP_UMZ) diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index 4f3a3a8b4123..cd371a71cfca 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -34,12 +34,13 @@ flush_thread(void) /* Arrange for each exec'ed process to start off with a clean slate * 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)); + unsigned int *ieee_state = ¤t_thread_info()->ieee_state; + + *ieee_state = 0; +#ifndef CONFIG_SUBARCH_C3B + *ieee_state |= IEEE_HARD_DM; #endif + wrfpcr(FPCR_INIT | ieee_swcr_to_fpcr(*ieee_state)); /* Clean slate for TLS. */ current_thread_info()->pcb.tp = 0; -- Gitee From 66c53cef3dfe289278d9a061d7cb778f796ffe68 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Thu, 14 Dec 2023 11:29:34 +0800 Subject: [PATCH 40/98] sw64: rewrite fpcr and swcr conversion Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Rewrite the conversion between fpcr and swcr. Add C4 new bits support and fix SIMD support. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/fpu.h | 167 ++++++++++++++++++++- arch/sw_64/include/asm/sfp-machine.h | 5 + arch/sw_64/include/uapi/asm/fpu.h | 215 ++++++++++++++++++--------- arch/sw_64/kernel/sys_sw64.c | 6 +- arch/sw_64/kernel/traps.c | 42 +++++- arch/sw_64/math-emu/math.c | 90 ++++++----- 6 files changed, 395 insertions(+), 130 deletions(-) diff --git a/arch/sw_64/include/asm/fpu.h b/arch/sw_64/include/asm/fpu.h index a0b0ff5af168..1d5e9b0efecc 100644 --- a/arch/sw_64/include/asm/fpu.h +++ b/arch/sw_64/include/asm/fpu.h @@ -3,8 +3,85 @@ #define _ASM_SW64_FPU_H #include + +#define EXC_SUM_SWC (1UL << 0) + +#define EXC_SUM_DZE_INT (1UL << 39) + +#define EXC_SUM_INV0 (1UL << 1) +#define EXC_SUM_DZE0 (1UL << 2) +#define EXC_SUM_OVF0 (1UL << 3) +#define EXC_SUM_UNF0 (1UL << 4) +#define EXC_SUM_INE0 (1UL << 5) +#define EXC_SUM_OVI0 (1UL << 6) +#define EXC_SUM_DNO0 (1UL << 40) + +#define EXC_SUM_INV1 (1UL << 15) +#define EXC_SUM_DZE1 (1UL << 16) +#define EXC_SUM_OVF1 (1UL << 17) +#define EXC_SUM_UNF1 (1UL << 18) +#define EXC_SUM_INE1 (1UL << 19) +#define EXC_SUM_OVI1 (1UL << 20) +#define EXC_SUM_DNO1 (1UL << 41) + +#define EXC_SUM_INV2 (1UL << 21) +#define EXC_SUM_DZE2 (1UL << 22) +#define EXC_SUM_OVF2 (1UL << 23) +#define EXC_SUM_UNF2 (1UL << 24) +#define EXC_SUM_INE2 (1UL << 25) +#define EXC_SUM_OVI2 (1UL << 26) +#define EXC_SUM_DNO2 (1UL << 42) + +#define EXC_SUM_INV3 (1UL << 27) +#define EXC_SUM_DZE3 (1UL << 28) +#define EXC_SUM_OVF3 (1UL << 29) +#define EXC_SUM_UNF3 (1UL << 30) +#define EXC_SUM_INE3 (1UL << 31) +#define EXC_SUM_OVI3 (1UL << 32) +#define EXC_SUM_DNO3 (1UL << 43) + +#define EXC_SUM_FP_STATUS0 (EXC_SUM_INV0 | EXC_SUM_DZE0 | \ + EXC_SUM_OVF0 | EXC_SUM_UNF0 | \ + EXC_SUM_INE0 | EXC_SUM_OVI0 | \ + EXC_SUM_DNO0) + +#define EXC_SUM_FP_STATUS1 (EXC_SUM_INV1 | EXC_SUM_DZE1 | \ + EXC_SUM_OVF1 | EXC_SUM_UNF1 | \ + EXC_SUM_INE1 | EXC_SUM_OVI1 | \ + EXC_SUM_DNO1) + +#define EXC_SUM_FP_STATUS2 (EXC_SUM_INV2 | EXC_SUM_DZE2 | \ + EXC_SUM_OVF2 | EXC_SUM_UNF2 | \ + EXC_SUM_INE2 | EXC_SUM_OVI2 | \ + EXC_SUM_DNO2) + +#define EXC_SUM_FP_STATUS3 (EXC_SUM_INV3 | EXC_SUM_DZE3 | \ + EXC_SUM_OVF3 | EXC_SUM_UNF3 | \ + EXC_SUM_INE3 | EXC_SUM_OVI3 | \ + EXC_SUM_DNO3) + +#define EXC_SUM_FP_STATUS_ALL (EXC_SUM_FP_STATUS0 | EXC_SUM_FP_STATUS1 | \ + EXC_SUM_FP_STATUS2 | EXC_SUM_FP_STATUS3) + +#define EXC_SUM_INV (EXC_SUM_INV0 | EXC_SUM_INV1 | \ + EXC_SUM_INV2 | EXC_SUM_INV3) +#define EXC_SUM_DZE (EXC_SUM_DZE0 | EXC_SUM_DZE1 | \ + EXC_SUM_DZE2 | EXC_SUM_DZE3) +#define EXC_SUM_OVF (EXC_SUM_OVF0 | EXC_SUM_OVF1 | \ + EXC_SUM_OVF2 | EXC_SUM_OVF3) +#define EXC_SUM_UNF (EXC_SUM_UNF0 | EXC_SUM_UNF1 | \ + EXC_SUM_UNF2 | EXC_SUM_UNF3) +#define EXC_SUM_INE (EXC_SUM_INE0 | EXC_SUM_INE1 | \ + EXC_SUM_INE2 | EXC_SUM_INE3) +#define EXC_SUM_OVI (EXC_SUM_OVI0 | EXC_SUM_OVI1 | \ + EXC_SUM_OVI2 | EXC_SUM_OVI3) +#define EXC_SUM_DNO (EXC_SUM_DNO0 | EXC_SUM_DNO1 | \ + EXC_SUM_DNO2 | EXC_SUM_DNO3) + #ifdef __KERNEL__ +#include + /* * The following two functions don't need trapb/excb instructions * around the mf_fpcr/mt_fpcr instructions because (a) the kernel @@ -62,15 +139,93 @@ swcr_update_status(unsigned long swcr, unsigned long fpcr) * SW64 implements most of the bits in hardware. Collect * the acrued exception bits from the real fpcr. */ - swcr &= ~(IEEE_STATUS_MASK0 | IEEE_STATUS_MASK1 - | IEEE_STATUS_MASK2 | IEEE_STATUS_MASK3); - swcr |= (fpcr >> 35) & IEEE_STATUS_MASK0; - swcr |= (fpcr >> 13) & IEEE_STATUS_MASK1; - swcr |= (fpcr << 14) & IEEE_STATUS_MASK2; - swcr |= (fpcr << 36) & IEEE_STATUS_MASK3; + swcr &= ~IEEE_STATUS_MASK_ALL; + swcr |= ieee_status_fpcr_to_swcr(fpcr & FPCR_STATUS_MASK_ALL); return swcr; } +static inline unsigned long +swcr_status_to_fex(unsigned long swcr_status, int part) +{ + unsigned long fex = 0; + + if (part < -1 || part > 3) { + pr_warn("%s: invalid part index, counting all parts\n", __func__); + part = -1; + } + + if (part == -1 || part == 0) { + fex |= (swcr_status & (IEEE_STATUS_INV0 | IEEE_STATUS_DZE0 | + IEEE_STATUS_OVF0 | IEEE_STATUS_UNF0 | + IEEE_STATUS_INE0 | IEEE_STATUS_DNO0)) >> + (17 - 1); + fex |= fex & IEEE_STATUS_OVI0 ? FP_EX_OVERINT : 0; + } + + if (part == -1 || part == 1) { + fex |= (swcr_status & (IEEE_STATUS_INV1 | IEEE_STATUS_DZE1 | + IEEE_STATUS_OVF1 | IEEE_STATUS_UNF1 | + IEEE_STATUS_INE1 | IEEE_STATUS_DNO1)) >> + (23 - 1); + fex |= fex & IEEE_STATUS_OVI1 ? FP_EX_OVERINT : 0; + } + + if (part == -1 || part == 2) { + fex |= (swcr_status & (IEEE_STATUS_INV2 | IEEE_STATUS_DZE2 | + IEEE_STATUS_OVF2 | IEEE_STATUS_UNF2 | + IEEE_STATUS_INE2 | IEEE_STATUS_DNO2)) >> + (34 - 1); + fex |= fex & IEEE_STATUS_OVI2 ? FP_EX_OVERINT : 0; + } + + if (part == -1 || part == 3) { + fex |= (swcr_status & (IEEE_STATUS_INV3 | IEEE_STATUS_DZE3 | + IEEE_STATUS_OVF3 | IEEE_STATUS_UNF3 | + IEEE_STATUS_INE3 | IEEE_STATUS_DNO3)) >> + (40 - 1); + fex |= fex & IEEE_STATUS_OVI3 ? FP_EX_OVERINT : 0; + } + + return fex; +} + +static inline unsigned long +fex_to_swcr_status(unsigned long fex, int part) +{ + unsigned long swcr_status = 0; + + switch (part) { + case 0: + swcr_status |= (fex & (FP_EX_INVALID | FP_EX_OVERFLOW | + FP_EX_UNDERFLOW | FP_EX_DIVZERO | + FP_EX_INEXACT | FP_EX_DENORM)) << (17 - 1); + swcr_status |= fex & FP_EX_OVERINT ? IEEE_STATUS_OVI0 : 0; + break; + case 1: + swcr_status |= (fex & (FP_EX_INVALID | FP_EX_OVERFLOW | + FP_EX_UNDERFLOW | FP_EX_DIVZERO | + FP_EX_INEXACT | FP_EX_DENORM)) << (23 - 1); + swcr_status |= fex & FP_EX_OVERINT ? IEEE_STATUS_OVI1 : 0; + break; + case 2: + swcr_status |= (fex & (FP_EX_INVALID | FP_EX_OVERFLOW | + FP_EX_UNDERFLOW | FP_EX_DIVZERO | + FP_EX_INEXACT | FP_EX_DENORM)) << (34 - 1); + swcr_status |= fex & FP_EX_OVERINT ? IEEE_STATUS_OVI2 : 0; + break; + case 3: + swcr_status |= (fex & (FP_EX_INVALID | FP_EX_OVERFLOW | + FP_EX_UNDERFLOW | FP_EX_DIVZERO | + FP_EX_INEXACT | FP_EX_DENORM)) << (40 - 1); + swcr_status |= fex & FP_EX_OVERINT ? IEEE_STATUS_OVI3 : 0; + break; + default: + pr_err("%s: invalid part index\n", __func__); + } + + return swcr_status; +} + extern unsigned long sw64_read_fp_reg(unsigned long reg); extern void sw64_write_fp_reg(unsigned long reg, unsigned long val); extern unsigned long sw64_read_fp_reg_s(unsigned long reg); diff --git a/arch/sw_64/include/asm/sfp-machine.h b/arch/sw_64/include/asm/sfp-machine.h index 156bebc9c515..b96938727d70 100644 --- a/arch/sw_64/include/asm/sfp-machine.h +++ b/arch/sw_64/include/asm/sfp-machine.h @@ -60,8 +60,13 @@ do { \ #define FP_EX_DIVZERO IEEE_TRAP_ENABLE_DZE #define FP_EX_INEXACT IEEE_TRAP_ENABLE_INE #define FP_EX_DENORM IEEE_TRAP_ENABLE_DNO +#define FP_EX_OVERINT IEEE_TRAP_ENABLE_OVI +#if defined(CONFIG_SUBARCH_C3A) || defined(CONFIG_SUBARCH_C3B) #define FP_DENORM_ZERO (swcr & IEEE_MAP_DMZ) +#elif defined(CONFIG_SUBARCH_C4) +#define FP_DENORM_ZERO 1 +#endif /* We write the results always */ #define FP_INHIBIT_RESULTS 0 diff --git a/arch/sw_64/include/uapi/asm/fpu.h b/arch/sw_64/include/uapi/asm/fpu.h index 7f88cfb9399d..5b2acc55aa57 100644 --- a/arch/sw_64/include/uapi/asm/fpu.h +++ b/arch/sw_64/include/uapi/asm/fpu.h @@ -5,18 +5,14 @@ /* * SW-64 floating-point control register defines: */ +#define FPCR_EXUN (1UL << 44) /* exact denorm result underflow */ +#define FPCR_OVID (1UL << 45) /* integer overflow disable */ #define FPCR_DNOD (1UL << 47) /* denorm INV trap disable */ #define FPCR_DNZ (1UL << 48) /* denorms to zero */ #define FPCR_DNOE (1UL << 48) /* hardware denormal support */ #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) */ -#define FPCR_INV (1UL << 52) /* invalid operation */ -#define FPCR_DZE (1UL << 53) /* division by zero */ -#define FPCR_OVF (1UL << 54) /* overflow */ -#define FPCR_UNF (1UL << 55) /* underflow */ -#define FPCR_INE (1UL << 56) /* inexact */ -#define FPCR_IOV (1UL << 57) /* integer overflow */ #define FPCR_UNDZ (1UL << 60) /* underflow to zero (opt.) */ #define FPCR_UNFD (1UL << 61) /* underflow disable (opt.) */ #define FPCR_INED (1UL << 62) /* inexact disable (opt.) */ @@ -34,6 +30,7 @@ #define FPCR_INIT FPCR_DYN_NORMAL /* status bit coming from hardware fpcr . definde by fire3 */ +#define FPCR_STATUS_DNO0 (1UL << 46) #define FPCR_STATUS_INV0 (1UL << 52) #define FPCR_STATUS_DZE0 (1UL << 53) #define FPCR_STATUS_OVF0 (1UL << 54) @@ -47,6 +44,7 @@ #define FPCR_STATUS_UNF1 (1UL << 39) #define FPCR_STATUS_INE1 (1UL << 40) #define FPCR_STATUS_OVI1 (1UL << 41) +#define FPCR_STATUS_DNO1 (1UL << 42) #define FPCR_STATUS_INV2 (1UL << 20) #define FPCR_STATUS_DZE2 (1UL << 21) @@ -54,6 +52,7 @@ #define FPCR_STATUS_UNF2 (1UL << 23) #define FPCR_STATUS_INE2 (1UL << 24) #define FPCR_STATUS_OVI2 (1UL << 25) +#define FPCR_STATUS_DNO2 (1UL << 26) #define FPCR_STATUS_INV3 (1UL << 4) #define FPCR_STATUS_DZE3 (1UL << 5) @@ -61,22 +60,30 @@ #define FPCR_STATUS_UNF3 (1UL << 7) #define FPCR_STATUS_INE3 (1UL << 8) #define FPCR_STATUS_OVI3 (1UL << 9) +#define FPCR_STATUS_DNO3 (1UL << 10) -#define FPCR_STATUS_MASK0 (FPCR_STATUS_INV0 | FPCR_STATUS_DZE0 | \ +#define FPCR_STATUS_MASK0 (FPCR_STATUS_INV0 | FPCR_STATUS_DZE0 | \ FPCR_STATUS_OVF0 | FPCR_STATUS_UNF0 | \ - FPCR_STATUS_INE0 | FPCR_STATUS_OVI0) + FPCR_STATUS_INE0 | FPCR_STATUS_OVI0 | \ + FPCR_STATUS_DNO0) -#define FPCR_STATUS_MASK1 (FPCR_STATUS_INV1 | FPCR_STATUS_DZE1 | \ +#define FPCR_STATUS_MASK1 (FPCR_STATUS_INV1 | FPCR_STATUS_DZE1 | \ FPCR_STATUS_OVF1 | FPCR_STATUS_UNF1 | \ - FPCR_STATUS_INE1 | FPCR_STATUS_OVI1) + FPCR_STATUS_INE1 | FPCR_STATUS_OVI1 | \ + FPCR_STATUS_DNO1) -#define FPCR_STATUS_MASK2 (FPCR_STATUS_INV2 | FPCR_STATUS_DZE2 | \ +#define FPCR_STATUS_MASK2 (FPCR_STATUS_INV2 | FPCR_STATUS_DZE2 | \ FPCR_STATUS_OVF2 | FPCR_STATUS_UNF2 | \ - FPCR_STATUS_INE2 | FPCR_STATUS_OVI2) + FPCR_STATUS_INE2 | FPCR_STATUS_OVI2 | \ + FPCR_STATUS_DNO2) -#define FPCR_STATUS_MASK3 (FPCR_STATUS_INV3 | FPCR_STATUS_DZE3 | \ +#define FPCR_STATUS_MASK3 (FPCR_STATUS_INV3 | FPCR_STATUS_DZE3 | \ FPCR_STATUS_OVF3 | FPCR_STATUS_UNF3 | \ - FPCR_STATUS_INE3 | FPCR_STATUS_OVI3) + FPCR_STATUS_INE3 | FPCR_STATUS_OVI3 | \ + FPCR_STATUS_DNO3) + +#define FPCR_STATUS_MASK_ALL (FPCR_STATUS_MASK0 | FPCR_STATUS_MASK1 |\ + FPCR_STATUS_MASK2 | FPCR_STATUS_MASK3) /* @@ -91,38 +98,25 @@ #define IEEE_TRAP_ENABLE_UNF (1UL << 4) /* underflow */ #define IEEE_TRAP_ENABLE_INE (1UL << 5) /* inexact */ #define IEEE_TRAP_ENABLE_DNO (1UL << 6) /* denorm */ +#define IEEE_TRAP_ENABLE_OVI (1UL << 7) /* integer overflow */ #define IEEE_TRAP_ENABLE_MASK (IEEE_TRAP_ENABLE_INV | IEEE_TRAP_ENABLE_DZE |\ IEEE_TRAP_ENABLE_OVF | IEEE_TRAP_ENABLE_UNF |\ - IEEE_TRAP_ENABLE_INE | IEEE_TRAP_ENABLE_DNO) + IEEE_TRAP_ENABLE_INE | IEEE_TRAP_ENABLE_DNO |\ + IEEE_TRAP_ENABLE_OVI) + +#define IEEE_CTL_EXUN (1UL << 10) /* exact denorm result underflow */ /* Denorm and Underflow flushing */ #define IEEE_MAP_DMZ (1UL << 12) /* Map denorm inputs to zero */ #define IEEE_HARD_DM (1UL << 12) /* Hardware denorm processing */ #define IEEE_MAP_UMZ (1UL << 13) /* Map underflowed outputs to zero */ -#define IEEE_MAP_MASK (IEEE_MAP_DMZ | IEEE_MAP_UMZ) +#define IEEE_MAP_MASK (IEEE_HARD_DM | IEEE_MAP_UMZ) /* status bits coming from fpcr: */ -#define IEEE_STATUS_INV (1UL << 17) -#define IEEE_STATUS_DZE (1UL << 18) -#define IEEE_STATUS_OVF (1UL << 19) -#define IEEE_STATUS_UNF (1UL << 20) -#define IEEE_STATUS_INE (1UL << 21) -#define IEEE_STATUS_DNO (1UL << 22) - - -#define IEEE_STATUS_MASK (IEEE_STATUS_INV | IEEE_STATUS_DZE | \ - IEEE_STATUS_OVF | IEEE_STATUS_UNF | \ - IEEE_STATUS_INE | IEEE_STATUS_DNO) - -#define IEEE_SW_MASK (IEEE_TRAP_ENABLE_MASK | \ - IEEE_STATUS_MASK | IEEE_MAP_MASK) - #define IEEE_CURRENT_RM_SHIFT 32 #define IEEE_CURRENT_RM_MASK (3UL << IEEE_CURRENT_RM_SHIFT) -#define IEEE_STATUS_TO_EXCSUM_SHIFT 16 - #define IEEE_INHERIT (1UL << 63) /* inherit on thread create? */ /* ieee_state expand to surport simd added by fire3 */ @@ -133,11 +127,11 @@ #define IEEE_STATUS_UNF0 (1UL << 20) #define IEEE_STATUS_INE0 (1UL << 21) #define IEEE_STATUS_DNO0 (1UL << 22) +#define IEEE_STATUS_OVI0 (1UL << 46) #define IEEE_STATUS_MASK0 (IEEE_STATUS_INV0 | IEEE_STATUS_DZE0 | \ IEEE_STATUS_OVF0 | IEEE_STATUS_UNF0 | \ - IEEE_STATUS_INE0 | IEEE_STATUS_DNO0) - -#define IEEE_STATUS0_TO_EXCSUM_SHIFT 16 + IEEE_STATUS_INE0 | IEEE_STATUS_DNO0 | \ + IEEE_STATUS_OVI0) #define IEEE_STATUS_INV1 (1UL << 23) #define IEEE_STATUS_DZE1 (1UL << 24) @@ -145,11 +139,11 @@ #define IEEE_STATUS_UNF1 (1UL << 26) #define IEEE_STATUS_INE1 (1UL << 27) #define IEEE_STATUS_DNO1 (1UL << 28) +#define IEEE_STATUS_OVI1 (1UL << 47) #define IEEE_STATUS_MASK1 (IEEE_STATUS_INV1 | IEEE_STATUS_DZE1 | \ IEEE_STATUS_OVF1 | IEEE_STATUS_UNF1 | \ - IEEE_STATUS_INE1 | IEEE_STATUS_DNO1) - -#define IEEE_STATUS1_TO_EXCSUM_SHIFT 22 + IEEE_STATUS_INE1 | IEEE_STATUS_DNO1 | \ + IEEE_STATUS_OVI1) #define IEEE_STATUS_INV2 (1UL << 34) #define IEEE_STATUS_DZE2 (1UL << 35) @@ -157,11 +151,11 @@ #define IEEE_STATUS_UNF2 (1UL << 37) #define IEEE_STATUS_INE2 (1UL << 38) #define IEEE_STATUS_DNO2 (1UL << 39) +#define IEEE_STATUS_OVI2 (1UL << 48) #define IEEE_STATUS_MASK2 (IEEE_STATUS_INV2 | IEEE_STATUS_DZE2 | \ IEEE_STATUS_OVF2 | IEEE_STATUS_UNF2 | \ - IEEE_STATUS_INE2 | IEEE_STATUS_DNO2) - -#define IEEE_STATUS2_TO_EXCSUM_SHIFT 33 + IEEE_STATUS_INE2 | IEEE_STATUS_DNO2 | \ + IEEE_STATUS_OVI2) #define IEEE_STATUS_INV3 (1UL << 40) #define IEEE_STATUS_DZE3 (1UL << 41) @@ -169,12 +163,18 @@ #define IEEE_STATUS_UNF3 (1UL << 43) #define IEEE_STATUS_INE3 (1UL << 44) #define IEEE_STATUS_DNO3 (1UL << 45) +#define IEEE_STATUS_OVI3 (1UL << 49) #define IEEE_STATUS_MASK3 (IEEE_STATUS_INV3 | IEEE_STATUS_DZE3 | \ IEEE_STATUS_OVF3 | IEEE_STATUS_UNF3 | \ - IEEE_STATUS_INE3 | IEEE_STATUS_DNO3) + IEEE_STATUS_INE3 | IEEE_STATUS_DNO3 | \ + IEEE_STATUS_OVI3) + +#define IEEE_STATUS_MASK_ALL (IEEE_STATUS_MASK0 | IEEE_STATUS_MASK1 |\ + IEEE_STATUS_MASK2 | IEEE_STATUS_MASK3) -#define IEEE_STATUS3_TO_EXCSUM_SHIFT 39 +#define IEEE_CTL_MASK (IEEE_TRAP_ENABLE_MASK | IEEE_MAP_MASK) +#define IEEE_SW_MASK (IEEE_STATUS_MASK_ALL | IEEE_CTL_MASK) /* * Convert the software IEEE trap enable and status bits into the @@ -185,43 +185,122 @@ * receive my thanks for making all the not-implemented fpcr bits * RAZ forcing us to use system calls to read/write this value. */ + +static inline unsigned long +ieee_status_swcr_to_fpcr(unsigned long sw_status) +{ + unsigned long fp_status = 0; + + fp_status |= (sw_status & (IEEE_STATUS_INV0 | IEEE_STATUS_DZE0 | + IEEE_STATUS_OVF0 | IEEE_STATUS_UNF0 | + IEEE_STATUS_INE0)) << (52 - 17); + + fp_status |= (sw_status & (IEEE_STATUS_INV1 | IEEE_STATUS_DZE1 | + IEEE_STATUS_OVF1 | IEEE_STATUS_UNF1 | + IEEE_STATUS_INE1)) << (36 - 23); + + fp_status |= (sw_status & (IEEE_STATUS_INV2 | IEEE_STATUS_DZE2 | + IEEE_STATUS_OVF2 | IEEE_STATUS_UNF2 | + IEEE_STATUS_INE2)) >> (34 - 20); + + fp_status |= (sw_status & (IEEE_STATUS_INV3 | IEEE_STATUS_DZE3 | + IEEE_STATUS_OVF3 | IEEE_STATUS_UNF3 | + IEEE_STATUS_INE3)) >> (40 - 4); + + fp_status |= sw_status & IEEE_STATUS_OVI0 ? FPCR_STATUS_OVI0 : 0; + fp_status |= sw_status & IEEE_STATUS_DNO0 ? FPCR_STATUS_DNO0 : 0; + + fp_status |= sw_status & IEEE_STATUS_OVI1 ? FPCR_STATUS_OVI1 : 0; + fp_status |= sw_status & IEEE_STATUS_DNO1 ? FPCR_STATUS_DNO1 : 0; + + fp_status |= sw_status & IEEE_STATUS_OVI2 ? FPCR_STATUS_OVI2 : 0; + fp_status |= sw_status & IEEE_STATUS_DNO2 ? FPCR_STATUS_DNO2 : 0; + + fp_status |= sw_status & IEEE_STATUS_OVI3 ? FPCR_STATUS_OVI3 : 0; + fp_status |= sw_status & IEEE_STATUS_DNO3 ? FPCR_STATUS_DNO3 : 0; + + return fp_status; +} + static inline unsigned long ieee_swcr_to_fpcr(unsigned long sw) { unsigned long fp; - fp = (sw & IEEE_STATUS_MASK0) << 35; - fp |= (sw & IEEE_STATUS_MASK1) << 13; - fp |= (sw & IEEE_STATUS_MASK2) >> 14; - fp |= (sw & IEEE_STATUS_MASK3) >> 36; - - fp |= (sw & IEEE_MAP_DMZ) << 36; - fp |= (sw & IEEE_STATUS_MASK0 ? FPCR_SUM : 0); - fp |= (sw & IEEE_STATUS_MASK1 ? FPCR_SUM : 0); - fp |= (sw & IEEE_STATUS_MASK2 ? FPCR_SUM : 0); - fp |= (sw & IEEE_STATUS_MASK3 ? FPCR_SUM : 0); - fp |= (~sw & (IEEE_TRAP_ENABLE_INV - | IEEE_TRAP_ENABLE_DZE - | IEEE_TRAP_ENABLE_OVF)) << 48; - fp |= (~sw & (IEEE_TRAP_ENABLE_UNF | IEEE_TRAP_ENABLE_INE)) << 57; - fp |= (sw & IEEE_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0); - fp |= (~sw & IEEE_TRAP_ENABLE_DNO) << 41; + fp = ieee_status_swcr_to_fpcr(sw & IEEE_STATUS_MASK_ALL); + + fp |= sw & IEEE_STATUS_MASK_ALL ? FPCR_SUM : 0; + + fp |= sw & IEEE_CTL_EXUN ? FPCR_EXUN : 0; + fp |= sw & IEEE_HARD_DM ? FPCR_DNOE : 0; + fp |= sw & IEEE_MAP_UMZ ? FPCR_UNDZ : 0; + + fp |= sw & IEEE_TRAP_ENABLE_INV ? 0 : FPCR_INVD; + fp |= sw & IEEE_TRAP_ENABLE_DZE ? 0 : FPCR_DZED; + fp |= sw & IEEE_TRAP_ENABLE_OVF ? 0 : FPCR_OVFD; + fp |= sw & IEEE_TRAP_ENABLE_UNF ? 0 : FPCR_UNFD; + fp |= sw & IEEE_TRAP_ENABLE_INE ? 0 : FPCR_INED; + fp |= sw & IEEE_TRAP_ENABLE_DNO ? 0 : FPCR_DNOD; + fp |= sw & IEEE_TRAP_ENABLE_OVI ? 0 : FPCR_OVID; + return fp; } +static inline unsigned long +ieee_status_fpcr_to_swcr(unsigned long fp_status) +{ + unsigned long sw_status = 0; + + sw_status |= (fp_status & (FPCR_STATUS_INV0 | FPCR_STATUS_DZE0 | + FPCR_STATUS_OVF0 | FPCR_STATUS_UNF0 | + FPCR_STATUS_INE0)) >> (52 - 17); + + sw_status |= (fp_status & (FPCR_STATUS_INV1 | FPCR_STATUS_DZE1 | + FPCR_STATUS_OVF1 | FPCR_STATUS_UNF1 | + FPCR_STATUS_INE1)) >> (36 - 23); + + sw_status |= (fp_status & (FPCR_STATUS_INV2 | FPCR_STATUS_DZE2 | + FPCR_STATUS_OVF2 | FPCR_STATUS_UNF2 | + FPCR_STATUS_INE2)) << (34 - 20); + + sw_status |= (fp_status & (FPCR_STATUS_INV3 | FPCR_STATUS_DZE3 | + FPCR_STATUS_OVF3 | FPCR_STATUS_UNF3 | + FPCR_STATUS_INE3)) << (40 - 4); + + sw_status |= fp_status & FPCR_STATUS_OVI0 ? IEEE_STATUS_OVI0 : 0; + sw_status |= fp_status & FPCR_STATUS_DNO0 ? IEEE_STATUS_DNO0 : 0; + + sw_status |= fp_status & FPCR_STATUS_OVI1 ? IEEE_STATUS_OVI1 : 0; + sw_status |= fp_status & FPCR_STATUS_DNO1 ? IEEE_STATUS_DNO1 : 0; + + sw_status |= fp_status & FPCR_STATUS_OVI2 ? IEEE_STATUS_OVI2 : 0; + sw_status |= fp_status & FPCR_STATUS_DNO2 ? IEEE_STATUS_DNO2 : 0; + + sw_status |= fp_status & FPCR_STATUS_OVI3 ? IEEE_STATUS_OVI3 : 0; + sw_status |= fp_status & FPCR_STATUS_DNO3 ? IEEE_STATUS_DNO3 : 0; + + return sw_status; +} + static inline unsigned long ieee_fpcr_to_swcr(unsigned long fp) { unsigned long sw; - sw = (fp >> 35) & IEEE_STATUS_MASK; - sw |= (fp >> 36) & IEEE_MAP_DMZ; - sw |= (~fp >> 48) & (IEEE_TRAP_ENABLE_INV - | IEEE_TRAP_ENABLE_DZE - | IEEE_TRAP_ENABLE_OVF); - sw |= (~fp >> 57) & (IEEE_TRAP_ENABLE_UNF | IEEE_TRAP_ENABLE_INE); - sw |= (fp >> 47) & IEEE_MAP_UMZ; - sw |= (~fp >> 41) & IEEE_TRAP_ENABLE_DNO; + sw = ieee_status_fpcr_to_swcr(fp & FPCR_STATUS_MASK_ALL); + + sw |= fp & FPCR_EXUN ? IEEE_CTL_EXUN : 0; + sw |= fp & FPCR_DNOE ? IEEE_HARD_DM : 0; + sw |= fp & FPCR_UNDZ ? IEEE_MAP_UMZ : 0; + + sw |= fp & FPCR_INVD ? 0 : IEEE_TRAP_ENABLE_INV; + sw |= fp & FPCR_DZED ? 0 : IEEE_TRAP_ENABLE_DZE; + sw |= fp & FPCR_OVFD ? 0 : IEEE_TRAP_ENABLE_OVF; + sw |= fp & FPCR_UNFD ? 0 : IEEE_TRAP_ENABLE_UNF; + sw |= fp & FPCR_INED ? 0 : IEEE_TRAP_ENABLE_INE; + sw |= fp & FPCR_DNOD ? 0 : IEEE_TRAP_ENABLE_DNO; + sw |= fp & FPCR_OVID ? 0 : IEEE_TRAP_ENABLE_OVI; + return sw; } #endif /* _UAPI_ASM_SW64_FPU_H */ diff --git a/arch/sw_64/kernel/sys_sw64.c b/arch/sw_64/kernel/sys_sw64.c index d0198aef554d..46e6197dce76 100644 --- a/arch/sw_64/kernel/sys_sw64.c +++ b/arch/sw_64/kernel/sys_sw64.c @@ -62,7 +62,7 @@ SYSCALL_DEFINE5(setsysinfo, unsigned long, op, void __user *, buffer, if (get_user(exc, (unsigned long __user *)buffer)) return -EFAULT; state = ¤t_thread_info()->ieee_state; - exc &= IEEE_STATUS_MASK; + exc &= IEEE_STATUS_MASK_ALL; /* Update softare trap enable bits. */ swcr = (*state & IEEE_SW_MASK) | exc; @@ -76,7 +76,7 @@ SYSCALL_DEFINE5(setsysinfo, unsigned long, op, void __user *, buffer, /* If any exceptions set by this call, and are unmasked, * send a signal. Old exceptions are not signaled. */ - fex = (exc >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr; + fex = swcr_status_to_fex(exc, -1) & swcr; if (fex) { int si_code = FPE_FLTUNK; @@ -92,6 +92,8 @@ SYSCALL_DEFINE5(setsysinfo, unsigned long, op, void __user *, buffer, si_code = FPE_FLTDIV; if (fex & IEEE_TRAP_ENABLE_INV) si_code = FPE_FLTINV; + if (fex & IEEE_TRAP_ENABLE_OVI) + si_code = FPE_INTOVF; send_sig_fault(SIGFPE, si_code, (void __user *)NULL, current); } diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index 133ad318edb6..295e8e3e73a6 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -143,17 +143,47 @@ EXPORT_SYMBOL_GPL(sw64_fp_emul_imprecise); long (*sw64_fp_emul)(unsigned long pc) = (void *)dummy_emul; EXPORT_SYMBOL_GPL(sw64_fp_emul); #else -long sw64_fp_emul_imprecise(struct pt_regs *regs, unsigned long writemask); -long sw64_fp_emul(unsigned long pc); +extern long sw64_fp_emul_imprecise(struct pt_regs *regs, unsigned long writemask); +extern long sw64_fp_emul(unsigned long pc); #endif asmlinkage void -do_entArith(unsigned long summary, unsigned long write_mask, +do_entArith(unsigned long exc_sum, unsigned long write_mask, struct pt_regs *regs) { long si_code = FPE_FLTINV; - if (summary & 1) { +#ifndef CONFIG_SUBARCH_C3B + /* integer divide by zero */ + if (exc_sum & EXC_SUM_DZE_INT) + si_code = FPE_INTDIV; + /* integer overflow */ + else if (exc_sum & EXC_SUM_OVI) + si_code = FPE_INTOVF; + /* floating point invalid operation */ + else if (exc_sum & EXC_SUM_INV) + si_code = FPE_FLTINV; + /* floating point divide by zero */ + else if (exc_sum & EXC_SUM_DZE) + si_code = FPE_FLTDIV; + /* floating point overflow */ + else if (exc_sum & EXC_SUM_OVF) + si_code = FPE_FLTOVF; + /* floating point underflow */ + else if (exc_sum & EXC_SUM_UNF) + si_code = FPE_FLTUND; + /* floating point inexact result */ + else if (exc_sum & EXC_SUM_INE) + si_code = FPE_FLTRES; + /* denormalized operand */ + else if (exc_sum & EXC_SUM_DNO) + si_code = FPE_FLTUND; + /* undiagnosed floating-point exception */ + else + si_code = FPE_FLTUNK; +#endif + + if ((exc_sum & EXC_SUM_FP_STATUS_ALL) && (exc_sum & EXC_SUM_SWC)) { /* Software-completion summary bit is set, so try to * emulate the instruction. If the processor supports * precise exceptions, we don't have to search. @@ -166,10 +196,6 @@ do_entArith(unsigned long summary, unsigned long write_mask, if (!user_mode(regs)) die("Arithmetic fault", regs, 0); - /*summary<39> means integer divide by zero in C4.*/ - if ((summary >> 39) & 1) - si_code = FPE_INTDIV; - force_sig_fault(SIGFPE, si_code, (void __user *)regs->pc); } diff --git a/arch/sw_64/math-emu/math.c b/arch/sw_64/math-emu/math.c index b578752f0730..b0c2fbca70b1 100644 --- a/arch/sw_64/math-emu/math.c +++ b/arch/sw_64/math-emu/math.c @@ -22,8 +22,6 @@ * This is for sw64 */ -#define IEEE_E_STATUS_MASK IEEE_STATUS_MASK -#define IEEE_E_STATUS_TO_EXCSUM_SHIFT 0 #define SW64_FP_DENOMAL 1 /* A denormal data */ #define SW64_FP_NORMAL 0 /* A denormal data */ #define SW64_FP_NAN 2 @@ -593,9 +591,9 @@ long sw64_fp_emul(unsigned long pc) done: if (_fex) { /* Record exceptions in software control word. */ - swcr |= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT); + swcr |= fex_to_swcr_status(_fex, 0); current_thread_info()->ieee_state - |= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(_fex, 0); /* Update hardware control register. */ fpcr &= (~FPCR_MASK | FPCR_DYN_MASK); @@ -852,9 +850,9 @@ long simd_cmp_emul_d(unsigned long pc) swcr_p0 = swcr_p1 = swcr_p2 = swcr_p3 = swcr; /* manage fpcr_p0 */ if (fex_p0) { - swcr_p0 |= (fex_p0 << IEEE_STATUS0_TO_EXCSUM_SHIFT); + swcr_p0 |= fex_to_swcr_status(fex_p0, 0); current_thread_info()->ieee_state - |= (fex_p0 << IEEE_STATUS0_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p0, 0); /* Update hardware control register. */ fpcr_p0 = fpcr; @@ -863,9 +861,9 @@ long simd_cmp_emul_d(unsigned long pc) } if (fex_p1) { - swcr_p1 |= (fex_p1 << IEEE_STATUS1_TO_EXCSUM_SHIFT); + swcr_p1 |= fex_to_swcr_status(fex_p1, 1); current_thread_info()->ieee_state - |= (fex_p1 << IEEE_STATUS1_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p1, 1); /* Update hardware control register. */ fpcr_p1 = fpcr; @@ -874,9 +872,9 @@ long simd_cmp_emul_d(unsigned long pc) } if (fex_p2) { - swcr_p2 |= (fex_p2 << IEEE_STATUS2_TO_EXCSUM_SHIFT); + swcr_p2 |= fex_to_swcr_status(fex_p2, 2); current_thread_info()->ieee_state - |= (fex_p2 << IEEE_STATUS2_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p2, 2); /* Update hardware control register. */ fpcr_p2 = fpcr; @@ -885,9 +883,9 @@ long simd_cmp_emul_d(unsigned long pc) } if (fex_p3) { - swcr_p3 |= (fex_p3 << IEEE_STATUS3_TO_EXCSUM_SHIFT); + swcr_p3 |= fex_to_swcr_status(fex_p3, 3); current_thread_info()->ieee_state - |= (fex_p3 << IEEE_STATUS3_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p3, 3); /* Update hardware control register. */ fpcr_p3 = fpcr; @@ -1119,9 +1117,9 @@ long simd_fp_emul_d(unsigned long pc) swcr_p0 = swcr_p1 = swcr_p2 = swcr_p3 = swcr; /* manage fpcr_p0 */ if (fex_p0) { - swcr_p0 |= (fex_p0 << IEEE_STATUS0_TO_EXCSUM_SHIFT); + swcr_p0 |= fex_to_swcr_status(fex_p0, 0); current_thread_info()->ieee_state - |= (fex_p0 << IEEE_STATUS0_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p0, 0); /* Update hardware control register. */ fpcr_p0 = fpcr; @@ -1130,9 +1128,9 @@ long simd_fp_emul_d(unsigned long pc) } if (fex_p1) { - swcr_p1 |= (fex_p1 << IEEE_STATUS1_TO_EXCSUM_SHIFT); + swcr_p1 |= fex_to_swcr_status(fex_p1, 1); current_thread_info()->ieee_state - |= (fex_p1 << IEEE_STATUS1_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p1, 1); /* Update hardware control register. */ fpcr_p1 = fpcr; @@ -1141,9 +1139,9 @@ long simd_fp_emul_d(unsigned long pc) } if (fex_p2) { - swcr_p2 |= (fex_p2 << IEEE_STATUS2_TO_EXCSUM_SHIFT); + swcr_p2 |= fex_to_swcr_status(fex_p2, 2); current_thread_info()->ieee_state - |= (fex_p2 << IEEE_STATUS2_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p2, 2); /* Update hardware control register. */ fpcr_p2 = fpcr; @@ -1152,9 +1150,9 @@ long simd_fp_emul_d(unsigned long pc) } if (fex_p3) { - swcr_p3 |= (fex_p3 << IEEE_STATUS3_TO_EXCSUM_SHIFT); + swcr_p3 |= fex_to_swcr_status(fex_p3, 3); current_thread_info()->ieee_state - |= (fex_p3 << IEEE_STATUS3_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p3, 3); /* Update hardware control register. */ fpcr_p3 = fpcr; @@ -1385,9 +1383,9 @@ long simd_fp_emul_s(unsigned long pc) swcr_p0 = swcr_p1 = swcr_p2 = swcr_p3 = swcr; /* manage fpcr_p0 */ if (fex_p0) { - swcr_p0 |= (fex_p0 << IEEE_STATUS0_TO_EXCSUM_SHIFT); + swcr_p0 |= fex_to_swcr_status(fex_p0, 0); current_thread_info()->ieee_state - |= (fex_p0 << IEEE_STATUS0_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p0, 0); /* Update hardware control register. */ fpcr_p0 = fpcr; @@ -1397,9 +1395,9 @@ long simd_fp_emul_s(unsigned long pc) } if (fex_p1) { - swcr_p1 |= (fex_p1 << IEEE_STATUS1_TO_EXCSUM_SHIFT); + swcr_p1 |= fex_to_swcr_status(fex_p1, 1); current_thread_info()->ieee_state - |= (fex_p1 << IEEE_STATUS1_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p1, 1); /* Update hardware control register. */ fpcr_p1 = fpcr; @@ -1409,9 +1407,9 @@ long simd_fp_emul_s(unsigned long pc) } if (fex_p2) { - swcr_p2 |= (fex_p2 << IEEE_STATUS2_TO_EXCSUM_SHIFT); + swcr_p2 |= fex_to_swcr_status(fex_p2, 2); current_thread_info()->ieee_state - |= (fex_p2 << IEEE_STATUS2_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p2, 2); /* Update hardware control register. */ fpcr_p2 = fpcr; @@ -1421,9 +1419,9 @@ long simd_fp_emul_s(unsigned long pc) } if (fex_p3) { - swcr_p3 |= (fex_p3 << IEEE_STATUS3_TO_EXCSUM_SHIFT); + swcr_p3 |= fex_to_swcr_status(fex_p3, 3); current_thread_info()->ieee_state - |= (fex_p3 << IEEE_STATUS3_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p3, 3); /* Update hardware control register. */ fpcr_p3 = fpcr; @@ -1598,9 +1596,9 @@ long mul_add_fp_emul(unsigned long pc) pr_debug("vd = %#lx\n", vd); if (_fex) { /* Record exceptions in software control word. */ - swcr |= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT); + swcr |= fex_to_swcr_status(_fex, 0); current_thread_info()->ieee_state - |= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(_fex, 0); /* Update hardware control register. */ fpcr &= (~FPCR_MASK | FPCR_DYN_MASK); @@ -1843,9 +1841,9 @@ long simd_mul_add_fp_emul_s(unsigned long pc) swcr_p0 = swcr_p1 = swcr_p2 = swcr_p3 = swcr; /* manage fpcr_p0 */ if (fex_p0) { - swcr_p0 |= (fex_p0 << IEEE_STATUS0_TO_EXCSUM_SHIFT); + swcr_p0 |= fex_to_swcr_status(fex_p0, 0); current_thread_info()->ieee_state - |= (fex_p0 << IEEE_STATUS0_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p0, 0); /* Update hardware control register. */ fpcr_p0 = fpcr; @@ -1854,9 +1852,9 @@ long simd_mul_add_fp_emul_s(unsigned long pc) } if (fex_p1) { - swcr_p1 |= (fex_p1 << IEEE_STATUS1_TO_EXCSUM_SHIFT); + swcr_p1 |= fex_to_swcr_status(fex_p1, 1); current_thread_info()->ieee_state - |= (fex_p1 << IEEE_STATUS1_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p1, 1); /* Update hardware control register. */ fpcr_p1 = fpcr; @@ -1865,9 +1863,9 @@ long simd_mul_add_fp_emul_s(unsigned long pc) } if (fex_p2) { - swcr_p2 |= (fex_p2 << IEEE_STATUS2_TO_EXCSUM_SHIFT); + swcr_p2 |= fex_to_swcr_status(fex_p2, 2); current_thread_info()->ieee_state - |= (fex_p2 << IEEE_STATUS2_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p2, 2); /* Update hardware control register. */ fpcr_p2 = fpcr; @@ -1876,9 +1874,9 @@ long simd_mul_add_fp_emul_s(unsigned long pc) } if (fex_p3) { - swcr_p3 |= (fex_p3 << IEEE_STATUS3_TO_EXCSUM_SHIFT); + swcr_p3 |= fex_to_swcr_status(fex_p3, 3); current_thread_info()->ieee_state - |= (fex_p3 << IEEE_STATUS3_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p3, 3); /* Update hardware control register. */ fpcr_p3 = fpcr; @@ -2131,9 +2129,9 @@ long simd_mul_add_fp_emul_d(unsigned long pc) swcr_p0 = swcr_p1 = swcr_p2 = swcr_p3 = swcr; /* manage fpcr_p0 */ if (fex_p0) { - swcr_p0 |= (fex_p0 << IEEE_STATUS0_TO_EXCSUM_SHIFT); + swcr_p0 |= fex_to_swcr_status(fex_p0, 0); current_thread_info()->ieee_state - |= (fex_p0 << IEEE_STATUS0_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p0, 0); /* Update hardware control register. */ fpcr_p0 = fpcr; @@ -2142,9 +2140,9 @@ long simd_mul_add_fp_emul_d(unsigned long pc) } if (fex_p1) { - swcr_p1 |= (fex_p1 << IEEE_STATUS1_TO_EXCSUM_SHIFT); + swcr_p1 |= fex_to_swcr_status(fex_p1, 1); current_thread_info()->ieee_state - |= (fex_p1 << IEEE_STATUS1_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p1, 1); /* Update hardware control register. */ fpcr_p1 = fpcr; @@ -2153,9 +2151,9 @@ long simd_mul_add_fp_emul_d(unsigned long pc) } if (fex_p2) { - swcr_p2 |= (fex_p2 << IEEE_STATUS2_TO_EXCSUM_SHIFT); + swcr_p2 |= fex_to_swcr_status(fex_p2, 2); current_thread_info()->ieee_state - |= (fex_p2 << IEEE_STATUS2_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p2, 2); /* Update hardware control register. */ fpcr_p2 = fpcr; @@ -2164,9 +2162,9 @@ long simd_mul_add_fp_emul_d(unsigned long pc) } if (fex_p3) { - swcr_p3 |= (fex_p3 << IEEE_STATUS3_TO_EXCSUM_SHIFT); + swcr_p3 |= fex_to_swcr_status(fex_p3, 3); current_thread_info()->ieee_state - |= (fex_p3 << IEEE_STATUS3_TO_EXCSUM_SHIFT); + |= fex_to_swcr_status(fex_p3, 3); /* Update hardware control register. */ fpcr_p3 = fpcr; -- Gitee From 3798f46629e5859b109b0c51aadd309ad5023d71 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Fri, 2 Feb 2024 17:12:13 +0800 Subject: [PATCH 41/98] sw64: use a new wrap_asid hmcall when asid wraps Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Use a new wrap_asid hmcall which loads the new asid and ptbr before tbivp(). Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/hmcall.h | 10 ++++++++++ arch/sw_64/include/asm/mmu_context.h | 7 +++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/include/asm/hmcall.h b/arch/sw_64/include/asm/hmcall.h index 0bcd901f671d..41c656470ca4 100644 --- a/arch/sw_64/include/asm/hmcall.h +++ b/arch/sw_64/include/asm/hmcall.h @@ -20,6 +20,7 @@ #define HMC_rdhtctl 0x0D #define HMC_wrksp 0x0E #define HMC_mtinten 0x0F +#define HMC_wrap_asid 0x10 #define HMC_load_mm 0x11 #define HMC_tbisasid 0x14 #define HMC_tbivpn 0x19 @@ -231,6 +232,15 @@ __CALL_HMC_W1(wrtp, unsigned long); /* Invalidate all user TLB with current UPN and VPN */ #define tbiu() __tbi(4, /* no second argument */) +#ifndef CONFIG_SUBARCH_C3B +__CALL_HMC_W2(wrap_asid, unsigned long, unsigned long); +#else +static inline void wrap_asid(unsigned long asid, unsigned long ptbr) +{ + tbivp(); +} +#endif + #endif /* !__ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/arch/sw_64/include/asm/mmu_context.h b/arch/sw_64/include/asm/mmu_context.h index 420ad5f745be..1ff7df9539c5 100644 --- a/arch/sw_64/include/asm/mmu_context.h +++ b/arch/sw_64/include/asm/mmu_context.h @@ -41,10 +41,13 @@ static inline bool asid_valid(struct mm_struct *mm, unsigned int cpu) static inline void __get_new_mm_context(struct mm_struct *mm, long cpu) { + unsigned long ptbr; unsigned long asid = last_asid(cpu); - if (!(++asid & ASID_MASK)) - tbivp(); + if (!(++asid & ASID_MASK)) { + ptbr = virt_to_pfn(mm->pgd); + wrap_asid(asid, ptbr); + } mm->context.asid[cpu] = last_asid(cpu) = asid; } -- Gitee From f463460ae46d4a7921879b92619e630aaf515325 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 19 Mar 2024 13:49:57 +0800 Subject: [PATCH 42/98] sw64: fix kconfig selections Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Fix kconfig selections to avoid linker error when using junzhang_defconfig. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 1 + drivers/irqchip/Kconfig | 2 ++ 2 files changed, 3 insertions(+) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index bc85bebde3be..2639987c44bf 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -243,6 +243,7 @@ config PLATFORM_JUNZHANG depends on UNCORE_JUNZHANG select SPARSE_IRQ select SYS_HAS_EARLY_PRINTK + select I2C_SUNWAY if I2C help Sunway board chipset for C4 diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 5934939c8496..336f357f380e 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -17,6 +17,8 @@ config SW64_PINTC default y select GENERIC_IRQ_CHIP select IRQ_DOMAIN + select IRQ_DOMAIN_HIERARCHY + select SW64_LPC_INTC help This enables support for the pINTC chip found in SW systems. The PINTC receives all platform devices' interrupts and passes -- Gitee From 40e8322a5fcf202416d00d5d3df6dc7050c44d93 Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Thu, 7 Mar 2024 13:50:10 +0800 Subject: [PATCH 43/98] sw64: fix compilation warning Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Signed-off-by: He Chuyue Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/kprobes/decode-insn.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sw_64/kernel/kprobes/decode-insn.c b/arch/sw_64/kernel/kprobes/decode-insn.c index 91c31111f2b7..0bbd03407013 100644 --- a/arch/sw_64/kernel/kprobes/decode-insn.c +++ b/arch/sw_64/kernel/kprobes/decode-insn.c @@ -58,6 +58,7 @@ static bool __kprobes sw64_insn_is_steppable(u32 insn) #ifdef CONFIG_KPROBES +#ifdef CONFIG_SUBARCH_C3B // lldl rd_f static bool __kprobes is_probed_between_atomic(kprobe_opcode_t *addr) { @@ -81,6 +82,7 @@ static bool __kprobes is_probed_between_atomic(kprobe_opcode_t *addr) return true; } +#endif bool __kprobes sw64_insn_can_kprobe(kprobe_opcode_t *addr) { -- Gitee From d8b0e4d6d67d22d9e9827a0653a6512c085475ed Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 20 Dec 2023 19:45:03 +0800 Subject: [PATCH 44/98] sw64: acpi: add ACPI-style structures for SW PINTC, MSIC and LPC-INTC Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- SW PINTC : Sunway Platform Interrupt Controller SW MSIC : Sunway MSI Controller SW LPC-INTC : Sunway LPC Interrupt Controller Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- include/acpi/actbl2.h | 87 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index b6eb68b951da..f18ca00bb863 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -910,6 +910,9 @@ enum acpi_madt_type { * used(start from 0x80). */ ACPI_MADT_TYPE_SW_CINTC = 0x80, + ACPI_MADT_TYPE_SW_PINTC = 0x81, + ACPI_MADT_TYPE_SW_MSIC = 0x82, + ACPI_MADT_TYPE_SW_LPC_INTC = 0x83 #endif }; @@ -1361,6 +1364,90 @@ enum acpi_madt_sw_cintc_version { ACPI_MADT_SW_CINTC_VERSION_V2 = 2, ACPI_MADT_SW_CINTC_VERSION_RESERVED = 3 /* 3 and greater are reserved */ }; + +/* 0x81: Sunway Platform Interrupt Controller (To be added to ACPI spec) */ + +struct acpi_madt_sw_sub_pintc { + u8 type; + u8 reserved[3]; + u32 hardware_id; + u64 address; + u32 size; + u32 gsi_base; + u32 gsi_count; + u32 cascade_vector; +}; + +struct acpi_madt_sw_pintc { + struct acpi_subtable_header header; + u8 version; + u8 reserved; + u32 flags; + u32 node; + u64 address; + u32 size; + u32 sub_num; + struct acpi_madt_sw_sub_pintc sub[]; +}; + +/* Values for version field above */ + +enum acpi_madt_sw_pintc_version { + ACPI_MADT_SW_PINTC_VERSION_NONE = 0, + ACPI_MADT_SW_PINTC_VERSION_V1 = 1, + ACPI_MADT_SW_PINTC_VERSION_V2 = 2, + ACPI_MADT_SW_PINTC_VERSION_RESERVED = 3 /* 3 and greater are reserved */ +}; + +/* 0x82: Sunway MSI Controller (To be added to ACPI spec) */ + +struct acpi_madt_sw_msic { + struct acpi_subtable_header header; + u8 version; + u8 reserved0; + u32 hardware_id; + u32 flags; + u64 address; + u32 size; + u32 cascade_vector; + u32 node; + u32 rc; + u32 num; + u32 reserved1[4]; +}; + +/* Values for version field above */ + +enum acpi_madt_sw_msic_version { + ACPI_MADT_SW_MSIC_VERSION_NONE = 0, + ACPI_MADT_SW_MSIC_VERSION_V1 = 1, + ACPI_MADT_SW_MSIC_VERSION_V2 = 2, + ACPI_MADT_SW_MSIC_VERSION_RESERVED = 3 /* 3 and greater are reserved */ +}; + +/* 0x83: Sunway LPC Interrupt Controller (To be added to ACPI spec) */ + +struct acpi_madt_sw_lpc_intc { + struct acpi_subtable_header header; + u8 version; + u8 reserved; + u32 hardware_id; + u32 flags; + u64 address; + u32 size; + u32 node; + u32 cascade_vector; + u32 gsi_base; + u32 gsi_count; +}; + +/* Values for version field above */ + +enum acpi_madt_sw_lpc_intc_version { + ACPI_MADT_SW_LPC_INTC_VERSION_NONE = 0, + ACPI_MADT_SW_LPC_INTC_VERSION_V1 = 1, + ACPI_MADT_SW_LPC_INTC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ +}; #endif /* -- Gitee From 0eee237f4afd8690722afcda63ed430856f887c0 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 17 Jan 2024 19:16:33 +0800 Subject: [PATCH 45/98] sw64: acpi: support MADT entry print for SW PINTC, MSIC and LPC-INTC Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- After this commit, we can print MADT entries of Sunway via the function acpi_table_print_madt_entry(). Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/acpi/tables.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 6c3a5ab15750..4fca04c8dd2d 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -239,6 +239,33 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) p->version, p->flags, p->hardware_id); } break; + + case ACPI_MADT_TYPE_SW_PINTC: + { + struct acpi_madt_sw_pintc *p = + (struct acpi_madt_sw_pintc *)header; + pr_info("SW PINTC (version[%u] flags[0x%x] address[0x%llx])\n", + p->version, p->flags, p->address); + } + break; + + case ACPI_MADT_TYPE_SW_MSIC: + { + struct acpi_madt_sw_msic *p = + (struct acpi_madt_sw_msic *)header; + pr_info("SW MSIC (version[%u] flags[0x%x] hardware_id[0x%x])\n", + p->version, p->flags, p->hardware_id); + } + break; + + case ACPI_MADT_TYPE_SW_LPC_INTC: + { + struct acpi_madt_sw_lpc_intc *p = + (struct acpi_madt_sw_lpc_intc *)header; + pr_info("SW LPC INTC (version[%u] flags[0x%x] hardware_id[0x%x])\n", + p->version, p->flags, p->hardware_id); + } + break; #endif default: -- Gitee From c8736966320b598696b3063ec3e1c96c774f8543 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 21 Dec 2023 16:50:05 +0800 Subject: [PATCH 46/98] sw64: irqchip: support ACPI-based interrupt controller initialization Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Update driver to support initialization of PINTC and LPC-INTC in ACPI environment, enabling devices to use interrupts. This commit also fixes compatibility issue with old dts description for PINTC and LPC-INTC. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/boot/dts/chip3.dts | 2 +- arch/sw_64/boot/dts/chip_vt.dts | 2 +- arch/sw_64/include/asm/irq.h | 16 ++ arch/sw_64/kernel/acpi.c | 4 - drivers/acpi/bus.c | 5 + drivers/irqchip/irq-sunway-cpu.c | 213 ++++++++++++++++ drivers/irqchip/irq-sunway-lpc-intc.c | 163 ++++++++++-- drivers/irqchip/irq-sunway-msi-v2.c | 35 +++ drivers/irqchip/irq-sunway-msi.c | 35 +++ drivers/irqchip/irq-sunway-pintc.c | 347 +++++++++++++++++++++++--- include/acpi/actbl2.h | 6 +- include/linux/acpi.h | 3 + 12 files changed, 767 insertions(+), 64 deletions(-) diff --git a/arch/sw_64/boot/dts/chip3.dts b/arch/sw_64/boot/dts/chip3.dts index 0e9ad8f5d464..920519566c58 100644 --- a/arch/sw_64/boot/dts/chip3.dts +++ b/arch/sw_64/boot/dts/chip3.dts @@ -36,7 +36,7 @@ spiclk: spiclk { }; pintc: interrupt-controller { - compatible = "sw64,pintc"; + compatible = "sw64,pintc", "sw64,sw6_irq_controller"; interrupt-controller; sw64,node = <0>; sw64,irq-num = <8>; diff --git a/arch/sw_64/boot/dts/chip_vt.dts b/arch/sw_64/boot/dts/chip_vt.dts index 9889fcae7a5c..5f2ec68cb1d0 100644 --- a/arch/sw_64/boot/dts/chip_vt.dts +++ b/arch/sw_64/boot/dts/chip_vt.dts @@ -20,7 +20,7 @@ soc { ranges; pintc: interrupt-controller { - compatible = "sw64,pintc_vt"; + compatible = "sw64,pintc_vt", "sw64,sw6_irq_vt_controller"; interrupt-controller; sw64,node = <0>; sw64,irq-num = <16>; diff --git a/arch/sw_64/include/asm/irq.h b/arch/sw_64/include/asm/irq.h index b3ac4105c29e..e393162d928b 100644 --- a/arch/sw_64/include/asm/irq.h +++ b/arch/sw_64/include/asm/irq.h @@ -28,4 +28,20 @@ extern void (*perf_irq)(unsigned long vector, struct pt_regs *regs); extern void fixup_irqs(void); extern void sw64_timer_interrupt(void); +struct irq_domain; +struct fwnode_handle; + +struct acpi_madt_sw_pintc; +struct acpi_madt_sw_msic; +struct acpi_madt_sw_lpc_intc; + +extern int __init sw64_add_gsi_domain_map(u32 gsi_base, u32 gsi_count, + struct fwnode_handle *handle); +extern int __init pintc_acpi_init(struct irq_domain *parent, + struct acpi_madt_sw_pintc *pintc); +extern int __init msic_acpi_init(struct irq_domain *parent, + struct acpi_madt_sw_msic *msic); +extern int __init lpc_intc_acpi_init(struct irq_domain *parent, + struct acpi_madt_sw_lpc_intc *lpc_intc); + #endif /* _ASM_SW64_IRQ_H */ diff --git a/arch/sw_64/kernel/acpi.c b/arch/sw_64/kernel/acpi.c index 20c6e851254b..56805db4431e 100644 --- a/arch/sw_64/kernel/acpi.c +++ b/arch/sw_64/kernel/acpi.c @@ -32,13 +32,9 @@ 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 diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 0d2e1de143ef..e0800d1f8ff7 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1174,6 +1174,11 @@ static int __init acpi_bus_init_irq(void) case ACPI_IRQ_MODEL_LPIC: message = "LPIC"; break; +#ifdef CONFIG_SW64 + case ACPI_IRQ_MODEL_SWPIC: + message = "SWPIC"; + break; +#endif default: pr_info("Unknown interrupt routing model\n"); return -ENODEV; diff --git a/drivers/irqchip/irq-sunway-cpu.c b/drivers/irqchip/irq-sunway-cpu.c index 09addf73e132..20cfa4f2b999 100644 --- a/drivers/irqchip/irq-sunway-cpu.c +++ b/drivers/irqchip/irq-sunway-cpu.c @@ -2,12 +2,43 @@ #include #include +#include +#include #include #include #include #include +/** + * The topology of interrupt controllers of SW64 is as follows: + * + * +-----------------------------------------------------------+ + * | | + * | +-------------+ | + * | | Core | | + * | +-------------+ | + * | | | + * | +----------------------+ | + * | | SW CINTC | | + * | +----------------------+ | + * | ______| |______ | + * | | | | + * | +-----------+ +--------------+ | + * | | SW MSIC | | SW PINTC | | + * | +-----------+ +--------------+ | + * | | | + * | +--------------+ | + * | | SW LPC INTC | | + * | +--------------+ | + * | | + * +-----------------------------------------------------------+ + */ + +#define PREFIX "CINTC: " + +struct fwnode_handle *cintc_handle; + static void handle_intx(unsigned int offset) { struct pci_controller *hose; @@ -208,3 +239,185 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, pr_crit("PC = %016lx PS = %04lx\n", regs->pc, regs->ps); } EXPORT_SYMBOL(do_entInt); + +#ifdef CONFIG_ACPI +#define SW_CINTC_FLAG_VIRTUAL 0x4 /* virtual CINTC */ + +#define is_core_virtual(flags) ((flags) & SW_CINTC_FLAG_VIRTUAL) + +struct gsi_domain_map { + u32 gsi_base; + u32 gsi_count; + struct fwnode_handle *handle; + struct gsi_domain_map *next; +}; + +static struct gsi_domain_map *gsi_domain_map_list; + +int __init sw64_add_gsi_domain_map(u32 gsi_base, u32 gsi_count, + struct fwnode_handle *handle) +{ + struct gsi_domain_map *map; + + if (WARN_ON(!handle)) + return -EINVAL; + + map = kzalloc(sizeof(struct gsi_domain_map), GFP_KERNEL); + if (!map) + return -ENOMEM; + + map->gsi_base = gsi_base; + map->gsi_count = gsi_count; + map->handle = handle; + + map->next = gsi_domain_map_list; + gsi_domain_map_list = map; + + return 0; +} + +/** + * The starting GSI num occupied by different domains are: + * + * SW CINTC on Node(x) : 0 + (512 * x) + * SW PINTC on Node(x) : 64 + (512 * x) + * SW LPC-INTC on Node(x) : 256 + (512 * x) + */ +static struct fwnode_handle *sw64_gsi_to_domain_id(u32 gsi) +{ + struct gsi_domain_map *map; + u32 base, limit; + + for (map = gsi_domain_map_list; map; map = map->next) { + base = map->gsi_base; + limit = map->gsi_base + map->gsi_count; + + if ((gsi >= base) && (gsi < limit)) + return map->handle; + } + + return NULL; +} + +static int __init pintc_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_sw_pintc *pintc; + + pintc = (struct acpi_madt_sw_pintc *)header; + + /* Not yet supported */ + if (pintc->node > 0) { + pr_warn(PREFIX "PINTC and LPC-INTC on node x(x > 0) are not supported\n"); + return 0; + } + + if ((pintc->version == ACPI_MADT_SW_PINTC_VERSION_NONE) || + (pintc->version >= ACPI_MADT_SW_PINTC_VERSION_RESERVED)) { + pr_err(PREFIX "invalid PINTC version\n"); + return -EINVAL; + } + + return pintc_acpi_init(NULL, pintc); +} + +#ifdef CONFIG_SW64_IRQ_MSI +static int __init msic_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_sw_msic *msic; + + msic = (struct acpi_madt_sw_msic *)header; + if ((msic->version == ACPI_MADT_SW_MSIC_VERSION_NONE) || + (msic->version >= ACPI_MADT_SW_MSIC_VERSION_RESERVED)) { + pr_err(PREFIX "invalid MSIC version\n"); + return -EINVAL; + } + + return msic_acpi_init(NULL, msic); +} +#endif + +static bool __init +acpi_check_sw_cintc_entry(struct acpi_subtable_header *header, + struct acpi_probe_entry *ape) +{ + struct acpi_madt_sw_cintc *cintc; + + cintc = (struct acpi_madt_sw_cintc *)header; + if (cintc->version != ape->driver_data) + return false; + + return true; +} + +static __init int cintc_acpi_init(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_sw_cintc *cintc; + bool virtual; + + /** + * There are more than one MADT entry of SW CINTC in + * multi-core system, but the initialization here only + * needs to be performed once per node. + */ + if (cintc_handle) + return 0; + + cintc = (struct acpi_madt_sw_cintc *)header; + virtual = is_core_virtual(cintc->flags); + pr_info(PREFIX "version [%u] (%s) found\n", cintc->version, + virtual ? "virtual" : "physical"); + + /** + * Currently, no irq_domain created for SW CINTC. The + * handle only used to avoid multiple initializations. + * Apart from this, there is no other meaning. + * + * Maybe we will create irq_domain for SW CINTC in the + * future to optimize the code. + */ + cintc_handle = irq_domain_alloc_named_fwnode("CINTC"); + if (!cintc_handle) { + pr_err(PREFIX "failed to alloc fwnode\n"); + return -ENOMEM; + } + + acpi_set_irq_model(ACPI_IRQ_MODEL_SWPIC, sw64_gsi_to_domain_id); + + /* Init SW PINTC */ + acpi_table_parse_madt(ACPI_MADT_TYPE_SW_PINTC, + pintc_parse_madt, 0); + +#ifdef CONFIG_SW64_IRQ_MSI + /* Init SW MSIC */ + acpi_table_parse_madt(ACPI_MADT_TYPE_SW_MSIC, + msic_parse_madt, 0); +#endif + + /** + * After initializing MSIC, it's time to enable MSI interrupts + * for boot core. For other SMP cores, if present, this + * initialization is performed during SMP startup. + */ + if (!virtual) { + 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); + } + + return 0; +} + +IRQCHIP_ACPI_DECLARE(cintc_v1, ACPI_MADT_TYPE_SW_CINTC, + acpi_check_sw_cintc_entry, + ACPI_MADT_SW_CINTC_VERSION_V1, + cintc_acpi_init); + +IRQCHIP_ACPI_DECLARE(cintc_v2, ACPI_MADT_TYPE_SW_CINTC, + acpi_check_sw_cintc_entry, + ACPI_MADT_SW_CINTC_VERSION_V2, + cintc_acpi_init); +#endif diff --git a/drivers/irqchip/irq-sunway-lpc-intc.c b/drivers/irqchip/irq-sunway-lpc-intc.c index bc69d1647aed..80442dae812f 100644 --- a/drivers/irqchip/irq-sunway-lpc-intc.c +++ b/drivers/irqchip/irq-sunway-lpc-intc.c @@ -12,6 +12,8 @@ #define LPC_IRQ 0x4 #define LPC_IRQ_MASK 0x8 +#define SW_LPC_INTC_GSI_BASE 256 + static DEFINE_RAW_SPINLOCK(lpc_lock); static int parent_irq; @@ -110,18 +112,70 @@ static int sw64_lpc_domain_map(struct irq_domain *d, unsigned int virq, return 0; } +static int lpc_intc_translate(struct irq_domain *domain, + struct irq_fwspec *fwspec, + unsigned long *hwirq, + unsigned int *type) +{ + if (WARN_ON(fwspec->param_count < 1)) + return -EINVAL; + + /* Device tree */ + if (is_of_node(fwspec->fwnode)) { + *hwirq = fwspec->param[0]; + *type = IRQ_TYPE_NONE; + return 0; + } + + /* ACPI */ + if (is_fwnode_irqchip(fwspec->fwnode)) { + if (WARN_ON(fwspec->param[0] < SW_LPC_INTC_GSI_BASE)) + return -EINVAL; + *hwirq = fwspec->param[0] - SW_LPC_INTC_GSI_BASE; + *type = IRQ_TYPE_NONE; + return 0; + } + + return -EINVAL; +} + static const struct irq_domain_ops sw64_lpc_domain_ops = { .map = sw64_lpc_domain_map, - .xlate = irq_domain_xlate_onecell, + .translate = lpc_intc_translate, }; +static struct irq_domain *lpc_irq_domain; + +static int __init lpc_intc_init(struct fwnode_handle *handle, + unsigned int irqnr, int parent_irq, void __iomem *base_addr) +{ + /** + * The current kernel does not support "irq_domain_create_legacy", + * we have to call "__irq_domain_add" directly. + */ + lpc_irq_domain = __irq_domain_add(handle, irqnr, irqnr, + 0, &sw64_lpc_domain_ops, base_addr); + if (!lpc_irq_domain) { + pr_info(PREFIX "failed to create irq domain\n"); + return -ENOMEM; + } + + irq_domain_associate_many(lpc_irq_domain, 0, 0, irqnr); + + /* Set the IRQ chaining logic */ + irq_set_chained_handler_and_data(parent_irq, + lpc_irq_handler, lpc_irq_domain); + + return 0; +} + +#ifdef CONFIG_OF 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) { - struct irq_domain *lpc_domain; int ret; u32 nr_irqs, node, version; void __iomem *base; @@ -133,20 +187,23 @@ static int __init lpc_intc_of_init(struct device_node *np, ret = of_property_read_u32(np, "sw64,node", &node); if (ret) { - pr_err(PREFIX "\"sw64,node\" not found\n"); - return -EINVAL; + node = 0; + pr_warn(PREFIX "\"sw64,node\" fallback to %u\n", + node); } ret = of_property_read_u32(np, "sw64,irq-num", &nr_irqs); if (ret) { - pr_err(PREFIX "\"sw64,irq-num\" not found\n"); - return -EINVAL; + nr_irqs = 16; + pr_warn(PREFIX "\"sw64,irq-num\" fallback to %u\n", + nr_irqs); } ret = of_property_read_u32(np, "sw64,ver", &version); if (ret) { - pr_err(PREFIX "\"sw64,ver\" not found\n"); - return -EINVAL; + version = 1; + pr_warn(PREFIX "\"sw64,ver\" fallback to %u\n", + version); } base = of_iomap(np, 0); @@ -162,21 +219,13 @@ static int __init lpc_intc_of_init(struct device_node *np, goto out_unmap; } - lpc_domain = irq_domain_add_legacy(np, nr_irqs, - 0, 0, &sw64_lpc_domain_ops, base); - if (!lpc_domain) { - pr_err(PREFIX "failed to create irq domain\n"); - ret = -ENOMEM; + ret = lpc_intc_init(of_node_to_fwnode(np), nr_irqs, parent_irq, base); + if (ret) goto out_unmap; - } pr_info(PREFIX "version [%u] on node [%u] initialized\n", version, node); - /* Set the IRQ chaining logic */ - irq_set_chained_handler_and_data(parent_irq, - lpc_irq_handler, lpc_domain); - return 0; out_unmap: @@ -184,3 +233,81 @@ static int __init lpc_intc_of_init(struct device_node *np, return ret; } IRQCHIP_DECLARE(sw_lpc_intc, "sw64,lpc_intc", lpc_intc_of_init); +#endif + +#ifdef CONFIG_ACPI +#define SW_LPC_INTC_FLAG_ENABLED ACPI_MADT_ENABLED /* 0x1 */ + +#define is_lpc_intc_enabled(flags) ((flags) & SW_LPC_INTC_FLAG_ENABLED) + +int __init lpc_intc_acpi_init(struct irq_domain *parent, + struct acpi_madt_sw_lpc_intc *lpc_intc) +{ + struct fwnode_handle *handle; + struct irq_fwspec fwspec; + void __iomem *base_addr; + int ret; + bool enabled; + + enabled = is_lpc_intc_enabled(lpc_intc->flags); + pr_info(PREFIX "version [%u] on node [%u] %s\n", + lpc_intc->version, lpc_intc->node, + enabled ? "found" : "disabled"); + if (!enabled) + return 0; + + if (lpc_intc->gsi_base != SW_LPC_INTC_GSI_BASE) { + pr_err(PREFIX "invalid GSI\n"); + return -EINVAL; + } + + handle = irq_domain_alloc_named_id_fwnode("LPC-INTC", lpc_intc->node); + if (!handle) { + pr_err(PREFIX "failed to alloc fwnode\n"); + return -ENOMEM; + } + + fwspec.fwnode = parent->fwnode; + fwspec.param[0] = lpc_intc->cascade_vector; + fwspec.param_count = 1; + + parent_irq = irq_create_fwspec_mapping(&fwspec); + if (parent_irq <= 0) { + pr_err(PREFIX "failed to map parent irq\n"); + ret = -EINVAL; + goto out_acpi_free_fwnode; + } + + base_addr = ioremap(lpc_intc->address, lpc_intc->size); + if (!base_addr) { + pr_err(PREFIX "failed to map base address\n"); + ret = -ENXIO; + goto out_acpi_free_fwnode; + } + + ret = lpc_intc_init(handle, lpc_intc->gsi_count, + parent_irq, base_addr); + if (ret) + goto out_acpi_unmap; + + ret = sw64_add_gsi_domain_map(lpc_intc->gsi_base, + lpc_intc->gsi_count, handle); + if (ret) { + pr_info(PREFIX "failed to add GSI map\n"); + goto out_acpi_free_lpc_domain; + } + + pr_info(PREFIX "version [%u] on node [%u] initialized\n", + lpc_intc->version, lpc_intc->node); + + return 0; + +out_acpi_free_lpc_domain: + irq_domain_remove(lpc_irq_domain); +out_acpi_unmap: + iounmap(base_addr); +out_acpi_free_fwnode: + irq_domain_free_fwnode(handle); + return ret; +} +#endif diff --git a/drivers/irqchip/irq-sunway-msi-v2.c b/drivers/irqchip/irq-sunway-msi-v2.c index 698c5c86408a..6f5c921fc520 100644 --- a/drivers/irqchip/irq-sunway-msi-v2.c +++ b/drivers/irqchip/irq-sunway-msi-v2.c @@ -3,10 +3,13 @@ #include #include #include +#include #include #include +#define PREFIX "MSIC: " + static struct irq_domain *msi_default_domain; static DEFINE_RAW_SPINLOCK(vector_lock); DEFINE_PER_CPU(vector_irq_t, vector_irq) = { @@ -508,3 +511,35 @@ void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned vector = int_pci_msi[i % 3]; } } + +MODULE_LICENSE("GPL v2"); + +#ifdef CONFIG_ACPI +#define SW_MSIC_FLAG_ENABLED ACPI_MADT_ENABLED /* 0x1 */ +#define SW_MSIC_FLAG_VIRTUAL 0x2 /* virtual MSIC */ + +#define is_msic_enabled(flags) ((flags) & SW_MSIC_FLAG_ENABLED) +#define is_msic_virtual(flags) ((flags) & SW_MSIC_FLAG_VIRTUAL) + +int __init msic_acpi_init(struct irq_domain *parent, + struct acpi_madt_sw_msic *msic) +{ + bool enabled, virtual; + + enabled = is_msic_enabled(msic->flags); + virtual = is_msic_virtual(msic->flags); + + pr_info(PREFIX "version [%u] on node [%u] Root Complex [%u] (%s) %s\n", + msic->version, msic->node, msic->rc, + virtual ? "virtual" : "physical", + enabled ? "found" : "disabled"); + + if (!enabled) + return 0; + + if (!msi_default_domain) + arch_init_msi_domain(parent); + + return 0; +} +#endif diff --git a/drivers/irqchip/irq-sunway-msi.c b/drivers/irqchip/irq-sunway-msi.c index 060aa96711b7..c231e504464b 100644 --- a/drivers/irqchip/irq-sunway-msi.c +++ b/drivers/irqchip/irq-sunway-msi.c @@ -2,10 +2,13 @@ #include #include #include +#include #include #include +#define PREFIX "MSIC: " + static struct irq_domain *msi_default_domain; static DEFINE_RAW_SPINLOCK(vector_lock); DEFINE_PER_CPU(vector_irq_t, vector_irq) = { @@ -470,3 +473,35 @@ void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned vector = int_pci_msi[i % 3]; } } + +MODULE_LICENSE("GPL v2"); + +#ifdef CONFIG_ACPI +#define SW_MSIC_FLAG_ENABLED ACPI_MADT_ENABLED /* 0x1 */ +#define SW_MSIC_FLAG_VIRTUAL 0x2 /* virtual MSIC */ + +#define is_msic_enabled(flags) ((flags) & SW_MSIC_FLAG_ENABLED) +#define is_msic_virtual(flags) ((flags) & SW_MSIC_FLAG_VIRTUAL) + +int __init msic_acpi_init(struct irq_domain *parent, + struct acpi_madt_sw_msic *msic) +{ + bool enabled, virtual; + + enabled = is_msic_enabled(msic->flags); + virtual = is_msic_virtual(msic->flags); + + pr_info(PREFIX "version [%u] on node [%u] Root Complex [%u] (%s) %s\n", + msic->version, msic->node, msic->rc, + virtual ? "virtual" : "physical", + enabled ? "found" : "disabled"); + + if (!enabled) + return 0; + + if (!msi_default_domain) + arch_init_msi_domain(parent); + + return 0; +} +#endif diff --git a/drivers/irqchip/irq-sunway-pintc.c b/drivers/irqchip/irq-sunway-pintc.c index 41c52f9fb09b..fa3af8c1c585 100644 --- a/drivers/irqchip/irq-sunway-pintc.c +++ b/drivers/irqchip/irq-sunway-pintc.c @@ -7,12 +7,54 @@ #include #include +/** + * Currently, Peripheral interrupt control logic of Sunway is mainly + * distributed on the device side, which are hardware entities + * corresponding to SW sub PINTC structures. + * + * At the same time, there are some interrupt configuration registers + * concentrated in INTPU, which is hardware entity corresponding to + * SW PINTC, excluding SW sub PINTC structures. + * + * The topology of SW PINTC(physical) is as follows: + * + * +----------------------------------------------------------------+ + * | | + * | +--------------------------------+ | + * | | SW CINTC | | + * | +--------------------------------+ | + * | | | | | | + * | _________| __| |__ |______ | + * | | | | | | + * | +-------|---------------|--------------|------------|------+ | + * | | | | | | | | + * | | +----------+ +--------+ +--------+ +--------+ | | + * | | | MCU | | MT | | ADR | | ...... | | | + * | | +----------+ +--------+ +--------+ +--------+ | | + * | | | SW PINTC | | + * | +-------|--------------------------------------------------+ | + * | | | + * | +--------------+ | + * | | SW LPC INTC | | + * | +--------------+ | + * | | + * +----------------------------------------------------------------+ + */ + #define PREFIX "PINTC: " #define OFFSET_MCU_DVC_INT_EN 0x3080UL #define OFFSET_DEV_INT_CONFIG 0x480UL +#define SW_PINTC_MCU_GSI_BASE 64 + +#define INTPU_BASE_V1 0x802a00000000 +#define INTPU_SIZE_V1 0x1680 + +#define MCU_BASE_V1 0x803000000000 +#define MCU_SIZE_V1 0x8f00 + struct pintc_chip_data { bool vt; /* virtual pintc */ u32 node; /* node ID */ @@ -20,6 +62,7 @@ struct pintc_chip_data { void __iomem *pintc_base; /* INTPU base address */ void __iomem *mcu_base; /* MCU/SPBU base address */ struct irq_chip *mcu_chip; + u32 mcu_irq_num; }; static DEFINE_RAW_SPINLOCK(pintc_lock); @@ -177,6 +220,33 @@ static struct irq_chip pintc_mcu_vt_chip = { .name = "VMCU-INT", }; +static int pintc_mcu_translate(struct irq_domain *domain, + struct irq_fwspec *fwspec, + unsigned long *hwirq, + unsigned int *type) +{ + if (WARN_ON(fwspec->param_count < 1)) + return -EINVAL; + + /* Device tree */ + if (is_of_node(fwspec->fwnode)) { + *hwirq = fwspec->param[0]; + *type = IRQ_TYPE_NONE; + return 0; + } + + /* ACPI */ + if (is_fwnode_irqchip(fwspec->fwnode)) { + if (WARN_ON(fwspec->param[0] < SW_PINTC_MCU_GSI_BASE)) + return -EINVAL; + *hwirq = fwspec->param[0] - SW_PINTC_MCU_GSI_BASE; + *type = IRQ_TYPE_NONE; + return 0; + } + + return -EINVAL; +} + static void pintc_mcu_free_irqs(struct irq_domain *irq_domain, unsigned int virq, unsigned int nr_irqs) { @@ -207,8 +277,13 @@ static int pintc_mcu_alloc_irqs(struct irq_domain *domain, void *arg) { struct irq_fwspec *fwspec = arg; - irq_hw_number_t hwirq = fwspec->param[0]; - int i; + irq_hw_number_t hwirq; + unsigned int type; + int i, ret; + + ret = pintc_mcu_translate(domain, fwspec, &hwirq, &type); + if (ret) + return ret; for (i = 0; i < nr_irqs; i++) pintc_mcu_map_irq(domain, virq + i, hwirq + i); @@ -218,7 +293,7 @@ static int pintc_mcu_alloc_irqs(struct irq_domain *domain, static const struct irq_domain_ops pintc_mcu_domain_ops = { .map = pintc_mcu_map_irq, - .xlate = irq_domain_xlate_onecell, + .translate = pintc_mcu_translate, .alloc = pintc_mcu_alloc_irqs, .free = pintc_mcu_free_irqs, }; @@ -226,6 +301,44 @@ static const struct irq_domain_ops pintc_mcu_domain_ops = { struct irq_domain *mcu_irq_domain; EXPORT_SYMBOL(mcu_irq_domain); +static int __init pintc_init_mcu(struct pintc_chip_data *chip_data, + struct fwnode_handle *handle) +{ + unsigned int mcu_irq_num = chip_data->mcu_irq_num; + + if (chip_data->vt) { + chip_data->mcu_chip = &pintc_mcu_vt_chip; + + /** + * The current kernel does not support the API + * "irq_domain_create_legacy", we have to call + * "__irq_domain_add" directly. + */ + mcu_irq_domain = __irq_domain_add(handle, mcu_irq_num, + mcu_irq_num, 0, &pintc_mcu_domain_ops, + chip_data); + if (mcu_irq_domain) + irq_domain_associate_many(mcu_irq_domain, + 0, 0, mcu_irq_num); + } else { + chip_data->mcu_chip = &pintc_mcu_chip; + mcu_irq_domain = irq_domain_create_linear(handle, mcu_irq_num, + &pintc_mcu_domain_ops, chip_data); + /* Mask all interrupts for now */ + writeq(0x0, chip_data->mcu_base + OFFSET_MCU_DVC_INT_EN); + } + + if (!mcu_irq_domain) { + pr_err(PREFIX "failed to create MCU irq domain\n"); + return -ENOMEM; + } + + pr_info(PREFIX "MCU sub controller [%u:%u] initialized\n", + chip_data->version, chip_data->node); + + return 0; +} + #ifdef CONFIG_OF static int __init pintc_of_init_common(struct device_node *pintc, @@ -247,39 +360,43 @@ pintc_of_init_common(struct device_node *pintc, ret = of_property_read_u32(pintc, "sw64,node", &node); if (ret) { - pr_err(PREFIX "\"sw64,node\" not found\n"); - return -EINVAL; + node = 0; + pr_warn(PREFIX "\"sw64,node\" fallback to %u\n", + node); } ret = of_property_read_u32(pintc, "sw64,irq-num", &nr_irqs); if (ret) { - pr_err(PREFIX "\"sw64,irq-num\" not found\n"); - return -EINVAL; + nr_irqs = vt ? 16 : 8; + pr_warn(PREFIX "\"sw64,irq-num\" fallback to %u\n", + nr_irqs); } ret = of_property_read_u32(pintc, "sw64,ver", &version); if (ret) { - pr_err(PREFIX "\"sw64,ver\" not found\n"); - return -EINVAL; + version = 1; + pr_warn(PREFIX "\"sw64,ver\" fallback to %u\n", + version); } pintc_base = of_iomap(pintc, 0); if (!vt && !pintc_base) { - pr_err(PREFIX "failed to map pintc base address\n"); - return -ENXIO; + pintc_base = ioremap(INTPU_BASE_V1, INTPU_SIZE_V1); + pr_warn(PREFIX "pintc base address fallback to 0x%lx\n", + INTPU_BASE_V1); } mcu_base = of_iomap(pintc, 1); if (!vt && !mcu_base) { - pr_err(PREFIX "failed to map mcu base address\n"); - ret = -ENXIO; - goto out_unmap0; + mcu_base = ioremap(MCU_BASE_V1, MCU_SIZE_V1); + pr_warn(PREFIX "mcu base address fallback to 0x%lx\n", + MCU_BASE_V1); } chip_data = kzalloc_node(sizeof(*chip_data), GFP_KERNEL, node); if (!chip_data) { ret = -ENOMEM; - goto out_unmap1; + goto out_unmap; } chip_data->vt = vt; @@ -287,37 +404,18 @@ pintc_of_init_common(struct device_node *pintc, chip_data->version = version; chip_data->pintc_base = pintc_base; chip_data->mcu_base = mcu_base; + chip_data->mcu_irq_num = nr_irqs; - if (vt) { - chip_data->mcu_chip = &pintc_mcu_vt_chip; - mcu_irq_domain = irq_domain_add_legacy(pintc, nr_irqs, 0, 0, - &pintc_mcu_domain_ops, chip_data); - } else { - chip_data->mcu_chip = &pintc_mcu_chip; - mcu_irq_domain = irq_domain_add_linear(pintc, nr_irqs, - &pintc_mcu_domain_ops, chip_data); - /* mask all interrupts for now */ - writeq(0x0, mcu_base + OFFSET_MCU_DVC_INT_EN); - } - - if (!mcu_irq_domain) { - pr_err(PREFIX "failed to create irq domain\n"); - ret = -ENOMEM; + ret = pintc_init_mcu(chip_data, of_node_to_fwnode(pintc)); + if (ret) goto out_free_mem; - } - - pr_info(PREFIX "version [%u] on node [%u] initialized\n", - version, node); - - irq_set_default_host(mcu_irq_domain); return 0; out_free_mem: kfree(chip_data); -out_unmap1: +out_unmap: iounmap(mcu_base); -out_unmap0: iounmap(pintc_base); return ret; } @@ -329,6 +427,7 @@ pintc_of_init(struct device_node *pintc, struct device_node *parent) } IRQCHIP_DECLARE(sw64_pintc, "sw64,pintc", pintc_of_init); +IRQCHIP_DECLARE(sw64_pintc_legacy, "sw64,sw6_irq_controller", pintc_of_init); static int __init pintc_vt_of_init(struct device_node *pintc, struct device_node *parent) @@ -337,4 +436,176 @@ pintc_vt_of_init(struct device_node *pintc, struct device_node *parent) } IRQCHIP_DECLARE(sw64_pintc_vt, "sw64,pintc_vt", pintc_vt_of_init); +IRQCHIP_DECLARE(sw64_pintc_vt_legacy, "sw64,sw6_irq_vt_controller", pintc_vt_of_init); +#endif + +#ifdef CONFIG_ACPI +#define SW_PINTC_FLAG_ENABLED ACPI_MADT_ENABLED /* 0x1 */ +#define SW_PINTC_FLAG_VIRTUAL 0x2 /* virtual PINTC */ + +#define is_pintc_enabled(flags) ((flags) & SW_PINTC_FLAG_ENABLED) +#define is_pintc_virtual(flags) ((flags) & SW_PINTC_FLAG_VIRTUAL) + +/* Physical sub interrupt controllers */ +enum sw_pintc_sub_type { + SW_PINTC_SUB_TYPE_MCU = 0x00, + SW_PINTC_SUB_TYPE_MT = 0x01, + SW_PINTC_SUB_TYPE_FAULT = 0x02, + SW_PINTC_SUB_TYPE_NMI = 0x03, + SW_PINTC_SUB_TYPE_S3 = 0x04, + SW_PINTC_SUB_TYPE_ADR = 0x05, + SW_PINTC_SUB_TYPE_COUNT +}; + +static int __init lpc_intc_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_sw_lpc_intc *lpc_intc; + + lpc_intc = (struct acpi_madt_sw_lpc_intc *)header; + + /* Not yet supported */ + if (lpc_intc->node > 0) + return 0; + + if ((lpc_intc->version == ACPI_MADT_SW_LPC_INTC_VERSION_NONE) || + (lpc_intc->version >= ACPI_MADT_SW_LPC_INTC_VERSION_RESERVED)) { + pr_err(PREFIX "invalid LPC-INTC version\n"); + return -EINVAL; + } + + return lpc_intc_acpi_init(mcu_irq_domain, lpc_intc); +} + +static bool __init +pintc_sub_type_check(const struct acpi_madt_sw_pintc *pintc) +{ + int i, count = 0; + + for (i = 0; i < pintc->sub_num; ++i) { + if (pintc->sub[i].type >= SW_PINTC_SUB_TYPE_COUNT) + count++; + } + + return count; +} + +static int __init pintc_acpi_init_mcu(struct pintc_chip_data *chip_data, + struct acpi_madt_sw_sub_pintc *mcu) +{ + struct fwnode_handle *handle; + int ret; + + if (!mcu->status) { + pr_info(PREFIX "MCU sub controller [%u:%u] disabled\n", + chip_data->version, chip_data->node); + return 0; + } + + if (mcu->gsi_base != SW_PINTC_MCU_GSI_BASE) { + pr_err(PREFIX "invalid MCU GSI\n"); + return -EINVAL; + } + + handle = irq_domain_alloc_named_id_fwnode("PINTC-MCU", chip_data->node); + if (!handle) { + pr_err(PREFIX "failed to alloc fwnode\n"); + return -ENOMEM; + } + + chip_data->mcu_irq_num = mcu->gsi_count; + + chip_data->mcu_base = ioremap(mcu->address, mcu->size); + if (!chip_data->mcu_base) { + pr_err(PREFIX "failed to map mcu base address\n"); + ret = -ENXIO; + goto out_acpi_free_fwnode; + } + + ret = pintc_init_mcu(chip_data, handle); + if (ret) + goto out_acpi_unmap_mcu; + + ret = sw64_add_gsi_domain_map(mcu->gsi_base, mcu->gsi_count, handle); + if (ret) { + pr_info(PREFIX "failed to add GSI map\n"); + goto out_acpi_free_mcu_domain; + } + + return 0; + +out_acpi_free_mcu_domain: + irq_domain_remove(mcu_irq_domain); +out_acpi_unmap_mcu: + iounmap(chip_data->mcu_base); +out_acpi_free_fwnode: + irq_domain_free_fwnode(handle); + return ret; +} + +int __init pintc_acpi_init(struct irq_domain *parent, + struct acpi_madt_sw_pintc *pintc) +{ + struct pintc_chip_data *chip_data; + int ret, i; + bool enabled, virtual; + + enabled = is_pintc_enabled(pintc->flags); + virtual = is_pintc_virtual(pintc->flags); + + pr_info(PREFIX "version [%u] on node [%u] (%s) %s\n", + pintc->version, pintc->node, + virtual ? "virtual" : "physical", + enabled ? "found" : "disabled"); + + if (!enabled) + return 0; + + if (pintc_sub_type_check(pintc)) { + pr_err(PREFIX "invalid sub type\n"); + return -EINVAL; + } + + chip_data = kzalloc_node(sizeof(*chip_data), GFP_KERNEL, + pintc->node); + if (!chip_data) + return -ENOMEM; + + /** + * The topology of interrupt controllers in Qemu is + * different from physical environment. We need to + * distinguish between them. + */ + chip_data->vt = virtual; + + chip_data->node = pintc->node; + chip_data->version = pintc->version; + + chip_data->pintc_base = ioremap(pintc->address, pintc->size); + if (!chip_data->pintc_base) { + pr_err(PREFIX "failed to map pintc base address\n"); + ret = -ENXIO; + goto out_acpi_free_chip_data; + } + + for (i = 0; i < pintc->sub_num; ++i) { + switch (pintc->sub[i].type) { + case SW_PINTC_SUB_TYPE_MCU: + pintc_acpi_init_mcu(chip_data, &pintc->sub[i]); + break; + default: + break; + } + } + + /* Init SW LPC INTC */ + acpi_table_parse_madt(ACPI_MADT_TYPE_SW_LPC_INTC, + lpc_intc_parse_madt, 0); + + return 0; + +out_acpi_free_chip_data: + kfree(chip_data); + return ret; +} #endif diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index f18ca00bb863..1236de5aee53 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -1369,7 +1369,8 @@ enum acpi_madt_sw_cintc_version { struct acpi_madt_sw_sub_pintc { u8 type; - u8 reserved[3]; + u8 status; + u16 reserved; u32 hardware_id; u64 address; u32 size; @@ -1413,7 +1414,8 @@ struct acpi_madt_sw_msic { u32 node; u32 rc; u32 num; - u32 reserved1[4]; + u64 message_address; + u32 reserved1[2]; }; /* Values for version field above */ diff --git a/include/linux/acpi.h b/include/linux/acpi.h index dadc6de0bce4..e254b5b8584a 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -95,6 +95,9 @@ enum acpi_irq_model_id { ACPI_IRQ_MODEL_PLATFORM, ACPI_IRQ_MODEL_GIC, ACPI_IRQ_MODEL_LPIC, +#ifdef CONFIG_SW64 + ACPI_IRQ_MODEL_SWPIC, +#endif ACPI_IRQ_MODEL_COUNT }; -- Gitee From e6d8cf345ed77c86b7397d9ce4e53c3525e5f76a Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 20 Dec 2023 19:12:17 +0800 Subject: [PATCH 47/98] sw64: acpi: enable generic GSI Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Use common implementation of GSI provided by kernel instead of the architecture specific implementation. In addition, this commit also remove some useless code. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 1 + arch/sw_64/kernel/acpi.c | 67 +--------------------------------------- 2 files changed, 2 insertions(+), 66 deletions(-) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 2639987c44bf..02e4c672c8b8 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -3,6 +3,7 @@ config SW64 bool default y select ACPI + select ACPI_GENERIC_GSI if ACPI select ACPI_MCFG if (ACPI && PCI) select ACPI_REDUCED_HARDWARE_ONLY select ARCH_ATOMIC diff --git a/arch/sw_64/kernel/acpi.c b/arch/sw_64/kernel/acpi.c index 56805db4431e..f2b2a4d5ce67 100644 --- a/arch/sw_64/kernel/acpi.c +++ b/arch/sw_64/kernel/acpi.c @@ -39,11 +39,7 @@ u64 acpi_saved_sp_s3; #define MAX_LOCAL_APIC 256 #define PREFIX "ACPI: " -/* - * The default interrupt routing model is PIC (8259). This gets - * overridden if IOAPICs are enumerated (below). - */ -enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC; + void __iomem *__init __acpi_map_table(unsigned long phys, unsigned long size) { if (!phys || !size) @@ -58,17 +54,6 @@ void __init __acpi_unmap_table(void __iomem *map, unsigned long size) early_iounmap(map, size); } -/* - * Following __acpi_xx functions should be implemented for sepecific cpu. - */ -int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp) -{ - if (irqp != NULL) - *irqp = acpi_register_gsi(NULL, gsi, -1, -1); - - return 0; -} -EXPORT_SYMBOL_GPL(acpi_gsi_to_irq); int acpi_isa_irq_to_gsi(unsigned int isa_irq, u32 *gsi) { @@ -80,56 +65,6 @@ int acpi_isa_irq_to_gsi(unsigned int isa_irq, u32 *gsi) int (*acpi_suspend_lowlevel)(void); -/* - * success: return IRQ number (>=0) - * failure: return < 0 - */ -static struct irq_domain *irq_default_domain; -int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) -{ - u32 irq; - - irq = irq_find_mapping(irq_default_domain, gsi); - - return irq; -} -EXPORT_SYMBOL_GPL(acpi_register_gsi); - -void acpi_unregister_gsi(u32 gsi) -{ - -} -EXPORT_SYMBOL_GPL(acpi_unregister_gsi); - -/* - * ACPI based hotplug support for CPU - */ -#ifdef CONFIG_ACPI_HOTPLUG_CPU -/* wrapper to silence section mismatch warning */ -int __ref acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu) -{ - return 0; -} -EXPORT_SYMBOL(acpi_map_lsapic); - -int acpi_unmap_lsapic(int cpu) -{ - return 0; -} -EXPORT_SYMBOL(acpi_unmap_lsapic); -#endif /* CONFIG_ACPI_HOTPLUG_CPU */ - -u8 acpi_checksum(u8 *table, u32 length) -{ - u8 ret = 0; - - while (length--) { - ret += *table; - table++; - } - return -ret; -} - static int __init parse_acpi(char *arg) { if (!arg) -- Gitee From c6713b35a0cf3f5e0aeafd6eb12fa859494b41bc Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 21 Feb 2024 09:49:32 +0800 Subject: [PATCH 48/98] sw64: irq: remove unnecessary initialization Sunway inclusion category: performance bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- It is unnecessary to set irqchip and handle for all irqs during early initialization. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/Makefile | 2 +- arch/sw_64/kernel/irq.c | 41 ++++++++++++++++++ arch/sw_64/kernel/irq_sw64.c | 84 ------------------------------------ 3 files changed, 42 insertions(+), 85 deletions(-) delete mode 100644 arch/sw_64/kernel/irq_sw64.c diff --git a/arch/sw_64/kernel/Makefile b/arch/sw_64/kernel/Makefile index abf27ad19a94..5ac06882ebc0 100644 --- a/arch/sw_64/kernel/Makefile +++ b/arch/sw_64/kernel/Makefile @@ -14,7 +14,7 @@ CFLAGS_REMOVE_printk.o = -pg endif obj-y := entry.o fpu.o traps.o process.o sys_sw64.o irq.o \ - irq_sw64.o signal.o setup.o ptrace.o time.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 \ vdso.o vdso/ hmcall.o stacktrace.o idle.o reset.o \ diff --git a/arch/sw_64/kernel/irq.c b/arch/sw_64/kernel/irq.c index 126fe2f70495..58ee5131e2a9 100644 --- a/arch/sw_64/kernel/irq.c +++ b/arch/sw_64/kernel/irq.c @@ -14,8 +14,11 @@ #include #include #include +#include #include +#include + volatile unsigned long irq_err_count; DEFINE_PER_CPU(unsigned long, irq_pmi_count); DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); @@ -106,3 +109,41 @@ void fixup_irqs(void) irq_migrate_all_off_this_cpu(); } #endif + +void __init init_IRQ(void) +{ + /* + * Just in case the platform init_irq() causes interrupts/mchecks + * (as is the case with RAWHIDE, at least). + */ + if (is_in_host()) { + 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); + + sw64_init_irq(); + irqchip_init(); +} + +void __weak arch_init_msi_domain(struct irq_domain *parent) {} + +int __init arch_early_irq_init(void) +{ + arch_init_msi_domain(NULL); + + return 0; +} + +int __init arch_probe_nr_irqs(void) +{ + return NR_IRQS_LEGACY; +} + +struct irq_chip sw64_irq_chip = { + .name = "SW64_DUMMY" +}; +EXPORT_SYMBOL(sw64_irq_chip); diff --git a/arch/sw_64/kernel/irq_sw64.c b/arch/sw_64/kernel/irq_sw64.c deleted file mode 100644 index 03aef463ec05..000000000000 --- a/arch/sw_64/kernel/irq_sw64.c +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * SW64 specific irq code. - */ - -#include -#include - -#include -#include - -void __init -init_IRQ(void) -{ - /* - * Just in case the platform init_irq() causes interrupts/mchecks - * (as is the case with RAWHIDE, at least). - */ - if (is_in_host()) { - 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); - - sw64_init_irq(); - irqchip_init(); -} - -DEFINE_SPINLOCK(irq_lock); - -static void -__enable_irq(struct irq_data *d) -{ -} - -static void -__disable_irq(struct irq_data *d) -{ -} - -static unsigned int -__startup_irq(struct irq_data *d) -{ - __enable_irq(d); - return 0; -} - -static void -__mask_and_ack_irq(struct irq_data *d) -{ - spin_lock(&irq_lock); - __disable_irq(d); - spin_unlock(&irq_lock); -} - -struct irq_chip sw64_irq_chip = { - .name = "SW64_NODE", - .irq_startup = __startup_irq, - .irq_unmask = __enable_irq, - .irq_mask = __disable_irq, - .irq_mask_ack = __mask_and_ack_irq, -}; - -void __weak arch_init_msi_domain(struct irq_domain *parent) {} - -int __init arch_early_irq_init(void) -{ - int i; - - for (i = 0; i < NR_IRQS; ++i) { - irq_set_chip_and_handler(i, &sw64_irq_chip, handle_level_irq); - irq_set_status_flags(i, IRQ_LEVEL); - } - arch_init_msi_domain(NULL); - return 0; -} - -int __init arch_probe_nr_irqs(void) -{ - return NR_IRQS_LEGACY; -} -- Gitee From 558957e130103769e773dcf0222fa56f52017c1e Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 11 Jan 2024 13:43:01 +0800 Subject: [PATCH 49/98] sw64: pci: remove duplicate pcie operations Sunway inclusion category: performance bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Use pcie operations implemented in pci-sunway.c and remove the duplicate one. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/pci.h | 10 ++ arch/sw_64/pci/pci-legacy.c | 192 +++------------------------- drivers/pci/controller/pci-sunway.c | 17 ++- 3 files changed, 40 insertions(+), 179 deletions(-) diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index 689a65e63517..07c447479efa 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -99,6 +99,16 @@ extern void sw64_pci_root_bridge_prepare(struct pci_host_bridge *bridge); extern void sw64_pci_root_bridge_scan_finish_up(struct pci_host_bridge *bridge); extern int sw64_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); +extern void __iomem *sw64_pcie_map_bus(struct pci_bus *bus, + unsigned int devfn, int where); +extern int sw64_pcie_config_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val); +extern int sw64_pcie_config_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val); + +extern void pci_mark_rc_linkup(unsigned long node, unsigned long index); +extern int pci_get_rc_linkup(unsigned long node, unsigned long index); + #ifdef CONFIG_PCI_DOMAINS static inline int pci_proc_domain(struct pci_bus *bus) { diff --git a/arch/sw_64/pci/pci-legacy.c b/arch/sw_64/pci/pci-legacy.c index 2a44463db0a4..bfaa08bf72c0 100644 --- a/arch/sw_64/pci/pci-legacy.c +++ b/arch/sw_64/pci/pci-legacy.c @@ -5,11 +5,10 @@ #include #include +#include #include #include -unsigned long rc_linkup; - /* * The PCI controller list. */ @@ -196,175 +195,10 @@ static void __init pcibios_reserve_legacy_regions(struct pci_bus *bus) return; } -/* PCIe RC operations */ -int sw6_pcie_read_rc_cfg(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 *val) -{ - u32 data; - struct pci_controller *hose = pci_bus_to_pci_controller(bus); - void __iomem *cfg_iobase = hose->rc_config_space_base; - - if (IS_ENABLED(CONFIG_PCI_DEBUG)) - pr_debug("rc read addr:%px bus %d, devfn %#x, where %#x size=%d\t", - cfg_iobase + ((where & ~3) << 5), bus->number, devfn, where, size); - - if ((uintptr_t)where & (size - 1)) { - *val = 0; - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (unlikely(devfn > 0)) { - *val = ~0; - return PCIBIOS_DEVICE_NOT_FOUND; - } - - data = readl(cfg_iobase + ((where & ~3) << 5)); - - switch (size) { - case 1: - *val = (data >> (8 * (where & 0x3))) & 0xff; - break; - case 2: - *val = (data >> (8 * (where & 0x2))) & 0xffff; - break; - default: - *val = data; - break; - } - - if (IS_ENABLED(CONFIG_PCI_DEBUG)) - pr_debug("*val %#x\n ", *val); - - return PCIBIOS_SUCCESSFUL; -} - -int sw6_pcie_write_rc_cfg(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 val) -{ - u32 data; - u32 shift = 8 * (where & 3); - struct pci_controller *hose = pci_bus_to_pci_controller(bus); - void __iomem *cfg_iobase = (void *)hose->rc_config_space_base; - - if ((uintptr_t)where & (size - 1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - - switch (size) { - case 1: - data = readl(cfg_iobase + ((where & ~3) << 5)); - data &= ~(0xff << shift); - data |= (val & 0xff) << shift; - break; - case 2: - data = readl(cfg_iobase + ((where & ~3) << 5)); - data &= ~(0xffff << shift); - data |= (val & 0xffff) << shift; - break; - default: - data = val; - break; - } - - if (IS_ENABLED(CONFIG_PCI_DEBUG)) - pr_debug("rc write addr:%px bus %d, devfn %#x, where %#x *val %#x size %d\n", - cfg_iobase + ((where & ~3) << 5), bus->number, devfn, where, val, size); - - writel(data, cfg_iobase + ((where & ~3) << 5)); - - return PCIBIOS_SUCCESSFUL; -} - -int sw6_pcie_config_read(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 *val) -{ - struct pci_controller *hose = pci_bus_to_pci_controller(bus); - int ret = PCIBIOS_DEVICE_NOT_FOUND; - - if (is_guest_or_emul()) - return pci_generic_config_read(bus, devfn, where, size, val); - - hose->self_busno = hose->busn_space->start; - - if (unlikely(bus->number == hose->self_busno)) { - ret = sw6_pcie_read_rc_cfg(bus, devfn, where, size, val); - } else { - if (test_bit(hose->node * 8 + hose->index, &rc_linkup)) - ret = pci_generic_config_read(bus, devfn, where, size, val); - else - return ret; - } - return ret; -} - -int sw6_pcie_config_write(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 val) -{ - struct pci_controller *hose = pci_bus_to_pci_controller(bus); - - if (is_guest_or_emul()) - return pci_generic_config_write(bus, devfn, where, size, val); - - hose->self_busno = hose->busn_space->start; - - if (unlikely(bus->number == hose->self_busno)) - return sw6_pcie_write_rc_cfg(bus, devfn, where, size, val); - else - return pci_generic_config_write(bus, devfn, where, size, val); -} - -/* - *sw6_pcie_valid_device - Check if a valid device is present on bus - *@bus: PCI Bus structure - *@devfn: device/function - * - *Return: 'true' on success and 'false' if invalid device is found - */ -static bool sw6_pcie_valid_device(struct pci_bus *bus, unsigned int devfn) -{ - struct pci_controller *hose = pci_bus_to_pci_controller(bus); - - if (is_in_host()) { - /* Only one device down on each root complex */ - if (bus->number == hose->self_busno && devfn > 0) - return false; - } - - return true; -} - -/* - *sw6_pcie_map_bus - Get configuration base - *@bus: PCI Bus structure - *@devfn: Device/function - *@where: Offset from base - * - *Return: Base address of the configuration space needed to be - *accessed. - */ -static void __iomem *sw6_pcie_map_bus(struct pci_bus *bus, - unsigned int devfn, int where) -{ - struct pci_controller *hose = pci_bus_to_pci_controller(bus); - void __iomem *cfg_iobase; - unsigned long relbus; - - if (!sw6_pcie_valid_device(bus, devfn)) - return NULL; - - relbus = (bus->number << 24) | (devfn << 16) | where; - - cfg_iobase = hose->ep_config_space_base + relbus; - - if (IS_ENABLED(CONFIG_PCI_DEBUG)) - pr_debug("addr:%px bus %d, devfn %d, where %d\n", - cfg_iobase, bus->number, devfn, where); - return cfg_iobase; -} - struct pci_ops sw64_pci_ops = { - .map_bus = sw6_pcie_map_bus, - .read = sw6_pcie_config_read, - .write = sw6_pcie_config_write, + .map_bus = sw64_pcie_map_bus, + .read = sw64_pcie_config_read, + .write = sw64_pcie_config_write, }; int sw64_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) @@ -399,13 +233,25 @@ sw64_init_host(unsigned long node, unsigned long index) ret = sw64_chip_init->pci_init.check_pci_linkup(node, index); if (ret == 0) { /* Root Complex downstream port is link up */ - set_bit(node * 8 + index, &rc_linkup); //8-bit per node + pci_mark_rc_linkup(node, index); // 8-bit per node } } void __weak set_devint_wken(int node) {} void __weak set_adr_int(int node) {} +static bool __init is_any_rc_linkup_one_node(unsigned long node) +{ + int i; + + for (i = 0; i < 8; ++i) { + if (pci_get_rc_linkup(node, i)) + return true; + } + + return false; +} + void __init sw64_init_arch(void) { if (IS_ENABLED(CONFIG_PCI)) { @@ -437,11 +283,11 @@ void __init sw64_init_arch(void) if ((rc_enable >> i) & 0x1) sw64_init_host(node, i); } - if ((rc_linkup >> node * 8) & 0xff) { + if (is_any_rc_linkup_one_node(node)) { memset(msg, 0, 64); sprintf(msg, "Node %ld: RC [ ", node); for (i = 0; i < MAX_NR_RCS; i++) { - if ((rc_linkup >> (i + node * 8)) & 1) { + if (pci_get_rc_linkup(node, i)) { memset(id, 0, 8); sprintf(id, "%d ", i); strcat(msg, id); diff --git a/drivers/pci/controller/pci-sunway.c b/drivers/pci/controller/pci-sunway.c index 7cd612bb82bb..46a75ef1a3e9 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -349,15 +349,17 @@ void __init setup_chip_pci_ops(void) static unsigned long rc_linkup; static struct pci_controller *head, **tail = &head; -static void pci_mark_rc_linkup(unsigned long node, unsigned long index) +void pci_mark_rc_linkup(unsigned long node, unsigned long index) { set_bit(node * 8 + index, &rc_linkup); } +EXPORT_SYMBOL(pci_mark_rc_linkup); -static int pci_get_rc_linkup(unsigned long node, unsigned long index) +int pci_get_rc_linkup(unsigned long node, unsigned long index) { return test_bit(node * 8 + index, &rc_linkup); } +EXPORT_SYMBOL(pci_get_rc_linkup); /** * Link the specified pci controller to list @@ -456,7 +458,7 @@ static int sw64_pcie_read_rc_cfg(struct pci_bus *bus, unsigned int devfn, /** * PCIe Root Complex write config space operations */ -int sw64_pcie_write_rc_cfg(struct pci_bus *bus, unsigned int devfn, +static int sw64_pcie_write_rc_cfg(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) { u32 data; @@ -528,7 +530,7 @@ static bool sw64_pcie_valid_device(struct pci_bus *bus, unsigned int devfn) * * @return: Whether read operation success */ -static int sw64_pcie_config_read(struct pci_bus *bus, unsigned int devfn, +int sw64_pcie_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) { struct pci_controller *hose = pci_bus_to_pci_controller(bus); @@ -549,6 +551,7 @@ static int sw64_pcie_config_read(struct pci_bus *bus, unsigned int devfn, } return ret; } +EXPORT_SYMBOL(sw64_pcie_config_read); /** * sw64_pcie_config_write - write val to config space of PCI @@ -562,7 +565,7 @@ static int sw64_pcie_config_read(struct pci_bus *bus, unsigned int devfn, * * @return: Whether write operation success */ -static int sw64_pcie_config_write(struct pci_bus *bus, unsigned int devfn, +int sw64_pcie_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) { struct pci_controller *hose = pci_bus_to_pci_controller(bus); @@ -577,6 +580,7 @@ static int sw64_pcie_config_write(struct pci_bus *bus, unsigned int devfn, else return pci_generic_config_write(bus, devfn, where, size, val); } +EXPORT_SYMBOL(sw64_pcie_config_write); /** * sw64_pcie_map_bus - get configuration base address @@ -587,7 +591,7 @@ static int sw64_pcie_config_write(struct pci_bus *bus, unsigned int devfn, * @return: base address of the configuration space needed to be * accessed. */ -static void __iomem *sw64_pcie_map_bus(struct pci_bus *bus, +void __iomem *sw64_pcie_map_bus(struct pci_bus *bus, unsigned int devfn, int where) { struct pci_controller *hose = pci_bus_to_pci_controller(bus); @@ -616,6 +620,7 @@ static void __iomem *sw64_pcie_map_bus(struct pci_bus *bus, cfg_iobase, bus->number, devfn, where); return cfg_iobase; } +EXPORT_SYMBOL(sw64_pcie_map_bus); int sw64_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { -- Gitee From 2e09f54231385b6921b9e01bff780ec9ec9e5bfa Mon Sep 17 00:00:00 2001 From: Jing Li Date: Mon, 26 Feb 2024 08:31:19 +0800 Subject: [PATCH 50/98] sw64: acpi: fix missed upper bits of rcid for junzhang Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- When initializing CPU affinity, only lower 8 bits of rcid are recorded. Because 8 bits are sufficient for xuelang's rcid. However, the rcid for junzhang needs more bits. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/acpi.c | 36 +++++++++++++++++------------------- include/linux/acpi.h | 2 +- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/arch/sw_64/kernel/acpi.c b/arch/sw_64/kernel/acpi.c index f2b2a4d5ce67..af80ae304948 100644 --- a/arch/sw_64/kernel/acpi.c +++ b/arch/sw_64/kernel/acpi.c @@ -114,26 +114,24 @@ static int rcid_to_cpu(int physical_id) /* Callback for Proximity Domain -> CPUID mapping */ void __init -acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) +acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) { int pxm, node; - int cpu; // logical core id + int cpu; // logical core id + int rcid; // physical core id if (srat_disabled()) return; - if (pa->header.length != sizeof(struct acpi_srat_cpu_affinity)) { + + if (pa->header.length != sizeof(struct acpi_srat_x2apic_cpu_affinity)) { bad_srat(); return; } + if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0) return; - pxm = pa->proximity_domain_lo; - if (acpi_srat_revision >= 2) { - pxm |= (pa->proximity_domain_hi[0] << 8); - pxm |= (pa->proximity_domain_hi[1] << 16); - pxm |= (pa->proximity_domain_hi[2] << 24); - } + pxm = pa->proximity_domain; node = acpi_map_pxm_to_node(pxm); if (node < 0) { pr_err("SRAT: Too many proximity domains %x\n", pxm); @@ -141,25 +139,25 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) return; } - if (pa->apic_id >= CONFIG_NR_CPUS) { - pr_err("SRAT: PXM %u -> CPU 0x%02x -> Node %u skipped apicid that is too big\n", - pxm, pa->apic_id, node); - return; - } + /** + * In fact, SW64 does not support local X2_APIC and just + * uses this structure to pass CPU affinity information. + */ + rcid = pa->apic_id; /* Record the mapping from logical core id to node id */ - cpu = rcid_to_cpu(pa->apic_id); + cpu = rcid_to_cpu(rcid); if (cpu < 0) { - pr_err("SRAT: Can not find the logical id for physical Core 0x%02x\n", - pa->apic_id); + pr_err("SRAT: Can not find the logical id for physical Core 0x%04x\n", + rcid); return; } early_map_cpu_to_node(cpu, node); node_set(node, numa_nodes_parsed); - pr_info("SRAT: PXM %u -> CPU 0x%02x -> Node %u\n", - pxm, pa->apic_id, node); + pr_debug("SRAT: PXM %u -> CPU 0x%04x -> Node %u\n", + pxm, rcid, node); } #ifdef CONFIG_MEMORY_HOTPLUG diff --git a/include/linux/acpi.h b/include/linux/acpi.h index e254b5b8584a..83bb76c7d5a1 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -267,7 +267,7 @@ static inline bool acpi_gicc_is_usable(struct acpi_madt_generic_interrupt *gicc) /* the following numa functions are architecture-dependent */ void acpi_numa_slit_init (struct acpi_table_slit *slit); -#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_LOONGARCH) || defined(CONFIG_SW64) +#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_LOONGARCH) void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa); #else static inline void -- Gitee From 28b0a823ab2b28b5ee1c081905554edb55092e04 Mon Sep 17 00:00:00 2001 From: Zhi Tongze Date: Tue, 12 Mar 2024 09:52:54 +0800 Subject: [PATCH 51/98] sw64: add unaligned access support for C4 new instructions Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- C4 has introduced some new load/store instructions which may cause unaligned access. This patch adds unaligned exception handler for these instructions. Signed-off-by: Zhi Tongze Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/traps.c | 431 +++++++++++++++++++++++++++++++++++++- 1 file changed, 428 insertions(+), 3 deletions(-) diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index 295e8e3e73a6..1405e42f27b4 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -388,7 +388,8 @@ asmlinkage void do_entUna(void *va, unsigned long opcode, unsigned long reg, struct pt_regs *regs) { - long error; + long error, disp; + unsigned int insn, fncode, rb; unsigned long tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; unsigned long pc = regs->pc - 4; @@ -399,6 +400,188 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, */ switch (opcode) { + case 0x1e: + insn = *(unsigned int *)pc; + fncode = (insn >> 12) & 0xf; + rb = (insn >> 16) & 0x1f; + disp = insn & 0xfff; + + disp = (disp << 52) >> 52; /* sext */ + + switch (fncode) { + case 0x1: /* ldhu_a */ + __asm__ __volatile__( + "1: ldl_u %1, 0(%3)\n" + "2: ldl_u %2, 1(%3)\n" + " extlh %1, %3, %1\n" + " exthh %2, %3, %2\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"(va), "0"(0)); + if (error) + goto got_exception; + regs->regs[reg] = tmp1 | tmp2; + regs->regs[rb] = regs->regs[rb] + disp; + return; + + case 0x2: /* ldw_a */ + __asm__ __volatile__( + "1: ldl_u %1,0(%3)\n" + "2: ldl_u %2,3(%3)\n" + " extlw %1,%3,%1\n" + " exthw %2,%3,%2\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"(va), "0"(0)); + + if (error) + goto got_exception; + regs->regs[reg] = (int)(tmp1 | tmp2); + regs->regs[rb] = regs->regs[rb] + disp; + return; + + case 0x3: /* ldl_a */ + __asm__ __volatile__( + "1: ldl_u %1, 0(%3)\n" + "2: ldl_u %2, 7(%3)\n" + " extll %1, %3, %1\n" + " exthl %2, %3, %2\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"(va), "0"(0)); + + if (error) + goto got_exception; + regs->regs[reg] = tmp1 | tmp2; + regs->regs[rb] = regs->regs[rb] + disp; + return; + + case 0x7: /* sth_a */ + __asm__ __volatile__( + " zap %6, 2, %1\n" + " srl %6, 8, %2\n" + "1: stb %1, 0x0(%5)\n" + "2: stb %2, 0x1(%5)\n" + "3:\n" + ".section __ex_table, \"a\"\n" + " .long 1b - .\n" + " ldi %2, 3b-1b(%0)\n" + " .long 2b - .\n" + " ldi %1, 3b-2b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), + "=&r"(tmp3), "=&r"(tmp4) + : "r"(va), "r"(regs->regs[reg]), "0"(0)); + + if (error) + goto got_exception; + regs->regs[rb] = regs->regs[rb] + disp; + return; + + case 0x8: /* stw_a */ + __asm__ __volatile__( + " zapnot %6, 0x1, %1\n" + " srl %6, 8, %2\n" + " zapnot %2, 0x1,%2\n" + " srl %6, 16, %3\n" + " zapnot %3, 0x1, %3\n" + " srl %6, 24, %4\n" + " zapnot %4, 0x1, %4\n" + "1: stb %1, 0x0(%5)\n" + "2: stb %2, 0x1(%5)\n" + "3: stb %3, 0x2(%5)\n" + "4: stb %4, 0x3(%5)\n" + "5:\n" + ".section __ex_table, \"a\"\n" + " .long 1b - .\n" + " ldi $31, 5b-1b(%0)\n" + " .long 2b - .\n" + " ldi $31, 5b-2b(%0)\n" + " .long 3b - .\n" + " ldi $31, 5b-3b(%0)\n" + " .long 4b - .\n" + " ldi $31, 5b-4b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), + "=&r"(tmp3), "=&r"(tmp4) + : "r"(va), "r"(regs->regs[reg]), "0"(0)); + + if (error) + goto got_exception; + regs->regs[rb] = regs->regs[rb] + disp; + return; + + case 0x9: /* stl_a */ + __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"(regs->regs[reg]), "0"(0)); + + if (error) + goto got_exception; + regs->regs[rb] = regs->regs[rb] + disp; + return; + } case 0x21: __asm__ __volatile__( "1: ldl_u %1, 0(%3)\n" @@ -614,6 +797,11 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, 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) @@ -628,7 +816,9 @@ do_entUnaUser(void __user *va, unsigned long opcode, long error; unsigned long tmp, tmp5, tmp6, tmp7, tmp8, vb; unsigned long fp[4]; - unsigned long instr, instr_op, value; + unsigned long instr, instr_op, value, fncode; + unsigned int rb = -1U; + long disp; #ifdef CONFIG_DEBUG_FS /* @@ -673,7 +863,11 @@ do_entUnaUser(void __user *va, unsigned long opcode, if ((unsigned long)va >= TASK_SIZE) goto give_sigsegv; - if ((1L << opcode) & OP_INT_MASK) { + get_user(instr, (__u32 *)(regs->pc - 4)); + fncode = (instr >> 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]; @@ -1287,6 +1481,237 @@ do_entUnaUser(void __user *va, unsigned long opcode, } } switch (opcode) { + case 0x1e: + rb = (instr >> 16) & 0x1f; + disp = instr & 0xfff; + disp = (disp << 52) >> 52; + + switch (fncode) { + case 0x1: /* ldhu_a */ + __asm__ __volatile__( + "1: ldl_u %1, 0(%3)\n" + "2: ldl_u %2, 1(%3)\n" + " extlh %1, %3, %1\n" + " exthh %2, %3, %2\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"(va), "0"(0)); + if (error) + goto give_sigsegv; + *reg_addr = tmp1 | tmp2; + regs->regs[rb] = regs->regs[rb] + disp; + break; + + case 0x2: /* ldw_a */ + __asm__ __volatile__( + "1: ldl_u %1, 0(%3)\n" + "2: ldl_u %2, 3(%3)\n" + " extlw %1, %3, %1\n" + " exthw %2, %3, %2\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"(va), "0"(0)); + if (error) + goto give_sigsegv; + *reg_addr = (int)(tmp1 | tmp2); + regs->regs[rb] = regs->regs[rb] + disp; + break; + + case 0x3: /* ldl_a */ + __asm__ __volatile__( + "1: ldl_u %1, 0(%3)\n" + "2: ldl_u %2, 7(%3)\n" + " extll %1, %3, %1\n" + " exthl %2, %3, %2\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"(va), "0"(0)); + if (error) + goto give_sigsegv; + *reg_addr = tmp1 | tmp2; + regs->regs[rb] = regs->regs[rb] + disp; + break; + + case 0x4: /* flds_a */ + __asm__ __volatile__( + "1: ldl_u %1, 0(%3)\n" + "2: ldl_u %2, 3(%3)\n" + " extlw %1, %3, %1\n" + " exthw %2, %3, %2\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"(va), "0"(0)); + if (error) + goto give_sigsegv; + sw64_write_fp_reg_s(reg, tmp1 | tmp2); + regs->regs[rb] = regs->regs[rb] + disp; + break; + + case 0x5: /* fldd_a */ + __asm__ __volatile__( + "1: ldl_u %1, 0(%3)\n" + "2: ldl_u %2, 7(%3)\n" + " extll %1, %3, %1\n" + " exthl %2, %3, %2\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"(va), "0"(0)); + if (error) + goto give_sigsegv; + sw64_write_fp_reg(reg, tmp1 | tmp2); + regs->regs[rb] = regs->regs[rb] + disp; + break; + + case 0x7: /* sth_a */ + __asm__ __volatile__( + " zap %6, 2, %1\n" + " srl %6, 8, %2\n" + "1: stb %1, 0x0(%5)\n" + "2: stb %2, 0x1(%5)\n" + "3:\n" + ".section __ex_table, \"a\"\n" + " .long 1b - .\n" + " ldi %2, 3b-1b(%0)\n" + " .long 2b - .\n" + " ldi %1, 3b-2b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), + "=&r"(tmp3), "=&r"(tmp4) + : "r"(va), "r"(*reg_addr), "0"(0)); + + if (error) + goto give_sigsegv; + regs->regs[rb] = regs->regs[rb] + disp; + break; + + case 0xa: /* fsts_a */ + fake_reg = sw64_read_fp_reg_s(reg); + regs->regs[rb] = regs->regs[rb] + disp; + break; + /* fallthrough; */ + case 0x8: /* stw_a */ + __asm__ __volatile__( + " zapnot %6, 0x1, %1\n" + " srl %6, 8, %2\n" + " zapnot %2, 0x1, %2\n" + " srl %6, 16, %3\n" + " zapnot %3, 0x1, %3\n" + " srl %6, 24, %4\n" + " zapnot %4, 0x1, %4\n" + "1: stb %1, 0x0(%5)\n" + "2: stb %2, 0x1(%5)\n" + "3: stb %3, 0x2(%5)\n" + "4: stb %4, 0x3(%5)\n" + "5:\n" + ".section __ex_table, \"a\"\n" + " .long 1b - .\n" + " ldi $31, 5b-1b(%0)\n" + " .long 2b - .\n" + " ldi $31, 5b-2b(%0)\n" + " .long 3b - .\n" + " ldi $31, 5b-3b(%0)\n" + " .long 4b - .\n" + " ldi $31, 5b-4b(%0)\n" + ".previous" + : "=r"(error), "=&r"(tmp1), "=&r"(tmp2), + "=&r"(tmp3), "=&r"(tmp4) + : "r"(va), "r"(*reg_addr), "0"(0)); + + if (error) + goto give_sigsegv; + regs->regs[rb] = regs->regs[rb] + disp; + break; + + case 0xb: /* fstd_a */ + fake_reg = sw64_read_fp_reg(reg); + regs->regs[rb] = regs->regs[rb] + disp; + break; + /* fallthrough; */ + case 0x9: /* stl_a */ + __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"(*reg_addr), "0"(0)); + + if (error) + goto give_sigsegv; + regs->regs[rb] = regs->regs[rb] + disp; + break; + } + break; + case 0x21: /* ldhu */ __asm__ __volatile__( "1: ldl_u %1, 0(%3)\n" -- Gitee From 46ec12ae12434dad8778148751cbae49a2084c6c Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Thu, 14 Mar 2024 17:31:28 +0000 Subject: [PATCH 52/98] sw64: msi: remove redundant interrupt enables Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Each cpu has enabled its msi interrupt in firmware, so remove the enables in kernel. Signed-off-by: Zheng Chongzhen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/irq.c | 7 ------- arch/sw_64/kernel/smp.c | 6 ------ drivers/irqchip/irq-sunway-cpu.c | 12 ------------ 3 files changed, 25 deletions(-) diff --git a/arch/sw_64/kernel/irq.c b/arch/sw_64/kernel/irq.c index 58ee5131e2a9..ac3d089eb656 100644 --- a/arch/sw_64/kernel/irq.c +++ b/arch/sw_64/kernel/irq.c @@ -116,13 +116,6 @@ void __init init_IRQ(void) * Just in case the platform init_irq() causes interrupts/mchecks * (as is the case with RAWHIDE, at least). */ - if (is_in_host()) { - 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); sw64_init_irq(); diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index c198e0510996..82222ed63f0a 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -77,12 +77,6 @@ void smp_callin(void) trap_init(); /* Set interrupt vector. */ - if (is_in_host()) { - 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); /* Get our local ticker going. */ diff --git a/drivers/irqchip/irq-sunway-cpu.c b/drivers/irqchip/irq-sunway-cpu.c index 20cfa4f2b999..3f5151b9b31d 100644 --- a/drivers/irqchip/irq-sunway-cpu.c +++ b/drivers/irqchip/irq-sunway-cpu.c @@ -396,18 +396,6 @@ static __init int cintc_acpi_init(union acpi_subtable_headers *header, msic_parse_madt, 0); #endif - /** - * After initializing MSIC, it's time to enable MSI interrupts - * for boot core. For other SMP cores, if present, this - * initialization is performed during SMP startup. - */ - if (!virtual) { - 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); - } - return 0; } -- Gitee From 1d5a87fa94559a84b1e174446630cd8a59e33975 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Fri, 15 Mar 2024 14:44:35 +0800 Subject: [PATCH 53/98] sw64: dynamically switch between lib implementation Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Use jump_label to dynamically switch between lib with hardware unaligned memory access handling and software unaligned memory access handling. With software unaligned memory access handling, the lib itself will check the alignment of memory address and make sure it's aligned with the memory access operation to improve performance because the software handling is too slow. With hardware unaligned memory access handling, the above check is removed because hardware handling is fast enough. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/hw_init.h | 3 + arch/sw_64/kernel/head.S | 1 + arch/sw_64/kernel/setup.c | 3 + arch/sw_64/lib/Makefile | 12 +-- ...-clear_user.S => deep-clear_user-hw_una.S} | 17 ++-- arch/sw_64/lib/deep-clear_user-sw_una.S | 47 +++++++++++ arch/sw_64/lib/deep-copy_template.S | 14 ++-- arch/sw_64/lib/deep-copy_template_c4.S | 10 +-- arch/sw_64/lib/deep-copy_user-hw_una.S | 40 ++++++++++ ...ep-copy_user.S => deep-copy_user-sw_una.S} | 21 ++--- .../{deep-memcpy.S => deep-memcpy-hw_una.S} | 19 ++--- arch/sw_64/lib/deep-memcpy-sw_una.S | 15 ++++ .../{deep-memset.S => deep-memset-hw_una.S} | 59 ++------------ arch/sw_64/lib/deep-memset-sw_una.S | 54 +++++++++++++ arch/sw_64/lib/deep-set_template.S | 12 +-- arch/sw_64/lib/deep-set_template_c4.S | 10 +-- arch/sw_64/lib/memmove.S | 7 +- arch/sw_64/lib/string.c | 77 +++++++++++++++++++ arch/sw_64/lib/uaccess.c | 29 +++++++ 19 files changed, 330 insertions(+), 120 deletions(-) rename arch/sw_64/lib/{deep-clear_user.S => deep-clear_user-hw_una.S} (78%) create mode 100644 arch/sw_64/lib/deep-clear_user-sw_una.S create mode 100644 arch/sw_64/lib/deep-copy_user-hw_una.S rename arch/sw_64/lib/{deep-copy_user.S => deep-copy_user-sw_una.S} (68%) rename arch/sw_64/lib/{deep-memcpy.S => deep-memcpy-hw_una.S} (40%) create mode 100644 arch/sw_64/lib/deep-memcpy-sw_una.S rename arch/sw_64/lib/{deep-memset.S => deep-memset-hw_una.S} (50%) create mode 100644 arch/sw_64/lib/deep-memset-sw_una.S create mode 100644 arch/sw_64/lib/string.c create mode 100644 arch/sw_64/lib/uaccess.c diff --git a/arch/sw_64/include/asm/hw_init.h b/arch/sw_64/include/asm/hw_init.h index 4710f15a9a56..d1d2c71bc344 100644 --- a/arch/sw_64/include/asm/hw_init.h +++ b/arch/sw_64/include/asm/hw_init.h @@ -3,6 +3,7 @@ #define _ASM_SW64_HW_INIT_H #include #include +#include #include @@ -98,6 +99,8 @@ DECLARE_STATIC_KEY_TRUE(run_mode_host_key); DECLARE_STATIC_KEY_FALSE(run_mode_guest_key); DECLARE_STATIC_KEY_FALSE(run_mode_emul_key); +DECLARE_STATIC_KEY_FALSE(core_hw_una_enabled); + #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) diff --git a/arch/sw_64/kernel/head.S b/arch/sw_64/kernel/head.S index fd0fbfbcf5b6..f3d27ea9e30e 100644 --- a/arch/sw_64/kernel/head.S +++ b/arch/sw_64/kernel/head.S @@ -33,6 +33,7 @@ __start: subl $18, $16, $18 mov $31, $17 call $26, __constant_c_memset + ldgp $29, 0($26) #ifdef CONFIG_RELOCATABLE ldi $30, -8($30) stl $29, 0($30) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 87324cd2268b..4bf49300d09e 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -108,6 +108,9 @@ 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(core_hw_una_enabled); + struct cpu_desc_t cpu_desc; struct socket_desc_t socket_desc[MAX_NUMSOCKETS]; int memmap_nr; diff --git a/arch/sw_64/lib/Makefile b/arch/sw_64/lib/Makefile index e6455bb51139..2028d61dd195 100644 --- a/arch/sw_64/lib/Makefile +++ b/arch/sw_64/lib/Makefile @@ -15,25 +15,27 @@ lib-y = __divlu.o __remlu.o __divwu.o __remwu.o \ strcpy.o \ strncpy.o \ fls.o \ - csum_ipv6_magic.o + csum_ipv6_magic.o \ + string.o \ + uaccess.o lib-clear_page-y := clear_page.o lib-clear_page-$(CONFIG_DEEP_CLEAR_PAGE) := deep-clear_page.o lib-clear_user-y := clear_user.o -lib-clear_user-$(CONFIG_DEEP_CLEAR_USER) := deep-clear_user.o +lib-clear_user-$(CONFIG_DEEP_CLEAR_USER) := deep-clear_user-hw_una.o deep-clear_user-sw_una.o lib-copy_page-y := copy_page.o lib-copy_page-$(CONFIG_DEEP_COPY_PAGE) := deep-copy_page.o lib-copy_user-y := copy_user.o -lib-copy_user-$(CONFIG_DEEP_COPY_USER) := deep-copy_user.o +lib-copy_user-$(CONFIG_DEEP_COPY_USER) := deep-copy_user-hw_una.o deep-copy_user-sw_una.o lib-memcpy-y := memcpy.o -lib-memcpy-$(CONFIG_DEEP_MEMCPY) := deep-memcpy.o +lib-memcpy-$(CONFIG_DEEP_MEMCPY) := deep-memcpy-hw_una.o deep-memcpy-sw_una.o lib-memset-y := memset.o -lib-memset-$(CONFIG_DEEP_MEMSET) := deep-memset.o +lib-memset-$(CONFIG_DEEP_MEMSET) := deep-memset-hw_una.o deep-memset-sw_una.o lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o diff --git a/arch/sw_64/lib/deep-clear_user.S b/arch/sw_64/lib/deep-clear_user-hw_una.S similarity index 78% rename from arch/sw_64/lib/deep-clear_user.S rename to arch/sw_64/lib/deep-clear_user-hw_una.S index c81418ed99a2..81c04dd0f056 100644 --- a/arch/sw_64/lib/deep-clear_user.S +++ b/arch/sw_64/lib/deep-clear_user-hw_una.S @@ -16,7 +16,7 @@ 99: x,##y; \ .section __ex_table,"a"; \ .long 99b - .; \ - ldi $31, $out-99b($31); \ + ldi $31, 255f-99b($31); \ .previous /* @@ -27,19 +27,15 @@ * $18: bytes left to copy * */ - .globl __clear_user - .ent __clear_user -__clear_user: + .globl ____clear_user_hw_una + .ent ____clear_user_hw_una +____clear_user_hw_una: .prologue 0 bis $31, $31, $7 mov $17, $18 bis $31, $31, $17 -#if defined(CONFIG_SUBARCH_C3B) -#include "deep-set_template.S" -#elif defined(CONFIG_SUBARCH_C4) #include "deep-set_template_c4.S" -#endif -$out: +255: bis $31, $18, $0 beq $7, $return @@ -48,5 +44,4 @@ $restore_simd: $return: ret - .end __clear_user - EXPORT_SYMBOL(__clear_user) + .end ____clear_user_hw_una diff --git a/arch/sw_64/lib/deep-clear_user-sw_una.S b/arch/sw_64/lib/deep-clear_user-sw_una.S new file mode 100644 index 000000000000..e48e5be9efac --- /dev/null +++ b/arch/sw_64/lib/deep-clear_user-sw_una.S @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Contributed by Mao Minkai + * + * Zero user space, handling exceptions as we go. + * + * We have to make sure that $0 is always up-to-date and contains the + * right "bytes left to zero" value (and that it is updated only _after_ + * a successful copy). There is also some rather minor exception setup + * stuff. + * + */ +#include +/* Allow an exception for an insn; exit if we get one. */ +#define FIXUP_LDST(x,y...) \ + 99: x,##y; \ + .section __ex_table,"a"; \ + .long 99b - .; \ + ldi $31, 255f-99b($31); \ + .previous + +/* + * $7: SIMD status + * 0: not in simd loop + * 1: in simd loop + * 2: in simd_u loop + * $18: bytes left to copy + * + */ + .globl ____clear_user_sw_una + .ent ____clear_user_sw_una +____clear_user_sw_una: + .prologue 0 + bis $31, $31, $7 + mov $17, $18 + bis $31, $31, $17 +#include "deep-set_template.S" +255: + bis $31, $18, $0 + beq $7, $return + +$restore_simd: + RESTORE_SIMD_REGS + +$return: + ret + .end ____clear_user_sw_una diff --git a/arch/sw_64/lib/deep-copy_template.S b/arch/sw_64/lib/deep-copy_template.S index 7705eb3f36d4..fbb5912e1213 100644 --- a/arch/sw_64/lib/deep-copy_template.S +++ b/arch/sw_64/lib/deep-copy_template.S @@ -55,7 +55,7 @@ ldi $sp, 0xc0($sp); \ bis $31, $31, $7 - ble $18, $out + ble $18, 255f and $16, 7, $1 beq $1, $dest_aligned_8 @@ -65,7 +65,7 @@ $byte_loop_head: subl $18, 1, $18 addl $17, 1, $17 addl $16, 1, $16 - ble $18, $out + ble $18, 255f and $16, 7, $1 bne $1, $byte_loop_head @@ -140,7 +140,7 @@ $no_more_simd: RESTORE_SIMD_REGS $simd_end: - ble $18, $out + ble $18, 255f cmplt $18, 16, $1 bne $1, $quad_loop_end bne $4, $prep_quad_u_loop_tail @@ -158,7 +158,7 @@ $quad_loop_tail: beq $1, $quad_loop_tail $quad_loop_end: - ble $18, $out + ble $18, 255f cmplt $18, 8, $1 bne $1, $byte_loop_tail bne $4, $move_one_quad_u @@ -169,7 +169,7 @@ $move_one_quad: subl $18, 8, $18 addl $17, 8, $17 addl $16, 8, $16 - ble $18, $out + ble $18, 255f .align 3 $byte_loop_tail: @@ -179,7 +179,7 @@ $byte_loop_tail: addl $17, 1, $17 addl $16, 1, $16 bgt $18, $byte_loop_tail - br $31, $out + br $31, 255f /* misaligned src and dst */ $quad_u_loop_head: @@ -297,5 +297,5 @@ $move_one_quad_u: subl $18, 8, $18 addl $17, 8, $17 addl $16, 8, $16 - ble $18, $out + ble $18, 255f br $31, $byte_loop_tail diff --git a/arch/sw_64/lib/deep-copy_template_c4.S b/arch/sw_64/lib/deep-copy_template_c4.S index e0740874dfa3..b89ea4a75db3 100644 --- a/arch/sw_64/lib/deep-copy_template_c4.S +++ b/arch/sw_64/lib/deep-copy_template_c4.S @@ -29,7 +29,7 @@ bis $31, $31, $7 - ble $18, $out + ble $18, 255f cmplt $18, 8, $1 bne $1, $byte_loop_tail @@ -68,7 +68,7 @@ $no_more_simd: RESTORE_SIMD_REGS $simd_end: - ble $18, $out + ble $18, 255f cmplt $18, 16, $1 bne $1, $quad_loop_end @@ -85,7 +85,7 @@ $quad_loop_tail: beq $1, $quad_loop_tail $quad_loop_end: - ble $18, $out + ble $18, 255f cmplt $18, 8, $1 bne $1, $byte_loop_tail @@ -95,7 +95,7 @@ $move_one_quad: subl $18, 8, $18 addl $17, 8, $17 addl $16, 8, $16 - ble $18, $out + ble $18, 255f .align 3 $byte_loop_tail: @@ -105,4 +105,4 @@ $byte_loop_tail: addl $17, 1, $17 addl $16, 1, $16 bgt $18, $byte_loop_tail - br $31, $out + br $31, 255f diff --git a/arch/sw_64/lib/deep-copy_user-hw_una.S b/arch/sw_64/lib/deep-copy_user-hw_una.S new file mode 100644 index 000000000000..b411a7ed52c2 --- /dev/null +++ b/arch/sw_64/lib/deep-copy_user-hw_una.S @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* Allow an exception for an insn; exit if we get one. */ +#define FIXUP_LDST(x, y) \ + 99: x, y; \ + .section __ex_table, "a"; \ + .long 99b - .; \ + ldi $31, 255f-99b($31); \ + .previous + +/* + * $7: SIMD status for C3B + * 0: not in simd loop + * 1: in simd loop + * 2: in simd_u loop + * $7: SIMD status for C4 + * 0: not in simd loop + * 1: in simd and simd_u loop + * $18: bytes left to copy + * + */ + .globl ____copy_user_hw_una + .ent ____copy_user_hw_una +____copy_user_hw_una: + .prologue 0 + .set noreorder + bis $31, $31, $7 +#include "deep-copy_template_c4.S" +255: + bis $31, $18, $0 + beq $7, $return + subl $7, 1, $7 + beq $7, $restore_simd + +$restore_simd: + RESTORE_SIMD_REGS + +$return: + ret + .end ____copy_user_hw_una diff --git a/arch/sw_64/lib/deep-copy_user.S b/arch/sw_64/lib/deep-copy_user-sw_una.S similarity index 68% rename from arch/sw_64/lib/deep-copy_user.S rename to arch/sw_64/lib/deep-copy_user-sw_una.S index b79f8f3f0f4a..a359aee65583 100644 --- a/arch/sw_64/lib/deep-copy_user.S +++ b/arch/sw_64/lib/deep-copy_user-sw_una.S @@ -1,13 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#include - /* Allow an exception for an insn; exit if we get one. */ #define FIXUP_LDST(x, y) \ 99: x, y; \ .section __ex_table, "a"; \ .long 99b - .; \ - ldi $31, $out-99b($31); \ + ldi $31, 255f-99b($31); \ .previous /* @@ -21,33 +19,26 @@ * $18: bytes left to copy * */ - .globl __copy_user - .ent __copy_user -__copy_user: + .globl ____copy_user_sw_una + .ent ____copy_user_sw_una +____copy_user_sw_una: .prologue 0 .set noreorder bis $31, $31, $7 -#if defined(CONFIG_SUBARCH_C3B) #include "deep-copy_template.S" -#elif defined(CONFIG_SUBARCH_C4) -#include "deep-copy_template_c4.S" -#endif -$out: +255: bis $31, $18, $0 beq $7, $return subl $7, 1, $7 beq $7, $restore_simd -#if defined(CONFIG_SUBARCH_C3B) $restore_simd_u: RESTORE_SIMD_U_REGS br $31, $return -#endif $restore_simd: RESTORE_SIMD_REGS $return: ret - .end __copy_user - EXPORT_SYMBOL(__copy_user) + .end ____copy_user_sw_una diff --git a/arch/sw_64/lib/deep-memcpy.S b/arch/sw_64/lib/deep-memcpy-hw_una.S similarity index 40% rename from arch/sw_64/lib/deep-memcpy.S rename to arch/sw_64/lib/deep-memcpy-hw_una.S index 78a6bd85cf01..ccdfaed4b8ab 100644 --- a/arch/sw_64/lib/deep-memcpy.S +++ b/arch/sw_64/lib/deep-memcpy-hw_una.S @@ -1,24 +1,15 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#include - #define FIXUP_LDST(x, y) \ x, y - .globl memcpy - .ent memcpy -memcpy: + .globl ____memcpy_hw_una + .ent ____memcpy_hw_una +____memcpy_hw_una: .frame $30, 0, $26, 0 .prologue 0 mov $16, $0 -#if defined(CONFIG_SUBARCH_C3B) -#include "deep-copy_template.S" -#elif defined(CONFIG_SUBARCH_C4) #include "deep-copy_template_c4.S" -#endif -$out: +255: ret - .end memcpy - EXPORT_SYMBOL(memcpy) -__memcpy = memcpy -.globl __memcpy + .end ____memcpy_hw_una diff --git a/arch/sw_64/lib/deep-memcpy-sw_una.S b/arch/sw_64/lib/deep-memcpy-sw_una.S new file mode 100644 index 000000000000..75aa10a42b52 --- /dev/null +++ b/arch/sw_64/lib/deep-memcpy-sw_una.S @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#define FIXUP_LDST(x, y) \ + x, y + + .globl ____memcpy_sw_una + .ent ____memcpy_sw_una +____memcpy_sw_una: + .frame $30, 0, $26, 0 + .prologue 0 + mov $16, $0 +#include "deep-copy_template.S" +255: + ret + .end ____memcpy_sw_una diff --git a/arch/sw_64/lib/deep-memset.S b/arch/sw_64/lib/deep-memset-hw_una.S similarity index 50% rename from arch/sw_64/lib/deep-memset.S rename to arch/sw_64/lib/deep-memset-hw_una.S index c6b5355beec6..dff6b2c2003c 100644 --- a/arch/sw_64/lib/deep-memset.S +++ b/arch/sw_64/lib/deep-memset-hw_una.S @@ -25,7 +25,6 @@ * */ -#include #include #define FIXUP_LDST(x, y) \ @@ -35,63 +34,21 @@ .set noreorder .text .align 4 - .globl memset - .globl __memset - .globl ___memset - .globl __memsetw - .globl __constant_c_memset - .ent ___memset -___memset: + + .globl ____constant_c_memset_hw_una + .ent ____constant_c_memset_hw_una .frame $30, 0, $26, 0 .prologue 0 - +____constant_c_memset_hw_una: + bis $31, $31, $7 + bis $31, $16, $0 #ifdef CONFIG_SUBARCH_C4 csrr $6, CSR_WR_FREGS #endif -/* expand 1 byte data to 8 bytes */ - and $17, 0xff, $17 - sll $17, 8, $4 - bis $17, $4, $17 - sll $17, 16, $4 - bis $17, $4, $17 - sll $17, 32, $4 - bis $17, $4, $17 - -__constant_c_memset: - bis $31, $31, $7 - bis $31, $16, $0 -#if defined(CONFIG_SUBARCH_C3B) -#include "deep-set_template.S" -#elif defined(CONFIG_SUBARCH_C4) #include "deep-set_template_c4.S" -#endif -$out: +255: #ifdef CONFIG_SUBARCH_C4 csrw $6, CSR_WR_FREGS #endif ret - - .end ___memset - EXPORT_SYMBOL(___memset) - - .align 5 - .ent __memsetw -__memsetw: - .prologue 0 - - inslh $17, 0, $1 - inslh $17, 2, $2 - inslh $17, 4, $3 - bis $1, $2, $1 - inslh $17, 6, $4 - bis $1, $3, $1 - bis $1, $4, $17 - br $31, __constant_c_memset - - .end __memsetw - EXPORT_SYMBOL(__memsetw) - -memset = ___memset -EXPORT_SYMBOL(memset) -__memset = ___memset -EXPORT_SYMBOL(__memset) + .end ____constant_c_memset_hw_una diff --git a/arch/sw_64/lib/deep-memset-sw_una.S b/arch/sw_64/lib/deep-memset-sw_una.S new file mode 100644 index 000000000000..b354b36dbbc9 --- /dev/null +++ b/arch/sw_64/lib/deep-memset-sw_una.S @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Optimized memset() for SW64 with SIMD instructions + * + * Copyright (C) Mao Minkai + * Author: Mao Minkai + * + * Fill SIZE bytes pointed to by SRC with CHAR. + * + * Input: + * $16: SRC, clobbered + * $17: CHAR, clobbered + * $18: SIZE, clobbered + * + * Output: + * $0: SRC + * + * Temporaries: + * $1: unaligned parts of addr (0 means aligned addr), tmp data + * $2: tmp data + * $3: tmp data + * $4: tmp data + * $5: compare result + * $f10: 32 bytes data (manually saved) + * + */ + +#include + +#define FIXUP_LDST(x, y) \ + x, y + + .set noat + .set noreorder + .text + .align 4 + + .globl ____constant_c_memset_sw_una + .ent ____constant_c_memset_sw_una + .frame $30, 0, $26, 0 + .prologue 0 +____constant_c_memset_sw_una: + bis $31, $31, $7 + bis $31, $16, $0 +#ifdef CONFIG_SUBARCH_C4 + csrr $6, CSR_WR_FREGS +#endif +#include "deep-set_template.S" +255: +#ifdef CONFIG_SUBARCH_C4 + csrw $6, CSR_WR_FREGS +#endif + ret + .end ____constant_c_memset_sw_una diff --git a/arch/sw_64/lib/deep-set_template.S b/arch/sw_64/lib/deep-set_template.S index f9073d638468..d581e2eb35d7 100644 --- a/arch/sw_64/lib/deep-set_template.S +++ b/arch/sw_64/lib/deep-set_template.S @@ -27,7 +27,7 @@ ldi $sp, 0x40($sp); \ bis $31, $31, $7 - ble $18, $out + ble $18, 255f and $16, 7, $1 beq $1, $dest_aligned_8 @@ -36,7 +36,7 @@ $byte_loop_head: FIXUP_LDST( stb $17, 0($16) ) subl $18, 1, $18 addl $16, 1, $16 - ble $18, $out + ble $18, 255f and $16, 7, $1 bne $1, $byte_loop_head @@ -100,7 +100,7 @@ $no_more_simd: RESTORE_SIMD_REGS $simd_end: - ble $18, $out + ble $18, 255f cmplt $18, 16, $1 bne $1, $quad_loop_end @@ -114,7 +114,7 @@ $quad_loop_tail: beq $1, $quad_loop_tail $quad_loop_end: - ble $18, $out + ble $18, 255f cmplt $18, 8, $1 bne $1, $byte_loop_tail @@ -122,7 +122,7 @@ $move_one_quad: FIXUP_LDST( stl $17, 0($16) ) subl $18, 8, $18 addl $16, 8, $16 - ble $18, $out + ble $18, 255f .align 3 $byte_loop_tail: @@ -130,4 +130,4 @@ $byte_loop_tail: subl $18, 1, $18 addl $16, 1, $16 bgt $18, $byte_loop_tail - br $31, $out + br $31, 255f diff --git a/arch/sw_64/lib/deep-set_template_c4.S b/arch/sw_64/lib/deep-set_template_c4.S index 2b1bcab8fec9..8a59d2733318 100644 --- a/arch/sw_64/lib/deep-set_template_c4.S +++ b/arch/sw_64/lib/deep-set_template_c4.S @@ -24,7 +24,7 @@ ldi $sp, 0x40($sp); \ bis $31, $31, $7 - ble $18, $out + ble $18, 255f cmplt $18, 8, $1 bne $1, $byte_loop_tail @@ -60,7 +60,7 @@ $no_more_simd: RESTORE_SIMD_REGS $simd_end: - ble $18, $out + ble $18, 255f cmplt $18, 16, $1 bne $1, $quad_loop_end @@ -74,7 +74,7 @@ $quad_loop_tail: beq $1, $quad_loop_tail $quad_loop_end: - ble $18, $out + ble $18, 255f cmplt $18, 8, $1 bne $1, $byte_loop_tail @@ -82,7 +82,7 @@ $move_one_quad: FIXUP_LDST( stl $17, 0($16) ) subl $18, 8, $18 addl $16, 8, $16 - ble $18, $out + ble $18, 255f .align 3 $byte_loop_tail: @@ -90,4 +90,4 @@ $byte_loop_tail: subl $18, 1, $18 addl $16, 1, $16 bgt $18, $byte_loop_tail - br $31, $out + br $31, 255f diff --git a/arch/sw_64/lib/memmove.S b/arch/sw_64/lib/memmove.S index 3e34fcd5b217..02c44d21bdb6 100644 --- a/arch/sw_64/lib/memmove.S +++ b/arch/sw_64/lib/memmove.S @@ -25,8 +25,13 @@ memmove: bis $1, $2, $1 mov $16, $0 xor $16, $17, $2 - bne $1, memcpy # samegp + beq $1, $memmove_cont + ldi $27, memcpy + jmp $31, ($27) + /* should never reach here + * memcpy should return to caller directly */ +$memmove_cont: and $2, 7, $2 # Test for src/dest co-alignment. and $16, 7, $1 cmpule $16, $17, $3 diff --git a/arch/sw_64/lib/string.c b/arch/sw_64/lib/string.c new file mode 100644 index 000000000000..4d10e0639bb8 --- /dev/null +++ b/arch/sw_64/lib/string.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +#include + +extern void *____memcpy_hw_una(void *dest, const void *src, size_t n); +extern void *____memcpy_sw_una(void *dest, const void *src, size_t n); + +static inline void *____memcpy(void *dest, const void *src, size_t n) +{ + if (static_branch_likely(&core_hw_una_enabled)) + return ____memcpy_hw_una(dest, src, n); + else + return ____memcpy_sw_una(dest, src, n); +} + +void *memcpy(void *dest, const void *src, size_t n) +{ + return ____memcpy(dest, src, n); +} +EXPORT_SYMBOL(memcpy); + +/* For backward compatibility with modules. Unused otherwise. */ +void *__memcpy(void *dest, const void *src, size_t n) +{ + return ____memcpy(dest, src, n); +} +EXPORT_SYMBOL(__memcpy); + +extern void *____constant_c_memset_hw_una(void *s, unsigned long c, size_t n); +extern void *____constant_c_memset_sw_una(void *s, unsigned long c, size_t n); + +static inline void *____constant_c_memset(void *s, unsigned long c, size_t n) +{ + if (static_branch_likely(&core_hw_una_enabled)) + return ____constant_c_memset_hw_una(s, c, n); + else + return ____constant_c_memset_sw_una(s, c, n); +} + +void *__constant_c_memset(void *s, unsigned long c, size_t n) +{ + return ____constant_c_memset(s, c, n); +} + +void *___memset(void *s, int c, size_t n) +{ + unsigned long c_ul = (c & 0xff) * 0x0101010101010101UL; + + return ____constant_c_memset(s, c_ul, n); +} +EXPORT_SYMBOL(___memset); + +void *__memset(void *s, int c, size_t n) +{ + unsigned long c_ul = (c & 0xff) * 0x0101010101010101UL; + + return ____constant_c_memset(s, c_ul, n); +} +EXPORT_SYMBOL(__memset); + +void *memset(void *s, int c, size_t n) +{ + unsigned long c_ul = (c & 0xff) * 0x0101010101010101UL; + + return ____constant_c_memset(s, c_ul, n); +} +EXPORT_SYMBOL(memset); + +void *__memsetw(void *dest, unsigned short c, size_t count) +{ + unsigned long c_ul = (c & 0xffff) * 0x0001000100010001UL; + + return ____constant_c_memset(dest, c_ul, count); +} +EXPORT_SYMBOL(__memsetw); diff --git a/arch/sw_64/lib/uaccess.c b/arch/sw_64/lib/uaccess.c new file mode 100644 index 000000000000..56d3075aedbb --- /dev/null +++ b/arch/sw_64/lib/uaccess.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +#include + +extern long ____copy_user_hw_una(void *to, const void *from, long len); +extern long ____copy_user_sw_una(void *to, const void *from, long len); + +long __copy_user(void *to, const void *from, long len) +{ + if (static_branch_likely(&core_hw_una_enabled)) + return ____copy_user_hw_una(to, from, len); + else + return ____copy_user_sw_una(to, from, len); +} +EXPORT_SYMBOL(__copy_user); + +extern long ____clear_user_hw_una(void __user *to, long len); +extern long ____clear_user_sw_una(void __user *to, long len); + +long __clear_user(void __user *to, long len) +{ + if (static_branch_likely(&core_hw_una_enabled)) + return ____clear_user_hw_una(to, len); + else + return ____clear_user_sw_una(to, len); +} +EXPORT_SYMBOL(__clear_user); -- Gitee From 412d89c6f62b07b711d8ec458d22d402dbf4d420 Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Tue, 19 Mar 2024 15:53:07 +0000 Subject: [PATCH 54/98] sw64: irq: update the initial value of nr_irqs Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- nr_irqs is initialized to NR_IRQS, making the /proc/stat file too large. So let arch update it's initial value to NR_IRQS_LEGACY, and then it grows with interrupt request. Along with that we redefine ACTUAL_NR_IRQS to nr_irqs for semantic correctness. Signed-off-by: Zheng Chongzhen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/hw_irq.h | 2 +- arch/sw_64/kernel/irq.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/include/asm/hw_irq.h b/arch/sw_64/include/asm/hw_irq.h index e0f8ee91c43a..59418a5fb1d3 100644 --- a/arch/sw_64/include/asm/hw_irq.h +++ b/arch/sw_64/include/asm/hw_irq.h @@ -7,7 +7,7 @@ extern volatile unsigned long irq_err_count; DECLARE_PER_CPU(unsigned long, irq_pmi_count); -#define ACTUAL_NR_IRQS NR_IRQS +#define ACTUAL_NR_IRQS nr_irqs extern struct irq_domain *mcu_irq_domain; diff --git a/arch/sw_64/kernel/irq.c b/arch/sw_64/kernel/irq.c index ac3d089eb656..bdc92b40c4c0 100644 --- a/arch/sw_64/kernel/irq.c +++ b/arch/sw_64/kernel/irq.c @@ -133,6 +133,7 @@ int __init arch_early_irq_init(void) int __init arch_probe_nr_irqs(void) { + nr_irqs = NR_IRQS_LEGACY; return NR_IRQS_LEGACY; } -- Gitee From e2b5968796450ce2995a8280adf87197c62b0a8f Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Tue, 19 Mar 2024 10:01:15 +0800 Subject: [PATCH 55/98] sw64: introduce new entry framework for C4 Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- The pt_regs used to be partly handled by firmware, which limits the extension of os because of compatibility. This patch introduces new entry framework for Core4. Firmware is responsible for preparing the necessary parameters when exception or interrupt occurs and saving them to the specified CSRs. struct pt_regs is accessed by the kernel only and ksp is saved to struct pcb_struct instead of struct vcpucb. For guest os, since SAVE_ALL may be interrupted by host IRQ, we have to reserve enough space in vcpucb to save these CSRs. Due to a flaw of hardware, when there are consecutive write and read on a CSR in a recent period, the read may be issued before write in some cases, leading to a wrong result. It has to read the CSR twice to avoid this bug. Signed-off-by: Wu Liliu Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/csr.h | 9 + arch/sw_64/include/asm/hmcall.h | 2 - arch/sw_64/include/asm/kvm.h | 142 ++++++++++ arch/sw_64/include/asm/ptrace.h | 6 +- arch/sw_64/include/asm/thread_info.h | 1 + arch/sw_64/include/asm/vcpu.h | 13 +- arch/sw_64/include/uapi/asm/kvm.h | 87 ------ arch/sw_64/kernel/Makefile | 6 +- arch/sw_64/kernel/asm-offsets.c | 18 +- arch/sw_64/kernel/early_init.c | 1 - arch/sw_64/kernel/{entry.S => entry_c3.S} | 15 +- arch/sw_64/kernel/entry_c4.S | 330 ++++++++++++++++++++++ arch/sw_64/kernel/head.S | 12 +- arch/sw_64/kernel/hibernate_asm.S | 10 +- arch/sw_64/kernel/smp.c | 4 - arch/sw_64/kvm/Makefile | 14 +- arch/sw_64/kvm/{entry.S => entry_core3.S} | 0 arch/sw_64/kvm/entry_core4.S | 275 ++++++++++++++++++ 18 files changed, 817 insertions(+), 128 deletions(-) create mode 100644 arch/sw_64/include/asm/kvm.h rename arch/sw_64/kernel/{entry.S => entry_c3.S} (96%) create mode 100644 arch/sw_64/kernel/entry_c4.S rename arch/sw_64/kvm/{entry.S => entry_core3.S} (100%) create mode 100644 arch/sw_64/kvm/entry_core4.S diff --git a/arch/sw_64/include/asm/csr.h b/arch/sw_64/include/asm/csr.h index dc400069a771..8f4f3d142db4 100644 --- a/arch/sw_64/include/asm/csr.h +++ b/arch/sw_64/include/asm/csr.h @@ -46,6 +46,15 @@ #define CSR_DV_MASK 0x57 #define CSR_IDA_MATCH 0xc5 #define CSR_IDA_MASK 0xc6 +#define CSR_BASE_KREGS 0xe0 +#define CSR_PS 0xe8 +#define CSR_PC 0xe9 +#define CSR_EARG0 0xea +#define CSR_EARG1 0xeb +#define CSR_EARG2 0xec +#define CSR_SCRATCH 0xed +#define CSR_SP 0xee +#define CSR_KTP 0xef #define DA_MATCH_EN_S 4 #define DV_MATCH_EN_S 6 diff --git a/arch/sw_64/include/asm/hmcall.h b/arch/sw_64/include/asm/hmcall.h index 41c656470ca4..71328c4eb332 100644 --- a/arch/sw_64/include/asm/hmcall.h +++ b/arch/sw_64/include/asm/hmcall.h @@ -155,9 +155,7 @@ __CALL_HMC_VOID(sleepen); __CALL_HMC_VOID(mtinten); __CALL_HMC_VOID(rdktp); -#define restore_ktp() rdktp() __CALL_HMC_VOID(wrktp); -#define save_ktp() wrktp() __CALL_HMC_R0(rdps, unsigned long); __CALL_HMC_R0(rvpcr, unsigned long); diff --git a/arch/sw_64/include/asm/kvm.h b/arch/sw_64/include/asm/kvm.h new file mode 100644 index 000000000000..f6e3022efcfe --- /dev/null +++ b/arch/sw_64/include/asm/kvm.h @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_SW64_KVM_H +#define _ASM_SW64_KVM_H +#include + +/* + * KVM SW specific structures and definitions. + */ +#define SWVM_IRQS 256 +#define IRQ_PENDING_INTX_SHIFT 16 +#define IRQ_PENDING_MSI_VECTORS_SHIFT 17 + +#define SWVM_NUM_NUMA_MEMBANKS 1 + +/* + * for KVM_GET_REGS and KVM_SET_REGS + */ +#ifdef CONFIG_SUBARCH_C3B +struct kvm_regs { + unsigned long r0; + unsigned long r1; + unsigned long r2; + unsigned long r3; + + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; + + unsigned long r19; + unsigned long r20; + unsigned long r21; + unsigned long r22; + + unsigned long r23; + unsigned long r24; + unsigned long r25; + unsigned long r26; + + unsigned long r27; + unsigned long r28; + unsigned long __padding0; + unsigned long fpcr; + + unsigned long fp[124]; + /* These are saved by HMcode: */ + unsigned long ps; + unsigned long pc; + unsigned long gp; + unsigned long r16; + unsigned long r17; + unsigned long r18; +}; + +#elif CONFIG_SUBARCH_C4 +struct kvm_regs { + unsigned long r0; + unsigned long r1; + unsigned long r2; + unsigned long r3; + + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; + + unsigned long r16; + unsigned long r17; + unsigned long r18; + unsigned long r19; + + unsigned long r20; + unsigned long r21; + unsigned long r22; + unsigned long r23; + + unsigned long r24; + unsigned long r25; + unsigned long r26; + unsigned long r27; + + unsigned long r28; + unsigned long gp; + unsigned long sp; + unsigned long fpcr; + + unsigned long fp[124]; + unsigned long ps; + unsigned long pc; +}; +#endif + +/* + * return stack for __sw64_vcpu_run + */ +struct vcpu_run_ret_stack { + unsigned long ra; + unsigned long r0; +}; + +struct host_int_args { + unsigned long r18; + unsigned long r17; + unsigned long r16; +}; + +struct hcall_args { + unsigned long arg0, arg1, arg2; +}; + +struct swvm_mem_bank { + unsigned long guest_phys_addr; + unsigned long host_phys_addr; + unsigned long host_addr; + unsigned long size; +}; + +struct swvm_mem { + struct swvm_mem_bank membank[SWVM_NUM_NUMA_MEMBANKS]; +}; + +#endif /* _ASM_SW64_KVM_H */ diff --git a/arch/sw_64/include/asm/ptrace.h b/arch/sw_64/include/asm/ptrace.h index 964f4fc730f2..aa8b269a7ef4 100644 --- a/arch/sw_64/include/asm/ptrace.h +++ b/arch/sw_64/include/asm/ptrace.h @@ -31,9 +31,9 @@ struct pt_regs { unsigned long hm_ps; unsigned long hm_pc; unsigned long hm_gp; - unsigned long hm_r16; - unsigned long hm_r17; - unsigned long hm_r18; + unsigned long earg0; + unsigned long earg1; + unsigned long earg2; }; #define arch_has_single_step() (1) diff --git a/arch/sw_64/include/asm/thread_info.h b/arch/sw_64/include/asm/thread_info.h index 4f3b837e2e90..17a93bd8baa4 100644 --- a/arch/sw_64/include/asm/thread_info.h +++ b/arch/sw_64/include/asm/thread_info.h @@ -14,6 +14,7 @@ typedef struct { struct pcb_struct { + unsigned long ksp; unsigned long tp; unsigned long da_match, da_mask; unsigned long dv_match, dv_mask; diff --git a/arch/sw_64/include/asm/vcpu.h b/arch/sw_64/include/asm/vcpu.h index c4e3caacbc70..a68e8ff56af5 100644 --- a/arch/sw_64/include/asm/vcpu.h +++ b/arch/sw_64/include/asm/vcpu.h @@ -55,7 +55,7 @@ struct vcpucb { unsigned long reserved[3]; }; -#else +#elif CONFIG_SUBARCH_C4 struct vcpucb { unsigned long ktp; @@ -98,7 +98,16 @@ struct vcpucb { unsigned long ipaddr; unsigned long vcpu_pc_save; unsigned long shtclock_offset; - unsigned long reserved[8]; + unsigned long migration_mark; + unsigned long shtclock; + unsigned long csr_pc; + unsigned long csr_ps; + unsigned long csr_sp; + unsigned long csr_ktp; + unsigned long csr_earg0; + unsigned long csr_earg1; + unsigned long csr_earg2; + unsigned long csr_scratch; }; #endif diff --git a/arch/sw_64/include/uapi/asm/kvm.h b/arch/sw_64/include/uapi/asm/kvm.h index 2253475deaa5..2ae0cc74bb2b 100644 --- a/arch/sw_64/include/uapi/asm/kvm.h +++ b/arch/sw_64/include/uapi/asm/kvm.h @@ -16,75 +16,9 @@ enum SW64_KVM_IRQ { SW64_KVM_IRQ_MOUSE = 30, }; -#define SWVM_VM_TYPE_DEFAULT 0 -#define SWVM_VM_TYPE_PHYVCPU 1 #define __KVM_HAVE_IRQ_LINE -#define SWVM_NUM_NUMA_MEMBANKS 1 #define KVM_NR_IRQCHIPS 1 -/* - * for KVM_GET_REGS and KVM_SET_REGS - */ -struct kvm_regs { - unsigned long r0; - unsigned long r1; - unsigned long r2; - unsigned long r3; - - unsigned long r4; - unsigned long r5; - unsigned long r6; - unsigned long r7; - - unsigned long r8; - unsigned long r9; - unsigned long r10; - unsigned long r11; - - unsigned long r12; - unsigned long r13; - unsigned long r14; - unsigned long r15; - - unsigned long r19; - unsigned long r20; - unsigned long r21; - unsigned long r22; - - unsigned long r23; - unsigned long r24; - unsigned long r25; - unsigned long r26; - - unsigned long r27; - unsigned long r28; - unsigned long __padding0; - unsigned long fpcr; - - unsigned long fp[124]; - /* These are saved by HMcode: */ - unsigned long ps; - unsigned long pc; - unsigned long gp; - unsigned long r16; - unsigned long r17; - unsigned long r18; -}; - - -/* - * return stack for __sw64_vcpu_run - */ -struct vcpu_run_ret_stack { - unsigned long ra; - unsigned long r0; -}; - -struct host_int_args { - unsigned long r18; - unsigned long r17; - unsigned long r16; -}; /* * for KVM_GET_FPU and KVM_SET_FPU @@ -92,15 +26,6 @@ struct host_int_args { struct kvm_fpu { }; -struct hcall_args { - unsigned long arg0, arg1, arg2; -}; - -struct phyvcpu_hcall_args { - unsigned long call; - struct hcall_args args; -}; - struct kvm_debug_exit_arch { unsigned long epc; }; @@ -116,16 +41,4 @@ struct kvm_sync_regs { /* dummy definition */ struct kvm_sregs { }; - -struct swvm_mem_bank { - unsigned long guest_phys_addr; - unsigned long host_phys_addr; - unsigned long host_addr; - unsigned long size; -}; - -struct swvm_mem { - struct swvm_mem_bank membank[SWVM_NUM_NUMA_MEMBANKS]; -}; - #endif /* _UAPI_ASM_SW64_KVM_H */ diff --git a/arch/sw_64/kernel/Makefile b/arch/sw_64/kernel/Makefile index 5ac06882ebc0..57124b8546ec 100644 --- a/arch/sw_64/kernel/Makefile +++ b/arch/sw_64/kernel/Makefile @@ -13,14 +13,16 @@ CFLAGS_REMOVE_insn.o = -pg CFLAGS_REMOVE_printk.o = -pg endif -obj-y := entry.o fpu.o traps.o process.o sys_sw64.o irq.o \ +obj-y := fpu.o traps.o process.o sys_sw64.o irq.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 \ vdso.o vdso/ hmcall.o stacktrace.o idle.o reset.o \ head.o termios.o -obj-$(CONFIG_SUBARCH_C3B) += tc.o +obj-$(CONFIG_SUBARCH_C3B) += entry_c3.o tc.o +obj-$(CONFIG_SUBARCH_C4) += entry_c4.o + obj-$(CONFIG_ACPI) += acpi.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/sw_64/kernel/asm-offsets.c b/arch/sw_64/kernel/asm-offsets.c index 41310a8a7af1..2fb2d807ae3f 100644 --- a/arch/sw_64/kernel/asm-offsets.c +++ b/arch/sw_64/kernel/asm-offsets.c @@ -21,6 +21,7 @@ void foo(void) { DEFINE(ASM_THREAD_SIZE, THREAD_SIZE); DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); + OFFSET(TI_PCB_KSP, thread_info, pcb.ksp); BLANK(); DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked)); @@ -106,9 +107,9 @@ void foo(void) DEFINE(PT_REGS_HM_PS, offsetof(struct pt_regs, hm_ps)); DEFINE(PT_REGS_HM_PC, offsetof(struct pt_regs, hm_pc)); DEFINE(PT_REGS_HM_GP, offsetof(struct pt_regs, hm_gp)); - DEFINE(PT_REGS_HM_R16, offsetof(struct pt_regs, hm_r16)); - DEFINE(PT_REGS_HM_R17, offsetof(struct pt_regs, hm_r17)); - DEFINE(PT_REGS_HM_R18, offsetof(struct pt_regs, hm_r18)); + DEFINE(PT_REGS_EARG0, offsetof(struct pt_regs, earg0)); + DEFINE(PT_REGS_EARG1, offsetof(struct pt_regs, earg1)); + DEFINE(PT_REGS_EARG2, offsetof(struct pt_regs, earg2)); BLANK(); DEFINE(KVM_REGS_SIZE, sizeof(struct kvm_regs)); @@ -128,6 +129,9 @@ void foo(void) DEFINE(KVM_REGS_R13, offsetof(struct kvm_regs, r13)); DEFINE(KVM_REGS_R14, offsetof(struct kvm_regs, r14)); DEFINE(KVM_REGS_R15, offsetof(struct kvm_regs, r15)); + DEFINE(KVM_REGS_R16, offsetof(struct kvm_regs, r16)); + DEFINE(KVM_REGS_R17, offsetof(struct kvm_regs, r17)); + DEFINE(KVM_REGS_R18, offsetof(struct kvm_regs, r18)); DEFINE(KVM_REGS_R19, offsetof(struct kvm_regs, r19)); DEFINE(KVM_REGS_R20, offsetof(struct kvm_regs, r20)); DEFINE(KVM_REGS_R21, offsetof(struct kvm_regs, r21)); @@ -138,6 +142,7 @@ void foo(void) DEFINE(KVM_REGS_R26, offsetof(struct kvm_regs, r26)); DEFINE(KVM_REGS_R27, offsetof(struct kvm_regs, r27)); DEFINE(KVM_REGS_R28, offsetof(struct kvm_regs, r28)); + DEFINE(KVM_REGS_GP, offsetof(struct kvm_regs, gp)); DEFINE(KVM_REGS_FPCR, offsetof(struct kvm_regs, fpcr)); DEFINE(KVM_REGS_F0, offsetof(struct kvm_regs, fp[0 * 4])); DEFINE(KVM_REGS_F1, offsetof(struct kvm_regs, fp[1 * 4])); @@ -172,10 +177,9 @@ void foo(void) DEFINE(KVM_REGS_F30, offsetof(struct kvm_regs, fp[30 * 4])); DEFINE(KVM_REGS_PS, offsetof(struct kvm_regs, ps)); DEFINE(KVM_REGS_PC, offsetof(struct kvm_regs, pc)); - DEFINE(KVM_REGS_GP, offsetof(struct kvm_regs, gp)); - DEFINE(KVM_REGS_R16, offsetof(struct kvm_regs, r16)); - DEFINE(KVM_REGS_R17, offsetof(struct kvm_regs, r17)); - DEFINE(KVM_REGS_R18, offsetof(struct kvm_regs, r18)); +#ifdef CONFIG_SUBARCH_C4 + DEFINE(KVM_REGS_SP, offsetof(struct kvm_regs, sp)); +#endif BLANK(); DEFINE(VCPU_RET_SIZE, sizeof(struct vcpu_run_ret_stack)); diff --git a/arch/sw_64/kernel/early_init.c b/arch/sw_64/kernel/early_init.c index 2ec7a3e99443..3d7b9c4325a9 100644 --- a/arch/sw_64/kernel/early_init.c +++ b/arch/sw_64/kernel/early_init.c @@ -6,6 +6,5 @@ asmlinkage __visible void __init sw64_start_kernel(void) { fixup_hmcall(); - save_ktp(); start_kernel(); } diff --git a/arch/sw_64/kernel/entry.S b/arch/sw_64/kernel/entry_c3.S similarity index 96% rename from arch/sw_64/kernel/entry.S rename to arch/sw_64/kernel/entry_c3.S index 59c2ff4eb915..a7183817671b 100644 --- a/arch/sw_64/kernel/entry.S +++ b/arch/sw_64/kernel/entry_c3.S @@ -49,9 +49,9 @@ stl $25, PT_REGS_R25($sp) stl $26, PT_REGS_R26($sp) stl $27, PT_REGS_R27($sp) - ldl $1, PT_REGS_HM_R16($sp) - ldl $2, PT_REGS_HM_R17($sp) - ldl $3, PT_REGS_HM_R18($sp) + ldl $1, PT_REGS_EARG0($sp) + ldl $2, PT_REGS_EARG1($sp) + ldl $3, PT_REGS_EARG2($sp) ldl $4, PT_REGS_HM_GP($sp) ldl $5, PT_REGS_HM_PC($sp) ldl $6, PT_REGS_HM_PS($sp) @@ -83,9 +83,9 @@ ldl $4, PT_REGS_GP($sp) ldl $5, PT_REGS_PC($sp) ldl $6, PT_REGS_PS($sp) - stl $1, PT_REGS_HM_R16($sp) - stl $2, PT_REGS_HM_R17($sp) - stl $3, PT_REGS_HM_R18($sp) + stl $1, PT_REGS_EARG0($sp) + stl $2, PT_REGS_EARG1($sp) + stl $3, PT_REGS_EARG2($sp) stl $4, PT_REGS_HM_GP($sp) stl $5, PT_REGS_HM_PC($sp) stl $6, PT_REGS_HM_PS($sp) @@ -214,10 +214,9 @@ entSys: .globl ret_from_sys_call .ent ret_from_sys_call ret_from_sys_call: -#ifdef CONFIG_SUBARCH_C3B fillcs 0($sp) /* prefetch */ fillcs 128($sp) /* prefetch */ -#endif + br $27, 1f 1: ldgp $29, 0($27) /* Make sure need_resched and sigpending don't change between diff --git a/arch/sw_64/kernel/entry_c4.S b/arch/sw_64/kernel/entry_c4.S new file mode 100644 index 000000000000..1209e627a7f1 --- /dev/null +++ b/arch/sw_64/kernel/entry_c4.S @@ -0,0 +1,330 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Kernel entry-points. + */ + +#include +#include +#include +#include +#include +#include +#include + + .text + .set noat + + .macro SAVE_ALL + csrw $sp, CSR_SP + csrw $1, CSR_SCRATCH + csrr $1, CSR_PS + and $1, 8, $1 + beq $1, 1f + csrr $1, CSR_KTP + ldl $sp, TI_PCB_KSP($1) +1: + /* Due to a flaw in the CSR design, in some cases the + * read CSR instruction is sent before the write instruction, + * so it needs to be read twice to ensure that the correct + * CSR value is read. Don`t delete it! + */ + csrr $1, CSR_SCRATCH + csrr $1, CSR_SCRATCH + ldi $sp, -PT_REGS_SIZE($sp) + stl $0, PT_REGS_R0($sp) + stl $1, PT_REGS_R1($sp) + stl $2, PT_REGS_R2($sp) + stl $3, PT_REGS_R3($sp) + stl $4, PT_REGS_R4($sp) + stl $5, PT_REGS_R5($sp) + stl $6, PT_REGS_R6($sp) + stl $7, PT_REGS_R7($sp) + stl $8, PT_REGS_R8($sp) + stl $9, PT_REGS_R9($sp) + stl $10, PT_REGS_R10($sp) + stl $11, PT_REGS_R11($sp) + stl $12, PT_REGS_R12($sp) + stl $13, PT_REGS_R13($sp) + stl $14, PT_REGS_R14($sp) + stl $15, PT_REGS_R15($sp) + stl $16, PT_REGS_R16($sp) + stl $17, PT_REGS_R17($sp) + stl $18, PT_REGS_R18($sp) + stl $19, PT_REGS_R19($sp) + stl $20, PT_REGS_R20($sp) + stl $21, PT_REGS_R21($sp) + stl $22, PT_REGS_R22($sp) + stl $23, PT_REGS_R23($sp) + stl $24, PT_REGS_R24($sp) + stl $25, PT_REGS_R25($sp) + stl $26, PT_REGS_R26($sp) + stl $27, PT_REGS_R27($sp) + stl $28, PT_REGS_R28($sp) + stl $29, PT_REGS_GP($sp) + + csrr $1, CSR_SP + csrr $1, CSR_SP + csrr $2, CSR_PS + csrr $3, CSR_PC + csrr $16, CSR_EARG0 + csrr $17, CSR_EARG1 + csrr $18, CSR_EARG2 + stl $16, PT_REGS_EARG0($sp) + stl $17, PT_REGS_EARG1($sp) + stl $18, PT_REGS_EARG2($sp) + + stl $1, PT_REGS_SP($sp) + stl $2, PT_REGS_PS($sp) + stl $3, PT_REGS_PC($sp) + ldi $1, NO_SYSCALL + stl $1, PT_REGS_ORIG_R0($sp) + csrr $8, CSR_KTP + .endm + + .macro RESTORE_ALL + ldi $16, 7 + sys_call HMC_swpipl + + ldl $1, PT_REGS_PS($sp) + ldl $2, PT_REGS_PC($sp) + csrw $1, CSR_PS + csrw $2, CSR_PC + and $1, 0x8, $1 + beq $1, 1f + ldi $16,PT_REGS_SIZE($sp) + stl $16, TI_PCB_KSP($8) +1: + ldl $0, PT_REGS_R0($sp) + ldl $1, PT_REGS_R1($sp) + ldl $2, PT_REGS_R2($sp) + ldl $3, PT_REGS_R3($sp) + ldl $4, PT_REGS_R4($sp) + ldl $5, PT_REGS_R5($sp) + ldl $6, PT_REGS_R6($sp) + ldl $7, PT_REGS_R7($sp) + ldl $8, PT_REGS_R8($sp) + ldl $9, PT_REGS_R9($sp) + ldl $10, PT_REGS_R10($sp) + ldl $11, PT_REGS_R11($sp) + ldl $12, PT_REGS_R12($sp) + ldl $13, PT_REGS_R13($sp) + ldl $14, PT_REGS_R14($sp) + ldl $15, PT_REGS_R15($sp) + ldl $16, PT_REGS_R16($sp) + ldl $17, PT_REGS_R17($sp) + ldl $18, PT_REGS_R18($sp) + ldl $19, PT_REGS_R19($sp) + ldl $20, PT_REGS_R20($sp) + ldl $21, PT_REGS_R21($sp) + ldl $22, PT_REGS_R22($sp) + ldl $23, PT_REGS_R23($sp) + ldl $24, PT_REGS_R24($sp) + ldl $25, PT_REGS_R25($sp) + ldl $26, PT_REGS_R26($sp) + ldl $27, PT_REGS_R27($sp) + ldl $28, PT_REGS_R28($sp) + ldl $29, PT_REGS_GP($sp) + ldl $sp, PT_REGS_SP($sp) + .endm + + .macro RESTORE_IRQ + csrr $16, CSR_PS + sys_call HMC_swpipl + ldl $16, PT_REGS_EARG0($sp) + .endm +/* + * Non-syscall kernel entry points. + */ + + .align 4 + .globl entInt + .ent entInt +entInt: + SAVE_ALL + br $27, 1f +1: ldgp $29, 0($27) + mov $sp, $19 + call $26, do_entInt + br ret_from_sys_call + .end entInt + + .align 4 + .globl entArith + .ent entArith +entArith: + SAVE_ALL + br $27, 1f +1: ldgp $29, 0($27) + RESTORE_IRQ + mov $sp, $18 + call $26, do_entArith + br ret_from_sys_call + .end entArith + + .align 4 + .globl entMM + .ent entMM +entMM: + SAVE_ALL + br $27, 1f +1: ldgp $29, 0($27) + RESTORE_IRQ + mov $sp, $19 + call $26, do_page_fault + br ret_from_sys_call + .end entMM + + .align 4 + .globl entIF + .ent entIF +entIF: + SAVE_ALL + br $27, 1f +1: ldgp $29, 0($27) + RESTORE_IRQ + mov $sp, $18 + call $26, do_entIF + br ret_from_sys_call + .end entIF + +/* + * Handle unalignment exception. + * We don't handle the "gp" register correctly, but if we fault on a + * gp-register unaligned load/store, something is _very_ wrong in the + * kernel anyway. + */ + .align 4 + .globl entUna + .ent entUna +entUna: + SAVE_ALL + br $27, 1f +1: ldgp $29, 0($27) + RESTORE_IRQ + mov $sp, $19 + ldl $0, PT_REGS_PS($sp) + and $0, 8, $0 /* user mode ? */ + beq $0, 1f + call $26, do_entUnaUser /* return to ret_from_syscall */ + br ret_from_sys_call +1: ldl $9, PT_REGS_GP($sp) + call $26, do_entUna + stl $9, PT_REGS_GP($sp) + RESTORE_ALL + sys_call HMC_rti + .end entUna + +/* + * The system call entry point is special. Most importantly, it looks + * like a function call to userspace as far as clobbered registers. We + * do preserve the argument registers (for syscall restarts) and $26 + * (for leaf syscall functions). + * + * So much for theory. We don't take advantage of this yet. + * + * Note that a0-a2 are not saved by HMcode as with the other entry points. + */ + + .align 4 + .globl entSys + .ent entSys +entSys: + SAVE_ALL + br $27, 1f +1: ldgp $29, 0($27) + RESTORE_IRQ + mov $sp, $16 + call $26, do_entSys + br ret_from_sys_call + .end entSys + + .align 4 + .globl ret_from_sys_call + .ent ret_from_sys_call +ret_from_sys_call: + br $27, 1f +1: ldgp $29, 0($27) + /* Make sure need_resched and sigpending don't change between + sampling and the rti. */ + ldi $16, 7 + sys_call HMC_swpipl + ldl $0, PT_REGS_PS($sp) + and $0, 8, $0 + beq $0, restore_all +ret_to_user: + ldw $17, TI_FLAGS($8) + and $17, _TIF_WORK_MASK, $2 + beq $2, restore_all + mov $sp, $16 + call $26, do_notify_resume +restore_all: + RESTORE_ALL + sys_call HMC_rti + .end ret_from_sys_call + +/* + * Integer register context switch + * The callee-saved registers must be saved and restored. + * + * a0: previous task_struct (must be preserved across the switch) + * a1: next task_struct + * + * The value of a0 must be preserved by this function, as that's how + * arguments are passed to schedule_tail. + */ + .align 4 + .globl __switch_to + .ent __switch_to +__switch_to: + .prologue 0 + /* Save context into prev->thread */ + stl $26, TASK_THREAD_RA($16) + stl $30, TASK_THREAD_SP($16) + stl $9, TASK_THREAD_S0($16) + stl $10, TASK_THREAD_S1($16) + stl $11, TASK_THREAD_S2($16) + stl $12, TASK_THREAD_S3($16) + stl $13, TASK_THREAD_S4($16) + stl $14, TASK_THREAD_S5($16) + stl $15, TASK_THREAD_S6($16) + /* Restore context from next->thread */ + ldl $26, TASK_THREAD_RA($17) + ldl $30, TASK_THREAD_SP($17) + ldl $9, TASK_THREAD_S0($17) + ldl $10, TASK_THREAD_S1($17) + ldl $11, TASK_THREAD_S2($17) + ldl $12, TASK_THREAD_S3($17) + ldl $13, TASK_THREAD_S4($17) + ldl $14, TASK_THREAD_S5($17) + ldl $15, TASK_THREAD_S6($17) + mov $17, $8 + csrw $8, CSR_KTP + mov $16, $0 + ret + .end __switch_to + +/* + * New processes begin life here. + */ + + .globl ret_from_fork + .align 4 + .ent ret_from_fork +ret_from_fork: + call $26, schedule_tail + br ret_from_sys_call + .end ret_from_fork + +/* + * ... and new kernel threads - here + */ + .align 4 + .globl ret_from_kernel_thread + .ent ret_from_kernel_thread +ret_from_kernel_thread: + call $26, schedule_tail + mov $9, $27 + mov $10, $16 + call $26, ($9) + br ret_to_user + .end ret_from_kernel_thread diff --git a/arch/sw_64/kernel/head.S b/arch/sw_64/kernel/head.S index f3d27ea9e30e..bfeb6859ecc2 100644 --- a/arch/sw_64/kernel/head.S +++ b/arch/sw_64/kernel/head.S @@ -10,6 +10,15 @@ #include #include #include +#include + + .macro SAVE_KTP +#ifdef CONFIG_SUBARCH_C3B + sys_call HMC_wrktp +#else + csrw $8, CSR_KTP +#endif + .endm __HEAD .globl _stext @@ -23,6 +32,7 @@ __start: 1: ldgp $29, 0($27) /* We need to get current_task_info loaded up... */ ldi $8, init_task + SAVE_KTP ldl $30, TASK_STACK($8) /* ... and find our stack ... */ ldi $30, ASM_THREAD_SIZE($30) @@ -88,7 +98,7 @@ __smp_callin: ldi $2, idle_task_pointer s8addl $0, $2, $2 ldl $8, 0($2) # Get ksp of idle thread - sys_call HMC_wrktp + SAVE_KTP ldl $30, TASK_STACK($8) ldi $30, ASM_THREAD_SIZE($30) diff --git a/arch/sw_64/kernel/hibernate_asm.S b/arch/sw_64/kernel/hibernate_asm.S index ff997cd76c5a..af0372879bb9 100644 --- a/arch/sw_64/kernel/hibernate_asm.S +++ b/arch/sw_64/kernel/hibernate_asm.S @@ -4,6 +4,13 @@ #include #include + .macro SAVE_KTP +#ifdef CONFIG_SUBARCH_C3B + sys_call HMC_wrktp +#else + csrw $8, CSR_KTP + .endm +#endif .text .set noat ENTRY(swsusp_arch_suspend) @@ -114,8 +121,7 @@ $hibernate_setfpec_over: ldl sp, PSTATE_SP($16) ldl $8, PSTATE_KTP($16) - sys_call HMC_wrktp - + SAVE_KTP ldi $0, 0($31) ret diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 82222ed63f0a..9fda2f95d0cb 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -69,10 +69,6 @@ void smp_callin(void) } set_cpu_online(cpuid, true); - /* clear ksp, usp */ - wrksp(0); - wrusp(0); - /* Set trap vectors. */ trap_init(); diff --git a/arch/sw_64/kvm/Makefile b/arch/sw_64/kvm/Makefile index 8111014c5cca..8f594155f352 100644 --- a/arch/sw_64/kvm/Makefile +++ b/arch/sw_64/kvm/Makefile @@ -9,12 +9,8 @@ include $(srctree)/virt/kvm/Makefile.kvm obj-$(CONFIG_KVM) += kvm.o -kvm-y += sw64.o -kvm-y += entry.o -kvm-y += emulate.o -kvm-y += mmio.o -kvm-y += kvm_timer.o -kvm-y += handle_exit.o -kvm-y += perf.o -kvm-$(CONFIG_SUBARCH_C3B) += kvm_core3.o kvm_cma.o -kvm-$(CONFIG_SUBARCH_C4) += kvm_core4.o mmu.o +kvm-y := $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/irqchip.o $(KVM)/vfio.o \ + sw64.o emulate.o mmio.o kvm_timer.o handle_exit.o perf.o + +kvm-$(CONFIG_SUBARCH_C3B) += kvm_core3.o entry_core3.o +kvm-$(CONFIG_SUBARCH_C4) += kvm_core4.o mmu.o entry_core4.o diff --git a/arch/sw_64/kvm/entry.S b/arch/sw_64/kvm/entry_core3.S similarity index 100% rename from arch/sw_64/kvm/entry.S rename to arch/sw_64/kvm/entry_core3.S diff --git a/arch/sw_64/kvm/entry_core4.S b/arch/sw_64/kvm/entry_core4.S new file mode 100644 index 000000000000..fb6757425f76 --- /dev/null +++ b/arch/sw_64/kvm/entry_core4.S @@ -0,0 +1,275 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2024 WXIAT + * Author: Wang Yuanheng + */ + .text +#include +#include +#include +#include +#include + + .set noat + +/* + * r16: physical address of guest kvm_vcpu.arch.vcb + * r17: pointer to guest kvm_vcpu.arch.kvm_regs + * r18: pointer to hcall args + */ +ENTRY(__sw64_vcpu_run) + /* save host fpregs */ + rfpcr $f0 + fstd $f0, TASK_THREAD_FPCR($8) + vstd $f2, TASK_THREAD_F2($8) + vstd $f3, TASK_THREAD_F3($8) + vstd $f4, TASK_THREAD_F4($8) + vstd $f5, TASK_THREAD_F5($8) + vstd $f6, TASK_THREAD_F6($8) + vstd $f7, TASK_THREAD_F7($8) + vstd $f8, TASK_THREAD_F8($8) + vstd $f9, TASK_THREAD_F9($8) + + ldi sp, -VCPU_RET_SIZE(sp) + /* save host pt_regs to current kernel stack */ + ldi sp, -PT_REGS_SIZE(sp) + stl $9, PT_REGS_R9(sp) + stl $8, PT_REGS_R8(sp) + stl $10, PT_REGS_R10(sp) + stl $11, PT_REGS_R11(sp) + stl $12, PT_REGS_R12(sp) + stl $13, PT_REGS_R13(sp) + stl $14, PT_REGS_R14(sp) + stl $15, PT_REGS_R15(sp) + stl $26, PT_REGS_R26(sp) + stl $29, PT_REGS_GP(sp) + csrw $16, CSR_EARG0 + csrw $17, CSR_EARG1 + csrw $18, CSR_EARG2 + + /* restore guest switch stack from guest kvm_regs struct */ + ldl $0, KVM_REGS_R0($17) + ldl $1, KVM_REGS_R1($17) + /* restore $2 later */ + ldl $3, KVM_REGS_R3($17) + ldl $4, KVM_REGS_R4($17) + ldl $5, KVM_REGS_R5($17) + ldl $6, KVM_REGS_R6($17) + ldl $7, KVM_REGS_R7($17) + ldl $8, KVM_REGS_R8($17) + ldl $9, KVM_REGS_R9($17) + ldl $10, KVM_REGS_R10($17) + ldl $11, KVM_REGS_R11($17) + ldl $12, KVM_REGS_R12($17) + ldl $13, KVM_REGS_R13($17) + ldl $14, KVM_REGS_R14($17) + ldl $15, KVM_REGS_R15($17) + ldl $16, KVM_REGS_R16($17) + ldl $18, KVM_REGS_R18($17) + ldl $19, KVM_REGS_R19($17) + ldl $20, KVM_REGS_R20($17) + ldl $21, KVM_REGS_R21($17) + ldl $22, KVM_REGS_R22($17) + ldl $23, KVM_REGS_R23($17) + ldl $24, KVM_REGS_R24($17) + ldl $25, KVM_REGS_R25($17) + ldl $26, KVM_REGS_R26($17) + ldl $27, KVM_REGS_R27($17) + ldl $28, KVM_REGS_R28($17) + ldl $29, KVM_REGS_GP($17) + + fldd $f0, KVM_REGS_FPCR($17) + wfpcr $f0 + fimovd $f0, $2 + and $2, 0x3, $2 + beq $2, $g_setfpec_0 + subl $2, 0x1, $2 + beq $2, $g_setfpec_1 + subl $2, 0x1, $2 + beq $2, $g_setfpec_2 + setfpec3 + br $g_setfpec_over +$g_setfpec_0: + setfpec0 + br $g_setfpec_over +$g_setfpec_1: + setfpec1 + br $g_setfpec_over +$g_setfpec_2: + setfpec2 +$g_setfpec_over: + ldl $2, KVM_REGS_R2($17) + vldd $f0, KVM_REGS_F0($17) + vldd $f1, KVM_REGS_F1($17) + vldd $f2, KVM_REGS_F2($17) + vldd $f3, KVM_REGS_F3($17) + vldd $f4, KVM_REGS_F4($17) + vldd $f5, KVM_REGS_F5($17) + vldd $f6, KVM_REGS_F6($17) + vldd $f7, KVM_REGS_F7($17) + vldd $f8, KVM_REGS_F8($17) + vldd $f9, KVM_REGS_F9($17) + vldd $f10, KVM_REGS_F10($17) + vldd $f11, KVM_REGS_F11($17) + vldd $f12, KVM_REGS_F12($17) + vldd $f13, KVM_REGS_F13($17) + vldd $f14, KVM_REGS_F14($17) + vldd $f15, KVM_REGS_F15($17) + vldd $f16, KVM_REGS_F16($17) + vldd $f17, KVM_REGS_F17($17) + vldd $f18, KVM_REGS_F18($17) + vldd $f19, KVM_REGS_F19($17) + vldd $f20, KVM_REGS_F20($17) + vldd $f21, KVM_REGS_F21($17) + vldd $f22, KVM_REGS_F22($17) + vldd $f23, KVM_REGS_F23($17) + vldd $f24, KVM_REGS_F24($17) + vldd $f25, KVM_REGS_F25($17) + vldd $f26, KVM_REGS_F26($17) + vldd $f27, KVM_REGS_F27($17) + vldd $f28, KVM_REGS_F28($17) + vldd $f29, KVM_REGS_F29($17) + vldd $f30, KVM_REGS_F30($17) + csrw $17, CSR_BASE_KREGS + ldl $17, KVM_REGS_R17($17) + + /* enter guest now */ + sys_call 0x31 + /* exit guest now */ + csrw $17, CSR_SCRATCH + csrr $17, CSR_BASE_KREGS /* r17: base of kvm_regs */ + + vstd $f0, KVM_REGS_F0($17) + vstd $f1, KVM_REGS_F1($17) + vstd $f2, KVM_REGS_F2($17) + vstd $f3, KVM_REGS_F3($17) + vstd $f4, KVM_REGS_F4($17) + vstd $f5, KVM_REGS_F5($17) + vstd $f6, KVM_REGS_F6($17) + vstd $f7, KVM_REGS_F7($17) + vstd $f8, KVM_REGS_F8($17) + vstd $f9, KVM_REGS_F9($17) + vstd $f10, KVM_REGS_F10($17) + vstd $f11, KVM_REGS_F11($17) + vstd $f12, KVM_REGS_F12($17) + vstd $f13, KVM_REGS_F13($17) + vstd $f14, KVM_REGS_F14($17) + vstd $f15, KVM_REGS_F15($17) + vstd $f16, KVM_REGS_F16($17) + vstd $f17, KVM_REGS_F17($17) + vstd $f18, KVM_REGS_F18($17) + vstd $f19, KVM_REGS_F19($17) + vstd $f20, KVM_REGS_F20($17) + vstd $f21, KVM_REGS_F21($17) + vstd $f22, KVM_REGS_F22($17) + vstd $f23, KVM_REGS_F23($17) + vstd $f24, KVM_REGS_F24($17) + vstd $f25, KVM_REGS_F25($17) + vstd $f26, KVM_REGS_F26($17) + vstd $f27, KVM_REGS_F27($17) + vstd $f28, KVM_REGS_F28($17) + vstd $f29, KVM_REGS_F29($17) + vstd $f30, KVM_REGS_F30($17) + + rfpcr $f0 + fstd $f0, KVM_REGS_FPCR($17) + + /* don't save r0 Hmcode have saved r0 for us */ + stl $1, KVM_REGS_R1($17) + stl $2, KVM_REGS_R2($17) + stl $3, KVM_REGS_R3($17) + stl $4, KVM_REGS_R4($17) + stl $5, KVM_REGS_R5($17) + stl $6, KVM_REGS_R6($17) + stl $7, KVM_REGS_R7($17) + stl $8, KVM_REGS_R8($17) + stl $9, KVM_REGS_R9($17) + stl $10, KVM_REGS_R10($17) + stl $11, KVM_REGS_R11($17) + stl $12, KVM_REGS_R12($17) + stl $13, KVM_REGS_R13($17) + stl $14, KVM_REGS_R14($17) + stl $15, KVM_REGS_R15($17) + stl $19, KVM_REGS_R19($17) + stl $20, KVM_REGS_R20($17) + stl $21, KVM_REGS_R21($17) + stl $22, KVM_REGS_R22($17) + stl $23, KVM_REGS_R23($17) + stl $24, KVM_REGS_R24($17) + stl $25, KVM_REGS_R25($17) + stl $26, KVM_REGS_R26($17) + stl $27, KVM_REGS_R27($17) + stl $28, KVM_REGS_R28($17) + stl $29, KVM_REGS_GP($17) + stl $16, KVM_REGS_R16($17) + stl $18, KVM_REGS_R18($17) + imemb + csrr $9, CSR_SCRATCH + stl $9, KVM_REGS_R17($17) + + /* restore host regs from host sp */ + csrr sp, CSR_SP + ldl $8, PT_REGS_R8(sp) + ldl $9, PT_REGS_R9(sp) + ldl $10, PT_REGS_R10(sp) + ldl $11, PT_REGS_R11(sp) + ldl $12, PT_REGS_R12(sp) + ldl $13, PT_REGS_R13(sp) + ldl $14, PT_REGS_R14(sp) + ldl $15, PT_REGS_R15(sp) + ldl $26, PT_REGS_R26(sp) + ldl $29, PT_REGS_GP(sp) + csrr $2, CSR_PS + stl $2, PT_REGS_PS(sp) + ldi sp, PT_REGS_SIZE(sp) + + /* restore host fpregs */ + fldd $f0, TASK_THREAD_FPCR($8) + wfpcr $f0 + fimovd $f0, $2 + and $2, 0x3, $2 + beq $2, $setfpec_0 + subl $2, 0x1, $2 + beq $2, $setfpec_1 + subl $2, 0x1, $2 + beq $2, $setfpec_2 + setfpec3 + br $setfpec_over +$setfpec_0: + setfpec0 + br $setfpec_over +$setfpec_1: + setfpec1 + br $setfpec_over +$setfpec_2: + setfpec2 +$setfpec_over: + vldd $f2, TASK_THREAD_F2($8) + vldd $f3, TASK_THREAD_F3($8) + vldd $f4, TASK_THREAD_F4($8) + vldd $f5, TASK_THREAD_F5($8) + vldd $f6, TASK_THREAD_F6($8) + vldd $f7, TASK_THREAD_F7($8) + vldd $f8, TASK_THREAD_F8($8) + vldd $f9, TASK_THREAD_F9($8) + + /* if $0 > 0, handle hcall */ + bgt $0, $ret_to + + stl $26, VCPU_RET_RA(sp) + stl $0, VCPU_RET_R0(sp) + + /* Hmcode will setup in */ + /* restore $16 $17 $18, do interrupt trick */ + csrr $16, CSR_EARG0 + csrr $17, CSR_EARG1 + csrr $18, CSR_EARG2 + + ldi $19, -PT_REGS_SIZE(sp) + call $26, do_entInt + ldl $26, VCPU_RET_RA(sp) + ldl $0, VCPU_RET_R0(sp) +$ret_to: + /* ret($0) indicate hcall number */ + ldi sp, VCPU_RET_SIZE(sp) /* pop stack */ + ret -- Gitee From f21eaf843de835da61dac5c576c7734ebd11a5b7 Mon Sep 17 00:00:00 2001 From: Zhi Tongze Date: Thu, 21 Mar 2024 15:40:46 +0800 Subject: [PATCH 56/98] sw64: improve cpu bring up method Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- It used to notify firmware through a shared flag that secondary cpu has been prepared, and firmware continuously read this flag to check whether secondary cpu is ready. This will continuously occupy cpu resources, resulting in aonther thread on the same physical core being unable to utilize processor resources. This patch makes it halt directly and wait for NMII to wake up. Signed-off-by: Zhi Tongze Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/smp.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 9fda2f95d0cb..9cb7c64b3afe 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -21,7 +21,6 @@ struct smp_rcb_struct *smp_rcb; extern struct cpuinfo_sw64 cpu_data[NR_CPUS]; -int smp_booted; void *idle_task_pointer[NR_CPUS]; @@ -304,10 +303,8 @@ int vt_cpu_up(unsigned int cpu, struct task_struct *tidle) wmb(); smp_rcb->ready = 0; - if (smp_booted) { - /* irq must be disabled before reset vCPU */ - reset_cpu(cpu); - } + /* irq must be disabled before reset vCPU */ + reset_cpu(cpu); smp_boot_one_cpu(cpu, tidle); return cpu_online(cpu) ? 0 : -EIO; @@ -328,23 +325,19 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle) /* send wake up signal */ send_wakeup_interrupt(cpu); /* send reset signal */ - if (smp_booted) { - if (is_in_host()) { - reset_cpu(cpu); - } else { - while (1) - cpu_relax(); - } + if (is_in_host()) { + reset_cpu(cpu); + } else { + while (1) + cpu_relax(); } smp_boot_one_cpu(cpu, tidle); #ifdef CONFIG_SUBARCH_C3B if (static_branch_likely(&use_tc_as_sched_clock)) { - if (smp_booted) { - tc_sync_clear(); - smp_call_function_single(cpu, tc_sync_ready, NULL, 0); - tc_sync_set(); - } + tc_sync_clear(); + smp_call_function_single(cpu, tc_sync_ready, NULL, 0); + tc_sync_set(); } #endif @@ -353,7 +346,6 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle) void __init smp_cpus_done(unsigned int max_cpus) { - smp_booted = 1; pr_info("SMP: Total of %d processors activated.\n", num_online_cpus()); } -- Gitee From 241bf24681f5ce3207dd11b76ca72acf876d0a12 Mon Sep 17 00:00:00 2001 From: Xu Chenjiao Date: Tue, 26 Mar 2024 10:58:55 +0000 Subject: [PATCH 57/98] sw64: lpc: work around hardware flaws Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- For lpc host of C4: - Legacy IO address can not be accessed normally, and we borrow memory IO address to access legacy IO. - It does not support interrupt, so the IPMI driver have to use poll mode instead of interrupt mode. Force the kipmi daemon to be enabled with "ipmi_si.force_kipmid=1" in the kernel command line. Signed-off-by: Xu Chenjiao Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 1 - drivers/mfd/Kconfig | 8 ++++---- drivers/mfd/Makefile | 2 +- drivers/mfd/{lpc_sunway_chip3.c => lpc_sunway.c} | 0 drivers/mfd/sunway_ast2400.c | 4 ++-- 5 files changed, 7 insertions(+), 8 deletions(-) rename drivers/mfd/{lpc_sunway_chip3.c => lpc_sunway.c} (100%) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 02e4c672c8b8..79be887a5a0c 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -234,7 +234,6 @@ config PLATFORM_XUELANG depends on UNCORE_XUELANG select SPARSE_IRQ select SYS_HAS_EARLY_PRINTK - select SW64_INTC_V2 select I2C_SUNWAY if I2C help Sunway board chipset for C3B diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 6b653487d954..96633e8d4a9c 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -604,12 +604,12 @@ config LPC_SCH LPC bridge function of the Intel SCH provides support for System Management Bus and General Purpose I/O. -config LPC_CHIP3 - tristate "CHIP3 LPC" - depends on UNCORE_XUELANG +config LPC_SUNWAY + tristate "SUNWAY LPC" + depends on SW64 select MFD_CORE help - LPC bridge function of the chip3 provides support for + LPC bridge function of the Sunway provides support for System Management Bus and General Purpose I/O. config SUNWAY_SUPERIO_AST2400 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 50b42df268ea..95867f732d2e 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -269,7 +269,7 @@ obj-$(CONFIG_MFD_KHADAS_MCU) += khadas-mcu.o obj-$(CONFIG_MFD_ACER_A500_EC) += acer-ec-a500.o obj-$(CONFIG_MFD_QCOM_PM8008) += qcom-pm8008.o -obj-$(CONFIG_LPC_CHIP3) += lpc_sunway_chip3.o +obj-$(CONFIG_LPC_SUNWAY) += lpc_sunway.o obj-$(CONFIG_SUNWAY_SUPERIO_AST2400) += sunway_ast2400.o obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o diff --git a/drivers/mfd/lpc_sunway_chip3.c b/drivers/mfd/lpc_sunway.c similarity index 100% rename from drivers/mfd/lpc_sunway_chip3.c rename to drivers/mfd/lpc_sunway.c diff --git a/drivers/mfd/sunway_ast2400.c b/drivers/mfd/sunway_ast2400.c index fbea07813643..ea981d9d0215 100644 --- a/drivers/mfd/sunway_ast2400.c +++ b/drivers/mfd/sunway_ast2400.c @@ -79,7 +79,7 @@ static void superio_com1_init(struct pnp_device *device) pnp_set_logical_device(device); pnp_set_enable(device, 1); - pnp_write_config(device, 0x60, 0x3); + pnp_write_config(device, 0x60, 0x2); pnp_write_config(device, 0x61, 0xf8); pnp_write_config(device, 0x70, superio_uart0_irq); @@ -96,7 +96,7 @@ static void superio_com2_init(struct pnp_device *device) pnp_set_logical_device(device); pnp_set_enable(device, 1); - pnp_write_config(device, 0x60, 0x2); + pnp_write_config(device, 0x60, 0x3); pnp_write_config(device, 0x61, 0xf8); pnp_write_config(device, 0x70, superio_uart1_irq); -- Gitee From ca0be9965d4a265605b7ab3bc10a9cc25f48e6fb Mon Sep 17 00:00:00 2001 From: Xu Chenjiao Date: Tue, 26 Mar 2024 11:37:16 +0000 Subject: [PATCH 58/98] sw64: dts: add Junzhang Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Add Device Tree for Sunway Junzhang SoC. Signed-off-by: Xu Chenjiao Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/boot/dts/junzhang.dts | 250 +++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 arch/sw_64/boot/dts/junzhang.dts diff --git a/arch/sw_64/boot/dts/junzhang.dts b/arch/sw_64/boot/dts/junzhang.dts new file mode 100644 index 000000000000..4e8cd655c798 --- /dev/null +++ b/arch/sw_64/boot/dts/junzhang.dts @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Default device tree; + */ + +/dts-v1/; +/ { + compatible = "sunway,junzhang"; + model = "junzhang"; + #address-cells = <2>; + #size-cells = <2>; + + chosen { + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + clocks { + i2cclk: i2cclk { + compatible = "fixed-clock"; + clock-frequency = <12500000>; + #clock-cells = <0>; + clock-output-names = "i2cclk_12.5mhz"; + }; + spiclk: spiclk { + compatible = "fixed-clock"; + clock-frequency = <12500000>; + #clock-cells = <0>; + clock-output-names = "spiclk_12.5mhz"; + }; + + }; + + pintc: interrupt-controller { + compatible = "sw64,pintc"; + interrupt-controller; + sw64,node = <0>; + sw64,irq-num = <8>; + sw64,ver = <2>; + reg = <0x803a 0x0 0x0 0x1900>, + <0x8030 0x0 0x0 0xe000>; + #interrupt-cells = <1>; + }; + + lpc_intc: interrupt-controller@0x8037 { + compatible = "sw64,lpc_intc"; + reg = <0x8037 0x40000000 0x0 0x8000>; + interrupt-controller; + sw64,node = <0>; + sw64,irq-num = <16>; + sw64,ver = <1>; + #interrupt-cells = <1>; + interrupt-parent = <&pintc>; + interrupts = <2>; + }; + + uart: serial0@8033 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "sw6,sunway-apb-uart"; + reg = <0x8033 0x0 0x0 0x1000>; + interrupt-parent=<&pintc>; + interrupts = <3>; + reg-shift = <9>; + reg-io-width = <4>; + clock-frequency = <24000000>; + status = "okay"; + }; + + serial1@9033 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "sw6,sunway-apb-uart"; + reg = <0x9033 0x0 0x0 0x1000>; + reg-shift = <9>; + reg-io-width = <4>; + clock-frequency = <24000000>; + status = "okay"; + }; + + + i2c0@0x8031 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "snps,designware-i2c"; + reg = <0x8031 0x0 0x0 0x8000>; + clock-frequency = <100000>; + clocks = <&i2cclk>; + interrupt-parent=<&pintc>; + interrupts = <5>; + status = "okay"; + }; + + i2c1@0x8034 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,designware-i2c"; + reg = <0x8034 0x0 0x0 0x8000>; + clock-frequency = <100000>; + clocks = <&i2cclk>; + interrupt-parent=<&pintc>; + interrupts = <6>; + status = "okay"; + }; + + i2c2@0x8035 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,designware-i2c"; + reg = <0x8035 0x0 0x0 0x8000>; + clock-frequency = <100000>; + clocks = <&i2cclk>; + interrupt-parent=<&pintc>; + interrupts = <7>; + status = "okay"; + + rtc: pcf8523@68 { + compatible = "nxp,pcf8523"; + reg = <0x68>; + }; + + lm75: at30tse752a@48 { + compatible = "microchip,tcn75"; + reg = <0x48>; + }; + }; + + pvt: pvt@0x8030 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "sw64,pvt-vol"; + reg = <0x8030 0x0 0x0 0x7c00>; + status = "okay"; + }; + + spi: spi@0x8032 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "sunway,chip-spi"; + reg = <0x8032 0x0 0x0 0x8000>; + clocks = <&spiclk>; + poll_mode = <1>; /* poll_mode:1 interrupt mode: 0 */ + reg-io-width = <2>; + status = "okay"; + + flash@0 { + compatible = "winbond,w25q32dw", "jedec,spi-nor"; + spi-max-frequency = <25000000>; + m25p,fast-read; + reg = <0>; /* 0: flash chip selected bit */ + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "test"; + reg = <0 0x400000>; + }; + }; + }; + + flash@1 { + compatible = "winbond,w25q32dw", "jedec,spi-nor"; + spi-max-frequency = <25000000>; + m25p,fast-read; + reg = <1>; /* 1: flash chip selected bit */ + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "test"; + reg = <0 0x400000>; + }; + }; + }; + }; + + lpc: lpc@0x8037 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "sunway,chip3_lpc"; + ranges; + reg = <0x8037 0x40000000 0x0 0x8000>; + status = "okay"; + }; + + ipmi-kcs@0x8037 { + #address-cells = <2>; + #size-cells = <2>; + device_type = "ipmi"; + compatible = "ipmi-kcs"; + reg = <0x8037 0x20ca2000 0x0 0x10>; + reg-size = <1>; + reg-spacing = <4096>; + reg-shift = <0>; + status = "disabled"; + }; + + ipmi-bt@0x8037 { + #address-cells = <2>; + #size-cells = <2>; + device_type = "ipmi"; + compatible = "ipmi-bt"; + reg = <0x8037 0x200e4000 0x0 0x10>; + reg-size = <1>; + reg-spacing = <4096>; + reg-shift = <0>; + status = "disabled"; + }; + + suart1: suart1@0x3f8 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "ns16550a"; + clock-frequency = <1843200>; + reg = <0x8037 0x203f8000 0x0 0x10>; + reg-shift = <12>; + reg-io-width = <1>; + status = "disabled"; + }; + + gpio: gpio@8036 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "snps,sw-gpio"; + reg = <0x8036 0x0 0x0 0x8000>; + status = "okay"; + + porta: gpio-contraller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + snps,nr-gpios = <8>; + reg = <0 0 0 0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts-extended = <&pintc 0>, <&pintc 1>; + }; + }; + }; +}; -- Gitee From f18848ec5a2e1e4daf3e1d60894b8b7a476d5a6f Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Fri, 22 Mar 2024 11:26:29 +0800 Subject: [PATCH 59/98] sw64: fix syscall_fallback() for vdso gettimeofday Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Get $0 and $19 from inline assembly output to avoid compiler clobbering these two registers before we use them. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/vdso/vgettimeofday.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/arch/sw_64/kernel/vdso/vgettimeofday.c b/arch/sw_64/kernel/vdso/vgettimeofday.c index 07e023d3d64b..69dcab66cb10 100644 --- a/arch/sw_64/kernel/vdso/vgettimeofday.c +++ b/arch/sw_64/kernel/vdso/vgettimeofday.c @@ -21,19 +21,22 @@ static __always_inline int syscall_fallback(clockid_t clkid, struct timespec64 *ts) { - register int r0 asm("$0"); - register unsigned long r19 asm("$19"); + long retval; + long error; asm volatile( - " mov %0, $16\n" - " mov %1, $17\n" - " ldi $0, %2\n" - " sys_call %3\n" - :: "r"(clkid), "r"(ts), "i"(__NR_clock_gettime), "i"(HMC_callsys) + " 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(r19)) - return -r0; + if (unlikely(error)) + return -retval; else - return r0; + return retval; } static __always_inline int do_realtime_coarse(struct timespec64 *ts, -- Gitee From 1b40f28118968ea952f146f5bf88b5519da0ff4a Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 26 Mar 2024 16:40:06 +0800 Subject: [PATCH 60/98] sw64: enable CONFIG_FRAME_POINTER by default for junzhang Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- The new compiler for junzhang platform has fixed stackframe issue, so enable CONFIG_FRAME_POINTER by default. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/configs/junzhang_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/configs/junzhang_defconfig b/arch/sw_64/configs/junzhang_defconfig index 0459d08fd40d..9baf68f8e0ac 100644 --- a/arch/sw_64/configs/junzhang_defconfig +++ b/arch/sw_64/configs/junzhang_defconfig @@ -662,6 +662,6 @@ CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_HW is not set CONFIG_CONSOLE_LOGLEVEL_QUIET=7 -# CONFIG_FRAME_POINTER is not set +# CONFIG_ENABLE_MUST_CHECK is not set CONFIG_SCHEDSTATS=y # CONFIG_RCU_TRACE is not set -- Gitee From cb64795d0641126588e409308c90f47a17f5d021 Mon Sep 17 00:00:00 2001 From: Zhi Tongze Date: Tue, 26 Mar 2024 17:01:18 +0800 Subject: [PATCH 61/98] sw64: employ trick on regs.pc for specific exception Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- In order to ensure compatibility with firmware, this patch implements special handing on regs.pc for specific exception entries. Signed-off-by: Zhi Tongze Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/entry_c4.S | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/sw_64/kernel/entry_c4.S b/arch/sw_64/kernel/entry_c4.S index 1209e627a7f1..097f4279e69b 100644 --- a/arch/sw_64/kernel/entry_c4.S +++ b/arch/sw_64/kernel/entry_c4.S @@ -153,6 +153,9 @@ entInt: .ent entArith entArith: SAVE_ALL + ldl $1, PT_REGS_PC($sp) + ldi $1, 4($1) + stl $1, PT_REGS_PC($sp) br $27, 1f 1: ldgp $29, 0($27) RESTORE_IRQ @@ -179,6 +182,9 @@ entMM: .ent entIF entIF: SAVE_ALL + ldl $1, PT_REGS_PC($sp) + ldi $1, 4($1) + stl $1, PT_REGS_PC($sp) br $27, 1f 1: ldgp $29, 0($27) RESTORE_IRQ @@ -198,6 +204,9 @@ entIF: .ent entUna entUna: SAVE_ALL + ldl $1, PT_REGS_PC($sp) + ldi $1, 4($1) + stl $1, PT_REGS_PC($sp) br $27, 1f 1: ldgp $29, 0($27) RESTORE_IRQ @@ -230,6 +239,9 @@ entUna: .ent entSys entSys: SAVE_ALL + ldl $1, PT_REGS_PC($sp) + ldi $1, 4($1) + stl $1, PT_REGS_PC($sp) br $27, 1f 1: ldgp $29, 0($27) RESTORE_IRQ -- Gitee From 3f90ac702510f9ffe641d30750d3edd240ee8207 Mon Sep 17 00:00:00 2001 From: Tang Jinyang Date: Mon, 25 Mar 2024 15:33:21 +0800 Subject: [PATCH 62/98] sw64: work around suspend for C4 Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- This patch introduces a light weight sleep mechanism to work around suspend for Core4. Signed-off-by: Tang Jinyang Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/sw64_init.h | 7 ++++ arch/sw_64/include/asm/uncore_io_junzhang.h | 3 ++ arch/sw_64/kernel/smp.c | 40 +++++++++++++++++++++ arch/sw_64/kernel/suspend.c | 10 ++++++ drivers/irqchip/irq-sunway-cpu.c | 16 +++++++++ 5 files changed, 76 insertions(+) diff --git a/arch/sw_64/include/asm/sw64_init.h b/arch/sw_64/include/asm/sw64_init.h index 86ddd2cb65f8..546be1a35250 100644 --- a/arch/sw_64/include/asm/sw64_init.h +++ b/arch/sw_64/include/asm/sw64_init.h @@ -43,6 +43,13 @@ extern struct sw64_chip_ops *sw64_chip; extern struct sw64_chip_init_ops *sw64_chip_init; #ifdef CONFIG_PM extern struct syscore_ops io_syscore_ops; + +#define PME_CLEAR 0 +#define PME_WFW 1 /* wait for wake */ +#define PME_PENDING 2 + +extern int pme_state; + #endif DECLARE_PER_CPU(unsigned long, hard_node_id); diff --git a/arch/sw_64/include/asm/uncore_io_junzhang.h b/arch/sw_64/include/asm/uncore_io_junzhang.h index 37cfe1fd6807..c0f759bbe740 100644 --- a/arch/sw_64/include/asm/uncore_io_junzhang.h +++ b/arch/sw_64/include/asm/uncore_io_junzhang.h @@ -116,6 +116,9 @@ enum { SI_FAULT_INT_EN = SPBU_BASE | 0x3200UL, ADR_CTL = SPBU_BASE | 0x3600UL, MC_ONLINE = SPBU_BASE | 0x3780UL, + CLK_CTL = SPBU_BASE | 0x3b80UL, + CLU_LV2_SELH = SPBU_BASE | 0x3a00UL, + CLU_LV2_SELL = SPBU_BASE | 0x3b00UL, PIU_TOP0_CONFIG = SPBU_BASE | 0x4c80UL, PIU_TOP1_CONFIG = SPBU_BASE | 0x4d00UL, SOFT_INFO0 = SPBU_BASE | 0xa000UL, diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 9cb7c64b3afe..cdb691692125 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -60,12 +60,26 @@ void smp_callin(void) { int cpuid = smp_processor_id(); +#ifdef CONFIG_SUBARCH_C4 + /* LV2 select PLL1 */ + int i, cpu_num; + + cpu_num = sw64_chip->get_cpu_num(); + + for (i = 0; i < cpu_num; i++) { + sw64_io_write(i, CLU_LV2_SELH, -1UL); + sw64_io_write(i, CLU_LV2_SELL, -1UL); + udelay(1000); + } +#endif + local_irq_disable(); if (cpu_online(cpuid)) { pr_err("??, cpu 0x%x already present??\n", cpuid); BUG(); } + set_cpu_online(cpuid, true); /* Set trap vectors. */ @@ -322,8 +336,10 @@ 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 /* send reset signal */ if (is_in_host()) { reset_cpu(cpu); @@ -602,6 +618,22 @@ void __cpu_die(unsigned int cpu) void arch_cpu_idle_dead(void) { +#ifdef CONFIG_SUBARCH_C4 + /* LV2 select PLL0 */ + int cpuid = smp_processor_id(); + int core_id = rcid_to_core_id(cpu_to_rcid(cpuid)); + int node_id = rcid_to_domain_id(cpu_to_rcid(cpuid)); + unsigned long value; + + if (core_id > 31) { + value = 1UL << (2 * (core_id - 32)); + sw64_io_write(node_id, CLU_LV2_SELH, value); + } else { + value = 1UL << (2 * core_id); + sw64_io_write(node_id, CLU_LV2_SELL, value); + } +#endif + idle_task_exit(); mb(); __this_cpu_write(cpu_state, CPU_DEAD); @@ -616,10 +648,18 @@ 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 + #else asm volatile("memb"); asm volatile("halt"); diff --git a/arch/sw_64/kernel/suspend.c b/arch/sw_64/kernel/suspend.c index 27a240e66149..97e5478a678f 100644 --- a/arch/sw_64/kernel/suspend.c +++ b/arch/sw_64/kernel/suspend.c @@ -4,6 +4,8 @@ #include #include +#define PME_EN 0x2 + struct processor_state suspend_state; static int native_suspend_state_valid(suspend_state_t pm_state) @@ -36,7 +38,15 @@ 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 + wrtp(current_thread_info()->pcb.tp); disable_local_timer(); diff --git a/drivers/irqchip/irq-sunway-cpu.c b/drivers/irqchip/irq-sunway-cpu.c index 3f5151b9b31d..2f4880036a2c 100644 --- a/drivers/irqchip/irq-sunway-cpu.c +++ b/drivers/irqchip/irq-sunway-cpu.c @@ -153,12 +153,28 @@ static void handle_dev_int(struct pt_regs *regs) sw64_io_write(node, DEV_INT_CONFIG, config_val); } +int pme_state; + asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned long irq_arg, struct pt_regs *regs) { struct pt_regs *old_regs; extern char __idle_start[], __idle_end[]; +#ifdef CONFIG_SUBARCH_C4 + if (pme_state == PME_WFW) { + pme_state = PME_PENDING; + return; + } + + if (pme_state == PME_PENDING) { + old_regs = set_irq_regs(regs); + handle_device_interrupt(vector); + set_irq_regs(old_regs); + pme_state = PME_CLEAR; + } +#endif + if (is_guest_or_emul()) { if ((type & 0xffff) > 15) { vector = type; -- Gitee From bb2c1f347836e9bfc7b9d94000afe29796d46b7f Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 27 Mar 2024 17:02:47 +0800 Subject: [PATCH 63/98] sw64: store topology and numa info by each cpu itself Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Let the boot cpu calculate and store the topology and numa info of a non-boot cpu after it is booted could cause some data issue. Now the non-boot cpu will calculate and store its own topology and numa info during initialization process. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/smp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index cdb691692125..f3ac8a899976 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -102,6 +102,8 @@ void smp_callin(void) per_cpu(cpu_state, cpuid) = CPU_ONLINE; per_cpu(hard_node_id, cpuid) = rcid_to_domain_id(cpu_to_rcid(cpuid)); + store_cpu_topology(cpuid); + numa_add_cpu(cpuid); /* Must have completely accurate bogos. */ local_irq_enable(); @@ -149,8 +151,6 @@ static int secondary_cpu_start(int cpuid, struct task_struct *idle) return -1; started: - store_cpu_topology(cpuid); - numa_add_cpu(cpuid); return 0; } -- Gitee From c295995686fe464b7656e7c5b3274e7376b05b0f Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 27 Mar 2024 20:45:28 +0800 Subject: [PATCH 64/98] sw64: choose lib at compile time Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Compile both SISD and SIMD version of memcpy/memset like libs and let the compiler optimize out the unused version based on kernel config. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/lib/Makefile | 12 +++------ arch/sw_64/lib/clear_user.S | 10 +++----- arch/sw_64/lib/copy_user.S | 10 +++----- arch/sw_64/lib/memcpy.S | 15 ++++------- arch/sw_64/lib/memset.S | 50 +++---------------------------------- arch/sw_64/lib/string.c | 8 ++++++ arch/sw_64/lib/uaccess.c | 8 ++++++ 7 files changed, 37 insertions(+), 76 deletions(-) diff --git a/arch/sw_64/lib/Makefile b/arch/sw_64/lib/Makefile index 2028d61dd195..6e428f2dcd05 100644 --- a/arch/sw_64/lib/Makefile +++ b/arch/sw_64/lib/Makefile @@ -22,20 +22,16 @@ lib-y = __divlu.o __remlu.o __divwu.o __remwu.o \ lib-clear_page-y := clear_page.o lib-clear_page-$(CONFIG_DEEP_CLEAR_PAGE) := deep-clear_page.o -lib-clear_user-y := clear_user.o -lib-clear_user-$(CONFIG_DEEP_CLEAR_USER) := deep-clear_user-hw_una.o deep-clear_user-sw_una.o +lib-clear_user-y := clear_user.o deep-clear_user-hw_una.o deep-clear_user-sw_una.o lib-copy_page-y := copy_page.o lib-copy_page-$(CONFIG_DEEP_COPY_PAGE) := deep-copy_page.o -lib-copy_user-y := copy_user.o -lib-copy_user-$(CONFIG_DEEP_COPY_USER) := deep-copy_user-hw_una.o deep-copy_user-sw_una.o +lib-copy_user-y := copy_user.o deep-copy_user-hw_una.o deep-copy_user-sw_una.o -lib-memcpy-y := memcpy.o -lib-memcpy-$(CONFIG_DEEP_MEMCPY) := deep-memcpy-hw_una.o deep-memcpy-sw_una.o +lib-memcpy-y := memcpy.o deep-memcpy-hw_una.o deep-memcpy-sw_una.o -lib-memset-y := memset.o -lib-memset-$(CONFIG_DEEP_MEMSET) := deep-memset-hw_una.o deep-memset-sw_una.o +lib-memset-y := memset.o deep-memset-hw_una.o deep-memset-sw_una.o lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o diff --git a/arch/sw_64/lib/clear_user.S b/arch/sw_64/lib/clear_user.S index 5ac77fc8ca0d..e006e0e6ceab 100644 --- a/arch/sw_64/lib/clear_user.S +++ b/arch/sw_64/lib/clear_user.S @@ -10,7 +10,6 @@ * stuff. * */ -#include /* Allow an exception for an insn; exit if we get one. */ #define EX(x,y...) \ 99: x,##y; \ @@ -23,11 +22,11 @@ .set noreorder .align 4 - .globl __clear_user - .ent __clear_user + .globl ____clear_user_sisd + .ent ____clear_user_sisd .frame $30, 0, $26 .prologue 0 -__clear_user: +____clear_user_sisd: and $17, $17, $0 and $16, 7, $4 beq $0, $zerolength @@ -98,5 +97,4 @@ $tail: clr $0 ret $31, ($26), 1 - .end __clear_user - EXPORT_SYMBOL(__clear_user) + .end ____clear_user_sisd diff --git a/arch/sw_64/lib/copy_user.S b/arch/sw_64/lib/copy_user.S index 2c3dd0b5656c..ac1336641b9f 100644 --- a/arch/sw_64/lib/copy_user.S +++ b/arch/sw_64/lib/copy_user.S @@ -9,7 +9,6 @@ * only _after_ a successful copy). There is also some rather minor * exception setup stuff.. */ -#include /* Allow an exception for an insn; exit if we get one. */ #define EXI(x,y...) \ 99: x,##y; \ @@ -27,9 +26,9 @@ .set noat .align 4 - .globl __copy_user - .ent __copy_user -__copy_user: + .globl ____copy_user_sisd + .ent ____copy_user_sisd +____copy_user_sisd: .prologue 0 and $18, $18, $0 and $16, 7, $3 @@ -102,5 +101,4 @@ $exitin: $exitout: ret $31, ($26), 1 - .end __copy_user - EXPORT_SYMBOL(__copy_user) + .end ____copy_user_sisd diff --git a/arch/sw_64/lib/memcpy.S b/arch/sw_64/lib/memcpy.S index 31c422b393ee..4a29ab6a6eab 100644 --- a/arch/sw_64/lib/memcpy.S +++ b/arch/sw_64/lib/memcpy.S @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Reasonably optimized memcpy() routine for the sw64 + * Reasonably optimized ____memcpy_sisd() routine for the sw64 * * - memory accessed as aligned quadwords only * - uses bcmpge to compare 8 bytes in parallel @@ -8,14 +8,13 @@ * Temp usage notes: * $1, $2, - scratch */ -#include .set noreorder .set noat .align 4 - .globl memcpy - .ent memcpy -memcpy: + .globl ____memcpy_sisd + .ent ____memcpy_sisd +____memcpy_sisd: .frame $30, 0, $26, 0 .prologue 0 @@ -194,8 +193,4 @@ $misalign_byte: $nomoredata: ret $31, ($26), 1 - .end memcpy - EXPORT_SYMBOL(memcpy) -/* For backwards module compatibility. */ -__memcpy = memcpy -.globl __memcpy + .end ____memcpy_sisd diff --git a/arch/sw_64/lib/memset.S b/arch/sw_64/lib/memset.S index dbc4d775c7ea..e5180adb4389 100644 --- a/arch/sw_64/lib/memset.S +++ b/arch/sw_64/lib/memset.S @@ -13,35 +13,16 @@ * hand, so they might well be incorrect, please do tell me about it..) */ -#include - .set noat .set noreorder .text - .globl memset - .globl __memset - .globl ___memset - .globl __memsetw - .globl __constant_c_memset + .globl ____constant_c_memset_sisd - .ent ___memset -.align 5 -___memset: + .ent ____constant_c_memset_sisd .frame $30, 0, $26, 0 .prologue 0 - - and $17, 255, $1 - inslb $17, 1, $17 - bis $17, $1, $17 - sll $17, 16, $1 - - bis $17, $1, $17 - sll $17, 32, $1 - bis $17, $1, $17 - ldl_u $31, 0($30) - .align 5 -__constant_c_memset: +____constant_c_memset_sisd: addl $18, $16, $6 bis $16, $16, $0 xor $16, $6, $1 @@ -127,27 +108,4 @@ within_one_quad_loop: end: ret $31, ($26), 1 - .end ___memset - EXPORT_SYMBOL(___memset) - - .align 5 - .ent __memsetw -__memsetw: - .prologue 0 - - inslh $17, 0, $1 - inslh $17, 2, $2 - inslh $17, 4, $3 - or $1, $2, $1 - inslh $17, 6, $4 - or $1, $3, $1 - or $1, $4, $17 - br __constant_c_memset - - .end __memsetw - EXPORT_SYMBOL(__memsetw) - -memset = ___memset -EXPORT_SYMBOL(memset) -__memset = ___memset -EXPORT_SYMBOL(__memset) + .end ____constant_c_memset_sisd diff --git a/arch/sw_64/lib/string.c b/arch/sw_64/lib/string.c index 4d10e0639bb8..2adca19a0fb3 100644 --- a/arch/sw_64/lib/string.c +++ b/arch/sw_64/lib/string.c @@ -4,11 +4,15 @@ #include +extern void *____memcpy_sisd(void *dest, const void *src, size_t n); extern void *____memcpy_hw_una(void *dest, const void *src, size_t n); extern void *____memcpy_sw_una(void *dest, const void *src, size_t n); static inline void *____memcpy(void *dest, const void *src, size_t n) { + if (!IS_ENABLED(CONFIG_DEEP_MEMCPY)) + return ____memcpy_sisd(dest, src, n); + if (static_branch_likely(&core_hw_una_enabled)) return ____memcpy_hw_una(dest, src, n); else @@ -28,11 +32,15 @@ void *__memcpy(void *dest, const void *src, size_t n) } EXPORT_SYMBOL(__memcpy); +extern void *____constant_c_memset_sisd(void *s, unsigned long c, size_t n); extern void *____constant_c_memset_hw_una(void *s, unsigned long c, size_t n); extern void *____constant_c_memset_sw_una(void *s, unsigned long c, size_t n); static inline void *____constant_c_memset(void *s, unsigned long c, size_t n) { + if (!IS_ENABLED(CONFIG_DEEP_MEMSET)) + return ____constant_c_memset_sisd(s, c, n); + if (static_branch_likely(&core_hw_una_enabled)) return ____constant_c_memset_hw_una(s, c, n); else diff --git a/arch/sw_64/lib/uaccess.c b/arch/sw_64/lib/uaccess.c index 56d3075aedbb..72bd66f5b48a 100644 --- a/arch/sw_64/lib/uaccess.c +++ b/arch/sw_64/lib/uaccess.c @@ -4,11 +4,15 @@ #include +extern long ____copy_user_sisd(void *to, const void *from, long len); extern long ____copy_user_hw_una(void *to, const void *from, long len); extern long ____copy_user_sw_una(void *to, const void *from, long len); long __copy_user(void *to, const void *from, long len) { + if (!IS_ENABLED(CONFIG_DEEP_COPY_USER)) + return ____copy_user_sisd(to, from, len); + if (static_branch_likely(&core_hw_una_enabled)) return ____copy_user_hw_una(to, from, len); else @@ -16,11 +20,15 @@ long __copy_user(void *to, const void *from, long len) } EXPORT_SYMBOL(__copy_user); +extern long ____clear_user_sisd(void __user *to, long len); extern long ____clear_user_hw_una(void __user *to, long len); extern long ____clear_user_sw_una(void __user *to, long len); long __clear_user(void __user *to, long len) { + if (!IS_ENABLED(CONFIG_DEEP_CLEAR_USER)) + return ____clear_user_sisd(to, len); + if (static_branch_likely(&core_hw_una_enabled)) return ____clear_user_hw_una(to, len); else -- Gitee From 3d6702788b1fede5e65b779baacb559afc4786f8 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 27 Mar 2024 21:07:16 +0800 Subject: [PATCH 65/98] sw64: rename copy and set lib files Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Rename the memcpy/memset like lib files to help understand their differences. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/lib/Makefile | 8 ++++---- ...ear_user-sw_una.S => deep-clear_user-force_ali_addr.S} | 2 +- ...clear_user-hw_una.S => deep-clear_user-no_una_check.S} | 2 +- ...opy_template.S => deep-copy_template-force_ali_addr.S} | 0 ...py_template_c4.S => deep-copy_template-no_una_check.S} | 0 ...copy_user-sw_una.S => deep-copy_user-force_ali_addr.S} | 2 +- ...p-copy_user-hw_una.S => deep-copy_user-no_una_check.S} | 2 +- ...{deep-memcpy-sw_una.S => deep-memcpy-force_ali_addr.S} | 2 +- .../{deep-memcpy-hw_una.S => deep-memcpy-no_una_check.S} | 2 +- ...{deep-memset-sw_una.S => deep-memset-force_ali_addr.S} | 2 +- .../{deep-memset-hw_una.S => deep-memset-no_una_check.S} | 2 +- ...-set_template.S => deep-set_template-force_ali_addr.S} | 0 ...set_template_c4.S => deep-set_template-no_una_check.S} | 0 13 files changed, 12 insertions(+), 12 deletions(-) rename arch/sw_64/lib/{deep-clear_user-sw_una.S => deep-clear_user-force_ali_addr.S} (95%) rename arch/sw_64/lib/{deep-clear_user-hw_una.S => deep-clear_user-no_una_check.S} (95%) rename arch/sw_64/lib/{deep-copy_template.S => deep-copy_template-force_ali_addr.S} (100%) rename arch/sw_64/lib/{deep-copy_template_c4.S => deep-copy_template-no_una_check.S} (100%) rename arch/sw_64/lib/{deep-copy_user-sw_una.S => deep-copy_user-force_ali_addr.S} (94%) rename arch/sw_64/lib/{deep-copy_user-hw_una.S => deep-copy_user-no_una_check.S} (94%) rename arch/sw_64/lib/{deep-memcpy-sw_una.S => deep-memcpy-force_ali_addr.S} (82%) rename arch/sw_64/lib/{deep-memcpy-hw_una.S => deep-memcpy-no_una_check.S} (83%) rename arch/sw_64/lib/{deep-memset-sw_una.S => deep-memset-force_ali_addr.S} (95%) rename arch/sw_64/lib/{deep-memset-hw_una.S => deep-memset-no_una_check.S} (95%) rename arch/sw_64/lib/{deep-set_template.S => deep-set_template-force_ali_addr.S} (100%) rename arch/sw_64/lib/{deep-set_template_c4.S => deep-set_template-no_una_check.S} (100%) diff --git a/arch/sw_64/lib/Makefile b/arch/sw_64/lib/Makefile index 6e428f2dcd05..8d3bc1fdd604 100644 --- a/arch/sw_64/lib/Makefile +++ b/arch/sw_64/lib/Makefile @@ -22,16 +22,16 @@ lib-y = __divlu.o __remlu.o __divwu.o __remwu.o \ lib-clear_page-y := clear_page.o lib-clear_page-$(CONFIG_DEEP_CLEAR_PAGE) := deep-clear_page.o -lib-clear_user-y := clear_user.o deep-clear_user-hw_una.o deep-clear_user-sw_una.o +lib-clear_user-y := clear_user.o deep-clear_user-no_una_check.o deep-clear_user-force_ali_addr.o lib-copy_page-y := copy_page.o lib-copy_page-$(CONFIG_DEEP_COPY_PAGE) := deep-copy_page.o -lib-copy_user-y := copy_user.o deep-copy_user-hw_una.o deep-copy_user-sw_una.o +lib-copy_user-y := copy_user.o deep-copy_user-no_una_check.o deep-copy_user-force_ali_addr.o -lib-memcpy-y := memcpy.o deep-memcpy-hw_una.o deep-memcpy-sw_una.o +lib-memcpy-y := memcpy.o deep-memcpy-no_una_check.o deep-memcpy-force_ali_addr.o -lib-memset-y := memset.o deep-memset-hw_una.o deep-memset-sw_una.o +lib-memset-y := memset.o deep-memset-no_una_check.o deep-memset-force_ali_addr.o lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o diff --git a/arch/sw_64/lib/deep-clear_user-sw_una.S b/arch/sw_64/lib/deep-clear_user-force_ali_addr.S similarity index 95% rename from arch/sw_64/lib/deep-clear_user-sw_una.S rename to arch/sw_64/lib/deep-clear_user-force_ali_addr.S index e48e5be9efac..adca61aede83 100644 --- a/arch/sw_64/lib/deep-clear_user-sw_una.S +++ b/arch/sw_64/lib/deep-clear_user-force_ali_addr.S @@ -34,7 +34,7 @@ ____clear_user_sw_una: bis $31, $31, $7 mov $17, $18 bis $31, $31, $17 -#include "deep-set_template.S" +#include "deep-set_template-force_ali_addr.S" 255: bis $31, $18, $0 beq $7, $return diff --git a/arch/sw_64/lib/deep-clear_user-hw_una.S b/arch/sw_64/lib/deep-clear_user-no_una_check.S similarity index 95% rename from arch/sw_64/lib/deep-clear_user-hw_una.S rename to arch/sw_64/lib/deep-clear_user-no_una_check.S index 81c04dd0f056..bbc84c0776aa 100644 --- a/arch/sw_64/lib/deep-clear_user-hw_una.S +++ b/arch/sw_64/lib/deep-clear_user-no_una_check.S @@ -34,7 +34,7 @@ ____clear_user_hw_una: bis $31, $31, $7 mov $17, $18 bis $31, $31, $17 -#include "deep-set_template_c4.S" +#include "deep-set_template-no_una_check.S" 255: bis $31, $18, $0 beq $7, $return diff --git a/arch/sw_64/lib/deep-copy_template.S b/arch/sw_64/lib/deep-copy_template-force_ali_addr.S similarity index 100% rename from arch/sw_64/lib/deep-copy_template.S rename to arch/sw_64/lib/deep-copy_template-force_ali_addr.S diff --git a/arch/sw_64/lib/deep-copy_template_c4.S b/arch/sw_64/lib/deep-copy_template-no_una_check.S similarity index 100% rename from arch/sw_64/lib/deep-copy_template_c4.S rename to arch/sw_64/lib/deep-copy_template-no_una_check.S diff --git a/arch/sw_64/lib/deep-copy_user-sw_una.S b/arch/sw_64/lib/deep-copy_user-force_ali_addr.S similarity index 94% rename from arch/sw_64/lib/deep-copy_user-sw_una.S rename to arch/sw_64/lib/deep-copy_user-force_ali_addr.S index a359aee65583..f3c84c93d71b 100644 --- a/arch/sw_64/lib/deep-copy_user-sw_una.S +++ b/arch/sw_64/lib/deep-copy_user-force_ali_addr.S @@ -25,7 +25,7 @@ ____copy_user_sw_una: .prologue 0 .set noreorder bis $31, $31, $7 -#include "deep-copy_template.S" +#include "deep-copy_template-force_ali_addr.S" 255: bis $31, $18, $0 beq $7, $return diff --git a/arch/sw_64/lib/deep-copy_user-hw_una.S b/arch/sw_64/lib/deep-copy_user-no_una_check.S similarity index 94% rename from arch/sw_64/lib/deep-copy_user-hw_una.S rename to arch/sw_64/lib/deep-copy_user-no_una_check.S index b411a7ed52c2..c913d85cb469 100644 --- a/arch/sw_64/lib/deep-copy_user-hw_una.S +++ b/arch/sw_64/lib/deep-copy_user-no_una_check.S @@ -25,7 +25,7 @@ ____copy_user_hw_una: .prologue 0 .set noreorder bis $31, $31, $7 -#include "deep-copy_template_c4.S" +#include "deep-copy_template-no_una_check.S" 255: bis $31, $18, $0 beq $7, $return diff --git a/arch/sw_64/lib/deep-memcpy-sw_una.S b/arch/sw_64/lib/deep-memcpy-force_ali_addr.S similarity index 82% rename from arch/sw_64/lib/deep-memcpy-sw_una.S rename to arch/sw_64/lib/deep-memcpy-force_ali_addr.S index 75aa10a42b52..c5629b3b4e06 100644 --- a/arch/sw_64/lib/deep-memcpy-sw_una.S +++ b/arch/sw_64/lib/deep-memcpy-force_ali_addr.S @@ -9,7 +9,7 @@ ____memcpy_sw_una: .frame $30, 0, $26, 0 .prologue 0 mov $16, $0 -#include "deep-copy_template.S" +#include "deep-copy_template-force_ali_addr.S" 255: ret .end ____memcpy_sw_una diff --git a/arch/sw_64/lib/deep-memcpy-hw_una.S b/arch/sw_64/lib/deep-memcpy-no_una_check.S similarity index 83% rename from arch/sw_64/lib/deep-memcpy-hw_una.S rename to arch/sw_64/lib/deep-memcpy-no_una_check.S index ccdfaed4b8ab..da61247c7eb3 100644 --- a/arch/sw_64/lib/deep-memcpy-hw_una.S +++ b/arch/sw_64/lib/deep-memcpy-no_una_check.S @@ -9,7 +9,7 @@ ____memcpy_hw_una: .frame $30, 0, $26, 0 .prologue 0 mov $16, $0 -#include "deep-copy_template_c4.S" +#include "deep-copy_template-no_una_check.S" 255: ret .end ____memcpy_hw_una diff --git a/arch/sw_64/lib/deep-memset-sw_una.S b/arch/sw_64/lib/deep-memset-force_ali_addr.S similarity index 95% rename from arch/sw_64/lib/deep-memset-sw_una.S rename to arch/sw_64/lib/deep-memset-force_ali_addr.S index b354b36dbbc9..61e3ffdd0e5b 100644 --- a/arch/sw_64/lib/deep-memset-sw_una.S +++ b/arch/sw_64/lib/deep-memset-force_ali_addr.S @@ -45,7 +45,7 @@ ____constant_c_memset_sw_una: #ifdef CONFIG_SUBARCH_C4 csrr $6, CSR_WR_FREGS #endif -#include "deep-set_template.S" +#include "deep-set_template-force_ali_addr.S" 255: #ifdef CONFIG_SUBARCH_C4 csrw $6, CSR_WR_FREGS diff --git a/arch/sw_64/lib/deep-memset-hw_una.S b/arch/sw_64/lib/deep-memset-no_una_check.S similarity index 95% rename from arch/sw_64/lib/deep-memset-hw_una.S rename to arch/sw_64/lib/deep-memset-no_una_check.S index dff6b2c2003c..aa43d7b7df08 100644 --- a/arch/sw_64/lib/deep-memset-hw_una.S +++ b/arch/sw_64/lib/deep-memset-no_una_check.S @@ -45,7 +45,7 @@ ____constant_c_memset_hw_una: #ifdef CONFIG_SUBARCH_C4 csrr $6, CSR_WR_FREGS #endif -#include "deep-set_template_c4.S" +#include "deep-set_template-no_una_check.S" 255: #ifdef CONFIG_SUBARCH_C4 csrw $6, CSR_WR_FREGS diff --git a/arch/sw_64/lib/deep-set_template.S b/arch/sw_64/lib/deep-set_template-force_ali_addr.S similarity index 100% rename from arch/sw_64/lib/deep-set_template.S rename to arch/sw_64/lib/deep-set_template-force_ali_addr.S diff --git a/arch/sw_64/lib/deep-set_template_c4.S b/arch/sw_64/lib/deep-set_template-no_una_check.S similarity index 100% rename from arch/sw_64/lib/deep-set_template_c4.S rename to arch/sw_64/lib/deep-set_template-no_una_check.S -- Gitee From 91b709fff62ce21fdd08eb3aa2b2f1650b0b39d2 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 27 Mar 2024 21:16:10 +0800 Subject: [PATCH 66/98] sw64: rename copy and set lib functions Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Rename memcpy/memset like lib functions to help understand their differences. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/lib/deep-clear_user-force_ali_addr.S | 8 ++++---- arch/sw_64/lib/deep-clear_user-no_una_check.S | 8 ++++---- arch/sw_64/lib/deep-copy_user-force_ali_addr.S | 8 ++++---- arch/sw_64/lib/deep-copy_user-no_una_check.S | 8 ++++---- arch/sw_64/lib/deep-memcpy-force_ali_addr.S | 8 ++++---- arch/sw_64/lib/deep-memcpy-no_una_check.S | 8 ++++---- arch/sw_64/lib/deep-memset-force_ali_addr.S | 8 ++++---- arch/sw_64/lib/deep-memset-no_una_check.S | 8 ++++---- arch/sw_64/lib/string.c | 16 ++++++++-------- arch/sw_64/lib/uaccess.c | 16 ++++++++-------- 10 files changed, 48 insertions(+), 48 deletions(-) diff --git a/arch/sw_64/lib/deep-clear_user-force_ali_addr.S b/arch/sw_64/lib/deep-clear_user-force_ali_addr.S index adca61aede83..24b1f03b6a4d 100644 --- a/arch/sw_64/lib/deep-clear_user-force_ali_addr.S +++ b/arch/sw_64/lib/deep-clear_user-force_ali_addr.S @@ -27,9 +27,9 @@ * $18: bytes left to copy * */ - .globl ____clear_user_sw_una - .ent ____clear_user_sw_una -____clear_user_sw_una: + .globl ____clear_user_simd_force_ali_addr + .ent ____clear_user_simd_force_ali_addr +____clear_user_simd_force_ali_addr: .prologue 0 bis $31, $31, $7 mov $17, $18 @@ -44,4 +44,4 @@ $restore_simd: $return: ret - .end ____clear_user_sw_una + .end ____clear_user_simd_force_ali_addr diff --git a/arch/sw_64/lib/deep-clear_user-no_una_check.S b/arch/sw_64/lib/deep-clear_user-no_una_check.S index bbc84c0776aa..b6c23a72702b 100644 --- a/arch/sw_64/lib/deep-clear_user-no_una_check.S +++ b/arch/sw_64/lib/deep-clear_user-no_una_check.S @@ -27,9 +27,9 @@ * $18: bytes left to copy * */ - .globl ____clear_user_hw_una - .ent ____clear_user_hw_una -____clear_user_hw_una: + .globl ____clear_user_simd_no_una_check + .ent ____clear_user_simd_no_una_check +____clear_user_simd_no_una_check: .prologue 0 bis $31, $31, $7 mov $17, $18 @@ -44,4 +44,4 @@ $restore_simd: $return: ret - .end ____clear_user_hw_una + .end ____clear_user_simd_no_una_check diff --git a/arch/sw_64/lib/deep-copy_user-force_ali_addr.S b/arch/sw_64/lib/deep-copy_user-force_ali_addr.S index f3c84c93d71b..e04180acfc41 100644 --- a/arch/sw_64/lib/deep-copy_user-force_ali_addr.S +++ b/arch/sw_64/lib/deep-copy_user-force_ali_addr.S @@ -19,9 +19,9 @@ * $18: bytes left to copy * */ - .globl ____copy_user_sw_una - .ent ____copy_user_sw_una -____copy_user_sw_una: + .globl ____copy_user_simd_force_ali_addr + .ent ____copy_user_simd_force_ali_addr +____copy_user_simd_force_ali_addr: .prologue 0 .set noreorder bis $31, $31, $7 @@ -41,4 +41,4 @@ $restore_simd: $return: ret - .end ____copy_user_sw_una + .end ____copy_user_simd_force_ali_addr diff --git a/arch/sw_64/lib/deep-copy_user-no_una_check.S b/arch/sw_64/lib/deep-copy_user-no_una_check.S index c913d85cb469..ec3e0f095b2d 100644 --- a/arch/sw_64/lib/deep-copy_user-no_una_check.S +++ b/arch/sw_64/lib/deep-copy_user-no_una_check.S @@ -19,9 +19,9 @@ * $18: bytes left to copy * */ - .globl ____copy_user_hw_una - .ent ____copy_user_hw_una -____copy_user_hw_una: + .globl ____copy_user_simd_no_una_check + .ent ____copy_user_simd_no_una_check +____copy_user_simd_no_una_check: .prologue 0 .set noreorder bis $31, $31, $7 @@ -37,4 +37,4 @@ $restore_simd: $return: ret - .end ____copy_user_hw_una + .end ____copy_user_simd_no_una_check diff --git a/arch/sw_64/lib/deep-memcpy-force_ali_addr.S b/arch/sw_64/lib/deep-memcpy-force_ali_addr.S index c5629b3b4e06..3b9652fd7ac4 100644 --- a/arch/sw_64/lib/deep-memcpy-force_ali_addr.S +++ b/arch/sw_64/lib/deep-memcpy-force_ali_addr.S @@ -3,13 +3,13 @@ #define FIXUP_LDST(x, y) \ x, y - .globl ____memcpy_sw_una - .ent ____memcpy_sw_una -____memcpy_sw_una: + .globl ____memcpy_simd_force_ali_addr + .ent ____memcpy_simd_force_ali_addr +____memcpy_simd_force_ali_addr: .frame $30, 0, $26, 0 .prologue 0 mov $16, $0 #include "deep-copy_template-force_ali_addr.S" 255: ret - .end ____memcpy_sw_una + .end ____memcpy_simd_force_ali_addr diff --git a/arch/sw_64/lib/deep-memcpy-no_una_check.S b/arch/sw_64/lib/deep-memcpy-no_una_check.S index da61247c7eb3..47d0b683e45e 100644 --- a/arch/sw_64/lib/deep-memcpy-no_una_check.S +++ b/arch/sw_64/lib/deep-memcpy-no_una_check.S @@ -3,13 +3,13 @@ #define FIXUP_LDST(x, y) \ x, y - .globl ____memcpy_hw_una - .ent ____memcpy_hw_una -____memcpy_hw_una: + .globl ____memcpy_simd_no_una_check + .ent ____memcpy_simd_no_una_check +____memcpy_simd_no_una_check: .frame $30, 0, $26, 0 .prologue 0 mov $16, $0 #include "deep-copy_template-no_una_check.S" 255: ret - .end ____memcpy_hw_una + .end ____memcpy_simd_no_una_check diff --git a/arch/sw_64/lib/deep-memset-force_ali_addr.S b/arch/sw_64/lib/deep-memset-force_ali_addr.S index 61e3ffdd0e5b..cbb0130100dd 100644 --- a/arch/sw_64/lib/deep-memset-force_ali_addr.S +++ b/arch/sw_64/lib/deep-memset-force_ali_addr.S @@ -35,11 +35,11 @@ .text .align 4 - .globl ____constant_c_memset_sw_una - .ent ____constant_c_memset_sw_una + .globl ____constant_c_memset_simd_force_ali_addr + .ent ____constant_c_memset_simd_force_ali_addr .frame $30, 0, $26, 0 .prologue 0 -____constant_c_memset_sw_una: +____constant_c_memset_simd_force_ali_addr: bis $31, $31, $7 bis $31, $16, $0 #ifdef CONFIG_SUBARCH_C4 @@ -51,4 +51,4 @@ ____constant_c_memset_sw_una: csrw $6, CSR_WR_FREGS #endif ret - .end ____constant_c_memset_sw_una + .end ____constant_c_memset_simd_force_ali_addr diff --git a/arch/sw_64/lib/deep-memset-no_una_check.S b/arch/sw_64/lib/deep-memset-no_una_check.S index aa43d7b7df08..91525bd67790 100644 --- a/arch/sw_64/lib/deep-memset-no_una_check.S +++ b/arch/sw_64/lib/deep-memset-no_una_check.S @@ -35,11 +35,11 @@ .text .align 4 - .globl ____constant_c_memset_hw_una - .ent ____constant_c_memset_hw_una + .globl ____constant_c_memset_simd_no_una_check + .ent ____constant_c_memset_simd_no_una_check .frame $30, 0, $26, 0 .prologue 0 -____constant_c_memset_hw_una: +____constant_c_memset_simd_no_una_check: bis $31, $31, $7 bis $31, $16, $0 #ifdef CONFIG_SUBARCH_C4 @@ -51,4 +51,4 @@ ____constant_c_memset_hw_una: csrw $6, CSR_WR_FREGS #endif ret - .end ____constant_c_memset_hw_una + .end ____constant_c_memset_simd_no_una_check diff --git a/arch/sw_64/lib/string.c b/arch/sw_64/lib/string.c index 2adca19a0fb3..ef7439b3715b 100644 --- a/arch/sw_64/lib/string.c +++ b/arch/sw_64/lib/string.c @@ -5,8 +5,8 @@ #include extern void *____memcpy_sisd(void *dest, const void *src, size_t n); -extern void *____memcpy_hw_una(void *dest, const void *src, size_t n); -extern void *____memcpy_sw_una(void *dest, const void *src, size_t n); +extern void *____memcpy_simd_no_una_check(void *dest, const void *src, size_t n); +extern void *____memcpy_simd_force_ali_addr(void *dest, const void *src, size_t n); static inline void *____memcpy(void *dest, const void *src, size_t n) { @@ -14,9 +14,9 @@ static inline void *____memcpy(void *dest, const void *src, size_t n) return ____memcpy_sisd(dest, src, n); if (static_branch_likely(&core_hw_una_enabled)) - return ____memcpy_hw_una(dest, src, n); + return ____memcpy_simd_no_una_check(dest, src, n); else - return ____memcpy_sw_una(dest, src, n); + return ____memcpy_simd_force_ali_addr(dest, src, n); } void *memcpy(void *dest, const void *src, size_t n) @@ -33,8 +33,8 @@ void *__memcpy(void *dest, const void *src, size_t n) EXPORT_SYMBOL(__memcpy); extern void *____constant_c_memset_sisd(void *s, unsigned long c, size_t n); -extern void *____constant_c_memset_hw_una(void *s, unsigned long c, size_t n); -extern void *____constant_c_memset_sw_una(void *s, unsigned long c, size_t n); +extern void *____constant_c_memset_simd_no_una_check(void *s, unsigned long c, size_t n); +extern void *____constant_c_memset_simd_force_ali_addr(void *s, unsigned long c, size_t n); static inline void *____constant_c_memset(void *s, unsigned long c, size_t n) { @@ -42,9 +42,9 @@ static inline void *____constant_c_memset(void *s, unsigned long c, size_t n) return ____constant_c_memset_sisd(s, c, n); if (static_branch_likely(&core_hw_una_enabled)) - return ____constant_c_memset_hw_una(s, c, n); + return ____constant_c_memset_simd_no_una_check(s, c, n); else - return ____constant_c_memset_sw_una(s, c, n); + return ____constant_c_memset_simd_force_ali_addr(s, c, n); } void *__constant_c_memset(void *s, unsigned long c, size_t n) diff --git a/arch/sw_64/lib/uaccess.c b/arch/sw_64/lib/uaccess.c index 72bd66f5b48a..f8efa5ad853d 100644 --- a/arch/sw_64/lib/uaccess.c +++ b/arch/sw_64/lib/uaccess.c @@ -5,8 +5,8 @@ #include extern long ____copy_user_sisd(void *to, const void *from, long len); -extern long ____copy_user_hw_una(void *to, const void *from, long len); -extern long ____copy_user_sw_una(void *to, const void *from, long len); +extern long ____copy_user_simd_no_una_check(void *to, const void *from, long len); +extern long ____copy_user_simd_force_ali_addr(void *to, const void *from, long len); long __copy_user(void *to, const void *from, long len) { @@ -14,15 +14,15 @@ long __copy_user(void *to, const void *from, long len) return ____copy_user_sisd(to, from, len); if (static_branch_likely(&core_hw_una_enabled)) - return ____copy_user_hw_una(to, from, len); + return ____copy_user_simd_no_una_check(to, from, len); else - return ____copy_user_sw_una(to, from, len); + return ____copy_user_simd_force_ali_addr(to, from, len); } EXPORT_SYMBOL(__copy_user); extern long ____clear_user_sisd(void __user *to, long len); -extern long ____clear_user_hw_una(void __user *to, long len); -extern long ____clear_user_sw_una(void __user *to, long len); +extern long ____clear_user_simd_no_una_check(void __user *to, long len); +extern long ____clear_user_simd_force_ali_addr(void __user *to, long len); long __clear_user(void __user *to, long len) { @@ -30,8 +30,8 @@ long __clear_user(void __user *to, long len) return ____clear_user_sisd(to, len); if (static_branch_likely(&core_hw_una_enabled)) - return ____clear_user_hw_una(to, len); + return ____clear_user_simd_no_una_check(to, len); else - return ____clear_user_sw_una(to, len); + return ____clear_user_simd_force_ali_addr(to, len); } EXPORT_SYMBOL(__clear_user); -- Gitee From 49d3e90f618f1f5444033035b01b4ea4d03d07b5 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 27 Mar 2024 15:06:08 +0800 Subject: [PATCH 67/98] sw64: save and restore CSR_WR_FREGS for SIMD libs Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- If the lib uses SIMD optimization, save CSR_WR_FREGS before the main part and restore it afterwards to avoid clobbering user SIMD state. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/lib/deep-clear_page.S | 7 +++++++ arch/sw_64/lib/deep-clear_user-force_ali_addr.S | 7 +++++++ arch/sw_64/lib/deep-clear_user-no_una_check.S | 7 +++++++ arch/sw_64/lib/deep-copy_user-force_ali_addr.S | 8 ++++++++ arch/sw_64/lib/deep-copy_user-no_una_check.S | 8 ++++++++ arch/sw_64/lib/deep-memcpy-force_ali_addr.S | 8 ++++++++ arch/sw_64/lib/deep-memcpy-no_una_check.S | 8 ++++++++ 7 files changed, 53 insertions(+) diff --git a/arch/sw_64/lib/deep-clear_page.S b/arch/sw_64/lib/deep-clear_page.S index 52a3db33fc17..0c7f163d781e 100644 --- a/arch/sw_64/lib/deep-clear_page.S +++ b/arch/sw_64/lib/deep-clear_page.S @@ -2,6 +2,7 @@ /* * Zero an entire page. */ +#include #include .text .align 4 @@ -37,6 +38,9 @@ clear_page: stl_nc $31,0x78($16) */ +#ifdef CONFIG_SUBARCH_C4 + csrr $7, CSR_WR_FREGS +#endif vstd_nc $f31, 0x0($16) vstd_nc $f31, 0x20($16) subl $0, 1, $0 @@ -47,6 +51,9 @@ clear_page: bne $0, 1b memb +#ifdef CONFIG_SUBARCH_C4 + csrw $7, CSR_WR_FREGS +#endif ret .end clear_page diff --git a/arch/sw_64/lib/deep-clear_user-force_ali_addr.S b/arch/sw_64/lib/deep-clear_user-force_ali_addr.S index 24b1f03b6a4d..78d989609e12 100644 --- a/arch/sw_64/lib/deep-clear_user-force_ali_addr.S +++ b/arch/sw_64/lib/deep-clear_user-force_ali_addr.S @@ -10,6 +10,7 @@ * stuff. * */ +#include #include /* Allow an exception for an insn; exit if we get one. */ #define FIXUP_LDST(x,y...) \ @@ -34,6 +35,9 @@ ____clear_user_simd_force_ali_addr: bis $31, $31, $7 mov $17, $18 bis $31, $31, $17 +#ifdef CONFIG_SUBARCH_C4 + csrr $6, CSR_WR_FREGS +#endif #include "deep-set_template-force_ali_addr.S" 255: bis $31, $18, $0 @@ -43,5 +47,8 @@ $restore_simd: RESTORE_SIMD_REGS $return: +#ifdef CONFIG_SUBARCH_C4 + csrw $6, CSR_WR_FREGS +#endif ret .end ____clear_user_simd_force_ali_addr diff --git a/arch/sw_64/lib/deep-clear_user-no_una_check.S b/arch/sw_64/lib/deep-clear_user-no_una_check.S index b6c23a72702b..da25c6be66fb 100644 --- a/arch/sw_64/lib/deep-clear_user-no_una_check.S +++ b/arch/sw_64/lib/deep-clear_user-no_una_check.S @@ -10,6 +10,7 @@ * stuff. * */ +#include #include /* Allow an exception for an insn; exit if we get one. */ #define FIXUP_LDST(x,y...) \ @@ -34,6 +35,9 @@ ____clear_user_simd_no_una_check: bis $31, $31, $7 mov $17, $18 bis $31, $31, $17 +#ifdef CONFIG_SUBARCH_C4 + csrr $6, CSR_WR_FREGS +#endif #include "deep-set_template-no_una_check.S" 255: bis $31, $18, $0 @@ -43,5 +47,8 @@ $restore_simd: RESTORE_SIMD_REGS $return: +#ifdef CONFIG_SUBARCH_C4 + csrw $6, CSR_WR_FREGS +#endif ret .end ____clear_user_simd_no_una_check diff --git a/arch/sw_64/lib/deep-copy_user-force_ali_addr.S b/arch/sw_64/lib/deep-copy_user-force_ali_addr.S index e04180acfc41..febb46f9b691 100644 --- a/arch/sw_64/lib/deep-copy_user-force_ali_addr.S +++ b/arch/sw_64/lib/deep-copy_user-force_ali_addr.S @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#include + /* Allow an exception for an insn; exit if we get one. */ #define FIXUP_LDST(x, y) \ 99: x, y; \ @@ -25,6 +27,9 @@ ____copy_user_simd_force_ali_addr: .prologue 0 .set noreorder bis $31, $31, $7 +#ifdef CONFIG_SUBARCH_C4 + csrr $6, CSR_WR_FREGS +#endif #include "deep-copy_template-force_ali_addr.S" 255: bis $31, $18, $0 @@ -40,5 +45,8 @@ $restore_simd: RESTORE_SIMD_REGS $return: +#ifdef CONFIG_SUBARCH_C4 + csrw $6, CSR_WR_FREGS +#endif ret .end ____copy_user_simd_force_ali_addr diff --git a/arch/sw_64/lib/deep-copy_user-no_una_check.S b/arch/sw_64/lib/deep-copy_user-no_una_check.S index ec3e0f095b2d..cadd5e0f31c1 100644 --- a/arch/sw_64/lib/deep-copy_user-no_una_check.S +++ b/arch/sw_64/lib/deep-copy_user-no_una_check.S @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#include + /* Allow an exception for an insn; exit if we get one. */ #define FIXUP_LDST(x, y) \ 99: x, y; \ @@ -25,6 +27,9 @@ ____copy_user_simd_no_una_check: .prologue 0 .set noreorder bis $31, $31, $7 +#ifdef CONFIG_SUBARCH_C4 + csrr $6, CSR_WR_FREGS +#endif #include "deep-copy_template-no_una_check.S" 255: bis $31, $18, $0 @@ -36,5 +41,8 @@ $restore_simd: RESTORE_SIMD_REGS $return: +#ifdef CONFIG_SUBARCH_C4 + csrw $6, CSR_WR_FREGS +#endif ret .end ____copy_user_simd_no_una_check diff --git a/arch/sw_64/lib/deep-memcpy-force_ali_addr.S b/arch/sw_64/lib/deep-memcpy-force_ali_addr.S index 3b9652fd7ac4..7e990bda936c 100644 --- a/arch/sw_64/lib/deep-memcpy-force_ali_addr.S +++ b/arch/sw_64/lib/deep-memcpy-force_ali_addr.S @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#include + #define FIXUP_LDST(x, y) \ x, y @@ -9,7 +11,13 @@ ____memcpy_simd_force_ali_addr: .frame $30, 0, $26, 0 .prologue 0 mov $16, $0 +#ifdef CONFIG_SUBARCH_C4 + csrr $6, CSR_WR_FREGS +#endif #include "deep-copy_template-force_ali_addr.S" 255: +#ifdef CONFIG_SUBARCH_C4 + csrw $6, CSR_WR_FREGS +#endif ret .end ____memcpy_simd_force_ali_addr diff --git a/arch/sw_64/lib/deep-memcpy-no_una_check.S b/arch/sw_64/lib/deep-memcpy-no_una_check.S index 47d0b683e45e..c7ded71b1ade 100644 --- a/arch/sw_64/lib/deep-memcpy-no_una_check.S +++ b/arch/sw_64/lib/deep-memcpy-no_una_check.S @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#include + #define FIXUP_LDST(x, y) \ x, y @@ -9,7 +11,13 @@ ____memcpy_simd_no_una_check: .frame $30, 0, $26, 0 .prologue 0 mov $16, $0 +#ifdef CONFIG_SUBARCH_C4 + csrr $6, CSR_WR_FREGS +#endif #include "deep-copy_template-no_una_check.S" 255: +#ifdef CONFIG_SUBARCH_C4 + csrw $6, CSR_WR_FREGS +#endif ret .end ____memcpy_simd_no_una_check -- Gitee From 90b8b6c31b63a75deebd30bbcd613658a2827866 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 27 Feb 2024 14:03:10 +0800 Subject: [PATCH 68/98] sw64: setup stackframe at kernel entry point Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Manually setup a stackframe at kernel entry point to produce a more accurate stacktrace. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/asm-offsets.c | 8 ++++++ arch/sw_64/kernel/entry_c3.S | 36 +++++++++++++++---------- arch/sw_64/kernel/entry_c4.S | 48 +++++++++++++++++++-------------- arch/sw_64/kernel/process.c | 2 +- 4 files changed, 59 insertions(+), 35 deletions(-) diff --git a/arch/sw_64/kernel/asm-offsets.c b/arch/sw_64/kernel/asm-offsets.c index 2fb2d807ae3f..334f7f2e9550 100644 --- a/arch/sw_64/kernel/asm-offsets.c +++ b/arch/sw_64/kernel/asm-offsets.c @@ -241,4 +241,12 @@ void foo(void) BLANK(); DEFINE(RT_SIGFRAME_SIZE, sizeof(struct rt_sigframe)); OFFSET(RT_SIGFRAME_MCTX, rt_sigframe, uc.uc_mcontext); + BLANK(); +#ifdef CONFIG_FRAME_POINTER + DEFINE(STACKFRAME_SIZE, sizeof(struct stackframe)); + OFFSET(STACKFRAME_PC, stackframe, pc); + OFFSET(STACKFRAME_FP, stackframe, fp); +#else + DEFINE(STACKFRAME_SIZE, 0); +#endif } diff --git a/arch/sw_64/kernel/entry_c3.S b/arch/sw_64/kernel/entry_c3.S index a7183817671b..df8bff5d09b3 100644 --- a/arch/sw_64/kernel/entry_c3.S +++ b/arch/sw_64/kernel/entry_c3.S @@ -70,9 +70,17 @@ ldi $1, NO_SYSCALL stl $1, PT_REGS_ORIG_R0($sp) sys_call HMC_rdktp +#ifdef CONFIG_FRAME_POINTER + ldi $sp, -STACKFRAME_SIZE($sp) + stl $5, STACKFRAME_PC($sp) + stl $15, STACKFRAME_FP($sp) + mov $sp, $15 +#endif .endm .macro RESTORE_ALL + ldi $sp, STACKFRAME_SIZE($sp) + ldl $16, PT_REGS_SP($sp) /* skip wrusp if returning to kernel */ blt $16, 1f @@ -127,7 +135,7 @@ .ent entInt entInt: SAVE_ALL - mov $sp, $19 + ldi $19, STACKFRAME_SIZE($sp) call $26, do_entInt br ret_from_sys_call .end entInt @@ -137,7 +145,7 @@ entInt: .ent entArith entArith: SAVE_ALL - mov $sp, $18 + ldi $18, STACKFRAME_SIZE($sp) call $26, do_entArith br ret_from_sys_call .end entArith @@ -147,7 +155,7 @@ entArith: .ent entMM entMM: SAVE_ALL - mov $sp, $19 + ldi $19, STACKFRAME_SIZE($sp) call $26, do_page_fault br ret_from_sys_call .end entMM @@ -157,7 +165,7 @@ entMM: .ent entIF entIF: SAVE_ALL - mov $sp, $18 + ldi $18, STACKFRAME_SIZE($sp) call $26, do_entIF br ret_from_sys_call .end entIF @@ -173,15 +181,15 @@ entIF: .ent entUna entUna: SAVE_ALL - mov $sp, $19 - ldl $0, PT_REGS_PS($sp) + ldi $19, STACKFRAME_SIZE($sp) + ldl $0, (PT_REGS_PS + STACKFRAME_SIZE)($sp) and $0, 8, $0 /* user mode ? */ beq $0, 1f call $26, do_entUnaUser /* return to ret_from_syscall */ br ret_from_sys_call -1: ldl $9, PT_REGS_GP($sp) +1: ldl $9, (PT_REGS_GP + STACKFRAME_SIZE)($sp) call $26, do_entUna - stl $9, PT_REGS_GP($sp) + stl $9, (PT_REGS_GP + STACKFRAME_SIZE)($sp) RESTORE_ALL sys_call HMC_rti .end entUna @@ -202,10 +210,10 @@ entUna: .ent entSys entSys: SAVE_ALL - stl $16, PT_REGS_R16($sp) - stl $17, PT_REGS_R17($sp) - stl $18, PT_REGS_R18($sp) - mov $sp, $16 + stl $16, (PT_REGS_R16 + STACKFRAME_SIZE)($sp) + stl $17, (PT_REGS_R17 + STACKFRAME_SIZE)($sp) + stl $18, (PT_REGS_R18 + STACKFRAME_SIZE)($sp) + ldi $16, STACKFRAME_SIZE($sp) call $26, do_entSys br ret_from_sys_call .end entSys @@ -223,14 +231,14 @@ ret_from_sys_call: sampling and the rti. */ ldi $16, 7 sys_call HMC_swpipl - ldl $0, PT_REGS_PS($sp) + ldl $0, (PT_REGS_PS + STACKFRAME_SIZE)($sp) and $0, 8, $0 beq $0, restore_all ret_to_user: ldw $17, TI_FLAGS($8) and $17, _TIF_WORK_MASK, $2 beq $2, restore_all - mov $sp, $16 + ldi $16, STACKFRAME_SIZE($sp) call $26, do_notify_resume restore_all: RESTORE_ALL diff --git a/arch/sw_64/kernel/entry_c4.S b/arch/sw_64/kernel/entry_c4.S index 097f4279e69b..c31143645b6f 100644 --- a/arch/sw_64/kernel/entry_c4.S +++ b/arch/sw_64/kernel/entry_c4.S @@ -79,12 +79,20 @@ ldi $1, NO_SYSCALL stl $1, PT_REGS_ORIG_R0($sp) csrr $8, CSR_KTP +#ifdef CONFIG_FRAME_POINTER + ldi $sp, -STACKFRAME_SIZE($sp) + stl $3, STACKFRAME_PC($sp) + stl $15, STACKFRAME_FP($sp) + mov $sp, $15 +#endif .endm .macro RESTORE_ALL ldi $16, 7 sys_call HMC_swpipl + ldi $sp, STACKFRAME_SIZE($sp) + ldl $1, PT_REGS_PS($sp) ldl $2, PT_REGS_PC($sp) csrw $1, CSR_PS @@ -130,7 +138,7 @@ .macro RESTORE_IRQ csrr $16, CSR_PS sys_call HMC_swpipl - ldl $16, PT_REGS_EARG0($sp) + ldl $16, (PT_REGS_EARG0 + STACKFRAME_SIZE)($sp) .endm /* * Non-syscall kernel entry points. @@ -143,7 +151,7 @@ entInt: SAVE_ALL br $27, 1f 1: ldgp $29, 0($27) - mov $sp, $19 + ldi $19, STACKFRAME_SIZE($sp) call $26, do_entInt br ret_from_sys_call .end entInt @@ -153,13 +161,13 @@ entInt: .ent entArith entArith: SAVE_ALL - ldl $1, PT_REGS_PC($sp) + ldl $1, (PT_REGS_PC + STACKFRAME_SIZE)($sp) ldi $1, 4($1) - stl $1, PT_REGS_PC($sp) + stl $1, (PT_REGS_PC + STACKFRAME_SIZE)($sp) br $27, 1f 1: ldgp $29, 0($27) RESTORE_IRQ - mov $sp, $18 + ldi $18, STACKFRAME_SIZE($sp) call $26, do_entArith br ret_from_sys_call .end entArith @@ -172,7 +180,7 @@ entMM: br $27, 1f 1: ldgp $29, 0($27) RESTORE_IRQ - mov $sp, $19 + ldi $19, STACKFRAME_SIZE($sp) call $26, do_page_fault br ret_from_sys_call .end entMM @@ -182,13 +190,13 @@ entMM: .ent entIF entIF: SAVE_ALL - ldl $1, PT_REGS_PC($sp) + ldl $1, (PT_REGS_PC + STACKFRAME_SIZE)($sp) ldi $1, 4($1) - stl $1, PT_REGS_PC($sp) + stl $1, (PT_REGS_PC + STACKFRAME_SIZE)($sp) br $27, 1f 1: ldgp $29, 0($27) RESTORE_IRQ - mov $sp, $18 + ldi $18, STACKFRAME_SIZE($sp) call $26, do_entIF br ret_from_sys_call .end entIF @@ -204,21 +212,21 @@ entIF: .ent entUna entUna: SAVE_ALL - ldl $1, PT_REGS_PC($sp) + ldl $1, (PT_REGS_PC + STACKFRAME_SIZE)($sp) ldi $1, 4($1) - stl $1, PT_REGS_PC($sp) + stl $1, (PT_REGS_PC + STACKFRAME_SIZE)($sp) br $27, 1f 1: ldgp $29, 0($27) RESTORE_IRQ - mov $sp, $19 - ldl $0, PT_REGS_PS($sp) + ldi $19, STACKFRAME_SIZE($sp) + ldl $0, (PT_REGS_PS + STACKFRAME_SIZE)($sp) and $0, 8, $0 /* user mode ? */ beq $0, 1f call $26, do_entUnaUser /* return to ret_from_syscall */ br ret_from_sys_call -1: ldl $9, PT_REGS_GP($sp) +1: ldl $9, (PT_REGS_GP + STACKFRAME_SIZE)($sp) call $26, do_entUna - stl $9, PT_REGS_GP($sp) + stl $9, (PT_REGS_GP + STACKFRAME_SIZE)($sp) RESTORE_ALL sys_call HMC_rti .end entUna @@ -239,13 +247,13 @@ entUna: .ent entSys entSys: SAVE_ALL - ldl $1, PT_REGS_PC($sp) + ldl $1, (PT_REGS_PC + STACKFRAME_SIZE)($sp) ldi $1, 4($1) - stl $1, PT_REGS_PC($sp) + stl $1, (PT_REGS_PC + STACKFRAME_SIZE)($sp) br $27, 1f 1: ldgp $29, 0($27) RESTORE_IRQ - mov $sp, $16 + ldi $16, STACKFRAME_SIZE($sp) call $26, do_entSys br ret_from_sys_call .end entSys @@ -260,14 +268,14 @@ ret_from_sys_call: sampling and the rti. */ ldi $16, 7 sys_call HMC_swpipl - ldl $0, PT_REGS_PS($sp) + ldl $0, (PT_REGS_PS + STACKFRAME_SIZE)($sp) and $0, 8, $0 beq $0, restore_all ret_to_user: ldw $17, TI_FLAGS($8) and $17, _TIF_WORK_MASK, $2 beq $2, restore_all - mov $sp, $16 + ldi $16, STACKFRAME_SIZE($sp) call $26, do_notify_resume restore_all: RESTORE_ALL diff --git a/arch/sw_64/kernel/process.c b/arch/sw_64/kernel/process.c index cd371a71cfca..ded9f780497a 100644 --- a/arch/sw_64/kernel/process.c +++ b/arch/sw_64/kernel/process.c @@ -78,7 +78,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) extern void ret_from_fork(void); extern void ret_from_kernel_thread(void); - p->thread.sp = (unsigned long) childregs; + p->thread.sp = (unsigned long) childregs - STACKFRAME_SIZE; if (unlikely(args->fn)) { /* kernel thread */ -- Gitee From ee25fca83050176d6fe8a069dbc0a699d9bffae7 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 27 Mar 2024 14:47:13 +0800 Subject: [PATCH 69/98] sw64: receive new boot params from firmware Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Starting from junzhang, firmware pass a magic number (0xDEED2024UL) via r16 and dtb base address via r17 when jumping to kernel. When kernel receives the magic number, it means that we can parse the required boot params from the chosen node in DTB. Otherwise, kernel will use legacy "struct boot_params" for backward compatibility. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/platform.h | 2 ++ arch/sw_64/kernel/head.S | 23 +++++++++++++++++++++++ arch/sw_64/kernel/setup.c | 10 ++++++++++ 3 files changed, 35 insertions(+) diff --git a/arch/sw_64/include/asm/platform.h b/arch/sw_64/include/asm/platform.h index ad54cdc772e1..7374f2087f90 100644 --- a/arch/sw_64/include/asm/platform.h +++ b/arch/sw_64/include/asm/platform.h @@ -19,6 +19,8 @@ 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); diff --git a/arch/sw_64/kernel/head.S b/arch/sw_64/kernel/head.S index bfeb6859ecc2..db4af8f9366b 100644 --- a/arch/sw_64/kernel/head.S +++ b/arch/sw_64/kernel/head.S @@ -37,6 +37,16 @@ __start: /* ... and find our stack ... */ ldi $30, ASM_THREAD_SIZE($30) + /** + * Starting from Core4, Grub uses $16 to pass magic num + * and use $17 to pass DTB base address. + * + * So, we need to save $16 and $17 before clearing bss. + */ + ldi $30, -16($30) + stl $16, 8($30) + stl $17, 0($30) + /* ... and then we can clear bss data. */ ldi $16, __bss_start ldi $18, __bss_stop @@ -44,6 +54,18 @@ __start: mov $31, $17 call $26, __constant_c_memset ldgp $29, 0($26) + + /* Get magic num and DTB base address. */ + ldl $16, 8($30) + ldl $17, 0($30) + ldi $30, 16($30) + /* sunway_boot_magic = $16 */ + ldi $7, sunway_boot_magic + stl $16, 0($7) + /* sunway_dtb_address = $17 */ + ldi $7, sunway_dtb_address + stl $17, 0($7) + #ifdef CONFIG_RELOCATABLE ldi $30, -8($30) stl $29, 0($30) @@ -56,6 +78,7 @@ __start: /* Repoint the sp into the new kernel image */ addl $30, $0, $30 #endif + /* ... and then we can start the kernel. */ call $26, sw64_start_kernel sys_call HMC_halt diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 4bf49300d09e..43d180a4fcca 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -125,8 +125,18 @@ static char builtin_cmdline[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; #endif /* boot_params */ +/** + * Keep sunway_boot_params for backward compatibility. All related code + * will be removed when kernel no longer support C3B(xuelang). + */ struct boot_params *sunway_boot_params = (struct boot_params *) (PARAM + 0x100); +unsigned long sunway_boot_magic; +EXPORT_SYMBOL(sunway_boot_magic); + +unsigned long sunway_dtb_address; +EXPORT_SYMBOL(sunway_dtb_address); + /* * The format of "screen_info" is strange, and due to early * i386-setup code. This is just enough to make the console -- Gitee From 211c14f47f84ec8e3420f5c673b23bcd6c3ef087 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 27 Mar 2024 14:52:38 +0800 Subject: [PATCH 70/98] sw64: apply new boot params from DTB chosen node Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Starting from junzhang, we use the chosen node in DTB to pass boot params, involving the following properties: - bootargs - linux,initrd-start - linux,initrd-end - linux,uefi-system-table - linux,uefi-mmap-start - linux,uefi-mmap-size - linux,uefi-mmap-desc-size - linux,uefi-mmap-desc-ver This commit will not break backward compatibility. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 81 +++++---- arch/sw_64/configs/junzhang_defconfig | 1 - arch/sw_64/configs/kata_guest_defconfig | 5 +- arch/sw_64/configs/kata_xuelang_defconfig | 1 - arch/sw_64/configs/xuelang_defconfig | 1 - arch/sw_64/include/asm/hw_init.h | 4 +- arch/sw_64/kernel/chip_setup.c | 2 +- arch/sw_64/kernel/machine_kexec.c | 203 +++++++++++++++++++-- arch/sw_64/kernel/setup.c | 212 +++++++++------------- arch/sw_64/mm/init.c | 80 +++++++- drivers/firmware/efi/sunway-init.c | 31 ++-- 11 files changed, 409 insertions(+), 212 deletions(-) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 79be887a5a0c..2753e1b0b058 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -103,12 +103,14 @@ config SW64 select HAVE_RELIABLE_STACKTRACE if STACKTRACE select HAVE_RSEQ select HAVE_SYSCALL_TRACEPOINTS + select IRQ_DOMAIN select IRQ_FORCED_THREADING select LOCK_MM_AND_FIND_VMA select MEMORY_HOTPLUG_SPARSE if MEMORY_HOTPLUG select MODULES_USE_ELF_RELA select NO_BOOTMEM - select OF_EARLY_FLATTREE if OF + select OF + select OF_EARLY_FLATTREE select OLD_SIGSUSPEND select PCI_DOMAINS_GENERIC if PCI select PCI_ECAM if (ACPI && PCI) @@ -508,13 +510,6 @@ endmenu menu "Boot options" -config USE_OF - bool "Flattened Device Tree support" - select OF - select IRQ_DOMAIN - help - Include support for flattened device tree machine descriptions. - config BUILTIN_DTB bool "Embed DTB in kernel image" depends on OF @@ -531,8 +526,10 @@ config BUILTIN_DTB_NAME config EFI bool "UEFI runtime support" + depends on OF select UCS2_STRING select EFI_RUNTIME_WRAPPERS + select EFI_PARAMS_FROM_FDT default y help This option provides support for runtime services provided @@ -558,48 +555,52 @@ config DMI firmware need to be enabled. This would require the DMI subsystem to be enabled much earlier than we do on ARM, which is non-trivial. -config CMDLINE_BOOL - bool "Built-in kernel command line" +config CMDLINE + string "Built-in kernel command line" + default "" help - Allow for specifying boot arguments to the kernel at - build time. On some systems (e.g. embedded ones), it is - necessary or convenient to provide some or all of the - kernel boot arguments with the kernel itself (that is, - to not rely on the boot loader to provide them.) + Allow for specifying boot arguments to the kernel at build + time. On some systems (e.g. embedded ones), it is necessary + or convenient to provide some or all of the kernel boot + arguments with the kernel itself (that is, to not rely on + firmware to provide them.) - To compile command line arguments into the kernel, - set this option to 'Y', then fill in the - boot arguments in CONFIG_CMDLINE. + Enter arguments here that should be compiled into the kernel + image. And choose how the kernel should use it later on. - Systems with fully functional boot loaders (i.e. non-embedded) - should leave this option set to 'N'. + In most cases, the command line (whether built-in or provided + by firmware) should specify the device for the root file system. -config CMDLINE - string "Built-in kernel command string" - depends on CMDLINE_BOOL - default "" +choice + prompt "Built-in kernel command line usage" if CMDLINE != "" + default CMDLINE_FROM_FIRMWARE help - Enter arguments here that should be compiled into the kernel - image and used at boot time. If the boot loader provides a - command line at boot time, it is appended to this string to - form the full kernel command line, when the system boots. + Choose how the kernel will handle the provided built-in kernel + command line. - However, you can use the CONFIG_CMDLINE_OVERRIDE option to - change this behavior. +config CMDLINE_FROM_FIRMWARE + bool "Use kernel command line provided by firmware" + help + Use kernel command line provided by firmware. If the firmware + doesn't provide any, the built-in kernel command line provided + in CMDLINE will be used. - In most cases, the command line (whether built-in or provided - by the boot loader) should specify the device for the root - file system. +config CMDLINE_EXTEND + bool "Extend kernel command line" + help + The built-in kernel command line will be appended to the command + line provided by firmware. This is useful in cases where the + command line provided by firmware is insufficient and you don't + want to or cannot modify them. -config CMDLINE_OVERRIDE - bool "Built-in command line overrides boot loader arguments" - depends on CMDLINE_BOOL +config CMDLINE_FORCE + bool "Always use built-in kernel command line" help - Set this option to 'Y' to have the kernel ignore the boot loader - command line, and use ONLY the built-in command line. + Always use built-in kernel command line, even if we get one + from firmware. This is useful in some cases. For example, + you need to work around broken boot loaders. - This is used to work around broken boot loaders. This should - be set to 'N' under normal conditions. +endchoice config FORCE_MAX_ZONEORDER int diff --git a/arch/sw_64/configs/junzhang_defconfig b/arch/sw_64/configs/junzhang_defconfig index 9baf68f8e0ac..62fccb2a8117 100644 --- a/arch/sw_64/configs/junzhang_defconfig +++ b/arch/sw_64/configs/junzhang_defconfig @@ -33,7 +33,6 @@ CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_NUMA=y CONFIG_HZ=100 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_USE_OF=y CONFIG_FIRMWARE_MEMMAP=y CONFIG_DMI_SYSFS=m CONFIG_ACPI_TAD=y diff --git a/arch/sw_64/configs/kata_guest_defconfig b/arch/sw_64/configs/kata_guest_defconfig index 8122155c1276..6a7c442b94a7 100644 --- a/arch/sw_64/configs/kata_guest_defconfig +++ b/arch/sw_64/configs/kata_guest_defconfig @@ -34,9 +34,8 @@ CONFIG_NUMA=y CONFIG_HZ=100 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=y -CONFIG_USE_OF=y -CONFIG_SW64_BUILTIN_DTB=y -CONFIG_SW64_BUILTIN_DTB_NAME="chip_vt" +CONFIG_BUILTIN_DTB=y +CONFIG_BUILTIN_DTB_NAME="chip_vt" CONFIG_FIRMWARE_MEMMAP=y CONFIG_DMI_SYSFS=m CONFIG_GOOGLE_FIRMWARE=y diff --git a/arch/sw_64/configs/kata_xuelang_defconfig b/arch/sw_64/configs/kata_xuelang_defconfig index f553f0e71dbf..c059bbb7a576 100644 --- a/arch/sw_64/configs/kata_xuelang_defconfig +++ b/arch/sw_64/configs/kata_xuelang_defconfig @@ -36,7 +36,6 @@ CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_NUMA=y CONFIG_HZ=100 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_USE_OF=y CONFIG_FIRMWARE_MEMMAP=y CONFIG_DMI_SYSFS=m # CONFIG_SUSPEND is not set diff --git a/arch/sw_64/configs/xuelang_defconfig b/arch/sw_64/configs/xuelang_defconfig index b1c0101d0089..3da2cffa2085 100644 --- a/arch/sw_64/configs/xuelang_defconfig +++ b/arch/sw_64/configs/xuelang_defconfig @@ -30,7 +30,6 @@ CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_NUMA=y CONFIG_HZ=100 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_USE_OF=y CONFIG_FIRMWARE_MEMMAP=y CONFIG_DMI_SYSFS=m CONFIG_ACPI_TAD=y diff --git a/arch/sw_64/include/asm/hw_init.h b/arch/sw_64/include/asm/hw_init.h index d1d2c71bc344..ab0e2ee4c9a6 100644 --- a/arch/sw_64/include/asm/hw_init.h +++ b/arch/sw_64/include/asm/hw_init.h @@ -7,7 +7,7 @@ #include -#define MMSIZE __va(0x2040) +#define MM_SIZE __va(0x2040) #define VPCR_SHIFT 44 /* @@ -93,7 +93,7 @@ static inline void update_cpu_freq(unsigned long khz) } #define EMUL_FLAG (0x1UL << 63) -#define MMSIZE_MASK (EMUL_FLAG - 1) +#define MM_SIZE_MASK (EMUL_FLAG - 1) DECLARE_STATIC_KEY_TRUE(run_mode_host_key); DECLARE_STATIC_KEY_FALSE(run_mode_guest_key); diff --git a/arch/sw_64/kernel/chip_setup.c b/arch/sw_64/kernel/chip_setup.c index b8c359db2ef6..60373429a64e 100644 --- a/arch/sw_64/kernel/chip_setup.c +++ b/arch/sw_64/kernel/chip_setup.c @@ -21,7 +21,7 @@ static unsigned long __init get_node_mem(int nodeid) { if (is_guest_or_emul()) - return *(unsigned long *)MMSIZE & MMSIZE_MASK; + return *(unsigned long *)MM_SIZE & MM_SIZE_MASK; return __get_node_mem(nodeid); } diff --git a/arch/sw_64/kernel/machine_kexec.c b/arch/sw_64/kernel/machine_kexec.c index 950998476cda..d6758d48dc26 100644 --- a/arch/sw_64/kernel/machine_kexec.c +++ b/arch/sw_64/kernel/machine_kexec.c @@ -10,8 +10,13 @@ #include #include #include +#include +#include +#include +#include #include +#include extern void *kexec_control_page; extern const unsigned char relocate_new_kernel[]; @@ -143,15 +148,189 @@ void machine_crash_shutdown(struct pt_regs *regs) #define phys_to_ktext(pa) (__START_KERNEL_map + (pa)) -typedef void (*noretfun_t)(void) __noreturn; +typedef void (*noretfun_t)(unsigned long, unsigned long) __noreturn; + +/** + * Current kernel does not yet have a common implementation for + * this function. So, make an arch-specific one. + */ +static void *arch_kexec_alloc_and_setup_fdt(unsigned long initrd_start, + unsigned long initrd_size, const char *cmdline) +{ + void *fdt; + int ret, chosen_node; + size_t fdt_size; + + fdt_size = fdt_totalsize(initial_boot_params) + + (cmdline ? strlen(cmdline) : 0) + 0x1000; + fdt = kzalloc(fdt_size, GFP_KERNEL); + if (!fdt) + return NULL; + + ret = fdt_open_into(initial_boot_params, fdt, fdt_size); + if (ret < 0) { + pr_err("Error %d setting up the new device tree\n", ret); + goto out; + } + + chosen_node = fdt_path_offset(fdt, "/chosen"); + if (chosen_node < 0) { + pr_err("Failed to find chosen node\n"); + goto out; + } + + /* update initrd params */ + if (initrd_size) { + ret = fdt_setprop_u64(fdt, chosen_node, "linux,initrd-start", + initrd_start); + if (ret) + goto out; + + ret = fdt_setprop_u64(fdt, chosen_node, "linux,initrd-end", + initrd_start + initrd_size); + if (ret) + goto out; + } else { + ret = fdt_delprop(fdt, chosen_node, "linux,initrd-start"); + if (ret) + goto out; + + ret = fdt_delprop(fdt, chosen_node, "linux,initrd-end"); + if (ret) + goto out; + } + + /* update cmdline */ + if (cmdline) { + ret = fdt_setprop_string(fdt, chosen_node, "bootargs", cmdline); + if (ret) + goto out; + } else { + ret = fdt_delprop(fdt, chosen_node, "bootargs"); + if (ret) + goto out; + } + + return fdt; + +out: + kfree(fdt); + return NULL; +} + +#ifdef CONFIG_EFI +static int update_efi_properties(const struct boot_params *params) +{ + int chosen_node, ret; + void *dtb_start = (void *)params->dtb_start; + + if (!dtb_start) + return -EINVAL; + + chosen_node = fdt_path_offset(dtb_start, "/chosen"); + if (chosen_node < 0) + return -EINVAL; + + ret = fdt_setprop_u64(dtb_start, chosen_node, + "linux,uefi-system-table", + params->efi_systab); + if (ret) + return ret; + + ret = fdt_setprop_u64(dtb_start, chosen_node, + "linux,uefi-mmap-start", + params->efi_memmap); + if (ret) + return ret; + + ret = fdt_setprop_u64(dtb_start, chosen_node, + "linux,uefi-mmap-size", + params->efi_memmap_size); + if (ret) + return ret; + + ret = fdt_setprop_u64(dtb_start, chosen_node, + "linux,uefi-mmap-desc-size", + params->efi_memdesc_size); + if (ret) + return ret; + + ret = fdt_setprop_u64(dtb_start, chosen_node, + "linux,uefi-mmap-desc-ver", + params->efi_memdesc_version); + if (ret) + return ret; + + return 0; +} +#endif + +static void update_boot_params(void) +{ + struct boot_params params = { 0 }; + + /* Cmdline and initrd can be new */ + params.cmdline = kexec_start_address - COMMAND_LINE_OFF; + params.initrd_start = *(__u64 *)(kexec_start_address - INITRD_START_OFF); + params.initrd_size = *(__u64 *)(kexec_start_address - INITRD_SIZE_OFF); + + if (sunway_boot_magic != 0xDEED2024UL) { + sunway_boot_params->cmdline = params.cmdline; + sunway_boot_params->initrd_start = params.initrd_start; + sunway_boot_params->initrd_size = params.initrd_size; + + params.dtb_start = sunway_boot_params->dtb_start; + params.efi_systab = sunway_boot_params->efi_systab; + params.efi_memmap = sunway_boot_params->efi_memmap; + params.efi_memmap_size = sunway_boot_params->efi_memmap_size; + params.efi_memdesc_size = sunway_boot_params->efi_memdesc_size; + params.efi_memdesc_version = sunway_boot_params->efi_memdesc_version; + } else { + params.dtb_start = (unsigned long)arch_kexec_alloc_and_setup_fdt( + params.initrd_start, params.initrd_size, + (const char *)params.cmdline); + /* update dtb base address */ + sunway_dtb_address = params.dtb_start; + +#ifdef CONFIG_EFI + params.efi_systab = virt_to_phys((void *)efi.systab); + params.efi_memmap = efi.memmap.phys_map; + params.efi_memmap_size = efi.memmap.map_end - efi.memmap.map; + params.efi_memdesc_size = efi.memmap.desc_size; + params.efi_memdesc_version = efi.memmap.desc_version; + + /** + * If current kernel take built-in DTB, it's possible that + * there are no efi related properties in "chosen" node. So, + * update these properties here. + * + * Harmless for the following cases: + * 1. Current kernel take DTB from firmware + * 2. New kernel with CONFIG_EFI=n + * 3. New kernel take built-in DTB + */ + if (update_efi_properties(¶ms)) + pr_err("Note: failed to update efi properties\n"); +#endif + } + + pr_info("initrd_start = %#llx, initrd_size = %#llx\n" + "dtb_start = %#llx, efi_systab = %#llx\n" + "efi_memmap = %#llx, efi_memmap_size = %#llx\n" + "efi_memdesc_size = %#llx, efi_memdesc_version = %#llx\n" + "cmdline = %s\n", + params.initrd_start, params.initrd_size, + params.dtb_start, params.efi_systab, + params.efi_memmap, params.efi_memmap_size, + params.efi_memdesc_size, params.efi_memdesc_version, + (char *)params.cmdline); +} void machine_kexec(struct kimage *image) { void *reboot_code_buffer; unsigned long entry; unsigned long *ptr; - struct boot_params *params = sunway_boot_params; - reboot_code_buffer = kexec_control_page; pr_info("reboot_code_buffer = %px\n", reboot_code_buffer); @@ -166,20 +345,7 @@ void machine_kexec(struct kimage *image) pr_info("kexec_indirection_page = %#lx, image->head=%#lx\n", kexec_indirection_page, image->head); - params->cmdline = kexec_start_address - COMMAND_LINE_OFF; - params->initrd_start = *(__u64 *)(kexec_start_address - INITRD_START_OFF); - params->initrd_size = *(__u64 *)(kexec_start_address - INITRD_SIZE_OFF); - - pr_info("initrd_start = %#llx, initrd_size = %#llx\n" - "dtb_start = %#llx, efi_systab = %#llx\n" - "efi_memmap = %#llx, efi_memmap_size = %#llx\n" - "efi_memdesc_size = %#llx, efi_memdesc_version = %#llx\n" - "cmdline = %#llx\n", - params->initrd_start, params->initrd_size, - params->dtb_start, params->efi_systab, - params->efi_memmap, params->efi_memmap_size, - params->efi_memdesc_size, params->efi_memdesc_version, - params->cmdline); + update_boot_params(); memcpy(reboot_code_buffer, relocate_new_kernel, relocate_new_kernel_size); @@ -205,5 +371,6 @@ void machine_kexec(struct kimage *image) pr_info("Will call new kernel at %08lx\n", image->start); pr_info("Bye ...\n"); smp_wmb(); - ((noretfun_t) reboot_code_buffer)(); + ((noretfun_t) reboot_code_buffer)(sunway_boot_magic, + sunway_dtb_address); } diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 43d180a4fcca..eb4a37f1b86f 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -10,7 +10,6 @@ #include #include #include -#include #ifdef CONFIG_MAGIC_SYSRQ #include #include @@ -119,11 +118,6 @@ bool memblock_initialized; cpumask_t cpu_offline = CPU_MASK_NONE; -static char command_line[COMMAND_LINE_SIZE] __initdata; -#ifdef CONFIG_CMDLINE_BOOL -static char builtin_cmdline[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; -#endif - /* boot_params */ /** * Keep sunway_boot_params for backward compatibility. All related code @@ -335,31 +329,6 @@ static int __init setup_cpuoffline(char *p) } early_param("cpuoffline", setup_cpuoffline); -#ifdef CONFIG_BLK_DEV_INITRD -static void * __init move_initrd(unsigned long mem_limit) -{ - void *start; - unsigned long size; - - size = initrd_end - initrd_start; - start = memblock_alloc_from(PAGE_ALIGN(size), PAGE_SIZE, 0); - if (!start || __pa(start) + size > mem_limit) { - initrd_start = initrd_end = 0; - return NULL; - } - memmove(start, (void *)initrd_start, size); - initrd_start = (unsigned long)start; - initrd_end = initrd_start + size; - pr_info("initrd moved to 0x%px\n", start); - return start; -} -#else -static void * __init move_initrd(unsigned long mem_limit) -{ - return NULL; -} -#endif - static bool __init memmap_range_valid(phys_addr_t base, phys_addr_t *size) { if (base > memblock_end_of_DRAM()) @@ -415,26 +384,9 @@ void __init process_memmap(void) } break; case memmap_initrd: - if ((base + size) > memblock_end_of_DRAM()) { - phys_addr_t old_base = base; - - base = (unsigned long) move_initrd(memblock_end_of_DRAM()); - if (!base) { - pr_err("initrd memmap region [mem %#018llx-%#018llx] extends beyond end of memory (%#018llx)\n", - old_base, old_base + size - 1, memblock_end_of_DRAM()); - break; - } - memmap_map[i].addr = base; - } - pr_info("initrd memmap region [mem %#018llx-%#018llx]\n", base, base + size - 1); - ret = memblock_reserve(base, size); - if (ret) - pr_err("reserve memmap region [mem %#018llx-%#018llx] failed\n", - base, base + size - 1); - break; case memmap_kvm: case memmap_crashkernel: - /* kvm and crashkernel are handled elsewhere, skip */ + /* initrd, kvm and crashkernel are handled elsewhere, skip */ break; case memmap_acpi: pr_err("ACPI memmap region is not supported.\n"); @@ -580,51 +532,103 @@ static int __init topology_init(void) } subsys_initcall(topology_init); -static void __init setup_machine_fdt(void) +static bool __init arch_dtb_verify(void *dt_virt, bool from_firmware) +{ + unsigned long dt_phys = __boot_pa(dt_virt); + + if (!phys_addr_valid(dt_phys)) { + pr_crit("Invalid physical DTB address 0x%lx\n", dt_phys); + return false; + } + + /* Only for non built-in DTB */ + if (from_firmware && + (dt_phys < virt_to_phys((void *)__bss_stop))) { + pr_crit("DTB has been corrupted by kernel image!\n"); + return false; + } + + return true; +} + +static void __init setup_firmware_fdt(void) { -#ifdef CONFIG_USE_OF void *dt_virt; const char *name; - /* Give a chance to select kernel builtin DTB firstly */ - if (IS_ENABLED(CONFIG_BUILTIN_DTB)) - dt_virt = (void *)__dtb_start; - else { + /** + * Use DTB provided by firmware for early initialization, regardless + * of whether a Built-in DTB configured or not. Since we need the + * boot params from firmware when using new method to pass boot params. + */ + if (sunway_boot_magic != 0xDEED2024UL) dt_virt = (void *)sunway_boot_params->dtb_start; - if (virt_to_phys(dt_virt) < virt_to_phys(__bss_stop)) { - pr_emerg("BUG: DTB has been corrupted by kernel image!\n"); - while (true) - cpu_relax(); - } + else { + pr_info("Parse boot params in DTB chosen node\n"); + dt_virt = (void *)sunway_dtb_address; } - if (!phys_addr_valid(__boot_pa(dt_virt)) || + if (!arch_dtb_verify(dt_virt, true) || !early_init_dt_scan(dt_virt)) { - pr_crit("\n" - "Error: invalid device tree blob at virtual address %px\n" - "The dtb must be 8-byte aligned and must not exceed 2 MB in size\n" - "\nPlease check your bootloader.", - dt_virt); - + pr_crit("Invalid DTB(from firmware) at virtual address 0x%lx\n", + (unsigned long)dt_virt); while (true) cpu_relax(); } name = of_flat_dt_get_machine_name(); - if (!name) - return; + if (name) + pr_info("Machine model: %s\n", name); - pr_info("Machine model: %s\n", name); + /** + * For C3B(xuelang), kernel command line always comes from + * "sunway_boot_params->cmdline". These code can be removed + * when no longer support C3B(xuelang). + */ + if (sunway_boot_magic != 0xDEED2024UL) { + if (!sunway_boot_params->cmdline) + sunway_boot_params->cmdline = (unsigned long)COMMAND_LINE; + strlcpy(boot_command_line, (char *)sunway_boot_params->cmdline, + COMMAND_LINE_SIZE); +#ifdef CONFIG_CMDLINE +#if defined(CONFIG_CMDLINE_EXTEND) + strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); + strlcat(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); +#elif defined(CONFIG_CMDLINE_FORCE) + strlcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); #else - pr_info("Kernel disable device tree support.\n"); - return; + /* No arguments from firmware, use kernel's built-in cmdline */ + if (!((char *)boot_command_line)[0]) + strlcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); #endif +#endif /* CONFIG_CMDLINE */ + } +} + +static void __init setup_builtin_fdt(void) +{ + void *dt_virt; + + dt_virt = (void *)__dtb_start; + if (!arch_dtb_verify(dt_virt, false) || + !early_init_dt_verify(dt_virt)) { + pr_crit("Invalid DTB(built-in) at virtual address 0x%lx\n", + (unsigned long)dt_virt); + while (true) + cpu_relax(); + } } -void __init device_tree_init(void) +static void __init device_tree_init(void) { - unflatten_and_copy_device_tree(); - sunway_boot_params->dtb_start = (__u64)initial_boot_params; + /** + * Built-in DTB is placed in init data, so we need + * to copy it. + */ + if (IS_ENABLED(CONFIG_BUILTIN_DTB)) + unflatten_and_copy_device_tree(); + else + unflatten_device_tree(); } static void __init setup_cpu_info(void) @@ -689,7 +693,7 @@ static void __init setup_run_mode(void) { if (rvpcr() >> VPCR_SHIFT) { static_branch_disable(&run_mode_host_key); - if (*(unsigned long *)MMSIZE & EMUL_FLAG) { + if (*(unsigned long *)MM_SIZE & EMUL_FLAG) { pr_info("run mode: emul\n"); static_branch_disable(&run_mode_guest_key); static_branch_enable(&run_mode_emul_key); @@ -721,26 +725,6 @@ static void __init setup_socket_info(void) } } -#ifdef CONFIG_BLK_DEV_INITRD -static void __init reserve_mem_for_initrd(void) -{ - int ret; - - initrd_start = sunway_boot_params->initrd_start; - if (initrd_start) { - initrd_start = __pa(initrd_start) + PAGE_OFFSET; - initrd_end = initrd_start + sunway_boot_params->initrd_size; - pr_info("Initial ramdisk at: 0x%px (%llu bytes)\n", - (void *)initrd_start, sunway_boot_params->initrd_size); - - ret = add_memmap_region(__pa(initrd_start), initrd_end - initrd_start, memmap_initrd); - if (ret) - pr_err("Add initrd area [mem %#018lx-%#018lx] to memmap region failed.\n", - __pa(initrd_start), __pa(initrd_end - 1)); - } -} -#endif /* CONFIG_BLK_DEV_INITRD */ - #ifdef CONFIG_SUBARCH_C3B #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) static int __init early_kvm_reserved_mem(char *p) @@ -787,7 +771,11 @@ setup_arch(char **cmdline_p) setup_sched_clock(); - setup_machine_fdt(); + /* Early initialization for device tree */ + setup_firmware_fdt(); + + /* Now we get the final boot_command_line */ + *cmdline_p = boot_command_line; /* Register a call for panic conditions. */ atomic_notifier_chain_register(&panic_notifier_list, @@ -795,28 +783,6 @@ setup_arch(char **cmdline_p) callback_init(); - /* command line */ - if (!sunway_boot_params->cmdline) - sunway_boot_params->cmdline = (unsigned long)COMMAND_LINE; - - strscpy(boot_command_line, (char *)sunway_boot_params->cmdline, COMMAND_LINE_SIZE); - -#if IS_ENABLED(CONFIG_CMDLINE_BOOL) -#if IS_ENABLED(CONFIG_CMDLINE_OVERRIDE) - strscpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); - strscpy((char *)sunway_boot_params->cmdline, boot_command_line, COMMAND_LINE_SIZE); -#else - if (builtin_cmdline[0]) { - /* append builtin to boot loader cmdline */ - strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); - strlcat(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); - } -#endif /* CMDLINE_EXTEND */ -#endif - - strscpy(command_line, boot_command_line, COMMAND_LINE_SIZE); - *cmdline_p = command_line; - /* * Process command-line arguments. */ @@ -829,10 +795,6 @@ setup_arch(char **cmdline_p) reserve_mem_for_pci(); #endif -#ifdef CONFIG_BLK_DEV_INITRD - reserve_mem_for_initrd(); -#endif - sw64_memblock_init(); reserve_crashkernel(); @@ -846,6 +808,10 @@ setup_arch(char **cmdline_p) efi_init(); + /* After efi initialization, switch to Builtin-in DTB if configured */ + if (IS_ENABLED(CONFIG_BUILTIN_DTB)) + setup_builtin_fdt(); + /* Try to upgrade ACPI tables via initrd */ acpi_table_upgrade(); diff --git a/arch/sw_64/mm/init.c b/arch/sw_64/mm/init.c index ca761b602ab6..d33d5a83e5b1 100644 --- a/arch/sw_64/mm/init.c +++ b/arch/sw_64/mm/init.c @@ -11,9 +11,13 @@ #include #include #include +#include +#include +#include #include #include +#include struct mem_desc_t mem_desc; #ifndef CONFIG_NUMA @@ -157,6 +161,61 @@ void __init mem_detect(void) mem_desc.size = mem_desc.phys_size - NODE0_START; } +#ifdef CONFIG_BLK_DEV_INITRD +static void __init reserve_mem_for_initrd(void) +{ + phys_addr_t phys_initrd_start, initrd_size; + + /** + * Get initrd params from boot_params for backward + * compatibility. These code can be removed when + * no longer support C3B(xuelang). + */ + if (sunway_boot_magic != 0xDEED2024UL) { + initrd_start = sunway_boot_params->initrd_start; + if (initrd_start) { + /** + * It works regardless of whether the firmware + * passes a virtual address or a physical address. + * + * __boot_pa here is used for compatibility with + * old firmware. We can use __pa instead when no + * longer support C3B(xuelang). + */ + initrd_start = (unsigned long)__va(__boot_pa(initrd_start)); + initrd_end = initrd_start + sunway_boot_params->initrd_size; + } + } + + phys_initrd_start = __boot_pa(initrd_start); + initrd_size = initrd_end - initrd_start; + + if (!initrd_start || !initrd_size) { + pr_info("No initrd found\n"); + return; + } + + pr_info("Initial ramdisk at: 0x%lx(va)/0x%llx(pa) (%llu bytes)\n", + initrd_start, phys_initrd_start, initrd_size); + + /** + * Usually, it means that there is an error in the + * initrd params. We should check the firmware. + */ + if ((phys_initrd_start + initrd_size) > memblock_end_of_DRAM()) { + /* Disable initrd */ + initrd_start = 0; + initrd_end = 0; + pr_err("Initial ramdisk exceed DRAM limitation\n"); + return; + } + + /* Reserve initrd */ + memblock_add(phys_initrd_start, initrd_size); + memblock_reserve(phys_initrd_start, initrd_size); +} +#endif /* CONFIG_BLK_DEV_INITRD */ + void __init sw64_memblock_init(void) { memblock_add(mem_desc.base, mem_desc.size); @@ -173,14 +232,21 @@ void __init sw64_memblock_init(void) memblock_add(__pa_symbol(_text), _end - _text); memblock_reserve(__pa_symbol(_text), _end - _text); +#ifdef CONFIG_BLK_DEV_INITRD /* Make sure initrd is in memory range. */ - if (sunway_boot_params->initrd_start) { - phys_addr_t base = __boot_pa(sunway_boot_params->initrd_start); - phys_addr_t size = sunway_boot_params->initrd_size; - - memblock_add(base, size); - memblock_reserve(base, size); - } + reserve_mem_for_initrd(); +#endif + /** + * When using non built-in DTB, we need to reserve + * it but avoid using early_init_fdt_reserve_self() + * since __pa() does not work for some old firmware. + * + * We can use early_init_fdt_reserve_self() instead + * when kernel no longer support C3B. + */ + if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) + memblock_reserve(__boot_pa(initial_boot_params), + fdt_totalsize(initial_boot_params)); /* end of DRAM range may have been changed */ max_pfn = max_low_pfn = PFN_DOWN(memblock_end_of_DRAM()); diff --git a/drivers/firmware/efi/sunway-init.c b/drivers/firmware/efi/sunway-init.c index 870abc2f5afe..8557c181c28c 100644 --- a/drivers/firmware/efi/sunway-init.c +++ b/drivers/firmware/efi/sunway-init.c @@ -179,20 +179,23 @@ void __init efi_init(void) struct efi_memory_map_data data; u64 efi_system_table; - if (sunway_boot_params->efi_systab == 0) { - pr_info("System Table is not exist, disabling EFI.\n"); - return; + if (sunway_boot_magic != 0xDEED2024UL) { + /* Legacy way: UEFI information placed in struct boot_params */ + efi_system_table = sunway_boot_params->efi_systab; + + data.desc_version = sunway_boot_params->efi_memdesc_version; + data.desc_size = sunway_boot_params->efi_memdesc_size; + data.size = sunway_boot_params->efi_memmap_size; + data.phys_map = sunway_boot_params->efi_memmap; + } else { + /* UEFI information placed in FDT("chosen" node) */ + efi_system_table = efi_get_fdt_params(&data); } - /* Grab UEFI information placed in struct boot_params by stub */ - efi_system_table = sunway_boot_params->efi_systab; - if (!efi_system_table) + if (efi_system_table == 0) { + pr_info("System Table is not exist, disabling EFI.\n"); return; - - data.desc_version = sunway_boot_params->efi_memdesc_version; - data.desc_size = sunway_boot_params->efi_memdesc_size; - data.size = sunway_boot_params->efi_memmap_size; - data.phys_map = sunway_boot_params->efi_memmap; + } if (efi_memmap_init_early(&data) < 0) { /* @@ -214,8 +217,6 @@ void __init efi_init(void) reserve_regions(); - memblock_reserve(sunway_boot_params->efi_memmap & PAGE_MASK, - PAGE_ALIGN(sunway_boot_params->efi_memmap_size + - (sunway_boot_params->efi_memmap & ~PAGE_MASK))); - + memblock_reserve(data.phys_map & PAGE_MASK, + PAGE_ALIGN(data.size + (data.phys_map & ~PAGE_MASK))); } -- Gitee From f1929cbf7aac367708bddb8c5ae95e4d124e1269 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Sat, 30 Mar 2024 13:57:54 +0800 Subject: [PATCH 71/98] sw64: improve the verification logic of DTB Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Provide better compatibility when using legacy boot_params. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/setup.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index eb4a37f1b86f..ba3402d2319d 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -543,10 +543,8 @@ static bool __init arch_dtb_verify(void *dt_virt, bool from_firmware) /* Only for non built-in DTB */ if (from_firmware && - (dt_phys < virt_to_phys((void *)__bss_stop))) { - pr_crit("DTB has been corrupted by kernel image!\n"); - return false; - } + (dt_phys < virt_to_phys((void *)__bss_stop))) + pr_warn("DTB(from firmware) may have been corrupted by kernel image!\n"); return true; } @@ -556,14 +554,18 @@ static void __init setup_firmware_fdt(void) void *dt_virt; const char *name; - /** - * Use DTB provided by firmware for early initialization, regardless - * of whether a Built-in DTB configured or not. Since we need the - * boot params from firmware when using new method to pass boot params. - */ - if (sunway_boot_magic != 0xDEED2024UL) + if (sunway_boot_magic != 0xDEED2024UL) { + /* Bypass DTB from firmware if built-in DTB configured */ + if (IS_ENABLED(CONFIG_BUILTIN_DTB)) + goto cmd_handle; dt_virt = (void *)sunway_boot_params->dtb_start; - else { + } else { + /** + * Use DTB provided by firmware for early initialization, + * regardless of whether a Built-in DTB configured or not. + * Since we need the boot params from firmware when using + * new method to pass boot params. + */ pr_info("Parse boot params in DTB chosen node\n"); dt_virt = (void *)sunway_dtb_address; } @@ -572,14 +574,16 @@ static void __init setup_firmware_fdt(void) !early_init_dt_scan(dt_virt)) { pr_crit("Invalid DTB(from firmware) at virtual address 0x%lx\n", (unsigned long)dt_virt); + while (true) cpu_relax(); } name = of_flat_dt_get_machine_name(); if (name) - pr_info("Machine model: %s\n", name); + pr_info("DTB(from firmware): Machine model: %s\n", name); +cmd_handle: /** * For C3B(xuelang), kernel command line always comes from * "sunway_boot_params->cmdline". These code can be removed @@ -608,6 +612,7 @@ static void __init setup_firmware_fdt(void) static void __init setup_builtin_fdt(void) { void *dt_virt; + const char *name; dt_virt = (void *)__dtb_start; if (!arch_dtb_verify(dt_virt, false) || @@ -617,6 +622,13 @@ static void __init setup_builtin_fdt(void) while (true) cpu_relax(); } + + /* Parse {size,address}-cells */ + early_init_dt_scan_root(); + + name = of_flat_dt_get_machine_name(); + if (name) + pr_info("DTB(built-in): Machine model: %s\n", name); } static void __init device_tree_init(void) -- Gitee From 13e8251fec32e7ad0b8418269fddc63f2e60b18e Mon Sep 17 00:00:00 2001 From: Jing Li Date: Mon, 18 Mar 2024 14:49:25 +0800 Subject: [PATCH 72/98] sw64: irq: fix compile error when PINTC or LPC-INTC is not set Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Fix compile error when CONFIG_SW64_PINTC=n or CONFIG_SW64_LPC_INTC=n. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/irq.h | 23 +++++++++++++++++++++-- drivers/irqchip/irq-sunway-cpu.c | 7 +++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/include/asm/irq.h b/arch/sw_64/include/asm/irq.h index e393162d928b..6a4abfc9687b 100644 --- a/arch/sw_64/include/asm/irq.h +++ b/arch/sw_64/include/asm/irq.h @@ -37,11 +37,30 @@ struct acpi_madt_sw_lpc_intc; extern int __init sw64_add_gsi_domain_map(u32 gsi_base, u32 gsi_count, struct fwnode_handle *handle); -extern int __init pintc_acpi_init(struct irq_domain *parent, - struct acpi_madt_sw_pintc *pintc); + extern int __init msic_acpi_init(struct irq_domain *parent, struct acpi_madt_sw_msic *msic); + +#ifdef CONFIG_SW64_PINTC +extern int __init pintc_acpi_init(struct irq_domain *parent, + struct acpi_madt_sw_pintc *pintc); +#else +static inline int __init pintc_acpi_init(struct irq_domain *parent, + struct acpi_madt_sw_pintc *pintc) +{ + return 0; +} +#endif + +#ifdef CONFIG_SW64_LPC_INTC extern int __init lpc_intc_acpi_init(struct irq_domain *parent, struct acpi_madt_sw_lpc_intc *lpc_intc); +#else +static inline int __init lpc_intc_acpi_init(struct irq_domain *parent, + struct acpi_madt_sw_lpc_intc *lpc_intc) +{ + return 0; +} +#endif #endif /* _ASM_SW64_IRQ_H */ diff --git a/drivers/irqchip/irq-sunway-cpu.c b/drivers/irqchip/irq-sunway-cpu.c index 2f4880036a2c..dca5020a789d 100644 --- a/drivers/irqchip/irq-sunway-cpu.c +++ b/drivers/irqchip/irq-sunway-cpu.c @@ -133,6 +133,7 @@ static void handle_nmi_int(void) pr_info("enter nmi int\n"); } +#ifdef CONFIG_SW64_PINTC static void handle_dev_int(struct pt_regs *regs) { unsigned long config_val, val, stat; @@ -152,6 +153,12 @@ static void handle_dev_int(struct pt_regs *regs) sw64_io_write(node, DEV_INT_CONFIG, config_val); } +#else +static void handle_dev_int(struct pt_regs *regs) +{ + pr_crit(PREFIX "the child controller PINTC is not configured!\n"); +} +#endif int pme_state; -- Gitee From a0f11dffa7b01c7f32105632d8dd5cffafb15176 Mon Sep 17 00:00:00 2001 From: Wang Yuanheng Date: Tue, 2 Apr 2024 10:56:37 +0800 Subject: [PATCH 73/98] sw64: fix secondary cpu bring up bug Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- If smp_rcb->ready is set after secondary cpu receives reset signal, the secondary cpu may fail to wake up. Signed-off-by: Wang Yuanheng Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/smp.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index f3ac8a899976..a57d05fe700f 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -139,6 +139,9 @@ static int secondary_cpu_start(int cpuid, struct task_struct *idle) set_secondary_ready(cpuid); + /* send reset signal */ + reset_cpu(cpuid); + /* Wait 10 seconds for secondary cpu. */ timeout = jiffies + 10*HZ; while (time_before(jiffies, timeout)) { @@ -318,7 +321,6 @@ int vt_cpu_up(unsigned int cpu, struct task_struct *tidle) wmb(); smp_rcb->ready = 0; /* irq must be disabled before reset vCPU */ - reset_cpu(cpu); smp_boot_one_cpu(cpu, tidle); return cpu_online(cpu) ? 0 : -EIO; @@ -340,13 +342,6 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle) /* send wake up signal */ send_wakeup_interrupt(cpu); #endif - /* send reset signal */ - if (is_in_host()) { - reset_cpu(cpu); - } else { - while (1) - cpu_relax(); - } smp_boot_one_cpu(cpu, tidle); #ifdef CONFIG_SUBARCH_C3B -- Gitee From b985c99dfa3bd8eb92e0e8dca00c5d2477c75473 Mon Sep 17 00:00:00 2001 From: He Sheng Date: Thu, 28 Mar 2024 10:31:56 +0800 Subject: [PATCH 74/98] sw64: rename static key and related simd libraries Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- No functional change intended. Signed-off-by: He Sheng Reviewed-by: Cui Wei Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/hw_init.h | 2 +- arch/sw_64/kernel/setup.c | 2 +- arch/sw_64/lib/Makefile | 12 +++++------ .../{deep-clear_page.S => clear_page_simd.S} | 0 ..._user-no_una_check.S => clear_user_simd.S} | 10 +++++----- ...rce_ali_addr.S => clear_user_simd_align.S} | 10 +++++----- .../{deep-copy_page.S => copy_page_simd.S} | 0 ..._ali_addr.S => copy_simd_align_template.S} | 0 ...te-no_una_check.S => copy_simd_template.S} | 0 ...y_user-no_una_check.S => copy_user_simd.S} | 10 +++++----- ...orce_ali_addr.S => copy_user_simd_align.S} | 10 +++++----- ...ep-memcpy-no_una_check.S => memcpy_simd.S} | 10 +++++----- ...y-force_ali_addr.S => memcpy_simd_align.S} | 10 +++++----- ...ep-memset-no_una_check.S => memset_simd.S} | 10 +++++----- ...t-force_ali_addr.S => memset_simd_align.S} | 10 +++++----- ...e_ali_addr.S => set_simd_align_template.S} | 2 +- ...ate-no_una_check.S => set_simd_template.S} | 0 arch/sw_64/lib/string.c | 20 +++++++++---------- arch/sw_64/lib/uaccess.c | 20 +++++++++---------- 19 files changed, 69 insertions(+), 69 deletions(-) rename arch/sw_64/lib/{deep-clear_page.S => clear_page_simd.S} (100%) rename arch/sw_64/lib/{deep-clear_user-no_una_check.S => clear_user_simd.S} (83%) rename arch/sw_64/lib/{deep-clear_user-force_ali_addr.S => clear_user_simd_align.S} (82%) rename arch/sw_64/lib/{deep-copy_page.S => copy_page_simd.S} (100%) rename arch/sw_64/lib/{deep-copy_template-force_ali_addr.S => copy_simd_align_template.S} (100%) rename arch/sw_64/lib/{deep-copy_template-no_una_check.S => copy_simd_template.S} (100%) rename arch/sw_64/lib/{deep-copy_user-no_una_check.S => copy_user_simd.S} (79%) rename arch/sw_64/lib/{deep-copy_user-force_ali_addr.S => copy_user_simd_align.S} (79%) rename arch/sw_64/lib/{deep-memcpy-no_una_check.S => memcpy_simd.S} (59%) rename arch/sw_64/lib/{deep-memcpy-force_ali_addr.S => memcpy_simd_align.S} (57%) rename arch/sw_64/lib/{deep-memset-no_una_check.S => memset_simd.S} (78%) rename arch/sw_64/lib/{deep-memset-force_ali_addr.S => memset_simd_align.S} (77%) rename arch/sw_64/lib/{deep-set_template-force_ali_addr.S => set_simd_align_template.S} (97%) rename arch/sw_64/lib/{deep-set_template-no_una_check.S => set_simd_template.S} (100%) diff --git a/arch/sw_64/include/asm/hw_init.h b/arch/sw_64/include/asm/hw_init.h index ab0e2ee4c9a6..5af3336d5fd6 100644 --- a/arch/sw_64/include/asm/hw_init.h +++ b/arch/sw_64/include/asm/hw_init.h @@ -99,7 +99,7 @@ DECLARE_STATIC_KEY_TRUE(run_mode_host_key); DECLARE_STATIC_KEY_FALSE(run_mode_guest_key); DECLARE_STATIC_KEY_FALSE(run_mode_emul_key); -DECLARE_STATIC_KEY_FALSE(core_hw_una_enabled); +DECLARE_STATIC_KEY_FALSE(hw_una_enabled); #define is_in_host() static_branch_likely(&run_mode_host_key) #define is_in_guest() static_branch_unlikely(&run_mode_guest_key) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index ba3402d2319d..cb69314d7684 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -108,7 +108,7 @@ 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(core_hw_una_enabled); +DEFINE_STATIC_KEY_FALSE(hw_una_enabled); struct cpu_desc_t cpu_desc; struct socket_desc_t socket_desc[MAX_NUMSOCKETS]; diff --git a/arch/sw_64/lib/Makefile b/arch/sw_64/lib/Makefile index 8d3bc1fdd604..a37d1ac0ca07 100644 --- a/arch/sw_64/lib/Makefile +++ b/arch/sw_64/lib/Makefile @@ -20,18 +20,18 @@ lib-y = __divlu.o __remlu.o __divwu.o __remwu.o \ uaccess.o lib-clear_page-y := clear_page.o -lib-clear_page-$(CONFIG_DEEP_CLEAR_PAGE) := deep-clear_page.o +lib-clear_page-$(CONFIG_DEEP_CLEAR_PAGE) := clear_page_simd.o -lib-clear_user-y := clear_user.o deep-clear_user-no_una_check.o deep-clear_user-force_ali_addr.o +lib-clear_user-y := clear_user.o clear_user_simd.o clear_user_simd_align.o lib-copy_page-y := copy_page.o -lib-copy_page-$(CONFIG_DEEP_COPY_PAGE) := deep-copy_page.o +lib-copy_page-$(CONFIG_DEEP_COPY_PAGE) := copy_page_simd.o -lib-copy_user-y := copy_user.o deep-copy_user-no_una_check.o deep-copy_user-force_ali_addr.o +lib-copy_user-y := copy_user.o copy_user_simd.o copy_user_simd_align.o -lib-memcpy-y := memcpy.o deep-memcpy-no_una_check.o deep-memcpy-force_ali_addr.o +lib-memcpy-y := memcpy.o memcpy_simd.o memcpy_simd_align.o -lib-memset-y := memset.o deep-memset-no_una_check.o deep-memset-force_ali_addr.o +lib-memset-y := memset.o memset_simd.o memset_simd_align.o lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o diff --git a/arch/sw_64/lib/deep-clear_page.S b/arch/sw_64/lib/clear_page_simd.S similarity index 100% rename from arch/sw_64/lib/deep-clear_page.S rename to arch/sw_64/lib/clear_page_simd.S diff --git a/arch/sw_64/lib/deep-clear_user-no_una_check.S b/arch/sw_64/lib/clear_user_simd.S similarity index 83% rename from arch/sw_64/lib/deep-clear_user-no_una_check.S rename to arch/sw_64/lib/clear_user_simd.S index da25c6be66fb..a8d6eebfc4f8 100644 --- a/arch/sw_64/lib/deep-clear_user-no_una_check.S +++ b/arch/sw_64/lib/clear_user_simd.S @@ -28,9 +28,9 @@ * $18: bytes left to copy * */ - .globl ____clear_user_simd_no_una_check - .ent ____clear_user_simd_no_una_check -____clear_user_simd_no_una_check: + .globl ____clear_user_simd + .ent ____clear_user_simd +____clear_user_simd: .prologue 0 bis $31, $31, $7 mov $17, $18 @@ -38,7 +38,7 @@ ____clear_user_simd_no_una_check: #ifdef CONFIG_SUBARCH_C4 csrr $6, CSR_WR_FREGS #endif -#include "deep-set_template-no_una_check.S" +#include "set_simd_template.S" 255: bis $31, $18, $0 beq $7, $return @@ -51,4 +51,4 @@ $return: csrw $6, CSR_WR_FREGS #endif ret - .end ____clear_user_simd_no_una_check + .end ____clear_user_simd diff --git a/arch/sw_64/lib/deep-clear_user-force_ali_addr.S b/arch/sw_64/lib/clear_user_simd_align.S similarity index 82% rename from arch/sw_64/lib/deep-clear_user-force_ali_addr.S rename to arch/sw_64/lib/clear_user_simd_align.S index 78d989609e12..3c1cd06f742f 100644 --- a/arch/sw_64/lib/deep-clear_user-force_ali_addr.S +++ b/arch/sw_64/lib/clear_user_simd_align.S @@ -28,9 +28,9 @@ * $18: bytes left to copy * */ - .globl ____clear_user_simd_force_ali_addr - .ent ____clear_user_simd_force_ali_addr -____clear_user_simd_force_ali_addr: + .globl ____clear_user_simd_align + .ent ____clear_user_simd_align +____clear_user_simd_align: .prologue 0 bis $31, $31, $7 mov $17, $18 @@ -38,7 +38,7 @@ ____clear_user_simd_force_ali_addr: #ifdef CONFIG_SUBARCH_C4 csrr $6, CSR_WR_FREGS #endif -#include "deep-set_template-force_ali_addr.S" +#include "set_simd_align_template.S" 255: bis $31, $18, $0 beq $7, $return @@ -51,4 +51,4 @@ $return: csrw $6, CSR_WR_FREGS #endif ret - .end ____clear_user_simd_force_ali_addr + .end ____clear_user_simd_align diff --git a/arch/sw_64/lib/deep-copy_page.S b/arch/sw_64/lib/copy_page_simd.S similarity index 100% rename from arch/sw_64/lib/deep-copy_page.S rename to arch/sw_64/lib/copy_page_simd.S diff --git a/arch/sw_64/lib/deep-copy_template-force_ali_addr.S b/arch/sw_64/lib/copy_simd_align_template.S similarity index 100% rename from arch/sw_64/lib/deep-copy_template-force_ali_addr.S rename to arch/sw_64/lib/copy_simd_align_template.S diff --git a/arch/sw_64/lib/deep-copy_template-no_una_check.S b/arch/sw_64/lib/copy_simd_template.S similarity index 100% rename from arch/sw_64/lib/deep-copy_template-no_una_check.S rename to arch/sw_64/lib/copy_simd_template.S diff --git a/arch/sw_64/lib/deep-copy_user-no_una_check.S b/arch/sw_64/lib/copy_user_simd.S similarity index 79% rename from arch/sw_64/lib/deep-copy_user-no_una_check.S rename to arch/sw_64/lib/copy_user_simd.S index cadd5e0f31c1..02082a2f2e1c 100644 --- a/arch/sw_64/lib/deep-copy_user-no_una_check.S +++ b/arch/sw_64/lib/copy_user_simd.S @@ -21,16 +21,16 @@ * $18: bytes left to copy * */ - .globl ____copy_user_simd_no_una_check - .ent ____copy_user_simd_no_una_check -____copy_user_simd_no_una_check: + .globl ____copy_user_simd + .ent ____copy_user_simd +____copy_user_simd: .prologue 0 .set noreorder bis $31, $31, $7 #ifdef CONFIG_SUBARCH_C4 csrr $6, CSR_WR_FREGS #endif -#include "deep-copy_template-no_una_check.S" +#include "copy_simd_template.S" 255: bis $31, $18, $0 beq $7, $return @@ -45,4 +45,4 @@ $return: csrw $6, CSR_WR_FREGS #endif ret - .end ____copy_user_simd_no_una_check + .end ____copy_user_simd diff --git a/arch/sw_64/lib/deep-copy_user-force_ali_addr.S b/arch/sw_64/lib/copy_user_simd_align.S similarity index 79% rename from arch/sw_64/lib/deep-copy_user-force_ali_addr.S rename to arch/sw_64/lib/copy_user_simd_align.S index febb46f9b691..c459ca0f95ae 100644 --- a/arch/sw_64/lib/deep-copy_user-force_ali_addr.S +++ b/arch/sw_64/lib/copy_user_simd_align.S @@ -21,16 +21,16 @@ * $18: bytes left to copy * */ - .globl ____copy_user_simd_force_ali_addr - .ent ____copy_user_simd_force_ali_addr -____copy_user_simd_force_ali_addr: + .globl ____copy_user_simd_align + .ent ____copy_user_simd_align +____copy_user_simd_align: .prologue 0 .set noreorder bis $31, $31, $7 #ifdef CONFIG_SUBARCH_C4 csrr $6, CSR_WR_FREGS #endif -#include "deep-copy_template-force_ali_addr.S" +#include "copy_simd_align_template.S" 255: bis $31, $18, $0 beq $7, $return @@ -49,4 +49,4 @@ $return: csrw $6, CSR_WR_FREGS #endif ret - .end ____copy_user_simd_force_ali_addr + .end ____copy_user_simd_align diff --git a/arch/sw_64/lib/deep-memcpy-no_una_check.S b/arch/sw_64/lib/memcpy_simd.S similarity index 59% rename from arch/sw_64/lib/deep-memcpy-no_una_check.S rename to arch/sw_64/lib/memcpy_simd.S index c7ded71b1ade..f42d8efb00b6 100644 --- a/arch/sw_64/lib/deep-memcpy-no_una_check.S +++ b/arch/sw_64/lib/memcpy_simd.S @@ -5,19 +5,19 @@ #define FIXUP_LDST(x, y) \ x, y - .globl ____memcpy_simd_no_una_check - .ent ____memcpy_simd_no_una_check -____memcpy_simd_no_una_check: + .globl ____memcpy_simd + .ent ____memcpy_simd +____memcpy_simd: .frame $30, 0, $26, 0 .prologue 0 mov $16, $0 #ifdef CONFIG_SUBARCH_C4 csrr $6, CSR_WR_FREGS #endif -#include "deep-copy_template-no_una_check.S" +#include "copy_simd_template.S" 255: #ifdef CONFIG_SUBARCH_C4 csrw $6, CSR_WR_FREGS #endif ret - .end ____memcpy_simd_no_una_check + .end ____memcpy_simd diff --git a/arch/sw_64/lib/deep-memcpy-force_ali_addr.S b/arch/sw_64/lib/memcpy_simd_align.S similarity index 57% rename from arch/sw_64/lib/deep-memcpy-force_ali_addr.S rename to arch/sw_64/lib/memcpy_simd_align.S index 7e990bda936c..6450c96a2406 100644 --- a/arch/sw_64/lib/deep-memcpy-force_ali_addr.S +++ b/arch/sw_64/lib/memcpy_simd_align.S @@ -5,19 +5,19 @@ #define FIXUP_LDST(x, y) \ x, y - .globl ____memcpy_simd_force_ali_addr - .ent ____memcpy_simd_force_ali_addr -____memcpy_simd_force_ali_addr: + .globl ____memcpy_simd_align + .ent ____memcpy_simd_align +____memcpy_simd_align: .frame $30, 0, $26, 0 .prologue 0 mov $16, $0 #ifdef CONFIG_SUBARCH_C4 csrr $6, CSR_WR_FREGS #endif -#include "deep-copy_template-force_ali_addr.S" +#include "copy_simd_align_template.S" 255: #ifdef CONFIG_SUBARCH_C4 csrw $6, CSR_WR_FREGS #endif ret - .end ____memcpy_simd_force_ali_addr + .end ____memcpy_simd_align diff --git a/arch/sw_64/lib/deep-memset-no_una_check.S b/arch/sw_64/lib/memset_simd.S similarity index 78% rename from arch/sw_64/lib/deep-memset-no_una_check.S rename to arch/sw_64/lib/memset_simd.S index 91525bd67790..03d301cccf7a 100644 --- a/arch/sw_64/lib/deep-memset-no_una_check.S +++ b/arch/sw_64/lib/memset_simd.S @@ -35,20 +35,20 @@ .text .align 4 - .globl ____constant_c_memset_simd_no_una_check - .ent ____constant_c_memset_simd_no_una_check + .globl ____constant_c_memset_simd + .ent ____constant_c_memset_simd .frame $30, 0, $26, 0 .prologue 0 -____constant_c_memset_simd_no_una_check: +____constant_c_memset_simd: bis $31, $31, $7 bis $31, $16, $0 #ifdef CONFIG_SUBARCH_C4 csrr $6, CSR_WR_FREGS #endif -#include "deep-set_template-no_una_check.S" +#include "set_simd_template.S" 255: #ifdef CONFIG_SUBARCH_C4 csrw $6, CSR_WR_FREGS #endif ret - .end ____constant_c_memset_simd_no_una_check + .end ____constant_c_memset_simd diff --git a/arch/sw_64/lib/deep-memset-force_ali_addr.S b/arch/sw_64/lib/memset_simd_align.S similarity index 77% rename from arch/sw_64/lib/deep-memset-force_ali_addr.S rename to arch/sw_64/lib/memset_simd_align.S index cbb0130100dd..f5329cd6125e 100644 --- a/arch/sw_64/lib/deep-memset-force_ali_addr.S +++ b/arch/sw_64/lib/memset_simd_align.S @@ -35,20 +35,20 @@ .text .align 4 - .globl ____constant_c_memset_simd_force_ali_addr - .ent ____constant_c_memset_simd_force_ali_addr + .globl ____constant_c_memset_simd_align + .ent ____constant_c_memset_simd_align .frame $30, 0, $26, 0 .prologue 0 -____constant_c_memset_simd_force_ali_addr: +____constant_c_memset_simd_align: bis $31, $31, $7 bis $31, $16, $0 #ifdef CONFIG_SUBARCH_C4 csrr $6, CSR_WR_FREGS #endif -#include "deep-set_template-force_ali_addr.S" +#include "set_simd_align_template.S" 255: #ifdef CONFIG_SUBARCH_C4 csrw $6, CSR_WR_FREGS #endif ret - .end ____constant_c_memset_simd_force_ali_addr + .end ____constant_c_memset_simd_align diff --git a/arch/sw_64/lib/deep-set_template-force_ali_addr.S b/arch/sw_64/lib/set_simd_align_template.S similarity index 97% rename from arch/sw_64/lib/deep-set_template-force_ali_addr.S rename to arch/sw_64/lib/set_simd_align_template.S index d581e2eb35d7..fa77cacf684f 100644 --- a/arch/sw_64/lib/deep-set_template-force_ali_addr.S +++ b/arch/sw_64/lib/set_simd_align_template.S @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * template for memcpy and copy_user with SIMD + * template for memset and clear_user with SIMD * * $7: SIMD status * 0: not in simd loop diff --git a/arch/sw_64/lib/deep-set_template-no_una_check.S b/arch/sw_64/lib/set_simd_template.S similarity index 100% rename from arch/sw_64/lib/deep-set_template-no_una_check.S rename to arch/sw_64/lib/set_simd_template.S diff --git a/arch/sw_64/lib/string.c b/arch/sw_64/lib/string.c index ef7439b3715b..e1ff596d8667 100644 --- a/arch/sw_64/lib/string.c +++ b/arch/sw_64/lib/string.c @@ -5,18 +5,18 @@ #include extern void *____memcpy_sisd(void *dest, const void *src, size_t n); -extern void *____memcpy_simd_no_una_check(void *dest, const void *src, size_t n); -extern void *____memcpy_simd_force_ali_addr(void *dest, const void *src, size_t n); +extern void *____memcpy_simd(void *dest, const void *src, size_t n); +extern void *____memcpy_simd_align(void *dest, const void *src, size_t n); static inline void *____memcpy(void *dest, const void *src, size_t n) { if (!IS_ENABLED(CONFIG_DEEP_MEMCPY)) return ____memcpy_sisd(dest, src, n); - if (static_branch_likely(&core_hw_una_enabled)) - return ____memcpy_simd_no_una_check(dest, src, n); + if (static_branch_likely(&hw_una_enabled)) + return ____memcpy_simd(dest, src, n); else - return ____memcpy_simd_force_ali_addr(dest, src, n); + return ____memcpy_simd_align(dest, src, n); } void *memcpy(void *dest, const void *src, size_t n) @@ -33,18 +33,18 @@ void *__memcpy(void *dest, const void *src, size_t n) EXPORT_SYMBOL(__memcpy); extern void *____constant_c_memset_sisd(void *s, unsigned long c, size_t n); -extern void *____constant_c_memset_simd_no_una_check(void *s, unsigned long c, size_t n); -extern void *____constant_c_memset_simd_force_ali_addr(void *s, unsigned long c, size_t n); +extern void *____constant_c_memset_simd(void *s, unsigned long c, size_t n); +extern void *____constant_c_memset_simd_align(void *s, unsigned long c, size_t n); static inline void *____constant_c_memset(void *s, unsigned long c, size_t n) { if (!IS_ENABLED(CONFIG_DEEP_MEMSET)) return ____constant_c_memset_sisd(s, c, n); - if (static_branch_likely(&core_hw_una_enabled)) - return ____constant_c_memset_simd_no_una_check(s, c, n); + if (static_branch_likely(&hw_una_enabled)) + return ____constant_c_memset_simd(s, c, n); else - return ____constant_c_memset_simd_force_ali_addr(s, c, n); + return ____constant_c_memset_simd_align(s, c, n); } void *__constant_c_memset(void *s, unsigned long c, size_t n) diff --git a/arch/sw_64/lib/uaccess.c b/arch/sw_64/lib/uaccess.c index f8efa5ad853d..fd28379fdc22 100644 --- a/arch/sw_64/lib/uaccess.c +++ b/arch/sw_64/lib/uaccess.c @@ -5,33 +5,33 @@ #include extern long ____copy_user_sisd(void *to, const void *from, long len); -extern long ____copy_user_simd_no_una_check(void *to, const void *from, long len); -extern long ____copy_user_simd_force_ali_addr(void *to, const void *from, long len); +extern long ____copy_user_simd(void *to, const void *from, long len); +extern long ____copy_user_simd_align(void *to, const void *from, long len); long __copy_user(void *to, const void *from, long len) { if (!IS_ENABLED(CONFIG_DEEP_COPY_USER)) return ____copy_user_sisd(to, from, len); - if (static_branch_likely(&core_hw_una_enabled)) - return ____copy_user_simd_no_una_check(to, from, len); + if (static_branch_likely(&hw_una_enabled)) + return ____copy_user_simd(to, from, len); else - return ____copy_user_simd_force_ali_addr(to, from, len); + return ____copy_user_simd_align(to, from, len); } EXPORT_SYMBOL(__copy_user); extern long ____clear_user_sisd(void __user *to, long len); -extern long ____clear_user_simd_no_una_check(void __user *to, long len); -extern long ____clear_user_simd_force_ali_addr(void __user *to, long len); +extern long ____clear_user_simd(void __user *to, long len); +extern long ____clear_user_simd_align(void __user *to, long len); long __clear_user(void __user *to, long len) { if (!IS_ENABLED(CONFIG_DEEP_CLEAR_USER)) return ____clear_user_sisd(to, len); - if (static_branch_likely(&core_hw_una_enabled)) - return ____clear_user_simd_no_una_check(to, len); + if (static_branch_likely(&hw_una_enabled)) + return ____clear_user_simd(to, len); else - return ____clear_user_simd_force_ali_addr(to, len); + return ____clear_user_simd_align(to, len); } EXPORT_SYMBOL(__clear_user); -- Gitee From ef281410c48b6c3c45617ee9ccff982a9c06f2ef Mon Sep 17 00:00:00 2001 From: Wang Yuanheng Date: Tue, 2 Apr 2024 16:59:29 +0800 Subject: [PATCH 75/98] sw64: redesign run mode setup method Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- For C4, run mode is determined by the lower two bits of sunway_boot_magic passed in by firmware. Signed-off-by: Wang Yuanheng Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/setup.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index cb69314d7684..564fc74de2b3 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -701,9 +701,10 @@ static void __init setup_cpu_info(void) } } +#ifdef CONFIG_SUBARCH_C3B static void __init setup_run_mode(void) { - if (rvpcr() >> VPCR_SHIFT) { + if (*(unsigned long *)MMSIZE) { static_branch_disable(&run_mode_host_key); if (*(unsigned long *)MM_SIZE & EMUL_FLAG) { pr_info("run mode: emul\n"); @@ -722,6 +723,29 @@ static void __init setup_run_mode(void) static_branch_disable(&run_mode_emul_key); } } +#elif CONFIG_SUBARCH_C4 +static void __init setup_run_mode(void) +{ + if (rvpcr() >> VPCR_SHIFT) { + pr_info("run mode: guest\n"); + static_branch_disable(&run_mode_host_key); + static_branch_disable(&run_mode_emul_key); + static_branch_enable(&run_mode_guest_key); + } else if (sunway_boot_magic == 0xA2024) { + pr_info("run mode: emul\n"); + static_branch_disable(&run_mode_host_key); + static_branch_disable(&run_mode_guest_key); + static_branch_enable(&run_mode_emul_key); + sunway_boot_magic = 0xDEED2024; + } else { + pr_info("run mode: host\n"); + static_branch_disable(&run_mode_guest_key); + static_branch_disable(&run_mode_emul_key); + static_branch_enable(&run_mode_host_key); + } + +} +#endif static void __init setup_socket_info(void) { -- Gitee From 14094c67278405ebf0f6a14c168893ac6c08babe Mon Sep 17 00:00:00 2001 From: Zhou Xuemei Date: Mon, 8 Apr 2024 11:40:59 +0000 Subject: [PATCH 76/98] sw64: ahci: disable parallel bus scan Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- On sw64 platform, if scan this host(type MARVELL 9230) in parallel, ahci ports reset failed as follows: ata4: link is slow to respond, please be patient (ready=0) ata8.00: qc timeout (cmd 0xa1) ata8.00: failed to IDENTIFY (I/O error, err_mask=0x4) ata3: link is slow to respond, please be patient (ready=0) ata8: SATA link up 1.5 Gbps (SStatus 113 SControl 300) ata4: COMRESET failed (errno=-16) ata3: COMRESET failed (errno=-16) ata4: link is slow to respond, please be patient (ready=0) ata3: link is slow to respond, please be patient (ready=0) ata8.00: qc timeout (cmd 0xa1) ata8.00: failed to IDENTIFY (I/O error, err_mask=0x4) ata8: SATA link up 1.5 Gbps (SStatus 113 SControl 300) ata4: COMRESET failed (errno=-16) ata3: COMRESET failed (errno=-16) ata3: link is slow to respond, please be patient (ready=0) ata4: link is slow to respond, please be patient (ready=0) ata8.00: qc timeout (cmd 0xa1) ata8.00: failed to IDENTIFY (I/O error, err_mask=0x4) ata8: SATA link up 1.5 Gbps (SStatus 113 SControl 300) ata4: COMRESET failed (errno=-16) ata4: limiting SATA link speed to 3.0 Gbps ata3: COMRESET failed (errno=-16) ata3: limiting SATA link speed to 3.0 Gbps ata4: COMRESET failed (errno=-16) ata4: reset failed, giving up ata3: COMRESET failed (errno=-16) ata3: reset failed, giving up To work around this problem, we disable it for synchronous scanning. Signed-off-by: Zhou Xuemei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/ata/ahci.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 5d9514ffff2a..e377a065d491 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1992,10 +1992,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } hpriv->irq = pci_irq_vector(pdev, 0); - if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) - host->flags |= ATA_HOST_PARALLEL_SCAN; - else - dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n"); + if (!IS_ENABLED(CONFIG_SW64)) { + if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) + host->flags |= ATA_HOST_PARALLEL_SCAN; + else + dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n"); + } if (!(hpriv->cap & HOST_CAP_PART)) host->flags |= ATA_HOST_NO_PART; -- Gitee From 85010445f45e49843262e21dcad8dfd045f6064c Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 9 Apr 2024 19:45:57 +0800 Subject: [PATCH 77/98] sw64: acpi: disable ACPI for xuelang Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Enabling ACPI on xuelang platform requires the latest firmware, otherwise kernel may fail to boot. To avoid potential risks, disable ACPI for xuelang platform. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/acpi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/kernel/acpi.c b/arch/sw_64/kernel/acpi.c index af80ae304948..c50ae846ff62 100644 --- a/arch/sw_64/kernel/acpi.c +++ b/arch/sw_64/kernel/acpi.c @@ -361,6 +361,12 @@ static int __init acpi_process_madt_sw_cintc(void) void __init acpi_boot_table_init(void) { + if (IS_ENABLED(CONFIG_SUBARCH_C3B)) { + pr_info(PREFIX "Current platform does not support ACPI\n"); + disable_acpi(); + return; + } + /** * ACPI is disabled by default. * ACPI is only enabled when firmware passes ACPI table @@ -375,7 +381,6 @@ void __init acpi_boot_table_init(void) 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(); -- Gitee From b6fc016cf8a050795042c45dacec53054d98fdb4 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 9 Apr 2024 15:03:31 +0800 Subject: [PATCH 78/98] sw64: fix compile error of MMSIZE Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- The MMSIZE macro has been renamed to MM_SIZE to avoid conflicts with MMSIZE in fdtparams.c. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 564fc74de2b3..ad1e90876d5e 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -704,7 +704,7 @@ static void __init setup_cpu_info(void) #ifdef CONFIG_SUBARCH_C3B static void __init setup_run_mode(void) { - if (*(unsigned long *)MMSIZE) { + if (*(unsigned long *)MM_SIZE) { static_branch_disable(&run_mode_host_key); if (*(unsigned long *)MM_SIZE & EMUL_FLAG) { pr_info("run mode: emul\n"); -- Gitee From c0d60a8df1ac4c82f5cd072bdccb1a19746bf9e4 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 3 Apr 2024 09:30:21 +0800 Subject: [PATCH 79/98] sw64: get mclk and external clk from firmware Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Starting from junzhang, kernel will not directly access Motherboard Configuration Tables to get mclk and external clk. Instead, kernel get mclk and external clk from firmware. This commit will not break backward compatibility. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/setup.h | 16 ++++++-- arch/sw_64/kernel/setup.c | 66 ++++++++++++++++++++++++++++++++ drivers/clocksource/timer-sw64.c | 7 +++- 3 files changed, 84 insertions(+), 5 deletions(-) diff --git a/arch/sw_64/include/asm/setup.h b/arch/sw_64/include/asm/setup.h index 2d557b349555..0a2edf9af3ca 100644 --- a/arch/sw_64/include/asm/setup.h +++ b/arch/sw_64/include/asm/setup.h @@ -38,14 +38,22 @@ #define INITRD_START_OFF (0x10000UL - 0xA100UL) #define INITRD_SIZE_OFF (0x10000UL - 0xA108UL) -/* Motherboard Configuration Tables */ -#define MB_CONFIG_START 0x908000 -#define MB_MCLK (MB_CONFIG_START + 0x1) -#define MB_EXTCLK (MB_CONFIG_START + 0x11) +/** + * Motherboard Configuration Tables + * + * Starting from junzhang, we will not directly access Motherboard + * Configuration Tables in kernel. These macros and related code can + * be removed when kernel no longer support C3B(xuelang). + */ +#define MB_CONFIG_START 0x908000 +#define MB_MCLK (MB_CONFIG_START + 0x1) +#define MB_EXTCLK (MB_CONFIG_START + 0x11) #ifndef __ASSEMBLY__ #include extern struct boot_params *sunway_boot_params; +extern u64 sunway_mclk_hz; +extern u64 sunway_extclk_hz; #endif #endif /* _ASM_SW64_SETUP_H */ diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index ad1e90876d5e..b154165dcb24 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -19,6 +19,7 @@ #endif #include #include +#include #include #include #include @@ -131,6 +132,9 @@ EXPORT_SYMBOL(sunway_boot_magic); unsigned long sunway_dtb_address; EXPORT_SYMBOL(sunway_dtb_address); +u64 sunway_mclk_hz; +u64 sunway_extclk_hz; + /* * The format of "screen_info" is strange, and due to early * i386-setup code. This is just enough to make the console @@ -549,6 +553,34 @@ static bool __init arch_dtb_verify(void *dt_virt, bool from_firmware) return true; } +static void early_parse_fdt_property(const void *fdt, const char *path, + const char *prop_name, u64 *property, int size) +{ + int node, prop_len; + const __be32 *prop; + + if (!path || !prop_name) + return; + + node = fdt_path_offset(fdt, path); + if (node < 0) { + pr_err("Failed to get node [%s]\n", path); + return; + } + + prop = fdt_getprop(initial_boot_params, node, prop_name, &prop_len); + if (!prop) { + pr_err("Failed to get property [%s]\n", prop_name); + return; + } + + if (prop_len != size) + pr_warn("Expect [%s] %d bytes, but %d bytes\n", + prop_name, size, prop_len); + + *property = of_read_number(prop, size / 4); +} + static void __init setup_firmware_fdt(void) { void *dt_virt; @@ -579,6 +611,18 @@ static void __init setup_firmware_fdt(void) cpu_relax(); } + if (sunway_boot_magic == 0xDEED2024UL) { + /* Parse MCLK(Hz) from firmware DTB */ + early_parse_fdt_property(dt_virt, "/soc/clocks/mclk", + "clock-frequency", &sunway_mclk_hz, sizeof(u32)); + pr_info("MCLK: %llu Hz\n", sunway_mclk_hz); + + /* Parse EXTCLK(Hz) from firmware DTB */ + early_parse_fdt_property(dt_virt, "/soc/clocks/extclk", + "clock-frequency", &sunway_extclk_hz, sizeof(u32)); + pr_info("EXTCLK: %llu Hz\n", sunway_extclk_hz); + } + name = of_flat_dt_get_machine_name(); if (name) pr_info("DTB(from firmware): Machine model: %s\n", name); @@ -1019,6 +1063,28 @@ static int __init debugfs_sw64(void) return 0; } arch_initcall(debugfs_sw64); + +static int __init debugfs_mclk_init(void) +{ + struct dentry *dir = sw64_debugfs_dir; + static u64 mclk_mhz, mclk_hz; + + if (!dir) + return -ENODEV; + + if (sunway_boot_magic != 0xDEED2024UL) { + mclk_mhz = *((unsigned char *)__va(MB_MCLK)); + mclk_hz = mclk_mhz * 1000000; + debugfs_create_u64("mclk", 0644, dir, &mclk_mhz); + debugfs_create_u64("mclk_hz", 0644, dir, &mclk_hz); + } else { + mclk_hz = sunway_mclk_hz; + debugfs_create_u64("mclk_hz", 0644, dir, &mclk_hz); + } + + return 0; +} +late_initcall(debugfs_mclk_init); #endif #ifdef CONFIG_OF diff --git a/drivers/clocksource/timer-sw64.c b/drivers/clocksource/timer-sw64.c index a2f4caced0a3..c70cf340a4b9 100644 --- a/drivers/clocksource/timer-sw64.c +++ b/drivers/clocksource/timer-sw64.c @@ -47,7 +47,12 @@ early_param("mclk_khz", setup_mclk); void __init sw64_setup_clocksource(void) { - unsigned long mclk_khz = *((unsigned char *)__va(MB_MCLK)) * 1000; + unsigned long mclk_khz; + + if (sunway_mclk_hz) + mclk_khz = sunway_mclk_hz / 1000; + else + mclk_khz = *((unsigned char *)__va(MB_MCLK)) * 1000; if (override_mclk_khz) { mclk_khz = override_mclk_khz; -- Gitee From 49e2eb556b93e87caf9cf4681bae3d15aa313217 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 10 Apr 2024 10:29:28 +0800 Subject: [PATCH 80/98] sw64: pci: adjust the maximum number of RC per node Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Adjust the maximum number of RC per node from 6 to 12, since the upcoming hardware platform supports 12 RC per node. This commit also update the OEM table ID of MCFG. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/pci.h | 3 ++ arch/sw_64/include/asm/uncore_io_junzhang.h | 3 -- arch/sw_64/include/asm/uncore_io_xuelang.h | 3 -- arch/sw_64/pci/pci-legacy.c | 6 +-- drivers/acpi/pci_mcfg.c | 46 ++++++++++----------- drivers/pci/controller/pci-sunway.c | 13 ++++-- 6 files changed, 39 insertions(+), 35 deletions(-) diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index 07c447479efa..f39d07144af9 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -107,6 +107,7 @@ extern int sw64_pcie_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val); extern void pci_mark_rc_linkup(unsigned long node, unsigned long index); +extern void pci_clear_rc_linkup(unsigned long node, unsigned long index); extern int pci_get_rc_linkup(unsigned long node, unsigned long index); #ifdef CONFIG_PCI_DOMAINS @@ -171,4 +172,6 @@ extern int chip_pcie_configure(struct pci_controller *hose); #define PCITODMA_OFFSET 0x0 /*0 offset*/ +#define MAX_NR_RCS_PER_NODE 12 + #endif /* _ASM_SW64_PCI_H */ diff --git a/arch/sw_64/include/asm/uncore_io_junzhang.h b/arch/sw_64/include/asm/uncore_io_junzhang.h index c0f759bbe740..2f745fe35365 100644 --- a/arch/sw_64/include/asm/uncore_io_junzhang.h +++ b/arch/sw_64/include/asm/uncore_io_junzhang.h @@ -48,9 +48,6 @@ #define SW64_PCI0_BUS 0 #define PCI0_BUS SW64_PCI0_BUS -#define MAX_NR_NODES 0x2 -#define MAX_NR_RCS 0x6 - #define SPBU_BASE (0x3UL << 36) #define INTPU_BASE (0x3aUL << 32) #define IIC0_BASE (0x31UL << 32) diff --git a/arch/sw_64/include/asm/uncore_io_xuelang.h b/arch/sw_64/include/asm/uncore_io_xuelang.h index aeaadec5be16..695ce68dded9 100644 --- a/arch/sw_64/include/asm/uncore_io_xuelang.h +++ b/arch/sw_64/include/asm/uncore_io_xuelang.h @@ -47,9 +47,6 @@ #define SW64_PCI0_BUS 0 #define PCI0_BUS SW64_PCI0_BUS -#define MAX_NR_NODES 0x2 -#define MAX_NR_RCS 0x6 - #define MCU_BASE (0x3UL << 36) #define CAB0_BASE (0x10UL << 32) #define INTPU_BASE (0x2aUL << 32) diff --git a/arch/sw_64/pci/pci-legacy.c b/arch/sw_64/pci/pci-legacy.c index bfaa08bf72c0..15ee626593e9 100644 --- a/arch/sw_64/pci/pci-legacy.c +++ b/arch/sw_64/pci/pci-legacy.c @@ -244,7 +244,7 @@ static bool __init is_any_rc_linkup_one_node(unsigned long node) { int i; - for (i = 0; i < 8; ++i) { + for (i = 0; i < MAX_NR_RCS_PER_NODE; ++i) { if (pci_get_rc_linkup(node, i)) return true; } @@ -279,14 +279,14 @@ void __init sw64_init_arch(void) pr_notice("PCIe is disabled on node %ld\n", node); continue; } - for (i = 0; i < MAX_NR_RCS; i++) { + for (i = 0; i < MAX_NR_RCS_PER_NODE; i++) { if ((rc_enable >> i) & 0x1) sw64_init_host(node, i); } if (is_any_rc_linkup_one_node(node)) { memset(msg, 0, 64); sprintf(msg, "Node %ld: RC [ ", node); - for (i = 0; i < MAX_NR_RCS; i++) { + for (i = 0; i < MAX_NR_RCS_PER_NODE; i++) { if (pci_get_rc_linkup(node, i)) { memset(id, 0, 8); sprintf(id, "%d ", i); diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c index db8c4a6f837c..b05d3cb94b68 100644 --- a/drivers/acpi/pci_mcfg.c +++ b/drivers/acpi/pci_mcfg.c @@ -201,29 +201,29 @@ static struct mcfg_fixup mcfg_quirks[] = { #endif /* LOONGARCH */ #ifdef CONFIG_SW64 -#define _SW64_ECAM_QUIRK(rev, seg) \ - { "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),\ - _SW64_ECAM_QUIRK(rev, node * 8 + 3),\ - _SW64_ECAM_QUIRK(rev, node * 8 + 4),\ - _SW64_ECAM_QUIRK(rev, node * 8 + 5),\ - _SW64_ECAM_QUIRK(rev, node * 8 + 6),\ - _SW64_ECAM_QUIRK(rev, node * 8 + 7) - - /** - * According to the address space of sw64, up to 8 nodes supported - * with a maximum of 8 pcie controllers per node - */ - SW64_ECAM_QUIRK(1, 0x00), - SW64_ECAM_QUIRK(1, 0x01), - SW64_ECAM_QUIRK(1, 0x02), - SW64_ECAM_QUIRK(1, 0x03), - SW64_ECAM_QUIRK(1, 0x04), - SW64_ECAM_QUIRK(1, 0x05), - SW64_ECAM_QUIRK(1, 0x06), - SW64_ECAM_QUIRK(1, 0x07), +#define SW64_ECAM_QUIRK(table_id, rev, node, ops) \ + { "SUNWAY", table_id, rev, ((node) * MAX_NR_RCS_PER_NODE + 0), MCFG_BUS_ANY, ops }, \ + { "SUNWAY", table_id, rev, ((node) * MAX_NR_RCS_PER_NODE + 1), MCFG_BUS_ANY, ops }, \ + { "SUNWAY", table_id, rev, ((node) * MAX_NR_RCS_PER_NODE + 2), MCFG_BUS_ANY, ops }, \ + { "SUNWAY", table_id, rev, ((node) * MAX_NR_RCS_PER_NODE + 3), MCFG_BUS_ANY, ops }, \ + { "SUNWAY", table_id, rev, ((node) * MAX_NR_RCS_PER_NODE + 4), MCFG_BUS_ANY, ops }, \ + { "SUNWAY", table_id, rev, ((node) * MAX_NR_RCS_PER_NODE + 5), MCFG_BUS_ANY, ops }, \ + { "SUNWAY", table_id, rev, ((node) * MAX_NR_RCS_PER_NODE + 6), MCFG_BUS_ANY, ops }, \ + { "SUNWAY", table_id, rev, ((node) * MAX_NR_RCS_PER_NODE + 7), MCFG_BUS_ANY, ops }, \ + { "SUNWAY", table_id, rev, ((node) * MAX_NR_RCS_PER_NODE + 8), MCFG_BUS_ANY, ops }, \ + { "SUNWAY", table_id, rev, ((node) * MAX_NR_RCS_PER_NODE + 9), MCFG_BUS_ANY, ops }, \ + { "SUNWAY", table_id, rev, ((node) * MAX_NR_RCS_PER_NODE + 10), MCFG_BUS_ANY, ops }, \ + { "SUNWAY", table_id, rev, ((node) * MAX_NR_RCS_PER_NODE + 11), MCFG_BUS_ANY, ops } \ + + /* up to 8 nodes for SW64 series */ + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x00, &sw64_pci_ecam_ops), + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x01, &sw64_pci_ecam_ops), + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x02, &sw64_pci_ecam_ops), + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x03, &sw64_pci_ecam_ops), + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x04, &sw64_pci_ecam_ops), + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x05, &sw64_pci_ecam_ops), + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x06, &sw64_pci_ecam_ops), + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x07, &sw64_pci_ecam_ops), #endif /* SW64 */ }; diff --git a/drivers/pci/controller/pci-sunway.c b/drivers/pci/controller/pci-sunway.c index 46a75ef1a3e9..2f2b5c19a414 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -346,18 +346,25 @@ void __init setup_chip_pci_ops(void) sw64_chip_init->pci_init = chip_pci_init_ops; } -static unsigned long rc_linkup; static struct pci_controller *head, **tail = &head; +static DECLARE_BITMAP(rc_linkup, (MAX_NUMNODES * MAX_NR_RCS_PER_NODE)); + void pci_mark_rc_linkup(unsigned long node, unsigned long index) { - set_bit(node * 8 + index, &rc_linkup); + set_bit(node * MAX_NR_RCS_PER_NODE + index, rc_linkup); } EXPORT_SYMBOL(pci_mark_rc_linkup); +void pci_clear_rc_linkup(unsigned long node, unsigned long index) +{ + clear_bit(node * MAX_NR_RCS_PER_NODE + index, rc_linkup); +} +EXPORT_SYMBOL(pci_clear_rc_linkup); + int pci_get_rc_linkup(unsigned long node, unsigned long index) { - return test_bit(node * 8 + index, &rc_linkup); + return test_bit(node * MAX_NR_RCS_PER_NODE + index, rc_linkup); } EXPORT_SYMBOL(pci_get_rc_linkup); -- Gitee From ac623bdf22a730266560daca4b11890540a32ea0 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Fri, 12 Apr 2024 09:15:58 +0800 Subject: [PATCH 81/98] sw64: fix compile error of efi.systab Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- The systab field has been removed from struct efi. To get systab, we can parse it from the DTB provided by firmware. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/platform.h | 2 ++ arch/sw_64/kernel/machine_kexec.c | 7 ++++--- arch/sw_64/kernel/setup.c | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/sw_64/include/asm/platform.h b/arch/sw_64/include/asm/platform.h index 7374f2087f90..4f93d9532f9a 100644 --- a/arch/sw_64/include/asm/platform.h +++ b/arch/sw_64/include/asm/platform.h @@ -30,5 +30,7 @@ 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); #endif /* _ASM_SW64_PLATFORM_H */ diff --git a/arch/sw_64/kernel/machine_kexec.c b/arch/sw_64/kernel/machine_kexec.c index d6758d48dc26..dc1b2b4f5949 100644 --- a/arch/sw_64/kernel/machine_kexec.c +++ b/arch/sw_64/kernel/machine_kexec.c @@ -289,11 +289,10 @@ static void update_boot_params(void) params.dtb_start = (unsigned long)arch_kexec_alloc_and_setup_fdt( params.initrd_start, params.initrd_size, (const char *)params.cmdline); - /* update dtb base address */ - sunway_dtb_address = params.dtb_start; #ifdef CONFIG_EFI - params.efi_systab = virt_to_phys((void *)efi.systab); + early_parse_fdt_property((void *)sunway_dtb_address, "/chosen", + "linux,uefi-system-table", ¶ms.efi_systab, sizeof(u64)); params.efi_memmap = efi.memmap.phys_map; params.efi_memmap_size = efi.memmap.map_end - efi.memmap.map; params.efi_memdesc_size = efi.memmap.desc_size; @@ -312,6 +311,8 @@ static void update_boot_params(void) if (update_efi_properties(¶ms)) pr_err("Note: failed to update efi properties\n"); #endif + /* update dtb base address */ + sunway_dtb_address = params.dtb_start; } pr_info("initrd_start = %#llx, initrd_size = %#llx\n" diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index b154165dcb24..6505fe0486aa 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -553,7 +553,7 @@ static bool __init arch_dtb_verify(void *dt_virt, bool from_firmware) return true; } -static void early_parse_fdt_property(const void *fdt, const char *path, +void early_parse_fdt_property(const void *fdt, const char *path, const char *prop_name, u64 *property, int size) { int node, prop_len; -- Gitee From 15411521b237ba3db271f6e4d6350cce23d7843d Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Sun, 7 Apr 2024 09:50:09 +0800 Subject: [PATCH 82/98] sw64: fix the .endm in hibernate_asm.S Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- This patch fixes compile error because of #ifdef guard mistake. Signed-off-by: Wu Liliu Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/hibernate_asm.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/kernel/hibernate_asm.S b/arch/sw_64/kernel/hibernate_asm.S index af0372879bb9..ebba57b8bd8b 100644 --- a/arch/sw_64/kernel/hibernate_asm.S +++ b/arch/sw_64/kernel/hibernate_asm.S @@ -9,8 +9,9 @@ sys_call HMC_wrktp #else csrw $8, CSR_KTP - .endm #endif + .endm + .text .set noat ENTRY(swsusp_arch_suspend) -- Gitee From 9bf51bee403ebb02046be8718bde66276f0dda88 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 9 Apr 2024 17:07:31 +0800 Subject: [PATCH 83/98] sw64: define cpu_relax() as imb() Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Use imb() to implement cpu_relax() which pause the cpu for a very short period of time until all instructions in pipelines are committed. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/processor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/include/asm/processor.h b/arch/sw_64/include/asm/processor.h index ec68fe6cc6f2..f66a77f233c9 100644 --- a/arch/sw_64/include/asm/processor.h +++ b/arch/sw_64/include/asm/processor.h @@ -65,7 +65,7 @@ unsigned long __get_wchan(struct task_struct *p); #define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[30]) -#define cpu_relax() barrier() +#define cpu_relax() imemb() #define ARCH_HAS_PREFETCH #define ARCH_HAS_PREFETCHW -- Gitee From cefd52df8e40bd1e283823e9cd6edd5f885533e6 Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Thu, 11 Apr 2024 18:31:08 +0800 Subject: [PATCH 84/98] sw64: add -fno-sw-unalign-byte to cflags for C4 Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- This ensures that kernel does not throw an unalign exception. Signed-off-by: Wu Liliu Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/Makefile b/arch/sw_64/Makefile index 84f0dca5e9f7..cfea96316c94 100644 --- a/arch/sw_64/Makefile +++ b/arch/sw_64/Makefile @@ -28,7 +28,7 @@ endif CHECKFLAGS += -D__sw__ cflags-y := -pipe -ffixed-8 -mno-fp-regs #-msmall-data ifeq ($(CONFIG_SUBARCH_C4),y) - cflags-y += -fsw-rev + cflags-y += -fsw-rev -fno-sw-unalign-byte endif cflags-y += $(call cc-option, -fno-jump-tables) -- Gitee From f88e42c40ad5f90a60fde2859467c9976a798587 Mon Sep 17 00:00:00 2001 From: Xu Chenjiao Date: Tue, 16 Apr 2024 15:07:03 +0000 Subject: [PATCH 85/98] sw64: spi: update spi controller driver Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Update spi controller driver. It should be noted as follows: - The m25p80 driver has been removed in commit b35b9a10362d ("mtd: spi-nor: Move m25p80 code in spi-nor.c"). - The data structures used by spi memory driver have changed. Signed-off-by: Xu Chenjiao Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/boot/dts/chip3.dts | 2 +- arch/sw_64/boot/dts/junzhang.dts | 4 +- drivers/spi/Kconfig | 22 +- drivers/spi/Makefile | 4 +- drivers/spi/spi-sunway-mmio.c | 144 ++++++++ drivers/spi/spi-sunway.c | 409 ++++++++++++++++++++++ drivers/spi/{spi-chip3.h => spi-sunway.h} | 162 +++++---- 7 files changed, 664 insertions(+), 83 deletions(-) create mode 100644 drivers/spi/spi-sunway-mmio.c create mode 100644 drivers/spi/spi-sunway.c rename drivers/spi/{spi-chip3.h => spi-sunway.h} (49%) diff --git a/arch/sw_64/boot/dts/chip3.dts b/arch/sw_64/boot/dts/chip3.dts index 920519566c58..4967e43dc005 100644 --- a/arch/sw_64/boot/dts/chip3.dts +++ b/arch/sw_64/boot/dts/chip3.dts @@ -140,7 +140,7 @@ pvt: pvt@0x8030 { spi: spi@0x8032 { #address-cells = <1>; #size-cells = <0>; - compatible = "sunway,chip3-spi"; + compatible = "sunway,chip-spi"; reg = <0x8032 0x0 0x0 0x8000>; clocks = <&spiclk>; poll_mode = <1>; /* poll_mode:1 interrupt mode: 0 */ diff --git a/arch/sw_64/boot/dts/junzhang.dts b/arch/sw_64/boot/dts/junzhang.dts index 4e8cd655c798..8712678a66e8 100644 --- a/arch/sw_64/boot/dts/junzhang.dts +++ b/arch/sw_64/boot/dts/junzhang.dts @@ -160,7 +160,7 @@ partitions { partition@0 { label = "test"; - reg = <0 0x400000>; + reg = <0 0x800000>; }; }; }; @@ -178,7 +178,7 @@ partitions { partition@0 { label = "test"; - reg = <0 0x400000>; + reg = <0 0x800000>; }; }; }; diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 60826b7ed21e..e3217ce5a3f6 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -343,6 +343,21 @@ config SPI_DW_BT1_DIRMAP endif +config SPI_SUNWAY + tristate "Sunway SPI controller support" + depends on SW64 + imply SPI_MEM + help + general driver for Sunway SPI controller + +if SPI_SUNWAY + +config SPI_SUNWAY_MMIO + tristate "Memory-mapped io interface driver for Sunway SPI controller" + depends on HAS_IOMEM + +endif + config SPI_DLN2 tristate "Diolan DLN-2 USB SPI adapter" depends on MFD_DLN2 @@ -1179,13 +1194,6 @@ config SPI_AMD # # Add new SPI master controllers in alphabetical order above this line # -config SPI_CHIP3 - tristate "Memory-mapped io interface driver for SUNWAY CHIP3 SPI core" - depends on UNCORE_XUELANG - help - general driver for SPI controller core from DesignWare - - comment "SPI Multiplexer support" config SPI_MUX diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 26bf16fcf890..d6fdb887d97d 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -48,8 +48,10 @@ spi-dw-y := spi-dw-core.o spi-dw-$(CONFIG_SPI_DW_DMA) += spi-dw-dma.o obj-$(CONFIG_SPI_DW_BT1) += spi-dw-bt1.o obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o -obj-$(CONFIG_SPI_CHIP3) += spi-chip3.o spi-chip3-mmio.o obj-$(CONFIG_SPI_DW_PCI) += spi-dw-pci.o +obj-$(CONFIG_SPI_SUNWAY) += spi-sunway.o +obj-$(CONFIG_SPI_SUNWAY_MMIO) += spi-sunway-mmio.o +obj-$(CONFIG_SPI_EFM32) += spi-efm32.o obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o obj-$(CONFIG_SPI_FALCON) += spi-falcon.o obj-$(CONFIG_SPI_FSI) += spi-fsi.o diff --git a/drivers/spi/spi-sunway-mmio.c b/drivers/spi/spi-sunway-mmio.c new file mode 100644 index 000000000000..b170207cd104 --- /dev/null +++ b/drivers/spi/spi-sunway-mmio.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Memory-mapped interface driver for SUNWAY CHIP SPI Core + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spi-sunway.h" + + +#define DRIVER_NAME "sunway_chip_spi" + +struct chip_spi_mmio { + struct spi_chip spi_chip; + struct clk *clk; + void *priv; +}; + +static int chip_spi_mmio_probe(struct platform_device *pdev) +{ + int (*init_func)(struct platform_device *pdev, + struct chip_spi_mmio *spimmio); + struct chip_spi_mmio *spimmio; + struct spi_chip *spi_chip; + struct resource *mem; + int ret; + int num_cs; + + spimmio = devm_kzalloc(&pdev->dev, sizeof(struct chip_spi_mmio), + GFP_KERNEL); + if (!spimmio) + return -ENOMEM; + + spi_chip = &spimmio->spi_chip; + + /* Get basic io resource and map it */ + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + spi_chip->regs = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(spi_chip->regs)) { + dev_err(&pdev->dev, "SPI region map failed\n"); + return PTR_ERR(spi_chip->regs); + } + + spimmio->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(spimmio->clk)) + return PTR_ERR(spimmio->clk); + ret = clk_prepare_enable(spimmio->clk); + if (ret) + return ret; + + spi_chip->bus_num = pdev->id; + spi_chip->max_freq = clk_get_rate(spimmio->clk); + + device_property_read_u32(&pdev->dev, "reg-io-width", + &spi_chip->reg_io_width); + + num_cs = 4; + device_property_read_u32(&pdev->dev, "num-cs", &num_cs); + spi_chip->num_cs = num_cs; + + if (pdev->dev.of_node) { + int i; + + for (i = 0; i < spi_chip->num_cs; i++) { + int cs_gpio = of_get_named_gpio(pdev->dev.of_node, + "cs-gpios", i); + + if (cs_gpio == -EPROBE_DEFER) { + ret = cs_gpio; + goto out; + } + + if (gpio_is_valid(cs_gpio)) { + ret = devm_gpio_request(&pdev->dev, cs_gpio, + dev_name(&pdev->dev)); + if (ret) + goto out; + } + } + } + + init_func = device_get_match_data(&pdev->dev); + if (init_func) { + ret = init_func(pdev, spimmio); + if (ret) + goto out; + } + + spi_chip->flags = SPI_PLAT; + + ret = spi_chip_add_host(&pdev->dev, spi_chip); + if (ret) + goto out; + + platform_set_drvdata(pdev, spimmio); + + return 0; +out: + clk_disable_unprepare(spimmio->clk); + return ret; +} + +static int chip_spi_mmio_remove(struct platform_device *pdev) +{ + struct chip_spi_mmio *spimmio = platform_get_drvdata(pdev); + + spi_chip_remove_host(&spimmio->spi_chip); + clk_disable_unprepare(spimmio->clk); + + return 0; +} + +static const struct of_device_id chip_spi_mmio_of_match[] = { + { .compatible = "sunway,chip-spi",}, + { /* end of table */} +}; +MODULE_DEVICE_TABLE(of, chip_spi_mmio_of_match); + +static struct platform_driver chip_spi_mmio_driver = { + .probe = chip_spi_mmio_probe, + .remove = chip_spi_mmio_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = chip_spi_mmio_of_match, + }, +}; +module_platform_driver(chip_spi_mmio_driver); + +MODULE_AUTHOR("Platform@wiat.com"); +MODULE_DESCRIPTION("Memory-mapped I/O interface driver for Sunway CHIP"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/spi/spi-sunway.c b/drivers/spi/spi-sunway.c new file mode 100644 index 000000000000..6133173ea09a --- /dev/null +++ b/drivers/spi/spi-sunway.c @@ -0,0 +1,409 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SPI core controller driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spi-sunway.h" + +/* Slave spi_dev related */ +struct chip_data { + u8 tmode; /* TR/TO/RO/EEPROM */ + u8 type; /* SPI/SSP/MicroWire */ + + u8 poll_mode; /* 1 means use poll mode */ + + u16 clk_div; /* baud rate divider */ + u32 speed_hz; /* baud rate */ + void (*cs_control)(u32 command); +}; + +static void spi_chip_handle_err(struct spi_controller *master, + struct spi_message *msg) +{ + struct spi_chip *spi_chip = spi_controller_get_devdata(master); + + spi_reset_chip(spi_chip); +} + +static size_t spi_chip_max_length(struct spi_device *spi) +{ + struct spi_chip *spi_chip = spi_controller_get_devdata(spi->master); + + return spi_chip->fifo_len; +} + +static int spi_chip_transfer_one_message(struct spi_controller *master, + struct spi_message *m) +{ + struct spi_chip *spi_chip = spi_controller_get_devdata(master); + struct spi_transfer *t = NULL; + u16 clk_div; + u32 freq; + u32 speed_hz; + u32 status; + u32 len = 0; + int ret = 0; + int i = 0; + + spi_enable_chip(spi_chip, 0); + + /* Handle per transfer options for bpw and speed. */ + freq = clamp(m->spi->max_speed_hz, 0U, spi_chip->max_freq); + clk_div = (DIV_ROUND_UP(spi_chip->max_freq, freq) + 1) & 0xfffe; + speed_hz = spi_chip->max_freq / clk_div; + + if (spi_chip->current_freq != speed_hz) { + spi_set_clk(spi_chip, clk_div); + spi_chip->current_freq = speed_hz; + } + + spi_chip->n_bytes = 1; + + /* For poll mode just disable all interrupts */ + spi_mask_intr(spi_chip, 0xff); + + spi_writel(spi_chip, SPI_CHIP_CTRL0, SPI_TRANSMIT_RECEIVE); + + spi_enable_chip(spi_chip, 1); + + list_for_each_entry(t, &m->transfers, transfer_list) { + len += t->len; + /* Judge if data is overflow */ + if (len > spi_chip->fifo_len) { + pr_err("SPI transfer overflow.\n"); + m->actual_length = 0; + m->status = -EIO; + ret = -EIO; + goto way_out; + } + + if (t->tx_buf) + memcpy(&spi_chip->buf[len], t->tx_buf, t->len); + else + memset(&spi_chip->buf[len], 0, t->len); + } + + spi_writel(spi_chip, SPI_CHIP_SER, 0x0); + for (i = 0; i < len; i++) + spi_writel(spi_chip, SPI_CHIP_DR, spi_chip->buf[i]); + spi_writel(spi_chip, SPI_CHIP_SER, BIT(m->spi->chip_select)); + + do { + status = spi_readl(spi_chip, SPI_CHIP_SR); + } while (status & SR_BUSY); + + list_for_each_entry(t, &m->transfers, transfer_list) { + if (t->rx_buf) { + for (i = 0; i < t->len; i++, t->rx_buf += 1) + *(u8 *)t->rx_buf = spi_readl(spi_chip, + SPI_CHIP_DR); + } else { + for (i = 0; i < t->len; i++) + spi_readl(spi_chip, SPI_CHIP_DR); + } + } + + m->actual_length = len; + m->status = 0; + spi_finalize_current_message(master); + +way_out: + return ret; +} + +static int spi_chip_adjust_mem_op_size(struct spi_mem *mem, + struct spi_mem_op *op) +{ + struct spi_chip *spi_chip = spi_controller_get_devdata( + mem->spi->controller); + size_t len; + + len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes; + + op->data.nbytes = min((size_t)op->data.nbytes, + (spi_chip->fifo_len - len)); + if (!op->data.nbytes) + return -EINVAL; + + return 0; +} + +static int spi_chip_init_mem_buf(struct spi_chip *spi_chip, + const struct spi_mem_op *op) +{ + int ret = 0; + int i, j, len; + + /* Calculate the total length of the transfer. */ + len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes; + + /* Judge if data is overflow */ + if (len + op->data.nbytes > spi_chip->fifo_len) { + ret = -EIO; + goto way_out; + } + + /* + * Collect the operation code, address and dummy bytes into the single + * buffer. If it's a transfer with data to be sent, also copy it into + * the single buffer. + */ + for (i = 0; i < op->cmd.nbytes; i++) + spi_chip->buf[i] = op->cmd.opcode; + for (j = 0; j < op->addr.nbytes; i++, j++) + spi_chip->buf[i] = op->addr.val >> (8 * (op->addr.nbytes - i)); + for (j = 0; j < op->dummy.nbytes; i++, j++) + spi_chip->buf[i] = 0xff; + + if (op->data.dir == SPI_MEM_DATA_OUT) { + memcpy(&spi_chip->buf[i], op->data.buf.out, op->data.nbytes); + len += op->data.nbytes; + } + + spi_chip->tx_len = len; + + if (op->data.dir == SPI_MEM_DATA_IN) { + spi_chip->rx = op->data.buf.in; + spi_chip->rx_len = op->data.nbytes; + } else { + spi_chip->rx = NULL; + spi_chip->rx_len = 0; + } + +way_out: + return ret; +} + +static int spi_chip_exec_mem_op(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + struct spi_chip *spi_chip = spi_controller_get_devdata( + mem->spi->controller); + u16 clk_div; + int ret = 0; + int i; + unsigned short value; + u32 freq; + u32 speed_hz; + + ret = spi_chip_init_mem_buf(spi_chip, op); + if (ret) + return ret; + + spi_enable_chip(spi_chip, 0); + + /* Handle per transfer options for bpw and speed. */ + freq = clamp(mem->spi->max_speed_hz, 0U, spi_chip->max_freq); + clk_div = (DIV_ROUND_UP(spi_chip->max_freq, freq) + 1) & 0xfffe; + speed_hz = spi_chip->max_freq / clk_div; + + if (spi_chip->current_freq != speed_hz) { + spi_set_clk(spi_chip, clk_div); + spi_chip->current_freq = speed_hz; + } + + spi_chip->n_bytes = 1; + + /* For poll mode just disable all interrupts */ + spi_mask_intr(spi_chip, 0xff); + + if ((spi_chip->tx_len != 0) && (spi_chip->rx_len != 0)) { + spi_writel(spi_chip, SPI_CHIP_CTRL0, SPI_EEPROM_READ); + spi_writel(spi_chip, SPI_CHIP_CTRL1, (spi_chip->rx_len - 1)); + } else { + spi_writel(spi_chip, SPI_CHIP_CTRL0, SPI_TRANSMIT_ONLY); + } + + spi_enable_chip(spi_chip, 1); + + spi_writel(spi_chip, SPI_CHIP_SER, 0x0); + for (i = 0; i < spi_chip->tx_len; i++) + spi_writel(spi_chip, SPI_CHIP_DR, spi_chip->buf[i]); + spi_writel(spi_chip, SPI_CHIP_SER, BIT(mem->spi->chip_select)); + + value = spi_readl(spi_chip, SPI_CHIP_SR); + while (value & SR_BUSY) + value = spi_readl(spi_chip, SPI_CHIP_SR); + + for (i = 0; i < spi_chip->rx_len; spi_chip->rx += spi_chip->n_bytes, i++) + *(u8 *)spi_chip->rx = spi_readl(spi_chip, SPI_CHIP_DR); + + return ret; +} + +/* This may be called twice for each spi dev */ +static int spi_chip_setup(struct spi_device *spi) +{ + struct spi_chip_info *chip_info = NULL; + struct chip_data *chip; + u32 poll_mode = 0; + struct device_node *np = spi->dev.of_node; + + /* Only alloc on first setup */ + chip = spi_get_ctldata(spi); + if (!chip) { + chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); + if (!chip) + return -ENOMEM; + spi_set_ctldata(spi, chip); + } + + /* + * Protocol drivers may change the chip settings, so... + * if chip_info exists, use it + */ + chip_info = spi->controller_data; + + /* chip_info doesn't always exist */ + if (chip_info) { + if (chip_info->cs_control) + chip->cs_control = chip_info->cs_control; + + chip->poll_mode = chip_info->poll_mode; + chip->type = chip_info->type; + } else { + if (np) { + of_property_read_u32(np, "poll_mode", &poll_mode); + chip->poll_mode = poll_mode; + } + + } + + chip->tmode = SPI_TMOD_TR; + return 0; +} + +static void spi_chip_cleanup(struct spi_device *spi) +{ + struct chip_data *chip = spi_get_ctldata(spi); + + kfree(chip); + spi_set_ctldata(spi, NULL); +} + +/* Restart the controller, disable all interrupts, clean rx fifo */ +static void spi_hw_init(struct device *dev, struct spi_chip *spi_chip) +{ + spi_reset_chip(spi_chip); + + /* + * Try to detect the FIFO depth if not set by interface driver, + * the depth could be from 2 to 256 from HW spec + */ + if (!spi_chip->fifo_len) { + u32 fifo; + + for (fifo = 1; fifo < 256; fifo++) { + spi_writel(spi_chip, SPI_CHIP_TXFLTR, fifo); + if (fifo != spi_readl(spi_chip, SPI_CHIP_TXFLTR)) + break; + } + spi_writel(spi_chip, SPI_CHIP_TXFLTR, 0); + + spi_chip->fifo_len = (fifo == 1) ? 0 : fifo; + dev_info(dev, "Detected FIFO size: %u bytes\n", + spi_chip->fifo_len); + } +} + +static const struct spi_controller_mem_ops spi_mem_ops = { + .adjust_op_size = spi_chip_adjust_mem_op_size, + .exec_op = spi_chip_exec_mem_op, +}; + +int spi_chip_add_host(struct device *dev, struct spi_chip *spi_chip) +{ + struct spi_controller *master; + int ret; + + WARN_ON(spi_chip == NULL); + + master = spi_alloc_master(dev, 0); + if (!master) + return -ENOMEM; + + spi_chip->master = master; + spi_chip->type = SSI_MOTO_SPI; + + spi_controller_set_devdata(master, spi_chip); + + master->mode_bits = SPI_CPOL | SPI_CPHA; + master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); + master->bus_num = spi_chip->bus_num; + master->num_chipselect = spi_chip->num_cs; + master->setup = spi_chip_setup; + master->cleanup = spi_chip_cleanup; + master->transfer_one_message = spi_chip_transfer_one_message; + 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->max_transfer_size = spi_chip_max_length; + master->max_message_size = spi_chip_max_length; + + master->mem_ops = &spi_mem_ops; + + /* Basic HW init */ + spi_hw_init(dev, spi_chip); + + ret = devm_spi_register_controller(dev, master); + if (ret) { + dev_err(&master->dev, "problem registering spi master\n"); + spi_enable_chip(spi_chip, 0); + free_irq(spi_chip->irq, master); + } + + return 0; +} +EXPORT_SYMBOL_GPL(spi_chip_add_host); + +void spi_chip_remove_host(struct spi_chip *spi_chip) +{ + spi_shutdown_chip(spi_chip); + + free_irq(spi_chip->irq, spi_chip->master); +} +EXPORT_SYMBOL_GPL(spi_chip_remove_host); + +int spi_chip_suspend_host(struct spi_chip *spi_chip) +{ + int ret; + + ret = spi_controller_suspend(spi_chip->master); + if (ret) + return ret; + + spi_shutdown_chip(spi_chip); + return 0; +} +EXPORT_SYMBOL_GPL(spi_chip_suspend_host); + +int spi_chip_resume_host(struct spi_chip *spi_chip) +{ + int ret; + + spi_hw_init(&spi_chip->master->dev, spi_chip); + ret = spi_controller_resume(spi_chip->master); + if (ret) + dev_err(&spi_chip->master->dev, "fail to start queue (%d)\n", + ret); + return ret; +} +EXPORT_SYMBOL_GPL(spi_chip_resume_host); + +MODULE_AUTHOR("Platform@wiat.com"); +MODULE_DESCRIPTION("Driver for SPI controller core"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/spi/spi-chip3.h b/drivers/spi/spi-sunway.h similarity index 49% rename from drivers/spi/spi-chip3.h rename to drivers/spi/spi-sunway.h index 88e49a9091a5..5f44050001d3 100644 --- a/drivers/spi/spi-chip3.h +++ b/drivers/spi/spi-sunway.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef CHIP3_SPI_HEADER_H -#define CHIP3_SPI_HEADER_H +#ifndef SPI_CHIP_HEADER_H +#define SPI_CHIP_HEADER_H #include #include @@ -8,31 +8,31 @@ #include /* Register offsets */ -#define CHIP3_SPI_CTRL0 (0x00<<7) -#define CHIP3_SPI_CTRL1 (0x04<<7) -#define CHIP3_SPI_SSIENR (0x08<<7) -#define CHIP3_SPI_MWCR (0x0c<<7) -#define CHIP3_SPI_SER (0x10<<7) -#define CHIP3_SPI_BAUDR (0x14<<7) -#define CHIP3_SPI_TXFLTR (0x18<<7) -#define CHIP3_SPI_RXFLTR (0x1c<<7) -#define CHIP3_SPI_TXFLR (0x20<<7) -#define CHIP3_SPI_RXFLR (0x24<<7) -#define CHIP3_SPI_SR (0x28<<7) -#define CHIP3_SPI_IMR (0x2c<<7) -#define CHIP3_SPI_ISR (0x30<<7) -#define CHIP3_SPI_RISR (0x34<<7) -#define CHIP3_SPI_TXOICR (0x38<<7) -#define CHIP3_SPI_RXOICR (0x3c<<7) -#define CHIP3_SPI_RXUICR (0x40<<7) -#define CHIP3_SPI_MSTICR (0x44<<7) -#define CHIP3_SPI_ICR (0x48<<7) -#define CHIP3_SPI_DMACR (0x4c<<7) -#define CHIP3_SPI_DMATDLR (0x50<<7) -#define CHIP3_SPI_DMARDLR (0x54<<7) -#define CHIP3_SPI_IDR (0x58<<7) -#define CHIP3_SPI_VERSION (0x5c<<7) -#define CHIP3_SPI_DR (0x60<<7) +#define SPI_CHIP_CTRL0 0x00 +#define SPI_CHIP_CTRL1 0x04 +#define SPI_CHIP_SSIENR 0x08 +#define SPI_CHIP_MWCR 0x0c +#define SPI_CHIP_SER 0x10 +#define SPI_CHIP_BAUDR 0x14 +#define SPI_CHIP_TXFLTR 0x18 +#define SPI_CHIP_RXFLTR 0x1c +#define SPI_CHIP_TXFLR 0x20 +#define SPI_CHIP_RXFLR 0x24 +#define SPI_CHIP_SR 0x28 +#define SPI_CHIP_IMR 0x2c +#define SPI_CHIP_ISR 0x30 +#define SPI_CHIP_RISR 0x34 +#define SPI_CHIP_TXOICR 0x38 +#define SPI_CHIP_RXOICR 0x3c +#define SPI_CHIP_RXUICR 0x40 +#define SPI_CHIP_MSTICR 0x44 +#define SPI_CHIP_ICR 0x48 +#define SPI_CHIP_DMACR 0x4c +#define SPI_CHIP_DMATDLR 0x50 +#define SPI_CHIP_DMARDLR 0x54 +#define SPI_CHIP_IDR 0x58 +#define SPI_CHIP_VERSION 0x5c +#define SPI_CHIP_DR 0x60 /* Bit fields in CTRLR0 */ #define SPI_DFS_OFFSET 0 @@ -91,17 +91,21 @@ #define SPI_EEPROM_READ 0x3c7 #define SPI_TRANSMIT_ONLY 0x1c7 -enum chip3_ssi_type { +#define SPI_PLAT 0x1 +#define SPI_PCI 0x2 + +enum spi_ssi_type { SSI_MOTO_SPI = 0, SSI_TI_SSP, SSI_NS_MICROWIRE, }; -struct chip3_spi; -struct chip3_spi { +struct spi_chip; + +struct spi_chip { struct spi_controller *master; - enum chip3_ssi_type type; + enum spi_ssi_type type; void __iomem *regs; unsigned long paddr; @@ -122,6 +126,7 @@ struct chip3_spi { unsigned int rx_len; u8 n_bytes; /* current is a 1/2 bytes op */ u32 current_freq; /* frequency in hz */ + int flags; u8 buf[MAX_LEN]; @@ -132,76 +137,89 @@ struct chip3_spi { #endif }; -static inline u32 chip3_readl(struct chip3_spi *dws, u32 offset) +static inline u32 spi_readl(struct spi_chip *spi_chip, u32 offset) { - return __raw_readl(dws->regs + offset); + if (spi_chip->flags & SPI_PLAT) + offset <<= 7; + + return __raw_readl(spi_chip->regs + offset); } -static inline u16 chip3_readw(struct chip3_spi *dws, u32 offset) +static inline u16 spi_readw(struct spi_chip *spi_chip, u32 offset) { - return __raw_readw(dws->regs + offset); + if (spi_chip->flags & SPI_PLAT) + offset <<= 7; + + return __raw_readw(spi_chip->regs + offset); } -static inline void chip3_writel(struct chip3_spi *dws, u32 offset, u32 val) +static inline void spi_writel(struct spi_chip *spi_chip, u32 offset, u32 val) { - __raw_writel(val, dws->regs + offset); + if (spi_chip->flags & SPI_PLAT) + offset <<= 7; + + __raw_writel(val, spi_chip->regs + offset); } -static inline void chip3_writew(struct chip3_spi *dws, u32 offset, u16 val) +static inline void spi_writew(struct spi_chip *spi_chip, u32 offset, u16 val) { - __raw_writew(val, dws->regs + offset); + if (spi_chip->flags & SPI_PLAT) + offset <<= 7; + + __raw_writew(val, spi_chip->regs + offset); } -static inline u32 chip3_read_io_reg(struct chip3_spi *dws, u32 offset) +static inline u32 spi_read_io_reg(struct spi_chip *spi_chip, u32 offset) { - switch (dws->reg_io_width) { + switch (spi_chip->reg_io_width) { case 2: - return chip3_readw(dws, offset); + return spi_readw(spi_chip, offset); case 4: default: - return chip3_readl(dws, offset); + return spi_readl(spi_chip, offset); } } -static inline void chip3_write_io_reg(struct chip3_spi *dws, u32 offset, u32 val) +static inline void spi_write_io_reg(struct spi_chip *spi_chip, u32 offset, + u32 val) { - switch (dws->reg_io_width) { + switch (spi_chip->reg_io_width) { case 2: - chip3_writew(dws, offset, val); + spi_writew(spi_chip, offset, val); break; case 4: default: - chip3_writel(dws, offset, val); + spi_writel(spi_chip, offset, val); break; } } -static inline void spi_enable_chip(struct chip3_spi *dws, int enable) +static inline void spi_enable_chip(struct spi_chip *spi_chip, int enable) { - chip3_writel(dws, CHIP3_SPI_SSIENR, (enable ? 1 : 0)); + spi_writel(spi_chip, SPI_CHIP_SSIENR, (enable ? 1 : 0)); } -static inline void spi_set_clk(struct chip3_spi *dws, u16 div) +static inline void spi_set_clk(struct spi_chip *spi_chip, u16 div) { - chip3_writel(dws, CHIP3_SPI_BAUDR, div); + spi_writel(spi_chip, SPI_CHIP_BAUDR, div); } /* Disable IRQ bits */ -static inline void spi_mask_intr(struct chip3_spi *dws, u32 mask) +static inline void spi_mask_intr(struct spi_chip *spi_chip, u32 mask) { u32 new_mask; - new_mask = chip3_readl(dws, CHIP3_SPI_IMR) & ~mask; - chip3_writel(dws, CHIP3_SPI_IMR, new_mask); + new_mask = spi_readl(spi_chip, SPI_CHIP_IMR) & ~mask; + spi_writel(spi_chip, SPI_CHIP_IMR, new_mask); } /* Enable IRQ bits */ -static inline void spi_umask_intr(struct chip3_spi *dws, u32 mask) +static inline void spi_umask_intr(struct spi_chip *spi_chip, u32 mask) { u32 new_mask; - new_mask = chip3_readl(dws, CHIP3_SPI_IMR) | mask; - chip3_writel(dws, CHIP3_SPI_IMR, new_mask); + new_mask = spi_readl(spi_chip, SPI_CHIP_IMR) | mask; + spi_writel(spi_chip, SPI_CHIP_IMR, new_mask); } /* @@ -209,37 +227,37 @@ static inline void spi_umask_intr(struct chip3_spi *dws, u32 mask) * controller back. Transmit and receive FIFO buffers are cleared when the * device is disabled. */ -static inline void spi_reset_chip(struct chip3_spi *dws) +static inline void spi_reset_chip(struct spi_chip *spi_chip) { - spi_enable_chip(dws, 0); - spi_mask_intr(dws, 0xff); - spi_enable_chip(dws, 1); + spi_enable_chip(spi_chip, 0); + spi_mask_intr(spi_chip, 0xff); + spi_enable_chip(spi_chip, 1); } -static inline void spi_shutdown_chip(struct chip3_spi *dws) +static inline void spi_shutdown_chip(struct spi_chip *spi_chip) { - spi_enable_chip(dws, 0); - spi_set_clk(dws, 0); + spi_enable_chip(spi_chip, 0); + spi_set_clk(spi_chip, 0); } /* - * Each SPI slave device to work with chip3_api controller should + * Each SPI slave device to work with spi_api controller should * has such a structure claiming its working mode (poll or PIO/DMA), * which can be save in the "controller_data" member of the * struct spi_device. */ -struct chip3_spi_chip { +struct spi_chip_info { u8 poll_mode; /* 1 for controller polling mode */ u8 type; /* SPI/SSP/MicroWire */ u8 chip_select; void (*cs_control)(u32 command); }; -extern int chip3_spi_add_host(struct device *dev, struct chip3_spi *dws); -extern void chip3_spi_remove_host(struct chip3_spi *dws); -extern int chip3_spi_suspend_host(struct chip3_spi *dws); -extern int chip3_spi_resume_host(struct chip3_spi *dws); +extern int spi_chip_add_host(struct device *dev, struct spi_chip *spi_chip); +extern void spi_chip_remove_host(struct spi_chip *spi_chip); +extern int spi_chip_suspend_host(struct spi_chip *spi_chip); +extern int spi_chip_resume_host(struct spi_chip *spi_chip); /* platform related setup */ -extern int chip3_spi_mid_init(struct chip3_spi *dws); /* Intel MID platforms */ -#endif /* CHIP3_SPI_HEADER_H */ +extern int spi_ich_init(struct spi_chip *spi_chip); +#endif /* SPI_CHIP_HEADER_H */ -- Gitee From 88cbdc829f6bb1caf2de7f28fdc75f3743d02b00 Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Fri, 19 Apr 2024 14:17:17 +0000 Subject: [PATCH 86/98] sw64: match platform device by acpi method Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- It support matching platform device by acpi method. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/boot/dts/chip3.dts | 6 +++--- drivers/acpi/acpi_apd.c | 4 ++-- drivers/gpio/gpio-sunway.c | 5 +++++ drivers/hwmon/sw64_pvt.c | 11 +++++++++++ drivers/i2c/busses/i2c-designware-platdrv.c | 1 + drivers/mfd/lpc_sunway.c | 10 +++++++++- drivers/spi/spi-sunway-mmio.c | 12 ++++++++++++ drivers/tty/serial/8250/8250_sunway.c | 1 + 8 files changed, 44 insertions(+), 6 deletions(-) diff --git a/arch/sw_64/boot/dts/chip3.dts b/arch/sw_64/boot/dts/chip3.dts index 4967e43dc005..fecb0f0f3be7 100644 --- a/arch/sw_64/boot/dts/chip3.dts +++ b/arch/sw_64/boot/dts/chip3.dts @@ -86,7 +86,7 @@ serial1@9033 { i2c0@0x8031 { #address-cells = <2>; #size-cells = <2>; - compatible = "snps,designware-i2c"; + compatible = "sunway,suntai-i2c", "snps,designware-i2c"; reg = <0x8031 0x0 0x0 0x8000>; clock-frequency = <100000>; clocks = <&i2cclk>; @@ -98,7 +98,7 @@ i2c0@0x8031 { i2c1@0x8034 { #address-cells = <1>; #size-cells = <0>; - compatible = "snps,designware-i2c"; + compatible = "sunway,suntai-i2c", "snps,designware-i2c"; reg = <0x8034 0x0 0x0 0x8000>; clock-frequency = <100000>; clocks = <&i2cclk>; @@ -110,7 +110,7 @@ i2c1@0x8034 { i2c2@0x8035 { #address-cells = <1>; #size-cells = <0>; - compatible = "snps,designware-i2c"; + compatible = "sunway,suntai-i2c", "snps,designware-i2c"; reg = <0x8035 0x0 0x0 0x8000>; clock-frequency = <100000>; clocks = <&i2cclk>; diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c index 791f4b234e02..c5afed1eeb9c 100644 --- a/drivers/acpi/acpi_apd.c +++ b/drivers/acpi/acpi_apd.c @@ -261,8 +261,8 @@ static const struct acpi_device_id acpi_apd_device_ids[] = { { "NXP0001", APD_ADDR(nxp_i2c_desc) }, #endif #ifdef CONFIG_SW64 - { "HISI02A1", APD_ADDR(sunway_i2c_desc) }, - { "HISI0173", APD_ADDR(sunway_spi_desc) }, + { "SUNW0005", APD_ADDR(sunway_i2c_desc) }, + { "SUNW0008", APD_ADDR(sunway_spi_desc) }, #endif { } }; diff --git a/drivers/gpio/gpio-sunway.c b/drivers/gpio/gpio-sunway.c index 11581dded64f..ecb87c41dc65 100644 --- a/drivers/gpio/gpio-sunway.c +++ b/drivers/gpio/gpio-sunway.c @@ -648,13 +648,16 @@ static const struct of_device_id sunway_of_match[] = { }; MODULE_DEVICE_TABLE(of, sunway_of_match); +#ifdef CONFIG_ACPI static const struct acpi_device_id sunway_acpi_match[] = { {"HISI0181", 0}, {"APMC0D07", 0}, {"APMC0D81", GPIO_REG_OFFSET_V2}, + {"SUNW0002", 0}, { } }; MODULE_DEVICE_TABLE(acpi, sunway_acpi_match); +#endif static int sunway_gpio_probe(struct platform_device *pdev) { @@ -727,6 +730,8 @@ static int sunway_gpio_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, gpio); + def_info(&pdev->dev, "GPIO probe succeed\n"); + return 0; out_unregister: diff --git a/drivers/hwmon/sw64_pvt.c b/drivers/hwmon/sw64_pvt.c index aedc29d44077..78620f91ae52 100644 --- a/drivers/hwmon/sw64_pvt.c +++ b/drivers/hwmon/sw64_pvt.c @@ -184,6 +184,8 @@ static int pvt_vol_plat_probe(struct platform_device *pdev) return false; } + dev_info(&pdev->dev, "PVT probe succeed\n"); + return 0; err: @@ -199,11 +201,20 @@ static const struct of_device_id pvt_vol_of_match[] = { MODULE_DEVICE_TABLE(of, pvt_vol_of_match); #endif +#ifdef CONFIG_ACPI +static const struct acpi_device_id pvt_vol_acpi_match[] = { + { "SUNW0007", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, pvt_vol_acpi_match); +#endif + static struct platform_driver pvt_vol_driver = { .probe = pvt_vol_plat_probe, .driver = { .name = "pvt-sw64", .of_match_table = of_match_ptr(pvt_vol_of_match), + .acpi_match_table = ACPI_PTR(pvt_vol_acpi_match), }, }; diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index c818e9d14b9a..11a75130a109 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -57,6 +57,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = { { "HISI02A2", 0 }, { "HISI02A3", 0 }, { "HYGO0010", ACCESS_INTR_MASK }, + { "SUNW0005", MODEL_SUNWAY }, { } }; MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match); diff --git a/drivers/mfd/lpc_sunway.c b/drivers/mfd/lpc_sunway.c index 1bcf40d6a6f7..a70971e7912d 100644 --- a/drivers/mfd/lpc_sunway.c +++ b/drivers/mfd/lpc_sunway.c @@ -242,9 +242,16 @@ static const struct of_device_id chip3_lpc_of_match[] = { {.compatible = "sunway,chip3_lpc",}, { /* end of table */ } }; - MODULE_DEVICE_TABLE(of, chip3_lpc_of_match); +#ifdef CONFIG_ACPI +static const struct acpi_device_id chip3_lpc_acpi_match[] = { + { "SUNW0006", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, chip3_lpc_acpi_match); +#endif + #ifdef CONFIG_PM_SLEEP unsigned int lpc_irq_ctrl_value; unsigned int lpc_irq_irq_value; @@ -293,6 +300,7 @@ static struct platform_driver chip3_lpc_platform_driver = { .driver = { .name = "chip3_lpc", .of_match_table = chip3_lpc_of_match, + .acpi_match_table = ACPI_PTR(chip3_lpc_acpi_match), #ifdef CONFIG_PM_SLEEP .pm = &chip3_lpc_pm_ops, #endif diff --git a/drivers/spi/spi-sunway-mmio.c b/drivers/spi/spi-sunway-mmio.c index b170207cd104..7c8ba0a61ffb 100644 --- a/drivers/spi/spi-sunway-mmio.c +++ b/drivers/spi/spi-sunway-mmio.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "spi-sunway.h" @@ -107,6 +108,8 @@ static int chip_spi_mmio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, spimmio); + dev_info(&pdev->dev, "SPI(MMIO) probe succeed\n"); + return 0; out: clk_disable_unprepare(spimmio->clk); @@ -129,12 +132,21 @@ static const struct of_device_id chip_spi_mmio_of_match[] = { }; MODULE_DEVICE_TABLE(of, chip_spi_mmio_of_match); +#ifdef CONFIG_ACPI +static const struct acpi_device_id chip_spi_mmio_acpi_match[] = { + { "SUNW0008", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, chip_spi_mmio_acpi_match); +#endif + static struct platform_driver chip_spi_mmio_driver = { .probe = chip_spi_mmio_probe, .remove = chip_spi_mmio_remove, .driver = { .name = DRIVER_NAME, .of_match_table = chip_spi_mmio_of_match, + .acpi_match_table = ACPI_PTR(chip_spi_mmio_acpi_match), }, }; module_platform_driver(chip_spi_mmio_driver); diff --git a/drivers/tty/serial/8250/8250_sunway.c b/drivers/tty/serial/8250/8250_sunway.c index 9e3db232c832..7ff5ff160725 100644 --- a/drivers/tty/serial/8250/8250_sunway.c +++ b/drivers/tty/serial/8250/8250_sunway.c @@ -763,6 +763,7 @@ static const struct acpi_device_id sunway8250_acpi_match[] = { { "AMDI0020", 0 }, { "BRCM2032", 0 }, { "HISI0031", 0 }, + { "SUNW0009", 0}, { }, }; MODULE_DEVICE_TABLE(acpi, sunway8250_acpi_match); -- Gitee From e508dce2e1c84493d4c4ce143d2f7d7ee0e205df Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Mon, 8 Apr 2024 10:33:56 +0800 Subject: [PATCH 87/98] sw64: force kernel stack to be 16 bytes aligned Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Make struct pt_regs and struct rt_sigframe 16 bytes aligned to make sure the kernel stack is always 16 bytes aligned. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/ptrace.h | 2 +- arch/sw_64/kernel/signal.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/include/asm/ptrace.h b/arch/sw_64/include/asm/ptrace.h index aa8b269a7ef4..44c9e2d1fe6a 100644 --- a/arch/sw_64/include/asm/ptrace.h +++ b/arch/sw_64/include/asm/ptrace.h @@ -34,7 +34,7 @@ struct pt_regs { unsigned long earg0; unsigned long earg1; unsigned long earg2; -}; +} __aligned(16); #define arch_has_single_step() (1) #define user_mode(regs) (((regs)->ps & 8) != 0) diff --git a/arch/sw_64/kernel/signal.c b/arch/sw_64/kernel/signal.c index 496f33bb1c89..2155e6fa98c3 100644 --- a/arch/sw_64/kernel/signal.c +++ b/arch/sw_64/kernel/signal.c @@ -82,7 +82,7 @@ SYSCALL_DEFINE3(odd_sigaction, int, sig, struct rt_sigframe { struct siginfo info; struct ucontext uc; -}; +} __aligned(16); /* * If this changes, userland unwinders that Know Things about our signal -- Gitee From 7cb1191d76251999925c2c60d3117e53d10a0cde Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 9 Apr 2024 09:17:34 +0800 Subject: [PATCH 88/98] sw64: fix broken rdfpcr() Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- The memory output is used again after the register output is written, so the register of the register output constraint cannot be reused to store the memory address. Add the necessary constraint modifier to avoid this register reuse. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/fpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/include/asm/fpu.h b/arch/sw_64/include/asm/fpu.h index 1d5e9b0efecc..763d763c0477 100644 --- a/arch/sw_64/include/asm/fpu.h +++ b/arch/sw_64/include/asm/fpu.h @@ -100,7 +100,7 @@ rdfpcr(void) " rfpcr $f0\n\t" " fimovd $f0, %1\n\t" " vldd $f0, %0\n\t" - : "=m"(*fp), "=r"(ret)); + : "=m"(*fp), "=&r"(ret)); return ret; } -- Gitee From a2df5aab1d25878f099415735caf65413de5aeb1 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 28 Feb 2024 09:38:22 +0800 Subject: [PATCH 89/98] sw64: add syscall pfh_ops Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Add a new syscall pfh_ops which allows system administrators to modify hardware cache prefetch configuration. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/csr.h | 4 ++ arch/sw_64/kernel/sys_sw64.c | 61 ++++++++++++++++++++++++++ arch/sw_64/kernel/syscalls/syscall.tbl | 2 +- 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/include/asm/csr.h b/arch/sw_64/include/asm/csr.h index 8f4f3d142db4..cdb9249eedd2 100644 --- a/arch/sw_64/include/asm/csr.h +++ b/arch/sw_64/include/asm/csr.h @@ -20,8 +20,12 @@ #define CSR_EXC_PC 0xe #define CSR_AS_INFO 0x3c #define CSR_DS_STAT 0x48 +#define CSR_PFH_CTL 0x4f #define CSR_SOFTCID 0xc9 #define CSR_DVA 0x54 +#define CSR_PFH_CNT 0x5c +#define CSR_BRRETC 0x5e +#define CSR_BRFAILC 0x5f #define CSR_PTBR_SYS 0x68 #define CSR_PTBR_USR 0x69 #define CSR_APTP 0x6a diff --git a/arch/sw_64/kernel/sys_sw64.c b/arch/sw_64/kernel/sys_sw64.c index 46e6197dce76..31e6a8d65cf9 100644 --- a/arch/sw_64/kernel/sys_sw64.c +++ b/arch/sw_64/kernel/sys_sw64.c @@ -151,3 +151,64 @@ SYSCALL_DEFINE0(sw64_pipe) } return res; } + +#ifdef CONFIG_SUBARCH_C4 + +struct pfh_val { + unsigned long pfh_ctl; + unsigned long pfh_cnt; +}; + +static void local_set_pfh(void *info) +{ + struct pfh_val *kbuf = 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); +} + +SYSCALL_DEFINE3(pfh_ops, unsigned long, op, + unsigned long __user *, pfh_ctl_p, + unsigned long __user *, pfh_cnt_p) +{ + struct pfh_val kbuf = {0, 0}; + long error = 0; + + 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); + + 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 (pfh_cnt_p) { + kbuf.pfh_cnt = sw64_read_csr(CSR_PFH_CNT); + error |= put_user(kbuf.pfh_cnt, pfh_cnt_p); + } + } + + return error; +} + +#else + +SYSCALL_DEFINE0(pfh_ops) +{ + return -ENOSYS; +} + +#endif /* CONFIG_SUBARCH_C4 */ diff --git a/arch/sw_64/kernel/syscalls/syscall.tbl b/arch/sw_64/kernel/syscalls/syscall.tbl index fdf9e4cb03eb..3acd8b5ea7db 100644 --- a/arch/sw_64/kernel/syscalls/syscall.tbl +++ b/arch/sw_64/kernel/syscalls/syscall.tbl @@ -117,7 +117,7 @@ #107 is unused #108 is unused #109 is unused -#110 is unused +110 common pfh_ops sys_pfh_ops 111 common sigsuspend sys_sigsuspend #112 is unused 113 common recvmsg sys_recvmsg -- Gitee From 7beff986f5d87aaa89c11b6e4a804d46bbce0d7b Mon Sep 17 00:00:00 2001 From: Tang Jinyang Date: Mon, 15 Apr 2024 17:22:18 +0800 Subject: [PATCH 90/98] sw64: fix PTBR save/restore for hibernation Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- For C4, both CSR:PTBR_USR and CSR:PTBR_SYS have to be saved/restored to make hibernation work. Signed-off-by: Tang Jinyang Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/hibernate.c | 10 ++++++++++ arch/sw_64/kernel/hibernate_asm.S | 1 + 2 files changed, 11 insertions(+) diff --git a/arch/sw_64/kernel/hibernate.c b/arch/sw_64/kernel/hibernate.c index 644ea8504313..e84f93762f13 100644 --- a/arch/sw_64/kernel/hibernate.c +++ b/arch/sw_64/kernel/hibernate.c @@ -15,7 +15,12 @@ void save_processor_state(void) vcb->ksp = rdksp(); vcb->usp = rdusp(); vcb->soft_tid = rtid(); +#if defined(CONFIG_SUBARCH_C3B) vcb->ptbr = rdptbr(); +#elif defined(CONFIG_SUBARCH_C4) + vcb->ptbr_usr = sw64_read_csr(CSR_PTBR_USR); + vcb->ptbr_sys = sw64_read_csr(CSR_PTBR_SYS); +#endif } void restore_processor_state(void) @@ -25,7 +30,12 @@ void restore_processor_state(void) wrksp(vcb->ksp); wrusp(vcb->usp); wrtp(vcb->soft_tid); +#if defined(CONFIG_SUBARCH_C3B) wrptbr(vcb->ptbr); +#elif defined(CONFIG_SUBARCH_C4) + sw64_write_csr_imb(vcb->ptbr_usr, CSR_PTBR_USR); + sw64_write_csr_imb(vcb->ptbr_sys, CSR_PTBR_SYS); +#endif sflush(); tbiv(); } diff --git a/arch/sw_64/kernel/hibernate_asm.S b/arch/sw_64/kernel/hibernate_asm.S index ebba57b8bd8b..0655efc59a25 100644 --- a/arch/sw_64/kernel/hibernate_asm.S +++ b/arch/sw_64/kernel/hibernate_asm.S @@ -3,6 +3,7 @@ #include #include #include +#include .macro SAVE_KTP #ifdef CONFIG_SUBARCH_C3B -- Gitee From 21f68a97ec85312b1dcfc628ae5981c49780729e Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Thu, 18 Apr 2024 10:34:54 +0800 Subject: [PATCH 91/98] sw64: fix save_ktp compatibility for C3 Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Commit 388c8e2bbf53 ("sw64: introduce new entry framework for C4") moves save_ktp() to head.S, and breaks compatibility with old firmware because hmcall_wrktp was not implemented. To fix it, save_ktp() should come after fixup_hmcall(). Fixes: 388c8e2bbf53 ("sw64: introduce new entry framework for C4") Signed-off-by: Wu Liliu Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/hmcall.h | 9 +++++++-- arch/sw_64/kernel/early_init.c | 1 + arch/sw_64/kernel/head.S | 1 - 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/sw_64/include/asm/hmcall.h b/arch/sw_64/include/asm/hmcall.h index 71328c4eb332..c9509327a229 100644 --- a/arch/sw_64/include/asm/hmcall.h +++ b/arch/sw_64/include/asm/hmcall.h @@ -230,13 +230,18 @@ __CALL_HMC_W1(wrtp, unsigned long); /* Invalidate all user TLB with current UPN and VPN */ #define tbiu() __tbi(4, /* no second argument */) -#ifndef CONFIG_SUBARCH_C3B +#if defined(CONFIG_SUBARCH_C4) __CALL_HMC_W2(wrap_asid, unsigned long, unsigned long); -#else +static inline void save_ktp(void) +{ + __asm__ __volatile__("csrw $8, 0xef"); +} +#elif defined(CONFIG_SUBARCH_C3B) static inline void wrap_asid(unsigned long asid, unsigned long ptbr) { tbivp(); } +#define save_ktp() wrktp() #endif #endif /* !__ASSEMBLY__ */ diff --git a/arch/sw_64/kernel/early_init.c b/arch/sw_64/kernel/early_init.c index 3d7b9c4325a9..2ec7a3e99443 100644 --- a/arch/sw_64/kernel/early_init.c +++ b/arch/sw_64/kernel/early_init.c @@ -6,5 +6,6 @@ asmlinkage __visible void __init sw64_start_kernel(void) { fixup_hmcall(); + save_ktp(); start_kernel(); } diff --git a/arch/sw_64/kernel/head.S b/arch/sw_64/kernel/head.S index db4af8f9366b..15265fa4a0ea 100644 --- a/arch/sw_64/kernel/head.S +++ b/arch/sw_64/kernel/head.S @@ -32,7 +32,6 @@ __start: 1: ldgp $29, 0($27) /* We need to get current_task_info loaded up... */ ldi $8, init_task - SAVE_KTP ldl $30, TASK_STACK($8) /* ... and find our stack ... */ ldi $30, ASM_THREAD_SIZE($30) -- Gitee From 8e53184da5d7870b1318e6e035b2d994b15ef95e Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Mon, 22 Apr 2024 14:51:36 +0800 Subject: [PATCH 92/98] sw64: fix compile warning of do_entUna() Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Fix the following warnings: arch/sw_64/kernel/traps.c: In function 'do_entUna': arch/sw_64/kernel/traps.c:411:3: warning: this statement may fall through [-Wimplicit-fallthrough=] switch (fncode) { ^~~~~~ arch/sw_64/kernel/traps.c:585:2: note: here case 0x21: ^~~~ Fixes: 678e75e7273f ("sw64: add unaligned access support for C4 new instructions") Signed-off-by: He Chuyue Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/traps.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index 1405e42f27b4..8dd522d09860 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -582,6 +582,8 @@ do_entUna(void *va, unsigned long opcode, unsigned long reg, regs->regs[rb] = regs->regs[rb] + disp; return; } + return; + case 0x21: __asm__ __volatile__( "1: ldl_u %1, 0(%3)\n" -- Gitee From dde9ed1fd57201b60608da4397c308db621d2a2c Mon Sep 17 00:00:00 2001 From: Jing Li Date: Mon, 22 Apr 2024 19:58:47 +0800 Subject: [PATCH 93/98] sw64: pci: get register base address from firmware Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Kernel get all register base addresses of PCIe controller from firmware. In this way, even if these base addresses change in the future, related drivers in kernel do not need to be modified. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/pci.h | 2 + arch/sw_64/pci/acpi.c | 26 +++--- drivers/pci/controller/pci-sunway.c | 123 +++++++++++++--------------- 3 files changed, 72 insertions(+), 79 deletions(-) diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index f39d07144af9..074b57908aad 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -51,6 +51,8 @@ struct pci_controller { /* This one's for the kernel only. It's in KSEG somewhere. */ void __iomem *ep_config_space_base; void __iomem *rc_config_space_base; + void __iomem *piu_ior0_base; + void __iomem *piu_ior1_base; unsigned long index; unsigned long node; diff --git a/arch/sw_64/pci/acpi.c b/arch/sw_64/pci/acpi.c index 2f446116e69e..6f03ea79131c 100644 --- a/arch/sw_64/pci/acpi.c +++ b/arch/sw_64/pci/acpi.c @@ -5,6 +5,8 @@ #include #include +#define UPPER_32_BITS_OF_U64(u64_val) ((u64_val) & 0xFFFFFFFF00000000ULL) + struct pci_root_info { struct acpi_pci_root_info info; struct pci_config_window *cfg; @@ -88,25 +90,25 @@ pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root) static int pci_acpi_prepare_root_resources(struct acpi_pci_root_info *ci) { int status = 0; - acpi_status rc; - unsigned long long memh = 0; + u64 memh; struct resource_entry *entry = NULL, *tmp = NULL; struct acpi_device *device = ci->bridge; /** * To distinguish between mem and pre_mem, firmware - * only pass the lower 32bits of mem via acpi and - * use vendor specific "MEMH" to record the upper - * 32 bits of mem. + * only pass the lower 32bits of mem via _CRS method. * * Get the upper 32 bits here. */ - rc = acpi_evaluate_integer(ci->bridge->handle, "MEMH", NULL, &memh); - if (rc != AE_OK) { - dev_err(&device->dev, "unable to retrieve MEMH\n"); - return -EEXIST; + status = fwnode_property_read_u64_array(&device->fwnode, + "sw64,ep_mem_32_base", &memh, 1); + if (status) { + dev_err(&device->dev, "unable to retrieve \"sw64,ep_mem_32_base\"\n"); + return status; } + memh = UPPER_32_BITS_OF_U64(memh); + /** * Get host bridge resources via _CRS method, the return value * is the num of resource parsed. @@ -129,10 +131,10 @@ static int pci_acpi_prepare_root_resources(struct acpi_pci_root_info *ci) resource_list_for_each_entry_safe(entry, tmp, &ci->resources) { if (entry->res->flags & IORESOURCE_MEM) { - if (!(entry->res->end & 0xFFFFFFFF00000000ULL)) { + if (!UPPER_32_BITS_OF_U64(entry->res->end)) { /* Patch mem res with upper 32 bits */ - entry->res->start |= (memh << 32); - entry->res->end |= (memh << 32); + entry->res->start |= memh; + entry->res->end |= memh; } else { /** * Add PREFETCH and MEM_64 flags for diff --git a/drivers/pci/controller/pci-sunway.c b/drivers/pci/controller/pci-sunway.c index 2f2b5c19a414..1a4bc27eb660 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -666,70 +666,61 @@ static void setup_intx_irqs(struct pci_controller *hose) set_pcieport_service_irq(node, index); } -static int sw64_pci_prepare_controller(struct pci_controller *hose, - struct acpi_device *adev) -{ - unsigned long long index, node; - unsigned long long rc_config_base_addr; - unsigned long long pci_io_base_addr; - unsigned long long ep_io_base_addr; - acpi_status rc; - - /* Get node from ACPI namespace */ - node = acpi_get_node(adev->handle); - if (node == NUMA_NO_NODE) { - dev_err(&adev->dev, "unable to get node ID\n"); - return -EEXIST; - } - - /* Get index from ACPI namespace */ - rc = acpi_evaluate_integer(adev->handle, "INDX", NULL, &index); - if (rc != AE_OK) { - dev_err(&adev->dev, "unable to retrieve INDX\n"); - return -EEXIST; - } - - /** - * Get Root Complex config space base address. - * - * For sw64, Root Complex config space base addr is different - * from Endpoint config space base address. Use MCFG table to - * pass Endpoint config space base address, and define Root Complex - * config space base address("RCCB") separately in the ACPI namespace. - */ - rc = acpi_evaluate_integer(adev->handle, - "RCCB", NULL, &rc_config_base_addr); - if (rc != AE_OK) { - dev_err(&adev->dev, "unable to retrieve RCCB\n"); - return -EEXIST; - } +enum pci_props { + PROP_RC_CONFIG_BASE = 0, + PROP_EP_CONFIG_BASE, + PROP_EP_MEM_32_BASE, + PROP_EP_MEM_64_BASE, + PROP_EP_IO_BASE, + PROP_PIU_IOR0_BASE, + PROP_PIU_IOR1_BASE, + PROP_RC_INDEX, + PROP_PCIE_IO_BASE, + PROP_NUM +}; - /* Get Root Complex I/O space base addr from ACPI namespace */ - rc = acpi_evaluate_integer(adev->handle, - "RCIO", NULL, &pci_io_base_addr); - if (rc != AE_OK) { - dev_err(&adev->dev, "unable to retrieve RCIO\n"); - return -EEXIST; - } +const char *prop_names[PROP_NUM] = { + "sw64,rc_config_base", + "sw64,ep_config_base", + "sw64,ep_mem_32_base", + "sw64,ep_mem_64_base", + "sw64,ep_io_base", + "sw64,piu_ior0_base", + "sw64,piu_ior1_base", + "sw64,rc_index", + "sw64,pcie_io_base" +}; - /* Get Endpoint I/O space base addr from ACPI namespace */ - rc = acpi_evaluate_integer(adev->handle, - "EPIO", NULL, &ep_io_base_addr); - if (rc != AE_OK) { - dev_err(&adev->dev, "unable to retrieve EPIO\n"); - return -EEXIST; +static int sw64_pci_prepare_controller(struct pci_controller *hose, + struct fwnode_handle *fwnode) +{ + u64 props[PROP_NUM]; + int i, ret; + + /* Get properties of Root Complex */ + for (i = 0; i < PROP_NUM; ++i) { + ret = fwnode_property_read_u64_array(fwnode, prop_names[i], + &props[i], 1); + if (ret) { + pr_err("unable to retrieve \"%s\"\n", + prop_names[i]); + return ret; + } } hose->iommu_enable = false; - hose->index = index; - hose->node = node; + + hose->index = props[PROP_RC_INDEX]; hose->sparse_mem_base = 0; hose->sparse_io_base = 0; - hose->dense_mem_base = pci_io_base_addr; - hose->dense_io_base = ep_io_base_addr; + hose->dense_mem_base = props[PROP_PCIE_IO_BASE]; + hose->dense_io_base = props[PROP_EP_IO_BASE]; - hose->rc_config_space_base = __va(rc_config_base_addr); + hose->rc_config_space_base = __va(props[PROP_RC_CONFIG_BASE]); + hose->ep_config_space_base = __va(props[PROP_EP_CONFIG_BASE]); + hose->piu_ior0_base = __va(props[PROP_PIU_IOR0_BASE]); + hose->piu_ior1_base = __va(props[PROP_PIU_IOR1_BASE]); hose->first_busno = 0xff; hose->last_busno = 0xff; @@ -754,11 +745,11 @@ static int sw64_pci_prepare_controller(struct pci_controller *hose, * Root Complex link up failed. * This usually means that no device on the slot. */ - dev_info(&adev->dev, ": failed to link up\n", + pr_info(": link down\n", hose->node, hose->index); } else { pci_mark_rc_linkup(hose->node, hose->index); - dev_info(&adev->dev, ": successfully link up\n", + pr_info(": successfully link up\n", hose->node, hose->index); } @@ -777,7 +768,6 @@ static int sw64_pci_ecam_init(struct pci_config_window *cfg) struct pci_controller *hose = NULL; struct device *dev = cfg->parent; struct acpi_device *adev = to_acpi_device(dev); - phys_addr_t mcfg_addr; int ret; /** @@ -805,17 +795,16 @@ static int sw64_pci_ecam_init(struct pci_config_window *cfg) if (!hose) return -ENOMEM; - /* Get Endpoint config space base address from MCFG table */ - mcfg_addr = cfg->res.start - (cfg->busr.start << cfg->ops->bus_shift); - - /** - * "__va(mcfg_addr)" is equal to "cfg->win", so we can also use - * "hose->ep_config_space_base = cfg->win" here - */ - hose->ep_config_space_base = __va(mcfg_addr); + /* Get node from ACPI namespace (_PXM) */ + hose->node = acpi_get_node(adev->handle); + if (hose->node == NUMA_NO_NODE) { + kfree(hose); + dev_err(&adev->dev, "unable to get node ID\n"); + return -EINVAL; + } /* Init pci_controller */ - ret = sw64_pci_prepare_controller(hose, adev); + ret = sw64_pci_prepare_controller(hose, &adev->fwnode); if (ret) { kfree(hose); dev_err(&adev->dev, "failed to init pci controller\n"); -- Gitee From b49062aa716c87dd7c5fbd88ccd31fd0eb6d302e Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 24 Apr 2024 20:15:54 +0800 Subject: [PATCH 94/98] sw64: acpi: remove constraint that cid of boot core must be zero Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- The current code has a constraint that cid of boot core must be zero. Actually, the boot core is the first online core, and its cid does not have to be zero. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/acpi.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/arch/sw_64/kernel/acpi.c b/arch/sw_64/kernel/acpi.c index c50ae846ff62..d0e853659211 100644 --- a/arch/sw_64/kernel/acpi.c +++ b/arch/sw_64/kernel/acpi.c @@ -22,9 +22,9 @@ 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 */ +static unsigned int possible_cores; /* number of possible cores */ +static unsigned int present_cores; /* number of present cores */ +static unsigned int disabled_cores; /* number of disabled cores */ int acpi_strict; u64 arch_acpi_wakeup_start; @@ -260,12 +260,6 @@ setup_rcid_and_core_mask(struct acpi_madt_sw_cintc *sw_cintc) 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\n"); - return -EINVAL; - } - /* Online capable makes core possible */ if (!is_core_enabled(sw_cintc->flags) && !is_core_online_capable(sw_cintc->flags)) { @@ -273,13 +267,9 @@ setup_rcid_and_core_mask(struct acpi_madt_sw_cintc *sw_cintc) return 0; } - rcid_information_init(sw_cintc->version); + logical_core_id = possible_cores++; - /* The logical core ID of the boot core must be 0 */ - if (rcid == 0) - logical_core_id = 0; - else - logical_core_id = possible_cores++; + rcid_information_init(sw_cintc->version); set_rcid_map(logical_core_id, rcid); set_cpu_possible(logical_core_id, true); @@ -294,8 +284,7 @@ setup_rcid_and_core_mask(struct acpi_madt_sw_cintc *sw_cintc) 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++; + present_cores++; } return 0; -- Gitee From a9a26dd6b47bb876565833901391f62f7372c107 Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Fri, 26 Apr 2024 16:55:50 +0000 Subject: [PATCH 95/98] sw64: distribute intx interrupts by hose Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- CPU0 may encounter performance issue if there are too many intx interrupts erupted. We change the intx interrupts init strategy to improve this condition. Instead of sending all intx interrupts to CPU0 directly, these interrupts will be distributed to different cores by hose accordingly. Thus, the overall pressure on CPU0 is expected to be substantially reduced. We also refactor intx interrupts handling and integrate all intx related code into another file to make it look more clean and organized. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/pci.h | 5 + arch/sw_64/pci/pci-legacy.c | 41 ------ drivers/irqchip/Kconfig | 5 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-sunway-pci-intx.c | 185 ++++++++++++++++++++++++++ drivers/pci/controller/pci-sunway.c | 30 ----- 6 files changed, 196 insertions(+), 71 deletions(-) create mode 100644 drivers/irqchip/irq-sunway-pci-intx.c diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index 074b57908aad..1bd2123362f0 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -82,6 +82,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 sw64_init_arch(void); extern struct pci_ops sw64_pci_ops; @@ -162,6 +163,10 @@ extern void pci_remove_resource_files(struct pci_dev *dev); extern void __init reserve_mem_for_pci(void); 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_VENDOR_ID_JN 0x5656 #define PCI_DEVICE_ID_SW64_ROOT_BRIDGE 0x3231 #define PCI_DEVICE_ID_JN_PCIESW 0x1000 diff --git a/arch/sw_64/pci/pci-legacy.c b/arch/sw_64/pci/pci-legacy.c index 15ee626593e9..c968b3543dbe 100644 --- a/arch/sw_64/pci/pci-legacy.c +++ b/arch/sw_64/pci/pci-legacy.c @@ -304,47 +304,6 @@ void __init sw64_init_arch(void) void __weak set_pcieport_service_irq(int node, int index) {} -static void __init sw64_init_intx(struct pci_controller *hose) -{ - unsigned long int_conf, node, val_node; - unsigned long index, irq; - int rcid; - - node = hose->node; - index = hose->index; - - if (!node_online(node)) - val_node = next_node_in(node, node_online_map); - else - val_node = node; - irq = irq_alloc_descs_from(NR_IRQS_LEGACY, 2, val_node); - WARN_ON(irq < 0); - irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_level_irq); - irq_set_status_flags(irq, IRQ_LEVEL); - hose->int_irq = irq; - irq_set_chip_and_handler(irq + 1, &dummy_irq_chip, handle_level_irq); - hose->service_irq = irq + 1; - rcid = cpu_to_rcid(0); - - pr_info_once("INTx are directed to node %d core %d.\n", - ((rcid >> 6) & 0x3), (rcid & 0x1f)); - int_conf = 1UL << 62 | rcid; /* rebase all intx on the first logical cpu */ - if (sw64_chip_init->pci_init.set_intx) - sw64_chip_init->pci_init.set_intx(node, index, int_conf); - - set_pcieport_service_irq(node, index); -} - -void __init sw64_init_irq(void) -{ - struct pci_controller *hose; - - /* Scan all of the recorded PCI controllers. */ - hose = hose_head; - for (hose = hose_head; hose; hose = hose->next) - sw64_init_intx(hose); -} - void __init sw64_init_pci(void) { diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 336f357f380e..a11ff05692ce 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -37,6 +37,11 @@ config SW64_IRQ_CPU depends on SW64 default y +config SW64_PCI_INTX + bool + depends on SW64 && PCI + default y + config SW64_IRQ_MSI bool depends on SW64 && PCI_MSI diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 6b90d7ce01f4..cd085dde0d35 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o obj-$(CONFIG_SW64_PINTC) += irq-sunway-pintc.o obj-$(CONFIG_SW64_LPC_INTC) += irq-sunway-lpc-intc.o +obj-$(CONFIG_SW64_PCI_INTX) += irq-sunway-pci-intx.o obj-$(CONFIG_SW64_IRQ_CPU) += irq-sunway-cpu.o ifeq ($(CONFIG_UNCORE_XUELANG),y) diff --git a/drivers/irqchip/irq-sunway-pci-intx.c b/drivers/irqchip/irq-sunway-pci-intx.c new file mode 100644 index 000000000000..93ee2361e958 --- /dev/null +++ b/drivers/irqchip/irq-sunway-pci-intx.c @@ -0,0 +1,185 @@ +#include +#include +#include + +#include +#include +#include +#include +#include + +static DEFINE_RAW_SPINLOCK(legacy_lock); +static void lock_legacy_lock(void) +{ + raw_spin_lock(&legacy_lock); +} + +static void unlock_legacy_lock(void) +{ + raw_spin_unlock(&legacy_lock); +} + +static void set_intx(unsigned long node, unsigned long index, unsigned long intx_conf) +{ + if (is_guest_or_emul()) + return; + + write_piu_ior0(node, index, INTACONFIG, intx_conf | (0x8UL << 10)); + write_piu_ior0(node, index, INTBCONFIG, intx_conf | (0x4UL << 10)); + write_piu_ior0(node, index, INTCCONFIG, intx_conf | (0x2UL << 10)); + write_piu_ior0(node, index, INTDCONFIG, intx_conf | (0x1UL << 10)); +} + +static int __assign_piu_intx_config(struct pci_controller *hose, cpumask_t *targets) +{ + unsigned long intx_conf; + unsigned int cpu; + int node, index; + int phy_cpu; + + node = hose->node; + index = hose->index; + + /* Use the last cpu in valid cpus to avoid core 0. */ + cpu = cpumask_last(targets); + phy_cpu = cpu_to_rcid(cpu); + + intx_conf = ((phy_cpu >> 5) << 6) | (phy_cpu & 0x1f); + set_intx(node, index, intx_conf); + + return 0; +} + +static int assign_piu_intx_config(struct pci_controller *hose, cpumask_t *targets) +{ + int ret; + + lock_legacy_lock(); + ret = __assign_piu_intx_config(hose, targets); + unlock_legacy_lock(); + + return ret; +} + +static void intx_irq_enable(struct irq_data *irq_data) +{ + struct pci_controller *hose = irq_data->chip_data; + unsigned long intx_conf, node, index; + + if (is_guest_or_emul()) + return; + BUG_ON(!hose); + + node = hose->node; + index = hose->index; + + intx_conf = read_piu_ior0(node, index, INTACONFIG); + intx_conf |= PCI_INTX_ENABLE; + write_piu_ior0(node, index, INTACONFIG, intx_conf); + + intx_conf = read_piu_ior0(node, index, INTBCONFIG); + intx_conf |= PCI_INTX_ENABLE; + write_piu_ior0(node, index, INTBCONFIG, intx_conf); + + intx_conf = read_piu_ior0(node, index, INTCCONFIG); + intx_conf |= PCI_INTX_ENABLE; + write_piu_ior0(node, index, INTCCONFIG, intx_conf); + + intx_conf = read_piu_ior0(node, index, INTDCONFIG); + intx_conf |= PCI_INTX_ENABLE; + write_piu_ior0(node, index, INTDCONFIG, intx_conf); +} + +static void intx_irq_disable(struct irq_data *irq_data) +{ + struct pci_controller *hose = irq_data->chip_data; + unsigned long intx_conf, node, index; + + if (is_guest_or_emul()) + return; + + BUG_ON(!hose); + node = hose->node; + index = hose->index; + + intx_conf = read_piu_ior0(node, index, INTACONFIG); + intx_conf &= PCI_INTX_DISABLE; + write_piu_ior0(node, index, INTACONFIG, intx_conf); + + intx_conf = read_piu_ior0(node, index, INTBCONFIG); + intx_conf &= PCI_INTX_DISABLE; + write_piu_ior0(node, index, INTBCONFIG, intx_conf); + + intx_conf = read_piu_ior0(node, index, INTCCONFIG); + intx_conf &= PCI_INTX_DISABLE; + write_piu_ior0(node, index, INTCCONFIG, intx_conf); + + intx_conf = read_piu_ior0(node, index, INTDCONFIG); + intx_conf &= PCI_INTX_DISABLE; + write_piu_ior0(node, index, INTDCONFIG, intx_conf); +} + +static int intx_set_affinity(struct irq_data *irq_data, + const struct cpumask *dest, bool force) +{ + struct pci_controller *hose = irq_data->chip_data; + cpumask_t targets; + int ret = 0; + + if (cpumask_any_and(dest, cpu_online_mask) >= nr_cpu_ids) + return -EINVAL; + + cpumask_copy(&targets, dest); + + intx_irq_disable(irq_data); + ret = assign_piu_intx_config(hose, &targets); + intx_irq_enable(irq_data); + + return ret; +} + +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, + .flags = IRQCHIP_SKIP_SET_WAKE, +}; + +void __weak set_pcieport_service_irq(int node, int index) {} + +void setup_intx_irqs(struct pci_controller *hose) +{ + unsigned long irq, node, index, val_node; + + node = hose->node; + index = hose->index; + + if (!node_online(node)) + val_node = next_node_in(node, node_online_map); + else + val_node = node; + + irq = irq_alloc_descs_from(NR_IRQS_LEGACY, 2, val_node); + 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); + hose->int_irq = irq; + irq_set_chip_and_handler(irq + 1, &dummy_irq_chip, handle_level_irq); + hose->service_irq = irq + 1; + + set_pcieport_service_irq(node, index); +} + +void __init sw64_init_irq(void) +{ + struct pci_controller *hose = hose_head; + + for (hose = hose_head; hose; hose = hose->next) + setup_intx_irqs(hose); +} + diff --git a/drivers/pci/controller/pci-sunway.c b/drivers/pci/controller/pci-sunway.c index 1a4bc27eb660..420572592779 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -635,36 +635,6 @@ int sw64_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) } #ifdef CONFIG_ACPI -static void setup_intx_irqs(struct pci_controller *hose) -{ - unsigned long int_conf, node, val_node; - unsigned long index, irq; - int rcid; - - node = hose->node; - index = hose->index; - - if (!node_online(node)) - val_node = next_node_in(node, node_online_map); - else - val_node = node; - irq = irq_alloc_descs_from(NR_IRQS_LEGACY, 2, val_node); - WARN_ON(irq < 0); - irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_level_irq); - irq_set_status_flags(irq, IRQ_LEVEL); - hose->int_irq = irq; - irq_set_chip_and_handler(irq + 1, &dummy_irq_chip, handle_level_irq); - hose->service_irq = irq + 1; - rcid = cpu_to_rcid(0); - - pr_info_once("INTx are directed to node %d core %d.\n", - ((rcid >> 6) & 0x3), (rcid & 0x1f)); - int_conf = 1UL << 62 | rcid; /* rebase all intx on the first logical cpu */ - - set_intx(node, index, int_conf); - - set_pcieport_service_irq(node, index); -} enum pci_props { PROP_RC_CONFIG_BASE = 0, -- Gitee From 92b013ee00c0eaa1eb2f1fba1f60b1f1edf67042 Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Mon, 22 Apr 2024 14:51:36 +0800 Subject: [PATCH 96/98] sw64: fix compile warning of smp_callin() Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- This patch fixes a mixed declaration in smp_callin(). Signed-off-by: He Chuyue Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/smp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index a57d05fe700f..465775cdb4fe 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -58,8 +58,7 @@ enum core_version { */ void smp_callin(void) { - int cpuid = smp_processor_id(); - + int cpuid; #ifdef CONFIG_SUBARCH_C4 /* LV2 select PLL1 */ int i, cpu_num; @@ -72,7 +71,7 @@ void smp_callin(void) udelay(1000); } #endif - + cpuid = smp_processor_id(); local_irq_disable(); if (cpu_online(cpuid)) { -- Gitee From e9adb8f98608328d8667742af81a25b322c6124a Mon Sep 17 00:00:00 2001 From: Wu Liliu Date: Tue, 23 Apr 2024 09:15:51 +0800 Subject: [PATCH 97/98] sw64: remove redudant save_ktp Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- Macro save_ktp are defined in both hmcall.h and head.S which is unnecessary. Remove the definition in head.S. Signed-off-by: Wu Liliu Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/head.S | 9 --------- arch/sw_64/kernel/smp.c | 1 + 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/arch/sw_64/kernel/head.S b/arch/sw_64/kernel/head.S index 15265fa4a0ea..03da6f80dd0d 100644 --- a/arch/sw_64/kernel/head.S +++ b/arch/sw_64/kernel/head.S @@ -12,14 +12,6 @@ #include #include - .macro SAVE_KTP -#ifdef CONFIG_SUBARCH_C3B - sys_call HMC_wrktp -#else - csrw $8, CSR_KTP -#endif - .endm - __HEAD .globl _stext .set noreorder @@ -120,7 +112,6 @@ __smp_callin: ldi $2, idle_task_pointer s8addl $0, $2, $2 ldl $8, 0($2) # Get ksp of idle thread - SAVE_KTP ldl $30, TASK_STACK($8) ldi $30, ASM_THREAD_SIZE($30) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 465775cdb4fe..4b5a97bdbeef 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -71,6 +71,7 @@ void smp_callin(void) udelay(1000); } #endif + save_ktp(); cpuid = smp_processor_id(); local_irq_disable(); -- Gitee From 37a272273265e3ee601b261e69892a517c8f3edd Mon Sep 17 00:00:00 2001 From: He Sheng Date: Tue, 23 Apr 2024 15:05:45 +0800 Subject: [PATCH 98/98] sw64: wrap frequency workaround into standalone functions Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR -------------------------------- This will make the code easier to understand and maintain. Besides, frequency workaround is useless on guest and emulator, so nothing is done in that situation. Signed-off-by: He Sheng Reviewed-by: Cui Wei Signed-off-by: Gu Zitao --- arch/sw_64/kernel/smp.c | 61 +++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 4b5a97bdbeef..78d4082e1a58 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -53,25 +53,53 @@ enum core_version { CORE_VERSION_RESERVED = 3 /* 3 and greater are reserved */ }; -/* - * Where secondaries begin a life of C. - */ -void smp_callin(void) -{ - int cpuid; #ifdef CONFIG_SUBARCH_C4 - /* LV2 select PLL1 */ +static void upshift_freq(void) +{ int i, cpu_num; + if (is_guest_or_emul()) + return; cpu_num = sw64_chip->get_cpu_num(); - for (i = 0; i < cpu_num; i++) { sw64_io_write(i, CLU_LV2_SELH, -1UL); sw64_io_write(i, CLU_LV2_SELL, -1UL); udelay(1000); } +} + +static void downshift_freq(void) +{ + unsigned long value; + int cpuid, core_id, node_id; + + if (is_guest_or_emul()) + return; + cpuid = smp_processor_id(); + core_id = rcid_to_core_id(cpu_to_rcid(cpuid)); + node_id = rcid_to_domain_id(cpu_to_rcid(cpuid)); + + if (core_id > 31) { + value = 1UL << (2 * (core_id - 32)); + sw64_io_write(node_id, CLU_LV2_SELH, value); + } else { + value = 1UL << (2 * core_id); + sw64_io_write(node_id, CLU_LV2_SELL, value); + } +} +#else +static void upshift_freq(void) { } +static void downshift_freq(void) { } #endif + +/* + * Where secondaries begin a life of C. + */ +void smp_callin(void) +{ + int cpuid; save_ktp(); + upshift_freq(); cpuid = smp_processor_id(); local_irq_disable(); @@ -613,22 +641,7 @@ void __cpu_die(unsigned int cpu) void arch_cpu_idle_dead(void) { -#ifdef CONFIG_SUBARCH_C4 - /* LV2 select PLL0 */ - int cpuid = smp_processor_id(); - int core_id = rcid_to_core_id(cpu_to_rcid(cpuid)); - int node_id = rcid_to_domain_id(cpu_to_rcid(cpuid)); - unsigned long value; - - if (core_id > 31) { - value = 1UL << (2 * (core_id - 32)); - sw64_io_write(node_id, CLU_LV2_SELH, value); - } else { - value = 1UL << (2 * core_id); - sw64_io_write(node_id, CLU_LV2_SELL, value); - } -#endif - + downshift_freq(); idle_task_exit(); mb(); __this_cpu_write(cpu_state, CPU_DEAD); -- Gitee