From 6bd549fbab60bfdcce5cf4ce2efdd0e9f69c0cde Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 6 Jun 2024 09:02:18 +0800 Subject: [PATCH 001/100] anolis: sw64: gpio: fix compile error of sunway_gpio_add_port ANBZ: #4688 The struct gpio_chip no longer has member 'of_node'. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/gpio/gpio-sunway.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-sunway.c b/drivers/gpio/gpio-sunway.c index 8532e31edbec..1b42ecbe25ee 100644 --- a/drivers/gpio/gpio-sunway.c +++ b/drivers/gpio/gpio-sunway.c @@ -525,9 +525,7 @@ static int sunway_gpio_add_port(struct sunway_gpio *gpio, return err; } -#ifdef CONFIG_OF_GPIO - port->gc.of_node = to_of_node(pp->fwnode); -#endif + port->gc.fwnode = pp->fwnode; port->gc.ngpio = pp->ngpio; port->gc.base = pp->gpio_base; -- Gitee From 530840d17be6639795c251f84656179addda66a6 Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Tue, 11 Jun 2024 14:52:33 +0000 Subject: [PATCH 002/100] anolis: sw64: adapt irq-sunway-msi.c and irq-sunway-msi-v2.c to upstream ANBZ: #4688 Due to the changes in the upstream, this patch adapts the above for irq-sunway-msi.c and irq-sunway-msi-v2.c. Signed-off-by: Zheng Chongzhen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/irqchip/irq-sunway-msi-v2.c | 77 ++++++++++++++--------------- drivers/irqchip/irq-sunway-msi.c | 55 +++++++++------------ 2 files changed, 61 insertions(+), 71 deletions(-) diff --git a/drivers/irqchip/irq-sunway-msi-v2.c b/drivers/irqchip/irq-sunway-msi-v2.c index 2beacb1be39d..4a4f4f6ca040 100644 --- a/drivers/irqchip/irq-sunway-msi-v2.c +++ b/drivers/irqchip/irq-sunway-msi-v2.c @@ -51,23 +51,19 @@ bool find_free_cpu_vector(const struct cpumask *search_mask, cpu = cpumask_first(search_mask); try_again: - if (is_guest_or_emul()) { - vector = IRQ_PENDING_MSI_VECTORS_SHIFT; - max_vector = SWVM_IRQS; - } else { - vector = 0; - max_vector = 256; - } + vector = 0; + max_vector = 256; for (; vector < max_vector; vector++) { while (per_cpu(vector_irq, cpu)[vector]) { cpu = cpumask_next(cpu, search_mask); if (cpu >= nr_cpu_ids) { if (vector == 255) { if (find_once_global) { - pr_warn("No global free vector\n"); + pr_info("No global free vector\n"); return false; } - pr_warn("No local free vector\n"); + pr_info("No local free vector, search_mask:%*pbl\n", + cpumask_pr_args(search_mask)); search_mask = cpu_online_mask; cpu = cpumask_first(search_mask); find_once_global = true; @@ -111,10 +107,11 @@ static bool find_free_cpu_vectors(const struct cpumask *search_mask, int *found_ goto try_again; else { if (find_once_global) { - pr_warn("No global free vectors\n"); + pr_info("No global free vectors\n"); return found; } - pr_warn("No local free vectors\n"); + pr_info("No local free vectors, search_mask:%*pbl\n", + cpumask_pr_args(search_mask)); search_mask = cpu_online_mask; cpu = cpumask_first(search_mask); find_once_global = true; @@ -146,6 +143,9 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask, if (!cdata) return -ENOMEM; + if (cdata->move_in_progress) + return -EBUSY; + /* * If existing target cpu is already in the new mask and is online * then do nothing. @@ -172,15 +172,22 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask, /* update new setting */ entry = irq_get_msi_desc(irqd->irq); spin_lock(&cdata->cdata_lock); + if (cpu_online(cdata->dst_cpu)) { + cdata->move_in_progress = true; + cdata->prev_vector = cdata->vector; + cdata->prev_cpu = cdata->dst_cpu; + } else { + for (i = 0; i < cdata->multi_msi; i++) + per_cpu(vector_irq, cdata->dst_cpu)[cdata->vector] = 0; + } + + cdata->vector = vector; + cdata->dst_cpu = cpu; for (i = 0; i < cdata->multi_msi; i++) per_cpu(vector_irq, cpu)[vector + i] = entry->irq + i; - BUG_ON(irq_chip_compose_msi_msg(irqd, &msg)); + + irq_msi_compose_msg(d, &msg); __pci_write_msi_msg(entry, &msg); - cdata->prev_vector = cdata->vector; - cdata->prev_cpu = cdata->dst_cpu; - cdata->dst_cpu = cpu; - cdata->vector = vector; - cdata->move_in_progress = true; spin_unlock(&cdata->cdata_lock); cpumask_copy(irq_data_get_affinity_mask(irqd), &searchmask); @@ -238,7 +245,7 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs, cdata = alloc_sw_msi_chip_data(irq_data); if (!cdata) { - pr_warn("error alloc irq chip data\n"); + pr_info("error alloc irq chip data\n"); return -ENOMEM; } @@ -274,7 +281,7 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs, cdata = alloc_sw_msi_chip_data(irq_data); if (!cdata) { - pr_warn("error alloc irq chip data\n"); + pr_info("error alloc irq chip data\n"); return -ENOMEM; } @@ -334,11 +341,6 @@ static void sw64_vector_free_irqs(struct irq_domain *domain, static void sw64_irq_free_descs(unsigned int virq, unsigned int nr_irqs) { - if (is_guest_or_emul()) { - vt_sw64_vector_free_irqs(virq, nr_irqs); - return irq_free_descs(virq, nr_irqs); - } - return irq_domain_free_irqs(virq, nr_irqs); } @@ -347,7 +349,7 @@ void arch_teardown_msi_irqs(struct pci_dev *dev) struct msi_desc *desc; int i; - for_each_pci_msi_entry(desc, dev) { + msi_for_each_desc(desc, &dev->dev, MSI_DESC_ASSOCIATED) { if (desc->irq) { for (i = 0; i < desc->nvec_used; i++) sw64_irq_free_descs(desc->irq + i, 1); @@ -379,11 +381,11 @@ static int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec, msi_alloc_info_t *arg) { struct pci_dev *pdev = to_pci_dev(dev); - struct msi_desc *desc = first_pci_msi_entry(pdev); + struct msi_desc *desc = msi_first_desc(dev, MSI_DESC_ALL); memset(arg, 0, sizeof(*arg)); arg->msi_dev = pdev; - if (desc->msi_attrib.is_msix) + if (desc->pci.msi_attrib.is_msix) arg->type = IRQ_ALLOC_TYPE_MSIX; else arg->type = IRQ_ALLOC_TYPE_MSI; @@ -425,7 +427,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) if (!msi_default_domain) return -EIO; - err = msi_domain_alloc_irqs(msi_default_domain, &pdev->dev, nvec); + err = msi_domain_alloc_irqs_all_locked(&pdev->dev, MSI_DEFAULT_DOMAIN, nvec); return err; } @@ -433,16 +435,20 @@ void arch_init_msi_domain(struct irq_domain *parent) { struct irq_domain *sw64_irq_domain; - if (is_guest_or_emul()) - return; - sw64_irq_domain = irq_domain_add_tree(NULL, &sw64_msi_domain_ops, NULL); BUG_ON(sw64_irq_domain == NULL); irq_set_default_host(sw64_irq_domain); msi_default_domain = pci_msi_create_irq_domain(NULL, &pci_msi_domain_info, sw64_irq_domain); if (!msi_default_domain) - pr_warn("failed to initialize irqdomain for MSI/MSI-x.\n"); + pr_info("failed to initialize irqdomain for MSI/MSI-x.\n"); +} + +int pcibios_device_add(struct pci_dev *dev) +{ + if (msi_default_domain) + dev_set_msi_domain(&dev->dev, msi_default_domain); + return 0; } static void irq_move_complete(struct sw64_msi_chip_data *cdata, int cpu, int vector) @@ -472,13 +478,6 @@ void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned struct irq_data *irq_data; struct sw64_msi_chip_data *cdata; - if (is_guest_or_emul()) { - cpu = smp_processor_id(); - irq = per_cpu(vector_irq, cpu)[vector]; - handle_irq(irq); - return; - } - ptr = (unsigned long *)pci_msi1_addr; int_pci_msi[0] = *ptr; int_pci_msi[1] = *(ptr + 1); diff --git a/drivers/irqchip/irq-sunway-msi.c b/drivers/irqchip/irq-sunway-msi.c index 6de689e5106f..e8fdcc5d744b 100644 --- a/drivers/irqchip/irq-sunway-msi.c +++ b/drivers/irqchip/irq-sunway-msi.c @@ -47,23 +47,19 @@ bool find_free_cpu_vector(const struct cpumask *search_mask, cpu = cpumask_first(search_mask); try_again: - if (is_guest_or_emul()) { - vector = IRQ_PENDING_MSI_VECTORS_SHIFT; - max_vector = SWVM_IRQS; - } else { - vector = 0; - max_vector = 256; - } + vector = 0; + max_vector = 256; for (; vector < max_vector; vector++) { while (per_cpu(vector_irq, cpu)[vector]) { cpu = cpumask_next(cpu, search_mask); if (cpu >= nr_cpu_ids) { if (vector == 255) { if (find_once_global) { - pr_warn("No global free vector\n"); + pr_info("No global free vector\n"); return false; } - pr_warn("No local free vector\n"); + pr_info("No local free vector, search_mask:%*pbl\n", + cpumask_pr_args(search_mask)); search_mask = cpu_online_mask; cpu = cpumask_first(search_mask); find_once_global = true; @@ -124,6 +120,9 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask, if (!cdata) return -ENOMEM; + if (cdata->move_in_progress) + return -EBUSY; + /* * If existing target cpu is already in the new mask and is online * then do nothing. @@ -144,14 +143,20 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask, pdev = (struct pci_dev *)msi_desc_to_pci_dev(entry); hose = pci_bus_to_pci_controller(pdev->bus); spin_lock(&cdata->cdata_lock); - per_cpu(vector_irq, cpu)[vector] = irqd->irq; - msi_config = set_piu_msi_config(hose, cpu, cdata->msi_config_index, vector); - cdata->prev_vector = cdata->vector; - cdata->prev_cpu = cdata->dst_cpu; + if (cpu_online(cdata->dst_cpu)) { + cdata->move_in_progress = true; + cdata->prev_vector = cdata->vector; + cdata->prev_cpu = cdata->dst_cpu; + } else { + per_cpu(vector_irq, cdata->dst_cpu)[cdata->vector] = 0; + } + cdata->dst_cpu = cpu; cdata->vector = vector; + per_cpu(vector_irq, cpu)[vector] = irqd->irq; + + msi_config = set_piu_msi_config(hose, cpu, cdata->msi_config_index, vector); cdata->msi_config = msi_config; - cdata->move_in_progress = true; spin_unlock(&cdata->cdata_lock); cpumask_copy((struct cpumask *)irq_data_get_affinity_mask(irqd), &searchmask); @@ -193,7 +198,8 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs, nr_irqs, nr_irqs - 1); if (msiconf_index >= 256) { - pr_warn("No free msi on PIU!\n"); + pr_info("No free msi on PIU! node:%ld index:%ld\n", + hose->node, hose->index); return -ENOSPC; } @@ -226,7 +232,7 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs, cdata = alloc_sw_msi_chip_data(irq_data); if (!cdata) { - pr_warn("error alloc irq chip data\n"); + pr_info("error alloc irq chip data\n"); return -ENOMEM; } @@ -291,11 +297,6 @@ static void sw64_vector_free_irqs(struct irq_domain *domain, static void sw64_irq_free_descs(unsigned int virq, unsigned int nr_irqs) { - if (is_guest_or_emul()) { - vt_sw64_vector_free_irqs(virq, nr_irqs); - return irq_free_descs(virq, nr_irqs); - } - return irq_domain_free_irqs(virq, nr_irqs); } @@ -391,16 +392,13 @@ void arch_init_msi_domain(struct irq_domain *parent) { struct irq_domain *sw64_irq_domain; - if (is_guest_or_emul()) - return; - sw64_irq_domain = irq_domain_add_tree(NULL, &sw64_msi_domain_ops, NULL); BUG_ON(sw64_irq_domain == NULL); irq_set_default_host(sw64_irq_domain); msi_default_domain = pci_msi_create_irq_domain(NULL, &pci_msi_domain_info, sw64_irq_domain); if (!msi_default_domain) - pr_warn("failed to initialize irqdomain for MSI/MSI-x.\n"); + pr_info("failed to initialize irqdomain for MSI/MSI-x.\n"); } int pcibios_device_add(struct pci_dev *dev) @@ -432,13 +430,6 @@ void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned struct irq_data *irq_data; struct sw64_msi_chip_data *cdata; - if (is_guest_or_emul()) { - cpu = smp_processor_id(); - irq = per_cpu(vector_irq, cpu)[vector]; - handle_irq(irq); - return; - } - ptr = (unsigned long *)pci_msi1_addr; int_pci_msi[0] = *ptr; int_pci_msi[1] = *(ptr + 1); -- Gitee From d16551ff2aba00e6f4bc2172d2e77090e237bf11 Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Tue, 11 Jun 2024 16:37:52 +0800 Subject: [PATCH 003/100] anolis: sw64: fix msi interrupt for guest os ANBZ: #4688 This patch: - Add msi_domain for guset os, including vt_pci_msi_domain_ops and pci_vt_msi_domain_info which support msi interrupt initialization in a standard way. - Modify the method to find free cpu vector to ensure that msi irq number can be set on the proper cpu. When migrate an interrupt, it can find the vector which was used before but not cleaned up. - Add vt_irq_move_complete() for guest os. If the interrupt migration has completed, it is necessory to clear its information on previous cpu before irq is handled. After that, it can handle msi interrupt correctly during cpu hotplug. Besides, move guset related code into irq-sunway-msi-vt.c. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/kvm.h | 2 +- arch/sw_64/include/asm/msi.h | 9 +- arch/sw_64/include/uapi/asm/kvm.h | 2 +- drivers/irqchip/irq-sunway-cpu.c | 7 +- drivers/irqchip/irq-sunway-msi-v2.c | 6 + drivers/irqchip/irq-sunway-msi-vt.c | 387 +++++++++++++++++----------- drivers/irqchip/irq-sunway-msi.c | 6 + 7 files changed, 263 insertions(+), 156 deletions(-) diff --git a/arch/sw_64/include/asm/kvm.h b/arch/sw_64/include/asm/kvm.h index f6e3022efcfe..41bb657bcacc 100644 --- a/arch/sw_64/include/asm/kvm.h +++ b/arch/sw_64/include/asm/kvm.h @@ -8,7 +8,7 @@ */ #define SWVM_IRQS 256 #define IRQ_PENDING_INTX_SHIFT 16 -#define IRQ_PENDING_MSI_VECTORS_SHIFT 17 +#define IRQ_PENDING_MSI_VECTORS_SHIFT 18 #define SWVM_NUM_NUMA_MEMBANKS 1 diff --git a/arch/sw_64/include/asm/msi.h b/arch/sw_64/include/asm/msi.h index e5d93040b2d3..4bec4b80fbe6 100644 --- a/arch/sw_64/include/asm/msi.h +++ b/arch/sw_64/include/asm/msi.h @@ -23,10 +23,15 @@ #define VT_MSIX_ADDR_DEST_ID(dest) \ (((dest) << VT_MSIX_ADDR_DEST_ID_SHIFT) & VT_MSIX_ADDR_DEST_ID_MASK) +enum irq_alloc_type; #ifdef CONFIG_PCI_MSI -extern void vt_sw64_vector_free_irqs(unsigned int virq, unsigned int nr_irqs); -extern int sw64_setup_vt_msi_irqs(struct pci_dev *dev, int nvec, int type); +extern void vt_handle_pci_msi_interrupt(unsigned long type, + unsigned long vector, + unsigned long pci_msi1_addr); +extern void sw64_init_vt_msi_domain(struct irq_domain *parent); +extern int sw64_setup_vt_msi_irqs(struct pci_dev *pdev, int nvec, int type); +extern int vt_pcibios_device_add(struct pci_dev *dev); extern bool find_free_cpu_vector(const struct cpumask *search_mask, int *found_cpu, int *found_vector); extern int msi_compose_msg(unsigned int irq, struct msi_msg *msg); diff --git a/arch/sw_64/include/uapi/asm/kvm.h b/arch/sw_64/include/uapi/asm/kvm.h index 2ae0cc74bb2b..3215aaa5f2eb 100644 --- a/arch/sw_64/include/uapi/asm/kvm.h +++ b/arch/sw_64/include/uapi/asm/kvm.h @@ -7,7 +7,7 @@ */ #define SWVM_IRQS 256 #define IRQ_PENDING_INTX_SHIFT 16 -#define IRQ_PENDING_MSI_VECTORS_SHIFT 17 +#define IRQ_PENDING_MSI_VECTORS_SHIFT 18 enum SW64_KVM_IRQ { SW64_KVM_IRQ_IPI = 27, diff --git a/drivers/irqchip/irq-sunway-cpu.c b/drivers/irqchip/irq-sunway-cpu.c index 23ad3b16af08..109bf4acedde 100644 --- a/drivers/irqchip/irq-sunway-cpu.c +++ b/drivers/irqchip/irq-sunway-cpu.c @@ -198,7 +198,7 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, if (is_guest_or_emul()) { if ((type & 0xffff) > 15) { vector = type; - if (vector == 16) + if (vector == 16 || vector == 17) type = INT_INTx; else type = INT_MSI; @@ -212,7 +212,10 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, switch (type & 0xffff) { case INT_MSI: old_regs = set_irq_regs(regs); - handle_pci_msi_interrupt(type, vector, irq_arg); + if (is_guest_or_emul()) + vt_handle_pci_msi_interrupt(type, vector, irq_arg); + else + handle_pci_msi_interrupt(type, vector, irq_arg); set_irq_regs(old_regs); return; case INT_INTx: diff --git a/drivers/irqchip/irq-sunway-msi-v2.c b/drivers/irqchip/irq-sunway-msi-v2.c index 4a4f4f6ca040..4e98a4c10f85 100644 --- a/drivers/irqchip/irq-sunway-msi-v2.c +++ b/drivers/irqchip/irq-sunway-msi-v2.c @@ -435,6 +435,9 @@ void arch_init_msi_domain(struct irq_domain *parent) { struct irq_domain *sw64_irq_domain; + if (is_guest_or_emul()) + return sw64_init_vt_msi_domain(parent); + sw64_irq_domain = irq_domain_add_tree(NULL, &sw64_msi_domain_ops, NULL); BUG_ON(sw64_irq_domain == NULL); irq_set_default_host(sw64_irq_domain); @@ -446,6 +449,9 @@ void arch_init_msi_domain(struct irq_domain *parent) int pcibios_device_add(struct pci_dev *dev) { + if (is_guest_or_emul()) + return vt_pcibios_device_add(dev); + if (msi_default_domain) dev_set_msi_domain(&dev->dev, msi_default_domain); return 0; diff --git a/drivers/irqchip/irq-sunway-msi-vt.c b/drivers/irqchip/irq-sunway-msi-vt.c index 65d4ea559447..a28f23799117 100644 --- a/drivers/irqchip/irq-sunway-msi-vt.c +++ b/drivers/irqchip/irq-sunway-msi-vt.c @@ -1,11 +1,100 @@ // SPDX-License-Identifier: GPL-2.0 -#include #include +#include #include +#include #include +#include +#include + +static struct irq_domain *vt_msi_default_domain; static DEFINE_RAW_SPINLOCK(vector_lock); +static void vt_irq_move_complete(struct sw64_msi_chip_data *cdata, int cpu) +{ + if (likely(!cdata->move_in_progress)) + return; + if (cdata->dst_cpu == cpu) { + raw_spin_lock(&vector_lock); + cdata->move_in_progress = false; + per_cpu(vector_irq, cdata->prev_cpu)[cdata->prev_vector] = 0; + raw_spin_unlock(&vector_lock); + } +} + +void vt_handle_pci_msi_interrupt(unsigned long type, unsigned long vector, + unsigned long pci_msi1_addr) +{ + int irq, cpu; + struct irq_data *irq_data; + struct sw64_msi_chip_data *cdata; + + cpu = smp_processor_id(); + irq = per_cpu(vector_irq, cpu)[vector]; + irq_data = irq_domain_get_irq_data(vt_msi_default_domain->parent, irq); + cdata = irq_data_get_irq_chip_data(irq_data); + + spin_lock(&cdata->cdata_lock); + vt_irq_move_complete(cdata, cpu); + spin_unlock(&cdata->cdata_lock); + + handle_irq(irq); +} + +static bool vt_find_free_cpu_vector(const struct cpumask *search_mask, + int *found_cpu, int *found_vector, struct irq_data *d) +{ + int vector, max_vector, cpu; + bool find_once_global = false; + + cpu = cpumask_first(search_mask); +try_again: + vector = IRQ_PENDING_MSI_VECTORS_SHIFT; + max_vector = SWVM_IRQS; + + for (; vector < max_vector; vector++) { + while (per_cpu(vector_irq, cpu)[vector]) { + if (per_cpu(vector_irq, cpu)[vector] == d->irq) + break; + + if (!irqd_affinity_is_managed(d)) + cpu = cpumask_next(cpu, search_mask); + else + vector++; + + if (vector >= max_vector) { + cpu = cpumask_next(cpu, search_mask); + vector = IRQ_PENDING_MSI_VECTORS_SHIFT; + } + + if (cpu >= nr_cpu_ids) { + if (vector == max_vector-1) { + if (find_once_global) { + pr_err("No global free vector\n"); + return false; + } + pr_err("No local free vector\n"); + search_mask = cpu_online_mask; + cpu = cpumask_first(search_mask); + find_once_global = true; + goto try_again; + } + cpu = cpumask_first(search_mask); + break; + } + } + if (per_cpu(vector_irq, cpu)[vector] == d->irq) + break; + if (!per_cpu(vector_irq, cpu)[vector]) + break; + } + + *found_cpu = cpu; + *found_vector = vector; + return true; +} + static void __vt_irq_msi_compose_msg(struct sw64_msi_chip_data *cdata, struct msi_msg *msg) { @@ -18,8 +107,11 @@ static void __vt_irq_msi_compose_msg(struct sw64_msi_chip_data *cdata, static void vt_irq_msi_compose_msg(struct irq_data *irqd, struct msi_msg *msg) { struct sw64_msi_chip_data *cdata; + struct irq_data *d; + + d = irq_domain_get_irq_data(vt_msi_default_domain->parent, irqd->irq); + cdata = d->chip_data; - cdata = irqd->chip_data; __vt_irq_msi_compose_msg(cdata, msg); } @@ -33,10 +125,11 @@ static void vt_irq_msi_update_msg(struct irq_data *irqd, } static int -vt_set_affinity(struct irq_data *irqd, const struct cpumask *cpumask, +vt_set_affinity(struct irq_data *d, const struct cpumask *cpumask, bool force) { struct sw64_msi_chip_data *cdata; + struct irq_data *irqd; struct cpumask searchmask; int cpu, vector; @@ -44,6 +137,7 @@ vt_set_affinity(struct irq_data *irqd, const struct cpumask *cpumask, if (cpumask_any_and(cpumask, cpu_online_mask) >= nr_cpu_ids) return -EINVAL; + irqd = irq_domain_get_irq_data(vt_msi_default_domain->parent, d->irq); if (!irqd_is_started(irqd)) return IRQ_SET_MASK_OK; @@ -59,63 +153,53 @@ vt_set_affinity(struct irq_data *irqd, const struct cpumask *cpumask, return IRQ_SET_MASK_OK; cpumask_and(&searchmask, cpumask, cpu_online_mask); - if (!find_free_cpu_vector(&searchmask, &cpu, &vector)) + if (!vt_find_free_cpu_vector(&searchmask, &cpu, &vector, irqd)) return -ENOSPC; per_cpu(vector_irq, cpu)[vector] = irqd->irq; spin_lock(&cdata->cdata_lock); - cdata->dst_cpu = cpu; - cdata->vector = vector; cdata->prev_cpu = cdata->dst_cpu; cdata->prev_vector = cdata->vector; + cdata->dst_cpu = cpu; + cdata->vector = vector; cdata->move_in_progress = true; spin_unlock(&cdata->cdata_lock); - cpumask_copy((struct cpumask *)irq_data_get_affinity_mask(irqd), &searchmask); + irq_data_update_effective_affinity(irqd, &searchmask); vt_irq_msi_update_msg(irqd, irqd->chip_data); return 0; } static struct irq_chip vt_pci_msi_controller = { - .name = "PCI-MSI", - .irq_unmask = pci_msi_unmask_irq, - .irq_mask = pci_msi_mask_irq, - .irq_ack = sw64_irq_noop, - .irq_compose_msi_msg = vt_irq_msi_compose_msg, - .irq_set_affinity = vt_set_affinity, + .name = "PCI-MSI", + .irq_unmask = pci_msi_unmask_irq, + .irq_mask = pci_msi_mask_irq, + .irq_ack = sw64_irq_noop, + .irq_compose_msi_msg = vt_irq_msi_compose_msg, + .flags = IRQCHIP_SKIP_SET_WAKE, + .irq_set_affinity = vt_set_affinity, }; -int chip_setup_vt_msix_irq(struct pci_dev *dev, struct msi_desc *desc) +int chip_setup_vt_msi_irqs(int virq, unsigned int nr_irqs, + struct irq_domain *domain, enum irq_alloc_type type) { - int virq, val_node = 0; struct irq_data *irq_data; struct sw64_msi_chip_data *cdata; - struct pci_controller *hose = pci_bus_to_pci_controller(dev->bus); - unsigned long flags, node, rc_index; - const struct cpumask *mask; + unsigned long node; + const struct cpumask *mask; struct cpumask searchmask; - int cpu, vector; - - node = hose->node; - rc_index = hose->index; - mask = cpumask_of_node(node); - - raw_spin_lock_irqsave(&vector_lock, flags); - /* Find unused msi config reg in PIU-IOR0 */ - if (!node_online(node)) - val_node = next_node_in(node, node_online_map); - else - val_node = node; + int i, vector, cpu; - virq = irq_alloc_descs_from(NR_IRQS_LEGACY, desc->nvec_used, val_node); - if (virq < 0) { - pr_err("Failed to allocate IRQ(base 16, count %d)\n", desc->nvec_used); - raw_spin_unlock_irqrestore(&vector_lock, flags); - return virq; + if (type != IRQ_ALLOC_TYPE_MSI && type != IRQ_ALLOC_TYPE_MSIX) { + pr_info("SW arch do not identify ID:%d\n", type); + return -ENOMEM; } - irq_data = irq_get_irq_data(virq); + irq_data = irq_domain_get_irq_data(domain, virq); + if (!irq_data) + return -EINVAL; + irq_data->chip = &vt_pci_msi_controller; if (irqd_affinity_is_managed(irq_data)) { mask = irq_data_get_affinity_mask(irq_data); @@ -127,155 +211,158 @@ int chip_setup_vt_msix_irq(struct pci_dev *dev, struct msi_desc *desc) if (cpumask_first(&searchmask) >= nr_cpu_ids) cpumask_copy(&searchmask, cpu_online_mask); - if (!find_free_cpu_vector(&searchmask, &cpu, &vector)) - return -ENOSPC; - - cdata = kzalloc(sizeof(*cdata), GFP_KERNEL); - if (!cdata) - return -ENOMEM; - - per_cpu(vector_irq, cpu)[vector] = virq; - - irq_set_msi_desc(virq, desc); - irq_set_chip_and_handler_name(virq, &vt_pci_msi_controller, - handle_edge_irq, "edge"); - - cdata->dst_cpu = cpu; - cdata->vector = vector; - cdata->rc_index = hose->index; - cdata->rc_node = hose->node; - cdata->prev_cpu = cpu; - cdata->prev_vector = vector; - - irq_data->chip_data = cdata; - - vt_irq_msi_update_msg(irq_data, irq_data->chip_data); - raw_spin_unlock_irqrestore(&vector_lock, flags); - return 0; -} -EXPORT_SYMBOL(chip_setup_vt_msix_irq); - -int chip_setup_vt_msi_irqs(struct pci_dev *dev, int nvec, int type) -{ - struct msi_desc *desc; - struct pci_controller *hose = pci_bus_to_pci_controller(dev->bus); - struct irq_data *irq_data; - struct sw64_msi_chip_data *cdata; - unsigned long node, rc_index; - int virq = -1, val_node = 0; - unsigned long flags; - - const struct cpumask *mask; - struct cpumask searchmask; - int i, vector, cpu; - - if (type == PCI_CAP_ID_MSI && nvec > 32) - return 1; - - node = hose->node; - rc_index = hose->index; - raw_spin_lock_irqsave(&vector_lock, flags); - msi_for_each_desc(desc, &(dev->dev), MSI_DESC_ALL) { - /* Find unused msi config reg in PIU-IOR0 */ - if (!node_online(node)) - val_node = next_node_in(node, node_online_map); - else - val_node = node; - virq = irq_alloc_descs_from(NR_IRQS_LEGACY, desc->nvec_used, val_node); - if (virq < 0) { - pr_err("Failed to allocate IRQ(base 16, count %d)\n", desc->nvec_used); - raw_spin_unlock_irqrestore(&vector_lock, flags); - return virq; - } - - irq_data = irq_get_irq_data(virq); - if (irqd_affinity_is_managed(irq_data)) { - mask = irq_data_get_affinity_mask(irq_data); - cpumask_and(&searchmask, mask, cpu_online_mask); - } else { - node = irq_data_get_node(irq_data); - cpumask_copy(&searchmask, cpumask_of_node(node)); + for (i = 0; i < nr_irqs; i++) { + if (i) { + irq_data = irq_domain_get_irq_data(domain, virq + i); + irq_data->chip = &vt_pci_msi_controller; } - if (cpumask_first(&searchmask) >= nr_cpu_ids) - cpumask_copy(&searchmask, cpu_online_mask); - - for (i = 0; i < desc->nvec_used; i++) { - if (!find_free_cpu_vector(&searchmask, &cpu, &vector)) - return -ENOSPC; - cdata = kzalloc(sizeof(*cdata), GFP_KERNEL); - if (!cdata) - return -ENOMEM; + if (!vt_find_free_cpu_vector(&searchmask, &cpu, &vector, irq_data)) + return -ENOSPC; - per_cpu(vector_irq, cpu)[vector] = virq + i; - irq_set_msi_desc_off(virq, i, desc); - irq_set_chip_and_handler_name(virq + i, &vt_pci_msi_controller, handle_edge_irq, "edge"); - irq_data = irq_get_irq_data(virq + i); + cdata = kzalloc(sizeof(*cdata), GFP_KERNEL); + if (!cdata) + return -ENOMEM; - cdata->dst_cpu = cpu; - cdata->vector = vector; - cdata->rc_index = hose->index; - cdata->rc_node = hose->node; - cdata->prev_cpu = cpu; - cdata->prev_vector = vector; + per_cpu(vector_irq, cpu)[vector] = virq + i; - irq_data->chip_data = cdata; + cdata->dst_cpu = cpu; + cdata->vector = vector; + cdata->prev_cpu = cpu; + cdata->prev_vector = vector; + cdata->move_in_progress = false; - vt_irq_msi_update_msg(irq_data, irq_data->chip_data); - } + irq_data->chip_data = cdata; } - raw_spin_unlock_irqrestore(&vector_lock, flags); return 0; } EXPORT_SYMBOL(chip_setup_vt_msi_irqs); -void vt_sw64_vector_free_irqs(unsigned int virq, unsigned int nr_irqs) +static void sw64_vt_vector_free_irqs(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs) { int i; - unsigned long flags; struct irq_data *irq_data; - struct sw64_msi_chip_data *cdata; + unsigned long flags; for (i = 0; i < nr_irqs; i++) { - irq_data = irq_get_irq_data(virq + i); + irq_data = irq_domain_get_irq_data(domain, virq + i); if (irq_data && irq_data->chip_data) { + struct sw64_msi_chip_data *cdata; + raw_spin_lock_irqsave(&vector_lock, flags); cdata = irq_data->chip_data; - irq_data->hwirq = 0; - irq_data->chip = &no_irq_chip; - irq_data->chip_data = NULL; + irq_domain_reset_irq_data(irq_data); per_cpu(vector_irq, cdata->dst_cpu)[cdata->vector] = 0; kfree(cdata); + raw_spin_unlock_irqrestore(&vector_lock, flags); } } } -int __arch_setup_vt_msix_irqs(struct pci_dev *dev, int nvec, int type) +static int assign_vt_irq_vector(int irq, unsigned int nr_irqs, + struct irq_domain *domain, enum irq_alloc_type type) { - struct msi_desc *entry; - int ret; + int err; + unsigned long flags; - msi_for_each_desc(entry, &dev->dev, MSI_DESC_ALL) { - ret = chip_setup_vt_msix_irq(dev, entry); - if (ret) - return ret; - } + raw_spin_lock_irqsave(&vector_lock, flags); + err = chip_setup_vt_msi_irqs(irq, nr_irqs, domain, type); + raw_spin_unlock_irqrestore(&vector_lock, flags); + return err; +} +static int sw64_vt_vector_alloc_irqs(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs, void *arg) +{ + int err; + struct irq_alloc_info *info = arg; + enum irq_alloc_type msi_type; + + if (arg == NULL) + return -ENODEV; + msi_type = info->type; + err = assign_vt_irq_vector(virq, nr_irqs, domain, msi_type); + if (err) + goto error; return 0; +error: + sw64_vt_vector_free_irqs(domain, virq, nr_irqs); + return err; } -int sw64_setup_vt_msi_irqs(struct pci_dev *dev, int nvec, int type) + +static int vt_pci_msi_prepare(struct irq_domain *domain, struct device *dev, + int nvec, msi_alloc_info_t *arg) { - int ret = 0; + struct pci_dev *pdev = to_pci_dev(dev); + struct msi_desc *desc = msi_first_desc(dev, MSI_DESC_ALL); - if (type == PCI_CAP_ID_MSI) - ret = chip_setup_vt_msi_irqs(dev, nvec, type); - else if (type == PCI_CAP_ID_MSIX) - ret = __arch_setup_vt_msix_irqs(dev, nvec, type); + memset(arg, 0, sizeof(*arg)); + arg->msi_dev = pdev; + if (desc->pci.msi_attrib.is_msix) + arg->type = IRQ_ALLOC_TYPE_MSIX; else - pr_info("SW arch do not identify ID:%d\n", type); + arg->type = IRQ_ALLOC_TYPE_MSI; + return 0; +} + +static struct msi_domain_ops vt_pci_msi_domain_ops = { + .msi_prepare = vt_pci_msi_prepare, +}; + +static struct msi_domain_info pci_vt_msi_domain_info = { + .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | + MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX, + .ops = &vt_pci_msi_domain_ops, + .chip = &vt_pci_msi_controller, + .handler = handle_edge_irq, + .handler_name = "edge", +}; + +static int sw64_vt_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw) +{ + irq_set_chip_and_handler(virq, &sw64_irq_chip, handle_level_irq); + irq_set_status_flags(virq, IRQ_LEVEL); + return 0; +} - return ret; +const struct irq_domain_ops sw64_vt_msi_domain_ops = { + .map = sw64_vt_irq_map, + .alloc = sw64_vt_vector_alloc_irqs, + .free = sw64_vt_vector_free_irqs, +}; + +int sw64_setup_vt_msi_irqs(struct pci_dev *pdev, int nvec, int type) +{ + struct irq_domain *domain; + int err; + + domain = vt_msi_default_domain; + if (domain == NULL) + return -EIO; + err = msi_domain_alloc_irqs_all_locked(&pdev->dev, MSI_DEFAULT_DOMAIN, nvec); + return err; +} + +void sw64_init_vt_msi_domain(struct irq_domain *parent) +{ + struct irq_domain *sw64_irq_domain; + + sw64_irq_domain = irq_domain_add_tree(NULL, &sw64_vt_msi_domain_ops, NULL); + BUG_ON(sw64_irq_domain == NULL); + irq_set_default_host(sw64_irq_domain); + vt_msi_default_domain = pci_msi_create_irq_domain(NULL, + &pci_vt_msi_domain_info, sw64_irq_domain); + if (!vt_msi_default_domain) + pr_warn("failed to initialize irqdomain for MSI/MSI-x.\n"); +} + +int vt_pcibios_device_add(struct pci_dev *dev) +{ + if (vt_msi_default_domain) + dev_set_msi_domain(&dev->dev, vt_msi_default_domain); + return 0; } diff --git a/drivers/irqchip/irq-sunway-msi.c b/drivers/irqchip/irq-sunway-msi.c index e8fdcc5d744b..7f55f675caa1 100644 --- a/drivers/irqchip/irq-sunway-msi.c +++ b/drivers/irqchip/irq-sunway-msi.c @@ -392,6 +392,9 @@ void arch_init_msi_domain(struct irq_domain *parent) { struct irq_domain *sw64_irq_domain; + if (is_guest_or_emul()) + return sw64_init_vt_msi_domain(parent); + sw64_irq_domain = irq_domain_add_tree(NULL, &sw64_msi_domain_ops, NULL); BUG_ON(sw64_irq_domain == NULL); irq_set_default_host(sw64_irq_domain); @@ -403,6 +406,9 @@ void arch_init_msi_domain(struct irq_domain *parent) int pcibios_device_add(struct pci_dev *dev) { + if (is_guest_or_emul()) + return vt_pcibios_device_add(dev); + if (msi_default_domain) dev_set_msi_domain(&dev->dev, msi_default_domain); return 0; -- Gitee From 43b4e4bdb149d36e78c4dd13fcbb5b5f3e346c7b Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Wed, 12 Jun 2024 16:22:43 +0000 Subject: [PATCH 004/100] anolis: sw64: adapt iommu for SW64 from upstream ANBZ: #4688 The interfaces from the upstream have changed. This adapts the modifications from the upstream for sw64 iommu. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/iommu/sw64/Kconfig | 5 +- drivers/iommu/sw64/iommu.c | 410 +++--- .../iommu/sw64/{sunway_iommu.h => iommu.h} | 15 +- drivers/iommu/sw64/iommu_v2.c | 1128 ++++++++--------- include/acpi/actbl1.h | 28 + 5 files changed, 818 insertions(+), 768 deletions(-) rename drivers/iommu/sw64/{sunway_iommu.h => iommu.h} (88%) diff --git a/drivers/iommu/sw64/Kconfig b/drivers/iommu/sw64/Kconfig index 3a6a1e994f31..4cc96bdcd233 100644 --- a/drivers/iommu/sw64/Kconfig +++ b/drivers/iommu/sw64/Kconfig @@ -8,14 +8,15 @@ config SUNWAY_IOMMU depends on SW64 && PCI && SUBARCH_C3B help Support for IOMMU on SW64 platform. It can enable or bypass specific device by - adding boot param "iommu_enable" and "iommu.passthrough". + adding boot param "sunway_iommu" and "iommu.passthrough". # SW64 IOMMU V2 SUPPORT config SUNWAY_IOMMU_V2 bool "Sunway IOMMU V2 Support" select IOMMU_API select IOMMU_IOVA + select IOMMU_DMA depends on SW64 && PCI && SUBARCH_C4 help Support for IOMMU V2 on SW64 platform. It can enable or bypass specific device by - adding boot param "iommu_enable" and "iommu.passthrough". + adding boot param "sunway_iommu" and "iommu.passthrough". diff --git a/drivers/iommu/sw64/iommu.c b/drivers/iommu/sw64/iommu.c index 32b18f726fd9..94b01ca35ecd 100644 --- a/drivers/iommu/sw64/iommu.c +++ b/drivers/iommu/sw64/iommu.c @@ -6,6 +6,7 @@ * in later chips, then it should work just as well. * */ +#define pr_fmt(fmt) "IOMMU: " fmt #include #include @@ -31,22 +32,17 @@ #include #include -#include "sunway_iommu.h" +#include "iommu.h" -#define MAX_DOMAIN_NUM 65536 -#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) -#define SW64_DMA_LIMIT (0xe0000000 - 1) #define SW64_BAR_ADDRESS (IO_BASE | PCI_BASE) -#define SW64_IOMMU_LEVEL1_OFFSET 0x1ff -#define SW64_IOMMU_LEVEL2_OFFSET 0x3ff - #define SW64_IOMMU_GRN_8K ((0UL) << 4) /* page size as 8KB */ #define SW64_IOMMU_GRN_8M ((0x2UL) << 4) /* page size as 8MB */ #define SW64_IOMMU_PGSIZES (((1ULL) << PAGE_SHIFT) | ((1ULL) << PAGE_8M_SHIFT)) -#define IDENTMAP_ALL ((1U) << 0) -#define DMA_MASK64 ((1U) << 1) +#define IDENTMAP_ALL ((1U) << 0) + +#define MAX_NR_IOMMU_PER_NODE 8 /* IOMMU Exceptional Status */ enum exceptype { @@ -62,7 +58,7 @@ enum exceptype { PTE_LEVEL2_VAL, }; -u64 iommu_enable_cmd; /* default IOMMU boot param: 0 */ +DECLARE_BITMAP(iommu_bitmap, 32); unsigned long *sunway_iommu_domain_bitmap; @@ -81,58 +77,104 @@ const struct iommu_ops sunway_iommu_ops; static int iommu_identity_mapping; +static int __last_alias(struct pci_dev *pdev, u16 alias, void *data) +{ + *(u16 *)data = alias; + return 0; +} + +static int get_alias(struct pci_dev *pdev) +{ + u16 pci_alias; + + /* As far as I know, few devices are using more than 2 aliases. */ + pci_for_each_dma_alias(pdev, __last_alias, &pci_alias); + + return pci_alias; +} + /* flush helpers */ -static void piu_flush_all(struct pci_controller *hose) +static void piu_flush_all(struct sunway_iommu *iommu) { - write_piu_ior0(hose->node, hose->index, DTLB_FLUSHALL, 0); - write_piu_ior0(hose->node, hose->index, PTLB_FLUSHALL, 0); - write_piu_ior0(hose->node, hose->index, PCACHE_FLUSHALL, 0); + void __iomem *base; + + base = iommu->reg_base_addr; + if (!base) + return; + + writeq(0, base + DTLB_FLUSHALL); + writeq(0, base + PTLB_FLUSHALL); + writeq(0, base + PCACHE_FLUSHALL); } -void dev_flush_dtlb(struct sunway_iommu_domain *sdomain, - struct sunway_iommu_dev *sdev_data) +static void do_pcache_flush(struct sunway_iommu *iommu, + unsigned long flush_addr) { - struct pci_controller *hose; - int devid; + void __iomem *base; - list_for_each_entry(sdev_data, &sdomain->dev_list, list) { - hose = pci_bus_to_pci_controller(sdev_data->pdev->bus); - devid = sdev_data->devid; + base = iommu->reg_base_addr; + if (!base) + return; - write_piu_ior0(hose->node, hose->index, DTLB_FLUSHDEV, devid); - } + writeq(flush_addr, base + PCACHE_FLUSHPADDR); } void flush_pcache_by_addr(struct sunway_iommu_domain *sdomain, unsigned long flush_addr) { struct pci_controller *hose; + struct sunway_iommu *iommu; struct sunway_iommu_dev *sdev_data; list_for_each_entry(sdev_data, &sdomain->dev_list, list) { hose = pci_bus_to_pci_controller(sdev_data->pdev->bus); + iommu = hose->pci_iommu; flush_addr = __pa(flush_addr); - write_piu_ior0(hose->node, hose->index, - PCACHE_FLUSHPADDR, flush_addr); + do_pcache_flush(iommu, flush_addr); } } +static void do_ptlb_flush(struct sunway_iommu *iommu, + unsigned long flush_addr) +{ + void __iomem *base; + + base = iommu->reg_base_addr; + if (!base) + return; + + writeq(flush_addr, base + PTLB_FLUSHVADDR); +} + void flush_ptlb_by_addr(struct sunway_iommu_domain *sdomain, unsigned long flush_addr) { struct pci_controller *hose; struct pci_dev *pdev; struct sunway_iommu_dev *sdev_data; + struct sunway_iommu *iommu; + unsigned long address; + u16 alias, bus_number, devfn; list_for_each_entry(sdev_data, &sdomain->dev_list, list) { pdev = sdev_data->pdev; hose = pci_bus_to_pci_controller(pdev->bus); + iommu = hose->pci_iommu; - flush_addr = (pdev->bus->number << 8) + address = (pdev->bus->number << 8) | pdev->devfn | (flush_addr << 16); - write_piu_ior0(hose->node, hose->index, - PTLB_FLUSHVADDR, flush_addr); + do_ptlb_flush(iommu, address); + + if (sdev_data->alias != sdev_data->devid) { + alias = sdev_data->alias; + bus_number = PCI_BUS_NUM(alias); + devfn = alias & 0xff; + + address = (bus_number << 8) + | devfn | (flush_addr << 16); + do_ptlb_flush(iommu, address); + } } } @@ -279,18 +321,29 @@ static struct dma_domain *dma_domain_alloc(void) sunway_domain_init(&dma_dom->sdomain); dma_dom->sdomain.type = IOMMU_DOMAIN_DMA; - dma_dom->sdomain.pt_root = (unsigned long *)get_zeroed_page(GFP_KERNEL); - if (dma_dom->sdomain.pt_root == NULL) { - pr_err("Allocating a new sdomain pt_root failed!\n"); - dma_domain_free(dma_dom); - return NULL; - } - add_domain_to_list(&dma_dom->sdomain); return dma_dom; } +static void do_flush_dev(struct pci_controller *hose, u16 devid) +{ + struct sunway_iommu *iommu; + void __iomem *base; + + iommu = hose->pci_iommu; + if (!iommu) + return; + + base = iommu->reg_base_addr; + if (!base) + return; + + writeq(devid, base + DTLB_FLUSHDEV); + writeq(devid, base + PTLB_FLUSHDEV); + writeq(devid, base + PCACHE_FLUSHDEV); +} + static void device_flush_all(struct sunway_iommu_dev *sdata) { struct pci_controller *hose = pci_bus_to_pci_controller(sdata->pdev->bus); @@ -298,51 +351,80 @@ static void device_flush_all(struct sunway_iommu_dev *sdata) if (hose == NULL) return; - write_piu_ior0(hose->node, hose->index, DTLB_FLUSHDEV, sdata->devid); - write_piu_ior0(hose->node, hose->index, PTLB_FLUSHDEV, sdata->devid); - write_piu_ior0(hose->node, hose->index, PCACHE_FLUSHDEV, sdata->devid); + do_flush_dev(hose, sdata->devid); + + if (sdata->devid != sdata->alias) + do_flush_dev(hose, sdata->alias); } /* iommu_ops device attach/unattach helpers */ -static void -set_dte_entry(struct sunway_iommu_dev *sdev, struct sunway_iommu_domain *sdomain) +static int +set_entry_by_devid(u16 devid, + struct sunway_iommu_domain *sdomain, + struct sunway_iommu *iommu) { - struct sunway_iommu *iommu; - struct pci_dev *pdev; - struct page *page; + struct page *dt_page, *pt_page; unsigned long *dte_l1, *dte_l2; unsigned long dte_l1_val, dte_l2_base, dte_l2_val; + u16 bus_number, devfn; + int node; - pdev = sdev->pdev; - if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) - return; + bus_number = PCI_BUS_NUM(devid); + devfn = devid & 0xff; - sdev->devid = PCI_DEVID(pdev->bus->number, pdev->devfn); - iommu = sdev->iommu; - dte_l1 = iommu->iommu_dtbr + (pdev->bus->number); + dte_l1 = iommu->iommu_dtbr + bus_number; dte_l1_val = *dte_l1; + node = node_online(iommu->node) ? iommu->node : NUMA_NO_NODE; if (!dte_l1_val) { /* Alloc a new level-2 device table page */ - page = alloc_pages_node(iommu->node, __GFP_ZERO, + dt_page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, get_order(PAGE_SIZE)); - if (!page) { - pr_err("Allocating a new level-2 device table page failed.\n"); - return; - } + if (!dt_page) + return -ENOMEM; - dte_l2_base = (unsigned long)page_address(page); + dte_l2_base = (unsigned long)page_address(dt_page); dte_l1_val = (__pa(dte_l2_base) & PAGE_MASK) | SW64_IOMMU_ENTRY_VALID; *dte_l1 = dte_l1_val; } - dte_l2 = __va(dte_l1_val & ~(SW64_IOMMU_ENTRY_VALID) & PAGE_MASK) + (pdev->devfn << 3); + if (!sdomain->pt_root) { + pt_page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0); + if (!pt_page) + return -ENOMEM; + + sdomain->pt_root = page_address(pt_page); + } + + dte_l2 = __va(dte_l1_val & ~(SW64_IOMMU_ENTRY_VALID) & PAGE_MASK) + (devfn << 3); dte_l2_val = (__pa(sdomain->pt_root) & PAGE_MASK) | SW64_IOMMU_ENTRY_VALID; - if (iommu_identity_mapping) { + + if (sdomain->type == IOMMU_DOMAIN_IDENTITY) dte_l2_val |= 0x1; - sdev->passthrough = IDENTMAP_ALL; - } + *dte_l2 = dte_l2_val; + pr_debug("iommu: device with id %d added to domain: %d\n", devid, sdomain->id); + + return 0; +} + +static void +set_dte_entry(struct sunway_iommu_dev *sdev, struct sunway_iommu_domain *sdomain) +{ + struct sunway_iommu *iommu; + struct pci_dev *pdev; + + pdev = sdev->pdev; + if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) + return; + + iommu = sdev->iommu; + set_entry_by_devid(sdev->devid, sdomain, iommu); + if (sdev->devid != sdev->alias) + set_entry_by_devid(sdev->alias, sdomain, iommu); + + if (sdomain->type == IOMMU_DOMAIN_IDENTITY) + sdev->passthrough = IDENTMAP_ALL; device_flush_all(sdev); } @@ -356,7 +438,7 @@ do_attach(struct sunway_iommu_dev *sdev_data, struct sunway_iommu_domain *sdomai sdomain->dev_cnt++; set_dte_entry(sdev_data, sdomain); - pr_debug("iommu: device %d add to domain: %d\n", + pr_debug("device %d add to domain: %d\n", sdev_data->devid, sdomain->id); } @@ -460,43 +542,6 @@ static struct sunway_iommu_dev *search_dev_data(u16 devid) * **********************************************************************/ -static struct sunway_iommu *sunway_iommu_early_init(struct pci_controller *hose) -{ - struct sunway_iommu *iommu; - struct page *page; - unsigned long base; - - hose->pci_iommu = kzalloc(sizeof(struct sunway_iommu), GFP_KERNEL); - if (!hose->pci_iommu) - return 0; - - iommu = hose->pci_iommu; - spin_lock_init(&iommu->dt_lock); - - iommu->node = hose->node; - if (!node_online(hose->node)) - iommu->node = -1; - - page = alloc_pages_node(iommu->node, __GFP_ZERO, get_order(PAGE_SIZE)); - if (!page) { - pr_err("Allocating a new iommu_dtbr page failed.\n"); - kfree(hose->pci_iommu); - return NULL; - } - - iommu->iommu_dtbr = page_address(page); - - iommu->hose_pt = hose; - iommu->index = hose->index; - - iommu->enabled = true; - - base = __pa(iommu->iommu_dtbr) & PAGE_MASK; - write_piu_ior0(hose->node, hose->index, DTBASEADDR, base); - - return iommu; -} - unsigned long fetch_dte(struct sunway_iommu *iommu, unsigned long devid, enum exceptype type) { @@ -571,11 +616,13 @@ irqreturn_t iommu_interrupt(int irq, void *dev) struct pci_controller *hose = (struct pci_controller *)dev; struct sunway_iommu_domain *sdomain; struct sunway_iommu_dev *sdev; + struct sunway_iommu *iommu; unsigned long iommu_status; unsigned long type; unsigned long devid, dva; - iommu_status = read_piu_ior0(hose->node, hose->index, IOMMUEXCPT_STATUS); + iommu = hose->pci_iommu; + iommu_status = readq(iommu->reg_base_addr + IOMMUEXCPT_STATUS); if (!(iommu_status >> 63)) return IRQ_NONE; @@ -590,13 +637,13 @@ irqreturn_t iommu_interrupt(int irq, void *dev) pr_info("no such dev!!!\n"); iommu_status &= ~(1UL << 62); - write_piu_ior0(hose->node, hose->index, - IOMMUEXCPT_STATUS, iommu_status); + writeq(iommu_status, iommu->reg_base_addr + IOMMUEXCPT_STATUS); return IRQ_HANDLED; } sdomain = sdev->domain; + switch (type) { case DTE_LEVEL1: pr_info("invalid level1 dte, addr:%#lx, val:%#lx\n", @@ -619,8 +666,7 @@ irqreturn_t iommu_interrupt(int irq, void *dev) fetch_pte(sdomain, dva, PTE_LEVEL2_VAL)); iommu_status &= ~(1UL << 62); - write_piu_ior0(hose->node, hose->index, - IOMMUEXCPT_STATUS, iommu_status); + writeq(iommu_status, iommu->reg_base_addr + IOMMUEXCPT_STATUS); break; case UNAUTHORIZED_ACCESS: @@ -645,6 +691,7 @@ struct irqaction iommu_irqaction = { void sunway_enable_iommu_func(struct pci_controller *hose) { + struct sunway_iommu *iommu; unsigned int iommu_irq, err; unsigned long iommu_conf, iommu_ctrl; @@ -656,28 +703,18 @@ void sunway_enable_iommu_func(struct pci_controller *hose) if (err < 0) pr_info("sw iommu request irq failed!\n"); + iommu = hose->pci_iommu; iommu_ctrl = (1UL << 63) | (0x100UL << 10); - write_piu_ior0(hose->node, hose->index, IOMMUEXCPT_CTRL, iommu_ctrl); - iommu_conf = read_piu_ior0(hose->node, hose->index, PIUCONFIG0); + writeq(iommu_ctrl, iommu->reg_base_addr + IOMMUEXCPT_CTRL); + iommu_conf = readq(iommu->reg_base_addr + PIUCONFIG0); iommu_conf = iommu_conf | (0x3 << 7); - write_piu_ior0(hose->node, hose->index, PIUCONFIG0, iommu_conf); - write_piu_ior0(hose->node, hose->index, TIMEOUT_CONFIG, 0xf); - iommu_conf = read_piu_ior0(hose->node, hose->index, PIUCONFIG0); + writeq(iommu_conf, iommu->reg_base_addr + PIUCONFIG0); + writeq(0xf, iommu->reg_base_addr + TIMEOUT_CONFIG); + iommu_conf = readq(iommu->reg_base_addr + PIUCONFIG0); pr_debug("SW arch configure node %ld hose-%ld iommu_conf = %#lx\n", hose->node, hose->index, iommu_conf); } -static bool is_iommu_enable(struct pci_controller *hose) -{ - u64 rc_mask = 0x1; - - rc_mask <<= (8 * hose->node + hose->index); - if (iommu_enable_cmd & rc_mask) - return true; - - return false; -} - /* iommu cpu syscore ops */ static int iommu_cpu_suspend(void) { @@ -696,12 +733,53 @@ struct syscore_ops iommu_cpu_syscore_ops = { static struct iommu_domain *sunway_iommu_domain_alloc(unsigned int type); +static struct sunway_iommu *sunway_iommu_early_init(struct pci_controller *hose) +{ + struct sunway_iommu *iommu; + struct page *page; + unsigned long base; + int ret = 0, node; + + iommu = kzalloc(sizeof(struct sunway_iommu), GFP_KERNEL); + if (!iommu) { + ret = -ENOMEM; + return 0; + } + + spin_lock_init(&iommu->dt_lock); + + iommu->node = hose->node; + iommu->index = hose->index; + + node = node_online(iommu->node) ? iommu->node : NUMA_NO_NODE; + page = alloc_pages_node(node, __GFP_ZERO, get_order(PAGE_SIZE)); + if (!page) { + ret = -ENOMEM; + goto free_iommu; + } + + iommu->iommu_dtbr = page_address(page); + base = __pa(iommu->iommu_dtbr) & PAGE_MASK; + iommu->reg_base_addr = __va(MK_PIU_IOR0(iommu->node, iommu->index)); + writeq(base, iommu->reg_base_addr + DTBASEADDR); + + hose->pci_iommu = iommu; + iommu->enabled = true; + return iommu; + +free_iommu: + kfree(iommu); + + return ERR_PTR(ret); +} + static int sunway_iommu_init(void) { struct pci_controller *hose; struct sunway_iommu *iommu; - int ret; + unsigned long rc_mask; int iommu_index = 0; + int ret; sunway_iommu_domain_bitmap = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, @@ -712,7 +790,8 @@ static int sunway_iommu_init(void) /* Do the loop */ for (hose = hose_head; hose; hose = hose->next) { - if (!is_iommu_enable(hose)) { + rc_mask = MAX_NR_IOMMU_PER_NODE * hose->node + hose->index; + if (!test_bit(rc_mask, iommu_bitmap)) { hose->iommu_enable = false; continue; } @@ -726,26 +805,24 @@ static int sunway_iommu_init(void) iommu_device_sysfs_add(&iommu->iommu, NULL, NULL, "%d", iommu_index); - iommu_index++; + iommu_device_register(&iommu->iommu, &sunway_iommu_ops, NULL); + sunway_enable_iommu_func(hose); hose->iommu_enable = true; + piu_flush_all(iommu); - iommu_device_register(&iommu->iommu, &sunway_iommu_ops, NULL); + iommu_index++; } ret = iova_cache_get(); if (ret) return ret; - for (hose = hose_head; hose; hose = hose->next) - if (hose->iommu_enable) - piu_flush_all(hose); - register_syscore_ops(&iommu_cpu_syscore_ops); - return 1; + return 0; } -device_initcall(sunway_iommu_init); +subsys_initcall_sync(sunway_iommu_init); /******************************************************************************* * @@ -790,7 +867,7 @@ sunway_iommu_unmap_page(struct sunway_iommu_domain *sunway_domain, int sunway_iommu_map_page(struct sunway_iommu_domain *sunway_domain, unsigned long bus_addr, unsigned long paddr, - size_t page_size) + size_t page_size, int iommu_prot) { /* * pde: page table entry @@ -856,7 +933,12 @@ int sunway_iommu_map_page(struct sunway_iommu_domain *sunway_domain, } pte = (paddr & PAGE_MASK) | SW64_IOMMU_ENTRY_VALID - | SW64_IOMMU_GRN_8K | SW64_IOMMU_ENABLE; + | SW64_IOMMU_GRN_8K; + + pte |= PTE_READE; + if (iommu_prot & IOMMU_WRITE) + pte |= PTE_WRITEE; + *(volatile u64 *)ptebaseaddr = pte; flush_pcache_by_addr(sunway_domain, ptebaseaddr); /* case 8M */ @@ -869,7 +951,11 @@ int sunway_iommu_map_page(struct sunway_iommu_domain *sunway_domain, ptes_one_cache = L1_CACHE_BYTES/sizeof(pte); pte = (paddr & PAGE_MASK) | SW64_IOMMU_ENTRY_VALID - | SW64_IOMMU_GRN_8M | SW64_IOMMU_ENABLE; + | SW64_IOMMU_GRN_8M; + + pte |= PTE_READE; + if (iommu_prot & IOMMU_WRITE) + pte |= PTE_WRITEE; for (i = 0; i < ptes_one_page; i++) { if (*ptr) { @@ -1084,7 +1170,7 @@ sunway_iommu_map_pages(struct iommu_domain *dom, unsigned long iova, mutex_lock(&sdomain->api_lock); while (pgcount--) { - ret = sunway_iommu_map_page(sdomain, iova, paddr, page_size); + ret = sunway_iommu_map_page(sdomain, iova, paddr, page_size, iommu_prot); if (ret) { pr_info("Failed to map page from IOVA %lx.\n", iova); return ret; @@ -1143,6 +1229,9 @@ static int iommu_init_device(struct device *dev) return -ENOMEM; pdev = to_pci_dev(dev); + sdev->devid = PCI_DEVID(pdev->bus->number, pdev->devfn); + sdev->alias = get_alias(pdev); + hose = pci_bus_to_pci_controller(pdev->bus); iommu = hose->pci_iommu; llist_add(&sdev->dev_data_list, &dev_data_list); @@ -1219,10 +1308,9 @@ static struct iommu_device *sunway_iommu_probe_device(struct device *dev) static int sunway_iommu_def_domain_type(struct device *dev) { - if (dev_is_pci(dev)) { + if (dev_is_pci(dev)) if (iommu_identity_mapping) return IOMMU_DOMAIN_IDENTITY; - } return 0; } @@ -1234,8 +1322,13 @@ static bool sunway_iommu_capable(struct device *dev, enum iommu_cap cap) static void sunway_iommu_probe_finalize(struct device *dev) { - set_dma_ops(dev, NULL); - iommu_setup_dma_ops(dev, 0, SW64_DMA_LIMIT); + struct iommu_domain *domain; + + domain = iommu_get_domain_for_dev(dev); + if (domain->type == IOMMU_DOMAIN_DMA) { + iommu_setup_dma_ops(dev, 0, SW64_32BIT_DMA_LIMIT); + } else + set_dma_ops(dev, get_arch_dma_ops()); } const struct iommu_ops sunway_iommu_ops = { @@ -1264,14 +1357,49 @@ const struct iommu_ops sunway_iommu_ops = { * rc0 for cpu node 1. * *****************************************************************************/ +static int __init sunway_iommu_setup(char *str) +{ + unsigned long rc_val; + int ret; + + if (!str) + return -EINVAL; + + bitmap_zero(iommu_bitmap, 64); + + if (!strncmp(str, "on", 2)) { + bitmap_fill(iommu_bitmap, 64); + } else if (!strncmp(str, "off", 3)) { + bitmap_zero(iommu_bitmap, 64); + } else { + ret = kstrtoul(str, 16, &rc_val); + if (!ret) + return -EINVAL; + + bitmap_from_u64(iommu_bitmap, rc_val); + } + + return 1; +} +__setup("sunway_iommu=", sunway_iommu_setup); + static int __init iommu_enable_setup(char *str) { + unsigned long rc_val; int ret; - unsigned long rc_bitmap = 0xffffffffUL; - ret = kstrtoul(str, 16, &rc_bitmap); - iommu_enable_cmd = rc_bitmap; + if (!str) + return -EINVAL; - return ret; + pr_info("iommu_enable= deprecated; use sunway_iommu=on/off instead.\n"); + bitmap_zero(iommu_bitmap, 64); + + ret = kstrtoul(str, 16, &rc_val); + if (!ret) + return -EINVAL; + + bitmap_from_u64(iommu_bitmap, rc_val); + + return 1; } -early_param("iommu_enable", iommu_enable_setup); +__setup("iommu_enable=", iommu_enable_setup); diff --git a/drivers/iommu/sw64/sunway_iommu.h b/drivers/iommu/sw64/iommu.h similarity index 88% rename from drivers/iommu/sw64/sunway_iommu.h rename to drivers/iommu/sw64/iommu.h index 94a155001d1b..f203d19234e7 100644 --- a/drivers/iommu/sw64/sunway_iommu.h +++ b/drivers/iommu/sw64/iommu.h @@ -14,14 +14,16 @@ struct sunway_iommu_bypass_id { }; struct sunway_iommu { - int index; bool enabled; + unsigned long index; + unsigned long node; + void __iomem *reg_base_addr; unsigned long *iommu_dtbr; spinlock_t dt_lock; /* Device Table Lock */ - int node; /* NUMA node */ struct pci_controller *hose_pt; struct iommu_device iommu; /* IOMMU core code handle */ + struct list_head list; }; struct sunway_iommu_dev { @@ -58,6 +60,11 @@ struct sunway_iommu_group { struct iommu_group *group; }; +#define MAX_DOMAIN_NUM 65536 +#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) + +#define SW64_32BIT_DMA_LIMIT (0xe0000000 - 1) + #define SW64_IOMMU_ENTRY_VALID ((1UL) << 63) #define SW64_PTE_LAST_MASK ((1UL) << 8) /*last stage valid*/ #define SW64_DMA_START 0x1000000 @@ -65,8 +72,8 @@ struct sunway_iommu_group { #define PAGE_8M_SHIFT 23 #define PAGE_512M_SHIFT 29 #define PAGE_8G_SHIFT 33 -#define SW64_IOMMU_ENABLE 3 -#define SW64_IOMMU_DISABLE 0 +#define PTE_WRITEE 0x2UL +#define PTE_READE 0x1UL #define SW64_IOMMU_LEVEL1_OFFSET 0x1ff #define SW64_IOMMU_LEVEL2_OFFSET 0x3ff #define SW64_IOMMU_LEVEL3_OFFSET 0x3ff diff --git a/drivers/iommu/sw64/iommu_v2.c b/drivers/iommu/sw64/iommu_v2.c index 4a8b576c2530..b2b68c9836a2 100644 --- a/drivers/iommu/sw64/iommu_v2.c +++ b/drivers/iommu/sw64/iommu_v2.c @@ -1,12 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 /* - * iommu.c: Generic sw64 IOMMU support - * - * This is designed and tested for 3231. If there are no changes in hardware - * in later chips, then it should work just as well. + * iommu.c: Generic sw64 IOMMU v2 support * */ +#define pr_fmt(fmt) "IOMMU: " fmt + #include #include #include @@ -17,48 +16,46 @@ #include #include #include -#include #include -#include #include #include #include #include #include #include -#include +#include #include +#include #include #include -#include "sunway_iommu.h" +#include "iommu.h" -#define MAX_DOMAIN_NUM 65536 -#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) -#define SW64_32BIT_DMA_LIMIT (0xe0000000 - 1) -#define SW64_64BIT_DMA_LIMIT ((1UL << 41) - 1) +#define SW64_64BIT_DMA_LIMIT ((1UL << 42) - 1) #define SW64_BAR_ADDRESS (IO_BASE | PCI_BASE) - -#define SW64_IOMMU_PGSIZES (((1ULL) << PAGE_SHIFT) \ - | ((1ULL) << PAGE_8M_SHIFT) \ - | ((1ULL) << PAGE_512M_SHIFT) \ - | ((1ULL) << PAGE_8G_SHIFT)) +#define IOVA_MAX_ADDRESS_WIDTH 42 #define IDENTMAP_ALL ((1U) << 0) -#define DMA_MASK64 ((1U) << 1) #define PTE_VALID 0x8000000000000000UL #define LAST_STAGE 0x100UL #define PTE_GRN_8M 0x10UL #define PTE_GRN_512M 0x20UL #define PTE_GRN_8G 0x30UL -#define PTE_WRITEE 0x2UL -#define PTE_READE 0x1UL -#define PTE_RWE 0x3UL #define PTE_FLAGS_MASK 0x8000000000000133UL #define PAGE_8G_OFFSET_MASK ((1UL << PAGE_8G_SHIFT) - 1) #define PAGE_512M_OFFSET_MASK ((1UL << PAGE_512M_SHIFT) - 1) #define PAGE_8M_OFFSET_MASK ((1UL << PAGE_8M_SHIFT) - 1) +#define MAX_NR_IOMMU_PER_NODE 16 + +DECLARE_BITMAP(iommu_bitmap, 64); +struct acpi_table_header *dmar_tbl; +#define for_each_iommu(iommu) \ + list_for_each_entry(iommu, &iommu_list, list) + +#define MAX_NR_IOMMU_PER_NODE 16 + +LIST_HEAD(iommu_list); /* IOMMU Exceptional Status */ enum exceptype { @@ -76,8 +73,6 @@ enum exceptype { PTE_LEVEL3_VAL, }; -u64 iommu_enable_cmd; /* default IOMMU boot param: 0 */ - unsigned long *sunway_iommu_domain_bitmap; static DEFINE_SPINLOCK(domain_bitmap_lock); @@ -93,46 +88,104 @@ struct dma_domain { }; const struct iommu_ops sunway_iommu_ops; static const struct dma_map_ops sunway_dma_ops; +static int iommu_identity_mapping; + +static int __last_alias(struct pci_dev *pdev, u16 alias, void *data) +{ + *(u16 *)data = alias; + return 0; +} + +static int get_alias(struct pci_dev *pdev) +{ + u16 pci_alias; + + /* As far as I know, few devices are using more than 2 aliases. */ + pci_for_each_dma_alias(pdev, __last_alias, &pci_alias); + return pci_alias; +} /* flush helpers */ -static void piu_flush_all(struct pci_controller *hose) +static void piu_flush_all(struct sunway_iommu *iommu) +{ + void __iomem *base; + + base = iommu->reg_base_addr; + if (!base) + return; + + writeq(0, base + DTLB_FLUSHALL); + writeq(0, base + PTLB_FLUSHALL); + writeq(0, base + PCACHE_FLUSHALL); +} + +static void do_pcache_flush(struct sunway_iommu *iommu, + unsigned long flush_addr) { - write_piu_ior0(hose->node, hose->index, DTLB_FLUSHALL, 0); - write_piu_ior0(hose->node, hose->index, PTLB_FLUSHALL, 0); - write_piu_ior0(hose->node, hose->index, PCACHE_FLUSHALL, 0); + void __iomem *base; + + base = iommu->reg_base_addr; + if (!base) + return; + + writeq(flush_addr, base + PCACHE_FLUSHPADDR); } void flush_pcache_by_addr(struct sunway_iommu_domain *sdomain, unsigned long flush_addr) { struct pci_controller *hose; struct sunway_iommu_dev *sdev; + struct sunway_iommu *iommu; list_for_each_entry(sdev, &sdomain->dev_list, list) { hose = pci_bus_to_pci_controller(sdev->pdev->bus); + iommu = hose->pci_iommu; flush_addr = __pa(flush_addr); - /* Set memory bar here */ - mb(); - write_piu_ior0(hose->node, hose->index, - PCACHE_FLUSHPADDR, flush_addr); + do_pcache_flush(iommu, flush_addr); } } +static void do_ptlb_flush(struct sunway_iommu *iommu, + unsigned long flush_addr) +{ + void __iomem *base; + + base = iommu->reg_base_addr; + if (!base) + return; + + writeq(flush_addr, base + PTLB_FLUSHVADDR); +} + void flush_ptlb_by_addr(struct sunway_iommu_domain *sdomain, unsigned long flush_addr) { struct pci_controller *hose; struct sunway_iommu_dev *sdev; + struct sunway_iommu *iommu; struct pci_dev *pdev; + unsigned long address; + u16 alias, bus_number, devfn; list_for_each_entry(sdev, &sdomain->dev_list, list) { pdev = sdev->pdev; hose = pci_bus_to_pci_controller(pdev->bus); + iommu = hose->pci_iommu; - flush_addr = (pdev->bus->number << 8) + address = (pdev->bus->number << 8) | pdev->devfn | (flush_addr << 16); - write_piu_ior0(hose->node, hose->index, - PTLB_FLUSHVADDR, flush_addr); + do_ptlb_flush(iommu, address); + + if (sdev->alias != sdev->devid) { + alias = sdev->alias; + bus_number = PCI_BUS_NUM(alias); + devfn = alias & 0xff; + + address = (bus_number << 8) + | devfn | (flush_addr << 16); + do_ptlb_flush(iommu, address); + } } } @@ -288,14 +341,30 @@ static struct dma_domain *dma_domain_alloc(void) sunway_domain_init(&dma_dom->sdomain); dma_dom->sdomain.type = IOMMU_DOMAIN_DMA; - init_iova_domain(&dma_dom->iovad, PAGE_SIZE, IOVA_PFN(SW64_DMA_START)); - reserve_iova(&dma_dom->iovad, (0xe0000000UL >> PAGE_SHIFT), (0x100000000UL >> PAGE_SHIFT)); add_domain_to_list(&dma_dom->sdomain); return dma_dom; } +static void do_flush_dev(struct pci_controller *hose, u16 devid) +{ + struct sunway_iommu *iommu; + void __iomem *base; + + iommu = hose->pci_iommu; + if (!iommu) + return; + + base = iommu->reg_base_addr; + if (!base) + return; + + writeq(devid, base + DTLB_FLUSHDEV); + writeq(devid, base + PTLB_FLUSHDEV); + writeq(devid, base + PCACHE_FLUSHDEV); +} + static void device_flush_all(struct sunway_iommu_dev *sdata) { struct pci_controller *hose = pci_bus_to_pci_controller(sdata->pdev->bus); @@ -303,38 +372,37 @@ static void device_flush_all(struct sunway_iommu_dev *sdata) if (hose == NULL) return; - write_piu_ior0(hose->node, hose->index, DTLB_FLUSHDEV, sdata->devid); - write_piu_ior0(hose->node, hose->index, PTLB_FLUSHDEV, sdata->devid); - write_piu_ior0(hose->node, hose->index, PCACHE_FLUSHDEV, sdata->devid); + do_flush_dev(hose, sdata->devid); + + if (sdata->devid != sdata->alias) + do_flush_dev(hose, sdata->alias); } /* iommu_ops device attach/unattach helpers */ -static void -set_dte_entry(struct sunway_iommu_dev *sdev, struct sunway_iommu_domain *sdomain) +static int +set_entry_by_devid(u16 devid, + struct sunway_iommu_domain *sdomain, + struct sunway_iommu *iommu) { - struct sunway_iommu *iommu; - struct pci_dev *pdev; struct page *dt_page, *pt_page; unsigned long *dte_l1, *dte_l2; unsigned long dte_l1_val, dte_l2_base, dte_l2_val; + u16 bus_number, devfn; + int node; - pdev = sdev->pdev; - if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) - return; + bus_number = PCI_BUS_NUM(devid); + devfn = devid & 0xff; - sdev->devid = PCI_DEVID(pdev->bus->number, pdev->devfn); - iommu = sdev->iommu; - dte_l1 = iommu->iommu_dtbr + (pdev->bus->number); + dte_l1 = iommu->iommu_dtbr + bus_number; dte_l1_val = *dte_l1; if (!dte_l1_val) { + node = node_online(iommu->node) ? iommu->node : NUMA_NO_NODE; /* Alloc a new level-2 device table page */ dt_page = alloc_pages_node(iommu->node, GFP_KERNEL | __GFP_ZERO, get_order(PAGE_SIZE)); - if (!dt_page) { - pr_err("Allocating a new level-2 device table page failed.\n"); - return; - } + if (!dt_page) + return -ENOMEM; dte_l2_base = (unsigned long)page_address(dt_page); dte_l1_val = (__pa(dte_l2_base) & PAGE_MASK) | SW64_IOMMU_ENTRY_VALID; @@ -342,22 +410,42 @@ set_dte_entry(struct sunway_iommu_dev *sdev, struct sunway_iommu_domain *sdomain } if (!sdomain->pt_root) { + node = node_online(iommu->node) ? iommu->node : NUMA_NO_NODE; pt_page = alloc_pages_node(iommu->node, GFP_KERNEL | __GFP_ZERO, 0); - if (!pt_page) { - pr_err("Allocating pt_root failed!\n"); - return; - } + if (!pt_page) + return -ENOMEM; sdomain->pt_root = page_address(pt_page); } - dte_l2 = __va(dte_l1_val & ~(SW64_IOMMU_ENTRY_VALID) & PAGE_MASK) + (pdev->devfn << 3); + dte_l2 = __va(dte_l1_val & ~(SW64_IOMMU_ENTRY_VALID) & PAGE_MASK) + (devfn << 3); dte_l2_val = (__pa(sdomain->pt_root) & PAGE_MASK) | SW64_IOMMU_ENTRY_VALID; - if (sdomain->type == IOMMU_DOMAIN_IDENTITY) { + if (sdomain->type == IOMMU_DOMAIN_IDENTITY) dte_l2_val |= 0x1; - sdev->passthrough = IDENTMAP_ALL; - } + *dte_l2 = dte_l2_val; + pr_debug("iommu: device with id %d added to domain: %d\n", devid, sdomain->id); + + return 0; +} + +static void set_dte_entry(struct sunway_iommu_dev *sdev, struct sunway_iommu_domain *sdomain) +{ + struct sunway_iommu *iommu; + struct pci_dev *pdev; + + pdev = sdev->pdev; + if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) + return; + + iommu = sdev->iommu; + set_entry_by_devid(sdev->devid, sdomain, iommu); + if (sdev->devid != sdev->alias) + set_entry_by_devid(sdev->alias, sdomain, iommu); + + if (sdomain->type == IOMMU_DOMAIN_IDENTITY) + sdev->passthrough = IDENTMAP_ALL; + device_flush_all(sdev); } @@ -468,32 +556,6 @@ static struct sunway_iommu_dev *search_dev_data(u16 devid) return NULL; } -/* dma_ops helpers*/ -static struct sunway_iommu_domain *get_sunway_domain(struct device *dev) -{ - struct sunway_iommu_domain *sdomain; - struct iommu_domain *domain; - struct pci_dev *pdev; - struct sunway_iommu_dev *sdev; - - pdev = to_pci_dev(dev); - if (!pdev) - return ERR_PTR(-ENODEV); - - sdev = dev_iommu_priv_get(dev); - sdomain = sdev->domain; - if (sdomain == NULL) { - domain = iommu_get_domain_for_dev(dev); - sdomain = to_sunway_domain(domain); - attach_device(dev, sdomain); - } - - if (sdomain == NULL) - return ERR_PTR(-EBUSY); - - return sdomain; -} - /********************************************************************** * * Following functions describe IOMMU init ops @@ -505,35 +567,41 @@ static struct sunway_iommu *sunway_iommu_early_init(struct pci_controller *hose) struct sunway_iommu *iommu; struct page *page; unsigned long base; + int ret = 0; + int node; - hose->pci_iommu = kzalloc(sizeof(struct sunway_iommu), GFP_KERNEL); - if (!hose->pci_iommu) - return 0; + iommu = kzalloc(sizeof(struct sunway_iommu), GFP_KERNEL); + if (!iommu) { + ret = -ENOMEM; + goto out; + } - iommu = hose->pci_iommu; spin_lock_init(&iommu->dt_lock); iommu->node = hose->node; - if (!node_online(hose->node)) - iommu->node = -1; + iommu->index = hose->index; - page = alloc_pages_node(iommu->node, __GFP_ZERO, get_order(PAGE_SIZE)); + node = node_online(iommu->node) ? iommu->node : NUMA_NO_NODE; + page = alloc_pages_node(node, __GFP_ZERO, get_order(PAGE_SIZE)); if (!page) { - pr_err("Allocating a new iommu_dtbr page failed.\n"); - kfree(hose->pci_iommu); - return NULL; + ret = -ENOMEM; + goto free_iommu; } - iommu->iommu_dtbr = page_address(page); - iommu->hose_pt = hose; - iommu->index = hose->index; + iommu->iommu_dtbr = page_address(page); + base = __pa(iommu->iommu_dtbr) & PAGE_MASK; + iommu->reg_base_addr = __va(MK_PIU_IOR0(iommu->node, iommu->index)); + writeq(base, iommu->reg_base_addr + DTBASEADDR); + hose->pci_iommu = iommu; iommu->enabled = true; - base = __pa(iommu->iommu_dtbr) & PAGE_MASK; - write_piu_ior0(hose->node, hose->index, DTBASEADDR, base); - return iommu; + +free_iommu: + kfree(iommu); +out: + return ERR_PTR(ret); } unsigned long fetch_dte(struct sunway_iommu *iommu, unsigned long devid, @@ -621,12 +689,14 @@ irqreturn_t iommu_interrupt(int irq, void *dev) { struct pci_controller *hose = (struct pci_controller *)dev; struct sunway_iommu_domain *sdomain; + struct sunway_iommu *iommu; struct sunway_iommu_dev *sdev; unsigned long iommu_status; unsigned long type; unsigned long devid, dva; - iommu_status = read_piu_ior0(hose->node, hose->index, IOMMUEXCPT_STATUS); + iommu = hose->pci_iommu; + iommu_status = readq(iommu->reg_base_addr + IOMMUEXCPT_STATUS); if (!(iommu_status >> 63)) return IRQ_NONE; @@ -641,23 +711,22 @@ irqreturn_t iommu_interrupt(int irq, void *dev) pr_info("no such dev!!!\n"); iommu_status &= ~(1UL << 62); - write_piu_ior0(hose->node, hose->index, - IOMMUEXCPT_STATUS, iommu_status); + writeq(iommu_status, iommu->reg_base_addr + IOMMUEXCPT_STATUS); return IRQ_HANDLED; } - sdomain = sdev->domain; + sdomain = sdev->domain; switch (type) { case DTE_LEVEL1: pr_info("invalid level1 dte, addr:%#lx, val:%#lx\n", - fetch_dte(hose->pci_iommu, devid, DTE_LEVEL1), - fetch_dte(hose->pci_iommu, devid, DTE_LEVEL1_VAL)); + fetch_dte(iommu, devid, DTE_LEVEL1), + fetch_dte(iommu, devid, DTE_LEVEL1_VAL)); break; case DTE_LEVEL2: pr_info("invalid level2 dte, addr:%#lx, val:%#lx\n", - fetch_dte(hose->pci_iommu, devid, DTE_LEVEL2), - fetch_dte(hose->pci_iommu, devid, DTE_LEVEL2_VAL)); + fetch_dte(iommu, devid, DTE_LEVEL2), + fetch_dte(iommu, devid, DTE_LEVEL2_VAL)); break; case PTE_LEVEL1: pr_info("invalid level1 pte, addr: %#lx, val:%#lx\n", @@ -665,8 +734,7 @@ irqreturn_t iommu_interrupt(int irq, void *dev) fetch_pte(sdomain, dva, PTE_LEVEL1_VAL)); iommu_status &= ~(1UL << 62); - write_piu_ior0(hose->node, hose->index, - IOMMUEXCPT_STATUS, iommu_status); + writeq(iommu_status, iommu->reg_base_addr + IOMMUEXCPT_STATUS); break; case PTE_LEVEL2: pr_info("invalid level2 pte, addr: %#lx, val: %#lx\n", @@ -674,8 +742,7 @@ irqreturn_t iommu_interrupt(int irq, void *dev) fetch_pte(sdomain, dva, PTE_LEVEL2_VAL)); iommu_status &= ~(1UL << 62); - write_piu_ior0(hose->node, hose->index, - IOMMUEXCPT_STATUS, iommu_status); + writeq(iommu_status, iommu->reg_base_addr + IOMMUEXCPT_STATUS); break; case PTE_LEVEL3: @@ -684,8 +751,7 @@ irqreturn_t iommu_interrupt(int irq, void *dev) fetch_pte(sdomain, dva, PTE_LEVEL3_VAL)); iommu_status &= ~(1UL << 62); - write_piu_ior0(hose->node, hose->index, - IOMMUEXCPT_STATUS, iommu_status); + writeq(iommu_status, iommu->reg_base_addr + IOMMUEXCPT_STATUS); break; default: pr_info("iommu exception type %ld\n", type); @@ -703,6 +769,7 @@ struct irqaction iommu_irqaction = { void sunway_enable_iommu_func(struct pci_controller *hose) { + struct sunway_iommu *iommu; unsigned int iommu_irq, err; unsigned long iommu_conf, iommu_ctrl; @@ -714,28 +781,18 @@ void sunway_enable_iommu_func(struct pci_controller *hose) if (err < 0) pr_info("sw iommu request irq failed!\n"); + iommu = hose->pci_iommu; iommu_ctrl = (1UL << 63) | (0x100UL << 10); - write_piu_ior0(hose->node, hose->index, IOMMUEXCPT_CTRL, iommu_ctrl); - iommu_conf = read_piu_ior0(hose->node, hose->index, PIUCONFIG0); + writeq(iommu_ctrl, iommu->reg_base_addr + IOMMUEXCPT_CTRL); + iommu_conf = readq(iommu->reg_base_addr + PIUCONFIG0); iommu_conf = iommu_conf | (0x3 << 7); - write_piu_ior0(hose->node, hose->index, PIUCONFIG0, iommu_conf); - write_piu_ior0(hose->node, hose->index, TIMEOUT_CONFIG, 0xf); - iommu_conf = read_piu_ior0(hose->node, hose->index, PIUCONFIG0); + writeq(iommu_conf, iommu->reg_base_addr + PIUCONFIG0); + writeq(0xf, iommu->reg_base_addr + TIMEOUT_CONFIG); + iommu_conf = readq(iommu->reg_base_addr + PIUCONFIG0); pr_debug("SW arch configure node %ld hose-%ld iommu_conf = %#lx\n", hose->node, hose->index, iommu_conf); } -static bool is_iommu_enable(struct pci_controller *hose) -{ - u64 rc_mask = 0x1; - - rc_mask <<= (8 * hose->node + hose->index); - if (iommu_enable_cmd & rc_mask) - return true; - - return false; -} - /* iommu cpu syscore ops */ static int iommu_cpu_suspend(void) { @@ -754,58 +811,239 @@ struct syscore_ops iommu_cpu_syscore_ops = { static struct iommu_domain *sunway_iommu_domain_alloc(unsigned int type); -static int sunway_iommu_init(void) +/* Init functions */ +static int do_detect(void) +{ + acpi_status status = AE_OK; + + status = acpi_get_table(ACPI_SIG_DMAR, 0, &dmar_tbl); + + if (ACPI_SUCCESS(status) && !dmar_tbl) { + pr_warn("No DMAR found!\n"); + status = AE_NOT_FOUND; + } + + return ACPI_SUCCESS(status) ? 0 : -ENOENT; +} + +static struct pci_controller *find_hose_by_rcid(int node, int index) { struct pci_controller *hose; + + for (hose = hose_head; hose; hose = hose->next) + if (hose->node == node && hose->index == index) + return hose; + + return NULL; +} + +static int parse_one_drhd_unit(struct acpi_sw_dmar_header *header) +{ + struct acpi_dmar_sw_hardware_unit *drhd; struct sunway_iommu *iommu; + struct pci_controller *hose; + struct page *page; + unsigned long base; + int cmdline_enabled; + int rc_mask, ret, node; + int rc_node, rc_index; + + drhd = (struct acpi_dmar_sw_hardware_unit *)header; + if (!drhd->enable) + return 0; + + rc_node = (drhd->index >> 8) & 0xff; + rc_index = drhd->index & 0xff; + + hose = find_hose_by_rcid(rc_node, rc_index); + if (!hose) + return 0; + + iommu = kzalloc(sizeof(struct sunway_iommu), GFP_KERNEL); + if (!iommu) + return -ENOMEM; + + iommu->node = rc_node; + iommu->index = rc_index; + iommu->reg_base_addr = ioremap(drhd->address, drhd->size); + + rc_mask = MAX_NR_IOMMU_PER_NODE * iommu->node + iommu->index; + cmdline_enabled = test_bit(rc_mask, iommu_bitmap); + if (!cmdline_enabled) { + iommu->enabled = false; + ret = 0; + goto free_iommu; + } + + node = node_online(iommu->node) ? iommu->node : NUMA_NO_NODE; + page = alloc_pages_node(node, __GFP_ZERO, get_order(PAGE_SIZE)); + if (!page) { + ret = -ENOMEM; + goto free_iommu; + } + + iommu->iommu_dtbr = page_address(page); + base = __pa(iommu->iommu_dtbr) & PAGE_MASK; + writeq(base, iommu->reg_base_addr + DTBASEADDR); + + list_add(&iommu->list, &iommu_list); + iommu->enabled = true; + + hose->pci_iommu = iommu; + + pr_info("iommu: node: %ld index: %ld IOMMU enabled!\n", + iommu->node, iommu->index); + return 0; + +free_iommu: + kfree(iommu); + return ret; +} + +static int parse_drhd_units(struct acpi_table_sw_dmar *dmar) +{ + struct acpi_sw_dmar_header *iter, *start, *next, *end; + size_t len = dmar->header.length - sizeof(*dmar); + int ret, count = 0; + + /* Skip DMAR table, point to first DRHD table. */ + start = (struct acpi_sw_dmar_header *)(dmar + 1); + end = ((void *)start) + len; + + for (iter = start; iter < end; iter = next) { + next = (void *)iter + iter->length; + if (iter->length == 0) { + pr_warn(FW_BUG "Invalid 0-length structure\n"); + break; + } else if (next > end) { + pr_warn(FW_BUG "Record passes table end\n"); + return -EINVAL; + } + + if (iter->type >= ACPI_SW_DMAR_TYPE_RESERVED) { + pr_info("Unknown DMAR structure type %d\n", + iter->type); + } else if (iter->type == 0) { + ret = parse_one_drhd_unit(iter); + if (ret) + return ret; + } + count++; + } + + return 0; +} + +static int sunway_iommu_acpi_early_init(void) +{ int ret; + + struct acpi_table_sw_dmar *dmar; + + ret = do_detect(); + if (ret) + return ret; + + dmar = (struct acpi_table_sw_dmar *)dmar_tbl; + if (!dmar) + return -ENODEV; + + if (dmar->width < 42) { + pr_warn("Invalid DMAR haw\n"); + return -EINVAL; + } + pr_info("Host address width: %d\n", dmar->width); + + ret = parse_drhd_units(dmar); + + return ret; +} + +static int sunway_iommu_acpi_init(void) +{ + struct sunway_iommu *iommu; + struct pci_controller *hose; int iommu_index = 0; + int ret; - sunway_iommu_domain_bitmap = - (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, - get_order(MAX_DOMAIN_NUM / 8)); - if (sunway_iommu_domain_bitmap == NULL) - return 0; - __set_bit(0, sunway_iommu_domain_bitmap); + ret = sunway_iommu_acpi_early_init(); + if (ret) + return ret; + + for_each_iommu(iommu) { + if (!iommu->enabled) + continue; + iommu_device_sysfs_add(&iommu->iommu, NULL, NULL, "%d", + iommu_index); + iommu_device_register(&iommu->iommu, &sunway_iommu_ops, NULL); + iommu_index++; + hose = find_hose_by_rcid(iommu->node, iommu->index); + sunway_enable_iommu_func(hose); + hose->iommu_enable = true; + piu_flush_all(iommu); + } + + ret = iova_cache_get(); + if (ret) + return ret; + + register_syscore_ops(&iommu_cpu_syscore_ops); + + return 0; +} + +static int sunway_iommu_legacy_init(void) +{ + struct pci_controller *hose; + struct sunway_iommu *iommu; + unsigned long rc_mask; + int iommu_index = 0; + int ret; /* Do the loop */ for (hose = hose_head; hose; hose = hose->next) { - if (!is_iommu_enable(hose)) { + rc_mask = MAX_NR_IOMMU_PER_NODE * hose->node + hose->index; + if (!test_bit(rc_mask, iommu_bitmap)) { hose->iommu_enable = false; continue; } iommu = sunway_iommu_early_init(hose); - if (!iommu) { - pr_err("Allocating sunway_iommu failed\n"); - hose->iommu_enable = false; - continue; - } - iommu_device_sysfs_add(&iommu->iommu, NULL, NULL, "%d", iommu_index); - iommu_device_set_ops(&iommu->iommu, &sunway_iommu_ops); - iommu_device_register(&iommu->iommu); + iommu_device_register(&iommu->iommu, &sunway_iommu_ops, NULL); iommu_index++; sunway_enable_iommu_func(hose); hose->iommu_enable = true; + piu_flush_all(iommu); } ret = iova_cache_get(); if (ret) return ret; - ret = bus_set_iommu(&pci_bus_type, &sunway_iommu_ops); - if (ret) - return ret; + register_syscore_ops(&iommu_cpu_syscore_ops); - for (hose = hose_head; hose; hose = hose->next) - if (hose->iommu_enable) - piu_flush_all(hose); + return 0; +} - register_syscore_ops(&iommu_cpu_syscore_ops); +static int sunway_iommu_init(void) +{ + int ret; - return 1; + sunway_iommu_domain_bitmap = + (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, + get_order(MAX_DOMAIN_NUM / 8)); + if (!sunway_iommu_domain_bitmap) + return 0; + __set_bit(0, sunway_iommu_domain_bitmap); + + if (!acpi_disabled) + ret = sunway_iommu_acpi_init(); + else + ret = sunway_iommu_legacy_init(); + + return ret; } subsys_initcall_sync(sunway_iommu_init); @@ -890,7 +1128,7 @@ sunway_iommu_unmap_page(struct sunway_iommu_domain *sunway_domain, int sunway_iommu_map_page(struct sunway_iommu_domain *sunway_domain, unsigned long bus_addr, unsigned long paddr, - size_t page_size) + size_t page_size, int iommu_prot) { struct page *page; struct sunway_iommu *iommu; @@ -930,7 +1168,7 @@ int sunway_iommu_map_page(struct sunway_iommu_domain *sunway_domain, pte = &pte_base[offset]; if (!(*pte) || (current_level == level)) { - pte_val = PTE_VALID | PTE_RWE | grn; + pte_val = PTE_VALID | grn; if (current_level == level) { *(volatile u64 *)(pte) = 0; pte_val |= ((paddr & PAGE_MASK) | LAST_STAGE); @@ -944,6 +1182,10 @@ int sunway_iommu_map_page(struct sunway_iommu_domain *sunway_domain, pte_val |= (page_to_phys(page) & PAGE_MASK); } + pte_val |= PTE_READE; + if (iommu_prot & IOMMU_WRITE) + pte_val |= PTE_WRITEE; + if ((grn == PTE_GRN_512M) && (current_level == 2)) { int i; @@ -967,410 +1209,6 @@ int sunway_iommu_map_page(struct sunway_iommu_domain *sunway_domain, return 0; } -static unsigned long -sunway_alloc_iova(struct dma_domain *dma_dom, unsigned long pages, struct pci_dev *pdev) -{ - struct device *dev; - unsigned long pfn = 0; - - pages = __roundup_pow_of_two(pages); - dev = &(pdev->dev); - if (min(dev->coherent_dma_mask, *dev->dma_mask) == DMA_BIT_MASK(32)) { - pfn = alloc_iova_fast(&dma_dom->iovad, pages, - IOVA_PFN(SW64_32BIT_DMA_LIMIT), true); - } else { - /* IOVA boundary should be 16M ~ 3.5G */ - pfn = alloc_iova_fast(&dma_dom->iovad, pages, - IOVA_PFN(SW64_64BIT_DMA_LIMIT), true); - } - - return (pfn << PAGE_SHIFT); -} - -static void sunway_free_iova(struct dma_domain *dma_dom, - unsigned long address, unsigned long pages) -{ - pages = __roundup_pow_of_two(pages); - address >>= PAGE_SHIFT; - - free_iova_fast(&dma_dom->iovad, address, pages); -} - -static dma_addr_t -__sunway_map_single(struct dma_domain *dma_dom, - struct pci_dev *pdev, phys_addr_t paddr, size_t size) -{ - dma_addr_t ret, address, start; - unsigned long npages, i; - - npages = iommu_num_pages(paddr, size, PAGE_SIZE); - - address = sunway_alloc_iova(dma_dom, npages, pdev); - if (!address) - return 0; - - start = address; - for (i = 0; i < npages; ++i) { - ret = sunway_iommu_map_page(&dma_dom->sdomain, start, - paddr, PAGE_SIZE); - if (ret) { - pr_info("error when map page.\n"); - goto out_unmap; - } - - start += PAGE_SIZE; - paddr += PAGE_SIZE; - } - - address += paddr & ~PAGE_MASK; - return address; - -out_unmap: - for (--i; i >= 0; --i) { - start -= PAGE_SIZE; - sunway_iommu_unmap_page(&dma_dom->sdomain, start, PAGE_SIZE); - } - - sunway_free_iova(dma_dom, address, npages); - return 0; -} - -static dma_addr_t -pci_iommu_map_single(struct pci_dev *pdev, - struct dma_domain *dma_dom, void *cpu_addr, size_t size) -{ - struct pci_controller *hose = pci_bus_to_pci_controller(pdev->bus); - unsigned long paddr; - - if (hose == NULL) { - pr_err("%s: hose does not exist!\n", __func__); - return 0; - } - - paddr = __sunway_map_single(dma_dom, pdev, __pa(cpu_addr), size); - - pr_debug("pci_alloc_consistent: %zx -> [%px,%lx] from %ps\n", - size, cpu_addr, paddr, __builtin_return_address(0)); - - return paddr; -} - -static void *sunway_alloc_coherent(struct device *dev, - size_t size, - dma_addr_t *dma_addr, gfp_t gfp, - unsigned long attrs) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct pci_controller *hose; - struct sunway_iommu_domain *sdomain; - struct dma_domain *dma_dom; - struct sunway_iommu_dev *sdev; - struct page *page; - void *cpu_addr; - - if (!pdev) - return NULL; - - hose = pci_bus_to_pci_controller(pdev->bus); - if (!hose) - return NULL; - - gfp &= ~GFP_DMA; - -try_again: - page = alloc_pages_node(dev_to_node(dev), gfp | __GFP_ZERO, get_order(size)); - if (!page) { - pr_err("Allocating pages failed.\n"); - return NULL; - } - - cpu_addr = page_address(page); - if (!cpu_addr) { - pr_info - ("pci_alloc_consistent: get_free_pages failed from %ps\n", - __builtin_return_address(0)); - - return NULL; - } - - *dma_addr = __pa(cpu_addr); - if (!(hose->iommu_enable)) - return cpu_addr; - - sdev = dev_iommu_priv_get(dev); - if (sdev->passthrough & DMA_MASK64) - return cpu_addr; - else if (sdev->passthrough) { - if (min(dev->coherent_dma_mask, *dev->dma_mask) > DMA_BIT_MASK(32)) { - sdev->passthrough |= DMA_MASK64; - return cpu_addr; - } - - __free_pages(page, get_order(size)); - set_dma_ops(dev, get_arch_dma_ops(dev->bus)); - return dev->dma_ops->alloc(dev, size, dma_addr, gfp, attrs); - } - - sdomain = get_sunway_domain(dev); - dma_dom = to_dma_domain(sdomain); - - *dma_addr = pci_iommu_map_single(pdev, dma_dom, cpu_addr, size); - if (*dma_addr == 0) { - free_pages((unsigned long)cpu_addr, get_order(size)); - if (gfp & GFP_DMA) - return NULL; - - gfp |= GFP_DMA; - goto try_again; - } - - return cpu_addr; -} - -static void -__sunway_unmap_single(struct dma_domain *dma_dom, dma_addr_t dma_addr, size_t size) -{ - dma_addr_t start; - unsigned long npages; - int i; - - npages = iommu_num_pages(dma_addr, size, PAGE_SIZE); - dma_addr &= PAGE_MASK; - start = dma_addr; - - for (i = 0; i < npages; i++) { - sunway_iommu_unmap_page(&dma_dom->sdomain, start, PAGE_SIZE); - start += PAGE_SIZE; - } - - sunway_free_iova(dma_dom, dma_addr, npages); - pr_debug("pci_free_consistent: %zx -> [%llx] from %ps\n", - size, dma_addr, __builtin_return_address(0)); - -} - -static void -sunway_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_addr, unsigned long attrs) -{ - struct sunway_iommu_domain *sdomain; - struct dma_domain *dma_dom; - struct pci_dev *pdev = to_pci_dev(dev); - struct pci_controller *hose; - struct sunway_iommu_dev *sdev; - - if (!pdev) - goto out_unmap; - - hose = pci_bus_to_pci_controller(pdev->bus); - if (!hose || !(hose->iommu_enable)) - goto out_unmap; - - sdev = dev_iommu_priv_get(dev); - if (sdev->passthrough) - goto out_unmap; - - sdomain = get_sunway_domain(dev); - dma_dom = to_dma_domain(sdomain); - __sunway_unmap_single(dma_dom, dma_addr, size); - goto out_free; - -out_unmap: - pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL); - -out_free: - pr_debug("sunway_free_consistent: [%llx,%zx] from %ps\n", - dma_addr, size, __builtin_return_address(0)); - - free_pages((unsigned long)vaddr, get_order(size)); -} - -static dma_addr_t -sunway_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction dir, unsigned long attrs) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct sunway_iommu_domain *sdomain; - struct dma_domain *dma_dom; - struct pci_controller *hose; - struct sunway_iommu_dev *sdev; - phys_addr_t paddr = page_to_phys(page) + offset; - - if (!pdev) - return 0; - - hose = pci_bus_to_pci_controller(pdev->bus); - if (!hose || !(hose->iommu_enable)) - return paddr; - - sdev = dev_iommu_priv_get(dev); - if (sdev->passthrough & DMA_MASK64) - return paddr; - else if (sdev->passthrough) { - if (min(dev->coherent_dma_mask, *dev->dma_mask) > DMA_BIT_MASK(32)) { - sdev->passthrough |= DMA_MASK64; - return paddr; - } - - set_dma_ops(dev, get_arch_dma_ops(dev->bus)); - return dev->dma_ops->map_page(dev, page, offset, size, dir, attrs); - } - - sdomain = get_sunway_domain(dev); - dma_dom = to_dma_domain(sdomain); - - return pci_iommu_map_single(pdev, dma_dom, - (char *)page_address(page) + offset, size); -} - -static void -sunway_unmap_page(struct device *dev, dma_addr_t dma_addr, - size_t size, enum dma_data_direction dir, unsigned long attrs) -{ - struct sunway_iommu_domain *sdomain; - struct dma_domain *dma_dom; - struct pci_dev *pdev; - struct pci_controller *hose; - struct sunway_iommu_dev *sdev; - - pdev = to_pci_dev(dev); - if (!pdev) - return; - - hose = pci_bus_to_pci_controller(pdev->bus); - if (hose == NULL) - return; - - if (!hose->iommu_enable) - return; - - sdev = dev_iommu_priv_get(dev); - if (sdev->passthrough) - return; - - sdomain = get_sunway_domain(dev); - dma_dom = to_dma_domain(sdomain); - __sunway_unmap_single(dma_dom, dma_addr, size); -} - -#define SG_ENT_VIRT_ADDRESS(SG) (sg_virt((SG))) -static int -sunway_map_sg(struct device *dev, struct scatterlist *sgl, - int nents, enum dma_data_direction dir, unsigned long attrs) -{ - struct sunway_iommu_domain *sdomain; - struct dma_domain *dma_dom = NULL; - struct scatterlist *sg; - struct pci_dev *pdev = to_pci_dev(dev); - struct pci_controller *hose; - struct sunway_iommu_dev *sdev; - int i, out_nents = 0; - - if (dir == PCI_DMA_NONE) - BUG(); - - if (!pdev) - return 0; - - hose = pci_bus_to_pci_controller(pdev->bus); - if (!hose) - return 0; - - sdomain = get_sunway_domain(dev); - dma_dom = to_dma_domain(sdomain); - - for_each_sg(sgl, sg, nents, i) { - BUG_ON(!sg_page(sg)); - - sg_dma_address(sg) = __pa(SG_ENT_VIRT_ADDRESS(sg)); - if (!(hose->iommu_enable)) - goto check; - - sdev = dev_iommu_priv_get(dev); - if (sdev->passthrough & DMA_MASK64) - goto check; - else if (sdev->passthrough) { - if (min(dev->coherent_dma_mask, *dev->dma_mask) > DMA_BIT_MASK(32)) { - sdev->passthrough |= DMA_MASK64; - goto check; - } - - set_dma_ops(dev, get_arch_dma_ops(dev->bus)); - return dev->dma_ops->map_sg(dev, sgl, nents, dir, attrs); - } - - sg_dma_address(sg) = - pci_iommu_map_single(pdev, dma_dom, - SG_ENT_VIRT_ADDRESS(sg), sg->length); -check: - if (sg_dma_address(sg) == 0) - goto error; - - sg_dma_len(sg) = sg->length; - out_nents++; - } - - return nents; - -error: - pr_warn("pci_map_sg failed:"); - pr_warn("could not allocate dma page tables\n"); - - if (out_nents) - pci_unmap_sg(pdev, sgl, out_nents, dir); - return 0; -} - -static void -sunway_unmap_sg(struct device *dev, struct scatterlist *sgl, - int nents, enum dma_data_direction dir, unsigned long attrs) -{ - struct sunway_iommu_domain *sdomain; - struct dma_domain *dma_dom; - struct scatterlist *sg; - struct pci_dev *pdev; - struct pci_controller *hose; - struct sunway_iommu_dev *sdev; - dma_addr_t dma_addr; - long size; - int j; - - pdev = to_pci_dev(dev); - if (!pdev) - return; - - hose = pci_bus_to_pci_controller(pdev->bus); - if (!hose->iommu_enable) - return; - - sdev = dev_iommu_priv_get(dev); - if (sdev->passthrough) - return; - - sdomain = get_sunway_domain(dev); - dma_dom = to_dma_domain(sdomain); - - for_each_sg(sgl, sg, nents, j) { - dma_addr = sg->dma_address; - size = sg->dma_length; - if (!size) - break; - - __sunway_unmap_single(dma_dom, dma_addr, size); - } -} - -static const struct dma_map_ops sunway_dma_ops = { - .alloc = sunway_alloc_coherent, - .free = sunway_free_coherent, - .map_sg = sunway_map_sg, - .unmap_sg = sunway_unmap_sg, - .map_page = sunway_map_page, - .unmap_page = sunway_unmap_page, - .dma_supported = dma_direct_supported, -}; - /********************************************************************** * * IOMMU OPS Functions @@ -1499,19 +1337,6 @@ static int sunway_iommu_attach_device(struct iommu_domain *dom, struct device *d return ret; } -static void sunway_iommu_detach_device(struct iommu_domain *dom, struct device *dev) -{ - struct sunway_iommu_dev *sdev; - struct pci_dev *pdev = to_pci_dev(dev); - - if (!pdev) - return; - - sdev = dev_iommu_priv_get(dev); - if (sdev->domain != NULL) - detach_device(dev); -} - static phys_addr_t sunway_iommu_iova_to_phys(struct iommu_domain *dom, dma_addr_t iova) { @@ -1519,7 +1344,7 @@ sunway_iommu_iova_to_phys(struct iommu_domain *dom, dma_addr_t iova) unsigned long paddr, grn; unsigned long is_last; - if (iova > SW64_BAR_ADDRESS) + if (iova >= SW64_BAR_ADDRESS) return iova; paddr = fetch_pte(sdomain, iova, PTE_LEVEL1_VAL); @@ -1574,10 +1399,12 @@ sunway_iommu_iova_to_phys(struct iommu_domain *dom, dma_addr_t iova) } static int -sunway_iommu_map(struct iommu_domain *dom, unsigned long iova, - phys_addr_t paddr, size_t page_size, int iommu_prot, gfp_t gfp) +sunway_iommu_map_pages(struct iommu_domain *dom, unsigned long iova, + phys_addr_t paddr, size_t page_size, size_t pgcount, + int iommu_prot, gfp_t gfp, size_t *mapped) { struct sunway_iommu_domain *sdomain = to_sunway_domain(dom); + size_t size = pgcount << PAGE_SHIFT; int ret; /* @@ -1585,37 +1412,59 @@ sunway_iommu_map(struct iommu_domain *dom, unsigned long iova, * and pci device BAR, check should be introduced manually * to avoid VFIO trying to map pci config space. */ - if (iova > SW64_BAR_ADDRESS) + if (iova >= SW64_BAR_ADDRESS) return 0; - mutex_lock(&sdomain->api_lock); - ret = sunway_iommu_map_page(sdomain, iova, paddr, page_size); - mutex_unlock(&sdomain->api_lock); + if (iova >= (1UL << IOVA_MAX_ADDRESS_WIDTH)) { + pr_err("IOMMU cannot map provided address: %lx\n", iova); + return -EFAULT; + } + + while (pgcount--) { + ret = sunway_iommu_map_page(sdomain, iova, paddr, page_size, iommu_prot); + if (ret) { + pr_info("Failed to map page from IOVA %lx.\n", iova); + return ret; + } + iova += page_size; + paddr += page_size; + } + + if (!ret && mapped) + *mapped = size; return ret; } static size_t -sunway_iommu_unmap(struct iommu_domain *dom, unsigned long iova, - size_t page_size, - struct iommu_iotlb_gather *gather) +sunway_iommu_unmap_pages(struct iommu_domain *dom, unsigned long iova, + size_t page_size, size_t pgcount, + struct iommu_iotlb_gather *gather) { struct sunway_iommu_domain *sdomain = to_sunway_domain(dom); size_t unmap_size; + size_t total_unmap = 0; - if (iova > SW64_BAR_ADDRESS) + if (iova >= SW64_BAR_ADDRESS) return page_size; - mutex_lock(&sdomain->api_lock); - unmap_size = sunway_iommu_unmap_page(sdomain, iova, page_size); - mutex_unlock(&sdomain->api_lock); + if (iova >= (1UL << IOVA_MAX_ADDRESS_WIDTH)) { + pr_err("IOMMU cannot map provided address: %lx\n", iova); + return -EFAULT; + } - return unmap_size; + while (pgcount--) { + unmap_size = sunway_iommu_unmap_page(sdomain, iova, page_size); + iova += page_size; + total_unmap += page_size; + } + + return total_unmap; } static struct iommu_group *sunway_iommu_device_group(struct device *dev) { - return pci_device_group(dev); + return generic_device_group(dev); } static void iommu_uninit_device(struct device *dev) @@ -1663,6 +1512,9 @@ static int iommu_init_device(struct device *dev) return -ENOMEM; pdev = to_pci_dev(dev); + sdev->devid = PCI_DEVID(pdev->bus->number, pdev->devfn); + sdev->alias = get_alias(pdev); + hose = pci_bus_to_pci_controller(pdev->bus); iommu = hose->pci_iommu; llist_add(&sdev->dev_data_list, &dev_data_list); @@ -1714,19 +1566,19 @@ static struct iommu_device *sunway_iommu_probe_device(struct device *dev) static int sunway_iommu_def_domain_type(struct device *dev) { - struct sunway_iommu_dev *sdev; - - sdev = dev_iommu_priv_get(dev); - if (sdev->domain) - return 0; + if (dev_is_pci(dev)) + if (iommu_identity_mapping) + return IOMMU_DOMAIN_IDENTITY; - return sdev->domain->type; + return 0; } -static bool sunway_iommu_capable(enum iommu_cap cap) +static bool sunway_iommu_capable(struct device *dev, enum iommu_cap cap) { switch (cap) { - case IOMMU_CAP_INTR_REMAP: + case IOMMU_CAP_CACHE_COHERENCY: + return true; + case IOMMU_CAP_NOEXEC: return true; default: return false; @@ -1738,43 +1590,77 @@ static void sunway_iommu_probe_finalize(struct device *dev) struct iommu_domain *domain; domain = iommu_get_domain_for_dev(dev); - if (domain) - set_dma_ops(dev, &sunway_dma_ops); + if (domain->type == IOMMU_DOMAIN_DMA) { + if (min(dev->coherent_dma_mask, *dev->dma_mask) == DMA_BIT_MASK(32)) + iommu_setup_dma_ops(dev, SW64_DMA_START, SW64_32BIT_DMA_LIMIT); + else + iommu_setup_dma_ops(dev, SW64_DMA_START, SW64_64BIT_DMA_LIMIT); + } else + set_dma_ops(dev, get_arch_dma_ops()); } const struct iommu_ops sunway_iommu_ops = { .capable = sunway_iommu_capable, .domain_alloc = sunway_iommu_domain_alloc, - .domain_free = sunway_iommu_domain_free, - .attach_dev = sunway_iommu_attach_device, - .detach_dev = sunway_iommu_detach_device, .probe_device = sunway_iommu_probe_device, .probe_finalize = sunway_iommu_probe_finalize, .release_device = sunway_iommu_release_device, - .map = sunway_iommu_map, - .unmap = sunway_iommu_unmap, - .iova_to_phys = sunway_iommu_iova_to_phys, .device_group = sunway_iommu_device_group, - .pgsize_bitmap = SW64_IOMMU_PGSIZES, + .pgsize_bitmap = SZ_8K | SZ_8M | SZ_512M | SZ_8G, .def_domain_type = sunway_iommu_def_domain_type, + .default_domain_ops = &(const struct iommu_domain_ops) { + .attach_dev = sunway_iommu_attach_device, + .map_pages = sunway_iommu_map_pages, + .unmap_pages = sunway_iommu_unmap_pages, + .iova_to_phys = sunway_iommu_iova_to_phys, + .free = sunway_iommu_domain_free, + } }; -/***************************************************************************** - * - * Boot param handle - * Each bit of iommu_enable bitmap represents an rc enable, and every 8 bits - * represents one cpu node. For example, iommu_enable=0x0100 means enabling - * rc0 for cpu node 1. - * - *****************************************************************************/ +/* Handle boot parameters */ +static int __init sunway_iommu_setup(char *str) +{ + unsigned long rc_val; + int ret; + + if (!str) + return -EINVAL; + + bitmap_zero(iommu_bitmap, 64); + + if (!strncmp(str, "on", 2)) { + bitmap_fill(iommu_bitmap, 64); + } else if (!strncmp(str, "off", 3)) { + bitmap_zero(iommu_bitmap, 64); + } else { + ret = kstrtoul(str, 16, &rc_val); + if (!ret) + return -EINVAL; + + bitmap_from_u64(iommu_bitmap, rc_val); + } + + return 1; +} +__setup("sunway_iommu=", sunway_iommu_setup); + static int __init iommu_enable_setup(char *str) { + unsigned long rc_val; int ret; - unsigned long rc_bitmap = 0xffffffffUL; - ret = kstrtoul(str, 16, &rc_bitmap); - iommu_enable_cmd = rc_bitmap; + if (!str) + return -EINVAL; - return ret; + pr_info("iommu_enable= deprecated; use sunway_iommu=on/off instead\n"); + bitmap_zero(iommu_bitmap, 64); + + ret = kstrtoul(str, 16, &rc_val); + if (!ret) + return -EINVAL; + + bitmap_from_u64(iommu_bitmap, rc_val); + + return 1; } __setup("iommu_enable=", iommu_enable_setup); diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 8d5572ad48cb..e490b4c37a48 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -915,6 +915,34 @@ struct acpi_dmar_satc { u8 reserved; u16 segment; }; + +#ifdef CONFIG_SW64 +struct acpi_table_sw_dmar { + struct acpi_table_header header; /* Common ACPI table header*/ + u8 version; /* IOMMU version */ + u8 width; /* Host Address Width */ + u8 flags; +}; + +struct acpi_sw_dmar_header { + u8 type; + u8 length; +}; + +enum acpi_sw_dmar_type { + ACPI_SW_DMAR_TYPE_HARDWARE_UNIT = 0, + ACPI_SW_DMAR_TYPE_RESERVED = 1 +}; + +struct acpi_dmar_sw_hardware_unit { + struct acpi_sw_dmar_header header; + u16 index; + u32 size; + u8 enable; + u64 address; +}; +#endif + /******************************************************************************* * * DRTM - Dynamic Root of Trust for Measurement table -- Gitee From e9942c4ef5a1fb685d78b8e6365f5bcb8c6a1c5f Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 11 Jun 2024 15:32:52 +0800 Subject: [PATCH 005/100] anolis: sw64: adapt IO interfaces for SW64 from upstream ANBZ: #4688 The interfaces from the upstream have changed. This adapts the modifications from the upstream for SW64 IO interfaces. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/io.h | 167 +---------------------------- arch/sw_64/kernel/setup.c | 4 - arch/sw_64/lib/iomap.c | 207 ------------------------------------ 3 files changed, 2 insertions(+), 376 deletions(-) diff --git a/arch/sw_64/include/asm/io.h b/arch/sw_64/include/asm/io.h index 2b045be5257e..daa0defa93c3 100644 --- a/arch/sw_64/include/asm/io.h +++ b/arch/sw_64/include/asm/io.h @@ -9,121 +9,11 @@ #include #include -/* The generic header contains only prototypes. Including it ensures that - * the implementation we have here matches that interface. - */ -#include - -/* We don't use IO slowdowns on the sw64, but.. */ -#define __SLOW_DOWN_IO do { } while (0) -#define SLOW_DOWN_IO do { } while (0) - #define page_to_phys(page) page_to_pa(page) /* Maximum PIO space address supported? */ #define IO_SPACE_LIMIT 0xffffffffffffffff -/* - * Generic IO read/write. These perform native-endian accesses. - */ - -#define __raw_writeb __raw_writeb -static inline void __raw_writeb(u8 val, volatile void __iomem *addr) -{ - asm volatile("stb %0, 0(%1)" : : "r" (val), "r" (addr)); -} - -#define __raw_writew __raw_writew -static inline void __raw_writew(u16 val, volatile void __iomem *addr) -{ - asm volatile("sth %0, 0(%1)" : : "r" (val), "r" (addr)); -} - -#define __raw_writel __raw_writel -static inline void __raw_writel(u32 val, volatile void __iomem *addr) -{ - asm volatile("stw %0, 0(%1)" : : "r" (val), "r" (addr)); -} - -#define __raw_writeq __raw_writeq -static inline void __raw_writeq(u64 val, volatile void __iomem *addr) -{ - asm volatile("stl %0, 0(%1)" : : "r" (val), "r" (addr)); -} - -#define __raw_readb __raw_readb -static inline u8 __raw_readb(const volatile void __iomem *addr) -{ - u8 val; - - asm volatile("ldbu %0, 0(%1)" : "=r" (val) : "r" (addr)); - return val; -} - -#define __raw_readw __raw_readw -static inline u16 __raw_readw(const volatile void __iomem *addr) -{ - u16 val; - - asm volatile("ldhu %0, 0(%1)" : "=r" (val) : "r" (addr)); - return val; -} - -#define __raw_readl __raw_readl -static inline u32 __raw_readl(const volatile void __iomem *addr) -{ - u32 val; - - asm volatile("ldw %0, 0(%1)\n" - "zapnot %0, 0xf, %0\n" - : "=r" (val) : "r" (addr)); - return val; -} - -#define __raw_readq __raw_readq -static inline u64 __raw_readq(const volatile void __iomem *addr) -{ - u64 val; - - asm volatile("ldl %0, 0(%1)" : "=r" (val) : "r" (addr)); - return val; -} - -/* IO barriers */ - -#define __iormb() rmb() -#define __iowmb() wmb() -#define mmiowb() do { } while (0) - -/* - * Relaxed I/O memory access primitives. These follow the Device memory - * ordering rules but do not guarantee any ordering relative to Normal memory - * accesses. - */ -#define readb_relaxed(c) __raw_readb(c) -#define readw_relaxed(c) __raw_readw(c) -#define readl_relaxed(c) __raw_readl(c) -#define readq_relaxed(c) __raw_readq(c) - -#define writeb_relaxed(v, c) __raw_writeb((v), (c)) -#define writew_relaxed(v, c) __raw_writew((v), (c)) -#define writel_relaxed(v, c) __raw_writel((v), (c)) -#define writeq_relaxed(v, c) __raw_writeq((v), (c)) - -/* - * I/O memory access primitives. Reads are ordered relative to any - * following Normal memory access. Writes are ordered relative to any prior - * Normal memory access. - */ -#define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; }) -#define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; }) -#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) -#define readq(c) ({ u64 __v = readq_relaxed(c); __iormb(); __v; }) - -#define writeb(v, c) ({ __iowmb(); writeb_relaxed((v), (c)); }) -#define writew(v, c) ({ __iowmb(); writew_relaxed((v), (c)); }) -#define writel(v, c) ({ __iowmb(); writel_relaxed((v), (c)); }) -#define writeq(v, c) ({ __iowmb(); writeq_relaxed((v), (c)); }) /* * We always have external versions of these routines. */ @@ -154,27 +44,12 @@ static inline void __iomem *__ioremap(phys_addr_t addr, size_t size, #define ioremap_uc ioremap_nocache #define ioport_map ioport_map -#define ioport_unmap ioport_unmap +extern void __iomem *ioport_map(unsigned long port, unsigned int nr); -static inline void __iounmap(volatile void __iomem *addr) +static inline void iounmap(volatile void __iomem *addr) { } -#define iounmap __iounmap - -#define ioread16be(p) be16_to_cpu(ioread16(p)) -#define ioread32be(p) be32_to_cpu(ioread32(p)) -#define iowrite16be(v, p) iowrite16(cpu_to_be16(v), (p)) -#define iowrite32be(v, p) iowrite32(cpu_to_be32(v), (p)) - -#define inb_p inb -#define inw_p inw -#define inl_p inl -#define outb_p outb -#define outw_p outw -#define outl_p outl - - /* * String version of IO memory access ops: */ @@ -214,44 +89,6 @@ extern void outsl(unsigned long port, const void *src, unsigned long count); #define outsw outsw #define outsl outsl -/* - * These defines will override the defaults when doing RTC queries - */ - -#define RTC_PORT(x) (0x70 + (x)) -#define RTC_ALWAYS_BCD 0 - -/* - * Convert a physical pointer to a virtual kernel pointer for /dev/mem - * access - */ -#define xlate_dev_mem_ptr(p) __va(p) - -/* - * Convert a virtual cached pointer to an uncached pointer - */ -#define xlate_dev_kmem_ptr(p) p - -/* - * These get provided from since sw64 does not - * select GENERIC_IOMAP. - */ -#define ioread8 ioread8 -#define ioread16 ioread16 -#define ioread32 ioread32 -#define ioread64 ioread64 -#define iowrite8 iowrite8 -#define iowrite16 iowrite16 -#define iowrite32 iowrite32 -#define iowrite64 iowrite64 -#define ioread64be ioread64be -#define iowrite64be iowrite64be -#define ioread8_rep ioread8_rep -#define ioread16_rep ioread16_rep -#define ioread32_rep ioread32_rep -#define iowrite8_rep iowrite8_rep -#define iowrite16_rep iowrite16_rep -#define iowrite32_rep iowrite32_rep #define pci_iounmap pci_iounmap #include diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 411810dbf10d..ee0b7850e820 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -180,10 +180,6 @@ reserve_std_resources(void) } } - /* Fix up for the Jensen's queer RTC placement. */ - standard_io_resources[0].start = RTC_PORT(0); - standard_io_resources[0].end = RTC_PORT(0) + 0x10; - for (i = 0; i < ARRAY_SIZE(standard_io_resources); ++i) request_resource(io, standard_io_resources+i); } diff --git a/arch/sw_64/lib/iomap.c b/arch/sw_64/lib/iomap.c index d9c66a89131e..f89cf16f683c 100644 --- a/arch/sw_64/lib/iomap.c +++ b/arch/sw_64/lib/iomap.c @@ -11,42 +11,6 @@ /* * Here comes the sw64 implementation of the IOMAP interfaces. */ -unsigned int ioread8(const void __iomem *addr) -{ - return readb(addr); -} -EXPORT_SYMBOL(ioread8); - -unsigned int ioread16(const void __iomem *addr) -{ - return readw(addr); -} -EXPORT_SYMBOL(ioread16); - -unsigned int ioread32(const void __iomem *addr) -{ - return readl(addr); -} -EXPORT_SYMBOL(ioread32); - -void iowrite8(u8 b, void __iomem *addr) -{ - writeb(b, addr); -} -EXPORT_SYMBOL(iowrite8); - -void iowrite16(u16 b, void __iomem *addr) -{ - writew(b, addr); -} -EXPORT_SYMBOL(iowrite16); - -void iowrite32(u32 b, void __iomem *addr) -{ - writel(b, addr); -} -EXPORT_SYMBOL(iowrite32); - u8 inb(unsigned long port) { return ioread8(ioport_map(port, 1)); @@ -83,202 +47,36 @@ void outl(u32 b, unsigned long port) } EXPORT_SYMBOL(outl); - -/* - * Read COUNT 8-bit bytes from port PORT into memory starting at SRC. - */ -void ioread8_rep(const void __iomem *port, void *dst, unsigned long count) -{ - while ((unsigned long)dst & 0x3) { - if (!count) - return; - count--; - *(unsigned char *)dst = ioread8(port); - dst += 1; - } - - while (count >= 4) { - unsigned int w; - - count -= 4; - w = ioread8(port); - w |= ioread8(port) << 8; - w |= ioread8(port) << 16; - w |= ioread8(port) << 24; - *(unsigned int *)dst = w; - dst += 4; - } - - while (count) { - --count; - *(unsigned char *)dst = ioread8(port); - dst += 1; - } -} -EXPORT_SYMBOL(ioread8_rep); - void insb(unsigned long port, void *dst, unsigned long count) { ioread8_rep(ioport_map(port, 1), dst, count); } EXPORT_SYMBOL(insb); -/* - * Read COUNT 16-bit words from port PORT into memory starting at - * SRC. SRC must be at least short aligned. This is used by the - * IDE driver to read disk sectors. Performance is important, but - * the interfaces seems to be slow: just using the inlined version - * of the inw() breaks things. - */ -void ioread16_rep(const void __iomem *port, void *dst, unsigned long count) -{ - if (unlikely((unsigned long)dst & 0x3)) { - if (!count) - return; - BUG_ON((unsigned long)dst & 0x1); - count--; - *(unsigned short *)dst = ioread16(port); - dst += 2; - } - - while (count >= 2) { - unsigned int w; - - count -= 2; - w = ioread16(port); - w |= ioread16(port) << 16; - *(unsigned int *)dst = w; - dst += 4; - } - - if (count) - *(unsigned short *)dst = ioread16(port); -} -EXPORT_SYMBOL(ioread16_rep); - void insw(unsigned long port, void *dst, unsigned long count) { ioread16_rep(ioport_map(port, 2), dst, count); } EXPORT_SYMBOL(insw); - -/* - * Read COUNT 32-bit words from port PORT into memory starting at - * SRC. Now works with any alignment in SRC. Performance is important, - * but the interfaces seems to be slow: just using the inlined version - * of the inl() breaks things. - */ -void ioread32_rep(const void __iomem *port, void *dst, unsigned long count) -{ - if (unlikely((unsigned long)dst & 0x3)) { - while (count--) { - struct S { int x __packed; }; - ((struct S *)dst)->x = ioread32(port); - dst += 4; - } - } else { - /* Buffer 32-bit aligned. */ - while (count--) { - *(unsigned int *)dst = ioread32(port); - dst += 4; - } - } -} -EXPORT_SYMBOL(ioread32_rep); - void insl(unsigned long port, void *dst, unsigned long count) { ioread32_rep(ioport_map(port, 4), dst, count); } EXPORT_SYMBOL(insl); - -/* - * Like insb but in the opposite direction. - * Don't worry as much about doing aligned memory transfers: - * doing byte reads the "slow" way isn't nearly as slow as - * doing byte writes the slow way (no r-m-w cycle). - */ -void iowrite8_rep(void __iomem *port, const void *xsrc, unsigned long count) -{ - const unsigned char *src = xsrc; - - while (count--) - iowrite8(*src++, port); -} -EXPORT_SYMBOL(iowrite8_rep); - void outsb(unsigned long port, const void *src, unsigned long count) { iowrite8_rep(ioport_map(port, 1), src, count); } EXPORT_SYMBOL(outsb); - -/* - * Like insw but in the opposite direction. This is used by the IDE - * driver to write disk sectors. Performance is important, but the - * interfaces seems to be slow: just using the inlined version of the - * outw() breaks things. - */ -void iowrite16_rep(void __iomem *port, const void *src, unsigned long count) -{ - if (unlikely((unsigned long)src & 0x3)) { - if (!count) - return; - BUG_ON((unsigned long)src & 0x1); - iowrite16(*(unsigned short *)src, port); - src += 2; - --count; - } - - while (count >= 2) { - unsigned int w; - - count -= 2; - w = *(unsigned int *)src; - src += 4; - iowrite16(w >> 0, port); - iowrite16(w >> 16, port); - } - - if (count) - iowrite16(*(unsigned short *)src, port); -} -EXPORT_SYMBOL(iowrite16_rep); - void outsw(unsigned long port, const void *src, unsigned long count) { iowrite16_rep(ioport_map(port, 2), src, count); } EXPORT_SYMBOL(outsw); - -/* - * Like insl but in the opposite direction. This is used by the IDE - * driver to write disk sectors. Works with any alignment in SRC. - * Performance is important, but the interfaces seems to be slow: - * just using the inlined version of the outl() breaks things. - */ -void iowrite32_rep(void __iomem *port, const void *src, unsigned long count) -{ - if (unlikely((unsigned long)src & 0x3)) { - while (count--) { - struct S { int x __packed; }; - iowrite32(((struct S *)src)->x, port); - src += 4; - } - } else { - /* Buffer 32-bit aligned. */ - while (count--) { - iowrite32(*(unsigned int *)src, port); - src += 4; - } - } -} -EXPORT_SYMBOL(iowrite32_rep); - void outsl(unsigned long port, const void *src, unsigned long count) { iowrite32_rep(ioport_map(port, 4), src, count); @@ -470,8 +268,3 @@ void __iomem *ioport_map(unsigned long port, unsigned int size) return __va(port); } EXPORT_SYMBOL(ioport_map); - -void ioport_unmap(void __iomem *addr) -{ -} -EXPORT_SYMBOL(ioport_unmap); -- Gitee From 942858b82eef564a80f5f83b38d320262797102e Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Thu, 20 Jun 2024 16:38:08 +0000 Subject: [PATCH 006/100] anolis: sw64: fix MSI compilation warnings ANBZ: #4688 Use a encapsulated function in MSI to resolve compilation warnings. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/irqchip/irq-sunway-msi-v2.c | 2 +- drivers/irqchip/irq-sunway-msi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/irq-sunway-msi-v2.c b/drivers/irqchip/irq-sunway-msi-v2.c index 4e98a4c10f85..01ac9f468b49 100644 --- a/drivers/irqchip/irq-sunway-msi-v2.c +++ b/drivers/irqchip/irq-sunway-msi-v2.c @@ -189,7 +189,7 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask, irq_msi_compose_msg(d, &msg); __pci_write_msi_msg(entry, &msg); spin_unlock(&cdata->cdata_lock); - cpumask_copy(irq_data_get_affinity_mask(irqd), &searchmask); + irq_data_update_effective_affinity(irqd, &searchmask); raw_spin_unlock_irqrestore(&vector_lock, flags); diff --git a/drivers/irqchip/irq-sunway-msi.c b/drivers/irqchip/irq-sunway-msi.c index 7f55f675caa1..299d98f4128a 100644 --- a/drivers/irqchip/irq-sunway-msi.c +++ b/drivers/irqchip/irq-sunway-msi.c @@ -158,7 +158,7 @@ static int sw64_set_affinity(struct irq_data *d, const struct cpumask *cpumask, msi_config = set_piu_msi_config(hose, cpu, cdata->msi_config_index, vector); cdata->msi_config = msi_config; spin_unlock(&cdata->cdata_lock); - cpumask_copy((struct cpumask *)irq_data_get_affinity_mask(irqd), &searchmask); + irq_data_update_effective_affinity(irqd, &searchmask); raw_spin_unlock_irqrestore(&vector_lock, flags); -- Gitee From e337ec46f744fdcf17dac7e267c3a50dea5d307e Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Mon, 24 Jun 2024 10:23:32 +0000 Subject: [PATCH 007/100] anolis: sw64: fix pci resource assignment bug ANBZ: #4688 This commit fixes two errors in pci resource assignment: -It includes RC in the resource calculation -It allows RC to participate in the resource assignment process Signed-off-by: Zheng Chongzhen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/pci/pci.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/sw_64/pci/pci.c b/arch/sw_64/pci/pci.c index 073781645f32..6eac8f5b9d8e 100644 --- a/arch/sw_64/pci/pci.c +++ b/arch/sw_64/pci/pci.c @@ -119,7 +119,7 @@ void pcibios_fixup_bus(struct pci_bus *bus) struct pci_controller *hose = pci_bus_to_pci_controller(bus); struct pci_dev *dev = bus->self; - if (!dev || bus->number == hose->first_busno) { + if (!dev) { bus->resource[0] = hose->io_space; bus->resource[1] = hose->mem_space; bus->resource[2] = hose->pre_mem_space; @@ -209,11 +209,6 @@ static void fixup_root_complex(struct pci_dev *dev) dev->class &= 0xff; dev->class |= PCI_CLASS_BRIDGE_PCI << 8; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - dev->resource[i].start = 0; - dev->resource[i].end = 0; - dev->resource[i].flags = IORESOURCE_PCI_FIXED; - } } atomic_inc(&dev->enable_cnt); -- Gitee From 6694a80b77b9793bb23ec87bf9b76d4077191fc6 Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Wed, 26 Jun 2024 14:15:07 +0000 Subject: [PATCH 008/100] anolis: sw64: amdgpu/radeon: correct low-level mmio memset/memcpy direct calls ANBZ: #4688 Driver codes of the direct calls, via the SIMD-optimized memset and memcpy functions, may raise default when using RX580/R7 under sw64 architecture, so work around 'memset' references to 'memset_io' and 'memcpy' to 'memcpy_fromio/toio'. Signed-off-by: Zheng Chongzhen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 8 ++++++++ drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 29 +++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 29 +++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_vce.c | 4 ++++ drivers/gpu/drm/radeon/vce_v1_0.c | 5 +++++ 5 files changed, 75 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index c2faf6b4c2fc..893d349aae07 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -2749,7 +2749,11 @@ static int gfx_v7_0_mec_init(struct amdgpu_device *adev) } /* clear memory. Not sure if this is required or not */ +#if IS_ENABLED(CONFIG_SW64) + memset_io(hpd, 0, mec_hpd_size); +#else memset(hpd, 0, mec_hpd_size); +#endif amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); @@ -2858,7 +2862,11 @@ static void gfx_v7_0_mqd_init(struct amdgpu_device *adev, u64 wb_gpu_addr; /* init the mqd struct */ +#if IS_ENABLED(CONFIG_SW64) + memset_io(mqd, 0, sizeof(struct cik_mqd)); +#else memset(mqd, 0, sizeof(struct cik_mqd)); +#endif mqd->header = 0xC0310800; mqd->compute_static_thread_mgmt_se0 = 0xffffffff; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 1943beb135c4..1471eeffd428 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -1322,7 +1322,11 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev) return r; } +#if IS_ENABLED(CONFIG_SW64) + memset_io(hpd, 0, mec_hpd_size); +#else memset(hpd, 0, mec_hpd_size); +#endif amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); @@ -4602,7 +4606,11 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring) if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.kiq[0].mqd_backup) +#if IS_ENABLED(CONFIG_SW64) + memcpy_toio(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(struct vi_mqd_allocation)); +#else memcpy(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(struct vi_mqd_allocation)); +#endif /* reset ring buffer */ ring->wptr = 0; @@ -4613,7 +4621,11 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring) vi_srbm_select(adev, 0, 0, 0, 0); mutex_unlock(&adev->srbm_mutex); } else { +#if IS_ENABLED(CONFIG_SW64) + memset_io((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); +#else memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); +#endif ((struct vi_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct vi_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; if (amdgpu_sriov_vf(adev) && adev->in_suspend) @@ -4626,7 +4638,11 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); if (adev->gfx.kiq[0].mqd_backup) +#if IS_ENABLED(CONFIG_SW64) + memcpy_fromio(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(struct vi_mqd_allocation)); +#else memcpy(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(struct vi_mqd_allocation)); +#endif } return 0; @@ -4639,7 +4655,11 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring) int mqd_idx = ring - &adev->gfx.compute_ring[0]; if (!amdgpu_in_reset(adev) && !adev->in_suspend) { +#if IS_ENABLED(CONFIG_SW64) + memset_io((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); +#else memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); +#endif ((struct vi_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct vi_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; mutex_lock(&adev->srbm_mutex); @@ -4649,11 +4669,20 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); if (adev->gfx.mec.mqd_backup[mqd_idx]) +#if IS_ENABLED(CONFIG_SW64) + memcpy_fromio(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct vi_mqd_allocation)); +#else memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct vi_mqd_allocation)); +#endif } else { /* restore MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) +#if IS_ENABLED(CONFIG_SW64) + memcpy_toio(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); +#else memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); +#endif + /* reset ring buffer */ ring->wptr = 0; amdgpu_ring_clear_ring(ring); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 895060f6948f..676c576b72cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -1711,7 +1711,11 @@ static int gfx_v9_0_mec_init(struct amdgpu_device *adev) return r; } +#if IS_ENABLED(CONFIG_SW64) + memset_io(hpd, 0, mec_hpd_size); +#else memset(hpd, 0, mec_hpd_size); +#endif amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); @@ -3547,7 +3551,11 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring) if (amdgpu_in_reset(adev) && tmp_mqd->cp_hqd_pq_control){ /* for GPU_RESET case , reset MQD to a clean status */ if (adev->gfx.kiq[0].mqd_backup) +#if IS_ENABLED(CONFIG_SW64) + memcpy_toio(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(struct v9_mqd_allocation)); +#else memcpy(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(struct v9_mqd_allocation)); +#endif /* reset ring buffer */ ring->wptr = 0; @@ -3559,7 +3567,11 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring) soc15_grbm_select(adev, 0, 0, 0, 0, 0); mutex_unlock(&adev->srbm_mutex); } else { +#if IS_ENABLED(CONFIG_SW64) + memset_io((void *)mqd, 0, sizeof(struct v9_mqd_allocation)); +#else memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation)); +#endif ((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; if (amdgpu_sriov_vf(adev) && adev->in_suspend) @@ -3572,7 +3584,11 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); if (adev->gfx.kiq[0].mqd_backup) +#if IS_ENABLED(CONFIG_SW64) + memcpy_fromio(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(struct v9_mqd_allocation)); +#else memcpy(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(struct v9_mqd_allocation)); +#endif } return 0; @@ -3592,7 +3608,11 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) if (!tmp_mqd->cp_hqd_pq_control || (!amdgpu_in_reset(adev) && !adev->in_suspend)) { +#if IS_ENABLED(CONFIG_SW64) + memset_io((void *)mqd, 0, sizeof(struct v9_mqd_allocation)); +#else memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation)); +#endif ((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; mutex_lock(&adev->srbm_mutex); @@ -3602,11 +3622,20 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); if (adev->gfx.mec.mqd_backup[mqd_idx]) +#if IS_ENABLED(CONFIG_SW64) + memcpy_fromio(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct v9_mqd_allocation)); +#else memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct v9_mqd_allocation)); +#endif } else { /* restore MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) +#if IS_ENABLED(CONFIG_SW64) + memcpy_toio(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation)); +#else memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation)); +#endif + /* reset ring buffer */ ring->wptr = 0; atomic64_set((atomic64_t *)ring->wptr_cpu_addr, 0); diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c index d1871af967d4..1c77d655e7ee 100644 --- a/drivers/gpu/drm/radeon/radeon_vce.c +++ b/drivers/gpu/drm/radeon/radeon_vce.c @@ -238,7 +238,11 @@ int radeon_vce_resume(struct radeon_device *rdev) return r; } +#ifdef __sw_64__ + memset_io(cpu_addr, 0, radeon_bo_size(rdev->vce.vcpu_bo)); +#else memset(cpu_addr, 0, radeon_bo_size(rdev->vce.vcpu_bo)); +#endif if (rdev->family < CHIP_BONAIRE) r = vce_v1_0_load_fw(rdev, cpu_addr); else diff --git a/drivers/gpu/drm/radeon/vce_v1_0.c b/drivers/gpu/drm/radeon/vce_v1_0.c index bdfbcf14b864..faab1addef26 100644 --- a/drivers/gpu/drm/radeon/vce_v1_0.c +++ b/drivers/gpu/drm/radeon/vce_v1_0.c @@ -193,8 +193,13 @@ int vce_v1_0_load_fw(struct radeon_device *rdev, uint32_t *data) data[3] = sign->val[i].nonce[3]; data[4] = cpu_to_le32(le32_to_cpu(sign->len) + 64); +#if IS_ENABLED(CONFIG_SW64) + memset_io(&data[5], 0, 44); + memcpy_toio(&data[16], &sign[1], rdev->vce_fw->size - sizeof(*sign)); +#else memset(&data[5], 0, 44); memcpy(&data[16], &sign[1], rdev->vce_fw->size - sizeof(*sign)); +#endif data += (le32_to_cpu(sign->len) + 64) / 4; data[0] = sign->val[i].sigval[0]; -- Gitee From 2e56443f6115bb92de890940e5954eeef5ba0c87 Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Wed, 3 Jul 2024 14:28:36 +0000 Subject: [PATCH 009/100] anolis: sw64: fix io resource remapping ANBZ: #4688 During the pci scan, the assigned IORESOURCE_IO addresses are not the expected address range. This is because asm-generic/io.h defines PCI_IOBASE, which results in the function acpi_pci_root_remap_iospace() doing remapping. To resolve this issue, the definition of PCI_IOBASE is removed. Signed-off-by: Zheng Chongzhen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/io.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sw_64/include/asm/io.h b/arch/sw_64/include/asm/io.h index daa0defa93c3..15abf97e9d57 100644 --- a/arch/sw_64/include/asm/io.h +++ b/arch/sw_64/include/asm/io.h @@ -92,6 +92,7 @@ extern void outsl(unsigned long port, const void *src, unsigned long count); #define pci_iounmap pci_iounmap #include +#undef PCI_IOBASE /* * Change addresses as seen by the kernel (virtual) to addresses as -- Gitee From ae6b7e62c39c8becd49505340690ae05aee6be97 Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Tue, 25 Jun 2024 09:42:03 +0000 Subject: [PATCH 010/100] anolis: sw64: fix some S3 CSRs problems for C4 ANBZ: #4688 This patch: - Restore CSR:KTP after wake-up. - Enable longtime to make CSR:SHTCLOCK continue to count after wake-up. Signed-off-by: Zheng Chongzhen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/uncore_io_ops_junzhang.h | 7 ++++++- arch/sw_64/kernel/chip_setup.c | 3 +++ arch/sw_64/kernel/suspend_asm.S | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/include/asm/uncore_io_ops_junzhang.h b/arch/sw_64/include/asm/uncore_io_ops_junzhang.h index 95a3b5c80531..00f9898f8540 100644 --- a/arch/sw_64/include/asm/uncore_io_ops_junzhang.h +++ b/arch/sw_64/include/asm/uncore_io_ops_junzhang.h @@ -28,7 +28,12 @@ static inline unsigned long __get_node_mem(int node) #define __io_read_longtime(node) (0UL) #define __io_write_longtime(node, data) do { } while (0) -#define __io_write_longtime_start_en(node, data) do { } while (0) + +static inline void +__io_write_longtime_start_en(int node, unsigned long data) +{ + sw64_io_write(node, GPIO_SWPORTA_DDR, data); +} static inline void __io_write_fault_int_en(int node, unsigned long data) diff --git a/arch/sw_64/kernel/chip_setup.c b/arch/sw_64/kernel/chip_setup.c index c6374ae18138..e6784968323d 100644 --- a/arch/sw_64/kernel/chip_setup.c +++ b/arch/sw_64/kernel/chip_setup.c @@ -193,6 +193,9 @@ static inline void intpu_restore(void) __io_write_longtime(0, saved_long_time); __io_write_longtime_start_en(0, 0x1); break; + case CPU_SW8A: + __io_write_longtime_start_en(0, 0x1); + break; default: pr_info("long time start is disable!"); break; diff --git a/arch/sw_64/kernel/suspend_asm.S b/arch/sw_64/kernel/suspend_asm.S index 34ee349515a7..c245e657503a 100644 --- a/arch/sw_64/kernel/suspend_asm.S +++ b/arch/sw_64/kernel/suspend_asm.S @@ -3,6 +3,7 @@ #include #include #include +#include .text .set noat @@ -56,6 +57,9 @@ $subloop: ldl $8, PSTATE_KTP($18) +#ifdef CONFIG_SUBARCH_C4 + csrw $8, CSR_KTP +#endif ldi $1, PSTATE_REGS($18) ldl $9, CALLEE_R9($1) ldl $10, CALLEE_R10($1) -- Gitee From fa2bb4297f30991a86c7045441a48eb3ebbf30c9 Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Tue, 25 Jun 2024 09:44:54 +0000 Subject: [PATCH 011/100] anolis: sw64: fix a base address of msiaddr register ANBZ: #4688 Fix base address of msiaddr register to make S3 work. Fixes: 43d035704fa6 ("anolis: sw64: pci: use readq/writeq to read/write RC and PIU IO registers") Signed-off-by: Zheng Chongzhen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/chip_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/kernel/chip_setup.c b/arch/sw_64/kernel/chip_setup.c index e6784968323d..f6e92adab5e6 100644 --- a/arch/sw_64/kernel/chip_setup.c +++ b/arch/sw_64/kernel/chip_setup.c @@ -92,7 +92,7 @@ static void pcie_save(void) piu_save->piuconfig0 = readq(piu_ior0_base + PIUCONFIG0); piu_save->piuconfig1 = readq(piu_ior1_base + PIUCONFIG1); piu_save->epdmabar = readq(piu_ior0_base + EPDMABAR); - piu_save->msiaddr = readq(piu_ior1_base + MSIADDR); + piu_save->msiaddr = readq(piu_ior0_base + MSIADDR); if (IS_ENABLED(CONFIG_UNCORE_XUELANG)) { for (i = 0; i < 256; i++) { -- Gitee From 6da7a0c989575464d6f9c220cb551ef97d450584 Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Wed, 3 Jul 2024 15:31:50 +0000 Subject: [PATCH 012/100] anolis: sw64: fix a compilation warning ANBZ: #4688 Signed-off-by: Zheng Chongzhen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/pci/pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/sw_64/pci/pci.c b/arch/sw_64/pci/pci.c index 6eac8f5b9d8e..fbbd54dd181c 100644 --- a/arch/sw_64/pci/pci.c +++ b/arch/sw_64/pci/pci.c @@ -194,7 +194,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, */ static void fixup_root_complex(struct pci_dev *dev) { - int i; struct pci_bus *bus = dev->bus; struct pci_controller *hose = pci_bus_to_pci_controller(bus); -- Gitee From 5511c5ec8004af24a7370b5fabe68385638af1dd Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Mon, 17 Jun 2024 17:13:09 +0000 Subject: [PATCH 013/100] anolis: sw64: handle null MSI irq ANBZ: #4688 Add a check after getting irq number from CPU vector_irq table. Otherwise, kernel will hang after getting a null irq. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/irqchip/irq-sunway-msi-v2.c | 5 +++++ drivers/irqchip/irq-sunway-msi-vt.c | 3 +++ drivers/irqchip/irq-sunway-msi.c | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/drivers/irqchip/irq-sunway-msi-v2.c b/drivers/irqchip/irq-sunway-msi-v2.c index 01ac9f468b49..553ccd0afa07 100644 --- a/drivers/irqchip/irq-sunway-msi-v2.c +++ b/drivers/irqchip/irq-sunway-msi-v2.c @@ -501,6 +501,11 @@ void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned } irq = per_cpu(vector_irq, cpu)[vector_index + msi_index]; + if (unlikely(!irq)) { + vector = vector & (~(1UL << msi_index)); + continue; + } + irq_data = irq_domain_get_irq_data(msi_default_domain->parent, irq); cdata = irq_data_get_irq_chip_data(irq_data); spin_lock(&cdata->cdata_lock); diff --git a/drivers/irqchip/irq-sunway-msi-vt.c b/drivers/irqchip/irq-sunway-msi-vt.c index a28f23799117..ac2e78757b51 100644 --- a/drivers/irqchip/irq-sunway-msi-vt.c +++ b/drivers/irqchip/irq-sunway-msi-vt.c @@ -32,6 +32,9 @@ void vt_handle_pci_msi_interrupt(unsigned long type, unsigned long vector, cpu = smp_processor_id(); irq = per_cpu(vector_irq, cpu)[vector]; + if (unlikely(!irq)) + return; + irq_data = irq_domain_get_irq_data(vt_msi_default_domain->parent, irq); cdata = irq_data_get_irq_chip_data(irq_data); diff --git a/drivers/irqchip/irq-sunway-msi.c b/drivers/irqchip/irq-sunway-msi.c index 299d98f4128a..ba96eab6a3de 100644 --- a/drivers/irqchip/irq-sunway-msi.c +++ b/drivers/irqchip/irq-sunway-msi.c @@ -453,6 +453,11 @@ void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned } irq = per_cpu(vector_irq, cpu)[vector_index + msi_index]; + if (unlikely(!irq)) { + vector = vector & (~(1UL << msi_index)); + continue; + } + irq_data = irq_domain_get_irq_data(msi_default_domain->parent, irq); cdata = irq_data_get_irq_chip_data(irq_data); spin_lock(&cdata->cdata_lock); -- Gitee From 095c5ddb24491593e5a87974a0286145fb336097 Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Wed, 19 Jun 2024 19:25:12 +0000 Subject: [PATCH 014/100] anolis: sw64: seperate IRQ_MSI configs for sub-architectures ANBZ: #4688 Current kernel configuration has two different MSI handling codes specific to sub-architectures controlled by one single config, which is confusing and unclear. To better organize and clarify the MSI config logic, this patch introduces two IRQ_MSI configs, each dependent on the respective SUBARCH, to differentiate the two MSI handling process. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 3 +-- drivers/irqchip/Kconfig | 9 +++++++-- drivers/irqchip/Makefile | 7 +------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 59c400211394..1861622fd184 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -121,8 +121,7 @@ config SW64 select SET_FS select SPARSEMEM_EXTREME if SPARSEMEM select SW64_IRQ_CPU - select SW64_IRQ_MSI if PCI_MSI - select SW64_IRQ_MSI_VT if PCI_MSI + select SW64_PCI_INTX if PCI select SW64_TIMER select SWIOTLB select THREAD_INFO_IN_TASK diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 21aeae9af675..6be0af85a0b5 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -44,12 +44,17 @@ config SW64_PCI_INTX config SW64_IRQ_MSI bool - depends on SW64 && PCI_MSI + depends on SW64 && PCI_MSI && SUBARCH_C3B + default y + +config SW64_IRQ_MSI_V2 + bool + depends on SW64 && PCI_MSI && SUBARCH_C4 default y config SW64_IRQ_MSI_VT bool - depends on SW64_IRQ_MSI + depends on SW64_IRQ_MSI || SW64_IRQ_MSI_V2 default y config ARM_GIC_PM diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index cd085dde0d35..f4697c1a39c0 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -31,13 +31,8 @@ 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) obj-$(CONFIG_SW64_IRQ_MSI) += irq-sunway-msi.o -else -obj-$(CONFIG_SW64_IRQ_MSI) += irq-sunway-msi-v2.o -endif - +obj-$(CONFIG_SW64_IRQ_MSI_V2) += irq-sunway-msi-v2.o obj-$(CONFIG_SW64_IRQ_MSI_VT) += irq-sunway-msi-vt.o obj-$(CONFIG_ARM_GIC_PM) += irq-gic-pm.o obj-$(CONFIG_ARCH_REALVIEW) += irq-gic-realview.o -- Gitee From f4522e64956d37c5ba2ef229bbc403d0cd020f74 Mon Sep 17 00:00:00 2001 From: Gao Chen Date: Fri, 24 May 2024 17:06:14 +0800 Subject: [PATCH 015/100] anolis: sw64: optimize the code in do_entInt() ANBZ: #4688 Modify the location of the following function: - set_irq_regs() - irq_enter() - irq_exit() These modifications make the do_entInt() more readable. They do not affect the original program logic. Signed-off-by: Gao Chen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/irq.c | 2 - arch/sw_64/kernel/smp.c | 2 - drivers/clocksource/timer-sw64.c | 3 -- drivers/irqchip/irq-sunway-cpu.c | 63 +++++++++++++++----------------- 4 files changed, 30 insertions(+), 40 deletions(-) diff --git a/arch/sw_64/kernel/irq.c b/arch/sw_64/kernel/irq.c index bdc92b40c4c0..6f367a2db319 100644 --- a/arch/sw_64/kernel/irq.c +++ b/arch/sw_64/kernel/irq.c @@ -98,9 +98,7 @@ handle_irq(int irq) return; } - irq_enter(); generic_handle_irq_desc(desc); - irq_exit(); } #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 03118ebc56ee..5cd30e1a7477 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -555,9 +555,7 @@ void handle_ipi(struct pt_regs *regs) break; case IPI_CALL_FUNC: - irq_enter(); generic_smp_call_function_interrupt(); - irq_exit(); break; case IPI_CPU_STOP: diff --git a/drivers/clocksource/timer-sw64.c b/drivers/clocksource/timer-sw64.c index c70cf340a4b9..c7233617283f 100644 --- a/drivers/clocksource/timer-sw64.c +++ b/drivers/clocksource/timer-sw64.c @@ -418,7 +418,6 @@ void sw64_timer_interrupt(void) { struct clock_event_device *evt = this_cpu_ptr(&timer_events); - irq_enter(); if (!evt->event_handler) { pr_warn("Spurious local timer interrupt on cpu %d\n", smp_processor_id()); @@ -429,6 +428,4 @@ void sw64_timer_interrupt(void) inc_irq_stat(timer_irqs_event); evt->event_handler(evt); - - irq_exit(); } diff --git a/drivers/irqchip/irq-sunway-cpu.c b/drivers/irqchip/irq-sunway-cpu.c index 109bf4acedde..31f170e0a5aa 100644 --- a/drivers/irqchip/irq-sunway-cpu.c +++ b/drivers/irqchip/irq-sunway-cpu.c @@ -181,16 +181,21 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, struct pt_regs *old_regs; extern char __idle_start[], __idle_end[]; + /* restart idle routine if it is interrupted */ + if (regs->pc > (u64)__idle_start && regs->pc < (u64)__idle_end) + regs->pc = (u64)__idle_start; + + irq_enter(); + old_regs = set_irq_regs(regs); + #ifdef CONFIG_SUBARCH_C4 if (pme_state == PME_WFW) { pme_state = PME_PENDING; - return; + goto out; } 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 @@ -205,74 +210,66 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, } } - /* restart idle routine if it is interrupted */ - if (regs->pc > (u64)__idle_start && regs->pc < (u64)__idle_end) - regs->pc = (u64)__idle_start; - switch (type & 0xffff) { case INT_MSI: - old_regs = set_irq_regs(regs); if (is_guest_or_emul()) vt_handle_pci_msi_interrupt(type, vector, irq_arg); else handle_pci_msi_interrupt(type, vector, irq_arg); - set_irq_regs(old_regs); - return; + goto out; case INT_INTx: - old_regs = set_irq_regs(regs); handle_device_interrupt(vector); - set_irq_regs(old_regs); - return; + goto out; case INT_IPI: #ifdef CONFIG_SMP handle_ipi(regs); - return; + goto out; #else irq_err_count++; pr_crit("Interprocessor interrupt? You must be kidding!\n"); -#endif break; +#endif case INT_RTC: - old_regs = set_irq_regs(regs); sw64_timer_interrupt(); - set_irq_regs(old_regs); - return; + goto out; case INT_VT_SERIAL: case INT_VT_HOTPLUG: case INT_VT_GPIOA_PIN0: - old_regs = set_irq_regs(regs); handle_irq(type); - set_irq_regs(old_regs); - return; + goto out; +#if defined(CONFIG_SUBARCH_C3B) case INT_PC0: perf_irq(PMC_PC0, regs); - return; + goto out; case INT_PC1: perf_irq(PMC_PC1, regs); - return; + goto out; +#elif defined(CONFIG_SUBARCH_C4) + case INT_PC: + perf_irq(PMC_PC0, regs); + goto out; +#endif case INT_DEV: handle_dev_int(regs); - return; + goto out; case INT_FAULT: - old_regs = set_irq_regs(regs); handle_fault_int(); - set_irq_regs(old_regs); - return; + goto out; case INT_MT: - old_regs = set_irq_regs(regs); handle_mt_int(); - set_irq_regs(old_regs); - return; + goto out; case INT_NMI: - old_regs = set_irq_regs(regs); handle_nmi_int(); - set_irq_regs(old_regs); - return; + goto out; default: pr_crit("Hardware intr %ld %lx? uh?\n", type, vector); } pr_crit("PC = %016lx PS = %04lx\n", regs->pc, regs->ps); + +out: + set_irq_regs(old_regs); + irq_exit(); } EXPORT_SYMBOL(do_entInt); -- Gitee From 4874d2c4047e725497ecae2ff5bad8f572bf3e10 Mon Sep 17 00:00:00 2001 From: Gao Chen Date: Fri, 24 May 2024 17:07:21 +0800 Subject: [PATCH 016/100] anolis: sw64: add CSR_CAUSE into pt_regs ANBZ: #4688 Add a soft_csr called CSR_CAUSE into pt_regs to record the cause of trap. It can be used to unify the trap entries and identify the nmi to be added in the future. Signed-off-by: Gao Chen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/csr.h | 1 + arch/sw_64/include/asm/ptrace.h | 1 + arch/sw_64/kernel/asm-offsets.c | 1 + arch/sw_64/kernel/entry_c4.S | 2 ++ 4 files changed, 5 insertions(+) diff --git a/arch/sw_64/include/asm/csr.h b/arch/sw_64/include/asm/csr.h index cdb9249eedd2..917894152e36 100644 --- a/arch/sw_64/include/asm/csr.h +++ b/arch/sw_64/include/asm/csr.h @@ -59,6 +59,7 @@ #define CSR_SCRATCH 0xed #define CSR_SP 0xee #define CSR_KTP 0xef +#define CSR_CAUSE 0xf0 #define DA_MATCH_EN_S 4 #define DV_MATCH_EN_S 6 diff --git a/arch/sw_64/include/asm/ptrace.h b/arch/sw_64/include/asm/ptrace.h index 44c9e2d1fe6a..0bbe85297f62 100644 --- a/arch/sw_64/include/asm/ptrace.h +++ b/arch/sw_64/include/asm/ptrace.h @@ -27,6 +27,7 @@ struct pt_regs { }; unsigned long orig_r0; unsigned long orig_r19; + unsigned long cause; /* These are saved by HMcode: */ unsigned long hm_ps; unsigned long hm_pc; diff --git a/arch/sw_64/kernel/asm-offsets.c b/arch/sw_64/kernel/asm-offsets.c index 334f7f2e9550..337386c163ff 100644 --- a/arch/sw_64/kernel/asm-offsets.c +++ b/arch/sw_64/kernel/asm-offsets.c @@ -104,6 +104,7 @@ void foo(void) DEFINE(PT_REGS_PS, offsetof(struct pt_regs, ps)); DEFINE(PT_REGS_ORIG_R0, offsetof(struct pt_regs, orig_r0)); DEFINE(PT_REGS_ORIG_R19, offsetof(struct pt_regs, orig_r19)); + DEFINE(PT_REGS_CAUSE, offsetof(struct pt_regs, cause)); 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)); diff --git a/arch/sw_64/kernel/entry_c4.S b/arch/sw_64/kernel/entry_c4.S index c31143645b6f..08760f2f9f73 100644 --- a/arch/sw_64/kernel/entry_c4.S +++ b/arch/sw_64/kernel/entry_c4.S @@ -66,6 +66,7 @@ csrr $1, CSR_SP csrr $2, CSR_PS csrr $3, CSR_PC + csrr $4, CSR_CAUSE csrr $16, CSR_EARG0 csrr $17, CSR_EARG1 csrr $18, CSR_EARG2 @@ -76,6 +77,7 @@ stl $1, PT_REGS_SP($sp) stl $2, PT_REGS_PS($sp) stl $3, PT_REGS_PC($sp) + stl $4, PT_REGS_CAUSE($sp) ldi $1, NO_SYSCALL stl $1, PT_REGS_ORIG_R0($sp) csrr $8, CSR_KTP -- Gitee From af7bb4027be5239ebe4e427471a9e1d96ce75092 Mon Sep 17 00:00:00 2001 From: Gao Chen Date: Fri, 24 May 2024 17:08:08 +0800 Subject: [PATCH 017/100] anolis: sw64: add NMI support ANBZ: #4688 Support the Non-Maskable Interrupt(NMI). Any type of interrupt can be configured to be non-maskable. NMI has its separate stack, also has a separate SAVE_ALL_NMI and RESTORE_ALL_NMI. Signed-off-by: Gao Chen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/core.h | 1 + arch/sw_64/include/asm/csr.h | 6 +- arch/sw_64/include/asm/hmcall.h | 4 + arch/sw_64/kernel/entry_c4.S | 139 +++++++++++++++++++++++++++++++ arch/sw_64/kernel/irq.c | 10 +++ arch/sw_64/kernel/smp.c | 14 ++++ arch/sw_64/kernel/traps.c | 19 +++++ arch/sw_64/kvm/entry_core4.S | 2 + drivers/irqchip/irq-sunway-cpu.c | 11 ++- 9 files changed, 202 insertions(+), 4 deletions(-) diff --git a/arch/sw_64/include/asm/core.h b/arch/sw_64/include/asm/core.h index 2b6748cec93d..9ce1d6b7418e 100644 --- a/arch/sw_64/include/asm/core.h +++ b/arch/sw_64/include/asm/core.h @@ -78,6 +78,7 @@ static inline bool core_is_ht(void) extern void entArith(void); extern void entIF(void); extern void entInt(void); +extern void entNMI(void); extern void entMM(void); extern void entSys(void); extern void entUna(void); diff --git a/arch/sw_64/include/asm/csr.h b/arch/sw_64/include/asm/csr.h index 917894152e36..9101e4c91fe1 100644 --- a/arch/sw_64/include/asm/csr.h +++ b/arch/sw_64/include/asm/csr.h @@ -51,6 +51,9 @@ #define CSR_IDA_MATCH 0xc5 #define CSR_IDA_MASK 0xc6 #define CSR_BASE_KREGS 0xe0 +#define CSR_NMI_STACK 0xe5 +#define CSR_NMI_SCRATCH 0xe6 +#define CSR_NMI_MASK 0xe7 #define CSR_PS 0xe8 #define CSR_PC 0xe9 #define CSR_EARG0 0xea @@ -79,7 +82,8 @@ static inline unsigned long sw64_read_csr(unsigned long x) { unsigned long __val; - __asm__ __volatile__("csrr %0,%1" : "=r"(__val) : "i"(x)); + + __asm__ __volatile__("csrr %0,%1; csrr %0,%1" : "=r"(__val) : "i"(x)); return __val; } diff --git a/arch/sw_64/include/asm/hmcall.h b/arch/sw_64/include/asm/hmcall.h index c9509327a229..fd873e825ae1 100644 --- a/arch/sw_64/include/asm/hmcall.h +++ b/arch/sw_64/include/asm/hmcall.h @@ -44,6 +44,9 @@ #define HMC_sendii 0x3E #define HMC_rti 0x3F +/* 0x40 - 0x7F : Hypervisor Level HMC routine */ +#define HMC_rti_nmi 0x40 +#define HMC_setup_nmi 0x41 /* 0x80 - 0xBF : User Level HMC routine */ #include @@ -185,6 +188,7 @@ __CALL_HMC_RW1(rdio64, unsigned long, unsigned long); __CALL_HMC_RW1(rdio32, unsigned int, unsigned long); __CALL_HMC_W2(wrent, void*, unsigned long); __CALL_HMC_W2(tbisasid, unsigned long, unsigned long); +__CALL_HMC_W2(setup_nmi, unsigned long, unsigned long); __CALL_HMC_W1(wrkgp, unsigned long); __CALL_HMC_RW2(wrperfmon, unsigned long, unsigned long, unsigned long); __CALL_HMC_RW3(sendii, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/arch/sw_64/kernel/entry_c4.S b/arch/sw_64/kernel/entry_c4.S index 08760f2f9f73..219016ef05b2 100644 --- a/arch/sw_64/kernel/entry_c4.S +++ b/arch/sw_64/kernel/entry_c4.S @@ -14,6 +14,123 @@ .text .set noat + .macro SAVE_ALL_NMI + csrw $sp, CSR_NMI_SCRATCH + csrr $sp, CSR_NMI_STACK + + 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) + + /* 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_NMI_SCRATCH + csrr $1, CSR_NMI_SCRATCH + csrr $2, CSR_PS + csrr $3, CSR_PC + csrr $4, CSR_CAUSE + 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) + stl $4, PT_REGS_CAUSE($sp) + 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 + br $27, 1f +1: ldgp $29, 0($27) + call $26, save_nmi_ctx + ldl $16, (PT_REGS_EARG0 + STACKFRAME_SIZE)($sp) + ldl $17, (PT_REGS_EARG1 + STACKFRAME_SIZE)($sp) + ldl $18, (PT_REGS_EARG2 + STACKFRAME_SIZE)($sp) + .endm + + .macro RESTORE_ALL_NMI + call $26, restore_nmi_ctx + + ldi $sp, STACKFRAME_SIZE($sp) + + ldl $1, PT_REGS_PS($sp) + ldl $2, PT_REGS_PC($sp) + csrw $1, CSR_PS + csrw $2, CSR_PC + + 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 SAVE_ALL csrw $sp, CSR_SP csrw $1, CSR_SCRATCH @@ -146,6 +263,18 @@ * Non-syscall kernel entry points. */ + .align 4 + .globl entNMI + .ent entNMI +entNMI: + SAVE_ALL_NMI + br $27, 1f +1: ldgp $29, 0($27) + ldi $19, STACKFRAME_SIZE($sp) + call $26, do_entInt + br ret_from_nmi + .end entNMI + .align 4 .globl entInt .ent entInt @@ -260,6 +389,16 @@ entSys: br ret_from_sys_call .end entSys + .align 4 + .globl ret_from_nmi + .ent ret_from_nmi +ret_from_nmi: + br $27, 1f +1: ldgp $29, 0($27) + RESTORE_ALL_NMI + sys_call HMC_rti_nmi + .end ret_from_nmi + .align 4 .globl ret_from_sys_call .ent ret_from_sys_call diff --git a/arch/sw_64/kernel/irq.c b/arch/sw_64/kernel/irq.c index 6f367a2db319..8066dcf91424 100644 --- a/arch/sw_64/kernel/irq.c +++ b/arch/sw_64/kernel/irq.c @@ -114,7 +114,17 @@ void __init init_IRQ(void) * Just in case the platform init_irq() causes interrupts/mchecks * (as is the case with RAWHIDE, at least). */ + struct page __maybe_unused *nmi_stack_page = alloc_pages_node( + cpu_to_node(smp_processor_id()), + THREADINFO_GFP, THREAD_SIZE_ORDER); + unsigned long nmi_stack __maybe_unused = nmi_stack_page ? + (unsigned long)page_address(nmi_stack_page) : 0; + wrent(entInt, 0); + if (IS_ENABLED(CONFIG_SUBARCH_C4) && is_in_host()) { + sw64_write_csr_imb(nmi_stack + THREAD_SIZE, CSR_NMI_STACK); + wrent(entNMI, 6); + } sw64_init_irq(); irqchip_init(); diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 5cd30e1a7477..ffa858e837a5 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -100,6 +100,9 @@ static void downshift_freq(void) { } void smp_callin(void) { int cpuid; + struct page __maybe_unused *nmi_stack_page; + unsigned long __maybe_unused nmi_stack; + save_ktp(); upshift_freq(); cpuid = smp_processor_id(); @@ -127,6 +130,17 @@ void smp_callin(void) /* update csr:ptbr */ update_ptbr_sys(virt_to_phys(init_mm.pgd)); + if (IS_ENABLED(CONFIG_SUBARCH_C4) && is_in_host()) { + nmi_stack_page = alloc_pages_node( + cpu_to_node(smp_processor_id()), + THREADINFO_GFP, + THREAD_SIZE_ORDER); + nmi_stack = nmi_stack_page ? + (unsigned long)page_address(nmi_stack_page) : 0; + sw64_write_csr_imb(nmi_stack + THREAD_SIZE, CSR_NMI_STACK); + wrent(entNMI, 6); + } + /* inform the notifiers about the new cpu */ notify_cpu_starting(cpuid); diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index c9e956b01dc9..e54db9a41be6 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -2006,6 +2006,25 @@ asmlinkage void do_entSys(struct pt_regs *regs) syscall_trace_leave(); } +struct nmi_ctx { + unsigned long csr_sp; + unsigned long csr_scratch; +}; + +DEFINE_PER_CPU(struct nmi_ctx, nmi_context); + +void save_nmi_ctx(void) +{ + this_cpu_write(nmi_context.csr_sp, sw64_read_csr(CSR_SP)); + this_cpu_write(nmi_context.csr_scratch, sw64_read_csr(CSR_SCRATCH)); +} + +void restore_nmi_ctx(void) +{ + sw64_write_csr_imb(this_cpu_read(nmi_context.csr_sp), CSR_SP); + sw64_write_csr_imb(this_cpu_read(nmi_context.csr_scratch), CSR_SCRATCH); +} + void trap_init(void) { diff --git a/arch/sw_64/kvm/entry_core4.S b/arch/sw_64/kvm/entry_core4.S index fb6757425f76..98993884fd08 100644 --- a/arch/sw_64/kvm/entry_core4.S +++ b/arch/sw_64/kvm/entry_core4.S @@ -266,6 +266,8 @@ $setfpec_over: csrr $18, CSR_EARG2 ldi $19, -PT_REGS_SIZE(sp) + csrr $1, CSR_CAUSE + stl $1, PT_REGS_CAUSE($19) call $26, do_entInt ldl $26, VCPU_RET_RA(sp) ldl $0, VCPU_RET_R0(sp) diff --git a/drivers/irqchip/irq-sunway-cpu.c b/drivers/irqchip/irq-sunway-cpu.c index 31f170e0a5aa..f68bca18923f 100644 --- a/drivers/irqchip/irq-sunway-cpu.c +++ b/drivers/irqchip/irq-sunway-cpu.c @@ -184,8 +184,10 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, /* restart idle routine if it is interrupted */ if (regs->pc > (u64)__idle_start && regs->pc < (u64)__idle_end) regs->pc = (u64)__idle_start; - - irq_enter(); + if (regs->cause != -2) + irq_enter(); + else + nmi_enter(); old_regs = set_irq_regs(regs); #ifdef CONFIG_SUBARCH_C4 @@ -269,7 +271,10 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, out: set_irq_regs(old_regs); - irq_exit(); + if (regs->cause != -2) + irq_exit(); + else + nmi_exit(); } EXPORT_SYMBOL(do_entInt); -- Gitee From 32a465b5d6a6fcb1ca2af03397ba3379b5b98cf4 Mon Sep 17 00:00:00 2001 From: Tang Jinyang Date: Tue, 21 May 2024 19:53:19 +0800 Subject: [PATCH 018/100] anolis: sw64: fix bugs in decreasing frequency ANBZ: #4688 The issue arose because the downshift_freq() was attempting to scale down the frequency of a physicial core when only one of its logical core was offline. The correct behavior should be to scale down the frequency only when both logical cores of a pyhsicial core are offline. Signed-off-by: Tang Jinyang Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/smp.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index ffa858e837a5..53e812efc3d2 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -62,6 +62,7 @@ static void upshift_freq(void) 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); @@ -73,11 +74,21 @@ static void upshift_freq(void) static void downshift_freq(void) { unsigned long value; - int cpuid, core_id, node_id; + int core_id, node_id, cpu; + int cpuid = smp_processor_id(); + struct cpu_topology *cpu_topo = &cpu_topology[cpuid]; if (is_guest_or_emul()) return; - cpuid = smp_processor_id(); + + for_each_online_cpu(cpu) { + struct cpu_topology *sib_topo = &cpu_topology[cpu]; + + if ((cpu_topo->package_id == sib_topo->package_id) && + (cpu_topo->core_id == sib_topo->core_id)) + return; + } + core_id = rcid_to_core_id(cpu_to_rcid(cpuid)); node_id = rcid_to_domain_id(cpu_to_rcid(cpuid)); -- Gitee From 81b6329dfb15f99d19065e19734648befd646d0d Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Fri, 31 May 2024 13:55:09 +0800 Subject: [PATCH 019/100] anolis: sw64: add HARDLOCKUP_DETECTOR support ANBZ: #4688 Hardlockup depends on non-maskable perf interrupts, so set PMI as NMI and make hw_nmi_get_sample_period() based on current frequecy. Signed-off-by: He Chuyue Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 2 ++ arch/sw_64/include/asm/hmcall.h | 3 +++ arch/sw_64/include/asm/irq_impl.h | 5 +++-- arch/sw_64/kernel/irq.c | 1 + arch/sw_64/kernel/setup.c | 7 +++++++ arch/sw_64/kernel/smp.c | 2 ++ 6 files changed, 18 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 1861622fd184..9211ece4824c 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -99,6 +99,8 @@ config SW64 select HAVE_PCI select HAVE_PCSPKR_PLATFORM select HAVE_PERF_EVENTS + select HAVE_PERF_EVENTS_NMI if SUBARCH_C4 + select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && HAVE_PERF_EVENTS_NMI select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP select HAVE_REGS_AND_STACK_ACCESS_API diff --git a/arch/sw_64/include/asm/hmcall.h b/arch/sw_64/include/asm/hmcall.h index fd873e825ae1..574144eab22b 100644 --- a/arch/sw_64/include/asm/hmcall.h +++ b/arch/sw_64/include/asm/hmcall.h @@ -248,6 +248,9 @@ static inline void wrap_asid(unsigned long asid, unsigned long ptbr) #define save_ktp() wrktp() #endif +#define set_nmi(irq) setup_nmi(1, (irq)) +#define clear_nmi(irq) setup_nmi(0, (irq)) + #endif /* !__ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/arch/sw_64/include/asm/irq_impl.h b/arch/sw_64/include/asm/irq_impl.h index 8040d22c53a5..c4f2690bca2e 100644 --- a/arch/sw_64/include/asm/irq_impl.h +++ b/arch/sw_64/include/asm/irq_impl.h @@ -24,8 +24,9 @@ enum sw64_irq_type { INT_IPI = 1, - INT_PC0 = 2, - INT_PC1 = 3, + INT_PC = 2, /* C4 PMI */ + INT_PC0 = 2, /* C3 PMI 0 */ + INT_PC1 = 3, /* C3 PMI 1 */ INT_INTx = 5, INT_MSI = 6, INT_MT = 7, diff --git a/arch/sw_64/kernel/irq.c b/arch/sw_64/kernel/irq.c index 8066dcf91424..5706df471a8d 100644 --- a/arch/sw_64/kernel/irq.c +++ b/arch/sw_64/kernel/irq.c @@ -124,6 +124,7 @@ void __init init_IRQ(void) if (IS_ENABLED(CONFIG_SUBARCH_C4) && is_in_host()) { sw64_write_csr_imb(nmi_stack + THREAD_SIZE, CSR_NMI_STACK); wrent(entNMI, 6); + set_nmi(INT_PC); } sw64_init_irq(); diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index ee0b7850e820..839176939efb 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -145,6 +145,13 @@ void store_cpu_data(int cpu) cpu_data[cpu].last_asid = ASID_FIRST_VERSION; } +#ifdef CONFIG_HARDLOCKUP_DETECTOR_PERF +u64 hw_nmi_get_sample_period(int watchdog_thresh) +{ + return get_cpu_freq() * watchdog_thresh; +} +#endif + /* * I/O resources inherited from PeeCees. Except for perhaps the * turbochannel SWs, everyone has these on some sort of SuperIO chip. diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 53e812efc3d2..699c63fbd38d 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -150,6 +151,7 @@ void smp_callin(void) (unsigned long)page_address(nmi_stack_page) : 0; sw64_write_csr_imb(nmi_stack + THREAD_SIZE, CSR_NMI_STACK); wrent(entNMI, 6); + set_nmi(INT_PC); } /* inform the notifiers about the new cpu */ -- Gitee From 0478aeb87cb12e611c0b357ce07fe60470d11a82 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Mon, 3 Jun 2024 14:46:41 +0800 Subject: [PATCH 020/100] anolis: sw64: defconfig: update defconfig for kata-containers ANBZ: #4688 For kata-containers in sw64, we rename kata_guest_defconfig to kata xuelang_defconfig for C3B, and add kata_junzhang_defconfig for C4. Signed-off-by: Chen Wang Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- ...uest_defconfig => kata_junzhang_defconfig} | 129 +++++++++++++--- arch/sw_64/configs/kata_xuelang_defconfig | 145 +++++++++++++++--- 2 files changed, 226 insertions(+), 48 deletions(-) rename arch/sw_64/configs/{kata_guest_defconfig => kata_junzhang_defconfig} (85%) diff --git a/arch/sw_64/configs/kata_guest_defconfig b/arch/sw_64/configs/kata_junzhang_defconfig similarity index 85% rename from arch/sw_64/configs/kata_guest_defconfig rename to arch/sw_64/configs/kata_junzhang_defconfig index 6a7c442b94a7..160944e463dc 100644 --- a/arch/sw_64/configs/kata_guest_defconfig +++ b/arch/sw_64/configs/kata_junzhang_defconfig @@ -1,4 +1,4 @@ -CONFIG_LOCALVERSION="-xuelang" +CONFIG_LOCALVERSION="-junzhang" CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y # CONFIG_CROSS_MEMORY_ATTACH is not set @@ -6,6 +6,7 @@ CONFIG_USELIB=y CONFIG_HIGH_RES_TIMERS=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_IKHEADERS=y CONFIG_LOG_BUF_SHIFT=18 CONFIG_MEMCG=y CONFIG_BLK_CGROUP=y @@ -17,6 +18,7 @@ CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_PERF=y CONFIG_NAMESPACES=y +CONFIG_USER_NS=y CONFIG_SCHED_AUTOGROUP=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y @@ -26,21 +28,17 @@ CONFIG_BPF_SYSCALL=y CONFIG_PERF_EVENTS=y CONFIG_DEBUG_PERF_USE_VMALLOC=y # CONFIG_COMPAT_BRK is not set -CONFIG_CPUFREQ_DEBUGFS=y -# CONFIG_LOCK_MEMB is not set +CONFIG_SUBARCH_C4=y CONFIG_SMP=y +CONFIG_SCHED_SMT=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_NUMA=y CONFIG_HZ=100 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=y -CONFIG_BUILTIN_DTB=y -CONFIG_BUILTIN_DTB_NAME="chip_vt" CONFIG_FIRMWARE_MEMMAP=y CONFIG_DMI_SYSFS=m -CONFIG_GOOGLE_FIRMWARE=y -CONFIG_SW64_SUSPEND_DEEPSLEEP_NONBOOT_CORE=y -CONFIG_SW64_SUSPEND_DEEPSLEEP_BOOTCORE=y +CONFIG_ACPI_TAD=y # CONFIG_CPU_IDLE is not set CONFIG_VIRTUALIZATION=y CONFIG_KVM=y @@ -55,6 +53,7 @@ CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y +CONFIG_BLK_DEV_THROTTLING=y CONFIG_PARTITION_ADVANCED=y CONFIG_OSF_PARTITION=y CONFIG_BSD_DISKLABEL=y @@ -67,6 +66,7 @@ CONFIG_ULTRIX_PARTITION=y CONFIG_MEMORY_HOTPLUG=y CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_CMA_AREAS=7 CONFIG_NET=y CONFIG_PACKET=y CONFIG_PACKET_DIAG=y @@ -108,7 +108,7 @@ CONFIG_INET6_IPCOMP=m CONFIG_IPV6_MIP6=m CONFIG_IPV6_ILA=m CONFIG_IPV6_VTI=m -CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_SIT=m CONFIG_IPV6_GRE=m CONFIG_IPV6_SUBTREES=y CONFIG_IPV6_MROUTE=y @@ -117,7 +117,8 @@ CONFIG_IPV6_PIMSM_V2=y CONFIG_IPV6_SEG6_LWTUNNEL=y CONFIG_IPV6_SEG6_HMAC=y CONFIG_NETFILTER=y -CONFIG_NF_CONNTRACK=m +CONFIG_BRIDGE_NETFILTER=m +CONFIG_NF_CONNTRACK=y CONFIG_NF_LOG_NETDEV=m CONFIG_NF_CONNTRACK_ZONES=y CONFIG_NF_CONNTRACK_EVENTS=y @@ -137,7 +138,7 @@ CONFIG_NF_CT_NETLINK=m CONFIG_NF_CT_NETLINK_TIMEOUT=m CONFIG_NF_CT_NETLINK_HELPER=m CONFIG_NETFILTER_NETLINK_GLUE_CT=y -CONFIG_NF_TABLES=y +CONFIG_NF_TABLES=m CONFIG_NF_TABLES_NETDEV=y CONFIG_NFT_NUMGEN=m CONFIG_NFT_CT=m @@ -209,6 +210,7 @@ CONFIG_NETFILTER_XT_MATCH_NFACCT=m CONFIG_NETFILTER_XT_MATCH_OSF=m CONFIG_NETFILTER_XT_MATCH_OWNER=m CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m CONFIG_NETFILTER_XT_MATCH_QUOTA=m CONFIG_NETFILTER_XT_MATCH_RATEEST=m @@ -239,7 +241,11 @@ CONFIG_IP_SET_HASH_NETNET=m CONFIG_IP_SET_HASH_NETPORT=m CONFIG_IP_SET_HASH_NETIFACE=m CONFIG_IP_SET_LIST_SET=m -CONFIG_IP_VS=m +CONFIG_IP_VS=y +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_RR=y +CONFIG_IP_VS_NFCT=y CONFIG_NF_TABLES_IPV4=y CONFIG_NFT_DUP_IPV4=m CONFIG_NFT_FIB_IPV4=m @@ -267,7 +273,7 @@ CONFIG_IP_NF_SECURITY=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m -CONFIG_NF_TABLES_BRIDGE=y +CONFIG_NF_TABLES_BRIDGE=m CONFIG_NF_LOG_BRIDGE=m CONFIG_BRIDGE_NF_EBTABLES=m CONFIG_BRIDGE_EBT_BROUTE=m @@ -333,7 +339,7 @@ CONFIG_CLS_U32_MARK=y CONFIG_NET_CLS_RSVP=m CONFIG_NET_CLS_RSVP6=m CONFIG_NET_CLS_FLOW=m -CONFIG_NET_CLS_CGROUP=m +CONFIG_NET_CLS_CGROUP=y CONFIG_NET_CLS_BPF=m CONFIG_NET_CLS_FLOWER=m CONFIG_NET_CLS_MATCHALL=m @@ -364,7 +370,6 @@ CONFIG_NET_IFE_SKBPRIO=m CONFIG_NET_IFE_SKBTCINDEX=m CONFIG_OPENVSWITCH=m CONFIG_VSOCKETS=y -CONFIG_VSOCKETS_DIAG=m CONFIG_VIRTIO_VSOCKETS=y CONFIG_NETLINK_DIAG=m CONFIG_CGROUP_NET_PRIO=y @@ -372,6 +377,15 @@ CONFIG_BPF_JIT=y # CONFIG_WIRELESS is not set CONFIG_NET_9P=y CONFIG_NET_9P_VIRTIO=y +CONFIG_PCI=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIEAER=y +# CONFIG_PCIEASPM is not set +CONFIG_PCI_MSI=y +CONFIG_PCI_IOV=y +CONFIG_UEVENT_HELPER=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_MTD=y @@ -390,12 +404,12 @@ CONFIG_MTD_PHYSMAP=y CONFIG_MTD_PHYSMAP_OF=y CONFIG_MTD_PLATRAM=y CONFIG_MTD_SPI_NOR=y -CONFIG_OF_OVERLAY=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=5000000 CONFIG_VIRTIO_BLK=y +CONFIG_BLK_DEV_NVME=y CONFIG_NVME_MULTIPATH=y CONFIG_NVME_RDMA=m CONFIG_NVME_FC=y @@ -420,12 +434,22 @@ CONFIG_SCSI_SAS_ATA=y CONFIG_SCSI_SRP_ATTRS=y CONFIG_ISCSI_TCP=m CONFIG_ISCSI_BOOT_SYSFS=y +CONFIG_SCSI_CXGB3_ISCSI=m +CONFIG_SCSI_CXGB4_ISCSI=m +CONFIG_SCSI_BNX2_ISCSI=m +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_MPT3SAS=m CONFIG_SCSI_DH=y CONFIG_SCSI_DH_RDAC=y CONFIG_SCSI_DH_HP_SW=y CONFIG_SCSI_DH_EMC=y CONFIG_SCSI_DH_ALUA=y CONFIG_ATA=y +CONFIG_SATA_AHCI=y # CONFIG_ATA_SFF is not set CONFIG_MD=y CONFIG_MD_LINEAR=m @@ -467,6 +491,49 @@ CONFIG_TCM_PSCSI=m CONFIG_TCM_USER2=m CONFIG_LOOPBACK_TARGET=m CONFIG_ISCSI_TARGET=m +CONFIG_NET_FC=y +CONFIG_MACVLAN=m +CONFIG_MACVTAP=m +CONFIG_VIRTIO_NET=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_AURORA is not set +CONFIG_CAVIUM_PTP=y +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +CONFIG_E100=y +CONFIG_E1000=y +CONFIG_E1000E=y +CONFIG_IGB=y +CONFIG_IGBVF=m +CONFIG_IXGB=m +CONFIG_IXGBE=m +CONFIG_IXGBEVF=m +CONFIG_I40E=y +CONFIG_I40EVF=y +# CONFIG_NET_VENDOR_MARVELL is not set +CONFIG_MLX4_EN=y +CONFIG_MLX5_CORE=m +CONFIG_MLX5_FPGA=y +CONFIG_MLX5_CORE_EN=y +CONFIG_MLXSW_CORE=y +CONFIG_MLXSW_PCI=y +CONFIG_MLXSW_I2C=y +CONFIG_MLXSW_MINIMAL=y +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_WLAN is not set CONFIG_INPUT_FF_MEMLESS=y CONFIG_INPUT_POLLDEV=y CONFIG_INPUT_MOUSEDEV=y @@ -477,22 +544,24 @@ CONFIG_INPUT_EVDEV=y CONFIG_SERIO_LIBPS2=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_PCI is not set CONFIG_SERIAL_8250_SUNWAY=y CONFIG_SERIAL_OF_PLATFORM=y CONFIG_VIRTIO_CONSOLE=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_VIRTIO=y +# CONFIG_HW_RANDOM is not set # CONFIG_DEVPORT is not set # CONFIG_I2C_COMPAT is not set CONFIG_I2C_CHARDEV=y CONFIG_I2C_MUX=y +CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_SPI=y CONFIG_SPI_SPIDEV=y CONFIG_SENSORS_PVT=y CONFIG_SENSORS_LM75=y CONFIG_SSB=y -CONFIG_SUNWAY_SUPERIO_AST2400=y CONFIG_DRM=y +CONFIG_DRM_RADEON=y +CONFIG_DRM_AST=y CONFIG_DRM_VIRTIO_GPU=y CONFIG_FIRMWARE_EDID=y CONFIG_LCD_CLASS_DEVICE=y @@ -507,14 +576,26 @@ CONFIG_USB_STORAGE=y CONFIG_INFINIBAND=m CONFIG_INFINIBAND_USER_MAD=m CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_MTHCA=m +# CONFIG_INFINIBAND_MTHCA_DEBUG is not set +CONFIG_MLX4_INFINIBAND=m +CONFIG_MLX5_INFINIBAND=m +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_CM=y CONFIG_RTC_CLASS=y # CONFIG_RTC_NVMEM is not set # CONFIG_RTC_INTF_PROC is not set CONFIG_RTC_DRV_PCF8523=y CONFIG_UIO=y +CONFIG_UIO_PCI_GENERIC=m +CONFIG_VFIO=y +CONFIG_VIRTIO_PCI=y +# CONFIG_VIRTIO_PCI_LEGACY is not set CONFIG_VIRTIO_MMIO=y CONFIG_STAGING=y -CONFIG_SW64_LPC_INTC=y +CONFIG_FB_SM750=y +CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y +CONFIG_SUNWAY_IOMMU_V2=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y @@ -544,7 +625,6 @@ CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_HUGETLBFS=y CONFIG_CONFIGFS_FS=y -CONFIG_SQUASHFS=y CONFIG_NFS_FS=y CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y @@ -564,7 +644,7 @@ CONFIG_9P_FS=y CONFIG_9P_FSCACHE=y CONFIG_9P_FS_POSIX_ACL=y CONFIG_9P_FS_SECURITY=y -CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_737=m CONFIG_NLS_CODEPAGE_775=m CONFIG_NLS_CODEPAGE_850=m @@ -588,7 +668,7 @@ CONFIG_NLS_ISO8859_8=m CONFIG_NLS_CODEPAGE_1250=m CONFIG_NLS_CODEPAGE_1251=m CONFIG_NLS_ASCII=m -CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_2=m CONFIG_NLS_ISO8859_3=m CONFIG_NLS_ISO8859_4=m @@ -619,14 +699,15 @@ CONFIG_SECURITY_INFINIBAND=y CONFIG_SECURITY_PATH=y CONFIG_CRYPTO_AUTHENC=y CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_SEQIV=y CONFIG_CRYPTO_ECHAINIV=y CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_HW is not set CONFIG_CONSOLE_LOGLEVEL_QUIET=7 # CONFIG_ENABLE_MUST_CHECK is not set -# CONFIG_FRAME_POINTER is not set CONFIG_SCHEDSTATS=y # CONFIG_RCU_TRACE is not set diff --git a/arch/sw_64/configs/kata_xuelang_defconfig b/arch/sw_64/configs/kata_xuelang_defconfig index c059bbb7a576..b6c4b4045b1f 100644 --- a/arch/sw_64/configs/kata_xuelang_defconfig +++ b/arch/sw_64/configs/kata_xuelang_defconfig @@ -6,14 +6,13 @@ CONFIG_USELIB=y CONFIG_HIGH_RES_TIMERS=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_IKHEADERS=y CONFIG_LOG_BUF_SHIFT=18 CONFIG_MEMCG=y CONFIG_BLK_CGROUP=y CONFIG_CFS_BANDWIDTH=y -CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_FREEZER=y -CONFIG_CGROUP_HUGETLB=y CONFIG_CPUSETS=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y @@ -25,25 +24,28 @@ CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y CONFIG_KALLSYMS_ALL=y +CONFIG_BPF_SYSCALL=y CONFIG_PERF_EVENTS=y CONFIG_DEBUG_PERF_USE_VMALLOC=y # CONFIG_COMPAT_BRK is not set -CONFIG_CPUFREQ_DEBUGFS=y -# CONFIG_LOCK_MEMB is not set CONFIG_SMP=y -CONFIG_HOTPLUG_CPU=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_NUMA=y CONFIG_HZ=100 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_MISC=y CONFIG_FIRMWARE_MEMMAP=y CONFIG_DMI_SYSFS=m -# CONFIG_SUSPEND is not set +CONFIG_ACPI_TAD=y # CONFIG_CPU_IDLE is not set CONFIG_VIRTUALIZATION=y CONFIG_KVM=y CONFIG_VHOST_NET=m -CONFIG_VHOST_VSOCK=y +CONFIG_VHOST_SCSI=m +CONFIG_VHOST_VSOCK=m +CONFIG_VHOST_CROSS_ENDIAN_LEGACY=y +CONFIG_KPROBES=y +CONFIG_JUMP_LABEL=y CONFIG_MODULES=y CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODULE_UNLOAD=y @@ -59,7 +61,10 @@ CONFIG_UNIXWARE_DISKLABEL=y CONFIG_LDM_PARTITION=y CONFIG_SGI_PARTITION=y CONFIG_ULTRIX_PARTITION=y +CONFIG_MEMORY_HOTPLUG=y +CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_CMA_AREAS=7 CONFIG_NET=y CONFIG_PACKET=y CONFIG_PACKET_DIAG=y @@ -67,7 +72,7 @@ CONFIG_UNIX=y CONFIG_UNIX_DIAG=y CONFIG_TLS=m CONFIG_TLS_DEVICE=y -CONFIG_XFRM_USER=m +CONFIG_XFRM_USER=y CONFIG_XFRM_INTERFACE=m CONFIG_XFRM_SUB_POLICY=y CONFIG_XFRM_STATISTICS=y @@ -91,7 +96,6 @@ CONFIG_INET_IPCOMP=m CONFIG_INET_UDP_DIAG=m CONFIG_TCP_CONG_ADVANCED=y CONFIG_TCP_MD5SIG=y -CONFIG_IPV6=m CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y CONFIG_IPV6_OPTIMISTIC_DAD=y @@ -111,7 +115,8 @@ CONFIG_IPV6_PIMSM_V2=y CONFIG_IPV6_SEG6_LWTUNNEL=y CONFIG_IPV6_SEG6_HMAC=y CONFIG_NETFILTER=y -CONFIG_NF_CONNTRACK=m +CONFIG_BRIDGE_NETFILTER=m +CONFIG_NF_CONNTRACK=y CONFIG_NF_LOG_NETDEV=m CONFIG_NF_CONNTRACK_ZONES=y CONFIG_NF_CONNTRACK_EVENTS=y @@ -203,6 +208,7 @@ CONFIG_NETFILTER_XT_MATCH_NFACCT=m CONFIG_NETFILTER_XT_MATCH_OSF=m CONFIG_NETFILTER_XT_MATCH_OWNER=m CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m CONFIG_NETFILTER_XT_MATCH_QUOTA=m CONFIG_NETFILTER_XT_MATCH_RATEEST=m @@ -233,10 +239,10 @@ CONFIG_IP_SET_HASH_NETNET=m CONFIG_IP_SET_HASH_NETPORT=m CONFIG_IP_SET_HASH_NETIFACE=m CONFIG_IP_SET_LIST_SET=m -CONFIG_IP_VS=m +CONFIG_IP_VS=y CONFIG_IP_VS_PROTO_TCP=y CONFIG_IP_VS_PROTO_UDP=y -CONFIG_IP_VS_RR=m +CONFIG_IP_VS_RR=y CONFIG_IP_VS_NFCT=y CONFIG_NF_TABLES_IPV4=y CONFIG_NFT_DUP_IPV4=m @@ -287,8 +293,7 @@ CONFIG_BRIDGE_EBT_REDIRECT=m CONFIG_BRIDGE_EBT_SNAT=m CONFIG_BRIDGE_EBT_LOG=m CONFIG_BRIDGE_EBT_NFLOG=m -CONFIG_BRIDGE=m -CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_BRIDGE=y CONFIG_VLAN_8021Q=m CONFIG_VLAN_8021Q_GVRP=y CONFIG_VLAN_8021Q_MVRP=y @@ -332,7 +337,7 @@ CONFIG_CLS_U32_MARK=y CONFIG_NET_CLS_RSVP=m CONFIG_NET_CLS_RSVP6=m CONFIG_NET_CLS_FLOW=m -CONFIG_NET_CLS_CGROUP=m +CONFIG_NET_CLS_CGROUP=y CONFIG_NET_CLS_BPF=m CONFIG_NET_CLS_FLOWER=m CONFIG_NET_CLS_MATCHALL=m @@ -363,13 +368,20 @@ CONFIG_NET_IFE_SKBPRIO=m CONFIG_NET_IFE_SKBTCINDEX=m CONFIG_OPENVSWITCH=m CONFIG_VSOCKETS=y -CONFIG_VSOCKETS_DIAG=m +CONFIG_VIRTIO_VSOCKETS=y CONFIG_NETLINK_DIAG=m CONFIG_CGROUP_NET_PRIO=y CONFIG_BPF_JIT=y -CONFIG_NET_DROP_MONITOR=m # CONFIG_WIRELESS is not set -CONFIG_CAIF=m +CONFIG_NET_9P=y +CONFIG_NET_9P_VIRTIO=y +CONFIG_PCI=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIEAER=y +# CONFIG_PCIEASPM is not set +CONFIG_PCI_MSI=y +CONFIG_PCI_IOV=y +CONFIG_UEVENT_HELPER=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y # CONFIG_STANDALONE is not set @@ -394,6 +406,8 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=5000000 +CONFIG_VIRTIO_BLK=y +CONFIG_BLK_DEV_NVME=y CONFIG_NVME_MULTIPATH=y CONFIG_NVME_RDMA=m CONFIG_NVME_FC=y @@ -418,12 +432,22 @@ CONFIG_SCSI_SAS_ATA=y CONFIG_SCSI_SRP_ATTRS=y CONFIG_ISCSI_TCP=m CONFIG_ISCSI_BOOT_SYSFS=y +CONFIG_SCSI_CXGB3_ISCSI=m +CONFIG_SCSI_CXGB4_ISCSI=m +CONFIG_SCSI_BNX2_ISCSI=m +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_MPT3SAS=m CONFIG_SCSI_DH=y CONFIG_SCSI_DH_RDAC=y CONFIG_SCSI_DH_HP_SW=y CONFIG_SCSI_DH_EMC=y CONFIG_SCSI_DH_ALUA=y CONFIG_ATA=y +CONFIG_SATA_AHCI=y # CONFIG_ATA_SFF is not set CONFIG_MD=y CONFIG_MD_LINEAR=m @@ -465,6 +489,49 @@ CONFIG_TCM_PSCSI=m CONFIG_TCM_USER2=m CONFIG_LOOPBACK_TARGET=m CONFIG_ISCSI_TARGET=m +CONFIG_NET_FC=y +CONFIG_MACVLAN=m +CONFIG_MACVTAP=m +CONFIG_VIRTIO_NET=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_AURORA is not set +CONFIG_CAVIUM_PTP=y +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +CONFIG_E100=y +CONFIG_E1000=y +CONFIG_E1000E=y +CONFIG_IGB=y +CONFIG_IGBVF=m +CONFIG_IXGB=m +CONFIG_IXGBE=m +CONFIG_IXGBEVF=m +CONFIG_I40E=y +CONFIG_I40EVF=y +# CONFIG_NET_VENDOR_MARVELL is not set +CONFIG_MLX4_EN=y +CONFIG_MLX5_CORE=m +CONFIG_MLX5_FPGA=y +CONFIG_MLX5_CORE_EN=y +CONFIG_MLXSW_CORE=y +CONFIG_MLXSW_PCI=y +CONFIG_MLXSW_I2C=y +CONFIG_MLXSW_MINIMAL=y +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_WLAN is not set CONFIG_INPUT_FF_MEMLESS=y CONFIG_INPUT_POLLDEV=y CONFIG_INPUT_MOUSEDEV=y @@ -475,15 +542,24 @@ CONFIG_INPUT_EVDEV=y CONFIG_SERIO_LIBPS2=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_PCI is not set CONFIG_SERIAL_8250_SUNWAY=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_VIRTIO_CONSOLE=y # CONFIG_HW_RANDOM is not set +# CONFIG_DEVPORT is not set # CONFIG_I2C_COMPAT is not set CONFIG_I2C_CHARDEV=y CONFIG_I2C_MUX=y CONFIG_SPI=y CONFIG_SPI_SPIDEV=y +CONFIG_SENSORS_PVT=y +CONFIG_SENSORS_LM75=y CONFIG_SSB=y CONFIG_DRM=y +CONFIG_DRM_RADEON=y +CONFIG_DRM_AST=y +CONFIG_DRM_VIRTIO_GPU=y CONFIG_FIRMWARE_EDID=y CONFIG_LCD_CLASS_DEVICE=y # CONFIG_VGA_CONSOLE is not set @@ -497,25 +573,40 @@ CONFIG_USB_STORAGE=y CONFIG_INFINIBAND=m CONFIG_INFINIBAND_USER_MAD=m CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_MTHCA=m +# CONFIG_INFINIBAND_MTHCA_DEBUG is not set +CONFIG_MLX4_INFINIBAND=m +CONFIG_MLX5_INFINIBAND=m +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_CM=y CONFIG_RTC_CLASS=y # CONFIG_RTC_NVMEM is not set # CONFIG_RTC_INTF_PROC is not set CONFIG_RTC_DRV_PCF8523=y CONFIG_UIO=y +CONFIG_UIO_PCI_GENERIC=m +CONFIG_VFIO=y +CONFIG_VIRTIO_PCI=y +# CONFIG_VIRTIO_PCI_LEGACY is not set +CONFIG_VIRTIO_MMIO=y CONFIG_STAGING=y +CONFIG_FB_SM750=y +CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y +CONFIG_SUNWAY_IOMMU=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y CONFIG_EXT4_DEBUG=y CONFIG_XFS_FS=y CONFIG_GFS2_FS=y -CONFIG_BTRFS_FS=m -CONFIG_BTRFS_FS_POSIX_ACL=y CONFIG_FANOTIFY=y CONFIG_QUOTA=y CONFIG_AUTOFS4_FS=y CONFIG_FUSE_FS=y -CONFIG_OVERLAY_FS=m +CONFIG_OVERLAY_FS=y +CONFIG_OVERLAY_FS_INDEX=y +CONFIG_OVERLAY_FS_XINO_AUTO=y +CONFIG_OVERLAY_FS_METACOPY=y CONFIG_FSCACHE=y CONFIG_ISO9660_FS=y CONFIG_JOLIET=y @@ -547,7 +638,11 @@ CONFIG_NFSD_V3_ACL=y CONFIG_NFSD_V4=y CONFIG_NFSD_SCSILAYOUT=y CONFIG_NFSD_V4_SECURITY_LABEL=y -CONFIG_NLS_CODEPAGE_437=m +CONFIG_9P_FS=y +CONFIG_9P_FSCACHE=y +CONFIG_9P_FS_POSIX_ACL=y +CONFIG_9P_FS_SECURITY=y +CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_737=m CONFIG_NLS_CODEPAGE_775=m CONFIG_NLS_CODEPAGE_850=m @@ -571,7 +666,7 @@ CONFIG_NLS_ISO8859_8=m CONFIG_NLS_CODEPAGE_1250=m CONFIG_NLS_CODEPAGE_1251=m CONFIG_NLS_ASCII=m -CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_2=m CONFIG_NLS_ISO8859_3=m CONFIG_NLS_ISO8859_4=m @@ -602,14 +697,16 @@ CONFIG_SECURITY_INFINIBAND=y CONFIG_SECURITY_PATH=y CONFIG_CRYPTO_AUTHENC=y CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_SEQIV=y CONFIG_CRYPTO_ECHAINIV=y CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_HW is not set CONFIG_CONSOLE_LOGLEVEL_QUIET=7 # CONFIG_ENABLE_MUST_CHECK is not set +# CONFIG_FRAME_POINTER is not set CONFIG_SCHEDSTATS=y # CONFIG_RCU_TRACE is not set -- Gitee From f0161bbcab94d8260249dca1c53dee0998ff7913 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Wed, 26 Jun 2024 14:15:01 +0800 Subject: [PATCH 021/100] anolis: sw64: bypass sunway pcie hotplug driver in non-physical scenario ANBZ: #4688 Sunway PCIe hotplug driver is specifically designed for physical hardware, and should not be activated in guest and emulator. Signed-off-by: Chen Wang Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/pci/hotplug/sunway_pciehp_core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/pci/hotplug/sunway_pciehp_core.c b/drivers/pci/hotplug/sunway_pciehp_core.c index e79a074d2557..6d155d3a0595 100644 --- a/drivers/pci/hotplug/sunway_pciehp_core.c +++ b/drivers/pci/hotplug/sunway_pciehp_core.c @@ -248,6 +248,11 @@ static int __init sunway_pciehp_init(void) struct pci_dev *pdev = NULL; struct pci_controller *hose = NULL; + if (is_guest_or_emul()) { + pr_info(DRIVER_DESC " does not support for VM and emulator.\n"); + return -ENODEV; + } + pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); for (hose = hose_head; hose; hose = hose->next) { -- Gitee From fb516ab440740706e8dc3c2b127408b7e96e0cd3 Mon Sep 17 00:00:00 2001 From: Gao Chen Date: Tue, 9 Jul 2024 09:33:19 +0800 Subject: [PATCH 022/100] anolis: sw64: adapt to the upstream changes in hotplug_slot_ops ANBZ: #4688 The upstream changes the parameter passing in reset_slot of struct hotplug_slot_ops from "int probe" to "bool probe". This patch adapts the above changes to sunway_pciehp_reset_slot(). Signed-off-by: Gao Chen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/pci/hotplug/sunway_pciehp.h | 2 +- drivers/pci/hotplug/sunway_pciehp_hpc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/hotplug/sunway_pciehp.h b/drivers/pci/hotplug/sunway_pciehp.h index 5ef5e745543b..d1addc487d07 100644 --- a/drivers/pci/hotplug/sunway_pciehp.h +++ b/drivers/pci/hotplug/sunway_pciehp.h @@ -193,7 +193,7 @@ void sunway_pciehp_release_ctrl(struct controller *ctrl); int sunway_pciehp_sysfs_enable_slot(struct hotplug_slot *hotplug_slot); int sunway_pciehp_sysfs_disable_slot(struct hotplug_slot *hotplug_slot); -int sunway_pciehp_reset_slot(struct hotplug_slot *hotplug_slot, int probe); +int sunway_pciehp_reset_slot(struct hotplug_slot *hotplug_slot, bool probe); int sunway_pciehp_get_attention_status(struct hotplug_slot *hotplug_slot, u8 *status); int sunway_pciehp_set_raw_indicator_status(struct hotplug_slot *hotplug_slot, u8 status); int sunway_pciehp_get_raw_indicator_status(struct hotplug_slot *hotplug_slot, u8 *status); diff --git a/drivers/pci/hotplug/sunway_pciehp_hpc.c b/drivers/pci/hotplug/sunway_pciehp_hpc.c index bd4556dbc3d4..e6559261788d 100644 --- a/drivers/pci/hotplug/sunway_pciehp_hpc.c +++ b/drivers/pci/hotplug/sunway_pciehp_hpc.c @@ -995,7 +995,7 @@ void sunway_pcie_clear_hotplug_events(struct controller *ctrl) * momentarily, if we see that they could interfere. Also, clear any spurious * events after. */ -int sunway_pciehp_reset_slot(struct hotplug_slot *hotplug_slot, int probe) +int sunway_pciehp_reset_slot(struct hotplug_slot *hotplug_slot, bool probe) { struct controller *ctrl = to_ctrl(hotplug_slot); struct pci_dev *pdev = ctrl_dev(ctrl); -- Gitee From e1d4776ca696b58870b85af00cefc7aec3443b4f Mon Sep 17 00:00:00 2001 From: Zheng Chongzhen Date: Tue, 9 Jul 2024 17:18:45 +0000 Subject: [PATCH 023/100] anolis: sw64: fix rc resource setup ANBZ: #4688 The increment of 'enable_cnt' for rc is removed. This ensures that the pci correctly sets up the resources for rc. Signed-off-by: Zheng Chongzhen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/pci/pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/sw_64/pci/pci.c b/arch/sw_64/pci/pci.c index fbbd54dd181c..de56ccfda574 100644 --- a/arch/sw_64/pci/pci.c +++ b/arch/sw_64/pci/pci.c @@ -209,7 +209,6 @@ static void fixup_root_complex(struct pci_dev *dev) dev->class &= 0xff; dev->class |= PCI_CLASS_BRIDGE_PCI << 8; } - atomic_inc(&dev->enable_cnt); dev->no_msi = 1; } -- Gitee From c723c6ef69d80156dfb8109e832111cd56ff0559 Mon Sep 17 00:00:00 2001 From: Hang Yiyi Date: Wed, 20 Dec 2023 15:50:35 +0800 Subject: [PATCH 024/100] anolis: sw64: kvm: add trace kvm function ANBZ: #4688 Add trace_kvm related functions to sw64. These functions can facilitate performance analysis and information tracking of kvm. Signed-off-by: Hang Yiyi Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmio.c | 13 ++- arch/sw_64/kvm/mmu.c | 10 +- arch/sw_64/kvm/sw64.c | 3 + arch/sw_64/kvm/trace.h | 205 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 226 insertions(+), 5 deletions(-) diff --git a/arch/sw_64/kvm/mmio.c b/arch/sw_64/kvm/mmio.c index 0bde3406eb89..3214a4efb0b1 100644 --- a/arch/sw_64/kvm/mmio.c +++ b/arch/sw_64/kvm/mmio.c @@ -8,6 +8,9 @@ #include #include #include +#include + +#include "trace.h" static unsigned long mmio_read_buf(char *buf, unsigned int len) { @@ -50,6 +53,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) return -EINVAL; data = mmio_read_buf(run->mmio.data, len); + trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr, &data); vcpu_set_reg(vcpu, vcpu->arch.mmio_decode.rt, data); } @@ -71,12 +75,17 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, run->mmio.phys_addr = sw64_read_csr(CSR_DVA) & 0xfffffffffffffUL; sw64_decode(vcpu, 0, run); #endif - if (run->mmio.is_write) + if (run->mmio.is_write) { + trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, run->mmio.len, + run->mmio.phys_addr, run->mmio.data); ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, run->mmio.phys_addr, run->mmio.len, run->mmio.data); - else + } else { + trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, run->mmio.len, + run->mmio.phys_addr, NULL); ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, run->mmio.phys_addr, run->mmio.len, run->mmio.data); + } if (!ret) { /* We handled the access successfully in the kernel. */ diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 23e035aa4e6c..74f7d86320ce 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -27,7 +27,7 @@ #include #include #include - +#include #include #include @@ -36,6 +36,7 @@ #include #include +#include "trace.h" #define KVM_APT_FLAG_LOGGING_ACTIVE (1UL << 1) static bool memslot_is_logging(struct kvm_memory_slot *memslot) @@ -1367,6 +1368,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) write_fault = kvm_is_write_fault(access_type); + trace_kvm_guest_fault(vcpu->arch.regs.pc, as_info, fault_entry_addr, fault_gpa); /* The memory slot for IO doesn't register in memory region * with kvm, if hva == KVM_HVA_ERR_BAD, the gpa used for MMIO * needs emulation. @@ -1427,6 +1429,7 @@ int kvm_unmap_hva_range(struct kvm *kvm, if (!kvm->arch.pgd) return 0; + trace_kvm_unmap_hva_range(start, end); handle_hva_to_gpa(kvm, start, end, &kvm_unmap_hva_handler, NULL); return 1; } @@ -1490,7 +1493,7 @@ int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end) { if (!kvm->arch.pgd) return 0; - + trace_kvm_age_hva(start, end); return handle_hva_to_gpa(kvm, start, end, kvm_age_hva_handler, NULL); } @@ -1498,6 +1501,7 @@ int kvm_test_age_hva(struct kvm *kvm, unsigned long hva) { if (!kvm->arch.pgd) return 0; + trace_kvm_test_age_hva(hva); return handle_hva_to_gpa(kvm, hva, hva, kvm_test_age_hva_handler, NULL); } @@ -1519,6 +1523,8 @@ int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte) if (!kvm->arch.pgd) return 0; + trace_kvm_set_spte_hva(hva); + apt_pte = pte_wrprotect(pte); handle_hva_to_gpa(kvm, hva, end, &kvm_set_apte_handler, &apt_pte); return 0; diff --git a/arch/sw_64/kvm/sw64.c b/arch/sw_64/kvm/sw64.c index f6bfb2452938..518aa35363c7 100644 --- a/arch/sw_64/kvm/sw64.c +++ b/arch/sw_64/kvm/sw64.c @@ -318,6 +318,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg) { + trace_kvm_set_guest_debug(vcpu, dbg->control); return 0; } @@ -549,6 +550,8 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level, bool level = irq_level->level; irq_num = irq; + trace_kvm_irq_line(0, irq_num, irq_level->level); + /* target core for Intx is core0 */ vcpu = kvm_get_vcpu(kvm, 0); if (!vcpu) diff --git a/arch/sw_64/kvm/trace.h b/arch/sw_64/kvm/trace.h index 2611df3d3fa5..2b7b1de1e5d5 100644 --- a/arch/sw_64/kvm/trace.h +++ b/arch/sw_64/kvm/trace.h @@ -51,7 +51,210 @@ TRACE_EVENT(kvm_sw64_exit, __entry->vcpu_pc) ); -#endif /* _SW64_KVM_TRACE_H */ +TRACE_EVENT(kvm_guest_fault, + TP_PROTO(unsigned long vcpu_pc, unsigned long as_info, + unsigned long fault_entry_addr, + phys_addr_t fault_gpa), + TP_ARGS(vcpu_pc, as_info, fault_entry_addr, fault_gpa), + + TP_STRUCT__entry( + __field(unsigned long, vcpu_pc) + __field(unsigned long, as_info) + __field(unsigned long, fault_entry_addr) + __field(unsigned long long, fault_gpa) + ), + + TP_fast_assign( + __entry->vcpu_pc = vcpu_pc; + __entry->as_info = as_info; + __entry->fault_entry_addr = fault_entry_addr; + __entry->fault_gpa = fault_gpa; + ), + + TP_printk("fault_gpa %#llx, as_info %#08lx, fault_entry_adr %#08lx, pc 0x%08lx", + __entry->fault_gpa, __entry->as_info, + __entry->fault_entry_addr, __entry->vcpu_pc) +); + +TRACE_EVENT(kvm_access_fault, + TP_PROTO(unsigned long ipa), + TP_ARGS(ipa), + + TP_STRUCT__entry( + __field(unsigned long, ipa) + ), + + TP_fast_assign( + __entry->ipa = ipa; + ), + + TP_printk("IPA: %lx", __entry->ipa) +); + +TRACE_EVENT(kvm_irq_line, + TP_PROTO(int vcpu_idx, int irq_num, int level), + TP_ARGS(vcpu_idx, irq_num, level), + + TP_STRUCT__entry( + __field(int, vcpu_idx) + __field(int, irq_num) + __field(int, level) + ), + + TP_fast_assign( + __entry->vcpu_idx = vcpu_idx; + __entry->irq_num = irq_num; + __entry->level = level; + ), + + TP_printk("Inject interrupt, vcpu->idx: %d, num: %d, level: %d", + __entry->vcpu_idx, __entry->irq_num, __entry->level) +); + +TRACE_EVENT(kvm_mmio_emulate, + TP_PROTO(unsigned long vcpu_pc, unsigned long instr, + unsigned long cpsr), + TP_ARGS(vcpu_pc, instr, cpsr), + + TP_STRUCT__entry( + __field(unsigned long, vcpu_pc) + __field(unsigned long, instr) + __field(unsigned long, cpsr) + ), + + TP_fast_assign( + __entry->vcpu_pc = vcpu_pc; + __entry->instr = instr; + __entry->cpsr = cpsr; + ), + + TP_printk("Emulate MMIO at: 0x%016lx (instr: %08lx, cpsr: %08lx)", + __entry->vcpu_pc, __entry->instr, __entry->cpsr) +); + +TRACE_EVENT(kvm_unmap_hva_range, + TP_PROTO(unsigned long start, unsigned long end), + TP_ARGS(start, end), + + TP_STRUCT__entry( + __field(unsigned long, start) + __field(unsigned long, end) + ), + + TP_fast_assign( + __entry->start = start; + __entry->end = end; + ), + + TP_printk("mmu notifier unmap range: %#016lx -- %#016lx", + __entry->start, __entry->end) +); + +TRACE_EVENT(kvm_set_spte_hva, + TP_PROTO(unsigned long hva), + TP_ARGS(hva), + + TP_STRUCT__entry( + __field(unsigned long, hva) + ), + + TP_fast_assign( + __entry->hva = hva; + ), + + TP_printk("mmu notifier set pte hva: %#016lx", __entry->hva) +); + +TRACE_EVENT(kvm_age_hva, + TP_PROTO(unsigned long start, unsigned long end), + TP_ARGS(start, end), + + TP_STRUCT__entry( + __field(unsigned long, start) + __field(unsigned long, end) + ), + + TP_fast_assign( + __entry->start = start; + __entry->end = end; + ), + + TP_printk("mmu notifier age hva: %#016lx -- %#016lx", + __entry->start, __entry->end) +); + +TRACE_EVENT(kvm_test_age_hva, + TP_PROTO(unsigned long hva), + TP_ARGS(hva), + + TP_STRUCT__entry( + __field(unsigned long, hva) + ), + + TP_fast_assign( + __entry->hva = hva; + ), + + TP_printk("mmu notifier test age hva: %#016lx", __entry->hva) +); + +TRACE_EVENT(kvm_set_way_flush, + TP_PROTO(unsigned long vcpu_pc, bool cache), + TP_ARGS(vcpu_pc, cache), + + TP_STRUCT__entry( + __field(unsigned long, vcpu_pc) + __field(bool, cache) + ), + + TP_fast_assign( + __entry->vcpu_pc = vcpu_pc; + __entry->cache = cache; + ), + + TP_printk("S/W flush at 0x%016lx (cache %s)", + __entry->vcpu_pc, __entry->cache ? "on" : "off") +); + +TRACE_EVENT(kvm_toggle_cache, + TP_PROTO(unsigned long vcpu_pc, bool was, bool now), + TP_ARGS(vcpu_pc, was, now), + + TP_STRUCT__entry( + __field(unsigned long, vcpu_pc) + __field(bool, was) + __field(bool, now) + ), + + TP_fast_assign( + __entry->vcpu_pc = vcpu_pc; + __entry->was = was; + __entry->now = now; + ), + + TP_printk("VM op at 0x%016lx (cache was %s, now %s)", + __entry->vcpu_pc, __entry->was ? "on" : "off", + __entry->now ? "on" : "off") +); + +TRACE_EVENT(kvm_set_guest_debug, + TP_PROTO(struct kvm_vcpu *vcpu, __u32 guest_debug), + TP_ARGS(vcpu, guest_debug), + + TP_STRUCT__entry( + __field(struct kvm_vcpu *, vcpu) + __field(__u32, guest_debug) + ), + + TP_fast_assign( + __entry->vcpu = vcpu; + __entry->guest_debug = guest_debug; + ), + + TP_printk("vcpu: %p, flags: 0x%08x", __entry->vcpu, __entry->guest_debug) +); + +#endif /* _TRACE_ARM_SW_64_KVM_H */ #undef TRACE_INCLUDE_PATH #define TRACE_INCLUDE_PATH . -- Gitee From d851f72b926730a6be47a28ccdb3f31320ec22c0 Mon Sep 17 00:00:00 2001 From: Du Yilong Date: Mon, 28 Aug 2023 16:30:47 +0800 Subject: [PATCH 025/100] anolis: sw64: kvm: fix return value of vmem_mmap ANBZ: #4688 The ret is uninitialized and may lead to unexpected result. Signed-off-by: Du Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/vmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/kvm/vmem.c b/arch/sw_64/kvm/vmem.c index 688449b65fa5..945667f25955 100644 --- a/arch/sw_64/kvm/vmem.c +++ b/arch/sw_64/kvm/vmem.c @@ -144,7 +144,7 @@ static int vmem_mmap(struct file *flip, struct vm_area_struct *vma) /*to do if size bigger than vm_mem_size*/ pr_info("sw64_vmem: vm_start=%#lx, size= %#lx\n", vma->vm_start, size); - vmem_vm_insert_page(vma); + ret = vmem_vm_insert_page(vma); if (ret < 0) return ret; -- Gitee From 32ddce3a8adc0d7781cfe44ea851438ec15b53be Mon Sep 17 00:00:00 2001 From: Zhang Yi Date: Sat, 7 Oct 2023 15:04:51 +0800 Subject: [PATCH 026/100] anolis: sw64: kvm: scale up the range of target vcpu parsed by hypervisor ANBZ: #4688 The range of target vcpu parsed by hypervisor was 0-31 when hypervisor injected msi into guest. It's not always, but it's very likely to cause guest runs slowly when the number of vcpus is more than 32. This patch scales up the range of target vcpu parsed by hypervisor to 0-255. Signed-off-by: Zhang Yi Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/sw64.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/arch/sw_64/kvm/sw64.c b/arch/sw_64/kvm/sw64.c index 518aa35363c7..eb6b891ab47f 100644 --- a/arch/sw_64/kvm/sw64.c +++ b/arch/sw_64/kvm/sw64.c @@ -52,19 +52,17 @@ int kvm_arch_check_processor_compat(void *opaque) int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm, int irq_source_id, int level, bool line_status) { - unsigned int vcid; - unsigned int vcpu_idx; + unsigned int dest_id; struct kvm_vcpu *vcpu = NULL; - int irq = e->msi.data & 0xff; + int vector = e->msi.data & 0xff; - vcid = (e->msi.address_lo & VT_MSIX_ADDR_DEST_ID_MASK) >> VT_MSIX_ADDR_DEST_ID_SHIFT; - vcpu_idx = vcid & 0x1f; - vcpu = kvm_get_vcpu(kvm, vcpu_idx); + dest_id = (e->msi.address_lo & VT_MSIX_ADDR_DEST_ID_MASK) >> VT_MSIX_ADDR_DEST_ID_SHIFT; + vcpu = kvm_get_vcpu(kvm, dest_id); if (!vcpu) return -EINVAL; - return vcpu_interrupt_line(vcpu, irq, true); + return vcpu_interrupt_line(vcpu, vector, true); } void sw64_kvm_switch_vpn(struct kvm_vcpu *vcpu) -- Gitee From c69b1e15907628ecf2d9ce77c0a8d85c9776e981 Mon Sep 17 00:00:00 2001 From: Deng Xiaoyun Date: Tue, 21 Feb 2023 11:12:46 +0800 Subject: [PATCH 027/100] anolis: sw64: add support for vmtop ANBZ: #4688 vmtop is a user-mode tool that runs on the host. It dynamically displays VM resource usage, including CPU and memory usage, and vCPU KVM exit events. To implement these functions, the kernel need to provide interfaces. Therefore, the kernel need to make the following changes. Add the contents of the kvm_vcpu_stat structure, which vmtop monitors. Add debugfs_entries structure and dfx_sw64_debugfs_entries structure, which generate corresponding files in the /sys/kernel/debug/kvm path for vmtop to read when VM is created. Add dfx_sw64_stat_fops, which is used for reading and writing vcpu_stat file in the /sys/kernel/debug/kvm path. Signed-off-by: Deng Xiaoyun Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/sw64.c | 76 +++++++++++++++++++++++++++++++++++++++- include/linux/kvm_host.h | 15 ++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/kvm/sw64.c b/arch/sw_64/kvm/sw64.c index eb6b891ab47f..630ea907592c 100644 --- a/arch/sw_64/kvm/sw64.c +++ b/arch/sw_64/kvm/sw64.c @@ -22,7 +22,12 @@ bool set_msi_flag; - +#define VCPU_STAT(n, x, ...) \ + { n, offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU, ## __VA_ARGS__ } +#define VM_STAT(n, x, ...) \ + { n, offsetof(struct kvm, stat.x), KVM_STAT_VM, ## __VA_ARGS__ } +#define DFX_STAT(n, x, ...) \ + { n, offsetof(struct kvm_vcpu_stat, x), DFX_SW64_STAT_U64, ## __VA_ARGS__ } static unsigned long get_new_vpn_context(struct kvm_vcpu *vcpu, long cpu) { @@ -115,6 +120,52 @@ void check_vcpu_requests(struct kvm_vcpu *vcpu) } } +struct kvm_stats_debugfs_item debugfs_entries[] = { + VCPU_STAT("exits", exits), + VCPU_STAT("io_exits", io_exits), + VCPU_STAT("mmio_exits", mmio_exits), + VCPU_STAT("migration_set_dirty", migration_set_dirty), + VCPU_STAT("shutdown_exits", shutdown_exits), + VCPU_STAT("restart_exits", restart_exits), + VCPU_STAT("ipi_exits", ipi_exits), + VCPU_STAT("timer_exits", timer_exits), + VCPU_STAT("debug_exits", debug_exits), + VCPU_STAT("fatal_error_exits", fatal_error_exits), + VCPU_STAT("halt_exits", halt_exits), + VCPU_STAT("halt_successful_poll", halt_successful_poll), + VCPU_STAT("halt_attempted_poll", halt_attempted_poll), + VCPU_STAT("halt_wakeup", halt_wakeup), + VCPU_STAT("halt_poll_invalid", halt_poll_invalid), + VCPU_STAT("signal_exits", signal_exits), + { "vcpu_stat", 0, KVM_STAT_DFX_SW64 }, + { NULL } +}; + +struct dfx_sw64_kvm_stats_debugfs_item dfx_sw64_debugfs_entries[] = { + DFX_STAT("pid", pid), + DFX_STAT("exits", exits), + DFX_STAT("io_exits", io_exits), + DFX_STAT("mmio_exits", mmio_exits), + DFX_STAT("migration_set_dirty", migration_set_dirty), + DFX_STAT("shutdown_exits", shutdown_exits), + DFX_STAT("restart_exits", restart_exits), + DFX_STAT("ipi_exits", ipi_exits), + DFX_STAT("timer_exits", timer_exits), + DFX_STAT("debug_exits", debug_exits), + DFX_STAT("fatal_error_exits", fatal_error_exits), + DFX_STAT("halt_exits", halt_exits), + DFX_STAT("halt_successful_poll", halt_successful_poll), + DFX_STAT("halt_attempted_poll", halt_attempted_poll), + DFX_STAT("halt_wakeup", halt_wakeup), + DFX_STAT("halt_poll_invalid", halt_poll_invalid), + DFX_STAT("signal_exits", signal_exits), + DFX_STAT("steal", steal), + DFX_STAT("st_max", st_max), + DFX_STAT("utime", utime), + DFX_STAT("stime", stime), + DFX_STAT("gtime", gtime), + { NULL } +}; int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) { @@ -273,10 +324,24 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) return 0; } +void kvm_arch_vcpu_stat_reset(struct kvm_vcpu_stat *vcpu_stat) +{ + vcpu_stat->st_max = 0; +} + +static void update_steal_time(struct kvm_vcpu *vcpu) +{ + u64 delta; + + delta = current->sched_info.run_delay - vcpu->stat.steal; + vcpu->stat.steal = current->sched_info.run_delay; + vcpu->stat.st_max = max(vcpu->stat.st_max, delta); +} void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { vcpu->cpu = cpu; + update_steal_time(vcpu); } void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) @@ -320,6 +385,12 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, return 0; } +void update_vcpu_stat_time(struct kvm_vcpu_stat *vcpu_stat) +{ + vcpu_stat->utime = current->utime; + vcpu_stat->stime = current->stime; + vcpu_stat->gtime = current->gtime; +} /* * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on @@ -358,6 +429,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) if (signal_pending(current)) { ret = -EINTR; run->exit_reason = KVM_EXIT_INTR; + vcpu->stat.signal_exits++; } if (ret <= 0) { @@ -398,6 +470,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) /* Back from guest */ vcpu->mode = OUTSIDE_GUEST_MODE; + vcpu->stat.exits++; local_irq_enable(); guest_exit_irqoff(); @@ -407,6 +480,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) /* ret = 0 indicate interrupt in guest mode, ret > 0 indicate hcall */ ret = handle_exit(vcpu, run, ret, &hargs); + update_vcpu_stat_time(&vcpu->stat); } if (vcpu->sigset_active) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index a0cb2625eecf..cc824a4605ca 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -1817,6 +1817,15 @@ struct kvm_stat_data { enum kvm_stat_kind kind; }; +#ifdef CONFIG_SW64 +struct kvm_stats_debugfs_item { + const char *name; + int offset; + enum kvm_stat_kind kind; + int mode; +}; +#endif + struct _kvm_stats_desc { struct kvm_stats_desc desc; char name[KVM_STATS_NAME_SIZE]; @@ -1939,6 +1948,11 @@ struct _kvm_stats_desc { STATS_DESC_IBOOLEAN(VCPU_GENERIC, blocking) #ifdef CONFIG_SW64 +#define VM_STAT(n, x, ...) \ + { n, offsetof(struct kvm, stat.x), KVM_STAT_VM, ## __VA_ARGS__ } +#define VCPU_STAT(n, x, ...) \ + { n, offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU, ## __VA_ARGS__ } + enum dfx_sw64_stat_kind { DFX_SW64_STAT_U64, DFX_SW64_STAT_CPUTIME, @@ -1952,6 +1966,7 @@ struct dfx_sw64_kvm_stats_debugfs_item { struct dentry *dentry; }; extern struct dfx_sw64_kvm_stats_debugfs_item dfx_sw64_debugfs_entries[]; +extern struct kvm_stats_debugfs_item debugfs_entries[]; #endif extern struct dentry *kvm_debugfs_dir; -- Gitee From cabe89a1ea9689c4524fd22db28b7f7c9aa467ba Mon Sep 17 00:00:00 2001 From: Wang Yuanheng Date: Thu, 4 Jan 2024 09:59:06 +0800 Subject: [PATCH 028/100] anolis: sw64: add missing c4 legacy power management code ANBZ: #4688 The c4 legacy power management is missing, which is causing errors when guest is excuting poweroff command. Signed-off-by: Wang Yuanheng Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/platform/sw64/Makefile | 1 + drivers/platform/sw64/legacy_junzhang.c | 62 +++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 drivers/platform/sw64/legacy_junzhang.c diff --git a/drivers/platform/sw64/Makefile b/drivers/platform/sw64/Makefile index 28922224fb17..3efa835ade5d 100644 --- a/drivers/platform/sw64/Makefile +++ b/drivers/platform/sw64/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_PLATFORM_XUELANG) += legacy_xuelang.o +obj-$(CONFIG_PLATFORM_JUNZHANG) += legacy_junzhang.o diff --git a/drivers/platform/sw64/legacy_junzhang.c b/drivers/platform/sw64/legacy_junzhang.c new file mode 100644 index 000000000000..17d6d151d0b8 --- /dev/null +++ b/drivers/platform/sw64/legacy_junzhang.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include + +static void vt_mode_kill_arch(int mode) +{ + hcall(HCALL_SET_CLOCKEVENT, 0, 0, 0); + + switch (mode) { + case LINUX_REBOOT_CMD_RESTART: + hcall(HCALL_RESTART, 0, 0, 0); + mb(); + break; + case LINUX_REBOOT_CMD_HALT: + case LINUX_REBOOT_CMD_POWER_OFF: + hcall(HCALL_SHUTDOWN, 0, 0, 0); + mb(); + break; + default: + break; + } +} + +void sw64_halt(void) +{ + if (is_in_host()) + cpld_write(0x64, 0x00, 0xf0); + else + vt_mode_kill_arch(LINUX_REBOOT_CMD_HALT); +} + +void sw64_poweroff(void) +{ + if (is_in_host()) + cpld_write(0x64, 0x00, 0xf0); + else + vt_mode_kill_arch(LINUX_REBOOT_CMD_POWER_OFF); +} + +void sw64_restart(void) +{ + if (is_in_host()) { + fix_jm585_reset(); + cpld_write(0x64, 0x00, 0xc3); + } else + vt_mode_kill_arch(LINUX_REBOOT_CMD_RESTART); +} + +static int sw64_reset_init(void) +{ +#ifdef CONFIG_EFI + if (BIOS_SUPPORT_RESET_CLALLBACK((void *)bios_version)) + return 0; +#endif + pm_restart = sw64_restart; + pm_power_off = sw64_poweroff; + pm_halt = sw64_halt; + return 0; +} +subsys_initcall(sw64_reset_init); -- Gitee From 79c7f374bd65acb0cfd045c292c82e0b3638cecb Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 2 Jan 2024 14:26:36 +0800 Subject: [PATCH 029/100] anolis: sw64: kvm: delete memory hotplug codes for CORE3B ANBZ: #4688 Guest memory hotplug of CORE3B is not support, so delete it to make the code clearer. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/hcall.h | 1 - arch/sw_64/include/asm/kvm_asm.h | 2 - arch/sw_64/include/asm/kvm_host.h | 11 ---- arch/sw_64/include/asm/memory.h | 1 - arch/sw_64/kvm/Kconfig | 7 --- arch/sw_64/kvm/handle_exit.c | 6 --- arch/sw_64/kvm/kvm_core3.c | 85 ------------------------------- arch/sw_64/mm/init.c | 5 +- drivers/misc/sunway-ged.c | 2 - 9 files changed, 1 insertion(+), 119 deletions(-) diff --git a/arch/sw_64/include/asm/hcall.h b/arch/sw_64/include/asm/hcall.h index bded05779db7..40eab985fcbd 100644 --- a/arch/sw_64/include/asm/hcall.h +++ b/arch/sw_64/include/asm/hcall.h @@ -18,7 +18,6 @@ enum HCALL_TYPE { HCALL_SWNET = 20, /* guest request swnet service */ HCALL_SWNET_IRQ = 21, /* guest request swnet intr */ HCALL_FATAL_ERROR = 22, /* guest fatal error, issued by hmcode */ - HCALL_MEMHOTPLUG = 23, /* guest memory hotplug event */ NR_HCALL }; diff --git a/arch/sw_64/include/asm/kvm_asm.h b/arch/sw_64/include/asm/kvm_asm.h index fd1b25018fc8..a8e8ef3d68a0 100644 --- a/arch/sw_64/include/asm/kvm_asm.h +++ b/arch/sw_64/include/asm/kvm_asm.h @@ -14,7 +14,6 @@ #define SW64_KVM_EXIT_RESTART 17 #define SW64_KVM_EXIT_APT_FAULT 18 #define SW64_KVM_EXIT_FATAL_ERROR 22 -#define SW64_KVM_EXIT_MEMHOTPLUG 23 #define SW64_KVM_EXIT_DEBUG 24 @@ -29,7 +28,6 @@ {17, "RESTART" }, \ {18, "APT_FAULT" }, \ {22, "FATAL_ERROR" }, \ - {23, "MEMHOTPLUG" }, \ {24, "DEBUG" } diff --git a/arch/sw_64/include/asm/kvm_host.h b/arch/sw_64/include/asm/kvm_host.h index 09a995218a2c..b398d72eb840 100644 --- a/arch/sw_64/include/asm/kvm_host.h +++ b/arch/sw_64/include/asm/kvm_host.h @@ -65,17 +65,12 @@ #define KVM_PHYS_MASK (KVM_PHYS_SIZE - _AC(1, ULL)) struct kvm_arch_memory_slot { - unsigned long host_phys_addr; - bool valid; }; struct kvm_arch { unsigned long host_phys_addr; unsigned long size; - /* segment table */ - unsigned long *seg_pgd; - struct swvm_mem mem; /* Addtional stage page table*/ pgd_t *pgd; @@ -157,9 +152,6 @@ struct kvm_vcpu_stat { u64 ipi_exits; u64 timer_exits; u64 debug_exits; -#ifdef CONFIG_KVM_MEMHOTPLUG - u64 memhotplug_exits; -#endif u64 fatal_error_exits; u64 halt_exits; u64 halt_successful_poll; @@ -176,9 +168,6 @@ struct kvm_vcpu_stat { u64 gtime; }; -#ifdef CONFIG_KVM_MEMHOTPLUG -void vcpu_mem_hotplug(struct kvm_vcpu *vcpu, unsigned long start_addr); -#endif #ifdef CONFIG_SUBARCH_C4 #define KVM_ARCH_WANT_MMU_NOTIFIER #endif diff --git a/arch/sw_64/include/asm/memory.h b/arch/sw_64/include/asm/memory.h index 65e5f8f79727..f0a20cbb096c 100644 --- a/arch/sw_64/include/asm/memory.h +++ b/arch/sw_64/include/asm/memory.h @@ -6,7 +6,6 @@ #include #endif -#define MIN_MEMORY_BLOCK_SIZE_VM_MEMHP (1UL << 30) #define NODE0_START (_TEXT_START - __START_KERNEL_map) #define MAX_PHYSMEM_BITS 48 diff --git a/arch/sw_64/kvm/Kconfig b/arch/sw_64/kvm/Kconfig index b7e43d0bae51..fdff308aed22 100644 --- a/arch/sw_64/kvm/Kconfig +++ b/arch/sw_64/kvm/Kconfig @@ -37,13 +37,6 @@ config KVM If unsure, say N. -config KVM_MEMHOTPLUG - bool "Memory hotplug support for guest" - depends on KVM && MEMORY_HOTPLUG && SUBARCH_C3B - help - Provides memory hotplug support for SW64 guest. - - source "drivers/vhost/Kconfig" endif # VIRTUALIZATION diff --git a/arch/sw_64/kvm/handle_exit.c b/arch/sw_64/kvm/handle_exit.c index 69b97860db88..e0c62dc1112e 100644 --- a/arch/sw_64/kvm/handle_exit.c +++ b/arch/sw_64/kvm/handle_exit.c @@ -63,12 +63,6 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, vcpu->run->exit_reason = KVM_EXIT_DEBUG; vcpu->run->debug.arch.epc = vcpu->arch.regs.pc; return 0; -#ifdef CONFIG_KVM_MEMHOTPLUG - case SW64_KVM_EXIT_MEMHOTPLUG: - vcpu->stat.memhotplug_exits++; - vcpu_mem_hotplug(vcpu, hargs->arg0); - return 1; -#endif #ifdef CONFIG_SUBARCH_C4 case SW64_KVM_EXIT_APT_FAULT: return kvm_handle_guest_abort(vcpu, run); diff --git a/arch/sw_64/kvm/kvm_core3.c b/arch/sw_64/kvm/kvm_core3.c index f7e9150d40e0..b9a5019ee9c0 100644 --- a/arch/sw_64/kvm/kvm_core3.c +++ b/arch/sw_64/kvm/kvm_core3.c @@ -52,15 +52,6 @@ static void bind_vcpu_exit(void) { } static unsigned long longtime_offset; -#ifdef CONFIG_KVM_MEMHOTPLUG -static unsigned long get_vpcr(struct kvm_vcpu *vcpu, u64 vpn) -{ - unsigned long base; - - base = virt_to_phys(vcpu->kvm->arch.seg_pgd); - return base | ((vpn & VPN_MASK) << 44); -} -#else static unsigned long get_vpcr(struct kvm_vcpu *vcpu, u64 vpn) { unsigned long base, size; @@ -69,13 +60,11 @@ static unsigned long get_vpcr(struct kvm_vcpu *vcpu, u64 vpn) size = vcpu->kvm->arch.size; return (base >> 23) | ((size >> 23) << 16) | ((vpn & VPN_MASK) << 44); } -#endif void vcpu_set_numa_affinity(struct kvm_vcpu *vcpu) { if (vcpu->arch.vcb.vpcr == 0) { vcpu->arch.vcb.vpcr = get_vpcr(vcpu, 0); -#ifndef CONFIG_KVM_MEMHOTPLUG if (unlikely(bind_vcpu_enabled)) { int nid; unsigned long end; @@ -85,7 +74,6 @@ void vcpu_set_numa_affinity(struct kvm_vcpu *vcpu) if (pfn_to_nid(PHYS_PFN(end)) == nid) set_cpus_allowed_ptr(vcpu->arch.tsk, cpumask_of_node(nid)); } -#endif vcpu->arch.vcb.upcr = 0x7; } } @@ -103,57 +91,14 @@ void kvm_sw64_update_vpn(struct kvm_vcpu *vcpu, unsigned long vpn) int kvm_sw64_init_vm(struct kvm *kvm) { -#ifdef CONFIG_KVM_MEMHOTPLUG - unsigned long *seg_pgd; - - if (kvm->arch.seg_pgd != NULL) { - kvm_err("kvm_arch already initialized?\n"); - return -EINVAL; - } - - seg_pgd = alloc_pages_exact(PAGE_SIZE, GFP_KERNEL | __GFP_ZERO); - if (!seg_pgd) - return -ENOMEM; - - kvm->arch.seg_pgd = seg_pgd; - #endif return 0; } void kvm_sw64_destroy_vm(struct kvm *kvm) { - #ifdef CONFIG_KVM_MEMHOTPLUG - void *seg_pgd = NULL; - - if (kvm->arch.seg_pgd) { - seg_pgd = READ_ONCE(kvm->arch.seg_pgd); - kvm->arch.seg_pgd = NULL; - } - - if (seg_pgd) - free_pages_exact(seg_pgd, PAGE_SIZE); - #endif kvm_destroy_vcpus(kvm); } -#ifdef CONFIG_KVM_MEMHOTPLUG -static void setup_segment_table(struct kvm *kvm, - struct kvm_memory_slot *memslot, unsigned long addr, size_t size) -{ - unsigned long *seg_pgd = kvm->arch.seg_pgd; - unsigned long num_of_entry; - unsigned long base_hpa = addr; - unsigned long i; - - num_of_entry = round_up(size, 1 << 30) >> 30; - - for (i = 0; i < num_of_entry; i++) { - *seg_pgd = base_hpa + (i << 30); - seg_pgd++; - } -} -#endif - int kvm_arch_prepare_memory_region(struct kvm *kvm, const struct kvm_memory_slot *old, struct kvm_memory_slot *new, @@ -182,12 +127,6 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, if (test_bit(IO_MARK_BIT + 1, (unsigned long *)(&(mem->guest_phys_addr)))) return 0; -#ifndef CONFIG_KVM_MEMHOTPLUG - if (mem->guest_phys_addr) { - pr_info("%s, No KVM MEMHOTPLUG support!\n", __func__); - return 0; - } -#endif if (!sw64_kvm_pool) return -ENOMEM; @@ -337,30 +276,6 @@ long kvm_sw64_set_vcb(struct file *filp, unsigned long arg) return 0; } -#ifdef CONFIG_KVM_MEMHOTPLUG -void vcpu_mem_hotplug(struct kvm_vcpu *vcpu, unsigned long start_addr) -{ - struct kvm *kvm = vcpu->kvm; - struct kvm_memory_slot *slot; - unsigned long start_pfn = start_addr >> PAGE_SHIFT; - - kvm_for_each_memslot(slot, kvm_memslots(kvm)) { - if (start_pfn == slot->base_gfn) { - unsigned long *seg_pgd; - unsigned long num_of_entry = slot->npages >> 17; - unsigned long base_hpa = slot->arch.host_phys_addr; - unsigned long i; - - seg_pgd = kvm->arch.seg_pgd + (start_pfn >> 17); - for (i = 0; i < num_of_entry; i++) { - *seg_pgd = base_hpa + (i << 30); - seg_pgd++; - } - } - } -} -#endif - void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu) { } diff --git a/arch/sw_64/mm/init.c b/arch/sw_64/mm/init.c index ed4f213c7165..0ac65a2fd61c 100644 --- a/arch/sw_64/mm/init.c +++ b/arch/sw_64/mm/init.c @@ -46,10 +46,7 @@ static phys_addr_t mem_size_limit; #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE unsigned long memory_block_size_bytes(void) { - if (is_in_guest()) - return MIN_MEMORY_BLOCK_SIZE_VM_MEMHP; - else - return MIN_MEMORY_BLOCK_SIZE; + return MIN_MEMORY_BLOCK_SIZE; } #endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */ diff --git a/drivers/misc/sunway-ged.c b/drivers/misc/sunway-ged.c index 5c397cb454c9..aa500421355d 100644 --- a/drivers/misc/sunway-ged.c +++ b/drivers/misc/sunway-ged.c @@ -161,8 +161,6 @@ static int sunway_memory_device_add(struct sunway_ged_device *device) list_add_tail(&mem_device->list, &device->dev_list); dev_dbg(device->dev, "Memory device configured\n"); - hcall(HCALL_MEMHOTPLUG, mem_device->start_addr, 0, 0); - return 1; } -- Gitee From 7940f706972bb9cbd7f3278c6261620671f25c9f Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 2 Jan 2024 10:51:13 +0800 Subject: [PATCH 030/100] anolis: sw64: kvm: fix clock sync of CORE4 live migration ANBZ: #4688 Move "migration_mark" and "shtclock" from struct kvm_vcpu_arch to struct vcpucb, so that they can be synced between the src and dst guest. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/kvm_host.h | 4 ---- arch/sw_64/kvm/kvm_core4.c | 13 +++++++------ arch/sw_64/kvm/mmu.c | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/arch/sw_64/include/asm/kvm_host.h b/arch/sw_64/include/asm/kvm_host.h index b398d72eb840..b726b0f5d94e 100644 --- a/arch/sw_64/include/asm/kvm_host.h +++ b/arch/sw_64/include/asm/kvm_host.h @@ -123,10 +123,6 @@ struct kvm_vcpu_arch { /* Cache some mmu pages needed inside spinlock regions */ struct kvm_mmu_memory_cache mmu_page_cache; - - /* guest live migration */ - unsigned long migration_mark; - unsigned long shtclock; }; struct vmem_info { diff --git a/arch/sw_64/kvm/kvm_core4.c b/arch/sw_64/kvm/kvm_core4.c index 3c52b0d7776c..81a999b3fd30 100644 --- a/arch/sw_64/kvm/kvm_core4.c +++ b/arch/sw_64/kvm/kvm_core4.c @@ -68,9 +68,9 @@ 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 = sw64_read_csr(CSR_SHTCLOCK) - + vcpu->arch.vcb.shtclock_offset; + if (vcpu->arch.vcb.migration_mark) + vcpu->arch.vcb.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; @@ -85,13 +85,14 @@ long kvm_sw64_set_vcb(struct file *filp, unsigned long arg) kvm_vcb = memdup_user((void __user *)arg, sizeof(*kvm_vcb)); memcpy(&(vcpu->arch.vcb), kvm_vcb, sizeof(struct vcpucb)); - if (vcpu->arch.migration_mark) { + if (vcpu->arch.vcb.migration_mark) { /* synchronize the longtime of source and destination */ if (vcpu->arch.vcb.soft_cid == 0) - shtclock_offset = vcpu->arch.shtclock - sw64_read_csr(CSR_SHTCLOCK); + shtclock_offset = vcpu->arch.vcb.shtclock - + sw64_read_csr(CSR_SHTCLOCK); vcpu->arch.vcb.shtclock_offset = shtclock_offset; set_timer(vcpu, 200000000); - vcpu->arch.migration_mark = 0; + vcpu->arch.vcb.migration_mark = 0; } return 0; } diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 74f7d86320ce..03428ea9ebbe 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -544,7 +544,7 @@ void kvm_mark_migration(struct kvm *kvm, int mark) unsigned long cpu; kvm_for_each_vcpu(cpu, vcpu, kvm) - vcpu->arch.migration_mark = mark; + vcpu->arch.vcb.migration_mark = mark; } void kvm_arch_commit_memory_region(struct kvm *kvm, -- Gitee From 6db1b1c37c8be1d0a70aab74dda37b207b97c24b Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Mon, 11 Mar 2024 10:18:52 +0800 Subject: [PATCH 031/100] anolis: sw64: kvm: fix unmap_apt_{ptes, pmds} ANBZ: #4688 It has to flush remote tlbs after APT pte/pmd/pud is set. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 03428ea9ebbe..7959bfa19578 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -149,6 +149,7 @@ static void unmap_apt_ptes(struct kvm *kvm, pmd_t *pmd, if (!pte_none(*pte)) { /* Do we need WRITE_ONCE(pte, 0)? */ set_pte(pte, __pte(0)); + kvm_flush_remote_tlbs(kvm); put_page(virt_to_page(pte)); } } while (pte++, addr += PAGE_SIZE, addr != end); @@ -158,6 +159,7 @@ static void unmap_apt_ptes(struct kvm *kvm, pmd_t *pmd, pte_t *pte_table = pte_offset_kernel(pmd, 0); pmd_clear(pmd); + kvm_flush_remote_tlbs(kvm); free_page((unsigned long)pte_table); put_page(virt_to_page(pmd)); } @@ -195,6 +197,7 @@ static void unmap_apt_pmds(struct kvm *kvm, pud_t *pud, pmd_t *pmd_table __maybe_unused = pmd_offset(pud, 0UL); pud_clear(pud); + kvm_flush_remote_tlbs(kvm); free_page((unsigned long)pmd_table); put_page(virt_to_page(pud)); } -- Gitee From 5ffd9f41b60c42dc592ef30af05b23206692a656 Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Tue, 26 Mar 2024 18:35:15 +0800 Subject: [PATCH 032/100] anolis: sw64: kvm: fix APT fault handler ANBZ: #4688 To prevent CSR:AS_INFO and CSR:EXC_GPA being corrupted by vCPU scheduling, save them in struct vcpucb, then hypervisor can get right values to handle APT_FAULT. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/kvm_mmu.h | 3 +- arch/sw_64/include/asm/vcpu.h | 4 +- arch/sw_64/kvm/emulate.c | 10 ----- arch/sw_64/kvm/handle_exit.c | 2 +- arch/sw_64/kvm/mmio.c | 6 +-- arch/sw_64/kvm/mmu.c | 66 ++++++++++++++++++-------------- 6 files changed, 43 insertions(+), 48 deletions(-) diff --git a/arch/sw_64/include/asm/kvm_mmu.h b/arch/sw_64/include/asm/kvm_mmu.h index f4493de934ba..f137e1c39e0c 100644 --- a/arch/sw_64/include/asm/kvm_mmu.h +++ b/arch/sw_64/include/asm/kvm_mmu.h @@ -126,6 +126,7 @@ void kvm_handle_apt_fault(struct kvm_vcpu *vcpu); int kvm_alloc_addtional_stage_pgd(struct kvm *kvm); void kvm_arch_flush_shadow_memslot(struct kvm *kvm, struct kvm_memory_slot *slot); -int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run); +int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, + struct hcall_args *hargs); void apt_unmap_vm(struct kvm *kvm); #endif /* _ASM_SW64_KVM_MMU_H */ diff --git a/arch/sw_64/include/asm/vcpu.h b/arch/sw_64/include/asm/vcpu.h index a68e8ff56af5..daa0c7e3913d 100644 --- a/arch/sw_64/include/asm/vcpu.h +++ b/arch/sw_64/include/asm/vcpu.h @@ -59,7 +59,7 @@ struct vcpucb { struct vcpucb { unsigned long ktp; - unsigned long pcbb; + unsigned long as_info; unsigned long ksp; unsigned long usp; unsigned long kgp; @@ -95,7 +95,7 @@ struct vcpucb { unsigned long reset_entry; unsigned long pvcpu; unsigned long exit_reason; - unsigned long ipaddr; + unsigned long fault_gpa; /* CSR:EXC_GPA */ unsigned long vcpu_pc_save; unsigned long shtclock_offset; unsigned long migration_mark; diff --git a/arch/sw_64/kvm/emulate.c b/arch/sw_64/kvm/emulate.c index 66e6335d9cce..9f2ededd5a1e 100644 --- a/arch/sw_64/kvm/emulate.c +++ b/arch/sw_64/kvm/emulate.c @@ -13,18 +13,8 @@ void sw64_decode(struct kvm_vcpu *vcpu, unsigned int insn, struct kvm_run *run) { int opc, ra; -#ifdef CONFIG_SUBARCH_C3B opc = (insn >> 26) & 0x3f; ra = (insn >> 21) & 0x1f; -#elif defined(CONFIG_SUBARCH_C4) - unsigned long ds_stat, 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; -#endif switch (opc) { case 0x20: /* LDBU */ diff --git a/arch/sw_64/kvm/handle_exit.c b/arch/sw_64/kvm/handle_exit.c index e0c62dc1112e..728d323a9f4d 100644 --- a/arch/sw_64/kvm/handle_exit.c +++ b/arch/sw_64/kvm/handle_exit.c @@ -65,7 +65,7 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, return 0; #ifdef CONFIG_SUBARCH_C4 case SW64_KVM_EXIT_APT_FAULT: - return kvm_handle_guest_abort(vcpu, run); + return kvm_handle_guest_abort(vcpu, run, hargs); #endif case SW64_KVM_EXIT_FATAL_ERROR: vcpu->stat.fatal_error_exits++; diff --git a/arch/sw_64/kvm/mmio.c b/arch/sw_64/kvm/mmio.c index 3214a4efb0b1..bc29dfbd2af9 100644 --- a/arch/sw_64/kvm/mmio.c +++ b/arch/sw_64/kvm/mmio.c @@ -68,13 +68,9 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, { int ret; -#ifdef CONFIG_SUBARCH_C3B run->mmio.phys_addr = hargs->arg1 & 0xfffffffffffffUL; sw64_decode(vcpu, hargs->arg2, run); -#elif defined(CONFIG_SUBARCH_C4) - run->mmio.phys_addr = sw64_read_csr(CSR_DVA) & 0xfffffffffffffUL; - sw64_decode(vcpu, 0, run); -#endif + if (run->mmio.is_write) { trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, run->mmio.len, run->mmio.phys_addr, run->mmio.data); diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 7959bfa19578..1805feb20389 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -786,16 +786,22 @@ static bool apt_is_exec(struct kvm *kvm, phys_addr_t addr) return kvm_pte_exec(ptep); } -static int apt_set_pte_fast(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, - phys_addr_t addr, const pte_t *new_pte, - unsigned long flags) +static int apt_set_pte_fast(struct kvm_vcpu *vcpu, + struct kvm_mmu_memory_cache *cache, + const pte_t *new_pte, unsigned long flags) { pud_t *pud; pmd_t *pmd; pte_t *pte, old_pte; + unsigned long as_info, inv_hpa; + int inv_level; + struct kvm *kvm = vcpu->kvm; bool logging_active = flags & KVM_APT_FLAG_LOGGING_ACTIVE; - 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; + phys_addr_t addr = vcpu->arch.vcb.fault_gpa; + + as_info = vcpu->arch.vcb.as_info; + inv_level = (as_info >> AF_INV_LEVEL_SHIFT) & AF_INV_LEVEL_MASK; + inv_hpa = as_info & AF_ENTRY_ADDR_MASK; VM_BUG_ON(logging_active && !cache); @@ -1134,25 +1140,28 @@ transparent_hugepage_adjust(struct kvm_memory_slot *memslot, return PAGE_SIZE; } -static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_gpa, - struct kvm_memory_slot *memslot, unsigned long hva, - unsigned long fault_status) +static int user_mem_abort(struct kvm_vcpu *vcpu, + struct kvm_memory_slot *memslot, + unsigned long hva, unsigned long fault_status) { int ret; - bool write_fault, exec_fault, writable, force_pte = false; - unsigned long mmu_seq; - gfn_t gfn = fault_gpa >> PAGE_SHIFT; + gfn_t gfn; + kvm_pfn_t pfn; + phys_addr_t fault_gpa; + unsigned int vma_shift; struct kvm *kvm = vcpu->kvm; - struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache; struct vm_area_struct *vma; - kvm_pfn_t pfn; pgprot_t mem_type = PAGE_READONLY; - bool logging_active = memslot_is_logging(memslot); - unsigned long vma_pagesize, flags = 0; unsigned long as_info, access_type; - unsigned int vma_shift; + unsigned long mmu_seq, vma_pagesize, flags = 0; + struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache; + bool logging_active, write_fault, exec_fault, writable, force_pte; - as_info = sw64_read_csr(CSR_AS_INFO); + force_pte = false; + logging_active = memslot_is_logging(memslot); + fault_gpa = vcpu->arch.vcb.fault_gpa; + gfn = fault_gpa >> PAGE_SHIFT; + as_info = vcpu->arch.vcb.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); @@ -1317,7 +1326,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_gpa, new_pte = kvm_pte_mkexec(new_pte); } - ret = apt_set_pte_fast(kvm, memcache, fault_gpa, &new_pte, flags); + ret = apt_set_pte_fast(vcpu, memcache, &new_pte, flags); if (!ret) goto out_unlock; } @@ -1342,28 +1351,27 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_gpa, * memory region has been registered as standard RAM by user space. */ #ifdef CONFIG_SUBARCH_C4 -int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) +int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, + struct hcall_args *hargs) { - unsigned long as_info; /* the value of CSR: AS_INFO */ - unsigned int access_type, inv_level; - unsigned int fault_status; + unsigned long as_info; + unsigned int access_type, fault_status; unsigned long fault_entry_addr; phys_addr_t fault_gpa; struct kvm_memory_slot *memslot; unsigned long hva; bool write_fault, writable; gfn_t gfn; - int ret, idx; - as_info = sw64_read_csr(CSR_AS_INFO); + idx = srcu_read_lock(&vcpu->kvm->srcu); + + as_info = vcpu->arch.vcb.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 = sw64_read_csr(CSR_EXC_GPA); - idx = srcu_read_lock(&vcpu->kvm->srcu); + fault_gpa = vcpu->arch.vcb.fault_gpa; gfn = fault_gpa >> PAGE_SHIFT; memslot = gfn_to_memslot(vcpu->kvm, gfn); @@ -1378,13 +1386,13 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) */ if (hva == KVM_HVA_ERR_BAD) { - ret = io_mem_abort(vcpu, run, NULL); + ret = io_mem_abort(vcpu, run, hargs); goto out_unlock; } /* Userspace should not be able to register out-of-bounds IPAs */ VM_BUG_ON(fault_gpa >= KVM_PHYS_SIZE); - ret = user_mem_abort(vcpu, fault_gpa, memslot, hva, fault_status); + ret = user_mem_abort(vcpu, memslot, hva, fault_status); if (ret == 0) ret = 1; out_unlock: -- Gitee From f9414af7abe1a2ab3620c9b0ffae2ee6aae83db6 Mon Sep 17 00:00:00 2001 From: Wang Yuanheng Date: Tue, 26 Mar 2024 09:32:03 +0800 Subject: [PATCH 033/100] anolis: sw64: kvm: fix live migration bug ANBZ: #4688 When it logs dirty pages it should dissolve hugepages, then reallocate pages. Signed-off-by: Wang Yuanheng Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 1805feb20389..1e3c7287769e 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -805,7 +805,9 @@ static int apt_set_pte_fast(struct kvm_vcpu *vcpu, VM_BUG_ON(logging_active && !cache); - if (inv_level == 1) { + if (logging_active) { + goto dissolve; + } else if (inv_level == 1) { pud = (pud_t *)(inv_hpa | PAGE_OFFSET); goto find_pud; } else if (inv_level == 2) { @@ -816,6 +818,7 @@ static int apt_set_pte_fast(struct kvm_vcpu *vcpu, goto find_pte; } +dissolve: /* Create addtional page table mapping - Levels 0 and 1 */ pud = apt_get_pud(kvm->arch.pgd, cache, addr); if (!pud) { -- Gitee From 8f5e6520b1200a548108ca32be8d31072684f37d Mon Sep 17 00:00:00 2001 From: Wang Yuanheng Date: Wed, 27 Mar 2024 14:28:55 +0800 Subject: [PATCH 034/100] anolis: sw64: redesign struct kvm_regs for C4 ANBZ: #4688 Reuse struct user_pt_regs and struct user_fpsimd_state to redesign struct kvm_regs in a way that makes the code clearer. This requires corresponding modification to firmware. Signed-off-by: Wang Yuanheng Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/kvm.h | 52 ++++----------------- arch/sw_64/include/asm/kvm_emulate.h | 16 +++++++ arch/sw_64/kernel/asm-offsets.c | 69 +++++++++++++++++++++++++++- 3 files changed, 92 insertions(+), 45 deletions(-) diff --git a/arch/sw_64/include/asm/kvm.h b/arch/sw_64/include/asm/kvm.h index 41bb657bcacc..6794fe085e0d 100644 --- a/arch/sw_64/include/asm/kvm.h +++ b/arch/sw_64/include/asm/kvm.h @@ -64,49 +64,15 @@ struct kvm_regs { #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; + union { + struct user_pt_regs regs; + struct { + unsigned long r[31]; + unsigned long pc; + unsigned long ps; + }; + }; + struct user_fpsimd_state fpstate; }; #endif diff --git a/arch/sw_64/include/asm/kvm_emulate.h b/arch/sw_64/include/asm/kvm_emulate.h index 915aa6c0bce2..d168f72a2deb 100644 --- a/arch/sw_64/include/asm/kvm_emulate.h +++ b/arch/sw_64/include/asm/kvm_emulate.h @@ -7,6 +7,7 @@ #define R(x) ((size_t) &((struct kvm_regs *)0)->x) +#ifdef CONFIG_SUBARCH_C3B static int reg_offsets[32] = { R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8), R(r9), R(r10), R(r11), R(r12), R(r13), R(r14), R(r15), @@ -36,6 +37,21 @@ static inline unsigned long vcpu_get_reg(struct kvm_vcpu *vcpu, u8 reg_num) return *(unsigned long *)regs_ptr; } +#elif defined(CONFIG_SUBARCH_C4) +static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num, + unsigned long val) +{ + vcpu->arch.regs.r[reg_num] = val; +} + +static inline unsigned long vcpu_get_reg(struct kvm_vcpu *vcpu, u8 reg_num) +{ + if (reg_num == 31) + return 0; + return vcpu->arch.regs.r[reg_num]; +} +#endif + void sw64_decode(struct kvm_vcpu *vcpu, unsigned int insn, struct kvm_run *run); diff --git a/arch/sw_64/kernel/asm-offsets.c b/arch/sw_64/kernel/asm-offsets.c index 337386c163ff..d865caffd014 100644 --- a/arch/sw_64/kernel/asm-offsets.c +++ b/arch/sw_64/kernel/asm-offsets.c @@ -114,6 +114,7 @@ void foo(void) BLANK(); DEFINE(KVM_REGS_SIZE, sizeof(struct kvm_regs)); +#ifdef CONFIG_SUBARCH_C3B DEFINE(KVM_REGS_R0, offsetof(struct kvm_regs, r0)); DEFINE(KVM_REGS_R1, offsetof(struct kvm_regs, r1)); DEFINE(KVM_REGS_R2, offsetof(struct kvm_regs, r2)); @@ -178,8 +179,72 @@ 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)); -#ifdef CONFIG_SUBARCH_C4 - DEFINE(KVM_REGS_SP, offsetof(struct kvm_regs, sp)); +#elif CONFIG_SUBARCH_C4 + DEFINE(KVM_REGS_R0, offsetof(struct kvm_regs, regs.regs[0])); + DEFINE(KVM_REGS_R1, offsetof(struct kvm_regs, regs.regs[1])); + DEFINE(KVM_REGS_R2, offsetof(struct kvm_regs, regs.regs[2])); + DEFINE(KVM_REGS_R3, offsetof(struct kvm_regs, regs.regs[3])); + DEFINE(KVM_REGS_R4, offsetof(struct kvm_regs, regs.regs[4])); + DEFINE(KVM_REGS_R5, offsetof(struct kvm_regs, regs.regs[5])); + DEFINE(KVM_REGS_R6, offsetof(struct kvm_regs, regs.regs[6])); + DEFINE(KVM_REGS_R7, offsetof(struct kvm_regs, regs.regs[7])); + DEFINE(KVM_REGS_R8, offsetof(struct kvm_regs, regs.regs[8])); + DEFINE(KVM_REGS_R9, offsetof(struct kvm_regs, regs.regs[9])); + DEFINE(KVM_REGS_R10, offsetof(struct kvm_regs, regs.regs[10])); + DEFINE(KVM_REGS_R11, offsetof(struct kvm_regs, regs.regs[11])); + DEFINE(KVM_REGS_R12, offsetof(struct kvm_regs, regs.regs[12])); + DEFINE(KVM_REGS_R13, offsetof(struct kvm_regs, regs.regs[13])); + DEFINE(KVM_REGS_R14, offsetof(struct kvm_regs, regs.regs[14])); + DEFINE(KVM_REGS_R15, offsetof(struct kvm_regs, regs.regs[15])); + DEFINE(KVM_REGS_R16, offsetof(struct kvm_regs, regs.regs[16])); + DEFINE(KVM_REGS_R17, offsetof(struct kvm_regs, regs.regs[17])); + DEFINE(KVM_REGS_R18, offsetof(struct kvm_regs, regs.regs[18])); + DEFINE(KVM_REGS_R19, offsetof(struct kvm_regs, regs.regs[19])); + DEFINE(KVM_REGS_R20, offsetof(struct kvm_regs, regs.regs[20])); + DEFINE(KVM_REGS_R21, offsetof(struct kvm_regs, regs.regs[21])); + DEFINE(KVM_REGS_R22, offsetof(struct kvm_regs, regs.regs[22])); + DEFINE(KVM_REGS_R23, offsetof(struct kvm_regs, regs.regs[23])); + DEFINE(KVM_REGS_R24, offsetof(struct kvm_regs, regs.regs[24])); + DEFINE(KVM_REGS_R25, offsetof(struct kvm_regs, regs.regs[25])); + DEFINE(KVM_REGS_R26, offsetof(struct kvm_regs, regs.regs[26])); + DEFINE(KVM_REGS_R27, offsetof(struct kvm_regs, regs.regs[27])); + DEFINE(KVM_REGS_R28, offsetof(struct kvm_regs, regs.regs[28])); + DEFINE(KVM_REGS_GP, offsetof(struct kvm_regs, regs.regs[29])); + DEFINE(KVM_REGS_SP, offsetof(struct kvm_regs, regs.regs[30])); + DEFINE(KVM_REGS_PC, offsetof(struct kvm_regs, regs.pc)); + DEFINE(KVM_REGS_PS, offsetof(struct kvm_regs, regs.pstate)); + DEFINE(KVM_REGS_F0, offsetof(struct kvm_regs, fpstate.fp[0])); + DEFINE(KVM_REGS_F1, offsetof(struct kvm_regs, fpstate.fp[1])); + DEFINE(KVM_REGS_F2, offsetof(struct kvm_regs, fpstate.fp[2])); + DEFINE(KVM_REGS_F3, offsetof(struct kvm_regs, fpstate.fp[3])); + DEFINE(KVM_REGS_F4, offsetof(struct kvm_regs, fpstate.fp[4])); + DEFINE(KVM_REGS_F5, offsetof(struct kvm_regs, fpstate.fp[5])); + DEFINE(KVM_REGS_F6, offsetof(struct kvm_regs, fpstate.fp[6])); + DEFINE(KVM_REGS_F7, offsetof(struct kvm_regs, fpstate.fp[7])); + DEFINE(KVM_REGS_F8, offsetof(struct kvm_regs, fpstate.fp[8])); + DEFINE(KVM_REGS_F9, offsetof(struct kvm_regs, fpstate.fp[9])); + DEFINE(KVM_REGS_F10, offsetof(struct kvm_regs, fpstate.fp[10])); + DEFINE(KVM_REGS_F11, offsetof(struct kvm_regs, fpstate.fp[11])); + DEFINE(KVM_REGS_F12, offsetof(struct kvm_regs, fpstate.fp[12])); + DEFINE(KVM_REGS_F13, offsetof(struct kvm_regs, fpstate.fp[13])); + DEFINE(KVM_REGS_F14, offsetof(struct kvm_regs, fpstate.fp[14])); + DEFINE(KVM_REGS_F15, offsetof(struct kvm_regs, fpstate.fp[15])); + DEFINE(KVM_REGS_F16, offsetof(struct kvm_regs, fpstate.fp[16])); + DEFINE(KVM_REGS_F17, offsetof(struct kvm_regs, fpstate.fp[17])); + DEFINE(KVM_REGS_F18, offsetof(struct kvm_regs, fpstate.fp[18])); + DEFINE(KVM_REGS_F19, offsetof(struct kvm_regs, fpstate.fp[19])); + DEFINE(KVM_REGS_F20, offsetof(struct kvm_regs, fpstate.fp[20])); + DEFINE(KVM_REGS_F21, offsetof(struct kvm_regs, fpstate.fp[21])); + DEFINE(KVM_REGS_F22, offsetof(struct kvm_regs, fpstate.fp[22])); + DEFINE(KVM_REGS_F23, offsetof(struct kvm_regs, fpstate.fp[23])); + DEFINE(KVM_REGS_F24, offsetof(struct kvm_regs, fpstate.fp[24])); + DEFINE(KVM_REGS_F25, offsetof(struct kvm_regs, fpstate.fp[25])); + DEFINE(KVM_REGS_F26, offsetof(struct kvm_regs, fpstate.fp[26])); + DEFINE(KVM_REGS_F27, offsetof(struct kvm_regs, fpstate.fp[27])); + DEFINE(KVM_REGS_F28, offsetof(struct kvm_regs, fpstate.fp[28])); + DEFINE(KVM_REGS_F29, offsetof(struct kvm_regs, fpstate.fp[29])); + DEFINE(KVM_REGS_F30, offsetof(struct kvm_regs, fpstate.fp[30])); + DEFINE(KVM_REGS_FPCR, offsetof(struct kvm_regs, fpstate.fpcr)); #endif BLANK(); -- Gitee From 9377880b32dc7509898a9054fdde4e6a83bdba71 Mon Sep 17 00:00:00 2001 From: Lu Feifei Date: Thu, 28 Mar 2024 13:49:59 +0800 Subject: [PATCH 035/100] anolis: sw64: kvm: fix page walk error of unmap_apt_range() ANBZ: #4688 There is an error in 5-level page walking, and fix it. Signed-off-by: Lu Feifei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 1e3c7287769e..527787c916a1 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -267,7 +267,7 @@ static void unmap_apt_range(struct kvm *kvm, phys_addr_t start, u64 size) */ if (!READ_ONCE(kvm->arch.pgd)) break; - next = p4d_addr_end(addr, end); + next = pgd_addr_end(addr, end); if (!p4d_none(*p4d)) unmap_apt_puds(kvm, p4d, addr, next); /* @@ -276,7 +276,7 @@ static void unmap_apt_range(struct kvm *kvm, phys_addr_t start, u64 size) */ if (next != end) cond_resched_lock(&kvm->mmu_lock); - } while (pgd++, addr = next, addr != end); + } while (p4d++, addr = next, addr != end); } static void apt_unmap_memslot(struct kvm *kvm, -- Gitee From 56005b63338f4639e3834f04f48e3079a212b8cb Mon Sep 17 00:00:00 2001 From: Lu Feifei Date: Thu, 28 Mar 2024 14:00:56 +0800 Subject: [PATCH 036/100] anolis: sw64: kvm: fix the check for THP ANBZ: #4688 Use kvm_is_transparent_hugepage() to explicitly check whether a compound page is a THP when populating KVM's secondary MMU. Signed-off-by: Lu Feifei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 527787c916a1..6e081ef7c592 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -1105,14 +1105,13 @@ transparent_hugepage_adjust(struct kvm_memory_slot *memslot, phys_addr_t *gpap) { kvm_pfn_t pfn = *pfnp; - struct page *page = pfn_to_page(pfn); /* * Make sure the adjustment is done only for THP pages. Also make * sure that the HVA and IPA are sufficiently aligned and that the * block map is contained within the memslot. */ - if (!PageHuge(page) && PageTransCompoundMap(page) && + if (kvm_is_transparent_hugepage(pfn) && fault_supports_apt_huge_mapping(memslot, hva, PMD_SIZE)) { /* * The address we faulted on is backed by a transparent huge -- Gitee From f14a66918381200fe06a19ac316bde6fa8938e52 Mon Sep 17 00:00:00 2001 From: Wang Yuanheng Date: Wed, 27 Mar 2024 17:20:19 +0800 Subject: [PATCH 037/100] anolis: sw64: kvm: add the member of the vcpucb structure ANBZ: #4688 Member atc is added for CSR_ATC to save and restore, and adjusted the size of the structure for future expansion. Signed-off-by: Wang Yuanheng Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/vcpu.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sw_64/include/asm/vcpu.h b/arch/sw_64/include/asm/vcpu.h index daa0c7e3913d..8227166d6998 100644 --- a/arch/sw_64/include/asm/vcpu.h +++ b/arch/sw_64/include/asm/vcpu.h @@ -108,6 +108,8 @@ struct vcpucb { unsigned long csr_earg1; unsigned long csr_earg2; unsigned long csr_scratch; + unsigned long atc; + unsigned long reserved[45]; }; #endif -- Gitee From a16be461878eaeb3a43a4d69e383de5e2de8e9ac Mon Sep 17 00:00:00 2001 From: Wang Yuanheng Date: Mon, 8 Apr 2024 18:36:14 +0800 Subject: [PATCH 038/100] anolis: sw64: kvm: fix size of struct kvm_regs for C3B ANBZ: #4688 The size of struct kvm_regs passed by Qemu is fixed and checked in kernel. Since Qemu has extended the struct kvm_regs, this patch adds some padding bytes to ensure that the size of struct kvm_regs is the same on both C3B and C4. Signed-off-by: Wang Yuanheng Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/kvm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/include/asm/kvm.h b/arch/sw_64/include/asm/kvm.h index 6794fe085e0d..c728504d219e 100644 --- a/arch/sw_64/include/asm/kvm.h +++ b/arch/sw_64/include/asm/kvm.h @@ -49,7 +49,7 @@ struct kvm_regs { unsigned long r27; unsigned long r28; - unsigned long __padding0; + unsigned long reserved; unsigned long fpcr; unsigned long fp[124]; @@ -60,6 +60,7 @@ struct kvm_regs { unsigned long r16; unsigned long r17; unsigned long r18; + unsigned long __padding[6]; }; #elif CONFIG_SUBARCH_C4 -- Gitee From db0082966f6122bc850402c9769442a4320baa9f Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Thu, 11 Apr 2024 14:39:59 +0800 Subject: [PATCH 039/100] anolis: sw64: kvm: fix pmd_trans_cont ANBZ: #4688 If CONFIG_TRANSPARENT_HUGEPAGE=n, it fails to complie because pmd_trans_cont() is undefined. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/pgtable.h | 10 +++++----- arch/sw_64/kvm/mmu.c | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/sw_64/include/asm/pgtable.h b/arch/sw_64/include/asm/pgtable.h index a7741a67e687..b9f98b9af33e 100644 --- a/arch/sw_64/include/asm/pgtable.h +++ b/arch/sw_64/include/asm/pgtable.h @@ -621,6 +621,11 @@ static inline int pte_devmap(pte_t a) } #endif +static inline int pmd_cont(pmd_t pmd) +{ + return !!(pmd_val(pmd) & _PAGE_CONT); +} + #ifdef CONFIG_TRANSPARENT_HUGEPAGE /* We don't have hardware dirty/accessed bits, generic_pmdp_establish is fine.*/ @@ -631,11 +636,6 @@ static inline int pmd_trans_splitting(pmd_t pmd) return !!(pmd_val(pmd) & _PAGE_SPLITTING); } -static inline int pmd_trans_cont(pmd_t pmd) -{ - return !!(pmd_val(pmd) & _PAGE_CONT); -} - static inline int pmd_trans_huge(pmd_t pmd) { return !!(pmd_val(pmd) & _PAGE_LEAF); diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 6e081ef7c592..c02baa04a221 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -73,7 +73,7 @@ static void apt_dissolve_pmd(struct kvm *kvm, phys_addr_t addr, pmd_t *pmd) if (!pmd_trans_huge(*pmd)) return; - if (pmd_trans_cont(*pmd)) { + if (pmd_cont(*pmd)) { for (i = 0; i < CONT_PMDS; i++, pmd++) pmd_clear(pmd); } else @@ -178,7 +178,7 @@ static void unmap_apt_pmds(struct kvm *kvm, pud_t *pud, next = pmd_addr_end(addr, end); if (!pmd_none(*pmd)) { if (pmd_trans_huge(*pmd)) { - if (pmd_trans_cont(*pmd)) { + if (pmd_cont(*pmd)) { for (i = 0; i < CONT_PMDS; i++, pmd++) pmd_clear(pmd); } else -- Gitee From 29786be20b4c016f64401e3605bed8f75dc79c57 Mon Sep 17 00:00:00 2001 From: Wang Yuanheng Date: Fri, 12 Apr 2024 17:25:34 +0800 Subject: [PATCH 040/100] anolis: sw64: kvm: remove some unused codes ANBZ: #4688 Signed-off-by: Wang Yuanheng Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/entry_core4.S | 2 -- arch/sw_64/kvm/kvm_core4.c | 2 -- arch/sw_64/kvm/sw64.c | 3 --- 3 files changed, 7 deletions(-) diff --git a/arch/sw_64/kvm/entry_core4.S b/arch/sw_64/kvm/entry_core4.S index 98993884fd08..48325cc7c2c5 100644 --- a/arch/sw_64/kvm/entry_core4.S +++ b/arch/sw_64/kvm/entry_core4.S @@ -219,8 +219,6 @@ $g_setfpec_over: 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 */ diff --git a/arch/sw_64/kvm/kvm_core4.c b/arch/sw_64/kvm/kvm_core4.c index 81a999b3fd30..a9d9326072e4 100644 --- a/arch/sw_64/kvm/kvm_core4.c +++ b/arch/sw_64/kvm/kvm_core4.c @@ -55,8 +55,6 @@ int kvm_sw64_vcpu_reset(struct kvm_vcpu *vcpu) apt_unmap_vm(vcpu->kvm); hrtimer_cancel(&vcpu->arch.hrt); - vcpu->arch.vcb.soft_cid = vcpu->vcpu_id; - vcpu->arch.vcb.vcpu_irq_disabled = 1; vcpu->arch.pcpu_id = -1; /* force flush tlb for the first time */ vcpu->arch.power_off = 0; memset(&vcpu->arch.irqs_pending, 0, sizeof(vcpu->arch.irqs_pending)); diff --git a/arch/sw_64/kvm/sw64.c b/arch/sw_64/kvm/sw64.c index 630ea907592c..86189243fc75 100644 --- a/arch/sw_64/kvm/sw64.c +++ b/arch/sw_64/kvm/sw64.c @@ -276,9 +276,6 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) hrtimer_init(&vcpu->arch.hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS); vcpu->arch.hrt.function = clockdev_fn; vcpu->arch.tsk = current; - - vcpu->arch.vcb.soft_cid = vcpu->vcpu_id; - vcpu->arch.vcb.vcpu_irq_disabled = 1; vcpu->arch.pcpu_id = -1; /* force flush tlb for the first time */ return 0; -- Gitee From bea2a7b9184594c0b31cb36e1bbba72e72a3d0ee Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Sun, 28 Apr 2024 10:36:54 +0800 Subject: [PATCH 041/100] anolis: sw64: kvm: use generic kvm mmu memory caches ANBZ: #4688 Switch to the generic MMU memory cache implementation. Besides, setting pud, pmd and pte page tables will call mmu_memory_cache_alloc() to request memory cache pages, so increase KVM_MMU_CACHE_MIN_PAGES to 3 to avoid kernel panic. Signed-off-by: Chen Wang Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/Kbuild | 1 - arch/sw_64/include/asm/kvm_host.h | 11 ------- arch/sw_64/include/asm/kvm_mmu.h | 2 +- arch/sw_64/include/asm/kvm_types.h | 7 ++++ arch/sw_64/kvm/mmu.c | 53 +++++------------------------- arch/sw_64/kvm/sw64.c | 3 +- 6 files changed, 18 insertions(+), 59 deletions(-) create mode 100644 arch/sw_64/include/asm/kvm_types.h diff --git a/arch/sw_64/include/asm/Kbuild b/arch/sw_64/include/asm/Kbuild index 0dd0a704d8f1..e9cbabda1516 100644 --- a/arch/sw_64/include/asm/Kbuild +++ b/arch/sw_64/include/asm/Kbuild @@ -2,7 +2,6 @@ generic-y += clkdev.h generic-y += export.h -generic-y += kvm_types.h generic-y += mcs_spinlock.h generic-y += param.h generic-y += qrwlock.h diff --git a/arch/sw_64/include/asm/kvm_host.h b/arch/sw_64/include/asm/kvm_host.h index b726b0f5d94e..0ab02eb62e4e 100644 --- a/arch/sw_64/include/asm/kvm_host.h +++ b/arch/sw_64/include/asm/kvm_host.h @@ -76,17 +76,6 @@ struct kvm_arch { pgd_t *pgd; }; -#define KVM_NR_MEM_OBJS 40 - -/* - * We don't want allocation failures within the mmu code, so we preallocate - * enough memory for a single page fault in a cache. - */ -struct kvm_mmu_memory_cache { - int nobjs; - void *objects[KVM_NR_MEM_OBJS]; -}; - struct kvm_vcpu_arch { struct kvm_regs regs __aligned(32); struct vcpucb vcb; diff --git a/arch/sw_64/include/asm/kvm_mmu.h b/arch/sw_64/include/asm/kvm_mmu.h index f137e1c39e0c..94fe863ccafd 100644 --- a/arch/sw_64/include/asm/kvm_mmu.h +++ b/arch/sw_64/include/asm/kvm_mmu.h @@ -29,7 +29,7 @@ #define AF_STATUS_FOE 0x8 #define AF_STATUS_INV 0x10 -#define KVM_MMU_CACHE_MIN_PAGES 2 +#define KVM_MMU_CACHE_MIN_PAGES 3 static inline void kvm_set_aptpte_readonly(pte_t *pte) { diff --git a/arch/sw_64/include/asm/kvm_types.h b/arch/sw_64/include/asm/kvm_types.h new file mode 100644 index 000000000000..c527d02eaddb --- /dev/null +++ b/arch/sw_64/include/asm/kvm_types.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_SW64_KVM_TYPES_H +#define _ASM_SW64_KVM_TYPES_H + +#define KVM_ARCH_NR_OBJS_PER_MEMORY_CACHE 40 + +#endif /* _ASM_SW64_KVM_TYPES_H */ diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index c02baa04a221..14c8c913ceb4 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -101,43 +101,6 @@ static void apt_dissolve_pud(struct kvm *kvm, phys_addr_t addr, pud_t *pudp) put_page(virt_to_page(pudp)); } -static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache, - int min, int max) -{ - void *page; - - BUG_ON(max > KVM_NR_MEM_OBJS); - if (cache->nobjs >= min) - return 0; - while (cache->nobjs < max) { - page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO); - if (!page) - return -ENOMEM; - cache->objects[cache->nobjs++] = page; - } - return 0; -} - -static void mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc) -{ - while (mc->nobjs) - free_page((unsigned long)mc->objects[--mc->nobjs]); -} - -void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu) -{ - mmu_free_memory_cache(&vcpu->arch.mmu_page_cache); -} - -static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc) -{ - void *p; - - BUG_ON(!mc || !mc->nobjs); - p = mc->objects[--mc->nobjs]; - return p; -} - static void unmap_apt_ptes(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr, phys_addr_t end) { @@ -362,7 +325,7 @@ static pud_t *apt_get_pud(pgd_t *pgd, struct kvm_mmu_memory_cache *cache, if (p4d_none(*p4d)) { if (!cache) return NULL; - pud = mmu_memory_cache_alloc(cache); + pud = kvm_mmu_memory_cache_alloc(cache); p4d_populate(NULL, p4d, pud); get_page(virt_to_page(p4d)); } @@ -382,7 +345,7 @@ static pmd_t *apt_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, if (pud_none(*pud)) { if (!cache) return NULL; - pmd = mmu_memory_cache_alloc(cache); + pmd = kvm_mmu_memory_cache_alloc(cache); pud_populate(NULL, pud, pmd); get_page(virt_to_page(pud)); } @@ -840,7 +803,7 @@ static int apt_set_pte_fast(struct kvm_vcpu *vcpu, if (pud_none(*pud)) { if (!cache) return 0; /* ignore calls from kvm_set_spte_hva */ - pmd = mmu_memory_cache_alloc(cache); + pmd = kvm_mmu_memory_cache_alloc(cache); pud_populate(NULL, pud, pmd); get_page(virt_to_page(pud)); } @@ -866,7 +829,7 @@ static int apt_set_pte_fast(struct kvm_vcpu *vcpu, if (pmd_none(*pmd)) { if (!cache) return 0; /* ignore calls from kvm_set_spte_hva */ - pte = mmu_memory_cache_alloc(cache); + pte = kvm_mmu_memory_cache_alloc(cache); pmd_populate_kernel(NULL, pmd, pte); get_page(virt_to_page(pmd)); } @@ -928,7 +891,7 @@ static int apt_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, if (pud_none(*pud)) { if (!cache) return 0; /* ignore calls from kvm_set_spte_hva */ - pmd = mmu_memory_cache_alloc(cache); + pmd = kvm_mmu_memory_cache_alloc(cache); pud_populate(NULL, pud, pmd); get_page(virt_to_page(pud)); } @@ -953,7 +916,7 @@ static int apt_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, if (pmd_none(*pmd)) { if (!cache) return 0; /* ignore calls from kvm_set_spte_hva */ - pte = mmu_memory_cache_alloc(cache); + pte = kvm_mmu_memory_cache_alloc(cache); pmd_populate_kernel(NULL, pmd, pte); get_page(virt_to_page(pmd)); } @@ -1199,8 +1162,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, gfn = (fault_gpa & huge_page_mask(hstate_vma(vma))) >> PAGE_SHIFT; up_read(¤t->mm->mmap_lock); /* We need minimum second+third level pages */ - ret = mmu_topup_memory_cache(memcache, KVM_MMU_CACHE_MIN_PAGES, - KVM_NR_MEM_OBJS); + ret = kvm_mmu_topup_memory_cache(memcache, KVM_MMU_CACHE_MIN_PAGES); + if (ret) return ret; diff --git a/arch/sw_64/kvm/sw64.c b/arch/sw_64/kvm/sw64.c index 86189243fc75..4cf57af96eae 100644 --- a/arch/sw_64/kvm/sw64.c +++ b/arch/sw_64/kvm/sw64.c @@ -258,7 +258,7 @@ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) { - kvm_mmu_free_memory_caches(vcpu); + kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache); hrtimer_cancel(&vcpu->arch.hrt); } @@ -272,6 +272,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) /* Set up the timer for Guest */ pr_info("vcpu: [%d], regs addr = %#lx, vcpucb = %#lx\n", vcpu->vcpu_id, (unsigned long)&vcpu->arch.regs, (unsigned long)&vcpu->arch.vcb); + vcpu->arch.mmu_page_cache.gfp_zero = __GFP_ZERO; vcpu->arch.vtimer_freq = cpuid(GET_CPU_FREQ, 0) * 1000UL * 1000UL; hrtimer_init(&vcpu->arch.hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS); vcpu->arch.hrt.function = clockdev_fn; -- Gitee From 3624c4687bf5674bdb88bfb1fe28268e552648de Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 30 Apr 2024 14:42:20 +0800 Subject: [PATCH 042/100] anolis: sw64: kvm: acpi: match sunway_ged by acpi method ANBZ: #4688 Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/misc/sunway-ged.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/misc/sunway-ged.c b/drivers/misc/sunway-ged.c index aa500421355d..516770036962 100644 --- a/drivers/misc/sunway-ged.c +++ b/drivers/misc/sunway-ged.c @@ -2,6 +2,7 @@ /* Generic Event Device for ACPI. */ +#include #include #include #include @@ -236,10 +237,19 @@ static const struct of_device_id sunwayged_of_match[] = { }; MODULE_DEVICE_TABLE(of, sunwayged_of_match); +#ifdef CONFIG_ACPI +static const struct acpi_device_id sunwayged_acpi_match[] = { + { "SUNW1000", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, sunwayged_acpi_match); +#endif + static struct platform_driver sunwayged_platform_driver = { .driver = { .name = "sunway-ged", .of_match_table = sunwayged_of_match, + .acpi_match_table = ACPI_PTR(sunwayged_acpi_match), }, .probe = sunwayged_probe, .remove = sunwayged_remove, -- Gitee From 0f420c6497c587d217e6fd6c8ec18c6c1544c748 Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Tue, 14 May 2024 14:32:39 +0800 Subject: [PATCH 043/100] anolis: sw64: kvm: fix bug when vcpu disable irq ANBZ: #4688 Vcpu should not wake up when its irq disabled, unless a NMII interrupt is received, that is, the restart flag is set to ture. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/sw64.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/sw_64/kvm/sw64.c b/arch/sw_64/kvm/sw64.c index 4cf57af96eae..7305d060bb2e 100644 --- a/arch/sw_64/kvm/sw64.c +++ b/arch/sw_64/kvm/sw64.c @@ -169,6 +169,12 @@ struct dfx_sw64_kvm_stats_debugfs_item dfx_sw64_debugfs_entries[] = { int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) { + if (vcpu->arch.restart) + return 1; + + if (vcpu->arch.vcb.vcpu_irq_disabled) + return 0; + return ((!bitmap_empty(vcpu->arch.irqs_pending, SWVM_IRQS) || !vcpu->arch.halted) && !vcpu->arch.power_off); } -- Gitee From 3ebff4d78ee5ab5c5c3d5de0e0bceb295b74b56d Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Wed, 22 May 2024 13:33:45 +0800 Subject: [PATCH 044/100] anolis: sw64: kvm: add numa support for memory hotplug ANBZ: #4688 Memory hotplug node id was always 0 in the past. Since vNUMA is supported, this patch adds 'node' into struct sunway_memory_device to hold numa node id which is prepared by Qemu, and then memory hotplug interfaces can handle argument nid correctly. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/misc/sunway-ged.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/misc/sunway-ged.c b/drivers/misc/sunway-ged.c index 516770036962..f2fda9f0dcb0 100644 --- a/drivers/misc/sunway-ged.c +++ b/drivers/misc/sunway-ged.c @@ -12,11 +12,14 @@ #include #include +/* offset should be the same as QEMU */ #define OFFSET_START_ADDR 0 #define OFFSET_LENGTH 8 #define OFFSET_STATUS 16 #define OFFSET_SLOT 24 +#define OFFSET_NODE 40 + /* Memory hotplug event */ #define SUNWAY_MEMHOTPLUG_ADD 0x1 #define SUNWAY_MEMHOTPLUG_REMOVE 0x2 @@ -29,6 +32,7 @@ struct sunway_memory_device { u64 start_addr; /* Memory Range start physical addr */ u64 length; /* Memory Range length */ u64 slot; /* Memory Range slot */ + u64 node; /* Memory Range node */ unsigned int enabled:1; }; @@ -59,7 +63,7 @@ static int sunway_memory_enable_device(struct sunway_memory_device *mem_device) lock_device_hotplug(); /* suppose node = 0, fix me! */ - result = __add_memory(0, mem_device->start_addr, mem_device->length, MHP_NONE); + result = __add_memory(mem_device->node, mem_device->start_addr, mem_device->length, MHP_NONE); unlock_device_hotplug(); /* * If the memory block has been used by the kernel, add_memory() @@ -106,7 +110,7 @@ static int sunway_memory_get_meminfo(struct sunway_memory_device *mem_device) static void sunway_memory_device_remove(struct sunway_ged_device *device) { struct sunway_memory_device *mem_dev, *n; - unsigned long start_addr, length, slot; + unsigned long start_addr, length, slot, node; if (!device) return; @@ -114,6 +118,7 @@ static void sunway_memory_device_remove(struct sunway_ged_device *device) start_addr = readq(device->membase + OFFSET_START_ADDR); length = readq(device->membase + OFFSET_LENGTH); slot = readq(device->membase + OFFSET_SLOT); + node = readq(device->membase + OFFSET_NODE); list_for_each_entry_safe(mem_dev, n, &device->dev_list, list) { if (!mem_dev->enabled) @@ -122,7 +127,7 @@ static void sunway_memory_device_remove(struct sunway_ged_device *device) if ((start_addr == mem_dev->start_addr) && (length == mem_dev->length)) { /* suppose node = 0, fix me! */ - remove_memory(0, start_addr, length); + remove_memory(node, start_addr, length); list_del(&mem_dev->list); kfree(mem_dev); } @@ -150,6 +155,7 @@ static int sunway_memory_device_add(struct sunway_ged_device *device) mem_device->start_addr = readq(device->membase + OFFSET_START_ADDR); mem_device->length = readq(device->membase + OFFSET_LENGTH); mem_device->slot = readq(device->membase + OFFSET_SLOT); + mem_device->node = readq(device->membase + OFFSET_NODE); result = sunway_memory_enable_device(mem_device); if (result) { -- Gitee From 7dc0adc30269259c970730e28773ea3e1b1fa176 Mon Sep 17 00:00:00 2001 From: Deng Xiaoyun Date: Thu, 9 May 2024 09:24:24 +0800 Subject: [PATCH 045/100] anolis: sw64: fix guest send ipi target ANBZ: #4688 For guest os, the target cpu id of IPI is vcpuid, and when vNUMA is supported, vcpuid is not equal to rcid. Signed-off-by: Deng Xiaoyun Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/smp.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/sw_64/include/asm/smp.h b/arch/sw_64/include/asm/smp.h index 130c52c9e306..33a73ca25a6b 100644 --- a/arch/sw_64/include/asm/smp.h +++ b/arch/sw_64/include/asm/smp.h @@ -122,12 +122,12 @@ static inline void send_ipi(int cpu, unsigned long type) { int rcid; - rcid = cpu_to_rcid(cpu); - if (is_in_guest()) - hcall(HCALL_IVI, rcid, type, 0); - else + hcall(HCALL_IVI, cpu, type, 0); + else { + rcid = cpu_to_rcid(cpu); sendii(rcid, type, 0); + } } #define reset_cpu(cpu) send_ipi((cpu), II_RESET) -- Gitee From 5665fd9d4032d93d93a92a3c64a9a9997a9abbfa Mon Sep 17 00:00:00 2001 From: Xu Linqin Date: Tue, 21 May 2024 18:11:13 +0800 Subject: [PATCH 046/100] anolis: sw64: kvm: implement kvm_arch_set_irq_inatomic() ANBZ: #4688 kvm_arch_set_irq_inatomic() is used in irqfd_wakeup() which is required by qemu to notify guest by irqfd. This patch improves IO performance of guest os because it injects irq directly instead of being scheduled. The virtualization rate has increased by 20% in guest randread/randwrite IOPS test when using SATA SSD. Signed-off-by: Xu Linqin Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/sw64.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/sw_64/kvm/sw64.c b/arch/sw_64/kvm/sw64.c index 7305d060bb2e..a22a7f78c2cb 100644 --- a/arch/sw_64/kvm/sw64.c +++ b/arch/sw_64/kvm/sw64.c @@ -42,6 +42,21 @@ static unsigned long get_new_vpn_context(struct kvm_vcpu *vcpu, long cpu) return next; } +int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int irq_source_id, + int level, bool line_status) +{ + switch (e->type) { + case KVM_IRQ_ROUTING_MSI: + if (!kvm_set_msi(e, kvm, irq_source_id, level, line_status)) + return 0; + break; + default: + break; + } + return -EWOULDBLOCK; +} + int vcpu_interrupt_line(struct kvm_vcpu *vcpu, int number, bool level) { set_bit(number, (vcpu->arch.irqs_pending)); -- Gitee From 925512c85badbbb0f745e185d59a229637514415 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Thu, 23 May 2024 15:00:25 +0800 Subject: [PATCH 047/100] anolis: sw64: kvm: fix inconsistent vcpucb of C4 ANBZ: #4688 The position of shtclock_offset in struct vcpucb is inconsistent between kvm and hmcode, leading to wrong SHTCLOCK after migration. Fix its position to solve the problem. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/vcpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/include/asm/vcpu.h b/arch/sw_64/include/asm/vcpu.h index 8227166d6998..b2ab8c7f8b86 100644 --- a/arch/sw_64/include/asm/vcpu.h +++ b/arch/sw_64/include/asm/vcpu.h @@ -97,9 +97,9 @@ struct vcpucb { unsigned long exit_reason; unsigned long fault_gpa; /* CSR:EXC_GPA */ unsigned long vcpu_pc_save; - unsigned long shtclock_offset; unsigned long migration_mark; unsigned long shtclock; + unsigned long shtclock_offset; unsigned long csr_pc; unsigned long csr_ps; unsigned long csr_sp; -- Gitee From 72521c1d4ae4a2656a493593a75d86b9fefd4464 Mon Sep 17 00:00:00 2001 From: Deng Xiaoyun Date: Mon, 13 May 2024 18:50:02 +0800 Subject: [PATCH 048/100] anolis: sw64: kvm: support up to 256 vCPUs for C4 ANBZ: #4688 Signed-off-by: Deng Xiaoyun Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/kvm_host.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/include/asm/kvm_host.h b/arch/sw_64/include/asm/kvm_host.h index 0ab02eb62e4e..66434307523d 100644 --- a/arch/sw_64/include/asm/kvm_host.h +++ b/arch/sw_64/include/asm/kvm_host.h @@ -33,18 +33,19 @@ #ifdef CONFIG_SUBARCH_C3B #define VPN_BITS 8 #define GUEST_RESET_PC 0xffffffff80011100 +#define KVM_MAX_VCPUS 64 #endif #ifdef CONFIG_SUBARCH_C4 #define VPN_BITS 10 #define GUEST_RESET_PC 0xfff0000000011002 +#define KVM_MAX_VCPUS 256 #endif #define VPN_FIRST_VERSION (1UL << VPN_BITS) #define VPN_MASK ((1UL << VPN_BITS) - 1) #define VPN_SHIFT (64 - VPN_BITS) -#define KVM_MAX_VCPUS 64 #define KVM_INTERNAL_MEM_SLOTS (KVM_MEM_SLOTS_NUM - 512) #define KVM_HALT_POLL_NS_DEFAULT 0 -- Gitee From 848ef916c58c7f015cd711b61b66b146ddb8aa89 Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Wed, 29 May 2024 10:56:03 +0800 Subject: [PATCH 049/100] anolis: sw64: add cpu hotplug support for C4 guest ANBZ: #4688 Qemu emulate IOR:VT_ONLINE_CPU to pass current online vCPUs to guest, which is used to initialize cpu_offline mask for C4 guest. Add sunway_cpu_device_add() and sunway_cpu_device_del() to sunway-ged driver to support cpu hotplug for C4 guest. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/uncore_io_junzhang.h | 1 + arch/sw_64/kernel/acpi.c | 12 ++++++ arch/sw_64/kernel/smp.c | 11 +++++ drivers/misc/sunway-ged.c | 48 ++++++++++++++++++++- 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/include/asm/uncore_io_junzhang.h b/arch/sw_64/include/asm/uncore_io_junzhang.h index 770af3907b5c..f553d2f61e64 100644 --- a/arch/sw_64/include/asm/uncore_io_junzhang.h +++ b/arch/sw_64/include/asm/uncore_io_junzhang.h @@ -100,6 +100,7 @@ enum { /* SPBU CSR */ enum { SMP_INFO = SPBU_BASE | 0x80UL, + VT_ONLINE_CPU = SPBU_BASE | 0x100UL, INIT_CTL = SPBU_BASE | 0x680UL, CORE_ONLINE = SPBU_BASE | 0x780UL, DLI_RLTD_FAULT = SPBU_BASE | 0x980UL, diff --git a/arch/sw_64/kernel/acpi.c b/arch/sw_64/kernel/acpi.c index 990db687657e..23b5a90cc7b2 100644 --- a/arch/sw_64/kernel/acpi.c +++ b/arch/sw_64/kernel/acpi.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -331,6 +332,17 @@ static int __init acpi_process_madt_sw_cintc(void) init_cpu_possible(cpu_none_mask); init_cpu_present(cpu_none_mask); +#ifdef CONFIG_SUBARCH_C4 + /* Set cpu_offline mask */ + if (is_guest_or_emul()) { + int vt_smp_cpu_num; + + vt_smp_cpu_num = sw64_io_read(0, VT_ONLINE_CPU); + for (i = vt_smp_cpu_num; i < KVM_MAX_VCPUS; i++) + cpumask_set_cpu(i, &cpu_offline); + } +#endif + /* Parse SW CINTC entries one by one */ ret = acpi_table_parse_madt(ACPI_MADT_TYPE_SW_CINTC, acpi_parse_sw_cintc, 0); diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 699c63fbd38d..1871196ff378 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -283,6 +284,15 @@ static int __init fdt_setup_smp(void) init_cpu_possible(cpu_none_mask); init_cpu_present(cpu_none_mask); +#ifdef CONFIG_SUBARCH_C4 + if (is_guest_or_emul()) { + int vt_smp_cpu_num; + + vt_smp_cpu_num = sw64_io_read(0, VT_ONLINE_CPU); + for (i = vt_smp_cpu_num; i < KVM_MAX_VCPUS; i++) + cpumask_set_cpu(i, &cpu_offline); + } +#endif while ((dn = of_find_node_by_type(dn, "cpu"))) { if (!of_device_is_available(dn)) { pr_info("OF: Core is not available\n"); @@ -794,6 +804,7 @@ void arch_cpu_idle_dead(void) if (is_in_guest()) { hcall(HCALL_SET_CLOCKEVENT, 0, 0, 0); hcall(HCALL_STOP, 0, 0, 0); + return; } else { wrtimer(0); } diff --git a/drivers/misc/sunway-ged.c b/drivers/misc/sunway-ged.c index f2fda9f0dcb0..c59d377ec8e5 100644 --- a/drivers/misc/sunway-ged.c +++ b/drivers/misc/sunway-ged.c @@ -18,11 +18,17 @@ #define OFFSET_STATUS 16 #define OFFSET_SLOT 24 +#define OFFSET_CPUID 32 + #define OFFSET_NODE 40 /* Memory hotplug event */ #define SUNWAY_MEMHOTPLUG_ADD 0x1 #define SUNWAY_MEMHOTPLUG_REMOVE 0x2 +/* Cpu hotplug event */ +#define SUNWAY_CPUHOTPLUG_ADD 0x4 +#define SUNWAY_CPUHOTPLUG_REMOVE 0x8 + struct sunway_memory_device { struct sunway_ged_device *device; @@ -171,12 +177,52 @@ static int sunway_memory_device_add(struct sunway_ged_device *device) return 1; } +static int sunway_cpu_device_add(struct sunway_ged_device *device) +{ + struct device *dev; + int cpuid; + + cpuid = readq(device->membase + OFFSET_CPUID); + + if (!device) + return -EINVAL; + set_cpu_present(cpuid, true); + dev = get_cpu_device(cpuid); + if (device_attach(dev) >= 0) + return 1; + dev_err(dev, "Processor driver could not be attached\n"); + set_cpu_present(cpuid, false); + return 0; +} + +static void sunway_cpu_device_del(struct sunway_ged_device *device) +{ + struct device *dev; + int cpuid; + + cpuid = readq(device->membase + OFFSET_CPUID); + + if (!device) + return; + set_cpu_present(cpuid, false); + dev = get_cpu_device(cpuid); + device_release_driver(dev); + + writeq(cpuid, device->membase + OFFSET_CPUID); +} + static irqreturn_t sunwayged_ist(int irq, void *data) { struct sunway_ged_device *sunwayged_dev = data; unsigned int status; - status = readl(sunwayged_dev->membase + OFFSET_STATUS); + status = readq(sunwayged_dev->membase + OFFSET_STATUS); + /* through IO status to add or remove cpu */ + if (status & SUNWAY_CPUHOTPLUG_ADD) + sunway_cpu_device_add(sunwayged_dev); + + if (status & SUNWAY_CPUHOTPLUG_REMOVE) + sunway_cpu_device_del(sunwayged_dev); /* through IO status to add or remove memory device */ if (status & SUNWAY_MEMHOTPLUG_ADD) -- Gitee From 1e7230ae4ddc068a01be0883318abb2cd0de724c Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Tue, 28 May 2024 13:59:12 +0800 Subject: [PATCH 050/100] anolis: sw64: Kconfig: activate ARCH_KEEP_MEMBLOCK ANBZ: #4688 This patch activates ARCH_KEEP_MEMBLOCK which add new memblock region within a NUMA node to 'memory' type. It fixes potential offnode page_structs warnings when new memory is added and used for page_structs. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 9211ece4824c..6c2f0da276cc 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -44,6 +44,7 @@ config SW64 select ARCH_INLINE_WRITE_UNLOCK_BH select ARCH_INLINE_WRITE_UNLOCK_IRQ select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE + select ARCH_KEEP_MEMBLOCK select ARCH_NO_PREEMPT select ARCH_SUPPORTS_ACPI select ARCH_SUPPORTS_ATOMIC_RMW -- Gitee From cf610e0abb82608ae09de8c471cdd691ce994b7b Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Tue, 28 May 2024 15:13:10 +0800 Subject: [PATCH 051/100] anolis: sw64: remove unused sunway_memory_get_meminfo() ANBZ: #4688 This function is no longer used, so remove it. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/misc/sunway-ged.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/drivers/misc/sunway-ged.c b/drivers/misc/sunway-ged.c index c59d377ec8e5..7d0b6f7fc682 100644 --- a/drivers/misc/sunway-ged.c +++ b/drivers/misc/sunway-ged.c @@ -95,24 +95,6 @@ static int sunway_memory_enable_device(struct sunway_memory_device *mem_device) return 0; } -static int sunway_memory_get_meminfo(struct sunway_memory_device *mem_device) -{ - struct sunway_ged_device *geddev; - - if (!mem_device) - return -EINVAL; - - if (mem_device->enabled) - return 0; - - geddev = mem_device->device; - - mem_device->start_addr = readq(geddev->membase + OFFSET_START_ADDR); - mem_device->length = readq(geddev->membase + OFFSET_LENGTH); - - return 0; -} - static void sunway_memory_device_remove(struct sunway_ged_device *device) { struct sunway_memory_device *mem_dev, *n; -- Gitee From b26b0c309975fb8d0e2ebde85bbbe63846626b9d Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Tue, 28 May 2024 15:32:34 +0800 Subject: [PATCH 052/100] anolis: sw64: fix compile error with CONFIG_SUNWAY_GED=m ANBZ: #4688 Fix the following errors: ERROR: modpost: "unlock_device_hotplug" [drivers/misc/sunway-ged.ko] undefined! ERROR: modpost: "__add_memory" [drivers/misc/sunway-ged.ko] undefined! ERROR: modpost: "lock_device_hotplug" [drivers/misc/sunway-ged.ko] undefined! Fixes: 51f31c3271e5 ("anolis: sw64: add memhotplug support for guest os") Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/misc/sunway-ged.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/misc/sunway-ged.c b/drivers/misc/sunway-ged.c index 7d0b6f7fc682..e2cd2218518b 100644 --- a/drivers/misc/sunway-ged.c +++ b/drivers/misc/sunway-ged.c @@ -67,10 +67,7 @@ static int sunway_memory_enable_device(struct sunway_memory_device *mem_device) if (!mem_device->length) goto out; - lock_device_hotplug(); - /* suppose node = 0, fix me! */ - result = __add_memory(mem_device->node, mem_device->start_addr, mem_device->length, MHP_NONE); - unlock_device_hotplug(); + result = add_memory(mem_device->node, mem_device->start_addr, mem_device->length, MHP_NONE); /* * If the memory block has been used by the kernel, add_memory() * returns -EEXIST. If add_memory() returns the other error, it -- Gitee From 00e94760aec6f5d93e4fa815760f126dfb9633ac Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Tue, 28 May 2024 13:39:20 +0800 Subject: [PATCH 053/100] anolis: sw64: add dependency for sunway-ged driver ANBZ: #4688 Both memory hotplug and cpu hotplug are implemented through sunway-ged driver, so make SUNWAY_GED depend on MEMORY_HOTPLUG || HOTPLUG_CPU. On ther other hand, cpu hotplug and memory cpuplug are independt, so necessary #if guards have to be added to wrap corresponding codes. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/misc/Kconfig | 7 ++++--- drivers/misc/sunway-ged.c | 8 ++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 1e9def44eb09..2916a2ac3804 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -377,12 +377,13 @@ config HMC6352 providing configuration and heading data via sysfs. config SUNWAY_GED - tristate "sunway generic device driver for memhotplug" + tristate "sunway generic device driver for memhotplug and cpuhotplug" depends on SW64 - depends on MEMORY_HOTPLUG + depends on MEMORY_HOTPLUG || HOTPLUG_CPU help This driver provides support for sunway generic device driver for - memhotplug, providing configuration and heading data via sysfs. + memhotplug and cpuhotplug, providing configuration and heading + data via sysfs. config DS1682 tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm" diff --git a/drivers/misc/sunway-ged.c b/drivers/misc/sunway-ged.c index e2cd2218518b..14d7ed3d3d92 100644 --- a/drivers/misc/sunway-ged.c +++ b/drivers/misc/sunway-ged.c @@ -50,6 +50,7 @@ struct sunway_ged_device { struct list_head dev_list; }; +#ifdef CONFIG_MEMORY_HOTPLUG static int sunway_memory_enable_device(struct sunway_memory_device *mem_device) { int num_enabled = 0; @@ -155,7 +156,9 @@ static int sunway_memory_device_add(struct sunway_ged_device *device) return 1; } +#endif +#ifdef CONFIG_HOTPLUG_CPU static int sunway_cpu_device_add(struct sunway_ged_device *device) { struct device *dev; @@ -189,6 +192,7 @@ static void sunway_cpu_device_del(struct sunway_ged_device *device) writeq(cpuid, device->membase + OFFSET_CPUID); } +#endif static irqreturn_t sunwayged_ist(int irq, void *data) { @@ -196,19 +200,23 @@ static irqreturn_t sunwayged_ist(int irq, void *data) unsigned int status; status = readq(sunwayged_dev->membase + OFFSET_STATUS); +#ifdef CONFIG_HOTPLUG_CPU /* through IO status to add or remove cpu */ if (status & SUNWAY_CPUHOTPLUG_ADD) sunway_cpu_device_add(sunwayged_dev); if (status & SUNWAY_CPUHOTPLUG_REMOVE) sunway_cpu_device_del(sunwayged_dev); +#endif +#ifdef CONFIG_MEMORY_HOTPLUG /* through IO status to add or remove memory device */ if (status & SUNWAY_MEMHOTPLUG_ADD) sunway_memory_device_add(sunwayged_dev); if (status & SUNWAY_MEMHOTPLUG_REMOVE) sunway_memory_device_remove(sunwayged_dev); +#endif return IRQ_HANDLED; } -- Gitee From 17834c8dc95f79e1ea8cc8c5fa029d7907f597ba Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Mon, 17 Jun 2024 14:37:46 +0800 Subject: [PATCH 054/100] anolis: sw64: kvm: fix build failure about KVM ANBZ: #4688 This patch: - built in kvm_cma.c to fix: arch/sw_64/mm/init.o: In function `sw64_kvm_reserve': (.init.text+0x424): undefined reference to `kvm_cma_declare_contiguous' - use Makefile.kvm for common files to avoid: virt/kvm/kvm_main.o: In function `kvm_vcpu_stats_read': (.text+0x3da4): undefined reference to `kvm_stats_read' Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/sw_64/kvm/Makefile b/arch/sw_64/kvm/Makefile index 8f594155f352..40f700f1a657 100644 --- a/arch/sw_64/kvm/Makefile +++ b/arch/sw_64/kvm/Makefile @@ -9,8 +9,7 @@ include $(srctree)/virt/kvm/Makefile.kvm obj-$(CONFIG_KVM) += kvm.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-y += 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_C3B) += kvm_core3.o entry_core3.o kvm_cma.o kvm-$(CONFIG_SUBARCH_C4) += kvm_core4.o mmu.o entry_core4.o -- Gitee From 09cae72298adb70a7c7ffa9c1970e517ded2d10a Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Mon, 17 Jun 2024 15:02:19 +0800 Subject: [PATCH 055/100] anolis: sw64: kvm: fix link error with CONFIG_KVM=m ANBZ: #4688 Move kvm_cma.c to the arch/sw_64/kernel/ directory to fix: arch/sw_64/kvm/kvm_cma.o: In function `kvm_cma_init_reserved_areas': (.init.text+0x0): multiple definition of `init_module' arch/sw_64/kvm/kvm_core3.o:(.init.text+0x68): first defined here scripts/Makefile.build:438: recipe for target 'arch/sw_64/kvm/kvm.o' failed make[4]: *** [arch/sw_64/kvm/kvm.o] Error 1 Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/Makefile | 4 ++++ arch/sw_64/{kvm => kernel}/kvm_cma.c | 0 arch/sw_64/kvm/Makefile | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) rename arch/sw_64/{kvm => kernel}/kvm_cma.c (100%) diff --git a/arch/sw_64/kernel/Makefile b/arch/sw_64/kernel/Makefile index 57124b8546ec..b5756003776f 100644 --- a/arch/sw_64/kernel/Makefile +++ b/arch/sw_64/kernel/Makefile @@ -40,6 +40,10 @@ ifndef CONFIG_PCI obj-y += pci-noop.o endif +ifdef CONFIG_KVM +obj-$(CONFIG_SUBARCH_C3B) += kvm_cma.o +endif + # Core logic support obj-$(CONFIG_SW64_CPUAUTOPLUG) += cpuautoplug.o diff --git a/arch/sw_64/kvm/kvm_cma.c b/arch/sw_64/kernel/kvm_cma.c similarity index 100% rename from arch/sw_64/kvm/kvm_cma.c rename to arch/sw_64/kernel/kvm_cma.c diff --git a/arch/sw_64/kvm/Makefile b/arch/sw_64/kvm/Makefile index 40f700f1a657..530170e9167d 100644 --- a/arch/sw_64/kvm/Makefile +++ b/arch/sw_64/kvm/Makefile @@ -11,5 +11,5 @@ obj-$(CONFIG_KVM) += kvm.o kvm-y += 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_cma.o +kvm-$(CONFIG_SUBARCH_C3B) += kvm_core3.o entry_core3.o kvm-$(CONFIG_SUBARCH_C4) += kvm_core4.o mmu.o entry_core4.o -- Gitee From a9beb8e568a2e4168e27c319c80781ffa2d33f41 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 18 Jun 2024 14:10:02 +0800 Subject: [PATCH 056/100] anolis: sw64: kvm: fix NULL poniter access in kvm_arch_prepare_memory_region ANBZ: #4688 'struct kvm_memory_slot *new' in kvm_arch_prepare_memory_region() should not be accessed if there is no memory slot creating, or it will result in kernel Oops due to the null *new. This patch also delete some unused codes. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/kvm_core3.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/sw_64/kvm/kvm_core3.c b/arch/sw_64/kvm/kvm_core3.c index b9a5019ee9c0..364cabdd6407 100644 --- a/arch/sw_64/kvm/kvm_core3.c +++ b/arch/sw_64/kvm/kvm_core3.c @@ -113,14 +113,13 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, unsigned long ret; size_t size; - mem->flags = new->flags; + if (change == KVM_MR_FLAGS_ONLY || change == KVM_MR_DELETE) + return 0; + mem->guest_phys_addr = ((new->base_gfn) << PAGE_SHIFT); mem->memory_size = ((new->npages) << PAGE_SHIFT); mem->userspace_addr = new->userspace_addr; - if (change == KVM_MR_FLAGS_ONLY || change == KVM_MR_DELETE) - return 0; - if (test_bit(IO_MARK_BIT, (unsigned long *)(&(mem->guest_phys_addr)))) return 0; -- Gitee From 0b2fb4a623f11fbe335c8114d485e2e5ee21427e Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 18 Jun 2024 15:18:56 +0800 Subject: [PATCH 057/100] anolis: sw64: kvm: fix the handling when the live migration fails ANBZ: #4688 To ensure that the source guest can still run properly when live migration fails, it is necessary to clear migration_mark and do tlb flush during kvm_arch_commit_memory_region(). Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/kvm_core3.c | 9 ++++++++- arch/sw_64/kvm/mmu.c | 5 +++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/arch/sw_64/kvm/kvm_core3.c b/arch/sw_64/kvm/kvm_core3.c index 364cabdd6407..355d7697c535 100644 --- a/arch/sw_64/kvm/kvm_core3.c +++ b/arch/sw_64/kvm/kvm_core3.c @@ -208,9 +208,16 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, * memory slot is write protected. */ + /* If dirty logging has been stopped, clear migration_mark for now. */ + if ((change == KVM_MR_FLAGS_ONLY) && (old->flags & KVM_MEM_LOG_DIRTY_PAGES) + && (!(new->flags & KVM_MEM_LOG_DIRTY_PAGES))) { + kvm_mark_migration(kvm, 0); + return; + } /* If it's the first time dirty logging, flush all vcpu tlbs. */ - if ((change == KVM_MR_FLAGS_ONLY) && (new->flags & KVM_MEM_LOG_DIRTY_PAGES)) + if ((change == KVM_MR_FLAGS_ONLY) && (!(old->flags & KVM_MEM_LOG_DIRTY_PAGES)) + && (new->flags & KVM_MEM_LOG_DIRTY_PAGES)) kvm_mark_migration(kvm, 1); } diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 14c8c913ceb4..3b9b0b69e67a 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -528,8 +528,9 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, kvm_mark_migration(kvm, 1); kvm_mmu_wp_memory_region(kvm, new->id); } - /* If dirty logging has been stopped, do nothing for now. */ - if ((change != KVM_MR_DELETE) + + /* If dirty logging has been stopped, clear migration mark for now. */ + if ((change == KVM_MR_FLAGS_ONLY) && (old->flags & KVM_MEM_LOG_DIRTY_PAGES) && (!(new->flags & KVM_MEM_LOG_DIRTY_PAGES))) { kvm_mark_migration(kvm, 0); -- Gitee From 8ecda40f04c8cec3e76ea1590386be2bb0452cf7 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 25 Jun 2024 11:04:57 +0800 Subject: [PATCH 058/100] anolis: sw64: kvm: use get_page() instead of kvm_get_pfn() ANBZ: #4688 When mapping a THP, it can be guaranteed that the page isn't reserved and safely avoid the kvm_is_reserved_pfn() call. And, kvm_get_pfn() has been removed in commit 36c3ce6c0d03 ("KVM: Get rid of kvm_get_pfn()"), so replace it with get_page(pfn_to_page()). Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 3b9b0b69e67a..350930d871f0 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -1098,7 +1098,7 @@ transparent_hugepage_adjust(struct kvm_memory_slot *memslot, *gpap &= PMD_MASK; kvm_release_pfn_clean(pfn); pfn &= ~(PTRS_PER_PMD - 1); - kvm_get_pfn(pfn); + get_page(pfn_to_page(pfn)); *pfnp = pfn; return PMD_SIZE; } -- Gitee From 185fc9e9491e915b1098dfe702a3b60bc4e73a64 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 25 Jun 2024 13:37:20 +0800 Subject: [PATCH 059/100] anolis: sw64: kvm: fix compiler errors caused by mismatched parameters ANBZ: #4688 Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/kvm_core4.c | 6 +++--- arch/sw_64/kvm/mmu.c | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/sw_64/kvm/kvm_core4.c b/arch/sw_64/kvm/kvm_core4.c index a9d9326072e4..6d518f28950c 100644 --- a/arch/sw_64/kvm/kvm_core4.c +++ b/arch/sw_64/kvm/kvm_core4.c @@ -96,9 +96,9 @@ long kvm_sw64_set_vcb(struct file *filp, unsigned long arg) } int kvm_arch_prepare_memory_region(struct kvm *kvm, - struct kvm_memory_slot *memslot, - const struct kvm_userspace_memory_region *mem, - enum kvm_mr_change change) + const struct kvm_memory_slot *old, + struct kvm_memory_slot *new, + enum kvm_mr_change change) { return 0; } diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 350930d871f0..7f5de7c9c4ab 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -295,14 +295,14 @@ void apt_unmap_vm(struct kvm *kvm) { struct kvm_memslots *slots; struct kvm_memory_slot *memslot; - int idx; + int idx, bkt; idx = srcu_read_lock(&kvm->srcu); down_read(¤t->mm->mmap_lock); spin_lock(&kvm->mmu_lock); slots = kvm_memslots(kvm); - kvm_for_each_memslot(memslot, slots) + kvm_for_each_memslot(memslot, bkt, slots) apt_unmap_memslot(kvm, memslot); spin_unlock(&kvm->mmu_lock); up_read(¤t->mm->mmap_lock); @@ -1373,11 +1373,12 @@ static int handle_hva_to_gpa(struct kvm *kvm, unsigned long start, unsigned long struct kvm_memslots *slots; struct kvm_memory_slot *memslot; int ret = 0; + int bkt; slots = kvm_memslots(kvm); /* we only care about the pages that the guest sees */ - kvm_for_each_memslot(memslot, slots) { + kvm_for_each_memslot(memslot, bkt, slots) { unsigned long hva_start, hva_end; gfn_t gpa; -- Gitee From ae1b6624b7b141983c03aa58ab8f0a29f0baf06d Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 25 Jun 2024 13:53:06 +0800 Subject: [PATCH 060/100] anolis: sw64: kvm: rename mmu_notifier_* to mmu_invalidate_* ANBZ: #4688 Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 7f5de7c9c4ab..dafad9db62de 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -1085,7 +1085,7 @@ transparent_hugepage_adjust(struct kvm_memory_slot *memslot, * THP doesn't start to split while we are adjusting the * refcounts. * - * We are sure this doesn't happen, because mmu_notifier_retry + * We are sure this doesn't happen, because mmu_invalidate_retry * was successful and we are holding the mmu_lock, so if this * THP is trying to split, it will be blocked in the mmu * notifier before touching any of the pages, specifically @@ -1168,9 +1168,9 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, if (ret) return ret; - mmu_seq = vcpu->kvm->mmu_notifier_seq; + mmu_seq = vcpu->kvm->mmu_invalidate_seq; /* - * Ensure the read of mmu_notifier_seq happens before we call + * Ensure the read of mmu_invalidate_seq happens before we call * gfn_to_pfn_prot (which calls get_user_pages), so that we don't risk * the page we just got a reference to gets unmapped before we have a * chance to grab the mmu_lock, which ensure that if the page gets @@ -1205,7 +1205,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, } spin_lock(&kvm->mmu_lock); - if (mmu_notifier_retry(kvm, mmu_seq)) + if (mmu_invalidate_retry(kvm, mmu_seq)) goto out_unlock; /* -- Gitee From c9ca209039148270eac35a2546ca8be7ac4e3c90 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 25 Jun 2024 14:46:57 +0800 Subject: [PATCH 061/100] anolis: sw64: kvm: convert to the gfn-based MMU notifier callbacks ANBZ: #4688 Commit 3039bcc74498 ("KVM: Move x86's MMU notifier memslot walkers to generic code") has done the hva->gfn lookup in common code, so move sw64 to the gfn-base MMU notifier APIs too. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/kvm_host.h | 4 - arch/sw_64/kvm/mmu.c | 125 +++++++++--------------------- arch/sw_64/kvm/trace.h | 66 ---------------- 3 files changed, 35 insertions(+), 160 deletions(-) diff --git a/arch/sw_64/include/asm/kvm_host.h b/arch/sw_64/include/asm/kvm_host.h index 66434307523d..cce39b0289e5 100644 --- a/arch/sw_64/include/asm/kvm_host.h +++ b/arch/sw_64/include/asm/kvm_host.h @@ -157,10 +157,6 @@ struct kvm_vcpu_stat { #ifdef CONFIG_SUBARCH_C4 #define KVM_ARCH_WANT_MMU_NOTIFIER #endif -int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte); -int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end, bool blockable); -int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end); -int kvm_test_age_hva(struct kvm *kvm, unsigned long hva); void update_vcpu_stat_time(struct kvm_vcpu_stat *vcpu_stat); void check_vcpu_requests(struct kvm_vcpu *vcpu); diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index dafad9db62de..dd0be82e96a4 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -1174,7 +1174,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, * gfn_to_pfn_prot (which calls get_user_pages), so that we don't risk * the page we just got a reference to gets unmapped before we have a * chance to grab the mmu_lock, which ensure that if the page gets - * unmapped afterwards, the call to kvm_unmap_hva will take it away + * unmapped afterwards, the call to kvm_unmap_gfn will take it away * from us again properly. This smp_rmb() interacts with the smp_wmb() * in kvm_mmu_notifier_invalidate_. */ @@ -1366,72 +1366,38 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, return ret; } #endif -static int handle_hva_to_gpa(struct kvm *kvm, unsigned long start, unsigned long end, - int (*handler)(struct kvm *kvm, gpa_t gpa, u64 size, void *data), - void *data) -{ - struct kvm_memslots *slots; - struct kvm_memory_slot *memslot; - int ret = 0; - int bkt; - - slots = kvm_memslots(kvm); - - /* we only care about the pages that the guest sees */ - kvm_for_each_memslot(memslot, bkt, slots) { - unsigned long hva_start, hva_end; - gfn_t gpa; - hva_start = max(start, memslot->userspace_addr); - hva_end = min(end, memslot->userspace_addr + - (memslot->npages << PAGE_SHIFT)); - if (hva_start >= hva_end) - continue; - - gpa = hva_to_gfn_memslot(hva_start, memslot) << PAGE_SHIFT; - ret |= handler(kvm, gpa, (u64)(hva_end - hva_start), data); - } - - return ret; -} - -static int kvm_unmap_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) -{ - unmap_apt_range(kvm, gpa, size); - return 0; -} - -int kvm_unmap_hva_range(struct kvm *kvm, - unsigned long start, unsigned long end, bool blockable) +bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) { if (!kvm->arch.pgd) - return 0; + return false; - trace_kvm_unmap_hva_range(start, end); - handle_hva_to_gpa(kvm, start, end, &kvm_unmap_hva_handler, NULL); - return 1; + unmap_apt_range(kvm, range->start << PAGE_SHIFT, + (range->end - range->start) << PAGE_SHIFT); + + return false; } -static int apt_ptep_test_and_clear_young(pte_t *pte) +static bool apt_ptep_test_and_clear_young(pte_t *pte) { if (pte_young(*pte)) { *pte = pte_mkold(*pte); - return 1; + return true; } - return 0; + return false; } -static int apt_pmdp_test_and_clear_young(pmd_t *pmd) +static bool apt_pmdp_test_and_clear_young(pmd_t *pmd) { return apt_ptep_test_and_clear_young((pte_t *)pmd); } -static int apt_pudp_test_and_clear_young(pud_t *pud) +static bool apt_pudp_test_and_clear_young(pud_t *pud) { return apt_ptep_test_and_clear_young((pte_t *)pud); } -static int kvm_age_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) +static bool kvm_apt_test_clear_young(struct kvm *kvm, gpa_t gpa, u64 size, void *data) { pud_t *pud; pmd_t *pmd; @@ -1439,7 +1405,7 @@ static int kvm_age_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) WARN_ON(size != PAGE_SIZE && size != PMD_SIZE && size != PUD_SIZE); if (!apt_get_leaf_entry(kvm, gpa, &pud, &pmd, &pte)) - return 0; + return false; if (pud) return apt_pudp_test_and_clear_young(pud); @@ -1449,63 +1415,42 @@ static int kvm_age_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) return apt_ptep_test_and_clear_young(pte); } -static int kvm_test_age_hva_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) +bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range) { - pud_t *pud; - pmd_t *pmd; - pte_t *pte; + gpa_t gpa = range->start << PAGE_SHIFT; + u64 size = (range->end - range->start) << PAGE_SHIFT; - WARN_ON(size != PAGE_SIZE && size != PMD_SIZE && size != PUD_SIZE); - if (!apt_get_leaf_entry(kvm, gpa, &pud, &pmd, &pte)) - return 0; - - if (pud) - return apt_pudp_test_and_clear_young(pud); - else if (pmd) - return apt_pmdp_test_and_clear_young(pmd); - else - return apt_ptep_test_and_clear_young(pte); -} - -int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end) -{ if (!kvm->arch.pgd) - return 0; - trace_kvm_age_hva(start, end); - return handle_hva_to_gpa(kvm, start, end, kvm_age_hva_handler, NULL); -} + return false; -int kvm_test_age_hva(struct kvm *kvm, unsigned long hva) -{ - if (!kvm->arch.pgd) - return 0; - trace_kvm_test_age_hva(hva); - return handle_hva_to_gpa(kvm, hva, hva, kvm_test_age_hva_handler, NULL); + return kvm_apt_test_clear_young(kvm, gpa, size, NULL); } -static int kvm_set_apte_handler(struct kvm *kvm, gpa_t gpa, u64 size, void *data) +bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range) { - pte_t *pte = (pte_t *)data; + gpa_t gpa = range->start << PAGE_SHIFT; + u64 size = (range->end - range->start) << PAGE_SHIFT; - WARN_ON(size != PAGE_SIZE); + if (!kvm->arch.pgd) + return false; - apt_set_pte(kvm, NULL, gpa, pte, 0); - return 0; + return kvm_apt_test_clear_young(kvm, gpa, size, NULL); } -int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte) +bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range) { - unsigned long end = hva + PAGE_SIZE; - pte_t apt_pte; - + gpa_t gpa = range->start << PAGE_SHIFT; + pte_t apt_pte = range->arg.pte; if (!kvm->arch.pgd) - return 0; + return false; - trace_kvm_set_spte_hva(hva); + WARN_ON(range->end - range->start != 1); - apt_pte = pte_wrprotect(pte); - handle_hva_to_gpa(kvm, hva, end, &kvm_set_apte_handler, &apt_pte); - return 0; + apt_pte = pte_wrprotect(apt_pte); + + apt_set_pte(kvm, NULL, gpa, &apt_pte, 0); + + return false; } /** diff --git a/arch/sw_64/kvm/trace.h b/arch/sw_64/kvm/trace.h index 2b7b1de1e5d5..0e6a75a57f11 100644 --- a/arch/sw_64/kvm/trace.h +++ b/arch/sw_64/kvm/trace.h @@ -132,72 +132,6 @@ TRACE_EVENT(kvm_mmio_emulate, __entry->vcpu_pc, __entry->instr, __entry->cpsr) ); -TRACE_EVENT(kvm_unmap_hva_range, - TP_PROTO(unsigned long start, unsigned long end), - TP_ARGS(start, end), - - TP_STRUCT__entry( - __field(unsigned long, start) - __field(unsigned long, end) - ), - - TP_fast_assign( - __entry->start = start; - __entry->end = end; - ), - - TP_printk("mmu notifier unmap range: %#016lx -- %#016lx", - __entry->start, __entry->end) -); - -TRACE_EVENT(kvm_set_spte_hva, - TP_PROTO(unsigned long hva), - TP_ARGS(hva), - - TP_STRUCT__entry( - __field(unsigned long, hva) - ), - - TP_fast_assign( - __entry->hva = hva; - ), - - TP_printk("mmu notifier set pte hva: %#016lx", __entry->hva) -); - -TRACE_EVENT(kvm_age_hva, - TP_PROTO(unsigned long start, unsigned long end), - TP_ARGS(start, end), - - TP_STRUCT__entry( - __field(unsigned long, start) - __field(unsigned long, end) - ), - - TP_fast_assign( - __entry->start = start; - __entry->end = end; - ), - - TP_printk("mmu notifier age hva: %#016lx -- %#016lx", - __entry->start, __entry->end) -); - -TRACE_EVENT(kvm_test_age_hva, - TP_PROTO(unsigned long hva), - TP_ARGS(hva), - - TP_STRUCT__entry( - __field(unsigned long, hva) - ), - - TP_fast_assign( - __entry->hva = hva; - ), - - TP_printk("mmu notifier test age hva: %#016lx", __entry->hva) -); - TRACE_EVENT(kvm_set_way_flush, TP_PROTO(unsigned long vcpu_pc, bool cache), TP_ARGS(vcpu_pc, cache), -- Gitee From 824e498f4333cded0644ac273e9d44fca3440c14 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Fri, 28 Jun 2024 16:13:54 +0800 Subject: [PATCH 062/100] anolis: sw64: kvm: walk host page tables to find THP mapping size ANBZ: #4688 Since kvm_is_transparent_hugepage() has been removed in commit 205d76ff0684 ("KVM: Remove kvm_is_transparent_hugepage() and PageTransCompoundMap()"). This patch walks the host page tables to identify THP mappings instead of relying solely on the metadata in struct page to get the mapping size like other archs. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 56 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index dd0be82e96a4..6f42e6cf9bb2 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -1063,8 +1063,49 @@ static int apt_set_pud_huge(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, return 0; } +static int get_user_mapping_size(struct kvm *kvm, u64 hva) +{ + unsigned long flags; + int pgsize = PAGE_SIZE; + pgd_t pgd; + p4d_t p4d; + pud_t pud; + pmd_t pmd; + + /* + * Disable IRQs to prevent concurrent tear down of host page tables, + * e.g. if the primary MMU promotes a P*D to a huge page and then frees + * the original page table. + */ + local_irq_save(flags); + + pgd = *(pgd_offset(kvm->mm, hva)); + if (pgd_none(pgd)) + goto out; + + p4d = *(p4d_offset(&pgd, hva)); + if (p4d_none(p4d) || !p4d_present(p4d)) + goto out; + + pud = *(pud_offset(&p4d, hva)); + if (pud_none(pud) || !pud_present(pud)) + goto out; + + pmd = *(pmd_offset(&pud, hva)); + if (pmd_none(pmd) || !pmd_present(pmd)) + goto out; + + if (pmd_trans_huge(pmd)) + pgsize = PMD_SIZE; + +out: + local_irq_restore(flags); + return pgsize; + +} + static unsigned long -transparent_hugepage_adjust(struct kvm_memory_slot *memslot, +transparent_hugepage_adjust(struct kvm *kvm, struct kvm_memory_slot *memslot, unsigned long hva, kvm_pfn_t *pfnp, phys_addr_t *gpap) { @@ -1075,8 +1116,14 @@ transparent_hugepage_adjust(struct kvm_memory_slot *memslot, * sure that the HVA and IPA are sufficiently aligned and that the * block map is contained within the memslot. */ - if (kvm_is_transparent_hugepage(pfn) && - fault_supports_apt_huge_mapping(memslot, hva, PMD_SIZE)) { + if (fault_supports_apt_huge_mapping(memslot, hva, PMD_SIZE)) { + int pgsz = get_user_mapping_size(kvm, hva); + + if (pgsz < 0) + return pgsz; + + if (pgsz < PMD_SIZE) + return PAGE_SIZE; /* * The address we faulted on is backed by a transparent huge * page. However, because we map the compound huge page and @@ -1181,6 +1228,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, smp_rmb(); pfn = gfn_to_pfn_prot(kvm, gfn, write_fault, &writable); + if (pfn == KVM_PFN_ERR_HWPOISON) { kvm_send_hwpoison_signal(hva, vma); return 0; @@ -1213,7 +1261,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, * backed by a THP and thus use block mapping if possible. */ if (vma_pagesize == PAGE_SIZE && !force_pte) { - vma_pagesize = transparent_hugepage_adjust(memslot, hva, + vma_pagesize = transparent_hugepage_adjust(kvm, memslot, hva, &pfn, &fault_gpa); } -- Gitee From ae7d8fcb27d5f9623683be9f8e28bb108694a498 Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Tue, 9 Jul 2024 10:00:15 +0800 Subject: [PATCH 063/100] anolis: sw64: fix guest memory and cpu hotplug function ANBZ: #4688 This patch: - Remove node information in memory hot unplugging because nid parameter has been removed from remove_memory() and friends in commit e1c158e49566. - Add header file cpu.h to sunway-ged.c so that we can use get_cpu_device() function when we hotplug cpu. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/misc/sunway-ged.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/misc/sunway-ged.c b/drivers/misc/sunway-ged.c index 14d7ed3d3d92..4a0d6fc736ef 100644 --- a/drivers/misc/sunway-ged.c +++ b/drivers/misc/sunway-ged.c @@ -3,6 +3,7 @@ /* Generic Event Device for ACPI. */ #include +#include #include #include #include @@ -17,9 +18,7 @@ #define OFFSET_LENGTH 8 #define OFFSET_STATUS 16 #define OFFSET_SLOT 24 - #define OFFSET_CPUID 32 - #define OFFSET_NODE 40 /* Memory hotplug event */ @@ -96,7 +95,7 @@ static int sunway_memory_enable_device(struct sunway_memory_device *mem_device) static void sunway_memory_device_remove(struct sunway_ged_device *device) { struct sunway_memory_device *mem_dev, *n; - unsigned long start_addr, length, slot, node; + unsigned long start_addr, length, slot; if (!device) return; @@ -104,7 +103,6 @@ static void sunway_memory_device_remove(struct sunway_ged_device *device) start_addr = readq(device->membase + OFFSET_START_ADDR); length = readq(device->membase + OFFSET_LENGTH); slot = readq(device->membase + OFFSET_SLOT); - node = readq(device->membase + OFFSET_NODE); list_for_each_entry_safe(mem_dev, n, &device->dev_list, list) { if (!mem_dev->enabled) @@ -112,8 +110,7 @@ static void sunway_memory_device_remove(struct sunway_ged_device *device) if ((start_addr == mem_dev->start_addr) && (length == mem_dev->length)) { - /* suppose node = 0, fix me! */ - remove_memory(node, start_addr, length); + remove_memory(start_addr, length); list_del(&mem_dev->list); kfree(mem_dev); } -- Gitee From 45db80f02bf81e625ac5fab196c5b207fcc9bfe7 Mon Sep 17 00:00:00 2001 From: Wang Yuanheng Date: Mon, 17 Jun 2024 14:18:03 +0800 Subject: [PATCH 064/100] anolis: sw64: kvm: fix mmio GPA for C4 ANBZ: #4688 The original value of hargs->arg1 is from CSR:DVA, but io_mem_abort() will treat it as mmio GPA, so fix it with CSR:EXC_GPA. Signed-off-by: Wang Yuanheng Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 6f42e6cf9bb2..27889a0d795c 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -1400,6 +1400,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, */ if (hva == KVM_HVA_ERR_BAD) { + hargs->arg1 = fault_gpa | (hargs->arg1 & 0x1fffUL); ret = io_mem_abort(vcpu, run, hargs); goto out_unlock; } -- Gitee From c73e5ad856e592c0876502ffab5b8c6ed1de5121 Mon Sep 17 00:00:00 2001 From: Xu Chenjiao Date: Wed, 10 Jul 2024 15:28:17 +0000 Subject: [PATCH 065/100] anolis: sw64: adapt the modifications from the upstream for pciehp ANBZ: #4688 The relevant interfaces from the upstream have changed. Therefore, this patch adapts the modifications from the upstream for the sunway pcie hotplug driver. Signed-off-by: Xu Chenjiao Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/pci.h | 1 + drivers/pci/controller/pci-sunway.c | 7 +- drivers/pci/hotplug/sunway_pciehp.h | 10 +- drivers/pci/hotplug/sunway_pciehp_core.c | 56 ++++++++-- drivers/pci/hotplug/sunway_pciehp_ctrl.c | 25 +++-- drivers/pci/hotplug/sunway_pciehp_hpc.c | 131 +++++++++++++++++------ drivers/pci/hotplug/sunway_pciehp_pci.c | 15 +++ 7 files changed, 193 insertions(+), 52 deletions(-) diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index 1bd2123362f0..62fee7ba5dd6 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -65,6 +65,7 @@ struct pci_controller { unsigned int need_domain_info; bool iommu_enable; struct sunway_iommu *pci_iommu; + bool hotplug_enable; int first_busno; int last_busno; int self_busno; diff --git a/drivers/pci/controller/pci-sunway.c b/drivers/pci/controller/pci-sunway.c index 139c9515fe6f..59962f9a6158 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -327,6 +327,8 @@ static void hose_init(struct pci_controller *hose) hose->first_busno = hose->self_busno = hose->busn_space->start; hose->last_busno = hose->busn_space->end; + hose->hotplug_enable = true; + if (is_in_host()) { if (IS_ENABLED(CONFIG_PCI_MSI)) memset(hose->piu_msiconfig, 0, 256/8); @@ -646,6 +648,7 @@ enum pci_props { PROP_PIU_IOR1_BASE, PROP_RC_INDEX, PROP_PCIE_IO_BASE, + PROP_HOTPLUG_ENABLE, PROP_NUM }; @@ -658,7 +661,8 @@ const char *prop_names[PROP_NUM] = { "sw64,piu_ior0_base", "sw64,piu_ior1_base", "sw64,rc_index", - "sw64,pcie_io_base" + "sw64,pcie_io_base", + "sw64,hot_plug_slot_enable" }; static int sw64_pci_prepare_controller(struct pci_controller *hose, @@ -681,6 +685,7 @@ static int sw64_pci_prepare_controller(struct pci_controller *hose, hose->iommu_enable = false; hose->index = props[PROP_RC_INDEX]; + hose->hotplug_enable = props[PROP_HOTPLUG_ENABLE]; hose->sparse_mem_base = 0; hose->sparse_io_base = 0; diff --git a/drivers/pci/hotplug/sunway_pciehp.h b/drivers/pci/hotplug/sunway_pciehp.h index d1addc487d07..2feecbcc5366 100644 --- a/drivers/pci/hotplug/sunway_pciehp.h +++ b/drivers/pci/hotplug/sunway_pciehp.h @@ -54,6 +54,9 @@ struct saved_piu_space { /** * struct controller - PCIe hotplug controller * @slot_cap: cached copy of the Slot Capabilities register + * @inband_presence_disabled: In-Band Presence Detect Disable supported by + * controller and disabled per spec recommendation (PCIe r5.0, appendix I + * implementation note) * @slot_ctrl: cached copy of the Slot Control register * @ctrl_lock: serializes writes to the Slot Control register * @cmd_started: jiffies when the Slot Control register was last written; @@ -79,6 +82,8 @@ struct saved_piu_space { * @reset_lock: prevents access to the Data Link Layer Link Active bit in the * Link Status register and to the Presence Detect State bit in the Slot * Status register during a slot reset which may cause them to flap + * @depth: Number of additional hotplug ports in the path to the root bus, + * used as lock subclass for @reset_lock * @ist_running: flag to keep user request waiting while IRQ thread is running * @request_result: result of last user request submitted to the IRQ thread * @requester: wait queue to wake up on completion of user request, @@ -109,6 +114,7 @@ struct controller { struct hotplug_slot hotplug_slot; /* hotplug core interface */ struct rw_semaphore reset_lock; + unsigned int depth; unsigned int ist_running; int request_result; wait_queue_head_t requester; @@ -202,6 +208,8 @@ int sunway_pciehp_link_enable(struct controller *ctrl); int sunway_pciehp_link_disable(struct controller *ctrl); void sunway_pciehp_restore_rc_piu(struct controller *ctrl); +int sunway_pciehp_slot_reset(struct pci_dev *dev); + static inline const char *slot_name(struct controller *ctrl) { return hotplug_slot_name(&ctrl->hotplug_slot); @@ -212,4 +220,4 @@ static inline struct controller *to_ctrl(struct hotplug_slot *hotplug_slot) return container_of(hotplug_slot, struct controller, hotplug_slot); } -#endif /* _PCIEHP_H */ +#endif /* _SUNWAYPCIEHP_H */ diff --git a/drivers/pci/hotplug/sunway_pciehp_core.c b/drivers/pci/hotplug/sunway_pciehp_core.c index 6d155d3a0595..acafc82b3224 100644 --- a/drivers/pci/hotplug/sunway_pciehp_core.c +++ b/drivers/pci/hotplug/sunway_pciehp_core.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include "../pci.h" #include "sunway_pciehp.h" @@ -161,7 +163,7 @@ static void sunway_pciehp_check_presence(struct controller *ctrl) { int occupied; - down_read(&ctrl->reset_lock); + down_read_nested(&ctrl->reset_lock, ctrl->depth); mutex_lock(&ctrl->state_lock); occupied = sunway_pciehp_card_present_or_link_active(ctrl); @@ -241,12 +243,42 @@ static void sunwayhp_remove(struct pci_dev *dev) sunway_pciehp_release_ctrl(ctrl); } -extern struct pci_controller *hose_head, **hose_tail; +static void sunway_hose_hotplug_init(void) +{ + int ret; + struct pci_dev *pdev = NULL; + struct pci_controller *hose; + struct pci_config_window *cfg; + struct acpi_device *adev; + u64 prop_hotplug_enable; + + while ((pdev = pci_get_device(PCI_VENDOR_ID_JN, PCI_DEVICE_ID_SW64_ROOT_BRIDGE, pdev))) { + hose = pci_bus_to_pci_controller(pdev->bus); + hose->hotplug_enable = false; + + if (!acpi_disabled) { + cfg = (struct pci_config_window *)pdev->bus->sysdata; + adev = to_acpi_device(cfg->parent); + + ret = fwnode_property_read_u64_array(&adev->fwnode, + "sw64,hot_plug_slot_enable", &prop_hotplug_enable, 1); + + if (ret == 0) + hose->hotplug_enable = prop_hotplug_enable; + } + } +} + static int __init sunway_pciehp_init(void) { int retval; struct pci_dev *pdev = NULL; - struct pci_controller *hose = NULL; + struct pci_controller *hose; + + if (is_guest_or_emul()) { + pr_info(DRIVER_DESC " does not support for VM and emulator.\n"); + return -ENODEV; + } if (is_guest_or_emul()) { pr_info(DRIVER_DESC " does not support for VM and emulator.\n"); @@ -255,8 +287,13 @@ static int __init sunway_pciehp_init(void) pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - for (hose = hose_head; hose; hose = hose->next) { - pdev = pci_get_device(PCI_VENDOR_ID_JN, PCI_DEVICE_ID_SW64_ROOT_BRIDGE, pdev); + sunway_hose_hotplug_init(); + + while ((pdev = pci_get_device(PCI_VENDOR_ID_JN, PCI_DEVICE_ID_SW64_ROOT_BRIDGE, pdev))) { + hose = pci_bus_to_pci_controller(pdev->bus); + + if (!hose->hotplug_enable) + continue; retval = sunwayhp_init(pdev); } @@ -267,12 +304,15 @@ static int __init sunway_pciehp_init(void) static void __exit sunway_pciehp_exit(void) { struct pci_dev *pdev = NULL; - struct pci_controller *hose = NULL; + struct pci_controller *hose; pr_info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); - for (hose = hose_head; hose; hose = hose->next) { - pdev = pci_get_device(PCI_VENDOR_ID_JN, PCI_DEVICE_ID_SW64_ROOT_BRIDGE, pdev); + while ((pdev = pci_get_device(PCI_VENDOR_ID_JN, PCI_DEVICE_ID_SW64_ROOT_BRIDGE, pdev))) { + hose = pci_bus_to_pci_controller(pdev->bus); + + if (!hose->hotplug_enable) + continue; sunwayhp_remove(pdev); } diff --git a/drivers/pci/hotplug/sunway_pciehp_ctrl.c b/drivers/pci/hotplug/sunway_pciehp_ctrl.c index 52e79bfe7dd6..a1c4da32d0ee 100644 --- a/drivers/pci/hotplug/sunway_pciehp_ctrl.c +++ b/drivers/pci/hotplug/sunway_pciehp_ctrl.c @@ -161,11 +161,11 @@ void sunway_pciehp_handle_button_press(struct controller *ctrl) case ON_STATE: if (ctrl->state == ON_STATE) { ctrl->state = BLINKINGOFF_STATE; - ctrl_info(ctrl, "Slot(%s): Powering off due to button press\n", + ctrl_info(ctrl, "Slot(%s): Button press: will power off in 5 sec\n", slot_name(ctrl)); } else { ctrl->state = BLINKINGON_STATE; - ctrl_info(ctrl, "Slot(%s) Powering on due to button press\n", + ctrl_info(ctrl, "Slot(%s): Button press: will power on in 5 sec\n", slot_name(ctrl)); } /* blink power indicator and turn off attention */ @@ -180,22 +180,23 @@ void sunway_pciehp_handle_button_press(struct controller *ctrl) * press the attention again before the 5 sec. limit * expires to cancel hot-add or hot-remove */ - ctrl_info(ctrl, "Slot(%s): Button cancel\n", slot_name(ctrl)); cancel_delayed_work(&ctrl->button_work); if (ctrl->state == BLINKINGOFF_STATE) { ctrl->state = ON_STATE; sunway_pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON, PCI_EXP_SLTCTL_ATTN_IND_OFF); + ctrl_info(ctrl, "Slot(%s): Button press: canceling request to power off\n", + slot_name(ctrl)); } else { ctrl->state = OFF_STATE; sunway_pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, PCI_EXP_SLTCTL_ATTN_IND_OFF); + ctrl_info(ctrl, "Slot(%s): Button press: canceling request to power on\n", + slot_name(ctrl)); } - ctrl_info(ctrl, "Slot(%s): Action canceled due to button press\n", - slot_name(ctrl)); break; default: - ctrl_err(ctrl, "Slot(%s): Ignoring invalid state %#x\n", + ctrl_err(ctrl, "Slot(%s): Button press: Ignoring invalid state %#x\n", slot_name(ctrl), ctrl->state); break; } @@ -489,6 +490,14 @@ void sunway_pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 e present = sunway_pciehp_card_present(ctrl); link_active = sunway_pciehp_check_link_active(ctrl); if (present <= 0 && link_active <= 0) { + if (ctrl->state == BLINKINGON_STATE) { + ctrl->state = OFF_STATE; + cancel_delayed_work(&ctrl->button_work); + sunway_pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, + INDICATOR_NOOP); + ctrl_info(ctrl, "Slot(%s): Card not present\n", + slot_name(ctrl)); + } sunway_pciehp_end(ctrl, false); mutex_unlock(&ctrl->state_lock); return; @@ -642,13 +651,11 @@ int sunway_pciehp_sysfs_disable_slot(struct hotplug_slot *hotplug_slot) switch (ctrl->state) { case BLINKINGOFF_STATE: case ON_STATE: - sunway_pciehp_start(hotplug_slot); - mutex_unlock(&ctrl->state_lock); + sunway_pciehp_start(hotplug_slot); wait_event(ctrl->requester, !atomic_read(&ctrl->pending_events) && !ctrl->ist_running); - return ctrl->request_result; case POWEROFF_STATE: ctrl_info(ctrl, "Slot(%s): Already in powering off state\n", diff --git a/drivers/pci/hotplug/sunway_pciehp_hpc.c b/drivers/pci/hotplug/sunway_pciehp_hpc.c index e6559261788d..2bb6d3ff3165 100644 --- a/drivers/pci/hotplug/sunway_pciehp_hpc.c +++ b/drivers/pci/hotplug/sunway_pciehp_hpc.c @@ -87,7 +87,7 @@ static int pcie_poll_cmd(struct controller *ctrl, int timeout) do { pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); - if (slot_status == (u16) ~0) { + if (PCI_POSSIBLE_ERROR(slot_status)) { ctrl_info(ctrl, "%s: no response from device\n", __func__); return 0; @@ -96,6 +96,8 @@ static int pcie_poll_cmd(struct controller *ctrl, int timeout) if (slot_status & PCI_EXP_SLTSTA_CC) { pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC); + ctrl->cmd_busy = 0; + smp_mb(); return 1; } msleep(10); @@ -163,7 +165,7 @@ static void pcie_do_write_cmd(struct controller *ctrl, u16 cmd, pcie_wait_cmd(ctrl); pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); - if (slot_ctrl == (u16) ~0) { + if (PCI_POSSIBLE_ERROR(slot_ctrl)) { ctrl_info(ctrl, "%s: no response from device\n", __func__); goto out; } @@ -233,7 +235,7 @@ int sunway_pciehp_check_link_active(struct controller *ctrl) int ret; ret = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); - if (ret == PCIBIOS_DEVICE_NOT_FOUND || lnk_status == (u16)~0) + if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status)) return -ENODEV; ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); @@ -380,17 +382,10 @@ int sunway_pciehp_check_link_status(struct controller *ctrl) static int __sunway_pciehp_link_set(struct controller *ctrl, bool enable) { struct pci_dev *pdev = ctrl_dev(ctrl); - u16 lnk_ctrl; - pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnk_ctrl); - - if (enable) - lnk_ctrl &= ~PCI_EXP_LNKCTL_LD; - else - lnk_ctrl |= PCI_EXP_LNKCTL_LD; - - pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnk_ctrl); - ctrl_dbg(ctrl, "%s: lnk_ctrl = %x\n", __func__, lnk_ctrl); + pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_LD, + enable ? 0 : PCI_EXP_LNKCTL_LD); return 0; } @@ -463,7 +458,6 @@ void sunway_pciehp_get_power_status(struct controller *ctrl, u8 *status) u16 slot_ctrl; pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); - ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", __func__, pci_pcie_cap(ctrl->pci_dev) + PCI_EXP_SLTCTL, slot_ctrl); @@ -508,7 +502,7 @@ int sunway_pciehp_card_present(struct controller *ctrl) int ret; ret = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); - if (ret == PCIBIOS_DEVICE_NOT_FOUND || slot_status == (u16)~0) + if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(slot_status)) return -ENODEV; return !!(slot_status & PCI_EXP_SLTSTA_PDS); @@ -728,6 +722,32 @@ void sunway_pciehp_poll(struct controller *ctrl, u32 events) } } +static void sunway_pciehp_ignore_dpc_link_change(struct controller *ctrl, + struct pci_dev *pdev, int irq) +{ + /* + * Ignore link changes which occurred while waiting for DPC recovery. + * Could be several if DPC triggered multiple times consecutively. + */ + synchronize_hardirq(irq); + atomic_and(~PCI_EXP_SLTSTA_DLLSC, &ctrl->pending_events); + if (sunway_pciehp_poll_mode) + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_DLLSC); + ctrl_info(ctrl, "Slot(%s): Link Down/Up ignored (recovered by DPC)\n", + slot_name(ctrl)); + + /* + * If the link is unexpectedly down after successful recovery, + * the corresponding link change may have been ignored above. + * Synthesize it to ensure that it is acted on. + */ + down_read_nested(&ctrl->reset_lock, ctrl->depth); + if (!sunway_pciehp_check_link_active(ctrl)) + sunway_pciehp_request(ctrl, PCI_EXP_SLTSTA_DLLSC); + up_read(&ctrl->reset_lock); +} + static irqreturn_t sunway_pciehp_isr(int irq, void *dev_id) { struct controller *ctrl = (struct controller *)dev_id; @@ -770,7 +790,7 @@ static irqreturn_t sunway_pciehp_isr(int irq, void *dev_id) read_status: pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &status); - if (status == (u16) ~0) { + if (PCI_POSSIBLE_ERROR(status)) { ctrl_info(ctrl, "%s: no response from device\n", __func__); if (parent) pm_runtime_put(parent); @@ -791,6 +811,8 @@ static irqreturn_t sunway_pciehp_isr(int irq, void *dev_id) */ if (ctrl->power_fault_detected) status &= ~PCI_EXP_SLTSTA_PFD; + else if (status & PCI_EXP_SLTSTA_PFD) + ctrl->power_fault_detected = true; events |= status; if (!events) { @@ -800,7 +822,7 @@ static irqreturn_t sunway_pciehp_isr(int irq, void *dev_id) } if (status) { - pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, events); + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, status); /* * In MSI mode, all event bits must be zero before the port @@ -874,31 +896,35 @@ static irqreturn_t sunway_pciehp_ist(int irq, void *dev_id) } /* Check Attention Button Pressed */ - if (events & PCI_EXP_SLTSTA_ABP) { - ctrl_info(ctrl, "Slot(%s): Attention button pressed\n", - slot_name(ctrl)); + if (events & PCI_EXP_SLTSTA_ABP) sunway_pciehp_handle_button_press(ctrl); - } /* Check Power Fault Detected */ - if ((events & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) { - ctrl->power_fault_detected = 1; + if (events & PCI_EXP_SLTSTA_PFD) { ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(ctrl)); sunway_pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, PCI_EXP_SLTCTL_ATTN_IND_ON); } + /* + * Ignore Link Down/Up events caused by Downstream Port Containment + * if recovery from the error succeeded. + */ + if ((events & PCI_EXP_SLTSTA_DLLSC) && pci_dpc_recovered(pdev) && + ctrl->state == ON_STATE) { + events &= ~PCI_EXP_SLTSTA_DLLSC; + sunway_pciehp_ignore_dpc_link_change(ctrl, pdev, irq); + } + /* * Disable requests have higher priority than Presence Detect Changed * or Data Link Layer State Changed events. */ - down_read(&ctrl->reset_lock); - + down_read_nested(&ctrl->reset_lock, ctrl->depth); if (events & DISABLE_SLOT) sunway_pciehp_handle_disable_request(ctrl); else if (events & (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC)) sunway_pciehp_handle_presence_or_link_change(ctrl, events); - up_read(&ctrl->reset_lock); ret = IRQ_HANDLED; @@ -956,7 +982,9 @@ static void pcie_enable_notification(struct controller *ctrl) else cmd |= PCI_EXP_SLTCTL_PDCE; if (!sunway_pciehp_poll_mode) - cmd |= PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE; + cmd |= PCI_EXP_SLTCTL_HPIE; + if (!sunway_pciehp_poll_mode && !NO_CMD_CMPL(ctrl)) + cmd |= PCI_EXP_SLTCTL_CCIE; mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | PCI_EXP_SLTCTL_PFDE | @@ -987,6 +1015,31 @@ void sunway_pcie_clear_hotplug_events(struct controller *ctrl) PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC); } +/** + * sunway_pciehp_slot_reset() - ignore link event caused by error-induced hot reset + * + * Called from pcie_portdrv_slot_reset() after AER or DPC initiated a reset + * further up in the hierarchy to recover from an error. The reset was + * propagated down to this hotplug port. Ignore the resulting link flap. + * If the link failed to retrain successfully, synthesize the ignored event. + * Surprise removal during reset is detected through Presence Detect Changed. + */ +int sunway_pciehp_slot_reset(struct pci_dev *dev) +{ + struct controller *ctrl = pci_get_drvdata(dev); + + if (ctrl->state != ON_STATE) + return 0; + + pcie_capability_write_word(ctrl_dev(ctrl), PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_DLLSC); + + if (!sunway_pciehp_check_link_active(ctrl)) + sunway_pciehp_request(ctrl, PCI_EXP_SLTSTA_DLLSC); + + return 0; +} + /* * sunway_pciehp has a 1:1 bus:slot relationship so we ultimately want a secondary * bus reset of the bridge, but at the same time we want to ensure that it is @@ -1005,7 +1058,7 @@ int sunway_pciehp_reset_slot(struct hotplug_slot *hotplug_slot, bool probe) if (probe) return 0; - down_write(&ctrl->reset_lock); + down_write_nested(&ctrl->reset_lock, ctrl->depth); if (!ATTN_BUTTN(ctrl)) { ctrl_mask |= PCI_EXP_SLTCTL_PDCE; @@ -1061,10 +1114,24 @@ static inline void dbg_ctrl(struct controller *ctrl) #define FLAG(x, y) (((x) & (y)) ? '+' : '-') +static inline int sunway_pcie_hotplug_depth(struct pci_dev *dev) +{ + struct pci_bus *bus = dev->bus; + int depth = 0; + + while (bus->parent) { + bus = bus->parent; + if (bus->self && bus->self->is_hotplug_bridge) + depth++; + } + + return depth; +} + struct controller *sunwayhpc_init(struct pci_dev *dev) { struct controller *ctrl; - u32 slot_cap, slot_cap2, link_cap; + u32 slot_cap, slot_cap2; u8 poweron; struct pci_bus *subordinate = dev->subordinate; @@ -1073,6 +1140,7 @@ struct controller *sunwayhpc_init(struct pci_dev *dev) return NULL; ctrl->pci_dev = dev; + ctrl->depth = sunway_pcie_hotplug_depth(dev); pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, &slot_cap); if (dev->hotplug_user_indicators) @@ -1108,9 +1176,6 @@ struct controller *sunwayhpc_init(struct pci_dev *dev) if (dmi_first_match(inband_presence_disabled_dmi_table)) ctrl->inband_presence_disabled = 1; - /* Check if Data Link Layer Link Active Reporting is implemented */ - pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &link_cap); - /* Clear all remaining event bits in Slot Status register. */ pcie_capability_write_word(dev, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | @@ -1129,7 +1194,7 @@ struct controller *sunwayhpc_init(struct pci_dev *dev) FLAG(slot_cap, PCI_EXP_SLTCAP_EIP), FLAG(slot_cap, PCI_EXP_SLTCAP_NCCS), FLAG(slot_cap2, PCI_EXP_SLTCAP2_IBPD), - FLAG(link_cap, PCI_EXP_LNKCAP_DLLLARC)); + FLAG(dev->link_active_reporting, true)); /* * If empty slot's power status is on, turn power off. The IRQ isn't diff --git a/drivers/pci/hotplug/sunway_pciehp_pci.c b/drivers/pci/hotplug/sunway_pciehp_pci.c index f627ea054342..79e9646005ef 100644 --- a/drivers/pci/hotplug/sunway_pciehp_pci.c +++ b/drivers/pci/hotplug/sunway_pciehp_pci.c @@ -54,7 +54,14 @@ int sunway_pciehp_configure_device(struct controller *ctrl) pci_assign_unassigned_bridge_resources(bridge); pcie_bus_configure_settings(parent); + + /* + * Release reset_lock during driver binding + * to avoid AB-BA deadlock with device_lock. + */ + up_read(&ctrl->reset_lock); pci_bus_add_devices(parent); + down_read_nested(&ctrl->reset_lock, ctrl->depth); out: pci_unlock_rescan_remove(); @@ -95,7 +102,15 @@ void sunway_pciehp_unconfigure_device(struct controller *ctrl, bool presence) list_for_each_entry_safe_reverse(dev, temp, &parent->devices, bus_list) { pci_dev_get(dev); + + /* + * Release reset_lock during driver unbinding + * to avoid AB-BA deadlock with device_lock. + */ + up_read(&ctrl->reset_lock); pci_stop_and_remove_bus_device(dev); + down_read_nested(&ctrl->reset_lock, ctrl->depth); + /* * Ensure that no new Requests will be generated from * the device. -- Gitee From 81357436de04f906461bbb85c958d46dda1199de Mon Sep 17 00:00:00 2001 From: Gao Chen Date: Wed, 10 Jul 2024 16:41:41 +0800 Subject: [PATCH 066/100] anolis: sw64: kvm: resolve a compile warning ANBZ: #4688 In upstream, the function arch_cpu_idle_dead() adds the "__noreturn" modifier. Threfore, the code "return;" in SW's arch_cpu_idle_dead() throws a warning. This patch deletes the meaningless "return;". Signed-off-by: Gao Chen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/smp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 1871196ff378..4d6b7f55a50a 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -804,7 +804,6 @@ void arch_cpu_idle_dead(void) if (is_in_guest()) { hcall(HCALL_SET_CLOCKEVENT, 0, 0, 0); hcall(HCALL_STOP, 0, 0, 0); - return; } else { wrtimer(0); } -- Gitee From b677a238068353cf8571ffcae69a3a6647b96b85 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 4 Jul 2024 12:03:31 +0800 Subject: [PATCH 067/100] anolis: sw64: dts: support online-capable property for cpu device node ANBZ: #4688 On sunway platform, we add a property named online-capable to cpu device node if the related core is hot-pluggable. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/uncore_io_junzhang.h | 1 - arch/sw_64/kernel/acpi.c | 12 ------------ arch/sw_64/kernel/smp.c | 21 +++++++++------------ 3 files changed, 9 insertions(+), 25 deletions(-) diff --git a/arch/sw_64/include/asm/uncore_io_junzhang.h b/arch/sw_64/include/asm/uncore_io_junzhang.h index f553d2f61e64..770af3907b5c 100644 --- a/arch/sw_64/include/asm/uncore_io_junzhang.h +++ b/arch/sw_64/include/asm/uncore_io_junzhang.h @@ -100,7 +100,6 @@ enum { /* SPBU CSR */ enum { SMP_INFO = SPBU_BASE | 0x80UL, - VT_ONLINE_CPU = SPBU_BASE | 0x100UL, INIT_CTL = SPBU_BASE | 0x680UL, CORE_ONLINE = SPBU_BASE | 0x780UL, DLI_RLTD_FAULT = SPBU_BASE | 0x980UL, diff --git a/arch/sw_64/kernel/acpi.c b/arch/sw_64/kernel/acpi.c index 23b5a90cc7b2..990db687657e 100644 --- a/arch/sw_64/kernel/acpi.c +++ b/arch/sw_64/kernel/acpi.c @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -332,17 +331,6 @@ static int __init acpi_process_madt_sw_cintc(void) init_cpu_possible(cpu_none_mask); init_cpu_present(cpu_none_mask); -#ifdef CONFIG_SUBARCH_C4 - /* Set cpu_offline mask */ - if (is_guest_or_emul()) { - int vt_smp_cpu_num; - - vt_smp_cpu_num = sw64_io_read(0, VT_ONLINE_CPU); - for (i = vt_smp_cpu_num; i < KVM_MAX_VCPUS; i++) - cpumask_set_cpu(i, &cpu_offline); - } -#endif - /* Parse SW CINTC entries one by one */ ret = acpi_table_parse_madt(ACPI_MADT_TYPE_SW_CINTC, acpi_parse_sw_cintc, 0); diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 4d6b7f55a50a..0051deb9f346 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -274,6 +273,8 @@ static int __init fdt_setup_smp(void) struct device_node *dn = NULL; u64 boot_flag_address; u32 rcid, logical_core_id = 0; + u32 online_capable = 0; + bool available; int ret, i, version; /* Clean the map from logical core ID to physical core ID */ @@ -284,17 +285,12 @@ static int __init fdt_setup_smp(void) init_cpu_possible(cpu_none_mask); init_cpu_present(cpu_none_mask); -#ifdef CONFIG_SUBARCH_C4 - if (is_guest_or_emul()) { - int vt_smp_cpu_num; - - vt_smp_cpu_num = sw64_io_read(0, VT_ONLINE_CPU); - for (i = vt_smp_cpu_num; i < KVM_MAX_VCPUS; i++) - cpumask_set_cpu(i, &cpu_offline); - } -#endif while ((dn = of_find_node_by_type(dn, "cpu"))) { - if (!of_device_is_available(dn)) { + of_property_read_u32(dn, "online-capable", &online_capable); + + available = of_device_is_available(dn); + + if (!available && !online_capable) { pr_info("OF: Core is not available\n"); continue; } @@ -333,7 +329,8 @@ static int __init fdt_setup_smp(void) set_cpu_possible(logical_core_id, true); store_cpu_data(logical_core_id); - if (!cpumask_test_cpu(logical_core_id, &cpu_offline)) + if (!cpumask_test_cpu(logical_core_id, &cpu_offline) && + available) set_cpu_present(logical_core_id, true); rcid_information_init(version); -- Gitee From 925d124f430306862a8c800924a16f073016b154 Mon Sep 17 00:00:00 2001 From: Xu Chenjiao Date: Mon, 15 Jul 2024 09:08:21 +0000 Subject: [PATCH 068/100] anolis: sw64: pciehp: remove useless code ANBZ: #4688 Kernel get hotplug enabled/disabled status of PCIe controllers from ACPI firmware settings in sunway_pciehp driver. Signed-off-by: Xu Chenjiao Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/pci/controller/pci-sunway.c | 7 +------ drivers/pci/hotplug/sunway_pciehp_core.c | 5 ----- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/pci/controller/pci-sunway.c b/drivers/pci/controller/pci-sunway.c index 59962f9a6158..139c9515fe6f 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -327,8 +327,6 @@ static void hose_init(struct pci_controller *hose) hose->first_busno = hose->self_busno = hose->busn_space->start; hose->last_busno = hose->busn_space->end; - hose->hotplug_enable = true; - if (is_in_host()) { if (IS_ENABLED(CONFIG_PCI_MSI)) memset(hose->piu_msiconfig, 0, 256/8); @@ -648,7 +646,6 @@ enum pci_props { PROP_PIU_IOR1_BASE, PROP_RC_INDEX, PROP_PCIE_IO_BASE, - PROP_HOTPLUG_ENABLE, PROP_NUM }; @@ -661,8 +658,7 @@ const char *prop_names[PROP_NUM] = { "sw64,piu_ior0_base", "sw64,piu_ior1_base", "sw64,rc_index", - "sw64,pcie_io_base", - "sw64,hot_plug_slot_enable" + "sw64,pcie_io_base" }; static int sw64_pci_prepare_controller(struct pci_controller *hose, @@ -685,7 +681,6 @@ static int sw64_pci_prepare_controller(struct pci_controller *hose, hose->iommu_enable = false; hose->index = props[PROP_RC_INDEX]; - hose->hotplug_enable = props[PROP_HOTPLUG_ENABLE]; hose->sparse_mem_base = 0; hose->sparse_io_base = 0; diff --git a/drivers/pci/hotplug/sunway_pciehp_core.c b/drivers/pci/hotplug/sunway_pciehp_core.c index acafc82b3224..45972adcff36 100644 --- a/drivers/pci/hotplug/sunway_pciehp_core.c +++ b/drivers/pci/hotplug/sunway_pciehp_core.c @@ -280,11 +280,6 @@ static int __init sunway_pciehp_init(void) return -ENODEV; } - if (is_guest_or_emul()) { - pr_info(DRIVER_DESC " does not support for VM and emulator.\n"); - return -ENODEV; - } - pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); sunway_hose_hotplug_init(); -- Gitee From 364a9ea6a04d90f7fab3496fc3c4033855d13729 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Mon, 15 Jul 2024 14:11:22 +0800 Subject: [PATCH 069/100] anolis: sw64: add uapi reg.h ANBZ: #4688 Add uapi reg.h which defines registers in Exception frame. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/uapi/asm/reg.h | 53 +++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 arch/sw_64/include/uapi/asm/reg.h diff --git a/arch/sw_64/include/uapi/asm/reg.h b/arch/sw_64/include/uapi/asm/reg.h new file mode 100644 index 000000000000..e692e45a4936 --- /dev/null +++ b/arch/sw_64/include/uapi/asm/reg.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_ASM_SW64_REG_H +#define _UAPI_ASM_SW64_REG_H + +/* + * Exception frame offsets. + */ +#define EF_V0 0 +#define EF_T0 1 +#define EF_T1 2 +#define EF_T2 3 +#define EF_T3 4 +#define EF_T4 5 +#define EF_T5 6 +#define EF_T6 7 +#define EF_T7 8 +#define EF_S0 9 +#define EF_S1 10 +#define EF_S2 11 +#define EF_S3 12 +#define EF_S4 13 +#define EF_S5 14 +#define EF_S6 15 +#define EF_A3 16 +#define EF_A4 17 +#define EF_A5 18 +#define EF_T8 19 +#define EF_T9 20 +#define EF_T10 21 +#define EF_T11 22 +#define EF_RA 23 +#define EF_T12 24 +#define EF_AT 25 +#define EF_SP 26 +#define EF_PS 27 +#define EF_PC 28 +#define EF_GP 29 +#define EF_A0 30 +#define EF_A1 31 +#define EF_A2 32 + +#define EF_SIZE (33*8) +#define HWEF_SIZE (6*8) /* size of HMCODE frame (PS-A2) */ + +#define EF_SSIZE (EF_SIZE - HWEF_SIZE) + +/* + * Map register number into core file offset. + */ +#define CORE_REG(reg, ubase) \ + (((unsigned long *)((unsigned long)(ubase)))[reg]) + +#endif /* _UAPI_ASM_SW64_REG_H */ -- Gitee From cb313dd6db2f32d7d3f5d3f60ae42bde03676d76 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 2 Jul 2024 15:01:52 +0800 Subject: [PATCH 070/100] anolis: sw64: pci: fix unable to get node ID when numa_off is set ANBZ: #4688 The function acpi_get_node() used to get node ID of PCIe controller cannot return the correct value when numa_off is set, further causing PCIe controller initialization failure. The reason why node ID is necessary is that it is used to mark whether PCIe controller is linked up. To solve this issue, add a linkup field in struct pci_controller to mark the link status. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/pci.h | 7 ++-- arch/sw_64/pci/pci-legacy.c | 9 ++++-- drivers/pci/controller/pci-sunway.c | 43 ++++++++++++------------- drivers/pci/hotplug/sunway_pciehp_hpc.c | 6 ++-- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index 62fee7ba5dd6..e43edf203e38 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -64,6 +64,7 @@ struct pci_controller { */ unsigned int need_domain_info; bool iommu_enable; + bool linkup; struct sunway_iommu *pci_iommu; bool hotplug_enable; int first_busno; @@ -110,9 +111,9 @@ extern int sw64_pcie_config_write(struct pci_bus *bus, unsigned int devfn, 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); +extern void pci_mark_rc_linkup(struct pci_controller *hose); +extern void pci_clear_rc_linkup(struct pci_controller *hose); +extern int pci_get_rc_linkup(const struct pci_controller *hose); #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 52ba53a1fc0d..8eb5458dc2fc 100644 --- a/arch/sw_64/pci/pci-legacy.c +++ b/arch/sw_64/pci/pci-legacy.c @@ -206,6 +206,8 @@ int sw64_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) return sw64_chip_init->pci_init.map_irq(dev, slot, pin); } +static bool rc_linkup[MAX_NUMNODES][MAX_NR_RCS_PER_NODE]; + static void __init sw64_init_host(unsigned long node, unsigned long index) { @@ -233,7 +235,8 @@ sw64_init_host(unsigned long node, unsigned long index) ret = sw64_chip_init->pci_init.check_pci_linkup(hose); if (ret == 0) { /* Root Complex downstream port is link up */ - pci_mark_rc_linkup(node, index); // 8-bit per node + pci_mark_rc_linkup(hose); // 8-bit per node + rc_linkup[node][index] = true; } } @@ -245,7 +248,7 @@ static bool __init is_any_rc_linkup_one_node(unsigned long node) int i; for (i = 0; i < MAX_NR_RCS_PER_NODE; ++i) { - if (pci_get_rc_linkup(node, i)) + if (rc_linkup[node][i]) return true; } @@ -287,7 +290,7 @@ void __init sw64_init_arch(void) memset(msg, 0, 64); sprintf(msg, "Node %ld: RC [ ", node); for (i = 0; i < MAX_NR_RCS_PER_NODE; i++) { - if (pci_get_rc_linkup(node, i)) { + if (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 139c9515fe6f..db4ad9247887 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -348,25 +348,20 @@ void __init setup_chip_pci_ops(void) 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) +void pci_mark_rc_linkup(struct pci_controller *hose) { - set_bit(node * MAX_NR_RCS_PER_NODE + index, rc_linkup); + hose->linkup = true; } -EXPORT_SYMBOL(pci_mark_rc_linkup); -void pci_clear_rc_linkup(unsigned long node, unsigned long index) +void pci_clear_rc_linkup(struct pci_controller *hose) { - clear_bit(node * MAX_NR_RCS_PER_NODE + index, rc_linkup); + hose->linkup = false; } -EXPORT_SYMBOL(pci_clear_rc_linkup); -int pci_get_rc_linkup(unsigned long node, unsigned long index) +int pci_get_rc_linkup(const struct pci_controller *hose) { - return test_bit(node * MAX_NR_RCS_PER_NODE + index, rc_linkup); + return hose->linkup; } -EXPORT_SYMBOL(pci_get_rc_linkup); /** * Link the specified pci controller to list @@ -551,7 +546,7 @@ int sw64_pcie_config_read(struct pci_bus *bus, unsigned int devfn, if (unlikely(bus->number == hose->self_busno)) { ret = sw64_pcie_read_rc_cfg(bus, devfn, where, size, val); } else { - if (pci_get_rc_linkup(hose->node, hose->index)) + if (pci_get_rc_linkup(hose)) ret = pci_generic_config_read(bus, devfn, where, size, val); else return ret; @@ -715,12 +710,10 @@ static int sw64_pci_prepare_controller(struct pci_controller *hose, * Root Complex link up failed. * This usually means that no device on the slot. */ - pr_info(": link down\n", - hose->node, hose->index); + pr_info("RC link down\n"); } else { - pci_mark_rc_linkup(hose->node, hose->index); - pr_info(": successfully link up\n", - hose->node, hose->index); + pci_mark_rc_linkup(hose); + pr_info("RC successfully link up\n"); } setup_intx_irqs(hose); @@ -765,13 +758,17 @@ static int sw64_pci_ecam_init(struct pci_config_window *cfg) if (!hose) return -ENOMEM; - /* 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; +#ifdef CONFIG_ACPI_NUMA + if (!numa_off) { + /* 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; + } } +#endif /* Init pci_controller */ ret = sw64_pci_prepare_controller(hose, &adev->fwnode); diff --git a/drivers/pci/hotplug/sunway_pciehp_hpc.c b/drivers/pci/hotplug/sunway_pciehp_hpc.c index 2bb6d3ff3165..5fd0167b55e6 100644 --- a/drivers/pci/hotplug/sunway_pciehp_hpc.c +++ b/drivers/pci/hotplug/sunway_pciehp_hpc.c @@ -251,7 +251,7 @@ static bool pcie_wait_link_active(struct controller *ctrl) struct pci_controller *hose = pci_bus_to_pci_controller(bus); if (pcie_wait_for_link(pdev, true)) { - pci_mark_rc_linkup(hose->node, hose->index); + pci_mark_rc_linkup(hose); sunway_pciehp_restore_rc_piu(ctrl); return true; } @@ -403,7 +403,7 @@ int sunway_pciehp_link_disable(struct controller *ctrl) int ret; ret = __sunway_pciehp_link_set(ctrl, false); - pci_clear_rc_linkup(hose->node, hose->index); + pci_clear_rc_linkup(hose); return ret; } @@ -694,7 +694,7 @@ void sunway_pciehp_poll(struct controller *ctrl, u32 events) for (i = 0; i < 30; i++) { if (pcie_wait_for_link(pdev, true)) { - pci_mark_rc_linkup(hose->node, hose->index); + pci_mark_rc_linkup(hose); sunway_pciehp_restore_rc_piu(ctrl); writeq(HP_CTRL_FINISH, (piu_ior0_base + HP_CTRL)); -- Gitee From 46292e0028e8cb0c98d7f49cdf5bde08d5868005 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 17 Jul 2024 08:41:50 +0800 Subject: [PATCH 071/100] anolis: sw64: pci: fix compile error when CONFIG_PCI_MSI=n ANBZ: #4688 Provide empty implementations of function vt_handle_pci_msi_interrupt() and msic_acpi_init() to fix compile error when CONFIG_PCI_MSI=n. This commit also removes some meaningless logs. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/irq.h | 3 --- arch/sw_64/include/asm/msi.h | 11 +++++++++++ arch/sw_64/pci/pci.c | 2 -- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/sw_64/include/asm/irq.h b/arch/sw_64/include/asm/irq.h index 6a4abfc9687b..13f3dbac3491 100644 --- a/arch/sw_64/include/asm/irq.h +++ b/arch/sw_64/include/asm/irq.h @@ -38,9 +38,6 @@ 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 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); diff --git a/arch/sw_64/include/asm/msi.h b/arch/sw_64/include/asm/msi.h index 4bec4b80fbe6..5f2cfe7f4bd7 100644 --- a/arch/sw_64/include/asm/msi.h +++ b/arch/sw_64/include/asm/msi.h @@ -40,6 +40,8 @@ extern struct irq_chip sw64_irq_chip; extern void handle_pci_msi_interrupt(unsigned long type, unsigned long vector, unsigned long pci_msi1_addr); +extern int __init msic_acpi_init(struct irq_domain *parent, + struct acpi_madt_sw_msic *msic); #define MSI_ADDR_BASE_HI 0 #define MSI_ADDR_BASE_LO 0x91abc0 @@ -93,5 +95,14 @@ static inline void handle_pci_msi_interrupt(unsigned long type, { pr_warn("SW arch disable CONFIG_PCI_MSI option.\n"); } + +static inline void vt_handle_pci_msi_interrupt(unsigned long type, + unsigned long vector, unsigned long pci_msi1_addr) +{ + pr_warn("SW arch disable CONFIG_PCI_MSI option.\n"); +} + +static inline int __init msic_acpi_init(struct irq_domain *parent, + struct acpi_madt_sw_msic *msic) { return 0; } #endif /* CONFIG_PCI_MSI */ #endif /* _ASM_SW64_MSI_H */ diff --git a/arch/sw_64/pci/pci.c b/arch/sw_64/pci/pci.c index de56ccfda574..de974eff019d 100644 --- a/arch/sw_64/pci/pci.c +++ b/arch/sw_64/pci/pci.c @@ -400,8 +400,6 @@ void sw64_pci_root_bridge_scan_finish_up(struct pci_host_bridge *bridge) pci_bus_update_busn_res_end(bus, last_bus); last_bus++; - pr_info("bus number update to %u\n", last_bus); - if (is_in_host()) sw64_pci_root_bridge_reserve_legacy_io(bridge); -- Gitee From 5dedea34f67dc2c3357c509f29e44d799352a3b2 Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Thu, 18 Jul 2024 11:34:43 +0000 Subject: [PATCH 072/100] anolis: sw64: fix C4 INTx configuration ANBZ: #4688 Correct the assembly logic for C4's INTxCONFIG to ensure that INTx interrupts delivered to the intended target. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/irqchip/irq-sunway-pci-intx.c | 29 ++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/irqchip/irq-sunway-pci-intx.c b/drivers/irqchip/irq-sunway-pci-intx.c index 434a0c1156de..a60262fafeb3 100644 --- a/drivers/irqchip/irq-sunway-pci-intx.c +++ b/drivers/irqchip/irq-sunway-pci-intx.c @@ -28,23 +28,38 @@ static void set_intx(struct pci_controller *hose, unsigned long intx_conf) piu_ior0_base = hose->piu_ior0_base; - writeq(intx_conf | (0x8UL << 10), (piu_ior0_base + INTACONFIG)); - writeq(intx_conf | (0x4UL << 10), (piu_ior0_base + INTBCONFIG)); - writeq(intx_conf | (0x2UL << 10), (piu_ior0_base + INTCCONFIG)); - writeq(intx_conf | (0x1UL << 10), (piu_ior0_base + INTDCONFIG)); + if (IS_ENABLED(CONFIG_SUBARCH_C3B)) { + writeq(intx_conf | (0x8UL << 10), (piu_ior0_base + INTACONFIG)); + writeq(intx_conf | (0x4UL << 10), (piu_ior0_base + INTBCONFIG)); + writeq(intx_conf | (0x2UL << 10), (piu_ior0_base + INTCCONFIG)); + writeq(intx_conf | (0x1UL << 10), (piu_ior0_base + INTDCONFIG)); + } else { + writeq(intx_conf | (0x8UL << 10), (piu_ior0_base + INTDCONFIG)); + writeq(intx_conf | (0x4UL << 10), (piu_ior0_base + INTCCONFIG)); + writeq(intx_conf | (0x2UL << 10), (piu_ior0_base + INTBCONFIG)); + writeq(intx_conf | (0x1UL << 10), (piu_ior0_base + INTACONFIG)); + } } static int __assign_piu_intx_config(struct pci_controller *hose, cpumask_t *targets) { unsigned long intx_conf; unsigned int cpu; - int phy_cpu; + int thread, node, core, rcid; /* Use the last cpu in valid cpus to avoid core 0. */ cpu = cpumask_last(targets); - phy_cpu = cpu_to_rcid(cpu); + rcid = cpu_to_rcid(cpu); + + thread = rcid_to_thread_id(rcid); + node = rcid_to_domain_id(rcid); + core = rcid_to_core_id(rcid); + + if (IS_ENABLED(CONFIG_SUBARCH_C3B)) + intx_conf = core | (node << 6); + else + intx_conf = core | (thread << 6) | (node << 7); - intx_conf = ((phy_cpu >> 5) << 6) | (phy_cpu & 0x1f); set_intx(hose, intx_conf); return 0; -- Gitee From ed5c9c7a9644c4313d000e67a224bde0f9f7e3b2 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 13 Jun 2024 09:37:53 +0800 Subject: [PATCH 073/100] anolis: sw64: smp: allow NR_CPUS less than the number detected by firmware ANBZ: #4688 When NR_CPUS is less than the number detected by firmware, smp initialization can still succeed, and the number of cores is limited to NR_CPUS. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/acpi.c | 4 ++-- arch/sw_64/kernel/smp.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/sw_64/kernel/acpi.c b/arch/sw_64/kernel/acpi.c index 990db687657e..02a4e8fa9c95 100644 --- a/arch/sw_64/kernel/acpi.c +++ b/arch/sw_64/kernel/acpi.c @@ -249,9 +249,9 @@ 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 "Core [0x%x] exceeds max core num [%u]\n", + pr_warn_once(PREFIX "Core [0x%x] exceeds max core num [%u]\n", rcid, nr_cpu_ids); - return -ENODEV; + return 0; } /* The rcid of each core is unique */ diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 0051deb9f346..02db49e919e4 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -302,9 +302,9 @@ static int __init fdt_setup_smp(void) } if (logical_core_id >= nr_cpu_ids) { - pr_err("OF: Core [0x%x] exceeds max core num [%u]\n", + pr_warn_once("OF: Core [0x%x] exceeds max core num [%u]\n", rcid, nr_cpu_ids); - return -ENODEV; + return 0; } if (is_rcid_duplicate(rcid)) { -- Gitee From 9f3a7a9c610cc4ff797ad019a030c6c233512567 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 17 Jul 2024 20:01:16 +0800 Subject: [PATCH 074/100] anolis: sw64: kexec: remove code for compatibility with builtin DTB ANBZ: #4688 Starting from junzhang, builtin DTB is no longer supported, so we can remove related code. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/machine_kexec.c | 60 ------------------------------- 1 file changed, 60 deletions(-) diff --git a/arch/sw_64/kernel/machine_kexec.c b/arch/sw_64/kernel/machine_kexec.c index a85cca14444b..f0a2338ddcbd 100644 --- a/arch/sw_64/kernel/machine_kexec.c +++ b/arch/sw_64/kernel/machine_kexec.c @@ -285,53 +285,6 @@ static void *arch_kexec_alloc_and_setup_fdt(unsigned long initrd_start, 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 }; @@ -364,19 +317,6 @@ static void update_boot_params(void) 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 /* update dtb base address */ sunway_dtb_address = params.dtb_start; -- Gitee From a9683c5a9f22443009c5e9979e16fb6454e06ce6 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 23 Jul 2024 15:32:16 +0800 Subject: [PATCH 075/100] anolis: sw64: kvm: don't retrieve memory slot again in page fault handler ANBZ: #4688 It is unnecessary to retrieve the memory slot again in user_mem_abort() because the corresponding memory slot has been passed from the caller. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 27889a0d795c..235088af8b39 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -1218,16 +1218,17 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, mmu_seq = vcpu->kvm->mmu_invalidate_seq; /* * Ensure the read of mmu_invalidate_seq happens before we call - * gfn_to_pfn_prot (which calls get_user_pages), so that we don't risk - * the page we just got a reference to gets unmapped before we have a - * chance to grab the mmu_lock, which ensure that if the page gets + * __gfn_to_pfn_memslot (which calls get_user_pages), so that we don't + * risk the page we just got a reference to gets unmapped before we have + * a chance to grab the mmu_lock, which ensure that if the page gets * unmapped afterwards, the call to kvm_unmap_gfn will take it away * from us again properly. This smp_rmb() interacts with the smp_wmb() * in kvm_mmu_notifier_invalidate_. */ smp_rmb(); - pfn = gfn_to_pfn_prot(kvm, gfn, write_fault, &writable); + pfn = __gfn_to_pfn_memslot(memslot, gfn, false, false, NULL, + write_fault, &writable, NULL); if (pfn == KVM_PFN_ERR_HWPOISON) { kvm_send_hwpoison_signal(hva, vma); @@ -1329,7 +1330,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, if (writable) { new_pte = kvm_pte_mkwrite(new_pte); kvm_set_pfn_dirty(pfn); - mark_page_dirty(kvm, gfn); + mark_page_dirty_in_slot(kvm, memslot, gfn); } if (exec_fault && fault_status == AF_STATUS_INV) { -- Gitee From 9f28ad60ea1889eaf9be3252aee96b8517621a8a Mon Sep 17 00:00:00 2001 From: Xu Chenjiao Date: Mon, 22 Jul 2024 10:36:50 +0000 Subject: [PATCH 076/100] anolis: sw64: pciehp: fix compile error when CONFIG_PCIE_DPC=y ANBZ: #4688 The DPC function is not supported now. Signed-off-by: Xu Chenjiao Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/pci/hotplug/sunway_pciehp_hpc.c | 36 ------------------------- 1 file changed, 36 deletions(-) diff --git a/drivers/pci/hotplug/sunway_pciehp_hpc.c b/drivers/pci/hotplug/sunway_pciehp_hpc.c index 5fd0167b55e6..5e762cfd54f8 100644 --- a/drivers/pci/hotplug/sunway_pciehp_hpc.c +++ b/drivers/pci/hotplug/sunway_pciehp_hpc.c @@ -722,32 +722,6 @@ void sunway_pciehp_poll(struct controller *ctrl, u32 events) } } -static void sunway_pciehp_ignore_dpc_link_change(struct controller *ctrl, - struct pci_dev *pdev, int irq) -{ - /* - * Ignore link changes which occurred while waiting for DPC recovery. - * Could be several if DPC triggered multiple times consecutively. - */ - synchronize_hardirq(irq); - atomic_and(~PCI_EXP_SLTSTA_DLLSC, &ctrl->pending_events); - if (sunway_pciehp_poll_mode) - pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, - PCI_EXP_SLTSTA_DLLSC); - ctrl_info(ctrl, "Slot(%s): Link Down/Up ignored (recovered by DPC)\n", - slot_name(ctrl)); - - /* - * If the link is unexpectedly down after successful recovery, - * the corresponding link change may have been ignored above. - * Synthesize it to ensure that it is acted on. - */ - down_read_nested(&ctrl->reset_lock, ctrl->depth); - if (!sunway_pciehp_check_link_active(ctrl)) - sunway_pciehp_request(ctrl, PCI_EXP_SLTSTA_DLLSC); - up_read(&ctrl->reset_lock); -} - static irqreturn_t sunway_pciehp_isr(int irq, void *dev_id) { struct controller *ctrl = (struct controller *)dev_id; @@ -906,16 +880,6 @@ static irqreturn_t sunway_pciehp_ist(int irq, void *dev_id) PCI_EXP_SLTCTL_ATTN_IND_ON); } - /* - * Ignore Link Down/Up events caused by Downstream Port Containment - * if recovery from the error succeeded. - */ - if ((events & PCI_EXP_SLTSTA_DLLSC) && pci_dpc_recovered(pdev) && - ctrl->state == ON_STATE) { - events &= ~PCI_EXP_SLTSTA_DLLSC; - sunway_pciehp_ignore_dpc_link_change(ctrl, pdev, irq); - } - /* * Disable requests have higher priority than Presence Detect Changed * or Data Link Layer State Changed events. -- Gitee From c40125bcdec624fbb6fa53fa5fc6809e82c62f2d Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 23 Jul 2024 15:06:21 +0800 Subject: [PATCH 077/100] anolis: sw64: kvm: fix invalid memslot flags checking during dirty logging ANBZ: #4688 We do not define __KVM_HAVE_READONLY_MEM now, so it is impossible to have KVM_MEM_READONLY flag set. And it is more reasonable to confirm the dirty logging status by KVM_MEM_LOG_DIRTY_PAGES. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 235088af8b39..ee57f0c85b86 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -41,7 +41,7 @@ static bool memslot_is_logging(struct kvm_memory_slot *memslot) { - return memslot->dirty_bitmap && !(memslot->flags & KVM_MEM_READONLY); + return memslot->dirty_bitmap && (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES); } /* -- Gitee From 3430f0b7223b7d0b4420b0b32a3f67bcf3486fdd Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 23 Jul 2024 15:31:10 +0800 Subject: [PATCH 078/100] anolis: sw64: kvm: enable ring-based dirty page tracking ANBZ: #4688 This patch introduces dirty ring feature. Different from dirty bitmap which needs to pull the whole bitmap to userspace and go through every bit even it is sparse, dirty ring records the dense dirty list of gfn which is mapped into userspace to allow fast dirty sync. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/kvm_host.h | 1 - arch/sw_64/include/uapi/asm/kvm.h | 2 ++ arch/sw_64/kvm/Kconfig | 1 + arch/sw_64/kvm/mmu.c | 10 +++++++--- arch/sw_64/kvm/sw64.c | 20 +++++++++++++++----- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/arch/sw_64/include/asm/kvm_host.h b/arch/sw_64/include/asm/kvm_host.h index cce39b0289e5..e2f367003509 100644 --- a/arch/sw_64/include/asm/kvm_host.h +++ b/arch/sw_64/include/asm/kvm_host.h @@ -159,7 +159,6 @@ struct kvm_vcpu_stat { #endif void update_vcpu_stat_time(struct kvm_vcpu_stat *vcpu_stat); -void check_vcpu_requests(struct kvm_vcpu *vcpu); void sw64_kvm_switch_vpn(struct kvm_vcpu *vcpu); int vmem_init(void); void vmem_exit(void); diff --git a/arch/sw_64/include/uapi/asm/kvm.h b/arch/sw_64/include/uapi/asm/kvm.h index 3215aaa5f2eb..430e82acee3e 100644 --- a/arch/sw_64/include/uapi/asm/kvm.h +++ b/arch/sw_64/include/uapi/asm/kvm.h @@ -9,6 +9,8 @@ #define IRQ_PENDING_INTX_SHIFT 16 #define IRQ_PENDING_MSI_VECTORS_SHIFT 18 +#define KVM_DIRTY_LOG_PAGE_OFFSET 64 + enum SW64_KVM_IRQ { SW64_KVM_IRQ_IPI = 27, SW64_KVM_IRQ_TIMER = 9, diff --git a/arch/sw_64/kvm/Kconfig b/arch/sw_64/kvm/Kconfig index fdff308aed22..5fac5b1d9fb4 100644 --- a/arch/sw_64/kvm/Kconfig +++ b/arch/sw_64/kvm/Kconfig @@ -31,6 +31,7 @@ config KVM select TUN select GENERIC_ALLOCATOR select KVM_GENERIC_DIRTYLOG_READ_PROTECT + select HAVE_KVM_DIRTY_RING_ACQ_REL help Support for hosting Guest kernels. We don't support KVM with 3-level page tables yet. diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index ee57f0c85b86..b161b2ed8c8c 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -39,9 +39,13 @@ #include "trace.h" #define KVM_APT_FLAG_LOGGING_ACTIVE (1UL << 1) -static bool memslot_is_logging(struct kvm_memory_slot *memslot) +static bool memslot_is_logging(struct kvm *kvm, struct kvm_memory_slot *memslot) { - return memslot->dirty_bitmap && (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES); + if (!kvm->dirty_ring_size) + return memslot->dirty_bitmap + && (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES); + else + return memslot->flags & KVM_MEM_LOG_DIRTY_PAGES; } /* @@ -1171,7 +1175,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, bool logging_active, write_fault, exec_fault, writable, force_pte; force_pte = false; - logging_active = memslot_is_logging(memslot); + logging_active = memslot_is_logging(kvm, memslot); fault_gpa = vcpu->arch.vcb.fault_gpa; gfn = fault_gpa >> PAGE_SHIFT; as_info = vcpu->arch.vcb.as_info; diff --git a/arch/sw_64/kvm/sw64.c b/arch/sw_64/kvm/sw64.c index a22a7f78c2cb..d0510e567c32 100644 --- a/arch/sw_64/kvm/sw64.c +++ b/arch/sw_64/kvm/sw64.c @@ -122,7 +122,7 @@ void sw64_kvm_switch_vpn(struct kvm_vcpu *vcpu) } } -void check_vcpu_requests(struct kvm_vcpu *vcpu) +static int check_vcpu_requests(struct kvm_vcpu *vcpu) { unsigned long vpn; long cpu = smp_processor_id(); @@ -132,7 +132,12 @@ void check_vcpu_requests(struct kvm_vcpu *vcpu) vpn = vcpu->arch.vpnc[cpu] & VPN_MASK; tbivpn(0, 0, vpn); } + + if (kvm_dirty_ring_check_request(vcpu)) + return 0; } + + return 1; } struct kvm_stats_debugfs_item debugfs_entries[] = { @@ -452,9 +457,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) } if (ret <= 0) { - local_irq_enable(); - preempt_enable(); - continue; + goto exit; } memset(&hargs, 0, sizeof(hargs)); @@ -474,7 +477,14 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) vcpu->arch.halted = 0; sw64_kvm_switch_vpn(vcpu); - check_vcpu_requests(vcpu); + ret = check_vcpu_requests(vcpu); + if (ret <= 0) { +exit: + local_irq_enable(); + preempt_enable(); + continue; + } + guest_enter_irqoff(); /* update aptp before the guest runs */ -- Gitee From 9bd1f805c7502e78b423adb9e5de728acada4d33 Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Thu, 8 Aug 2024 11:13:17 +0800 Subject: [PATCH 079/100] anolis: sw64: remove redundant link options ANBZ: #4688 Due to an issue with the binutils-dev package, extra link options were added to support libbfd. But a better approach is to fix the binutils-dev and remove the extra link options from kernel source. Signed-off-by: He Chuyue Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- tools/build/feature/Makefile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index cb57e46cec4b..2753d8f028c4 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 include ../../scripts/Makefile.include -ARCH ?= $(shell uname -m) FILES= \ test-all.bin \ test-backtrace.bin \ @@ -88,11 +87,7 @@ all: $(FILES) __BUILD = $(CC) $(CFLAGS) -MD -Wall -Werror -o $@ $(patsubst %.bin,%.c,$(@F)) $(LDFLAGS) BUILD = $(__BUILD) > $(@:.bin=.make.output) 2>&1 -ifeq ($(ARCH),sw_64) - BUILD_BFD = $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz -else BUILD_BFD = $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl -endif BUILD_ALL = $(BUILD) -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -lslang $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz -llzma -lzstd -lcap __BUILDXX = $(CXX) $(CXXFLAGS) -MD -Wall -Werror -o $@ $(patsubst %.bin,%.cpp,$(@F)) $(LDFLAGS) -- Gitee From da11641c6a36832947c93577bf1c19baec790b4b Mon Sep 17 00:00:00 2001 From: Zhi Tongze Date: Wed, 5 Jun 2024 09:26:51 +0800 Subject: [PATCH 080/100] anolis: sw64: add basic frequency scaling support for JunZhang ANBZ: #4688 This patch adds basic frequency scaling support for JunZhang SoC, and fixes mismatch of mhz and khz in sw64_cpufreq_debugfs. Signed-off-by: Zhi Tongze Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/cpufreq.h | 41 +++- arch/sw_64/include/asm/uncore_io_junzhang.h | 1 + arch/sw_64/platform/Makefile | 2 +- .../platform/{cpufreq_xuelang.c => cpufreq.c} | 192 +++++++++++------- drivers/cpufreq/Kconfig | 1 - drivers/cpufreq/sw64_cpufreq_debugfs.c | 28 +-- 6 files changed, 159 insertions(+), 106 deletions(-) rename arch/sw_64/platform/{cpufreq_xuelang.c => cpufreq.c} (31%) diff --git a/arch/sw_64/include/asm/cpufreq.h b/arch/sw_64/include/asm/cpufreq.h index e6f1d16e5620..70dfc67cf4e8 100644 --- a/arch/sw_64/include/asm/cpufreq.h +++ b/arch/sw_64/include/asm/cpufreq.h @@ -38,23 +38,42 @@ struct clk { #define CLK_ALWAYS_ENABLED (1 << 0) #define CLK_RATE_PROPAGATES (1 << 1) -#define CLK_PRT 0x1UL -#define CORE_CLK0_V (0x1UL << 1) -#define CORE_CLK0_R (0x1UL << 2) -#define CORE_CLK2_V (0x1UL << 15) -#define CORE_CLK2_R (0x1UL << 16) - -#define CLK_LV1_SEL_PRT 0x1UL -#define CLK_LV1_SEL_MUXA (0x1UL << 2) -#define CLK_LV1_SEL_MUXB (0x1UL << 3) - +#define CORE_CLK0_VALID (0x1UL << 1) +#define CORE_CLK0_RESET (0x1UL << 2) + +#define CLK_LV1_SEL_PROTECT (0x1UL << 0) +#define CLK_LV1_SEL_MUXA (0x1UL << 2) +#define CLK_LV1_SEL_MUXB (0x1UL << 3) + +#ifdef CONFIG_UNCORE_JUNZHANG +#define CLK0_PROTECT (0x1UL << 0) +#define CLK2_PROTECT (0x1UL << 32) +#define CORE_CLK2_VALID (0x1UL << 33) +#define CORE_CLK2_RESET (0x1UL << 34) +#define CORE_CLK2_LOCK (0x1UL << 35) +#define CORE_PLL0_CFG_SHIFT 20 +#define CORE_PLL2_CFG_SHIFT 36 +#define CORE_PLL2_CFG_MASK 0x1f +#define STARTUP_RATE (2000UL * 1000 * 1000) +#endif + +#ifdef CONFIG_UNCORE_XUELANG +#define CLK_PROTECT (0x1UL << 0) +#define CLK0_PROTECT CLK_PROTECT +#define CLK2_PROTECT CLK_PROTECT +#define CORE_CLK2_VALID (0x1UL << 15) +#define CORE_CLK2_RESET (0x1UL << 16) +#define CORE_CLK2_LOCK (0x1UL << 17) #define CORE_PLL0_CFG_SHIFT 4 #define CORE_PLL2_CFG_SHIFT 18 +#define CORE_PLL2_CFG_MASK 0xf +#define STARTUP_RATE (2400UL * 1000 * 1000) +#endif extern struct cpufreq_frequency_table freq_table[]; int clk_init(void); -void sw64_set_rate(unsigned int index); +int sw64_set_rate(unsigned int index); struct clk *sw64_clk_get(struct device *dev, const char *id); diff --git a/arch/sw_64/include/asm/uncore_io_junzhang.h b/arch/sw_64/include/asm/uncore_io_junzhang.h index 770af3907b5c..e21876f70d1e 100644 --- a/arch/sw_64/include/asm/uncore_io_junzhang.h +++ b/arch/sw_64/include/asm/uncore_io_junzhang.h @@ -120,6 +120,7 @@ enum { MC_ONLINE = SPBU_BASE | 0x3780UL, CLK_CTL = SPBU_BASE | 0x3b80UL, CLU_LV2_SELH = SPBU_BASE | 0x3a00UL, + CLU_LV1_SEL = SPBU_BASE | 0x3a80UL, CLU_LV2_SELL = SPBU_BASE | 0x3b00UL, PIU_TOP0_CONFIG = SPBU_BASE | 0x4c80UL, PIU_TOP1_CONFIG = SPBU_BASE | 0x4d00UL, diff --git a/arch/sw_64/platform/Makefile b/arch/sw_64/platform/Makefile index 4c0edceb4a2c..09ed3eb0f743 100644 --- a/arch/sw_64/platform/Makefile +++ b/arch/sw_64/platform/Makefile @@ -1,2 +1,2 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_PLATFORM_XUELANG) += cpufreq_xuelang.o +obj-y += cpufreq.o diff --git a/arch/sw_64/platform/cpufreq_xuelang.c b/arch/sw_64/platform/cpufreq.c similarity index 31% rename from arch/sw_64/platform/cpufreq_xuelang.c rename to arch/sw_64/platform/cpufreq.c index e639fdc34fb9..87f66b2313b5 100644 --- a/arch/sw_64/platform/cpufreq_xuelang.c +++ b/arch/sw_64/platform/cpufreq.c @@ -1,51 +1,101 @@ // SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include #include -#include -#include #include +#include +#include +#include +#include +#include -/* Minimum CLK support */ -enum { - DC_0, DC_1, DC_2, DC_3, DC_4, DC_5, DC_6, DC_7, DC_8, - DC_9, DC_10, DC_11, DC_12, DC_13, DC_14, DC_15, DC_RESV -}; - -struct cpufreq_frequency_table freq_table[] = { - {0, 200, CPUFREQ_ENTRY_INVALID}, - {0, DC_1, CPUFREQ_ENTRY_INVALID}, - {0, DC_2, 0}, - {0, DC_3, 0}, - {0, DC_4, 0}, - {0, DC_5, 0}, - {0, DC_6, 0}, - {0, DC_7, 0}, - {0, DC_8, 0}, - {0, DC_9, 0}, - {0, DC_10, 0}, - {0, DC_11, 0}, - {0, DC_12, 0}, - {0, DC_13, 0}, - {0, DC_14, 0}, - {0, DC_15, 0}, - {-1, DC_RESV, CPUFREQ_TABLE_END}, -}; - +#define MAX_RETRY 10 static struct platform_device sw64_cpufreq_device = { .name = "sw64_cpufreq", .id = -1, }; -static int __init sw64_cpufreq_init(void) +/* + * frequency in MHz, volts in mV and stored as "driver_data" in the structure. + * volts 0 means to be determined + */ +#define FV(mhz, mv) \ + { \ + .frequency = (mhz) * 1000, \ + .driver_data = (mv) \ + } + +#ifdef CONFIG_PLATFORM_JUNZHANG +struct cpufreq_frequency_table freq_table[] = { + {0, 0, CPUFREQ_ENTRY_INVALID}, /* 200Mhz is ignored */ + FV(1200, 850), + FV(1300, 850), + FV(1400, 850), + FV(1450, 850), + FV(1500, 850), + FV(1550, 850), + FV(1600, 850), + FV(1650, 900), + FV(1700, 900), + FV(1750, 900), + FV(1800, 900), + FV(1850, 900), + FV(1900, 900), + FV(1950, 900), + FV(2000, 900), + FV(2050, 950), + FV(2100, 950), + FV(2150, 950), + FV(2200, 950), + FV(2250, 0), + FV(2300, 0), + FV(2350, 0), + FV(2400, 0), + FV(2450, 0), + FV(2500, 0), + FV(2550, 0), + FV(2600, 0), + FV(2650, 0), + FV(2700, 0), + FV(2800, 0), + FV(2850, 0), + {0, 0, CPUFREQ_TABLE_END}, +}; +static void __init fill_freq_table(struct cpufreq_frequency_table *ft) +{ +} +#elif CONFIG_PLATFORM_XUELANG +struct cpufreq_frequency_table freq_table[] = { + {0, 0, CPUFREQ_ENTRY_INVALID}, /* 200Mhz is ignored */ + {0, 0, CPUFREQ_ENTRY_INVALID}, /* 1200Mhz is ignored */ + {0, 0, CPUFREQ_ENTRY_INVALID}, + {0, 0, CPUFREQ_ENTRY_INVALID}, + {0, 0, CPUFREQ_ENTRY_INVALID}, + {0, 0, CPUFREQ_ENTRY_INVALID}, + {0, 0, CPUFREQ_ENTRY_INVALID}, + {0, 0, CPUFREQ_ENTRY_INVALID}, + {0, 0, CPUFREQ_ENTRY_INVALID}, + {0, 0, CPUFREQ_ENTRY_INVALID}, + {0, 0, CPUFREQ_ENTRY_INVALID}, + {0, 0, CPUFREQ_ENTRY_INVALID}, + {0, 0, CPUFREQ_ENTRY_INVALID}, + {0, 0, CPUFREQ_ENTRY_INVALID}, + {0, 0, CPUFREQ_ENTRY_INVALID}, + {0, 0, CPUFREQ_ENTRY_INVALID}, + {0, 0, CPUFREQ_TABLE_END}, +}; + +static void __init fill_freq_table(struct cpufreq_frequency_table *ft) { int i; + unsigned long freq_off; unsigned char external_clk; - unsigned long max_rate, freq_off; - - max_rate = get_cpu_freq() / 1000; - external_clk = *((unsigned char *)__va(MB_EXTCLK)); if (external_clk == 240) @@ -53,19 +103,22 @@ static int __init sw64_cpufreq_init(void) else freq_off = 50000; - /* clock table init */ + freq_table[2].frequency = freq_off * 36; + for (i = 3; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) + freq_table[i].frequency = freq_off * 38 + ((i - 3) * freq_off); +} +#endif + +static int __init sw64_cpufreq_init(void) +{ + int i; + unsigned long max_rate = get_cpu_freq() / 1000; + + fill_freq_table(freq_table); for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { - if (i == 1) - freq_table[i].driver_data = freq_off * 24; - if (i == 2) - freq_table[i].frequency = freq_off * 36; - if (i > 2) - freq_table[i].frequency = freq_off * 38 + ((i - 3) * freq_off); - - if (freq_table[i].frequency == max_rate) - freq_table[i + 1].frequency = CPUFREQ_TABLE_END; + if (max_rate == freq_table[i].frequency) + freq_table[i+1].frequency = CPUFREQ_TABLE_END; } - return platform_device_register(&sw64_cpufreq_device); } arch_initcall(sw64_cpufreq_init); @@ -73,7 +126,7 @@ arch_initcall(sw64_cpufreq_init); static struct clk cpu_clk = { .name = "cpu_clk", .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, - .rate = 2400000000, + .rate = STARTUP_RATE, }; struct clk *sw64_clk_get(struct device *dev, const char *id) @@ -89,6 +142,7 @@ unsigned int __sw64_cpufreq_get(struct cpufreq_policy *policy) struct cpufreq_frequency_table *ft = policy->freq_table; val = sw64_io_read(0, CLK_CTL) >> CORE_PLL2_CFG_SHIFT; + val &= CORE_PLL2_CFG_MASK; for (i = 0; ft[i].frequency != CPUFREQ_TABLE_END; i++) { if (val == i) @@ -98,41 +152,29 @@ unsigned int __sw64_cpufreq_get(struct cpufreq_policy *policy) } EXPORT_SYMBOL(__sw64_cpufreq_get); -void sw64_set_rate(unsigned int index) +int sw64_set_rate(unsigned int index) { - unsigned int i, val; - int cpu_num; + int i, retry, cpu_num; cpu_num = sw64_chip->get_cpu_num(); - for (i = 0; i < cpu_num; i++) { - sw64_io_write(i, CLK_CTL, CORE_CLK2_R | CORE_CLK2_V | CLK_PRT); - val = sw64_io_read(i, CLK_CTL); - - sw64_io_write(i, CLK_CTL, val | index << CORE_PLL2_CFG_SHIFT); - + sw64_io_write(i, CLU_LV1_SEL, CLK_LV1_SEL_PROTECT); + sw64_io_write(i, CLK_CTL, CLK2_PROTECT | CORE_CLK2_RESET | CORE_CLK2_VALID | CLK0_PROTECT); + sw64_io_write(i, CLK_CTL, CLK2_PROTECT | CORE_CLK2_VALID | (unsigned long)index << CORE_PLL2_CFG_SHIFT); udelay(1); - - sw64_io_write(i, CLK_CTL, CORE_CLK2_V | CLK_PRT - | index << CORE_PLL2_CFG_SHIFT); - val = sw64_io_read(i, CLK_CTL); - - /* LV1 select PLL1/PLL2 */ - sw64_io_write(i, CLU_LV1_SEL, CLK_LV1_SEL_MUXA | CLK_LV1_SEL_PRT); - - /* Set CLK_CTL PLL0 */ - sw64_io_write(i, CLK_CTL, val | CORE_CLK0_R | CORE_CLK0_V); - - sw64_io_write(i, CLK_CTL, val | CORE_CLK0_R | CORE_CLK0_V - | index << CORE_PLL0_CFG_SHIFT); - - udelay(1); - - sw64_io_write(i, CLK_CTL, val | CORE_CLK0_V - | index << CORE_PLL0_CFG_SHIFT); - - /* LV1 select PLL0/PLL1 */ - sw64_io_write(i, CLU_LV1_SEL, CLK_LV1_SEL_MUXB | CLK_LV1_SEL_PRT); + sw64_io_write(i, CLK_CTL, CORE_CLK2_VALID); + retry = 0; + while (retry < MAX_RETRY) { + if (sw64_io_read(i, CLK_CTL) & CORE_CLK2_LOCK) + break; + retry++; + udelay(100); + } + if (retry == MAX_RETRY) + return -ETIME; + sw64_io_write(i, CLK_CTL, 0); + sw64_io_write(i, CLU_LV1_SEL, CLK_LV1_SEL_MUXA | CLK_LV1_SEL_MUXB | CLK_LV1_SEL_PROTECT); } + return 0; } EXPORT_SYMBOL_GPL(sw64_set_rate); diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index d1fdea27eb0d..980107a10863 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -317,7 +317,6 @@ endif if SW64 config SW64_CPUFREQ bool "SW64 CPU Frequency interface" - depends on UNCORE_XUELANG default y help This adds the CPUFreq driver for SW64 processor which supports diff --git a/drivers/cpufreq/sw64_cpufreq_debugfs.c b/drivers/cpufreq/sw64_cpufreq_debugfs.c index bb4ae26bc22b..f72dbb9d5e16 100644 --- a/drivers/cpufreq/sw64_cpufreq_debugfs.c +++ b/drivers/cpufreq/sw64_cpufreq_debugfs.c @@ -8,25 +8,22 @@ #include #include +/* Show cpufreq in Mhz */ static int cpufreq_show(struct seq_file *m, void *v) { int i; u64 val; - int freq; - - val = sw64_io_read(0, CLK_CTL); - val = val >> CORE_PLL2_CFG_SHIFT; + val = sw64_io_read(0, CLK_CTL) >> CORE_PLL2_CFG_SHIFT; + val &= CORE_PLL2_CFG_MASK; + seq_puts(m, "CPU frequency in Mhz:\n"); for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { - if (freq_table[i].frequency != CPUFREQ_ENTRY_INVALID) - freq = freq_table[i].frequency; - else - freq = freq_table[i].driver_data; - + if (freq_table[i].frequency == CPUFREQ_ENTRY_INVALID) + continue; if (val == i) - seq_printf(m, "[%d] ", freq); + seq_printf(m, "[%d] ", freq_table[i].frequency / 1000); else - seq_printf(m, "%d ", freq); + seq_printf(m, "%d ", freq_table[i].frequency / 1000); } seq_puts(m, "\n"); @@ -53,15 +50,10 @@ static ssize_t cpufreq_set(struct file *file, const char __user *user_buf, err = kstrtoint(buf, 10, &cf); if (err) return err; - + cf *= 1000; /* convert Mhz to khz */ index = -1; for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { - if (freq_table[i].frequency != CPUFREQ_ENTRY_INVALID) - freq = freq_table[i].frequency; - else - freq = freq_table[i].driver_data; - - if (cf == freq) { + if (cf == freq_table[i].frequency) { index = i; break; } -- Gitee From 900351682e79932218eadb3195beaeaeaa27567d Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 23 May 2024 09:38:34 +0800 Subject: [PATCH 081/100] anolis: sw64: platform: add misc platform driver ANBZ: #4688 Add a platform driver to sunway platform. The driver is bound to platform devices that hold base addresses for some sunway platform specific peripherals. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/platform.h | 8 ++ drivers/platform/sw64/Makefile | 1 + drivers/platform/sw64/misc-platform.c | 168 ++++++++++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 drivers/platform/sw64/misc-platform.c diff --git a/arch/sw_64/include/asm/platform.h b/arch/sw_64/include/asm/platform.h index 4f93d9532f9a..df5e570ccc5f 100644 --- a/arch/sw_64/include/asm/platform.h +++ b/arch/sw_64/include/asm/platform.h @@ -33,4 +33,12 @@ 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); +extern void __iomem *misc_platform_get_spbu_base(unsigned long node); +extern void __iomem *misc_platform_get_intpu_base(unsigned long node); +extern void __iomem *misc_platform_get_gpio_base(unsigned long node); + +#ifdef CONFIG_SUBARCH_C3B +extern void __iomem *misc_platform_get_cab0_base(unsigned long node); +#endif + #endif /* _ASM_SW64_PLATFORM_H */ diff --git a/drivers/platform/sw64/Makefile b/drivers/platform/sw64/Makefile index 3efa835ade5d..84ba9957a9ce 100644 --- a/drivers/platform/sw64/Makefile +++ b/drivers/platform/sw64/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_PLATFORM_XUELANG) += legacy_xuelang.o obj-$(CONFIG_PLATFORM_JUNZHANG) += legacy_junzhang.o +obj-y += misc-platform.o diff --git a/drivers/platform/sw64/misc-platform.c b/drivers/platform/sw64/misc-platform.c new file mode 100644 index 000000000000..0350df9c9135 --- /dev/null +++ b/drivers/platform/sw64/misc-platform.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define pr_fmt(fmt) "sunway-misc-platform: " fmt + +#include +#include +#include + +#include + +struct misc_platform { + void __iomem *spbu_base; + void __iomem *intpu_base; + void __iomem *gpio_base; +}; + +static struct misc_platform misc_platform_devices[MAX_NUMNODES]; + +#ifdef CONFIG_OF +static const struct of_device_id misc_platform_of_match[] = { + { .compatible = "sunway,misc-platform" }, + {}, +}; +#endif + +#ifdef CONFIG_ACPI +static const struct acpi_device_id misc_platform_acpi_match[] = { + { "SUNW0200", 0 }, + {}, +}; +#endif + +static int misc_platform_get_node(struct device *dev) +{ + int nid = NUMA_NO_NODE; + unsigned long long pxm; + struct device_node *np; + acpi_status status; + + /* Try to directly get the physical node ID */ + if (acpi_disabled) { + /** + * We don't use the function of_node_to_nid() + * in case CONFIG_NUMA=n. + */ + np = of_node_get(dev->of_node); + of_property_read_u32(np, "numa-node-id", &nid); + of_node_put(np); + } else { + /** + * We don't use the function acpi_get_node() here + * beacuse we want physical node ID instead of the + * logical one. + */ + status = acpi_evaluate_integer(ACPI_HANDLE(dev), + "_PXM", NULL, &pxm); + if (ACPI_SUCCESS(status)) + nid = (int)pxm; + } + + return nid; +} + +static int misc_platform_probe(struct platform_device *pdev) +{ + int ret, node; + u64 base_address; + void __iomem *spbu_base = NULL; + void __iomem *intpu_base = NULL; + void __iomem *gpio_base = NULL; + struct device *dev = &pdev->dev; + + node = misc_platform_get_node(dev); + if (node == NUMA_NO_NODE) { + pr_err("unable to get node ID\n"); + return ret; + } + + if (!device_property_read_u64(dev, "sunway,spbu_base", + &base_address)) + spbu_base = __va(base_address); + + if (!device_property_read_u64(dev, "sunway,intpu_base", + &base_address)) + intpu_base = __va(base_address); + + if (!device_property_read_u64(dev, "sunway,gpio_base", + &base_address)) + gpio_base = __va(base_address); + + misc_platform_devices[node].spbu_base = spbu_base; + misc_platform_devices[node].intpu_base = intpu_base; + misc_platform_devices[node].gpio_base = gpio_base; + + pr_info("misc-platform on node %d found\n", node); + + return 0; +} + +void __iomem *misc_platform_get_spbu_base(unsigned long node) +{ + void __iomem *spbu_base; + + if (node >= MAX_NUMNODES) + return NULL; + + spbu_base = misc_platform_devices[node].spbu_base; + + /* Fallback to legacy address */ + if (!spbu_base) + return __va(SW64_IO_BASE(node) | SPBU_BASE); + + return spbu_base; +} + +void __iomem *misc_platform_get_intpu_base(unsigned long node) +{ + void __iomem *intpu_base; + + if (node >= MAX_NUMNODES) + return NULL; + + intpu_base = misc_platform_devices[node].intpu_base; + + /* Fallback to legacy address */ + if (!intpu_base) + return __va(SW64_IO_BASE(node) | INTPU_BASE); + + return intpu_base; +} + +void __iomem *misc_platform_get_gpio_base(unsigned long node) +{ + void __iomem *gpio_base; + + if (node >= MAX_NUMNODES) + return NULL; + + gpio_base = misc_platform_devices[node].gpio_base; + + /* Fallback to legacy address */ + if (!gpio_base) + return __va(SW64_IO_BASE(node) | GPIO_BASE); + + return gpio_base; +} + +#ifdef CONFIG_SUBARCH_C3B +void __iomem *misc_platform_get_cab0_base(unsigned long node) +{ + return __va(SW64_IO_BASE(node) | CAB0_BASE); +} +#endif + +static struct platform_driver misc_platform_driver = { + .probe = misc_platform_probe, + .driver = { + .name = "sunway-misc-platform", + .of_match_table = of_match_ptr(misc_platform_of_match), + .acpi_match_table = ACPI_PTR(misc_platform_acpi_match), + }, +}; + +static int __init misc_platform_driver_init(void) +{ + return platform_driver_register(&misc_platform_driver); +} +arch_initcall(misc_platform_driver_init); -- Gitee From 93d176c4e69edf04efb6a75fbff879a7cbe25f74 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 9 Jul 2024 09:35:10 +0800 Subject: [PATCH 082/100] anolis: sw64: remove sw64_io related functions ANBZ: #4688 Remove sw64_io related functions to decouple architecture related kernel code and hardware. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/cpufreq.h | 3 + arch/sw_64/include/asm/irq.h | 12 + arch/sw_64/include/asm/pci.h | 74 +++++- arch/sw_64/include/asm/platform.h | 2 + arch/sw_64/include/asm/sw64io.h | 18 -- arch/sw_64/include/asm/topology.h | 2 - arch/sw_64/include/asm/uncore_io_junzhang.h | 138 ---------- .../include/asm/uncore_io_ops_junzhang.h | 27 +- .../sw_64/include/asm/uncore_io_ops_xuelang.h | 46 +--- arch/sw_64/include/asm/uncore_io_xuelang.h | 247 +----------------- arch/sw_64/kernel/chip_setup.c | 52 +++- arch/sw_64/kernel/setup.c | 14 +- arch/sw_64/kernel/smp.c | 22 +- arch/sw_64/kernel/topology.c | 8 +- arch/sw_64/kvm/kvm_core3.c | 8 +- arch/sw_64/pci/pci-legacy.c | 28 +- arch/sw_64/platform/cpufreq.c | 31 ++- drivers/clocksource/timer-sw64.c | 23 +- drivers/cpufreq/sw64_cpufreq_debugfs.c | 3 +- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-sunway-cpu.c | 52 ---- drivers/irqchip/irq-sunway-pintc.c | 207 +++++++++++++-- drivers/pci/controller/pci-sunway.c | 22 +- 23 files changed, 448 insertions(+), 592 deletions(-) diff --git a/arch/sw_64/include/asm/cpufreq.h b/arch/sw_64/include/asm/cpufreq.h index 70dfc67cf4e8..93244b3b18c6 100644 --- a/arch/sw_64/include/asm/cpufreq.h +++ b/arch/sw_64/include/asm/cpufreq.h @@ -70,6 +70,9 @@ struct clk { #define STARTUP_RATE (2400UL * 1000 * 1000) #endif +#define OFFSET_CLU_LV1_SEL 0x3a80UL +#define OFFSET_CLK_CTL 0x3b80UL + extern struct cpufreq_frequency_table freq_table[]; int clk_init(void); diff --git a/arch/sw_64/include/asm/irq.h b/arch/sw_64/include/asm/irq.h index 13f3dbac3491..de3530b687e0 100644 --- a/arch/sw_64/include/asm/irq.h +++ b/arch/sw_64/include/asm/irq.h @@ -41,12 +41,24 @@ extern int __init sw64_add_gsi_domain_map(u32 gsi_base, u32 gsi_count, #ifdef CONFIG_SW64_PINTC extern int __init pintc_acpi_init(struct irq_domain *parent, struct acpi_madt_sw_pintc *pintc); +extern void handle_dev_int(struct pt_regs *regs); +extern void handle_fault_int(void); #else static inline int __init pintc_acpi_init(struct irq_domain *parent, struct acpi_madt_sw_pintc *pintc) { return 0; } + +static inline void handle_dev_int(struct pt_regs *regs) +{ + pr_crit("Enter MCU int, but the driver is not configured!\n"); +} + +static inline void handle_fault_int(void) +{ + pr_crit("Enter fault int, but the driver is not configured!\n"); +} #endif #ifdef CONFIG_SW64_LPC_INTC diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index e43edf203e38..877aa0107539 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -8,9 +8,77 @@ #include #include -/* - * The following structure is used to manage multiple PCI busses. - */ +/* Offset for PCIe controller registers */ +enum SUNWAY_PIU_IOR0 { + PIUCONFIG0 = 0x0UL, + EPDMABAR = 0x80UL, + IOMMUSEGITEM0 = 0x100UL, + IOMMUEXCPT_CTRL = 0x2100UL, + MSIADDR = 0x2180UL, + MSICONFIG0 = 0x2200UL, + INTACONFIG = 0xa200UL, + INTBCONFIG = 0xa280UL, + INTCCONFIG = 0xa300UL, + INTDCONFIG = 0xa380UL, + AERERRINTCONFIG = 0xa400UL, + AERERRMSICONFIG = 0xa480UL, + PMEINTCONFIG = 0xa500UL, + PMEMSICONFIG = 0xa580UL, + HPINTCONFIG = 0xa600UL, + HPMSICONFIG = 0xa680UL, + HP_CTRL = 0xac80UL, /* verison >= junzhang */ + HP_WATCHOUT = 0xae00UL, /* version >= junzhang */ + DTBASEADDR = 0xb000UL, + DTLB_FLUSHALL = 0xb080UL, + DTLB_FLUSHDEV = 0xb100UL, + PTLB_FLUSHALL = 0xb180UL, + PTLB_FLUSHDEV = 0xb200UL, + PTLB_FLUSHVADDR = 0xb280UL, + PCACHE_FLUSHALL = 0xb300UL, + PCACHE_FLUSHDEV = 0xb380UL, + PCACHE_FLUSHPADDR = 0xb400UL, + TIMEOUT_CONFIG = 0xb480UL, + IOMMUEXCPT_STATUS = 0xb500UL, + IOMMUPAGE_PADDR1 = 0xb580UL, + IOMMUPAGE_PADDR2 = 0xb600UL, + IOMMUPAGE_PADDR3 = 0xb680UL, + PTLB_ACCESS = 0xb700UL, + PTLB_ITEM_TAG = 0xb780UL, + PTLB_ITEM_DATA = 0xb800UL, + PCACHE_ACCESS = 0xb880UL, + PCACHE_ITEM_TAG = 0xb900UL, + PCACHE_ITEM_DATA0 = 0xb980UL, +}; + +enum SUNWAY_PIU_IOR1 { + PIUCONFIG1 = 0x0UL, + NEWLTSSMSTATE0 = 0x300UL, /* verison >= junzhang */ + ERRENABLE = 0x880UL, + RCDEBUGINF1 = 0xc80UL, + DCACONTROL = 0x1a00UL, + DEVICEID0 = 0x1a80UL, +}; + +enum SUNWAY_RC { + RC_VENDOR_ID = 0x0UL, + RC_COMMAND = 0x80UL, + RC_REVISION_ID = 0x100UL, + RC_PRIMARY_BUS = 0x300UL, + RC_MSI_CONTROL = 0xa00UL, + RC_EXP_DEVCAP = 0xe80UL, + RC_EXP_DEVCTL = 0xf00UL, + RC_SLOT_CTRL = 0x1100UL, + RC_LINK_STAT = 0x1000UL, + RC_CONTROL = 0X1180UL, + RC_STATUS = 0X1200UL, + RC_EXP_DEVCTL2 = 0x1300UL, + RC_PORT_LINK_CTL = 0xe200UL, + RC_ORDER_RULE_CTL = 0x11680UL, + RC_MISC_CONTROL_1 = 0x11780UL, + RC_PHY_INT_REG = 0x80000UL, + RC_PHY_EXT_GEN1 = 0x82400UL, + RC_PHY_EXT_GEN2 = 0x82480UL, +}; struct pci_dev; struct pci_bus; diff --git a/arch/sw_64/include/asm/platform.h b/arch/sw_64/include/asm/platform.h index df5e570ccc5f..c44116df8e16 100644 --- a/arch/sw_64/include/asm/platform.h +++ b/arch/sw_64/include/asm/platform.h @@ -41,4 +41,6 @@ extern void __iomem *misc_platform_get_gpio_base(unsigned long node); extern void __iomem *misc_platform_get_cab0_base(unsigned long node); #endif +extern bool sunway_machine_is_compatible(const char *compat); + #endif /* _ASM_SW64_PLATFORM_H */ diff --git a/arch/sw_64/include/asm/sw64io.h b/arch/sw_64/include/asm/sw64io.h index e9c4a3be95ef..925206ba7d6e 100644 --- a/arch/sw_64/include/asm/sw64io.h +++ b/arch/sw_64/include/asm/sw64io.h @@ -20,24 +20,6 @@ #define MK_PIU_IOR1(nid, idx) \ (SW64_PCI_IO_BASE((nid), (idx)) | PCI_IOR1_BASE) -static inline unsigned long -sw64_io_read(unsigned long node, unsigned long reg) -{ - void __iomem *addr; - - addr = __va(SW64_IO_BASE(node) | reg); - return readq(addr); -} - -static inline void -sw64_io_write(unsigned long node, unsigned long reg, unsigned long data) -{ - void __iomem *addr; - - addr = __va(SW64_IO_BASE(node) | reg); - writeq(data, addr); -} - #if defined(CONFIG_UNCORE_XUELANG) #include #endif diff --git a/arch/sw_64/include/asm/topology.h b/arch/sw_64/include/asm/topology.h index 25ec7b9e9431..c4da0cfcceff 100644 --- a/arch/sw_64/include/asm/topology.h +++ b/arch/sw_64/include/asm/topology.h @@ -62,8 +62,6 @@ static inline void numa_remove_cpu(unsigned int cpu) { } static inline void numa_store_cpu_info(unsigned int cpu) { } #endif /* CONFIG_NUMA */ -extern void get_vt_smp_info(void); - #include static inline void arch_fix_phys_package_id(int num, u32 slot) { } diff --git a/arch/sw_64/include/asm/uncore_io_junzhang.h b/arch/sw_64/include/asm/uncore_io_junzhang.h index e21876f70d1e..24c1e3be32f3 100644 --- a/arch/sw_64/include/asm/uncore_io_junzhang.h +++ b/arch/sw_64/include/asm/uncore_io_junzhang.h @@ -71,142 +71,4 @@ #define PIUCONFIG0_INIT_VAL 0x38016 -/*-----------------------addr-----------------------*/ -/* INTPU REG */ -enum { - DEVINT_MISS = INTPU_BASE | 0x100UL, - MT_INT_CONFIG = INTPU_BASE | 0x300UL, - DEV_INT_CONFIG = INTPU_BASE | 0x480UL, - FMT_ERR = INTPU_BASE | 0x700UL, - FAULT_INT_CONFIG = INTPU_BASE | 0x780UL, - SERR_CNTTH = INTPU_BASE | 0x880UL, - SPBUSERR_CNT = INTPU_BASE | 0x900UL, - IRUSERR_CNT = INTPU_BASE | 0xa80UL, - ERRRPT_EN = INTPU_BASE | 0xb00UL, - IINT_MISS_VECTOR0 = INTPU_BASE | 0x1080UL, - IINT_MISS_VECTOR1 = INTPU_BASE | 0x1100UL, - IINT_MISS = INTPU_BASE | 0x1180UL, - IINT_MISS_RPTEN = INTPU_BASE | 0x1200UL, - DEVINT_MISS_RPTEN = INTPU_BASE | 0x1280UL, - ECCSERR = INTPU_BASE | 0x1300UL, - ECCSERR_RPTEN = INTPU_BASE | 0x1380UL, - ECCMERR = INTPU_BASE | 0x1400UL, - ECCMERR_RPTEN = INTPU_BASE | 0x1480UL, - DEVINT_WKEN = INTPU_BASE | 0x1500UL, - ADR_INT_CONFIG = INTPU_BASE | 0x1580UL, - DEVINTWK_INTEN = INTPU_BASE | 0x1600UL, -}; - -/* SPBU CSR */ -enum { - SMP_INFO = SPBU_BASE | 0x80UL, - INIT_CTL = SPBU_BASE | 0x680UL, - CORE_ONLINE = SPBU_BASE | 0x780UL, - DLI_RLTD_FAULT = SPBU_BASE | 0x980UL, - DLI_RLTD_FAULT_EN = SPBU_BASE | 0xa00UL, - DLI_RLTD_FAULT_INTEN = SPBU_BASE | 0xa80UL, - CFG_INFO = SPBU_BASE | 0x1100UL, - IO_START = SPBU_BASE | 0x1300UL, - I2C0_SRST_L = SPBU_BASE | 0x1900UL, - I2C1_SRST_L = SPBU_BASE | 0x1980UL, - I2C2_SRST_L = SPBU_BASE | 0x1a00UL, - MCU_DVC_INT = SPBU_BASE | 0x3000UL, - MCU_DVC_INT_EN = SPBU_BASE | 0x3080UL, - SI_FAULT_STAT = SPBU_BASE | 0x3100UL, - SI_FAULT_STAT_EN = SPBU_BASE | 0x3180UL, - SI_FAULT_INT_EN = SPBU_BASE | 0x3200UL, - ADR_CTL = SPBU_BASE | 0x3600UL, - PIUH_CTRL = SPBU_BASE | 0x3680UL, - MC_ONLINE = SPBU_BASE | 0x3780UL, - CLK_CTL = SPBU_BASE | 0x3b80UL, - CLU_LV2_SELH = SPBU_BASE | 0x3a00UL, - CLU_LV1_SEL = SPBU_BASE | 0x3a80UL, - CLU_LV2_SELL = SPBU_BASE | 0x3b00UL, - PIU_TOP0_CONFIG = SPBU_BASE | 0x4c80UL, - PIU_TOP1_CONFIG = SPBU_BASE | 0x4d00UL, - PIU_PHY_SRST_H = SPBU_BASE | 0x6280UL, - BUTTON_RST_N_PCIE0 = SPBU_BASE | 0x6a80UL, - SOFT_INFO0 = SPBU_BASE | 0xa000UL, -}; - -/*--------------------------offset-----------------------------------*/ -/* PIU IOR0 */ -enum { - PIUCONFIG0 = 0x0UL, - EPDMABAR = 0x80UL, - IOMMUSEGITEM0 = 0x100UL, - IOMMUEXCPT_CTRL = 0x2100UL, - MSIADDR = 0x2180UL, - MSICONFIG0 = 0x2200UL, - INTACONFIG = 0xa200UL, - INTBCONFIG = 0xa280UL, - INTCCONFIG = 0xa300UL, - INTDCONFIG = 0xa380UL, - AERERRINTCONFIG = 0xa400UL, - AERERRMSICONFIG = 0xa480UL, - PMEINTCONFIG = 0xa500UL, - PMEMSICONFIG = 0xa580UL, - HPINTCONFIG = 0xa600UL, - HPMSICONFIG = 0xa680UL, - HP_CTRL = 0xac80UL, - HP_WATCHOUT = 0xae00UL, - DTBASEADDR = 0xb000UL, - DTLB_FLUSHALL = 0xb080UL, - DTLB_FLUSHDEV = 0xb100UL, - PTLB_FLUSHALL = 0xb180UL, - PTLB_FLUSHDEV = 0xb200UL, - PTLB_FLUSHVADDR = 0xb280UL, - PCACHE_FLUSHALL = 0xb300UL, - PCACHE_FLUSHDEV = 0xb380UL, - PCACHE_FLUSHPADDR = 0xb400UL, - TIMEOUT_CONFIG = 0xb480UL, - IOMMUEXCPT_STATUS = 0xb500UL, - IOMMUPAGE_PADDR1 = 0xb580UL, - IOMMUPAGE_PADDR2 = 0xb600UL, - IOMMUPAGE_PADDR3 = 0xb680UL, - PTLB_ACCESS = 0xb700UL, - PTLB_ITEM_TAG = 0xb780UL, - PTLB_ITEM_DATA = 0xb800UL, - PCACHE_ACCESS = 0xb880UL, - PCACHE_ITEM_TAG = 0xb900UL, - PCACHE_ITEM_DATA0 = 0xb980UL, -}; - -/* PIU IOR1 */ -enum { - PIUCONFIG1 = 0x0UL, - NEWLTSSMSTATE0 = 0x300UL, - ERRENABLE = 0x880UL, - RCDEBUGINF1 = 0xc80UL, - DCACONTROL = 0x1a00UL, - DEVICEID0 = 0x1a80UL, -}; - -/* RC */ -enum { - RC_VENDOR_ID = 0x0UL, - RC_COMMAND = 0x80UL, - RC_REVISION_ID = 0x100UL, - RC_PRIMARY_BUS = 0x300UL, - RC_MSI_CONTROL = 0xa00UL, - RC_EXP_DEVCAP = 0xe80UL, - RC_EXP_DEVCTL = 0xf00UL, - RC_SLOT_CTRL = 0x1100UL, - RC_LINK_STAT = 0x1000UL, - RC_CONTROL = 0X1180UL, - RC_STATUS = 0X1200UL, - RC_EXP_DEVCTL2 = 0x1300UL, - RC_PORT_LINK_CTL = 0xe200UL, - RC_ORDER_RULE_CTL = 0x11680UL, - RC_MISC_CONTROL_1 = 0x11780UL, - RC_PHY_INT_REG = 0x80000UL, - RC_PHY_EXT_GEN1 = 0x82400UL, - RC_PHY_EXT_GEN2 = 0x82480UL, -}; -/* GPIO */ -enum { - GPIO_SWPORTA_DR = GPIO_BASE | 0x0UL, - GPIO_SWPORTA_DDR = GPIO_BASE | 0x200UL, -}; -/*--------------------------------------------------------------------------*/ #endif /* _ASM_SW64_UNCORE_IO_JUNZHANG_H */ diff --git a/arch/sw_64/include/asm/uncore_io_ops_junzhang.h b/arch/sw_64/include/asm/uncore_io_ops_junzhang.h index 00f9898f8540..eff4f40886d8 100644 --- a/arch/sw_64/include/asm/uncore_io_ops_junzhang.h +++ b/arch/sw_64/include/asm/uncore_io_ops_junzhang.h @@ -2,12 +2,17 @@ #ifndef _ASM_SW64_UNCORE_IO_OPS_JUNZHANG_H #define _ASM_SW64_UNCORE_IO_OPS_JUNZHANG_H +#define OFFSET_CFG_INFO 0x1100UL + static inline int __get_cpu_nums(void) { int cpus; unsigned long cfg_info; + void __iomem *spbu_base; + + spbu_base = misc_platform_get_spbu_base(0); - cfg_info = sw64_io_read(0, CFG_INFO); + cfg_info = readq(spbu_base + OFFSET_CFG_INFO); cfg_info = (cfg_info >> 33) & 0x3; cpus = 1 << cfg_info; @@ -18,27 +23,15 @@ static inline unsigned long __get_node_mem(int node) { unsigned long node_mem; unsigned long total_mem; + void __iomem *spbu_base; + + spbu_base = misc_platform_get_spbu_base(node); - total_mem = sw64_io_read(node, CFG_INFO) >> 3; + total_mem = readq(spbu_base + OFFSET_CFG_INFO) >> 3; total_mem = (total_mem & 0xffff) << 28; node_mem = total_mem / __get_cpu_nums(); return node_mem; } -#define __io_read_longtime(node) (0UL) -#define __io_write_longtime(node, data) do { } while (0) - -static inline void -__io_write_longtime_start_en(int node, unsigned long data) -{ - sw64_io_write(node, GPIO_SWPORTA_DDR, data); -} - -static inline void -__io_write_fault_int_en(int node, unsigned long data) -{ - sw64_io_write(node, FAULT_INT_CONFIG, data); -} - #endif /* _ASM_SW64_UNCORE_IO_OPS_JUNZHANG_H */ diff --git a/arch/sw_64/include/asm/uncore_io_ops_xuelang.h b/arch/sw_64/include/asm/uncore_io_ops_xuelang.h index 9336e473211d..e96c3669b577 100644 --- a/arch/sw_64/include/asm/uncore_io_ops_xuelang.h +++ b/arch/sw_64/include/asm/uncore_io_ops_xuelang.h @@ -2,12 +2,20 @@ #ifndef _ASM_SW64_UNCORE_IO_OPS_XUELANG_H #define _ASM_SW64_UNCORE_IO_OPS_XUELANG_H +#define OFFSET_TRKMODE 0x80UL + +#define OFFSET_MC_CAP_CFG 0x1180UL +#define OFFSET_MC_ONLINE 0x3780UL + static inline int __get_cpu_nums(void) { int cpus; unsigned long trkmode; + void __iomem *cab0_base; - trkmode = sw64_io_read(0, TRKMODE); + cab0_base = misc_platform_get_cab0_base(0); + + trkmode = readq(cab0_base + OFFSET_TRKMODE); trkmode = (trkmode >> 6) & 0x3; cpus = 1 << trkmode; @@ -21,45 +29,15 @@ static inline unsigned long __get_node_mem(int node) unsigned long mc_online; unsigned long mc_cap; unsigned long mc_num; + void __iomem *mcu_base = misc_platform_get_spbu_base(node); - mc_config = sw64_io_read(node, MC_CAP_CFG) & 0xf; + mc_config = readq(mcu_base + OFFSET_MC_CAP_CFG) & 0xf; mc_cap = (1UL << mc_config) << 28; - mc_online = sw64_io_read(node, MC_ONLINE) & 0xff; + mc_online = readq(mcu_base + OFFSET_MC_ONLINE) & 0xff; mc_num = __kernel_ctpop(mc_online); node_mem = mc_cap * mc_num; return node_mem; } -static inline unsigned long -__io_read_longtime(int node) -{ - return sw64_io_read(node, LONG_TIME); -} - -static inline void -__io_write_longtime(int node, unsigned long data) -{ - sw64_io_write(node, LONG_TIME, data); -} - -static inline void -__io_write_longtime_start_en(int node, unsigned long data) -{ - sw64_io_write(node, LONG_TIME_START_EN, data); -} - -static inline void -__io_write_fault_int_en(int node, unsigned long data) -{ - sw64_io_write(node, DUAL_CG0_FAULT_INTEN, data); - sw64_io_write(node, DUAL_CG1_FAULT_INTEN, data); - sw64_io_write(node, DUAL_CG2_FAULT_INTEN, data); - sw64_io_write(node, DUAL_CG3_FAULT_INTEN, data); - sw64_io_write(node, DUAL_CG4_FAULT_INTEN, data); - sw64_io_write(node, DUAL_CG5_FAULT_INTEN, data); - sw64_io_write(node, DUAL_CG6_FAULT_INTEN, data); - sw64_io_write(node, DUAL_CG7_FAULT_INTEN, data); -} - #endif /* _ASM_SW64_UNCORE_IO_OPS_XUELANG_H */ diff --git a/arch/sw_64/include/asm/uncore_io_xuelang.h b/arch/sw_64/include/asm/uncore_io_xuelang.h index 7a8c9edc8bfb..c8f01cb01e52 100644 --- a/arch/sw_64/include/asm/uncore_io_xuelang.h +++ b/arch/sw_64/include/asm/uncore_io_xuelang.h @@ -48,6 +48,7 @@ #define PCI0_BUS SW64_PCI0_BUS #define MCU_BASE (0x3UL << 36) +#define SPBU_BASE MCU_BASE #define CAB0_BASE (0x10UL << 32) #define INTPU_BASE (0x2aUL << 32) #define IIC0_BASE (0x31UL << 32) @@ -73,250 +74,4 @@ #define PIUCONFIG0_INIT_VAL 0x38056 -/*-----------------------addr-----------------------*/ -/* CAB0 REG */ -enum { - TRKMODE = CAB0_BASE | 0x80UL, -}; - -/* DLIA IO REG */ -enum { - DLIA_BWTEST_PAT = DLIA_BASE | 0x100980UL, - DLIA_PHY_VLDLANE = DLIA_BASE | DLI_PHY_CTL | 0x300UL, -}; - -/* DLIB IO REG */ -enum { - DLIB_BWTEST_PAT = DLIB_BASE | 0x100980UL, - DLIB_PHY_VLDLANE = DLIB_BASE | DLI_PHY_CTL | 0x300UL, -}; - -/* DLIC IO REG */ -enum { - DLIC_BWTEST_PAT = DLIC_BASE | 0x100980UL, - DLIC_PHY_VLDLANE = DLIC_BASE | DLI_PHY_CTL | 0x300UL, -}; -/* INTPU REG */ -enum { - LCORE_SLEEPY = INTPU_BASE | 0x0UL, - LCORE_SLEEP = INTPU_BASE | 0x80UL, - DEVICE_MISS = INTPU_BASE | 0x100UL, - LONG_TIME = INTPU_BASE | 0x180UL, - LCORE_IDLE = INTPU_BASE | 0x280UL, - MT_INT_CONFIG = INTPU_BASE | 0x300UL, - DEV_INT_CONFIG = INTPU_BASE | 0x480UL, - FMT_ERR = INTPU_BASE | 0x700UL, - FAULT_INT_CONFIG = INTPU_BASE | 0x780UL, - SERR_CNTTH = INTPU_BASE | 0x880UL, - MCUSERR_CNT = INTPU_BASE | 0x900UL, - IRUSERR_CNT = INTPU_BASE | 0xa80UL, - ERRRPT_EN = INTPU_BASE | 0xb00UL, - IINT_MISS_VECTOR = INTPU_BASE | 0x1100UL, - IINT_MIS = INTPU_BASE | 0x1180UL, - IINT_MISS_RPTEN = INTPU_BASE | 0x1200UL, - DEVINT_MISS_RPTEN = INTPU_BASE | 0x1280UL, - ECCSERR = INTPU_BASE | 0x1300UL, - ECCSERR_RPTEN = INTPU_BASE | 0x1380UL, - ECCMERR = INTPU_BASE | 0x1400UL, - ECCMERR_RPTEN = INTPU_BASE | 0x1480UL, - DEVINT_WKEN = INTPU_BASE | 0x1500UL, - NMI_INT_CONFIG = INTPU_BASE | 0x1580UL, - DEVINTWK_INTEN = INTPU_BASE | 0x1600UL, -}; - -/* MC IO REG */ -enum { - CFGDEC = 0x400UL, - CFGCR = 0x480UL, - INIT_CTRL = 0x580UL, - CFGERR = 0xd00UL, - FSMSTAT = 0xe00UL, - PUB_INTERFACE = 0x1000UL, - POWERCTRL = 0x1080UL, - CFGMR0 = 0x1280UL, - CFGMR1 = 0x1300UL, - CFGMR2 = 0x1380UL, - CFGMR3 = 0x1400UL, - PERF_CTRL = 0x1480UL, - MC_PERF0 = 0x1500UL, - CFGMR4 = 0x1800UL, - CFGMR5 = 0x1880UL, - CFGMR6 = 0x1900UL, - MC_CTRL = 0x1c00UL, - MEMSERR_P = 0x1c80UL, - MEMSERR = 0x1d00UL, -}; - -/* MCU CSR */ -enum { - SMP_INFO = MCU_BASE | 0x80UL, - INIT_CTL = MCU_BASE | 0x680UL, - MT_STATE = MCU_BASE | 0x700UL, - CORE_ONLINE = MCU_BASE | 0x780UL, - MT_INT = MCU_BASE | 0x800UL, - MT_INT_END = MCU_BASE | 0x880UL, - CPU_ID = MCU_BASE | 0x900UL, - DLI_RLTD_FAULT = MCU_BASE | 0x980UL, - DLI_RLTD_FAULT_EN = MCU_BASE | 0xa00UL, - DLI_RLTD_FAULT_INTEN = MCU_BASE | 0xa80UL, - FAULT_SOURCE = MCU_BASE | 0xb00UL, - INT_SOURCE = MCU_BASE | 0xb80UL, - CORE_STATE0 = MCU_BASE | 0xc00UL, - CORE_STATE1 = MCU_BASE | 0xc80UL, - CFG_INFO = MCU_BASE | 0x1100UL, - MC_CAP_CFG = MCU_BASE | 0x1180UL, - IO_START = MCU_BASE | 0x1300UL, - UART_ONLINE = MCU_BASE | 0x1780UL, - I2C0_SRST_L = MCU_BASE | 0x1900UL, - I2C1_SRST_L = MCU_BASE | 0x1980UL, - I2C2_SRST_L = MCU_BASE | 0x1a00UL, - MCU_DVC_INT = MCU_BASE | 0x3000UL, - MCU_DVC_INT_EN = MCU_BASE | 0x3080UL, - SI_FAULT_STAT = MCU_BASE | 0x3100UL, - SI_FAULT_EN = MCU_BASE | 0x3180UL, - SI_FAULT_INT_EN = MCU_BASE | 0x3200UL, - FIFO_SYNSEL = MCU_BASE | 0x3400UL, - CPU_INFO = MCU_BASE | 0x3480UL, - WAKEUP_CTL = MCU_BASE | 0x3500UL, - FLAGREG = MCU_BASE | 0x3580UL, - NMI_CTL = MCU_BASE | 0x3600UL, - PIUPLL_CNT = MCU_BASE | 0x3680UL, - MC_ONLINE = MCU_BASE | 0x3780UL, - FLASH_INFO = MCU_BASE | 0x3800UL, - RTPUSROMCNT = MCU_BASE | 0x3880UL, - CLU_LV1_SEL = MCU_BASE | 0x3a80UL, - CLU_LV2_SEL = MCU_BASE | 0x3b00UL, - CLK_CTL = MCU_BASE | 0x3b80UL, - SLEEP_WAIT_CNT = MCU_BASE | 0x4980UL, - CHIP_ID = MCU_BASE | 0x4b00UL, - PIU_TOP0_CONFIG = MCU_BASE | 0x4c80UL, - PIU_TOP1_CONFIG = MCU_BASE | 0x4d00UL, - LVDS_CTL = MCU_BASE | 0x4d80UL, - LPC_DMAREQ_TOTH = MCU_BASE | 0x5100UL, - DLI_ONLINE = MCU_BASE | 0x6180UL, - LPC_DMAREQ_HADR = MCU_BASE | 0x6200UL, - PIU_PHY_SRST_H = MCU_BASE | 0x6280UL, - CLK_SEL_PCIE0 = MCU_BASE | 0x6280UL, - CLK_SEL_PCIE1 = MCU_BASE | 0x6300UL, - CLK_SEL_PCIE2 = MCU_BASE | 0x6380UL, - CLK_SEL_PCIE3 = MCU_BASE | 0x6400UL, - CLK_SEL_PCIE4 = MCU_BASE | 0x6480UL, - CLK_SEL_PCIE5 = MCU_BASE | 0x6500UL, - PERST_N_PCIE0 = MCU_BASE | 0x6680UL, - PERST_N_PCIE1 = MCU_BASE | 0x6700UL, - PERST_N_PCIE2 = MCU_BASE | 0x6780UL, - PERST_N_PCIE3 = MCU_BASE | 0x6800UL, - PERST_N_PCIE4 = MCU_BASE | 0x6880UL, - PERST_N_PCIE5 = MCU_BASE | 0x6900UL, - BUTTON_RST_N_PCIE0 = MCU_BASE | 0x6a80UL, - BUTTON_RST_N_PCIE1 = MCU_BASE | 0x6b00UL, - BUTTON_RST_N_PCIE2 = MCU_BASE | 0x6b80UL, - BUTTON_RST_N_PCIE3 = MCU_BASE | 0x6c00UL, - BUTTON_RST_N_PCIE4 = MCU_BASE | 0x6c80UL, - BUTTON_RST_N_PCIE5 = MCU_BASE | 0x6d00UL, - DUAL_CG0_FAULT = MCU_BASE | 0x6d80UL, - DUAL_CG1_FAULT = MCU_BASE | 0x6e00UL, - DUAL_CG2_FAULT = MCU_BASE | 0x6e80UL, - DUAL_CG3_FAULT = MCU_BASE | 0x6f00UL, - DUAL_CG4_FAULT = MCU_BASE | 0x6f80UL, - DUAL_CG5_FAULT = MCU_BASE | 0x7000UL, - DUAL_CG6_FAULT = MCU_BASE | 0x7080UL, - DUAL_CG7_FAULT = MCU_BASE | 0x7100UL, - DUAL_CG0_FAULT_EN = MCU_BASE | 0x7180UL, - DUAL_CG1_FAULT_EN = MCU_BASE | 0x7200UL, - DUAL_CG2_FAULT_EN = MCU_BASE | 0x7280UL, - DUAL_CG3_FAULT_EN = MCU_BASE | 0x7300UL, - DUAL_CG4_FAULT_EN = MCU_BASE | 0x7380UL, - DUAL_CG5_FAULT_EN = MCU_BASE | 0x7400UL, - DUAL_CG6_FAULT_EN = MCU_BASE | 0x7480UL, - DUAL_CG7_FAULT_EN = MCU_BASE | 0x7500UL, - DUAL_CG0_FAULT_INTEN = MCU_BASE | 0x7580UL, - DUAL_CG1_FAULT_INTEN = MCU_BASE | 0x7600UL, - DUAL_CG2_FAULT_INTEN = MCU_BASE | 0x7680UL, - DUAL_CG3_FAULT_INTEN = MCU_BASE | 0x7700UL, - DUAL_CG4_FAULT_INTEN = MCU_BASE | 0x7780UL, - DUAL_CG5_FAULT_INTEN = MCU_BASE | 0x7800UL, - DUAL_CG6_FAULT_INTEN = MCU_BASE | 0x7880UL, - DUAL_CG7_FAULT_INTEN = MCU_BASE | 0x7900UL, - SOFT_INFO0 = MCU_BASE | 0x7f00UL, - LONG_TIME_START_EN = MCU_BASE | 0x9000UL, -}; - -/*--------------------------offset-----------------------------------*/ -/* PIU IOR0 */ -enum { - PIUCONFIG0 = 0x0UL, - EPDMABAR = 0x80UL, - IOMMUSEGITEM0 = 0x100UL, - IOMMUEXCPT_CTRL = 0x2100UL, - MSIADDR = 0x2180UL, - MSICONFIG0 = 0x2200UL, - INTACONFIG = 0xa200UL, - INTBCONFIG = 0xa280UL, - INTCCONFIG = 0xa300UL, - INTDCONFIG = 0xa380UL, - AERERRINTCONFIG = 0xa400UL, - AERERRMSICONFIG = 0xa480UL, - PMEINTCONFIG = 0xa500UL, - PMEMSICONFIG = 0xa580UL, - HPINTCONFIG = 0xa600UL, - HPMSICONFIG = 0xa680UL, - DTBASEADDR = 0xb000UL, - DTLB_FLUSHALL = 0xb080UL, - DTLB_FLUSHDEV = 0xb100UL, - PTLB_FLUSHALL = 0xb180UL, - PTLB_FLUSHDEV = 0xb200UL, - PTLB_FLUSHVADDR = 0xb280UL, - PCACHE_FLUSHALL = 0xb300UL, - PCACHE_FLUSHDEV = 0xb380UL, - PCACHE_FLUSHPADDR = 0xb400UL, - TIMEOUT_CONFIG = 0xb480UL, - IOMMUEXCPT_STATUS = 0xb500UL, - IOMMUPAGE_PADDR1 = 0xb580UL, - IOMMUPAGE_PADDR2 = 0xb600UL, - IOMMUPAGE_PADDR3 = 0xb680UL, - PTLB_ACCESS = 0xb700UL, - PTLB_ITEM_TAG = 0xb780UL, - PTLB_ITEM_DATA = 0xb800UL, - PCACHE_ACCESS = 0xb880UL, - PCACHE_ITEM_TAG = 0xb900UL, - PCACHE_ITEM_DATA0 = 0xb980UL, -}; - -/* PIU IOR1 */ -enum { - PIUCONFIG1 = 0x0UL, - ERRENABLE = 0x880UL, - RCDEBUGINF1 = 0xc80UL, - DCACONTROL = 0x1a00UL, - DEVICEID0 = 0x1a80UL, -}; - -/* RC */ -enum { - RC_VENDOR_ID = 0x0UL, - RC_COMMAND = 0x80UL, - RC_REVISION_ID = 0x100UL, - RC_PRIMARY_BUS = 0x300UL, - RC_MSI_CONTROL = 0xa00UL, - RC_EXP_DEVCAP = 0xe80UL, - RC_EXP_DEVCTL = 0xf00UL, - RC_SLOT_CTRL = 0x1100UL, - RC_LINK_STAT = 0x1000UL, - RC_CONTROL = 0X1180UL, - RC_STATUS = 0X1200UL, - RC_EXP_DEVCTL2 = 0x1300UL, - RC_PORT_LINK_CTL = 0xe200UL, - RC_ORDER_RULE_CTL = 0x11680UL, - RC_MISC_CONTROL_1 = 0x11780UL, - RC_PHY_INT_REG = 0x80000UL, - RC_PHY_EXT_GEN1 = 0x82400UL, - RC_PHY_EXT_GEN2 = 0x82480UL, -}; -/* GPIO */ -enum { - GPIO_SWPORTA_DR = GPIO_BASE | 0x0UL, - GPIO_SWPORTA_DDR = GPIO_BASE | 0x200UL, -}; -/*--------------------------------------------------------------------------*/ #endif /* _ASM_SW64_UNCORE_IO_XUELANG_H */ diff --git a/arch/sw_64/kernel/chip_setup.c b/arch/sw_64/kernel/chip_setup.c index f6e92adab5e6..211d673250c7 100644 --- a/arch/sw_64/kernel/chip_setup.c +++ b/arch/sw_64/kernel/chip_setup.c @@ -6,6 +6,18 @@ #include #include +#define OFFSET_CORE_ONLINE 0x780UL +#define OFFSET_MC_ONLINE 0x3780UL +#define OFFSET_I2C0_SRST_L 0x1900UL +#define OFFSET_I2C1_SRST_L 0x1980UL +#define OFFSET_I2C2_SRST_L 0x1a00UL +#define OFFSET_MCU_DVC_INT_EN 0x3080UL +#define OFFSET_LONG_TIME_START_EN 0x9000UL + +#define OFFSET_LONG_TIME 0x180UL + +#define OFFSET_GPIO_SWPORTA_DDR 0x200UL + struct sw64_chip_ops *sw64_chip; struct sw64_chip_init_ops *sw64_chip_init; @@ -30,11 +42,13 @@ static void __init setup_core_map(struct cpumask *cpumask) { int i, j, cpu_num, cpuid, max_cores_per_cpu; unsigned long coreonline; + void __iomem *spbu_base; cpu_num = get_cpu_nums(); cpuid = 0; for (i = 0; i < cpu_num; i++) { - coreonline = sw64_io_read(i, CORE_ONLINE); + spbu_base = misc_platform_get_spbu_base(i); + coreonline = readq(spbu_base + OFFSET_CORE_ONLINE); max_cores_per_cpu = MAX_CORES_PER_CPU; if (is_guest_or_emul()) @@ -64,14 +78,16 @@ static void __init setup_core_map(struct cpumask *cpumask) #ifdef CONFIG_PM static void i2c_srst(void) { - sw64_io_write(0, I2C0_SRST_L, 0x0); - sw64_io_write(0, I2C0_SRST_L, 0x1); + void __iomem *spbu_base = misc_platform_get_spbu_base(0); + + writeq(0x0, spbu_base + OFFSET_I2C0_SRST_L); + writeq(0x1, spbu_base + OFFSET_I2C0_SRST_L); - sw64_io_write(0, I2C1_SRST_L, 0x0); - sw64_io_write(0, I2C1_SRST_L, 0x1); + writeq(0x0, spbu_base + OFFSET_I2C1_SRST_L); + writeq(0x1, spbu_base + OFFSET_I2C1_SRST_L); - sw64_io_write(0, I2C2_SRST_L, 0x0); - sw64_io_write(0, I2C2_SRST_L, 0x1); + writeq(0x0, spbu_base + OFFSET_I2C2_SRST_L); + writeq(0x1, spbu_base + OFFSET_I2C2_SRST_L); } static void pcie_save(void) @@ -178,9 +194,11 @@ static unsigned long saved_dvc_int, saved_long_time; static inline void intpu_save(void) { + void __iomem *intpu_base = misc_platform_get_intpu_base(0); + switch (cpu_desc.model) { case CPU_SW831: - saved_long_time = __io_read_longtime(0); + saved_long_time = readq(intpu_base + OFFSET_LONG_TIME); default: break; } @@ -188,13 +206,17 @@ static inline void intpu_save(void) static inline void intpu_restore(void) { + void __iomem *intpu_base = misc_platform_get_intpu_base(0); + void __iomem *spbu_base = misc_platform_get_spbu_base(0); + void __iomem *gpio_base = misc_platform_get_gpio_base(0); + switch (cpu_desc.model) { case CPU_SW831: - __io_write_longtime(0, saved_long_time); - __io_write_longtime_start_en(0, 0x1); + writeq(saved_long_time, intpu_base + OFFSET_LONG_TIME); + writeq(0x1, spbu_base + OFFSET_LONG_TIME_START_EN); break; case CPU_SW8A: - __io_write_longtime_start_en(0, 0x1); + writeq(0x1, gpio_base + OFFSET_GPIO_SWPORTA_DDR); break; default: pr_info("long time start is disable!"); @@ -204,13 +226,17 @@ static inline void intpu_restore(void) static inline void spbu_save(void) { - saved_dvc_int = sw64_io_read(0, MCU_DVC_INT_EN); + void __iomem *spbu_base = misc_platform_get_spbu_base(0); + + saved_dvc_int = readq(spbu_base + OFFSET_MCU_DVC_INT_EN); } static inline void spbu_restore(void) { + void __iomem *spbu_base = misc_platform_get_spbu_base(0); + i2c_srst(); - sw64_io_write(0, MCU_DVC_INT_EN, saved_dvc_int); + writeq(saved_dvc_int, spbu_base + OFFSET_MCU_DVC_INT_EN); } static int io_suspend(void) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 839176939efb..f55ddc856df9 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -470,6 +470,18 @@ void early_parse_fdt_property(const void *fdt, const char *path, *property = of_read_number(prop, size / 4); } +bool sunway_machine_is_compatible(const char *compat) +{ + const void *fdt = initial_boot_params; + int offset; + + offset = fdt_path_offset(fdt, "/"); + if (offset < 0) + return false; + + return !fdt_node_check_compatible(fdt, offset, compat); +} + static void __init setup_firmware_fdt(void) { void *dt_virt; @@ -691,8 +703,6 @@ setup_arch(char **cmdline_p) setup_cpu_info(); setup_run_mode(); setup_chip_ops(); - if (is_guest_or_emul()) - get_vt_smp_info(); setup_sched_clock(); diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 02db49e919e4..dba2feae32e2 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -57,17 +57,25 @@ enum core_version { }; #ifdef CONFIG_SUBARCH_C4 +#define OFFSET_CLU_LV2_SELH 0x3a00UL +#define OFFSET_CLU_LV2_SELL 0x3b00UL + static void upshift_freq(void) { int i, cpu_num; + void __iomem *spbu_base; if (is_guest_or_emul()) return; + if (!sunway_machine_is_compatible("sunway,junzhang")) + 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); + spbu_base = misc_platform_get_spbu_base(i); + writeq(-1UL, spbu_base + OFFSET_CLU_LV2_SELH); + writeq(-1UL, spbu_base + OFFSET_CLU_LV2_SELL); udelay(1000); } } @@ -78,10 +86,14 @@ static void downshift_freq(void) int core_id, node_id, cpu; int cpuid = smp_processor_id(); struct cpu_topology *cpu_topo = &cpu_topology[cpuid]; + void __iomem *spbu_base; if (is_guest_or_emul()) return; + if (!sunway_machine_is_compatible("sunway,junzhang")) + return; + for_each_online_cpu(cpu) { struct cpu_topology *sib_topo = &cpu_topology[cpu]; @@ -93,12 +105,14 @@ static void downshift_freq(void) core_id = rcid_to_core_id(cpu_to_rcid(cpuid)); node_id = rcid_to_domain_id(cpu_to_rcid(cpuid)); + spbu_base = misc_platform_get_spbu_base(node_id); + if (core_id > 31) { value = 1UL << (2 * (core_id - 32)); - sw64_io_write(node_id, CLU_LV2_SELH, value); + writeq(value, spbu_base + OFFSET_CLU_LV2_SELH); } else { value = 1UL << (2 * core_id); - sw64_io_write(node_id, CLU_LV2_SELL, value); + writeq(value, spbu_base + OFFSET_CLU_LV2_SELL); } } #else diff --git a/arch/sw_64/kernel/topology.c b/arch/sw_64/kernel/topology.c index 8371c013446f..b00f083517c3 100644 --- a/arch/sw_64/kernel/topology.c +++ b/arch/sw_64/kernel/topology.c @@ -6,6 +6,8 @@ #include #include +#define OFFSET_SMP_INFO 0x80UL + static int __init parse_dt_topology(void) { return 0; @@ -24,11 +26,12 @@ static int topo_threads[NR_CPUS]; static int topo_cores[NR_CPUS]; static int topo_packages[NR_CPUS]; -void __init get_vt_smp_info(void) +static void __init get_vt_smp_info(void) { unsigned long smp_info; + void __iomem *spbu_base = misc_platform_get_spbu_base(0); - smp_info = sw64_io_read(0, SMP_INFO); + smp_info = readq(spbu_base + OFFSET_SMP_INFO); if (smp_info == -1UL) smp_info = 0; topo_nr_threads = (smp_info >> VT_THREADS_SHIFT) & VT_THREADS_MASK; @@ -79,6 +82,7 @@ static void __init init_topo_packages(void) static void __init init_topology_array(void) { + get_vt_smp_info(); topo_nr_cpus = num_present_cpus(); if (topo_nr_maxcpus > topo_nr_cpus) topo_nr_cpus = topo_nr_maxcpus; diff --git a/arch/sw_64/kvm/kvm_core3.c b/arch/sw_64/kvm/kvm_core3.c index 355d7697c535..8b751c76f121 100644 --- a/arch/sw_64/kvm/kvm_core3.c +++ b/arch/sw_64/kvm/kvm_core3.c @@ -24,6 +24,8 @@ #include "trace.h" #include "vmem.c" +#define OFFSET_LONG_TIME 0x180UL + __read_mostly bool bind_vcpu_enabled; #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_NUMA) @@ -240,10 +242,11 @@ int kvm_sw64_vcpu_reset(struct kvm_vcpu *vcpu) long kvm_sw64_get_vcb(struct file *filp, unsigned long arg) { + void __iomem *intpu_base = misc_platform_get_intpu_base(0); struct kvm_vcpu *vcpu = filp->private_data; if (vcpu->arch.vcb.migration_mark) { - unsigned long result = sw64_io_read(0, LONG_TIME) + unsigned long result = readq(intpu_base + OFFSET_LONG_TIME) + vcpu->arch.vcb.guest_longtime_offset; vcpu->arch.vcb.guest_longtime = result; vcpu->arch.vcb.guest_irqs_pending = vcpu->arch.irqs_pending[0]; @@ -260,6 +263,7 @@ long kvm_sw64_set_vcb(struct file *filp, unsigned long arg) unsigned long result; struct kvm_vcpu *vcpu = filp->private_data; struct vcpucb *kvm_vcb; + void __iomem *intpu_base = misc_platform_get_intpu_base(0); kvm_vcb = memdup_user((void __user *)arg, sizeof(*kvm_vcb)); memcpy(&(vcpu->arch.vcb), kvm_vcb, sizeof(struct vcpucb)); @@ -269,7 +273,7 @@ long kvm_sw64_set_vcb(struct file *filp, unsigned long arg) vcpu->arch.vcb.vpcr = get_vpcr(vcpu, 0); /* synchronize the longtime of source and destination */ if (vcpu->arch.vcb.soft_cid == 0) { - result = sw64_io_read(0, LONG_TIME); + result = readq(intpu_base + OFFSET_LONG_TIME); vcpu->arch.vcb.guest_longtime_offset = vcpu->arch.vcb.guest_longtime - result; longtime_offset = vcpu->arch.vcb.guest_longtime_offset; } else diff --git a/arch/sw_64/pci/pci-legacy.c b/arch/sw_64/pci/pci-legacy.c index 8eb5458dc2fc..379a6566f0da 100644 --- a/arch/sw_64/pci/pci-legacy.c +++ b/arch/sw_64/pci/pci-legacy.c @@ -9,6 +9,9 @@ #include #include +#define OFFSET_DEVINT_WKEN 0x1500UL +#define OFFSET_DEVINTWK_INTEN 0x1600UL + /* * The PCI controller list. */ @@ -240,8 +243,16 @@ sw64_init_host(unsigned long node, unsigned long index) } } -void __weak set_devint_wken(int node) {} -void __weak set_adr_int(int node) {} +static void set_devint_wken(int node) +{ + unsigned long val; + void __iomem *intpu_base = misc_platform_get_intpu_base(node); + + /* enable INTD wakeup */ + val = 0x80; + writeq(val, intpu_base + OFFSET_DEVINT_WKEN); + writeq(val, intpu_base + OFFSET_DEVINTWK_INTEN); +} static bool __init is_any_rc_linkup_one_node(unsigned long node) { @@ -263,18 +274,19 @@ void __init sw64_init_arch(void) char id[8], msg[64]; int i; + if (!acpi_disabled) + return; + + if (sunway_machine_is_compatible("sunway,junzhang_v3")) + return; + cpu_num = sw64_chip->get_cpu_num(); for (node = 0; node < cpu_num; node++) { - if (is_in_host()) { + if (is_in_host()) set_devint_wken(node); - set_adr_int(node); - } } - if (!acpi_disabled) - return; - pr_info("SW arch PCI initialize!\n"); for (node = 0; node < cpu_num; node++) { rc_enable = sw64_chip_init->pci_init.get_rc_enable(node); diff --git a/arch/sw_64/platform/cpufreq.c b/arch/sw_64/platform/cpufreq.c index 87f66b2313b5..69d7611a2fb0 100644 --- a/arch/sw_64/platform/cpufreq.c +++ b/arch/sw_64/platform/cpufreq.c @@ -8,11 +8,10 @@ #include #include -#include #include #include #include -#include +#include #define MAX_RETRY 10 @@ -139,9 +138,10 @@ unsigned int __sw64_cpufreq_get(struct cpufreq_policy *policy) { int i; u64 val; + void __iomem *spbu_base = misc_platform_get_spbu_base(0); struct cpufreq_frequency_table *ft = policy->freq_table; - val = sw64_io_read(0, CLK_CTL) >> CORE_PLL2_CFG_SHIFT; + val = readq(spbu_base + OFFSET_CLK_CTL) >> CORE_PLL2_CFG_SHIFT; val &= CORE_PLL2_CFG_MASK; for (i = 0; ft[i].frequency != CPUFREQ_TABLE_END; i++) { @@ -155,25 +155,36 @@ EXPORT_SYMBOL(__sw64_cpufreq_get); int sw64_set_rate(unsigned int index) { int i, retry, cpu_num; + void __iomem *spbu_base; cpu_num = sw64_chip->get_cpu_num(); for (i = 0; i < cpu_num; i++) { - sw64_io_write(i, CLU_LV1_SEL, CLK_LV1_SEL_PROTECT); - sw64_io_write(i, CLK_CTL, CLK2_PROTECT | CORE_CLK2_RESET | CORE_CLK2_VALID | CLK0_PROTECT); - sw64_io_write(i, CLK_CTL, CLK2_PROTECT | CORE_CLK2_VALID | (unsigned long)index << CORE_PLL2_CFG_SHIFT); + spbu_base = misc_platform_get_spbu_base(i); + + /* select PLL0/PLL1 */ + writeq(CLK_LV1_SEL_PROTECT, spbu_base + OFFSET_CLU_LV1_SEL); + /* reset PLL2 */ + writeq(CLK2_PROTECT | CORE_CLK2_RESET | CORE_CLK2_VALID, spbu_base + OFFSET_CLK_CTL); + /* configure PLL2_CFG */ + writeq(CLK2_PROTECT | CORE_CLK2_VALID | (unsigned long)index << CORE_PLL2_CFG_SHIFT, + spbu_base + OFFSET_CLK_CTL); udelay(1); - sw64_io_write(i, CLK_CTL, CORE_CLK2_VALID); + /* reset over */ + writeq(CORE_CLK2_VALID, spbu_base + OFFSET_CLK_CTL); retry = 0; while (retry < MAX_RETRY) { - if (sw64_io_read(i, CLK_CTL) & CORE_CLK2_LOCK) + if (readq(spbu_base + OFFSET_CLK_CTL) & CORE_CLK2_LOCK) break; retry++; udelay(100); } if (retry == MAX_RETRY) return -ETIME; - sw64_io_write(i, CLK_CTL, 0); - sw64_io_write(i, CLU_LV1_SEL, CLK_LV1_SEL_MUXA | CLK_LV1_SEL_MUXB | CLK_LV1_SEL_PROTECT); + /* configure over */ + writeq(0, spbu_base + OFFSET_CLK_CTL); + /* select PLL2/PLL2 */ + writeq(CLK_LV1_SEL_MUXA | CLK_LV1_SEL_MUXB | CLK_LV1_SEL_PROTECT, + spbu_base + OFFSET_CLU_LV1_SEL); } return 0; } diff --git a/drivers/clocksource/timer-sw64.c b/drivers/clocksource/timer-sw64.c index c7233617283f..5dad3496c0a0 100644 --- a/drivers/clocksource/timer-sw64.c +++ b/drivers/clocksource/timer-sw64.c @@ -71,23 +71,36 @@ void __init sw64_setup_clocksource(void) void __init setup_sched_clock(void) { } #elif defined(CONFIG_SUBARCH_C3B) #ifdef CONFIG_SMP +#define OFFSET_LONG_TIME_START_EN 0x9000UL + +#define OFFSET_LONG_TIME 0x180UL + +#define OFFSET_GPIO_SWPORTA_DR 0x0UL +#define OFFSET_GPIO_SWPORTA_DDR 0x200UL + static u64 read_longtime(struct clocksource *cs) { unsigned long node; + void __iomem *intpu_base; node = __this_cpu_read(hard_node_id); - return __io_read_longtime(node); + intpu_base = misc_platform_get_intpu_base(node); + + return readq(intpu_base + OFFSET_LONG_TIME); } static int longtime_enable(struct clocksource *cs) { + void __iomem *spbu_base = misc_platform_get_spbu_base(0); + void __iomem *gpio_base = misc_platform_get_gpio_base(0); + switch (cpu_desc.model) { case CPU_SW3231: - sw64_io_write(0, GPIO_SWPORTA_DR, 0); - sw64_io_write(0, GPIO_SWPORTA_DDR, 0xff); + writeq(0, gpio_base + OFFSET_GPIO_SWPORTA_DR); + writeq(0xff, gpio_base + OFFSET_GPIO_SWPORTA_DDR); break; case CPU_SW831: - __io_write_longtime_start_en(0, 0x1); + writeq(0x1, spbu_base + OFFSET_LONG_TIME_START_EN); break; default: break; @@ -111,7 +124,7 @@ static u64 read_vtime(struct clocksource *cs) { unsigned long vtime_addr; - vtime_addr = IO_BASE | LONG_TIME; + vtime_addr = IO_BASE | INTPU_BASE | OFFSET_LONG_TIME; return rdio64(vtime_addr); } diff --git a/drivers/cpufreq/sw64_cpufreq_debugfs.c b/drivers/cpufreq/sw64_cpufreq_debugfs.c index f72dbb9d5e16..e09c63495a0e 100644 --- a/drivers/cpufreq/sw64_cpufreq_debugfs.c +++ b/drivers/cpufreq/sw64_cpufreq_debugfs.c @@ -13,8 +13,9 @@ static int cpufreq_show(struct seq_file *m, void *v) { int i; u64 val; + void __iomem *spbu_base = misc_platform_get_spbu_base(0); - val = sw64_io_read(0, CLK_CTL) >> CORE_PLL2_CFG_SHIFT; + val = readq(spbu_base + OFFSET_CLK_CTL) >> CORE_PLL2_CFG_SHIFT; val &= CORE_PLL2_CFG_MASK; seq_puts(m, "CPU frequency in Mhz:\n"); for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 6be0af85a0b5..44cb6b258a38 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -36,6 +36,7 @@ config SW64_IRQ_CPU bool depends on SW64 default y + select SW64_PINTC config SW64_PCI_INTX bool diff --git a/drivers/irqchip/irq-sunway-cpu.c b/drivers/irqchip/irq-sunway-cpu.c index f68bca18923f..4947805c33ab 100644 --- a/drivers/irqchip/irq-sunway-cpu.c +++ b/drivers/irqchip/irq-sunway-cpu.c @@ -117,25 +117,6 @@ static void dummy_perf(unsigned long vector, struct pt_regs *regs) void (*perf_irq)(unsigned long vector, struct pt_regs *regs) = dummy_perf; EXPORT_SYMBOL(perf_irq); -static void handle_fault_int(void) -{ - int node; - unsigned long value; - - node = __this_cpu_read(hard_node_id); - pr_info("enter fault int, si_fault_stat = %#lx\n", - sw64_io_read(node, SI_FAULT_STAT)); - sw64_io_write(node, SI_FAULT_INT_EN, 0); - sw64_io_write(node, DLI_RLTD_FAULT_INTEN, 0); -#if defined(CONFIG_UNCORE_XUELANG) - value = 0; -#elif defined(CONFIG_UNCORE_JUNZHANG) - value = sw64_io_read(node, FAULT_INT_CONFIG); - value |= (1 << 8); -#endif - __io_write_fault_int_en(node, value); -} - static void handle_mt_int(void) { pr_info("enter mt int\n"); @@ -146,33 +127,6 @@ 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; - int node = 0; - unsigned int hwirq; - - config_val = sw64_io_read(node, DEV_INT_CONFIG); - val = config_val & (~(1UL << 8)); - sw64_io_write(node, DEV_INT_CONFIG, val); - stat = sw64_io_read(node, MCU_DVC_INT); - - while (stat) { - hwirq = ffs(stat) - 1; - generic_handle_domain_irq(mcu_irq_domain, hwirq); - stat &= ~(1UL << hwirq); - } - - 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; asmlinkage void do_entInt(unsigned long type, unsigned long vector, @@ -344,12 +298,6 @@ static int __init pintc_parse_madt(union acpi_subtable_headers *header, 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"); diff --git a/drivers/irqchip/irq-sunway-pintc.c b/drivers/irqchip/irq-sunway-pintc.c index fa3af8c1c585..e2f1c39538d6 100644 --- a/drivers/irqchip/irq-sunway-pintc.c +++ b/drivers/irqchip/irq-sunway-pintc.c @@ -7,6 +7,8 @@ #include #include +#include + /** * Currently, Peripheral interrupt control logic of Sunway is mainly * distributed on the device side, which are hardware entities @@ -43,9 +45,26 @@ #define PREFIX "PINTC: " -#define OFFSET_MCU_DVC_INT_EN 0x3080UL - -#define OFFSET_DEV_INT_CONFIG 0x480UL +#define OFFSET_DLI_RLTD_FAULT_INTEN 0xa80UL +#define OFFSET_MCU_DVC_INT 0x3000UL +#define OFFSET_MCU_DVC_INT_EN 0x3080UL +#define OFFSET_SI_FAULT_STAT 0x3100UL +#define OFFSET_SI_FAULT_INT_EN 0x3200UL +#define OFFSET_ADR_CTL 0x3600UL /* PINTC version >= 2 */ +#define OFFSET_DUAL_CG0_FAULT_INTEN 0x7580UL /* PINTC version 1 only */ +#define OFFSET_DUAL_CG1_FAULT_INTEN 0x7600UL /* PINTC version 1 only */ +#define OFFSET_DUAL_CG2_FAULT_INTEN 0x7680UL /* PINTC version 1 only */ +#define OFFSET_DUAL_CG3_FAULT_INTEN 0x7700UL /* PINTC version 1 only */ +#define OFFSET_DUAL_CG4_FAULT_INTEN 0x7780UL /* PINTC version 1 only */ +#define OFFSET_DUAL_CG5_FAULT_INTEN 0x7800UL /* PINTC version 1 only */ +#define OFFSET_DUAL_CG6_FAULT_INTEN 0x7880UL /* PINTC version 1 only */ +#define OFFSET_DUAL_CG7_FAULT_INTEN 0x7900UL /* PINTC version 1 only */ + +#define OFFSET_DEV_INT_CONFIG 0x480UL +#define OFFSET_FAULT_INT_CONFIG 0x780UL +#define OFFSET_DEVINT_WKEN 0x1500UL +#define OFFSET_ADR_INT_CONFIG 0x1580UL /* PINTC version >= 2 */ +#define OFFSET_DEVINTWK_INTEN 0x1600UL #define SW_PINTC_MCU_GSI_BASE 64 @@ -55,6 +74,8 @@ #define MCU_BASE_V1 0x803000000000 #define MCU_SIZE_V1 0x8f00 +DECLARE_PER_CPU(unsigned long, hard_node_id); + struct pintc_chip_data { bool vt; /* virtual pintc */ u32 node; /* node ID */ @@ -65,6 +86,39 @@ struct pintc_chip_data { u32 mcu_irq_num; }; +static struct pintc_chip_data *chip_datas[MAX_NUMNODES]; + +static struct pintc_chip_data *pintc_alloc_chip_data(u32 node) +{ + struct pintc_chip_data *chip_data; + + if (WARN_ON(node >= MAX_NUMNODES)) + return NULL; + + chip_data = kzalloc_node(sizeof(struct pintc_chip_data), + GFP_KERNEL, node); + if (!chip_data) + chip_data = kzalloc(sizeof(struct pintc_chip_data), + GFP_KERNEL); + + chip_datas[node] = chip_data; + + return chip_data; +} + +static void pintc_free_chip_data(struct pintc_chip_data *chip_data) +{ + if (!chip_data) + return; + + if (WARN_ON((chip_data->node >= MAX_NUMNODES) || + (chip_datas[chip_data->node] != chip_data))) + return; + + chip_datas[chip_data->node] = NULL; + kfree(chip_data); +} + static DEFINE_RAW_SPINLOCK(pintc_lock); static void lock_dev_lock(void) { @@ -120,7 +174,7 @@ static void mcu_irq_disable(struct irq_data *irq_data) mcu_irq_mask(irq_data); } -static unsigned long make_mcu_int_target(u32 version, int rcid) +static unsigned long make_pintc_int_target(u32 version, int rcid) { int node, core, thread; unsigned long target = 0; @@ -168,7 +222,7 @@ static int __assign_mcu_irq_config(const struct pintc_chip_data *chip_data, rcid = cpu_to_rcid(cpu); val = readq(chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); - dev_int_tar = make_mcu_int_target(chip_data->version, rcid); + dev_int_tar = make_pintc_int_target(chip_data->version, rcid); val &= 0xffff; val |= dev_int_tar << 16; writeq(val, chip_data->pintc_base + OFFSET_DEV_INT_CONFIG); @@ -333,13 +387,89 @@ static int __init pintc_init_mcu(struct pintc_chip_data *chip_data, return -ENOMEM; } - pr_info(PREFIX "MCU sub controller [%u:%u] initialized\n", + pr_info(PREFIX "MCU version [%u] on node [%u] initialized\n", chip_data->version, chip_data->node); return 0; } +void handle_dev_int(struct pt_regs *regs) +{ + void __iomem *mcu_base, *intpu_base; + unsigned long config_val, val, stat; + unsigned int hwirq; + + /* Currently, only MCU controller on node 0 is supported */ + mcu_base = chip_datas[0]->mcu_base; + intpu_base = chip_datas[0]->pintc_base; + + config_val = readq(intpu_base + OFFSET_DEV_INT_CONFIG); + val = config_val & (~(1UL << 8)); + writeq(val, intpu_base + OFFSET_DEV_INT_CONFIG); + stat = readq(mcu_base + OFFSET_MCU_DVC_INT); + + while (stat) { + hwirq = ffs(stat) - 1; + generic_handle_domain_irq(mcu_irq_domain, hwirq); + stat &= ~(1UL << hwirq); + } + + writeq(config_val, intpu_base + OFFSET_DEV_INT_CONFIG); +} + +void handle_fault_int(void) +{ + int node; + unsigned long value; + void __iomem *mcu_base, *intpu_base; + + node = __this_cpu_read(hard_node_id); + +#if defined(CONFIG_UNCORE_XUELANG) + mcu_base = misc_platform_get_spbu_base(node); + intpu_base = misc_platform_get_intpu_base(node); +#elif defined(CONFIG_UNCORE_JUNZHANG) + mcu_base = chip_datas[node]->mcu_base; + intpu_base = chip_datas[node]->pintc_base; +#endif + + pr_info("Enter fault int, si_fault_stat = %#llx\n", + readq(mcu_base + OFFSET_SI_FAULT_STAT)); + + writeq(0, mcu_base + OFFSET_SI_FAULT_INT_EN); + writeq(0, mcu_base + OFFSET_DLI_RLTD_FAULT_INTEN); + +#if defined(CONFIG_UNCORE_XUELANG) + value = 0; + writeq(value, mcu_base + OFFSET_DUAL_CG0_FAULT_INTEN); + writeq(value, mcu_base + OFFSET_DUAL_CG1_FAULT_INTEN); + writeq(value, mcu_base + OFFSET_DUAL_CG2_FAULT_INTEN); + writeq(value, mcu_base + OFFSET_DUAL_CG3_FAULT_INTEN); + writeq(value, mcu_base + OFFSET_DUAL_CG4_FAULT_INTEN); + writeq(value, mcu_base + OFFSET_DUAL_CG5_FAULT_INTEN); + writeq(value, mcu_base + OFFSET_DUAL_CG6_FAULT_INTEN); + writeq(value, mcu_base + OFFSET_DUAL_CG7_FAULT_INTEN); +#elif defined(CONFIG_UNCORE_JUNZHANG) + value = readq(intpu_base + OFFSET_FAULT_INT_CONFIG); + value |= (1 << 8); + writeq(value, intpu_base + OFFSET_FAULT_INT_CONFIG); +#endif +} + #ifdef CONFIG_OF +static int __init pintc_of_init_mcu(struct pintc_chip_data *chip_data, + struct device_node *pintc) +{ + /* Not yet supported */ + if (chip_data->node > 0) { + pr_info(PREFIX "MCU version [%u] on node [%u] skipped\n", + chip_data->version, chip_data->node); + return 0; + } + + return pintc_init_mcu(chip_data, of_node_to_fwnode(pintc)); +} + static int __init pintc_of_init_common(struct device_node *pintc, struct device_node *parent, bool vt) @@ -393,7 +523,7 @@ pintc_of_init_common(struct device_node *pintc, MCU_BASE_V1); } - chip_data = kzalloc_node(sizeof(*chip_data), GFP_KERNEL, node); + chip_data = pintc_alloc_chip_data(node); if (!chip_data) { ret = -ENOMEM; goto out_unmap; @@ -406,14 +536,20 @@ pintc_of_init_common(struct device_node *pintc, chip_data->mcu_base = mcu_base; chip_data->mcu_irq_num = nr_irqs; - ret = pintc_init_mcu(chip_data, of_node_to_fwnode(pintc)); + /* Enable S3 wakeup interrupt for physical environment */ + if (!vt && IS_ENABLED(CONFIG_SUSPEND)) { + writeq(0x80, chip_data->pintc_base + OFFSET_DEVINT_WKEN); + writeq(0x80, chip_data->pintc_base + OFFSET_DEVINTWK_INTEN); + } + + ret = pintc_of_init_mcu(chip_data, pintc); if (ret) goto out_free_mem; return 0; out_free_mem: - kfree(chip_data); + pintc_free_chip_data(chip_data); out_unmap: iounmap(mcu_base); iounmap(pintc_base); @@ -496,8 +632,15 @@ static int __init pintc_acpi_init_mcu(struct pintc_chip_data *chip_data, struct fwnode_handle *handle; int ret; + /* Not yet supported */ + if (chip_data->node > 0) { + pr_info(PREFIX "MCU version [%u] on node [%u] skipped\n", + chip_data->version, chip_data->node); + return 0; + } + if (!mcu->status) { - pr_info(PREFIX "MCU sub controller [%u:%u] disabled\n", + pr_info(PREFIX "MCU version [%u] on node [%u] disabled\n", chip_data->version, chip_data->node); return 0; } @@ -532,6 +675,10 @@ static int __init pintc_acpi_init_mcu(struct pintc_chip_data *chip_data, goto out_acpi_free_mcu_domain; } + /* Init SW LPC INTC */ + acpi_table_parse_madt(ACPI_MADT_TYPE_SW_LPC_INTC, + lpc_intc_parse_madt, 0); + return 0; out_acpi_free_mcu_domain: @@ -543,6 +690,28 @@ static int __init pintc_acpi_init_mcu(struct pintc_chip_data *chip_data, return ret; } +static int __init pintc_acpi_init_fault(struct pintc_chip_data *chip_data, + struct acpi_madt_sw_sub_pintc *fault) +{ + if (!fault->status) { + pr_info(PREFIX "Fault version [%u] on node [%u] disabled\n", + chip_data->version, chip_data->node); + return 0; + } + + /* Fault share the same base address with MCU currently */ + chip_data->mcu_base = ioremap(fault->address, fault->size); + if (!chip_data->mcu_base) { + pr_err(PREFIX "failed to map fault base address\n"); + return -ENXIO; + } + + pr_info(PREFIX "Fault version [%u] on node [%u] initialized\n", + chip_data->version, chip_data->node); + + return 0; +} + int __init pintc_acpi_init(struct irq_domain *parent, struct acpi_madt_sw_pintc *pintc) { @@ -566,8 +735,7 @@ int __init pintc_acpi_init(struct irq_domain *parent, return -EINVAL; } - chip_data = kzalloc_node(sizeof(*chip_data), GFP_KERNEL, - pintc->node); + chip_data = pintc_alloc_chip_data(pintc->node); if (!chip_data) return -ENOMEM; @@ -588,24 +756,29 @@ int __init pintc_acpi_init(struct irq_domain *parent, goto out_acpi_free_chip_data; } + /* Enable S3 wakeup interrupt for physical environment */ + if (!virtual && IS_ENABLED(CONFIG_SUSPEND)) { + writeq(0x80, chip_data->pintc_base + OFFSET_DEVINT_WKEN); + writeq(0x80, chip_data->pintc_base + OFFSET_DEVINTWK_INTEN); + } + 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; + case SW_PINTC_SUB_TYPE_FAULT: + pintc_acpi_init_fault(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); + pintc_free_chip_data(chip_data); return ret; } #endif diff --git a/drivers/pci/controller/pci-sunway.c b/drivers/pci/controller/pci-sunway.c index db4ad9247887..e6e178923fd1 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -6,23 +6,7 @@ #include -void set_devint_wken(int node) -{ - unsigned long val; - - /* enable INTD wakeup */ - val = 0x80; - sw64_io_write(node, DEVINT_WKEN, val); - sw64_io_write(node, DEVINTWK_INTEN, val); -} - -#ifdef CONFIG_UNCORE_JUNZHANG -void set_adr_int(int node) -{ - sw64_io_write(node, ADR_INT_CONFIG, (CORE0_CID << 16 | 0x3f)); - sw64_io_write(node, ADR_CTL, 0xc); -} -#endif +#define OFFSET_IO_START 0x1300UL void set_pcieport_service_irq(struct pci_controller *hose) { @@ -263,11 +247,13 @@ static void set_rc_piu(struct pci_controller *hose) static unsigned long get_rc_enable(unsigned long node) { unsigned long rc_enable; + void __iomem *spbu_base; if (is_guest_or_emul()) return 1; - rc_enable = sw64_io_read(node, IO_START); + spbu_base = misc_platform_get_spbu_base(node); + rc_enable = readq(spbu_base + OFFSET_IO_START); return rc_enable; } -- Gitee From a5a6a31b366a295b4fe13d316007f17f0b8f06c0 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 14 Aug 2024 10:12:35 +0800 Subject: [PATCH 083/100] anolis: sw64: pci: support PCIe controller driver based on device tree ANBZ: #4688 Now we can describe Sunway PCIe controller via device tree. Here is an example of a device tree description: pcie0: pcie@8800 { compatible = "sunway,pcie"; device_type = "pci"; numa-node-id = <0>; reg = <0x8806 0x0 0x1 0x0>; reg-names = "ecam"; sunway,rc-config-base = <0x8805 0x0>; sunway,ep-config-base = <0x8806 0x0>; sunway,ep-mem-32-base = <0x8800 0x0>; sunway,ep-mem-64-base = <0x8880 0x0>; sunway,ep-io-base = <0x8801 0x0>; sunway,piu-ior0-base = <0x8802 0x0>; sunway,piu-ior1-base = <0x8803 0x0>; sunway,rc-index = <0x0 0x0>; sunway,pcie-io-base = <0x8800 0x0>; #address-cells = <3>; #size-cells = <2>; bus-range = <0x0 0xff>; /* I/O, 32 bits mem and prefetchable 64 bits mem */ ranges = <0x01000000 0x0 0x0 0x8801 0x0 0x1 0x0>, <0x02000000 0x0 0xe0000000 0x8800 0xe0000000 0x0 0x20000000>, <0x43000000 0x8880 0x0 0x8880 0x0 0x80 0x0>; status = "okay"; }; Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/io.h | 14 ++ arch/sw_64/include/asm/pci.h | 3 +- arch/sw_64/pci/acpi.c | 61 +++--- arch/sw_64/pci/pci-legacy.c | 9 +- arch/sw_64/pci/pci.c | 25 ++- drivers/pci/controller/pci-sunway.c | 234 ++++++++++++++++++++--- drivers/pci/hotplug/sunway_pciehp_core.c | 37 ++-- 7 files changed, 307 insertions(+), 76 deletions(-) diff --git a/arch/sw_64/include/asm/io.h b/arch/sw_64/include/asm/io.h index 15abf97e9d57..1695801e6c4b 100644 --- a/arch/sw_64/include/asm/io.h +++ b/arch/sw_64/include/asm/io.h @@ -121,6 +121,20 @@ static inline void * __deprecated bus_to_virt(unsigned long address) } #define isa_bus_to_virt bus_to_virt +static inline int pci_remap_iospace(const struct resource *res, + phys_addr_t phys_addr) +{ + if (!(res->flags & IORESOURCE_IO)) + return -EINVAL; + + if (res->end > IO_SPACE_LIMIT) + return -EINVAL; + + return 0; +} + +#define pci_remap_iospace pci_remap_iospace + #endif /* __KERNEL__ */ #endif /* _ASM_SW64_IO_H */ diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index 877aa0107539..7e9bf4fcb25d 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -158,6 +158,8 @@ extern void __init sw64_init_arch(void); extern struct pci_ops sw64_pci_ops; extern int sw64_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); extern struct pci_controller *hose_head; +extern bool sunway_legacy_pci; + #ifdef CONFIG_PCI_SW64 extern void __init setup_chip_pci_ops(void); #else @@ -168,7 +170,6 @@ 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); 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); diff --git a/arch/sw_64/pci/acpi.c b/arch/sw_64/pci/acpi.c index 6f03ea79131c..514e7838f3c8 100644 --- a/arch/sw_64/pci/acpi.c +++ b/arch/sw_64/pci/acpi.c @@ -5,8 +5,6 @@ #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; @@ -87,6 +85,33 @@ pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root) return cfg; } +static int upper_32_bits_of_ep_mem_32_base(struct acpi_device *adev, u64 *memh) +{ + int status = 0; + u64 val; + const char *prop = "sunway,ep-mem-32-base"; + const char *legacy_prop = "sw64,ep_mem_32_base"; + + status = fwnode_property_read_u64(&adev->fwnode, prop, &val); + + /* Fallback to legacy property name and try again */ + if (status) + status = fwnode_property_read_u64(&adev->fwnode, + legacy_prop, &val); + + /* This property is necessary */ + if (status) { + dev_err(&adev->dev, "failed to retrieve %s or %s\n", + prop, legacy_prop); + return status; + } + + *memh = upper_32_bits(val); + *memh <<= 32; + + return 0; +} + static int pci_acpi_prepare_root_resources(struct acpi_pci_root_info *ci) { int status = 0; @@ -100,14 +125,9 @@ static int pci_acpi_prepare_root_resources(struct acpi_pci_root_info *ci) * * Get the upper 32 bits here. */ - 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"); + status = upper_32_bits_of_ep_mem_32_base(device, &memh); + if (status) return status; - } - - memh = UPPER_32_BITS_OF_U64(memh); /** * Get host bridge resources via _CRS method, the return value @@ -131,7 +151,7 @@ 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 (!UPPER_32_BITS_OF_U64(entry->res->end)) { + if (!upper_32_bits(entry->res->end)) { /* Patch mem res with upper 32 bits */ entry->res->start |= memh; entry->res->end |= memh; @@ -225,27 +245,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) return NULL; } -int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) -{ - if (!acpi_disabled) { - struct pci_config_window *cfg = bridge->sysdata; - struct acpi_device *adev = to_acpi_device(cfg->parent); - struct pci_controller *hose = cfg->priv; - struct device *bus_dev = &bridge->bus->dev; - - ACPI_COMPANION_SET(&bridge->dev, adev); - set_dev_node(bus_dev, hose->node); - - /** - * Some quirks for pci controller of Sunway - * before scanning Root Complex - */ - sw64_pci_root_bridge_prepare(bridge); - } - - return 0; -} - void pcibios_add_bus(struct pci_bus *bus) { acpi_pci_add_bus(bus); diff --git a/arch/sw_64/pci/pci-legacy.c b/arch/sw_64/pci/pci-legacy.c index 379a6566f0da..caa64977fa74 100644 --- a/arch/sw_64/pci/pci-legacy.c +++ b/arch/sw_64/pci/pci-legacy.c @@ -12,6 +12,8 @@ #define OFFSET_DEVINT_WKEN 0x1500UL #define OFFSET_DEVINTWK_INTEN 0x1600UL +bool sunway_legacy_pci; + /* * The PCI controller list. */ @@ -22,7 +24,7 @@ static void __init pcibios_reserve_legacy_regions(struct pci_bus *bus); static int __init pcibios_init(void) { - if (acpi_disabled) + if (sunway_legacy_pci) sw64_init_pci(); return 0; } @@ -277,9 +279,12 @@ void __init sw64_init_arch(void) if (!acpi_disabled) return; - if (sunway_machine_is_compatible("sunway,junzhang_v3")) + if (!sunway_machine_is_compatible("sunway,chip3") && + !sunway_machine_is_compatible("sunway,junzhang")) return; + sunway_legacy_pci = true; + cpu_num = sw64_chip->get_cpu_num(); for (node = 0; node < cpu_num; node++) { diff --git a/arch/sw_64/pci/pci.c b/arch/sw_64/pci/pci.c index de974eff019d..0b1a3692fd40 100644 --- a/arch/sw_64/pci/pci.c +++ b/arch/sw_64/pci/pci.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -287,7 +288,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, enable_sw_dca); */ static unsigned char last_bus; -void sw64_pci_root_bridge_prepare(struct pci_host_bridge *bridge) +static void sw64_pci_root_bridge_prepare(struct pci_host_bridge *bridge) { struct pci_controller *hose = NULL; struct resource_entry *entry = NULL; @@ -429,3 +430,25 @@ void sw64_pci_root_bridge_scan_finish_up(struct pci_host_bridge *bridge) */ pci_clear_flags(PCI_REASSIGN_ALL_BUS); } + +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + struct pci_config_window *cfg = bridge->sysdata; + struct acpi_device *adev = NULL; + struct pci_controller *hose = cfg->priv; + struct device *bus_dev = &bridge->bus->dev; + + if (sunway_legacy_pci) + return 0; + + if (!acpi_disabled) + adev = to_acpi_device(cfg->parent); + + ACPI_COMPANION_SET(&bridge->dev, adev); + set_dev_node(bus_dev, hose->node); + + /* Some quirks for Sunway PCIe controller before scanning */ + sw64_pci_root_bridge_prepare(bridge); + + return 0; +} diff --git a/drivers/pci/controller/pci-sunway.c b/drivers/pci/controller/pci-sunway.c index e6e178923fd1..3f369e81dab0 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -3,6 +3,9 @@ #include #include #include +#include +#include +#include #include @@ -385,7 +388,7 @@ struct pci_controller *pci_bus_to_pci_controller(const struct pci_bus *bus) if (unlikely(!bus)) return NULL; - if (acpi_disabled) + if (sunway_legacy_pci) return (struct pci_controller *)(bus->sysdata); cfg = (struct pci_config_window *)bus->sysdata; @@ -615,8 +618,6 @@ int sw64_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) return map_irq(dev, slot, pin); } -#ifdef CONFIG_ACPI - enum pci_props { PROP_RC_CONFIG_BASE = 0, PROP_EP_CONFIG_BASE, @@ -630,7 +631,7 @@ enum pci_props { PROP_NUM }; -const char *prop_names[PROP_NUM] = { +static const char *prop_names_legacy[PROP_NUM] = { "sw64,rc_config_base", "sw64,ep_config_base", "sw64,ep_mem_32_base", @@ -642,23 +643,68 @@ const char *prop_names[PROP_NUM] = { "sw64,pcie_io_base" }; +static const char *prop_names[PROP_NUM] = { + "sunway,rc-config-base", + "sunway,ep-config-base", + "sunway,ep-mem-32-base", + "sunway,ep-mem-64-base", + "sunway,ep-io-base", + "sunway,piu-ior0-base", + "sunway,piu-ior1-base", + "sunway,rc-index", + "sunway,pcie-io-base" +}; + +#ifdef CONFIG_NUMA +static void pci_controller_set_node(struct pci_controller *hose, + struct fwnode_handle *fwnode) +{ + if (numa_off) + return; + + /* Get node from ACPI namespace (_PXM) or DTB */ + if (acpi_disabled) + hose->node = of_node_to_nid(to_of_node(fwnode)); + else + hose->node = acpi_get_node(ACPI_HANDLE_FWNODE(fwnode)); + + /** + * If numa_off is not set, we expect a valid node ID. + * If not, fallback to node 0. + */ + if (hose->node == NUMA_NO_NODE) { + pr_warn("Invalid node ID\n"); + hose->node = 0; + } +} +#endif + 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 */ + /* Get necessary properties of Root Complex */ for (i = 0; i < PROP_NUM; ++i) { - ret = fwnode_property_read_u64_array(fwnode, prop_names[i], - &props[i], 1); + ret = fwnode_property_read_u64(fwnode, prop_names[i], + &props[i]); + + /* Fallback to legacy names and try again */ + if (ret) + ret = fwnode_property_read_u64(fwnode, + prop_names_legacy[i], &props[i]); + if (ret) { - pr_err("unable to retrieve \"%s\"\n", - prop_names[i]); + pr_err("unable to retrieve \"%s\"\n", prop_names[i]); return ret; } } +#ifdef CONFIG_NUMA + pci_controller_set_node(hose, fwnode); +#endif + hose->iommu_enable = false; hose->index = props[PROP_RC_INDEX]; @@ -709,13 +755,9 @@ static int sw64_pci_prepare_controller(struct pci_controller *hose, return 0; } -/** - * Use the info from ACPI to init pci_controller - */ -static int sw64_pci_ecam_init(struct pci_config_window *cfg) +#ifdef CONFIG_ACPI +static int sw64_pci_acpi_present(struct device *dev) { - struct pci_controller *hose = NULL; - struct device *dev = cfg->parent; struct acpi_device *adev = to_acpi_device(dev); int ret; @@ -740,27 +782,39 @@ static int sw64_pci_ecam_init(struct pci_config_window *cfg) return -ENODEV; } - hose = kzalloc(sizeof(*hose), GFP_KERNEL); - if (!hose) - return -ENOMEM; + return 0; +} +#endif -#ifdef CONFIG_ACPI_NUMA - if (!numa_off) { - /* 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; - } +/** + * Use the information from ACPI or DTB to init pci_controller + */ +static int sw64_pci_ecam_init(struct pci_config_window *cfg) +{ + struct pci_controller *hose = NULL; + struct device *dev = cfg->parent; + struct fwnode_handle *fwnode = dev->fwnode; + int ret; + +#ifdef CONFIG_ACPI + if (!acpi_disabled) { + ret = sw64_pci_acpi_present(dev); + if (ret) + return ret; + + fwnode = acpi_fwnode_handle(to_acpi_device(dev)); } #endif + hose = kzalloc(sizeof(*hose), GFP_KERNEL); + if (!hose) + return -ENOMEM; + /* Init pci_controller */ - ret = sw64_pci_prepare_controller(hose, &adev->fwnode); + ret = sw64_pci_prepare_controller(hose, fwnode); if (ret) { kfree(hose); - dev_err(&adev->dev, "failed to init pci controller\n"); + dev_err(dev, "failed to init pci controller\n"); return ret; } @@ -778,4 +832,124 @@ const struct pci_ecam_ops sw64_pci_ecam_ops = { .write = sw64_pcie_config_write, } }; -#endif + +#ifdef CONFIG_OF + +static const struct of_device_id sunway_pcie_of_match[] = { + { + .compatible = "sunway,pcie", + .data = &sw64_pci_ecam_ops, + }, + {}, +}; + +static void sunway_pcie_ecam_free(void *p) +{ + pci_ecam_free((struct pci_config_window *)p); +} + +static struct pci_host_bridge *sunway_pcie_of_init(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct pci_host_bridge *bridge; + struct pci_config_window *cfg; + struct pci_ecam_ops *ops; + struct resource *ecam_res = NULL; + struct resource_entry *bus_range = NULL; + int ret; + + ops = (struct pci_ecam_ops *)of_device_get_match_data(dev); + if (!ops) { + dev_err(dev, "failed to get ecam ops\n"); + return NULL; + } + + ecam_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ecam"); + if (!ecam_res) { + dev_err(dev, "failed to get ecam\n"); + return NULL; + } + + bridge = devm_pci_alloc_host_bridge(dev, 0); + if (!bridge) { + dev_err(dev, "failed to create host bridge\n"); + return NULL; + } + + bus_range = resource_list_first_type(&bridge->windows, IORESOURCE_BUS); + if (!bus_range) { + dev_err(dev, "failed to get bus resource\n"); + return NULL; + } + + cfg = pci_ecam_create(dev, ecam_res, bus_range->res, ops); + if (IS_ERR(cfg)) { + dev_err(dev, "failed to create ecam\n"); + return NULL; + } + + ret = devm_add_action_or_reset(dev, sunway_pcie_ecam_free, cfg); + if (ret) + return NULL; + + bridge->sysdata = cfg; + bridge->ops = (struct pci_ops *)&ops->pci_ops; + + return bridge; +} + +static int sunway_pcie_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct pci_host_bridge *bridge; + struct pci_bus *bus, *child; + int ret; + + /* Prevent conflicts between legacy PCI and DT-based PCI */ + if (sunway_legacy_pci) + return 0; + + bridge = sunway_pcie_of_init(pdev); + if (!bridge) + return -ENODEV; + + ret = pci_scan_root_bus_bridge(bridge); + if (ret < 0) { + dev_err(dev, "failed to scan root bridge\n"); + return ret; + } + + bus = bridge->bus; + + /** + * Some quirks for Sunway PCIe controller after scanning, + * that's why we don't directly call function pci_host_probe(). + */ + sw64_pci_root_bridge_scan_finish_up(bridge); + + pci_bus_size_bridges(bus); + pci_bus_assign_resources(bus); + + list_for_each_entry(child, &bus->children, node) + pcie_bus_configure_settings(child); + + pci_bus_add_devices(bus); + + return 0; +} + +static struct platform_driver sunway_pcie_driver = { + .probe = sunway_pcie_probe, + .driver = { + .name = "sunway-pcie", + .of_match_table = sunway_pcie_of_match, + }, +}; + +static int __init sunway_pcie_driver_init(void) +{ + return platform_driver_register(&sunway_pcie_driver); +} +subsys_initcall(sunway_pcie_driver_init); + +#endif /* CONFIG_OF */ diff --git a/drivers/pci/hotplug/sunway_pciehp_core.c b/drivers/pci/hotplug/sunway_pciehp_core.c index 45972adcff36..43c1a4facfae 100644 --- a/drivers/pci/hotplug/sunway_pciehp_core.c +++ b/drivers/pci/hotplug/sunway_pciehp_core.c @@ -249,23 +249,38 @@ static void sunway_hose_hotplug_init(void) struct pci_dev *pdev = NULL; struct pci_controller *hose; struct pci_config_window *cfg; - struct acpi_device *adev; - u64 prop_hotplug_enable; + struct device *dev; + struct fwnode_handle *fwnode; + u64 hotplug_enable; - while ((pdev = pci_get_device(PCI_VENDOR_ID_JN, PCI_DEVICE_ID_SW64_ROOT_BRIDGE, pdev))) { + while ((pdev = pci_get_device(PCI_VENDOR_ID_JN, + PCI_DEVICE_ID_SW64_ROOT_BRIDGE, pdev))) { hose = pci_bus_to_pci_controller(pdev->bus); + + /* disable by default */ hose->hotplug_enable = false; - if (!acpi_disabled) { - cfg = (struct pci_config_window *)pdev->bus->sysdata; - adev = to_acpi_device(cfg->parent); + if (sunway_legacy_pci) + continue; + + cfg = (struct pci_config_window *)pdev->bus->sysdata; + dev = cfg->parent; + + if (acpi_disabled) + fwnode = dev->fwnode; + else + fwnode = acpi_fwnode_handle(to_acpi_device(dev)); + + ret = fwnode_property_read_u64(fwnode, + "sunway,hotplug-enable", &hotplug_enable); - ret = fwnode_property_read_u64_array(&adev->fwnode, - "sw64,hot_plug_slot_enable", &prop_hotplug_enable, 1); + /* Fallback to legacy prop name */ + if (ret) + ret = fwnode_property_read_u64(fwnode, + "sw64,hot_plug_slot_enable", &hotplug_enable); - if (ret == 0) - hose->hotplug_enable = prop_hotplug_enable; - } + if (!ret) + hose->hotplug_enable = hotplug_enable; } } -- Gitee From 1c0b9eeece795a158f2efea8701b9cb132954e19 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Fri, 16 Aug 2024 14:45:58 +0800 Subject: [PATCH 084/100] anolis: sw64: pci: rename some functions ANBZ: #4688 Rename some PCI related functions to improve code readability. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/pci.h | 11 +++-- arch/sw_64/include/asm/sw64_init.h | 1 - arch/sw_64/pci/acpi.c | 11 ++--- arch/sw_64/pci/pci-legacy.c | 21 ++++------ arch/sw_64/pci/pci.c | 8 ++-- drivers/acpi/pci_mcfg.c | 18 ++++---- drivers/pci/controller/pci-sunway.c | 64 +++++++++++++---------------- include/linux/pci-ecam.h | 2 +- 8 files changed, 60 insertions(+), 76 deletions(-) diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index 7e9bf4fcb25d..f28a3acb015c 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -155,7 +155,6 @@ 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; extern int sw64_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); extern struct pci_controller *hose_head; extern bool sunway_legacy_pci; @@ -170,14 +169,14 @@ 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_scan_finish_up(struct pci_host_bridge *bridge); -extern int sw64_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); +extern int sunway_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); +extern void sunway_pci_root_bridge_scan_finish(struct pci_host_bridge *bridge); -extern void __iomem *sw64_pcie_map_bus(struct pci_bus *bus, +extern void __iomem *sunway_pci_map_bus(struct pci_bus *bus, unsigned int devfn, int where); -extern int sw64_pcie_config_write(struct pci_bus *bus, unsigned int devfn, +extern int sunway_pci_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, +extern int sunway_pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val); extern void pci_mark_rc_linkup(struct pci_controller *hose); diff --git a/arch/sw_64/include/asm/sw64_init.h b/arch/sw_64/include/asm/sw64_init.h index 2d553242487d..34a28e365ec6 100644 --- a/arch/sw_64/include/asm/sw64_init.h +++ b/arch/sw_64/include/asm/sw64_init.h @@ -14,7 +14,6 @@ struct sw64_early_init_ops { }; struct sw64_pci_init_ops { - int (*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin); unsigned long (*get_rc_enable)(unsigned long node); void (*hose_init)(struct pci_controller *hose); void (*set_rc_piu)(struct pci_controller *hose); diff --git a/arch/sw_64/pci/acpi.c b/arch/sw_64/pci/acpi.c index 514e7838f3c8..1b748074fdf8 100644 --- a/arch/sw_64/pci/acpi.c +++ b/arch/sw_64/pci/acpi.c @@ -85,7 +85,7 @@ pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root) return cfg; } -static int upper_32_bits_of_ep_mem_32_base(struct acpi_device *adev, u64 *memh) +static int ep_32bits_memio_base(struct acpi_device *adev, u64 *memh) { int status = 0; u64 val; @@ -125,7 +125,7 @@ static int pci_acpi_prepare_root_resources(struct acpi_pci_root_info *ci) * * Get the upper 32 bits here. */ - status = upper_32_bits_of_ep_mem_32_base(device, &memh); + status = ep_32bits_memio_base(device, &memh); if (status) return status; @@ -219,11 +219,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) if (!bus) return NULL; - /** - * Some quirks for pci controller of Sunway - * after scanning Root Complex - */ - sw64_pci_root_bridge_scan_finish_up(pci_find_host_bridge(bus)); + /* Some quirks for Sunway PCIe controller after scanning */ + sunway_pci_root_bridge_scan_finish(pci_find_host_bridge(bus)); pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); diff --git a/arch/sw_64/pci/pci-legacy.c b/arch/sw_64/pci/pci-legacy.c index caa64977fa74..ccf87520c72d 100644 --- a/arch/sw_64/pci/pci-legacy.c +++ b/arch/sw_64/pci/pci-legacy.c @@ -70,6 +70,12 @@ int __weak chip_pcie_configure(struct pci_controller *hose) return 0; } +static struct pci_ops sunway_pci_ops = { + .map_bus = sunway_pci_map_bus, + .read = sunway_pci_config_read, + .write = sunway_pci_config_write, +}; + unsigned char last_bus = PCI0_BUS; void __init common_init_pci(void) { @@ -102,9 +108,9 @@ void __init common_init_pci(void) bridge->dev.parent = NULL; bridge->sysdata = hose; bridge->busnr = hose->busn_space->start; - bridge->ops = &sw64_pci_ops; + bridge->ops = &sunway_pci_ops; bridge->swizzle_irq = pci_common_swizzle; - bridge->map_irq = sw64_map_irq; + bridge->map_irq = sunway_pci_map_irq; ret = pci_scan_root_bus_bridge(bridge); if (ret) { @@ -200,17 +206,6 @@ static void __init pcibios_reserve_legacy_regions(struct pci_bus *bus) return; } -struct pci_ops sw64_pci_ops = { - .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) -{ - return sw64_chip_init->pci_init.map_irq(dev, slot, pin); -} - static bool rc_linkup[MAX_NUMNODES][MAX_NR_RCS_PER_NODE]; static void __init diff --git a/arch/sw_64/pci/pci.c b/arch/sw_64/pci/pci.c index 0b1a3692fd40..a01eac0a890e 100644 --- a/arch/sw_64/pci/pci.c +++ b/arch/sw_64/pci/pci.c @@ -288,7 +288,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, enable_sw_dca); */ static unsigned char last_bus; -static void sw64_pci_root_bridge_prepare(struct pci_host_bridge *bridge) +static void sunway_pci_root_bridge_prepare(struct pci_host_bridge *bridge) { struct pci_controller *hose = NULL; struct resource_entry *entry = NULL; @@ -332,7 +332,7 @@ static void sw64_pci_root_bridge_prepare(struct pci_host_bridge *bridge) bus->number = last_bus; bridge->swizzle_irq = pci_common_swizzle; - bridge->map_irq = sw64_pci_map_irq; + bridge->map_irq = sunway_pci_map_irq; init_busnr = (0xff << 16) + ((last_bus + 1) << 8) + (last_bus); writel(init_busnr, (hose->rc_config_space_base + RC_PRIMARY_BUS)); @@ -372,7 +372,7 @@ sw64_pci_root_bridge_reserve_legacy_io(struct pci_host_bridge *bridge) } } -void sw64_pci_root_bridge_scan_finish_up(struct pci_host_bridge *bridge) +void sunway_pci_root_bridge_scan_finish(struct pci_host_bridge *bridge) { struct pci_controller *hose = NULL; struct pci_bus *bus = NULL; @@ -448,7 +448,7 @@ int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) set_dev_node(bus_dev, hose->node); /* Some quirks for Sunway PCIe controller before scanning */ - sw64_pci_root_bridge_prepare(bridge); + sunway_pci_root_bridge_prepare(bridge); return 0; } diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c index 58d19e109f61..0b2e7bb60707 100644 --- a/drivers/acpi/pci_mcfg.c +++ b/drivers/acpi/pci_mcfg.c @@ -211,15 +211,15 @@ static struct mcfg_fixup mcfg_quirks[] = { { "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), + /* Up to 8 nodes for Sunway PCIe controller */ + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x00, &sunway_pci_ecam_ops), + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x01, &sunway_pci_ecam_ops), + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x02, &sunway_pci_ecam_ops), + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x03, &sunway_pci_ecam_ops), + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x04, &sunway_pci_ecam_ops), + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x05, &sunway_pci_ecam_ops), + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x06, &sunway_pci_ecam_ops), + SW64_ECAM_QUIRK("SUNWAY ", 1, 0x07, &sunway_pci_ecam_ops), #endif /* SW64 */ }; diff --git a/drivers/pci/controller/pci-sunway.c b/drivers/pci/controller/pci-sunway.c index 3f369e81dab0..5df5bca108aa 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -261,7 +261,7 @@ static unsigned long get_rc_enable(unsigned long node) return rc_enable; } -static int map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int sunway_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { struct pci_controller *hose = pci_bus_to_pci_controller(dev->bus); @@ -323,7 +323,6 @@ static void hose_init(struct pci_controller *hose) }; static struct sw64_pci_init_ops chip_pci_init_ops = { - .map_irq = map_irq, .get_rc_enable = get_rc_enable, .hose_init = hose_init, .set_rc_piu = set_rc_piu, @@ -399,7 +398,7 @@ EXPORT_SYMBOL(pci_bus_to_pci_controller); /** * PCIe Root Complex read config space operations */ -static int sw64_pcie_read_rc_cfg(struct pci_bus *bus, unsigned int devfn, +static int pci_read_rc_cfg(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) { u32 data; @@ -449,7 +448,7 @@ static int sw64_pcie_read_rc_cfg(struct pci_bus *bus, unsigned int devfn, /** * PCIe Root Complex write config space operations */ -static int sw64_pcie_write_rc_cfg(struct pci_bus *bus, unsigned int devfn, +static int pci_write_rc_cfg(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) { u32 data; @@ -488,7 +487,7 @@ static int sw64_pcie_write_rc_cfg(struct pci_bus *bus, unsigned int devfn, } /** - * sw64_pcie_valid_device - check if a valid device is present + * pci_valid_device - check if a valid device is present * on bus * * @bus : PCI bus structure @@ -496,7 +495,7 @@ static int sw64_pcie_write_rc_cfg(struct pci_bus *bus, unsigned int devfn, * * @return: 'true' on success and 'false' if invalid device is found */ -static bool sw64_pcie_valid_device(struct pci_bus *bus, unsigned int devfn) +static bool pci_valid_device(struct pci_bus *bus, unsigned int devfn) { struct pci_controller *hose = pci_bus_to_pci_controller(bus); @@ -510,7 +509,7 @@ static bool sw64_pcie_valid_device(struct pci_bus *bus, unsigned int devfn) } /** - * sw64_pcie_config_read - read val from config space of + * sunway_pci_config_read - read val from config space of * PCI host controller or device * * @bus : PCI bus structure @@ -521,7 +520,7 @@ static bool sw64_pcie_valid_device(struct pci_bus *bus, unsigned int devfn) * * @return: Whether read operation success */ -int sw64_pcie_config_read(struct pci_bus *bus, unsigned int devfn, +int sunway_pci_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); @@ -533,7 +532,7 @@ int sw64_pcie_config_read(struct pci_bus *bus, unsigned int devfn, hose->self_busno = hose->busn_space->start; if (unlikely(bus->number == hose->self_busno)) { - ret = sw64_pcie_read_rc_cfg(bus, devfn, where, size, val); + ret = pci_read_rc_cfg(bus, devfn, where, size, val); } else { if (pci_get_rc_linkup(hose)) ret = pci_generic_config_read(bus, devfn, where, size, val); @@ -542,10 +541,10 @@ int sw64_pcie_config_read(struct pci_bus *bus, unsigned int devfn, } return ret; } -EXPORT_SYMBOL(sw64_pcie_config_read); +EXPORT_SYMBOL(sunway_pci_config_read); /** - * sw64_pcie_config_write - write val to config space of PCI + * sunway_pci_config_write - write val to config space of PCI * host controller or device * * @bus : PCI bus structure @@ -556,7 +555,7 @@ EXPORT_SYMBOL(sw64_pcie_config_read); * * @return: Whether write operation success */ -int sw64_pcie_config_write(struct pci_bus *bus, unsigned int devfn, +int sunway_pci_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); @@ -567,14 +566,14 @@ int sw64_pcie_config_write(struct pci_bus *bus, unsigned int devfn, hose->self_busno = hose->busn_space->start; if (unlikely(bus->number == hose->self_busno)) - return sw64_pcie_write_rc_cfg(bus, devfn, where, size, val); + return pci_write_rc_cfg(bus, devfn, where, size, val); else return pci_generic_config_write(bus, devfn, where, size, val); } -EXPORT_SYMBOL(sw64_pcie_config_write); +EXPORT_SYMBOL(sunway_pci_config_write); /** - * sw64_pcie_map_bus - get configuration base address + * sunway_pci_map_bus - get configuration base address * @bus : PCI bus structure * @devfn: device/function * @where: offset from base @@ -582,14 +581,14 @@ EXPORT_SYMBOL(sw64_pcie_config_write); * @return: base address of the configuration space needed to be * accessed. */ -void __iomem *sw64_pcie_map_bus(struct pci_bus *bus, +void __iomem *sunway_pci_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 (!sw64_pcie_valid_device(bus, devfn)) + if (!pci_valid_device(bus, devfn)) return NULL; /** @@ -611,12 +610,7 @@ 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) -{ - return map_irq(dev, slot, pin); -} +EXPORT_SYMBOL(sunway_pci_map_bus); enum pci_props { PROP_RC_CONFIG_BASE = 0, @@ -679,7 +673,7 @@ static void pci_controller_set_node(struct pci_controller *hose, } #endif -static int sw64_pci_prepare_controller(struct pci_controller *hose, +static int pci_prepare_controller(struct pci_controller *hose, struct fwnode_handle *fwnode) { u64 props[PROP_NUM]; @@ -756,7 +750,7 @@ static int sw64_pci_prepare_controller(struct pci_controller *hose, } #ifdef CONFIG_ACPI -static int sw64_pci_acpi_present(struct device *dev) +static int pci_acpi_present(struct device *dev) { struct acpi_device *adev = to_acpi_device(dev); int ret; @@ -789,7 +783,7 @@ static int sw64_pci_acpi_present(struct device *dev) /** * Use the information from ACPI or DTB to init pci_controller */ -static int sw64_pci_ecam_init(struct pci_config_window *cfg) +static int sunway_pci_ecam_init(struct pci_config_window *cfg) { struct pci_controller *hose = NULL; struct device *dev = cfg->parent; @@ -798,7 +792,7 @@ static int sw64_pci_ecam_init(struct pci_config_window *cfg) #ifdef CONFIG_ACPI if (!acpi_disabled) { - ret = sw64_pci_acpi_present(dev); + ret = pci_acpi_present(dev); if (ret) return ret; @@ -811,7 +805,7 @@ static int sw64_pci_ecam_init(struct pci_config_window *cfg) return -ENOMEM; /* Init pci_controller */ - ret = sw64_pci_prepare_controller(hose, fwnode); + ret = pci_prepare_controller(hose, fwnode); if (ret) { kfree(hose); dev_err(dev, "failed to init pci controller\n"); @@ -823,13 +817,13 @@ static int sw64_pci_ecam_init(struct pci_config_window *cfg) return 0; } -const struct pci_ecam_ops sw64_pci_ecam_ops = { +const struct pci_ecam_ops sunway_pci_ecam_ops = { .bus_shift = 24, - .init = sw64_pci_ecam_init, + .init = sunway_pci_ecam_init, .pci_ops = { - .map_bus = sw64_pcie_map_bus, - .read = sw64_pcie_config_read, - .write = sw64_pcie_config_write, + .map_bus = sunway_pci_map_bus, + .read = sunway_pci_config_read, + .write = sunway_pci_config_write, } }; @@ -838,7 +832,7 @@ const struct pci_ecam_ops sw64_pci_ecam_ops = { static const struct of_device_id sunway_pcie_of_match[] = { { .compatible = "sunway,pcie", - .data = &sw64_pci_ecam_ops, + .data = &sunway_pci_ecam_ops, }, {}, }; @@ -925,7 +919,7 @@ static int sunway_pcie_probe(struct platform_device *pdev) * Some quirks for Sunway PCIe controller after scanning, * that's why we don't directly call function pci_host_probe(). */ - sw64_pci_root_bridge_scan_finish_up(bridge); + sunway_pci_root_bridge_scan_finish(bridge); pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h index 863e572202e2..ac473d00e9a1 100644 --- a/include/linux/pci-ecam.h +++ b/include/linux/pci-ecam.h @@ -88,7 +88,7 @@ extern const struct pci_ecam_ops xgene_v2_pcie_ecam_ops; /* APM X-Gene PCIe v2.x extern const struct pci_ecam_ops al_pcie_ops; /* Amazon Annapurna Labs PCIe */ extern const struct pci_ecam_ops tegra194_pcie_ops; /* Tegra194 PCIe */ extern const struct pci_ecam_ops loongson_pci_ecam_ops; /* Loongson PCIe */ -extern const struct pci_ecam_ops sw64_pci_ecam_ops; /* SW64 PCIe */ +extern const struct pci_ecam_ops sunway_pci_ecam_ops; /* Sunway PCIe */ #endif #if IS_ENABLED(CONFIG_PCI_HOST_COMMON) -- Gitee From 89cf26ffc5f924fd4d2e72029c3eb4710d5de4d5 Mon Sep 17 00:00:00 2001 From: Gao Chen Date: Wed, 14 Aug 2024 09:55:00 +0800 Subject: [PATCH 085/100] anolis: sw64: fix a bug in huge_pte_offset() ANBZ: #4688 In the function huge_pte_offset(), when the value of pmd is detected as "unpresent", it returns an unexpected "NULL" instead of the address of the pmd. This patch ensures that huge_pte_offset() returns the expected value. Signed-off-by: Gao Chen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/mm/hugetlbpage.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/sw_64/mm/hugetlbpage.c b/arch/sw_64/mm/hugetlbpage.c index fae1fa8bf7df..f986422398ef 100644 --- a/arch/sw_64/mm/hugetlbpage.c +++ b/arch/sw_64/mm/hugetlbpage.c @@ -94,11 +94,12 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr, pud = pud_offset(p4d, addr); if (pud_present(*pud)) { pmd = pmd_offset(pud, addr); - if (!pmd_present(*pmd)) - return NULL; - if (pmd_val(*pmd) & _PAGE_CONT) - pte = pte_offset_map(pmd, addr); - else + if (sz == CONT_PMD_SIZE) { + if (!pmd_none(*pmd)) + pte = pte_offset_map(pmd, addr); + else + return NULL; + } else if (sz == PMD_SIZE) pte = (pte_t *) pmd; } } -- Gitee From 4ae6f16738e57ec9d35d5ecc1e3f35221c1c4c81 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Fri, 2 Aug 2024 10:29:43 +0800 Subject: [PATCH 086/100] anolis: sw64: clk: fix the clock frequency of SPI and I2C ANBZ: #4688 Fix the clock frequency of SPI and I2C to make these peripherals work properly. This commit also fixes some format issues and typos for junzhang's default dts file. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/boot/dts/junzhang.dts | 25 ++++++++++++------------- drivers/acpi/acpi_apd.c | 31 ++++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/arch/sw_64/boot/dts/junzhang.dts b/arch/sw_64/boot/dts/junzhang.dts index 8712678a66e8..7ec626f00faa 100644 --- a/arch/sw_64/boot/dts/junzhang.dts +++ b/arch/sw_64/boot/dts/junzhang.dts @@ -21,18 +21,17 @@ soc { clocks { i2cclk: i2cclk { - compatible = "fixed-clock"; - clock-frequency = <12500000>; - #clock-cells = <0>; - clock-output-names = "i2cclk_12.5mhz"; + compatible = "fixed-clock"; + clock-frequency = <12000000>; + #clock-cells = <0>; + clock-output-names = "i2cclk_12mhz"; }; spiclk: spiclk { - compatible = "fixed-clock"; - clock-frequency = <12500000>; - #clock-cells = <0>; - clock-output-names = "spiclk_12.5mhz"; + compatible = "fixed-clock"; + clock-frequency = <12000000>; + #clock-cells = <0>; + clock-output-names = "spiclk_12mhz"; }; - }; pintc: interrupt-controller { @@ -135,7 +134,7 @@ pvt: pvt@0x8030 { compatible = "sw64,pvt-vol"; reg = <0x8030 0x0 0x0 0x7c00>; status = "okay"; - }; + }; spi: spi@0x8032 { #address-cells = <1>; @@ -235,7 +234,7 @@ gpio: gpio@8036 { reg = <0x8036 0x0 0x0 0x8000>; status = "okay"; - porta: gpio-contraller@0 { + porta: gpio-controller@0 { compatible = "snps,dw-apb-gpio-port"; gpio-controller; #gpio-cells = <2>; @@ -244,7 +243,7 @@ porta: gpio-contraller@0 { interrupt-controller; #interrupt-cells = <2>; interrupts-extended = <&pintc 0>, <&pintc 1>; - }; - }; + }; + }; }; }; diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c index c5afed1eeb9c..e62f024f8d39 100644 --- a/drivers/acpi/acpi_apd.c +++ b/drivers/acpi/acpi_apd.c @@ -180,16 +180,33 @@ static const struct apd_device_desc hip08_spi_desc = { #endif /* CONFIG_ARM64 */ #ifdef CONFIG_SW64 -static const struct apd_device_desc sunway_i2c_desc = { - .setup = acpi_apd_setup, - .fixed_clk_rate = 25000000, +#include + +extern u64 sunway_mclk_hz; +static int sw64_acpi_apd_setup(struct apd_private_data *pdata); + +static struct apd_device_desc sunway_i2c_desc = { + .setup = sw64_acpi_apd_setup, + .fixed_clk_rate = 50000000, }; -static const struct apd_device_desc sunway_spi_desc = { - .setup = acpi_apd_setup, - .fixed_clk_rate = 25000000, +static struct apd_device_desc sunway_spi_desc = { + .setup = sw64_acpi_apd_setup, + .fixed_clk_rate = 50000000, }; -#endif + +static int sw64_acpi_apd_setup(struct apd_private_data *pdata) +{ + struct apd_device_desc *dev_desc = (struct apd_device_desc *)pdata->dev_desc; + + if (sunway_machine_is_compatible("sunway,junzhang")) + dev_desc->fixed_clk_rate = 12000000; + else + dev_desc->fixed_clk_rate = sunway_mclk_hz; + + return acpi_apd_setup(pdata); +} +#endif /* CONFIG_SW64 */ #endif -- Gitee From 77c81abce77bcf0a6563163e9bedbc633363625c Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Fri, 23 Aug 2024 07:52:27 +0000 Subject: [PATCH 087/100] anolis: sw64: iommu: improve iommu initialization ANBZ: #4688 After restructuring of pci controller initialization, IOMMU should get its reg_base_addr from pci_controller instead of making it up again to match the semantic. Add the following two methods to help improve these conditions: - Setup iommu->reg_base by fetching pci_controller->piu_ior0_base. - Check whether the IOMMU node has been initialized to make sure there are no unexpected behaviours happening if PCI accidentally init the same IOMMU twice. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/iommu/sw64/iommu.c | 5 ++++- drivers/iommu/sw64/iommu_v2.c | 8 ++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/sw64/iommu.c b/drivers/iommu/sw64/iommu.c index 94b01ca35ecd..f705d10830ff 100644 --- a/drivers/iommu/sw64/iommu.c +++ b/drivers/iommu/sw64/iommu.c @@ -760,7 +760,7 @@ static struct sunway_iommu *sunway_iommu_early_init(struct pci_controller *hose) iommu->iommu_dtbr = page_address(page); base = __pa(iommu->iommu_dtbr) & PAGE_MASK; - iommu->reg_base_addr = __va(MK_PIU_IOR0(iommu->node, iommu->index)); + iommu->reg_base_addr = hose->piu_ior0_base; writeq(base, iommu->reg_base_addr + DTBASEADDR); hose->pci_iommu = iommu; @@ -796,6 +796,9 @@ static int sunway_iommu_init(void) continue; } + if (hose->iommu_enable) + continue; + iommu = sunway_iommu_early_init(hose); if (!iommu) { pr_err("Allocating sunway_iommu failed\n"); diff --git a/drivers/iommu/sw64/iommu_v2.c b/drivers/iommu/sw64/iommu_v2.c index b2b68c9836a2..d9e3b75e6c9e 100644 --- a/drivers/iommu/sw64/iommu_v2.c +++ b/drivers/iommu/sw64/iommu_v2.c @@ -590,7 +590,7 @@ static struct sunway_iommu *sunway_iommu_early_init(struct pci_controller *hose) iommu->iommu_dtbr = page_address(page); base = __pa(iommu->iommu_dtbr) & PAGE_MASK; - iommu->reg_base_addr = __va(MK_PIU_IOR0(iommu->node, iommu->index)); + iommu->reg_base_addr = hose->piu_ior0_base; writeq(base, iommu->reg_base_addr + DTBASEADDR); hose->pci_iommu = iommu; @@ -971,8 +971,9 @@ static int sunway_iommu_acpi_init(void) return ret; for_each_iommu(iommu) { - if (!iommu->enabled) + if (!iommu->enabled || hose->iommu_enable) continue; + iommu_device_sysfs_add(&iommu->iommu, NULL, NULL, "%d", iommu_index); iommu_device_register(&iommu->iommu, &sunway_iommu_ops, NULL); @@ -1008,6 +1009,9 @@ static int sunway_iommu_legacy_init(void) continue; } + if (hose->iommu_enable) + continue; + iommu = sunway_iommu_early_init(hose); iommu_device_sysfs_add(&iommu->iommu, NULL, NULL, "%d", iommu_index); -- Gitee From 00004c03968fa50dae5dab8563240ba0e199df7e Mon Sep 17 00:00:00 2001 From: Jing Li Date: Tue, 20 Aug 2024 12:13:43 +0800 Subject: [PATCH 088/100] anolis: sw64: mm: remove legacy memory detection for JunZhang platform ANBZ: #4688 We prefer to get memory information from firmware instead of detecting memory in kernel to improve kernel compatibility. Due to the latest firmware being able to provide comprehensive memory information, it's time to remove legacy memory detection for JunZhang platform. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/mm/init.c | 18 +++++++++--------- arch/sw_64/mm/numa.c | 9 +++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/arch/sw_64/mm/init.c b/arch/sw_64/mm/init.c index 0ac65a2fd61c..6e976d7b20e4 100644 --- a/arch/sw_64/mm/init.c +++ b/arch/sw_64/mm/init.c @@ -328,16 +328,16 @@ core_initcall_sync(sw64_kvm_pool_init); void __init sw64_memblock_init(void) { - /** - * Detect all memory on all nodes, used in the following - * cases: - * 1. Legacy memory detect - * 2. Legacy NUMA initialization - */ - setup_socket_info(); - show_socket_mem_layout(); - if (sunway_boot_magic != 0xDEED2024UL) { + /** + * Detect all memory on all nodes, used in the following + * cases: + * 1. Legacy memory detect + * 2. Legacy NUMA initialization + */ + setup_socket_info(); + show_socket_mem_layout(); + /* Find our usable memory */ mem_detect(); diff --git a/arch/sw_64/mm/numa.c b/arch/sw_64/mm/numa.c index e46372f3ac77..2793718c66f6 100644 --- a/arch/sw_64/mm/numa.c +++ b/arch/sw_64/mm/numa.c @@ -9,6 +9,7 @@ #include #include +#include int cpu_to_node_map[NR_CPUS]; cpumask_var_t node_to_cpumask_map[MAX_NUMNODES]; @@ -294,6 +295,14 @@ static int __init manual_numa_init(void) struct memblock_region *mblk; phys_addr_t node_base, node_size, node_end; + /** + * When boot magic is 0xDEED2024UL, legacy memory detection is + * completely bypassed, causing manual_numa_init failure. So we + * disable numa here. + */ + if (sunway_boot_magic == 0xDEED2024UL) + numa_off = 1; + if (numa_off) { pr_info("NUMA disabled\n"); /* Forced off on command line. */ pr_info("Faking one node at [mem %#018llx-%#018llx]\n", -- Gitee From da77c03783f8c26a5f53aa4054c2c29a1c0bb3a2 Mon Sep 17 00:00:00 2001 From: Gao Chen Date: Fri, 25 Apr 2025 19:06:46 +0800 Subject: [PATCH 089/100] anolis: sw64: fix compiler error when enabling CONFIG_SW64_CPUAUTOPLUG ANBZ: #4688 This patch adapts get_idle_time_jiffy() to sw64_get_idle_time_jiffy(), fixing the complier error that occurs when CONFIG_SW64_CPUAUTOPLUG is enabled. Signed-off-by: Gao Chen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/cpuautoplug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/kernel/cpuautoplug.c b/arch/sw_64/kernel/cpuautoplug.c index b4ea0ef080d8..28608880f67e 100644 --- a/arch/sw_64/kernel/cpuautoplug.c +++ b/arch/sw_64/kernel/cpuautoplug.c @@ -213,7 +213,7 @@ static cputime64_t calc_busy_time(unsigned int cpu) return busy_time; } -static inline cputime64_t get_idle_time_jiffy(cputime64_t *wall) +static inline cputime64_t sw64_get_idle_time_jiffy(cputime64_t *wall) { unsigned int cpu; cputime64_t idle_time = 0; @@ -242,7 +242,7 @@ static inline cputime64_t sw64_get_idle_time(cputime64_t *wall) for_each_online_cpu(cpu) { idle_time += get_cpu_idle_time_us(cpu, wall); if (idle_time == -1ULL) - return get_idle_time_jiffy(wall); + return sw64_get_idle_time_jiffy(wall); } return idle_time; -- Gitee From 6222e3d510033e4a27cb657fbf9dddd3d57d5f91 Mon Sep 17 00:00:00 2001 From: Gao Chen Date: Fri, 25 Apr 2025 19:17:10 +0800 Subject: [PATCH 090/100] anolis: sw64: fix compiler error when enabling CONFIG_DEBUG_MATCH ANBZ: #4688 This patch fixes the compilation error that occurred when selecting CONFIG_DEBUG_MATCH due to changes in the upstream. Signed-off-by: Gao Chen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/match.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/arch/sw_64/kernel/match.c b/arch/sw_64/kernel/match.c index 9ecd5d838846..2d7eec649e31 100644 --- a/arch/sw_64/kernel/match.c +++ b/arch/sw_64/kernel/match.c @@ -211,8 +211,7 @@ static ssize_t da_match_set(struct file *file, const char __user *user_buf, if (err) return err; - if (on_each_cpu(write_da_match, NULL, 1)) - pr_crit("%s: timed out\n", __func__); + on_each_cpu(write_da_match, NULL, 1); return len; } @@ -258,8 +257,7 @@ static ssize_t dv_match_set(struct file *file, const char __user *user_buf, if (err) return err; - if (on_each_cpu(write_dv_match, NULL, 1)) - pr_crit("%s: timed out\n", __func__); + on_each_cpu(write_dv_match, NULL, 1); return len; } @@ -313,9 +311,7 @@ static ssize_t dav_match_set(struct file *file, const char __user *user_buf, if (err) return err; - - if (on_each_cpu(write_dav_match, NULL, 1)) - pr_crit("%s: timed out\n", __func__); + on_each_cpu(write_dav_match, NULL, 1); return len; } @@ -364,8 +360,7 @@ static ssize_t ia_match_set(struct file *file, const char __user *user_buf, if (err) return err; - if (on_each_cpu(write_ia_match, NULL, 1)) - pr_crit("%s: timed out\n", __func__); + on_each_cpu(write_ia_match, NULL, 1); return len; } @@ -406,8 +401,7 @@ static ssize_t iv_match_set(struct file *file, const char __user *user_buf, if (err) return err; - if (on_each_cpu(write_iv_match, NULL, 1)) - pr_crit("%s: timed out\n", __func__); + on_each_cpu(write_iv_match, NULL, 1); return len; } @@ -448,8 +442,7 @@ static ssize_t ida_match_set(struct file *file, const char __user *user_buf, if (err) return err; - if (on_each_cpu(write_ida_match, NULL, 1)) - pr_crit("%s: timed out\n", __func__); + on_each_cpu(write_ida_match, NULL, 1); return len; } -- Gitee From 0163fbb657f69a32ed88eca395715b819c58aac2 Mon Sep 17 00:00:00 2001 From: Gao Chen Date: Fri, 25 Apr 2025 21:45:58 +0800 Subject: [PATCH 091/100] anolis: sw64: fix compiler error when enabling CONFIG_RELOCATABLE ANBZ: #4688 Due to the changes of upstream, we need to reference the header file linux/panic_notifier.h to fix the compiler error. Signed-off-by: Gao Chen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 2 +- arch/sw_64/kernel/relocate.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 6c2f0da276cc..30e63a5616fa 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -480,7 +480,7 @@ config RELOCATION_TABLE_SIZE hex "Relocation table size" depends on RELOCATABLE range 0x0 0x01000000 - default "0x80000" + default "0x100000" help A table of relocation data will be appended to the kernel binary and parsed at boot to fix up the relocated kernel. diff --git a/arch/sw_64/kernel/relocate.c b/arch/sw_64/kernel/relocate.c index ebdf7d894805..dfd323d76597 100644 --- a/arch/sw_64/kernel/relocate.c +++ b/arch/sw_64/kernel/relocate.c @@ -9,6 +9,7 @@ */ #include #include +#include #include #include -- Gitee From ebc21495fccb54b1a14d4bd85924d79e14319ff1 Mon Sep 17 00:00:00 2001 From: Gao Chen Date: Fri, 25 Apr 2025 21:52:27 +0800 Subject: [PATCH 092/100] anolis: sw64: fix compiler error of perf tests ANBZ: #4688 Solve the problem of compiler errors in perf tests caused by changes in the upstream. Signed-off-by: Gao Chen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- tools/perf/arch/sw_64/include/arch-tests.h | 2 +- tools/perf/arch/sw_64/tests/arch-tests.c | 11 +++-------- tools/perf/arch/sw_64/tests/regs_load.S | 6 +++--- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/tools/perf/arch/sw_64/include/arch-tests.h b/tools/perf/arch/sw_64/include/arch-tests.h index 90ec4c8cb880..35bb987d797b 100644 --- a/tools/perf/arch/sw_64/include/arch-tests.h +++ b/tools/perf/arch/sw_64/include/arch-tests.h @@ -7,6 +7,6 @@ struct thread; struct perf_sample; #endif -extern struct test arch_tests[]; +extern struct test_suite *arch_tests[]; #endif diff --git a/tools/perf/arch/sw_64/tests/arch-tests.c b/tools/perf/arch/sw_64/tests/arch-tests.c index 5b1543c98022..ad16b4f8f63e 100644 --- a/tools/perf/arch/sw_64/tests/arch-tests.c +++ b/tools/perf/arch/sw_64/tests/arch-tests.c @@ -3,14 +3,9 @@ #include "tests/tests.h" #include "arch-tests.h" -struct test arch_tests[] = { +struct test_suite *arch_tests[] = { #ifdef HAVE_DWARF_UNWIND_SUPPORT - { - .desc = "DWARF unwind", - .func = test__dwarf_unwind, - }, + &suite__dwarf_unwind, #endif - { - .func = NULL, - }, + NULL, }; diff --git a/tools/perf/arch/sw_64/tests/regs_load.S b/tools/perf/arch/sw_64/tests/regs_load.S index 8c5aabc2c6fb..35f7fb65012e 100644 --- a/tools/perf/arch/sw_64/tests/regs_load.S +++ b/tools/perf/arch/sw_64/tests/regs_load.S @@ -3,12 +3,12 @@ .text .set noat -.type perf_regs_load,%function +.globl perf_regs_load #define STL_REG(r) stl $r, (8 * r)($16) #define LDL_REG(r) ldl $r, (8 * r)($16) #define SP (8 * 30) #define PC (8 * 31) -SYM_FUNC_START(perf_regs_load) +perf_regs_load: STL_REG(0) STL_REG(1) STL_REG(2) @@ -44,4 +44,4 @@ SYM_FUNC_START(perf_regs_load) stl $26, (PC)($16) LDL_REG(17) ret -SYM_FUNC_END(perf_regs_load) +.end perf_regs_load -- Gitee From de0ea1ff7acaa85ef6471373f4f187d8f15ceb7a Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Fri, 23 Aug 2024 03:24:42 +0000 Subject: [PATCH 093/100] anolis: sw64: fix LPC legacy IO space on chip junzhang and junzhang_v2 ANBZ: #4688 According to commit a15ee190f55d ("anolis: sw64: lpc: work around hardware flaws"), PCI Legacy IO address can not be accessed normally, so we borrow memory IO address to access legacy IO on chip junchang/junzhang_v2. The above commit can handle most access cases, as LPC driver can be successfully directed to the new address space by retrieving lpc->hst_regs from ACPI or DTS. However, if an uninformed user use inb/outb directly from userspace to initiate an access, it will be transformed into accessing an illegal address space as current inb/outb still use the original legacy IO space address. To optimize the iomap performance, initiate the corresponding enhancements globally during arch setup by adding a check on chip types to differentiate LPC legacy IO space. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/setup.c | 30 ++++++++++++++++++++++++++++++ arch/sw_64/lib/iomap.c | 13 ++++++------- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index f55ddc856df9..8e255480470a 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -118,6 +118,9 @@ EXPORT_SYMBOL(sunway_boot_magic); unsigned long sunway_dtb_address; EXPORT_SYMBOL(sunway_dtb_address); +unsigned long legacy_io_base; +unsigned long legacy_io_shift; + u64 sunway_mclk_hz; u64 sunway_extclk_hz; @@ -552,6 +555,30 @@ static void __init setup_firmware_fdt(void) } } +static void __init setup_legacy_io(void) +{ + if (is_guest_or_emul()) { + legacy_io_base = PCI_VT_LEGACY_IO; + legacy_io_shift = 0; + return; + } + + if (sunway_machine_is_compatible("sunway,junzhang") || + sunway_machine_is_compatible("sunway,junzhang_v2")) { + /* + * Due to a hardware defect, chip junzhang and junzhang_v2 cannot + * recognize accesses to LPC legacy IO. The workaround is using some + * of the LPC MEMIO space to access Legacy IO space. Thus, + * legacy_io_base should be LPC_MEM_IO instead on these chips. + */ + legacy_io_base = LPC_MEM_IO; + legacy_io_shift = 12; + } else { + legacy_io_base = LPC_LEGACY_IO; + legacy_io_shift = 0; + } +} + static void __init setup_builtin_fdt(void) { void *dt_virt; @@ -712,6 +739,9 @@ setup_arch(char **cmdline_p) /* Now we get the final boot_command_line */ *cmdline_p = boot_command_line; + /* Decide legacy IO base addr based on chips */ + setup_legacy_io(); + /* Register a call for panic conditions. */ atomic_notifier_chain_register(&panic_notifier_list, &sw64_panic_block); diff --git a/arch/sw_64/lib/iomap.c b/arch/sw_64/lib/iomap.c index f89cf16f683c..c73004a87dcd 100644 --- a/arch/sw_64/lib/iomap.c +++ b/arch/sw_64/lib/iomap.c @@ -8,6 +8,9 @@ #include #include +extern unsigned long legacy_io_base; +extern unsigned long legacy_io_shift; + /* * Here comes the sw64 implementation of the IOMAP interfaces. */ @@ -258,13 +261,9 @@ EXPORT_SYMBOL(_memset_c_io); void __iomem *ioport_map(unsigned long port, unsigned int size) { - unsigned long io_offset; - - if (port < 0x100000) { - io_offset = is_in_host() ? LPC_LEGACY_IO : PCI_VT_LEGACY_IO; - port = port | io_offset; - } + if (port >= 0x100000) + return __va(port); - return __va(port); + return __va((port << legacy_io_shift) | legacy_io_base); } EXPORT_SYMBOL(ioport_map); -- Gitee From 7f376ea2806c58bb4e3c3e52e845de938f0d4f86 Mon Sep 17 00:00:00 2001 From: Zhou Xuemei Date: Tue, 3 Sep 2024 06:13:20 +0000 Subject: [PATCH 094/100] anolis: sw64: pci: remove legacy io reservation ANBZ: #4688 This patch removes the legacy io reservation code, which is no longer necessary in sw64 architecture. Additionally, the 'PCIBIOS_MIN_IO' value is adjusted to raise the base address for legacy io resource assignment. Signed-off-by: Zhou Xuemei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/pci.h | 2 +- arch/sw_64/pci/pci-legacy.c | 36 ------------------------------------ arch/sw_64/pci/pci.c | 33 --------------------------------- 3 files changed, 1 insertion(+), 70 deletions(-) diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index f28a3acb015c..9662fdd87cb1 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -147,7 +147,7 @@ struct pci_controller { #define pcibios_assign_all_busses() (pci_has_flag(PCI_REASSIGN_ALL_BUS)) -#define PCIBIOS_MIN_IO 0 +#define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_MEM 0 extern void __init sw64_init_pci(void); diff --git a/arch/sw_64/pci/pci-legacy.c b/arch/sw_64/pci/pci-legacy.c index ccf87520c72d..8a9ac6f1146b 100644 --- a/arch/sw_64/pci/pci-legacy.c +++ b/arch/sw_64/pci/pci-legacy.c @@ -19,7 +19,6 @@ bool sunway_legacy_pci; */ struct pci_controller *hose_head, **hose_tail = &hose_head; -static void __init pcibios_reserve_legacy_regions(struct pci_bus *bus); static int __init pcibios_init(void) @@ -138,13 +137,7 @@ void __init common_init_pci(void) pcibios_claim_console_setup(); - if (is_in_host()) { - list_for_each_entry(bus, &pci_root_buses, node) - pcibios_reserve_legacy_regions(bus); - } - pr_info("SW arch assign unassigned resources.\n"); - pci_assign_unassigned_resources(); for (hose = hose_head; hose; hose = hose->next) { @@ -177,35 +170,6 @@ alloc_resource(void) return res; } -static void __init pcibios_reserve_legacy_regions(struct pci_bus *bus) -{ - struct pci_controller *hose = pci_bus_to_pci_controller(bus); - resource_size_t offset; - struct resource *res; - - pr_debug("Reserving legacy ranges for domain %04x\n", pci_domain_nr(bus)); - - /* Check for IO */ - if (!(hose->io_space->flags & IORESOURCE_IO)) - goto no_io; - offset = (unsigned long)hose->io_space->start; - res = kzalloc(sizeof(struct resource), GFP_KERNEL); - BUG_ON(res == NULL); - res->name = "Legacy IO"; - res->flags = IORESOURCE_IO; - res->start = offset; - res->end = (offset + 0xfff) & 0xfffffffffffffffful; - pr_debug("Candidate legacy IO: %pR\n", res); - if (request_resource(hose->io_space, res)) { - pr_debug("PCI %04x:%02x Cannot reserve Legacy IO %pR\n", - pci_domain_nr(bus), bus->number, res); - kfree(res); - } - -no_io: - return; -} - static bool rc_linkup[MAX_NUMNODES][MAX_NR_RCS_PER_NODE]; static void __init diff --git a/arch/sw_64/pci/pci.c b/arch/sw_64/pci/pci.c index a01eac0a890e..841ec3ea9f75 100644 --- a/arch/sw_64/pci/pci.c +++ b/arch/sw_64/pci/pci.c @@ -342,36 +342,6 @@ static void sunway_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) -{ - struct pci_bus *bus = bridge->bus; - struct resource_entry *entry = NULL; - struct resource *res = NULL; - - resource_list_for_each_entry(entry, &bridge->windows) { - if (!(entry->res->flags & IORESOURCE_IO)) - continue; - - res = kzalloc(sizeof(struct resource), GFP_KERNEL); - if (WARN_ON(!res)) - return; - - res->name = "legacy io"; - res->flags = IORESOURCE_IO; - res->start = entry->res->start; - res->end = (res->start + 0xFFF) & 0xFFFFFFFFFFFFFFFFUL; - - pr_info("reserving legacy io %pR for domain %04x\n", - res, pci_domain_nr(bus)); - if (request_resource(entry->res, res)) { - pr_err("pci %04x:%02x reserve legacy io %pR failed\n", - pci_domain_nr(bus), bus->number, res); - kfree(res); - } - } -} - void sunway_pci_root_bridge_scan_finish(struct pci_host_bridge *bridge) { struct pci_controller *hose = NULL; @@ -401,9 +371,6 @@ void sunway_pci_root_bridge_scan_finish(struct pci_host_bridge *bridge) pci_bus_update_busn_res_end(bus, last_bus); last_bus++; - if (is_in_host()) - sw64_pci_root_bridge_reserve_legacy_io(bridge); - /** * Root Complex of SW64 does not support ASPM, causing * control field(_OSC) unable to be updated. -- Gitee From 1608f07b4e5a4cd75ed97e606296aabcd717386c Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 29 Aug 2024 13:47:58 +0800 Subject: [PATCH 095/100] anolis: sw64: smp: fix function fdt_setup_smp() ANBZ: #4688 This commit includes some small fixes: - Provide compatibility for CPU device node with vendor prefix "sunway". - Remove unnecessary logs. - When NR_CPUS less than the number detected by firmware, break the loop instead of the function return. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/smp.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index dba2feae32e2..a9577cd91515 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -269,12 +269,14 @@ static int __init sw64_of_core_version(const struct device_node *dn, if (!dn || !version) return -EINVAL; - if (of_device_is_compatible(dn, "sw64,xuelang")) { + if (of_device_is_compatible(dn, "sw64,xuelang") || + of_device_is_compatible(dn, "sunway,xuelang")) { *version = CORE_VERSION_C3B; return 0; } - if (of_device_is_compatible(dn, "sw64,junzhang")) { + if (of_device_is_compatible(dn, "sw64,junzhang") || + of_device_is_compatible(dn, "sunway,junzhang")) { *version = CORE_VERSION_C4; return 0; } @@ -304,10 +306,8 @@ static int __init fdt_setup_smp(void) available = of_device_is_available(dn); - if (!available && !online_capable) { - pr_info("OF: Core is not available\n"); + if (!available && !online_capable) continue; - } ret = of_property_read_u32(dn, "reg", &rcid); if (ret) { @@ -318,7 +318,7 @@ static int __init fdt_setup_smp(void) if (logical_core_id >= nr_cpu_ids) { pr_warn_once("OF: Core [0x%x] exceeds max core num [%u]\n", rcid, nr_cpu_ids); - return 0; + break; } if (is_rcid_duplicate(rcid)) { @@ -334,6 +334,9 @@ static int __init fdt_setup_smp(void) ret = of_property_read_u64(dn, "sw64,boot_flag_address", &boot_flag_address); + if (ret) + ret = of_property_read_u64(dn, "sunway,boot_flag_address", + &boot_flag_address); if (ret) { pr_err("OF: No boot_flag_address found\n"); return ret; -- Gitee From 582afc685344ddaa2bf48dfd3893d5d2c1a2220c Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 29 Aug 2024 14:37:45 +0800 Subject: [PATCH 096/100] anolis: sw64: clk: further fix the clock frequency of SPI and I2C ANBZ: #4688 The clock frequency of SPI and I2C is equal to Sunway MCLK. Fixes: 889b6b1dba80 ("anolis: sw64: clk: fix the clock frequency of SPI and I2C") Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/acpi/acpi_apd.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c index e62f024f8d39..6b1b31eabfdd 100644 --- a/drivers/acpi/acpi_apd.c +++ b/drivers/acpi/acpi_apd.c @@ -199,10 +199,7 @@ static int sw64_acpi_apd_setup(struct apd_private_data *pdata) { struct apd_device_desc *dev_desc = (struct apd_device_desc *)pdata->dev_desc; - if (sunway_machine_is_compatible("sunway,junzhang")) - dev_desc->fixed_clk_rate = 12000000; - else - dev_desc->fixed_clk_rate = sunway_mclk_hz; + dev_desc->fixed_clk_rate = sunway_mclk_hz; return acpi_apd_setup(pdata); } -- Gitee From 72b124aa5ea85fc53e3ef198138ca9c62fca780e Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 29 Aug 2024 14:53:13 +0800 Subject: [PATCH 097/100] anolis: sw64: acpi: suppress log of function acpi_numa_x2apic_affinity_init() ANBZ: #4688 Suppress unnecessary logs to make the kernel startup log clean. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/kernel/acpi.c b/arch/sw_64/kernel/acpi.c index 02a4e8fa9c95..515728920cfd 100644 --- a/arch/sw_64/kernel/acpi.c +++ b/arch/sw_64/kernel/acpi.c @@ -148,7 +148,7 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) /* Record the mapping from logical core id to node id */ cpu = rcid_to_cpu(rcid); if (cpu < 0) { - pr_err("SRAT: Can not find the logical id for physical Core 0x%04x\n", + pr_warn_once("SRAT: Can not find the logical id for physical Core 0x%04x\n", rcid); return; } -- Gitee From 9a7b5b3dbdc9e4761fa113c10ff1cf584524d0cf Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 29 Aug 2024 15:01:11 +0800 Subject: [PATCH 098/100] anolis: sw64: fix null pointer issue when CONFIG_BUILTIN_DTB=y ANBZ: #4688 If CONFIG_BUILTIN_DTB=y, then initial_boot_params is initialized after function setup_builtin_fdt(), causing null pointer issue in function setup_legacy_io(). So we need to move setup_legacy_io() after setup_builtin_fdt(). Fixes: 158c423d4329 ("anolis: sw64: fix LPC legacy IO space on chip junzhang and junzhang_v2") Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/setup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 8e255480470a..b735fe0e3e59 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -739,9 +739,6 @@ setup_arch(char **cmdline_p) /* Now we get the final boot_command_line */ *cmdline_p = boot_command_line; - /* Decide legacy IO base addr based on chips */ - setup_legacy_io(); - /* Register a call for panic conditions. */ atomic_notifier_chain_register(&panic_notifier_list, &sw64_panic_block); @@ -764,6 +761,9 @@ setup_arch(char **cmdline_p) if (IS_ENABLED(CONFIG_BUILTIN_DTB)) setup_builtin_fdt(); + /* Decide legacy IO base addr based on chips */ + setup_legacy_io(); + sw64_memblock_init(); /* Try to upgrade ACPI tables via initrd */ -- Gitee From f6d1322d283aa00185ecebbbdc5bea5f914ee5f1 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 29 Aug 2024 15:27:28 +0800 Subject: [PATCH 099/100] anolis: sw64: irqchip: add version 3 for PINTC ANBZ: #4688 For forward compatibility. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/irqchip/irq-sunway-pintc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/irqchip/irq-sunway-pintc.c b/drivers/irqchip/irq-sunway-pintc.c index e2f1c39538d6..eb7128b79c6f 100644 --- a/drivers/irqchip/irq-sunway-pintc.c +++ b/drivers/irqchip/irq-sunway-pintc.c @@ -188,6 +188,7 @@ static unsigned long make_pintc_int_target(u32 version, int rcid) target = core | (thread << 5) | (node << 6); break; case 0x2: /* PINTC v2 */ + case 0x3: /* PINTC v3 */ target = core | (thread << 6) | (node << 7); break; default: -- Gitee From 21dd1478341ad08e31209ba3471161ecc36b55cc Mon Sep 17 00:00:00 2001 From: Jing Li Date: Mon, 2 Sep 2024 15:40:44 +0800 Subject: [PATCH 100/100] anolis: sw64: defconfig: fix SPI related configuration items ANBZ: #4688 SPI_CHIP is renamed to SPI_SUNWAY, and SPI_CHIP_MMIO is renamed to SPI_SUNWAY_MMIO. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/configs/junzhang_defconfig | 4 ++-- arch/sw_64/configs/xuelang_defconfig | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/sw_64/configs/junzhang_defconfig b/arch/sw_64/configs/junzhang_defconfig index e97e1fdfac4d..2073cb0fecdb 100644 --- a/arch/sw_64/configs/junzhang_defconfig +++ b/arch/sw_64/configs/junzhang_defconfig @@ -526,8 +526,8 @@ CONFIG_I2C_CHARDEV=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_I2C_MUX=y CONFIG_SPI=y -CONFIG_SPI_CHIP=y -CONFIG_SPI_CHIP_MMIO=y +CONFIG_SPI_SUNWAY=y +CONFIG_SPI_SUNWAY_MMIO=y CONFIG_SPI_SPIDEV=y CONFIG_SENSORS_PVT=y CONFIG_SENSORS_LM75=y diff --git a/arch/sw_64/configs/xuelang_defconfig b/arch/sw_64/configs/xuelang_defconfig index 68bceb7c8da8..2272d99db00c 100644 --- a/arch/sw_64/configs/xuelang_defconfig +++ b/arch/sw_64/configs/xuelang_defconfig @@ -521,7 +521,7 @@ CONFIG_VIRTIO_CONSOLE=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_MUX=y CONFIG_SPI=y -CONFIG_SPI_CHIP3=y +CONFIG_SPI_SUNWAY=y CONFIG_SPI_SPIDEV=y CONFIG_SENSORS_PVT=y CONFIG_SENSORS_LM75=y -- Gitee