diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index ae4b450170935c8f890ba06095fa8f4468c9b290..8bd45cc963a425d9cd9ff70d71d5fe1580346861 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -81,6 +81,8 @@ config SW64 select GPIOLIB if ACPI select HANDLE_DOMAIN_IRQ select HARDIRQS_SW_RESEND + select HAS_IOPORT + select HAVE_ACPI_APEI if ACPI select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_KGDB diff --git a/arch/sw_64/include/asm/acpi.h b/arch/sw_64/include/asm/acpi.h index e386d07d1e73c443646f50928b43724b33306935..82982759effa6edea56b490bb3c2c05a16e90f35 100644 --- a/arch/sw_64/include/asm/acpi.h +++ b/arch/sw_64/include/asm/acpi.h @@ -15,6 +15,12 @@ extern int acpi_strict; extern int acpi_disabled; extern int acpi_pci_disabled; +/* + * acpi_disable_cmcff is only used in IA-32 Architecture, this + * definition is only for compatibility. + */ +#define acpi_disable_cmcff 1 + /* _ASM_SW64_PDC_H */ #define ACPI_PDC_P_FFH (0x0001) #define ACPI_PDC_C_C1_HALT (0x0002) diff --git a/arch/sw_64/include/asm/kvm_host.h b/arch/sw_64/include/asm/kvm_host.h index 63b344ed0359fa4eda38b81bc4fadd9fa03fc02b..cf0009f2d3656aa3874ebc0c9489ffa4ad7b5f64 100644 --- a/arch/sw_64/include/asm/kvm_host.h +++ b/arch/sw_64/include/asm/kvm_host.h @@ -199,4 +199,14 @@ long kvm_sw64_get_vcb(struct file *filp, unsigned long arg); void update_aptp(unsigned long pgd); void vcpu_set_numa_affinity(struct kvm_vcpu *vcpu); + +/* + * Returns true if a Performance Monitoring Interrupt (PMI), a.k.a. perf event, + * arrived in guest context. + */ +static inline bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu) +{ + return IS_ENABLED(CONFIG_GUEST_PERF_EVENTS) && !!vcpu; +} + #endif /* _ASM_SW64_KVM_HOST_H */ diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index 6e8d0ed37567cb8e51b3aaced661845fa586cd9e..e05b54585e550197f89c35beaf899121db111c4d 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -83,6 +83,8 @@ enum SUNWAY_RC { SUNWAY_RC_SIZE = 0x82500UL, }; +#define SUNWAY_DEVMN_SIZE 0x3480UL + struct pci_dev; struct pci_bus; struct resource; @@ -108,11 +110,11 @@ struct pci_controller { unsigned long sparse_io_base; unsigned long dense_io_base; - /* This one's for the kernel only. It's in KSEG somewhere. */ void __iomem *ep_config_space_base; void __iomem *rc_config_space_base; void __iomem *piu_ior0_base; void __iomem *piu_ior1_base; + void __iomem *devmn_base; unsigned long index; unsigned long node; diff --git a/arch/sw_64/kernel/sys_sw64.c b/arch/sw_64/kernel/sys_sw64.c index c11c02285bf3ef4f518e375751bb6d50b9b5dd3e..8daed9829ec5221991a32945e6142a05a8da46c2 100644 --- a/arch/sw_64/kernel/sys_sw64.c +++ b/arch/sw_64/kernel/sys_sw64.c @@ -349,6 +349,23 @@ asmlinkage void noinstr do_entSys(struct pt_regs *regs) nr = regs->regs[0]; if (ti_flags & _TIF_SYSCALL_WORK) { + /* + * The de-facto standard way to skip a system call using ptrace + * is to set the system call to -1 (NO_SYSCALL) and set r0 to a + * suitable error code for consumption by userspace. However, + * this cannot be distinguished from a user-issued syscall(-1) + * and so we must set r0 to -ENOSYS here in case the tracer doesn't + * issue the skip and we fall into trace_exit with r0 preserved. + * + * This is slightly odd because it also means that if a tracer + * sets the system call number to -1 but does not initialise r0, + * then r0 will be preserved for all system calls apart from a + * user-issued syscall(-1). However, requesting a skip and not + * setting the return value is unlikely to do anything sensible + * anyway. + */ + if (nr == NO_SYSCALL) + syscall_set_return_value(current, regs, -ENOSYS, 0); nr = syscall_trace_enter(); if (nr == NO_SYSCALL) goto syscall_out; diff --git a/arch/sw_64/kvm/Kconfig b/arch/sw_64/kvm/Kconfig index 5fac5b1d9fb481f795f17153d1aa7fd22ab77dd7..124cead28b53167932fd2e9ee3ac643a7f3b35c9 100644 --- a/arch/sw_64/kvm/Kconfig +++ b/arch/sw_64/kvm/Kconfig @@ -32,6 +32,7 @@ config KVM select GENERIC_ALLOCATOR select KVM_GENERIC_DIRTYLOG_READ_PROTECT select HAVE_KVM_DIRTY_RING_ACQ_REL + select GUEST_PERF_EVENTS if PERF_EVENTS help Support for hosting Guest kernels. We don't support KVM with 3-level page tables yet. diff --git a/arch/sw_64/kvm/kvm_core3.c b/arch/sw_64/kvm/kvm_core3.c index 26c27c69ba7b2d5735972eca104c2a1c5074fc35..378831c211397a1dbe02f4a45e95156f8ea45b1a 100644 --- a/arch/sw_64/kvm/kvm_core3.c +++ b/arch/sw_64/kvm/kvm_core3.c @@ -376,6 +376,8 @@ static int __init kvm_core3_init(void) for (i = 0; i < NR_CPUS; i++) last_vpn(i) = VPN_FIRST_VERSION; + kvm_register_perf_callbacks(NULL); + ret = kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE); if (likely(!ret)) diff --git a/arch/sw_64/kvm/kvm_core4.c b/arch/sw_64/kvm/kvm_core4.c index 4b6376f3c0394bb5449b8c606b641b0d10e429c2..98fdbfe88fedbb63cb716b0a57c3a758b7d9d181 100644 --- a/arch/sw_64/kvm/kvm_core4.c +++ b/arch/sw_64/kvm/kvm_core4.c @@ -220,6 +220,8 @@ static int __init kvm_core4_init(void) for (i = 0; i < NR_CPUS; i++) last_vpn(i) = VPN_FIRST_VERSION; + kvm_register_perf_callbacks(NULL); + ret = kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE); if (ret) diff --git a/arch/sw_64/kvm/perf.c b/arch/sw_64/kvm/perf.c index 730dd1feeccf83e4de96ea93608b7a7752ef5ebc..7817f1e199e7fa1844917dbba7bfcd13fce2b8eb 100644 --- a/arch/sw_64/kvm/perf.c +++ b/arch/sw_64/kvm/perf.c @@ -11,17 +11,14 @@ bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu) { - return (vcpu->arch.regs.ps & 8) != 0; + if (IS_ENABLED(CONFIG_SUBARCH_C3B)) + return (vcpu->arch.regs.ps & 0x8) == 0; + else + return (vcpu->arch.regs.pc & 0x3) == 0x2; + } unsigned long kvm_arch_vcpu_get_ip(struct kvm_vcpu *vcpu) { return vcpu->arch.regs.pc; } - - - -static inline bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu) -{ - return IS_ENABLED(CONFIG_GUEST_PERF_EVENTS) && !!vcpu; -} diff --git a/arch/sw_64/lib/string.c b/arch/sw_64/lib/string.c index 5eed2016dc61d14001ee092e23f1c5fa3d0d8f21..16f5b37a1eca106b5919945626243cc26a05f8c0 100644 --- a/arch/sw_64/lib/string.c +++ b/arch/sw_64/lib/string.c @@ -19,14 +19,14 @@ static inline void *____memcpy(void *dest, const void *src, size_t n) return ____memcpy_simd_align(dest, src, n); } -void notrace *memcpy(void *dest, const void *src, size_t n) +void * notrace memcpy(void *dest, const void *src, size_t n) { return ____memcpy(dest, src, n); } EXPORT_SYMBOL(memcpy); /* For backward compatibility with modules. Unused otherwise. */ -void notrace *__memcpy(void *dest, const void *src, size_t n) +void * notrace __memcpy(void *dest, const void *src, size_t n) { return ____memcpy(dest, src, n); } @@ -47,12 +47,12 @@ static inline void *____constant_c_memset(void *s, unsigned long c, size_t n) return ____constant_c_memset_simd_align(s, c, n); } -void notrace *__constant_c_memset(void *s, unsigned long c, size_t n) +void * notrace __constant_c_memset(void *s, unsigned long c, size_t n) { return ____constant_c_memset(s, c, n); } -void notrace *___memset(void *s, int c, size_t n) +void * notrace ___memset(void *s, int c, size_t n) { unsigned long c_ul = (c & 0xff) * 0x0101010101010101UL; @@ -60,7 +60,7 @@ void notrace *___memset(void *s, int c, size_t n) } EXPORT_SYMBOL(___memset); -void notrace *__memset(void *s, int c, size_t n) +void * notrace __memset(void *s, int c, size_t n) { unsigned long c_ul = (c & 0xff) * 0x0101010101010101UL; @@ -68,7 +68,7 @@ void notrace *__memset(void *s, int c, size_t n) } EXPORT_SYMBOL(__memset); -void notrace *memset(void *s, int c, size_t n) +void * notrace memset(void *s, int c, size_t n) { unsigned long c_ul = (c & 0xff) * 0x0101010101010101UL; @@ -76,7 +76,7 @@ void notrace *memset(void *s, int c, size_t n) } EXPORT_SYMBOL(memset); -void notrace *__memsetw(void *dest, unsigned short c, size_t count) +void * notrace __memsetw(void *dest, unsigned short c, size_t count) { unsigned long c_ul = (c & 0xffff) * 0x0001000100010001UL; diff --git a/arch/sw_64/pci/pci.c b/arch/sw_64/pci/pci.c index 2ce6c3931c96b750cf69d0a84f8abac3d40ef826..a7721db94609e36d5b76daac78f44285fd9fef8f 100644 --- a/arch/sw_64/pci/pci.c +++ b/arch/sw_64/pci/pci.c @@ -236,19 +236,6 @@ static void fixup_root_complex(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_JN, PCI_DEVICE_ID_SW64_ROOT_BRIDGE, fixup_root_complex); -static int setup_bus_dma_cb(struct pci_dev *pdev, void *data) -{ - pdev->dev.bus_dma_limit = DMA_BIT_MASK(32); - return 0; -} - -static void fix_bus_dma_limit(struct pci_dev *dev) -{ - pci_walk_bus(dev->subordinate, setup_bus_dma_cb, NULL); - pr_info("Set zx200 bus_dma_limit to 32-bit\n"); -} -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ZHAOXIN, 0x071f, fix_bus_dma_limit); - #ifdef CONFIG_DCA static void enable_sw_dca(struct pci_dev *dev) { @@ -383,8 +370,10 @@ static void sunway_pci_root_bridge_prepare(struct pci_host_bridge *bridge) bridge->swizzle_irq = pci_common_swizzle; 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)); + if (!is_guest_or_emul()) { + init_busnr = (0xff << 16) + ((last_bus + 1) << 8) + (last_bus); + writel(init_busnr, (hose->rc_config_space_base + RC_PRIMARY_BUS)); + } hose->first_busno = last_bus + (is_in_host() ? 1 : 0); @@ -412,10 +401,12 @@ void sunway_pci_root_bridge_scan_finish(struct pci_host_bridge *bridge) hose->last_busno = last_bus; hose->busn_space->end = last_bus; - init_busnr = readl(hose->rc_config_space_base + RC_PRIMARY_BUS); - init_busnr &= ~(0xff << 16); - init_busnr |= last_bus << 16; - writel(init_busnr, (hose->rc_config_space_base + RC_PRIMARY_BUS)); + if (!is_guest_or_emul()) { + init_busnr = readl(hose->rc_config_space_base + RC_PRIMARY_BUS); + init_busnr &= ~(0xff << 16); + init_busnr |= last_bus << 16; + writel(init_busnr, (hose->rc_config_space_base + RC_PRIMARY_BUS)); + } pci_bus_update_busn_res_end(bus, last_bus); last_bus++; diff --git a/drivers/irqchip/irq-sunway-pci-intx.c b/drivers/irqchip/irq-sunway-pci-intx.c index bd108d58ff534152acad275022079c36549f852c..6b82872c23460f25e8339162519d631789c40f6f 100644 --- a/drivers/irqchip/irq-sunway-pci-intx.c +++ b/drivers/irqchip/irq-sunway-pci-intx.c @@ -224,11 +224,9 @@ void setup_intx_irqs(struct pci_controller *hose) { unsigned long irq, node, val_node; struct intx_chip_data *chip_data; - void __iomem *piu_ior0_base; int i = 0; node = hose->node; - piu_ior0_base = hose->piu_ior0_base; if (!node_online(node)) val_node = next_node_in(node, node_online_map); @@ -259,7 +257,8 @@ void setup_intx_irqs(struct pci_controller *hose) irq_set_chip_and_handler(irq + 1, &dummy_irq_chip, handle_level_irq); hose->service_irq = irq + 1; - set_pcieport_service_irq(hose); + if (!is_guest_or_emul()) + set_pcieport_service_irq(hose); } void __init sunway_init_pci_intx(void) diff --git a/drivers/pci/controller/pci-sunway.c b/drivers/pci/controller/pci-sunway.c index 5c7346efd5a3effb085cb48dd71109a47d7c4e34..c29ce8dca60337d1f8660bd916c21cc96b6a8b39 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -779,6 +779,7 @@ enum pci_props { PROP_PIU_IOR1_BASE, PROP_RC_INDEX, PROP_PCIE_IO_BASE, + PROP_DEVMN_BASE, PROP_NUM }; @@ -803,7 +804,8 @@ static const char *prop_names[PROP_NUM] = { "sunway,piu-ior0-base", "sunway,piu-ior1-base", "sunway,rc-index", - "sunway,pcie-io-base" + "sunway,pcie-io-base", + "sunway,devmn-base" }; #ifdef CONFIG_NUMA @@ -838,6 +840,9 @@ static int pci_prepare_controller(struct pci_controller *hose, /* Get necessary properties of Root Complex */ for (i = 0; i < PROP_NUM; ++i) { + if ((i == PROP_DEVMN_BASE) && !is_junzhang_v3()) + break; + ret = fwnode_property_read_u64(fwnode, prop_names[i], &props[i]); @@ -865,9 +870,16 @@ static int pci_prepare_controller(struct pci_controller *hose, hose->dense_mem_base = props[PROP_PCIE_IO_BASE]; hose->dense_io_base = props[PROP_EP_IO_BASE]; - hose->rc_config_space_base = ioremap(props[PROP_RC_CONFIG_BASE], SUNWAY_RC_SIZE); - hose->piu_ior0_base = ioremap(props[PROP_PIU_IOR0_BASE], SUNWAY_PIU_IOR0_SIZE); - hose->piu_ior1_base = ioremap(props[PROP_PIU_IOR1_BASE], SUNWAY_PIU_IOR1_SIZE); + if (!is_guest_or_emul()) { + hose->rc_config_space_base = ioremap(props[PROP_RC_CONFIG_BASE], SUNWAY_RC_SIZE); + hose->piu_ior0_base = ioremap(props[PROP_PIU_IOR0_BASE], SUNWAY_PIU_IOR0_SIZE); + hose->piu_ior1_base = ioremap(props[PROP_PIU_IOR1_BASE], SUNWAY_PIU_IOR1_SIZE); + hose->piu_ior0 = alloc_piu_saved_data(PIU_IOR0_SAVE_REGS * sizeof(u64)); + hose->piu_ior1 = alloc_piu_saved_data(PIU_IOR1_SAVE_REGS * sizeof(u64)); + } + + if (is_junzhang_v3()) + hose->devmn_base = ioremap(props[PROP_DEVMN_BASE], SUNWAY_DEVMN_SIZE); hose->first_busno = 0xff; hose->last_busno = 0xff; @@ -875,9 +887,6 @@ static int pci_prepare_controller(struct pci_controller *hose, hose->need_domain_info = 0; - hose->piu_ior0 = alloc_piu_saved_data(PIU_IOR0_SAVE_REGS * sizeof(u64)); - hose->piu_ior1 = alloc_piu_saved_data(PIU_IOR1_SAVE_REGS * sizeof(u64)); - #if IS_ENABLED(CONFIG_PCI_MSI) if (is_in_host()) memset(hose->piu_msiconfig, 0, 256 / 8); /* 256 bits bitmap */ diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index fb290a90b263d10b94d23d359e0a49498c4b5602..2f4a14df3825460da41b27f4ed82623715e5d3fd 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -54,7 +54,6 @@ FEATURE_TESTS_BASIC := \ libtracefs \ libcrypto \ libunwind \ - libunwind-sw_64 \ pthread-attr-setaffinity-np \ pthread-barrier \ reallocarray \ @@ -94,6 +93,7 @@ FEATURE_TESTS_EXTRA := \ libunwind-x86_64 \ libunwind-arm \ libunwind-aarch64 \ + libunwind-sw_64 \ libunwind-debug-frame \ libunwind-debug-frame-arm \ libunwind-debug-frame-aarch64 \ diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index a48258330cc0e5f6c39401540e13280b05162d6e..a3a8666b43c9bb6ae7024ba8d52c5dc99d1bcc78 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -153,6 +153,7 @@ FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_L FEATURE_CHECK_LDFLAGS-libunwind-arm += -lunwind -lunwind-arm FEATURE_CHECK_LDFLAGS-libunwind-aarch64 += -lunwind -lunwind-aarch64 +FEATURE_CHECK_LDFLAGS-libunwind-sw_64 += -lunwind -lunwind-sw_64 FEATURE_CHECK_LDFLAGS-libunwind-x86 += -lunwind -llzma -lunwind-x86 FEATURE_CHECK_LDFLAGS-libunwind-x86_64 += -lunwind -llzma -lunwind-x86_64 @@ -646,6 +647,8 @@ ifndef NO_LIBUNWIND CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME_AARCH64 endif endif + + $(call feature_check,libunwind-sw_64) ifeq ($(feature-libunwind-sw_64), 1) $(call detected,CONFIG_LIBUNWIND_SW64) CFLAGS += -DHAVE_LIBUNWIND_SW_64_SUPPORT