From db1003a719d75cebe5843a7906c02c29bec9922c Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Mon, 21 Sep 2015 01:01:59 +0800 Subject: x86/numachip: Cleanup Numachip support Drop unused code and includes in Numachip header files and APIC driver. Additionally, use the 'numachip1' prefix on Numachip1-specific functions; this prepares for adding Numachip2 support in later patches. Signed-off-by: Daniel J Blueman Acked-by: Steffen Persvold Cc: Daniel Lezcano Link: http://lkml.kernel.org/r/1442768522-19217-1-git-send-email-daniel@numascale.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/numachip/numachip_csr.h | 118 +-------------------------- arch/x86/kernel/apic/apic_numachip.c | 104 ++++++++++------------- 2 files changed, 44 insertions(+), 178 deletions(-) diff --git a/arch/x86/include/asm/numachip/numachip_csr.h b/arch/x86/include/asm/numachip/numachip_csr.h index 660f843df928..7469b13a9cfa 100644 --- a/arch/x86/include/asm/numachip/numachip_csr.h +++ b/arch/x86/include/asm/numachip/numachip_csr.h @@ -14,12 +14,7 @@ #ifndef _ASM_X86_NUMACHIP_NUMACHIP_CSR_H #define _ASM_X86_NUMACHIP_NUMACHIP_CSR_H -#include -#include #include -#include -#include -#include #define CSR_NODE_SHIFT 16 #define CSR_NODE_BITS(p) (((unsigned long)(p)) << CSR_NODE_SHIFT) @@ -27,11 +22,8 @@ /* 32K CSR space, b15 indicates geo/non-geo */ #define CSR_OFFSET_MASK 0x7fffUL - -/* Global CSR space covers all 4K possible nodes with 64K CSR space per node */ -#define NUMACHIP_GCSR_BASE 0x3fff00000000ULL -#define NUMACHIP_GCSR_LIM 0x3fff0fffffffULL -#define NUMACHIP_GCSR_SIZE (NUMACHIP_GCSR_LIM - NUMACHIP_GCSR_BASE + 1) +#define CSR_G0_NODE_IDS (0x008 + (0 << 12)) +#define CSR_G3_EXT_IRQ_GEN (0x030 + (3 << 12)) /* * Local CSR space starts in global CSR space with "nodeid" = 0xfff0, however @@ -42,28 +34,12 @@ #define NUMACHIP_LCSR_LIM 0x3fffffffffffULL #define NUMACHIP_LCSR_SIZE (NUMACHIP_LCSR_LIM - NUMACHIP_LCSR_BASE + 1) -static inline void *gcsr_address(int node, unsigned long offset) -{ - return __va(NUMACHIP_GCSR_BASE | (1UL << 15) | - CSR_NODE_BITS(node & CSR_NODE_MASK) | (offset & CSR_OFFSET_MASK)); -} - static inline void *lcsr_address(unsigned long offset) { return __va(NUMACHIP_LCSR_BASE | (1UL << 15) | CSR_NODE_BITS(0xfff0) | (offset & CSR_OFFSET_MASK)); } -static inline unsigned int read_gcsr(int node, unsigned long offset) -{ - return swab32(readl(gcsr_address(node, offset))); -} - -static inline void write_gcsr(int node, unsigned long offset, unsigned int val) -{ - writel(swab32(val), gcsr_address(node, offset)); -} - static inline unsigned int read_lcsr(unsigned long offset) { return swab32(readl(lcsr_address(offset))); @@ -74,94 +50,4 @@ static inline void write_lcsr(unsigned long offset, unsigned int val) writel(swab32(val), lcsr_address(offset)); } -/* ========================================================================= */ -/* CSR_G0_STATE_CLEAR */ -/* ========================================================================= */ - -#define CSR_G0_STATE_CLEAR (0x000 + (0 << 12)) -union numachip_csr_g0_state_clear { - unsigned int v; - struct numachip_csr_g0_state_clear_s { - unsigned int _state:2; - unsigned int _rsvd_2_6:5; - unsigned int _lost:1; - unsigned int _rsvd_8_31:24; - } s; -}; - -/* ========================================================================= */ -/* CSR_G0_NODE_IDS */ -/* ========================================================================= */ - -#define CSR_G0_NODE_IDS (0x008 + (0 << 12)) -union numachip_csr_g0_node_ids { - unsigned int v; - struct numachip_csr_g0_node_ids_s { - unsigned int _initialid:16; - unsigned int _nodeid:12; - unsigned int _rsvd_28_31:4; - } s; -}; - -/* ========================================================================= */ -/* CSR_G3_EXT_IRQ_GEN */ -/* ========================================================================= */ - -#define CSR_G3_EXT_IRQ_GEN (0x030 + (3 << 12)) -union numachip_csr_g3_ext_irq_gen { - unsigned int v; - struct numachip_csr_g3_ext_irq_gen_s { - unsigned int _vector:8; - unsigned int _msgtype:3; - unsigned int _index:5; - unsigned int _destination_apic_id:16; - } s; -}; - -/* ========================================================================= */ -/* CSR_G3_EXT_IRQ_STATUS */ -/* ========================================================================= */ - -#define CSR_G3_EXT_IRQ_STATUS (0x034 + (3 << 12)) -union numachip_csr_g3_ext_irq_status { - unsigned int v; - struct numachip_csr_g3_ext_irq_status_s { - unsigned int _result:32; - } s; -}; - -/* ========================================================================= */ -/* CSR_G3_EXT_IRQ_DEST */ -/* ========================================================================= */ - -#define CSR_G3_EXT_IRQ_DEST (0x038 + (3 << 12)) -union numachip_csr_g3_ext_irq_dest { - unsigned int v; - struct numachip_csr_g3_ext_irq_dest_s { - unsigned int _irq:8; - unsigned int _rsvd_8_31:24; - } s; -}; - -/* ========================================================================= */ -/* CSR_G3_NC_ATT_MAP_SELECT */ -/* ========================================================================= */ - -#define CSR_G3_NC_ATT_MAP_SELECT (0x7fc + (3 << 12)) -union numachip_csr_g3_nc_att_map_select { - unsigned int v; - struct numachip_csr_g3_nc_att_map_select_s { - unsigned int _upper_address_bits:4; - unsigned int _select_ram:4; - unsigned int _rsvd_8_31:24; - } s; -}; - -/* ========================================================================= */ -/* CSR_G3_NC_ATT_MAP_SELECT_0-255 */ -/* ========================================================================= */ - -#define CSR_G3_NC_ATT_MAP_SELECT_0 (0x800 + (3 << 12)) - #endif /* _ASM_X86_NUMACHIP_NUMACHIP_CSR_H */ - diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index b548fd3b764b..eeefbb11ec79 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -11,30 +11,20 @@ * */ -#include -#include -#include -#include -#include -#include -#include #include -#include -#include #include #include -#include -#include #include #include #include +#include -static int numachip_system __read_mostly; +u8 numachip_system __read_mostly; +static const struct apic apic_numachip1; +static void (*numachip_apic_icr_write)(int apicid, unsigned int val) __read_mostly; -static const struct apic apic_numachip; - -static unsigned int get_apic_id(unsigned long x) +static unsigned int numachip1_get_apic_id(unsigned long x) { unsigned long value; unsigned int id = (x >> 24) & 0xff; @@ -47,7 +37,7 @@ static unsigned int get_apic_id(unsigned long x) return id; } -static unsigned long set_apic_id(unsigned int id) +static unsigned long numachip1_set_apic_id(unsigned int id) { unsigned long x; @@ -55,11 +45,6 @@ static unsigned long set_apic_id(unsigned int id) return x; } -static unsigned int read_xapic_id(void) -{ - return get_apic_id(apic_read(APIC_ID)); -} - static int numachip_apic_id_valid(int apicid) { /* Trust what bootloader passes in MADT */ @@ -68,7 +53,7 @@ static int numachip_apic_id_valid(int apicid) static int numachip_apic_id_registered(void) { - return physid_isset(read_xapic_id(), phys_cpu_present_map); + return 1; } static int numachip_phys_pkg_id(int initial_apic_id, int index_msb) @@ -76,36 +61,27 @@ static int numachip_phys_pkg_id(int initial_apic_id, int index_msb) return initial_apic_id >> index_msb; } -static int numachip_wakeup_secondary(int phys_apicid, unsigned long start_rip) +static void numachip1_apic_icr_write(int apicid, unsigned int val) { - union numachip_csr_g3_ext_irq_gen int_gen; - - int_gen.s._destination_apic_id = phys_apicid; - int_gen.s._vector = 0; - int_gen.s._msgtype = APIC_DM_INIT >> 8; - int_gen.s._index = 0; - - write_lcsr(CSR_G3_EXT_IRQ_GEN, int_gen.v); - - int_gen.s._msgtype = APIC_DM_STARTUP >> 8; - int_gen.s._vector = start_rip >> 12; + write_lcsr(CSR_G3_EXT_IRQ_GEN, (apicid << 16) | val); +} - write_lcsr(CSR_G3_EXT_IRQ_GEN, int_gen.v); +static int numachip_wakeup_secondary(int phys_apicid, unsigned long start_rip) +{ + numachip_apic_icr_write(phys_apicid, APIC_DM_INIT); + numachip_apic_icr_write(phys_apicid, APIC_DM_STARTUP | + (start_rip >> 12)); return 0; } static void numachip_send_IPI_one(int cpu, int vector) { - union numachip_csr_g3_ext_irq_gen int_gen; int apicid = per_cpu(x86_cpu_to_apicid, cpu); + unsigned int dmode; - int_gen.s._destination_apic_id = apicid; - int_gen.s._vector = vector; - int_gen.s._msgtype = (vector == NMI_VECTOR ? APIC_DM_NMI : APIC_DM_FIXED) >> 8; - int_gen.s._index = 0; - - write_lcsr(CSR_G3_EXT_IRQ_GEN, int_gen.v); + dmode = (vector == NMI_VECTOR) ? APIC_DM_NMI : APIC_DM_FIXED; + numachip_apic_icr_write(apicid, dmode | vector); } static void numachip_send_IPI_mask(const struct cpumask *mask, int vector) @@ -149,9 +125,9 @@ static void numachip_send_IPI_self(int vector) apic_write(APIC_SELF_IPI, vector); } -static int __init numachip_probe(void) +static int __init numachip1_probe(void) { - return apic == &apic_numachip; + return apic == &apic_numachip1; } static void fixup_cpu_id(struct cpuinfo_x86 *c, int node) @@ -172,34 +148,38 @@ static void fixup_cpu_id(struct cpuinfo_x86 *c, int node) static int __init numachip_system_init(void) { - if (!numachip_system) + /* Map the LCSR area and set up the apic_icr_write function */ + switch (numachip_system) { + case 1: + init_extra_mapping_uc(NUMACHIP_LCSR_BASE, NUMACHIP_LCSR_SIZE); + numachip_apic_icr_write = numachip1_apic_icr_write; + x86_init.pci.arch_init = pci_numachip_init; + break; + default: return 0; - - init_extra_mapping_uc(NUMACHIP_LCSR_BASE, NUMACHIP_LCSR_SIZE); - init_extra_mapping_uc(NUMACHIP_GCSR_BASE, NUMACHIP_GCSR_SIZE); + } x86_cpuinit.fixup_cpu_id = fixup_cpu_id; - x86_init.pci.arch_init = pci_numachip_init; return 0; } early_initcall(numachip_system_init); -static int numachip_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static int numachip1_acpi_madt_oem_check(char *oem_id, char *oem_table_id) { - if (!strncmp(oem_id, "NUMASC", 6)) { - numachip_system = 1; - return 1; - } + if ((strncmp(oem_id, "NUMASC", 6) != 0) || + (strncmp(oem_table_id, "NCONNECT", 8) != 0)) + return 0; - return 0; -} + numachip_system = 1; -static const struct apic apic_numachip __refconst = { + return 1; +} +static const struct apic apic_numachip1 __refconst = { .name = "NumaConnect system", - .probe = numachip_probe, - .acpi_madt_oem_check = numachip_acpi_madt_oem_check, + .probe = numachip1_probe, + .acpi_madt_oem_check = numachip1_acpi_madt_oem_check, .apic_id_valid = numachip_apic_id_valid, .apic_id_registered = numachip_apic_id_registered, @@ -221,8 +201,8 @@ static const struct apic apic_numachip __refconst = { .check_phys_apicid_present = default_check_phys_apicid_present, .phys_pkg_id = numachip_phys_pkg_id, - .get_apic_id = get_apic_id, - .set_apic_id = set_apic_id, + .get_apic_id = numachip1_get_apic_id, + .set_apic_id = numachip1_set_apic_id, .apic_id_mask = 0xffU << 24, .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, @@ -244,5 +224,5 @@ static const struct apic apic_numachip __refconst = { .wait_icr_idle = native_apic_wait_icr_idle, .safe_wait_icr_idle = native_safe_apic_wait_icr_idle, }; -apic_driver(apic_numachip); +apic_driver(apic_numachip1); -- cgit v1.2.3 From d9d4dee6cedfa17e5eedcba242dca3091bf73bc3 Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Mon, 21 Sep 2015 01:02:00 +0800 Subject: x86/numachip: Add Numachip2 APIC support Introduce support for Numachip2 remote interrupts via detecting the right ACPI SRAT signature. Access is performed via a fixed mapping in the x86 physical address space. Signed-off-by: Daniel J Blueman Acked-by: Steffen Persvold Cc: Daniel Lezcano Link: http://lkml.kernel.org/r/1442768522-19217-2-git-send-email-daniel@numascale.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/numachip/numachip.h | 1 + arch/x86/include/asm/numachip/numachip_csr.h | 35 +++++++++++ arch/x86/kernel/apic/apic_numachip.c | 93 ++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) diff --git a/arch/x86/include/asm/numachip/numachip.h b/arch/x86/include/asm/numachip/numachip.h index 1c6f7f6212c1..c64373a2d731 100644 --- a/arch/x86/include/asm/numachip/numachip.h +++ b/arch/x86/include/asm/numachip/numachip.h @@ -14,6 +14,7 @@ #ifndef _ASM_X86_NUMACHIP_NUMACHIP_H #define _ASM_X86_NUMACHIP_NUMACHIP_H +extern u8 numachip_system; extern int __init pci_numachip_init(void); #endif /* _ASM_X86_NUMACHIP_NUMACHIP_H */ diff --git a/arch/x86/include/asm/numachip/numachip_csr.h b/arch/x86/include/asm/numachip/numachip_csr.h index 7469b13a9cfa..e08b803f8491 100644 --- a/arch/x86/include/asm/numachip/numachip_csr.h +++ b/arch/x86/include/asm/numachip/numachip_csr.h @@ -14,6 +14,7 @@ #ifndef _ASM_X86_NUMACHIP_NUMACHIP_CSR_H #define _ASM_X86_NUMACHIP_NUMACHIP_CSR_H +#include #include #define CSR_NODE_SHIFT 16 @@ -50,4 +51,38 @@ static inline void write_lcsr(unsigned long offset, unsigned int val) writel(swab32(val), lcsr_address(offset)); } +/* + * On NumaChip2, local CSR space is 16MB and starts at fixed offset below 4G + */ + +#define NUMACHIP2_LCSR_BASE 0xf0000000UL +#define NUMACHIP2_LCSR_SIZE 0x1000000UL +#define NUMACHIP2_APIC_ICR 0x100000 + +static inline void __iomem *numachip2_lcsr_address(unsigned long offset) +{ + return (void __iomem *)__va(NUMACHIP2_LCSR_BASE | + (offset & (NUMACHIP2_LCSR_SIZE - 1))); +} + +static inline u32 numachip2_read32_lcsr(unsigned long offset) +{ + return readl(numachip2_lcsr_address(offset)); +} + +static inline u64 numachip2_read64_lcsr(unsigned long offset) +{ + return readq(numachip2_lcsr_address(offset)); +} + +static inline void numachip2_write32_lcsr(unsigned long offset, u32 val) +{ + writel(val, numachip2_lcsr_address(offset)); +} + +static inline void numachip2_write64_lcsr(unsigned long offset, u64 val) +{ + writeq(val, numachip2_lcsr_address(offset)); +} + #endif /* _ASM_X86_NUMACHIP_NUMACHIP_CSR_H */ diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index eeefbb11ec79..3cb929481d46 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -22,6 +22,7 @@ u8 numachip_system __read_mostly; static const struct apic apic_numachip1; +static const struct apic apic_numachip2; static void (*numachip_apic_icr_write)(int apicid, unsigned int val) __read_mostly; static unsigned int numachip1_get_apic_id(unsigned long x) @@ -45,6 +46,19 @@ static unsigned long numachip1_set_apic_id(unsigned int id) return x; } +static unsigned int numachip2_get_apic_id(unsigned long x) +{ + u64 mcfg; + + rdmsrl(MSR_FAM10H_MMIO_CONF_BASE, mcfg); + return ((mcfg >> (28 - 8)) & 0xfff00) | (x >> 24); +} + +static unsigned long numachip2_set_apic_id(unsigned int id) +{ + return id << 24; +} + static int numachip_apic_id_valid(int apicid) { /* Trust what bootloader passes in MADT */ @@ -66,6 +80,11 @@ static void numachip1_apic_icr_write(int apicid, unsigned int val) write_lcsr(CSR_G3_EXT_IRQ_GEN, (apicid << 16) | val); } +static void numachip2_apic_icr_write(int apicid, unsigned int val) +{ + numachip2_write32_lcsr(NUMACHIP2_APIC_ICR, (apicid << 12) | val); +} + static int numachip_wakeup_secondary(int phys_apicid, unsigned long start_rip) { numachip_apic_icr_write(phys_apicid, APIC_DM_INIT); @@ -130,6 +149,11 @@ static int __init numachip1_probe(void) return apic == &apic_numachip1; } +static int __init numachip2_probe(void) +{ + return apic == &apic_numachip2; +} + static void fixup_cpu_id(struct cpuinfo_x86 *c, int node) { u64 val; @@ -155,6 +179,13 @@ static int __init numachip_system_init(void) numachip_apic_icr_write = numachip1_apic_icr_write; x86_init.pci.arch_init = pci_numachip_init; break; + case 2: + init_extra_mapping_uc(NUMACHIP2_LCSR_BASE, NUMACHIP2_LCSR_SIZE); + numachip_apic_icr_write = numachip2_apic_icr_write; + + /* Use MCFG config cycles rather than locked CF8 cycles */ + raw_pci_ops = &pci_mmcfg; + break; default: return 0; } @@ -176,6 +207,17 @@ static int numachip1_acpi_madt_oem_check(char *oem_id, char *oem_table_id) return 1; } +static int numachip2_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + if ((strncmp(oem_id, "NUMASC", 6) != 0) || + (strncmp(oem_table_id, "NCONECT2", 8) != 0)) + return 0; + + numachip_system = 2; + + return 1; +} + static const struct apic apic_numachip1 __refconst = { .name = "NumaConnect system", .probe = numachip1_probe, @@ -226,3 +268,54 @@ static const struct apic apic_numachip1 __refconst = { }; apic_driver(apic_numachip1); + +static const struct apic apic_numachip2 __refconst = { + .name = "NumaConnect2 system", + .probe = numachip2_probe, + .acpi_madt_oem_check = numachip2_acpi_madt_oem_check, + .apic_id_valid = numachip_apic_id_valid, + .apic_id_registered = numachip_apic_id_registered, + + .irq_delivery_mode = dest_Fixed, + .irq_dest_mode = 0, /* physical */ + + .target_cpus = online_target_cpus, + .disable_esr = 0, + .dest_logical = 0, + .check_apicid_used = NULL, + + .vector_allocation_domain = default_vector_allocation_domain, + .init_apic_ldr = flat_init_apic_ldr, + + .ioapic_phys_id_map = NULL, + .setup_apic_routing = NULL, + .cpu_present_to_apicid = default_cpu_present_to_apicid, + .apicid_to_cpu_present = NULL, + .check_phys_apicid_present = default_check_phys_apicid_present, + .phys_pkg_id = numachip_phys_pkg_id, + + .get_apic_id = numachip2_get_apic_id, + .set_apic_id = numachip2_set_apic_id, + .apic_id_mask = 0xffU << 24, + + .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, + + .send_IPI_mask = numachip_send_IPI_mask, + .send_IPI_mask_allbutself = numachip_send_IPI_mask_allbutself, + .send_IPI_allbutself = numachip_send_IPI_allbutself, + .send_IPI_all = numachip_send_IPI_all, + .send_IPI_self = numachip_send_IPI_self, + + .wakeup_secondary_cpu = numachip_wakeup_secondary, + .inquire_remote_apic = NULL, /* REMRD not supported */ + + .read = native_apic_mem_read, + .write = native_apic_mem_write, + .eoi_write = native_apic_mem_write, + .icr_read = native_apic_icr_read, + .icr_write = native_apic_icr_write, + .wait_icr_idle = native_apic_wait_icr_idle, + .safe_wait_icr_idle = native_safe_apic_wait_icr_idle, +}; + +apic_driver(apic_numachip2); -- cgit v1.2.3 From ad03a9c25d258641556c7198e26fd882c741987a Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Mon, 21 Sep 2015 01:02:01 +0800 Subject: x86/numachip: Add Numachip IPI optimisations When sending IPIs, first check if the non-local part of the source and destination APIC IDs match; if so, send via the local APIC for efficiency. Secondly, since the AMD BIOS-kernel developer guide states IPI delivery will occur invarient of prior deliver status, avoid polling the delivery status bit for efficiency. Signed-off-by: Daniel J Blueman Acked-by: Steffen Persvold Cc: Daniel Lezcano Link: http://lkml.kernel.org/r/1442768522-19217-3-git-send-email-daniel@numascale.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/numachip/numachip_csr.h | 1 + arch/x86/kernel/apic/apic_numachip.c | 37 ++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/numachip/numachip_csr.h b/arch/x86/include/asm/numachip/numachip_csr.h index e08b803f8491..e09d845ce406 100644 --- a/arch/x86/include/asm/numachip/numachip_csr.h +++ b/arch/x86/include/asm/numachip/numachip_csr.h @@ -34,6 +34,7 @@ #define NUMACHIP_LCSR_BASE 0x3ffffe000000ULL #define NUMACHIP_LCSR_LIM 0x3fffffffffffULL #define NUMACHIP_LCSR_SIZE (NUMACHIP_LCSR_LIM - NUMACHIP_LCSR_BASE + 1) +#define NUMACHIP_LAPIC_BITS 8 static inline void *lcsr_address(unsigned long offset) { diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index 3cb929481d46..38dd5efdd04c 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -96,9 +96,25 @@ static int numachip_wakeup_secondary(int phys_apicid, unsigned long start_rip) static void numachip_send_IPI_one(int cpu, int vector) { - int apicid = per_cpu(x86_cpu_to_apicid, cpu); + int local_apicid, apicid = per_cpu(x86_cpu_to_apicid, cpu); unsigned int dmode; + preempt_disable(); + local_apicid = __this_cpu_read(x86_cpu_to_apicid); + + /* Send via local APIC where non-local part matches */ + if (!((apicid ^ local_apicid) >> NUMACHIP_LAPIC_BITS)) { + unsigned long flags; + + local_irq_save(flags); + __default_send_IPI_dest_field(apicid, vector, + APIC_DEST_PHYSICAL); + local_irq_restore(flags); + preempt_enable(); + return; + } + preempt_enable(); + dmode = (vector == NMI_VECTOR) ? APIC_DM_NMI : APIC_DM_FIXED; numachip_apic_icr_write(apicid, dmode | vector); } @@ -218,6 +234,17 @@ static int numachip2_acpi_madt_oem_check(char *oem_id, char *oem_table_id) return 1; } +/* APIC IPIs are queued */ +static void numachip_apic_wait_icr_idle(void) +{ +} + +/* APIC NMI IPIs are queued */ +static u32 numachip_safe_apic_wait_icr_idle(void) +{ + return 0; +} + static const struct apic apic_numachip1 __refconst = { .name = "NumaConnect system", .probe = numachip1_probe, @@ -263,8 +290,8 @@ static const struct apic apic_numachip1 __refconst = { .eoi_write = native_apic_mem_write, .icr_read = native_apic_icr_read, .icr_write = native_apic_icr_write, - .wait_icr_idle = native_apic_wait_icr_idle, - .safe_wait_icr_idle = native_safe_apic_wait_icr_idle, + .wait_icr_idle = numachip_apic_wait_icr_idle, + .safe_wait_icr_idle = numachip_safe_apic_wait_icr_idle, }; apic_driver(apic_numachip1); @@ -314,8 +341,8 @@ static const struct apic apic_numachip2 __refconst = { .eoi_write = native_apic_mem_write, .icr_read = native_apic_icr_read, .icr_write = native_apic_icr_write, - .wait_icr_idle = native_apic_wait_icr_idle, - .safe_wait_icr_idle = native_safe_apic_wait_icr_idle, + .wait_icr_idle = numachip_apic_wait_icr_idle, + .safe_wait_icr_idle = numachip_safe_apic_wait_icr_idle, }; apic_driver(apic_numachip2); -- cgit v1.2.3 From ce2e572cfe7b2fc3f0e9da4aa7bc61a2c2c51fc7 Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Mon, 21 Sep 2015 18:02:25 +0800 Subject: x86/numachip: Introduce Numachip2 timer mechanisms Add 1GHz 64-bit Numachip2 clocksource timer support for accurate system-wide timekeeping, as core TSCs are unsynchronised. Additionally, add a per-core clockevent mechanism that interrupts via the platform IPI vector after a programmed period. [ tglx: Taking it through x86 due to dependencies ] Signed-off-by: Daniel J Blueman Acked-by: Steffen Persvold Cc: Daniel Lezcano Link: http://lkml.kernel.org/r/1442829745-29311-1-git-send-email-daniel@numascale.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/numachip/numachip_csr.h | 9 +++ drivers/clocksource/Makefile | 1 + drivers/clocksource/numachip.c | 95 ++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 drivers/clocksource/numachip.c diff --git a/arch/x86/include/asm/numachip/numachip_csr.h b/arch/x86/include/asm/numachip/numachip_csr.h index e09d845ce406..29719eecdc2e 100644 --- a/arch/x86/include/asm/numachip/numachip_csr.h +++ b/arch/x86/include/asm/numachip/numachip_csr.h @@ -59,6 +59,10 @@ static inline void write_lcsr(unsigned long offset, unsigned int val) #define NUMACHIP2_LCSR_BASE 0xf0000000UL #define NUMACHIP2_LCSR_SIZE 0x1000000UL #define NUMACHIP2_APIC_ICR 0x100000 +#define NUMACHIP2_TIMER_DEADLINE 0x200000 +#define NUMACHIP2_TIMER_INT 0x200008 +#define NUMACHIP2_TIMER_NOW 0x200018 +#define NUMACHIP2_TIMER_RESET 0x200020 static inline void __iomem *numachip2_lcsr_address(unsigned long offset) { @@ -86,4 +90,9 @@ static inline void numachip2_write64_lcsr(unsigned long offset, u64 val) writeq(val, numachip2_lcsr_address(offset)); } +static inline unsigned int numachip2_timer(void) +{ + return (smp_processor_id() % 48) << 6; +} + #endif /* _ASM_X86_NUMACHIP_NUMACHIP_CSR_H */ diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 5c00863c3e33..57dfad312341 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -62,3 +62,4 @@ obj-$(CONFIG_H8300) += h8300_timer8.o obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o obj-$(CONFIG_H8300_TPU) += h8300_tpu.o obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o +obj-$(CONFIG_X86_NUMACHIP) += numachip.o diff --git a/drivers/clocksource/numachip.c b/drivers/clocksource/numachip.c new file mode 100644 index 000000000000..088e5fac8b3f --- /dev/null +++ b/drivers/clocksource/numachip.c @@ -0,0 +1,95 @@ +/* + * + * Copyright (C) 2015 Numascale AS. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include + +#include +#include +#include + +static DEFINE_PER_CPU(struct clock_event_device, cpu_ced); + +static cycles_t numachip2_timer_read(struct clocksource *cs) +{ + return numachip2_read64_lcsr(NUMACHIP2_TIMER_NOW); +} + +static struct clocksource numachip2_clocksource = { + .name = "numachip2", + .rating = 295, + .read = numachip2_timer_read, + .mask = CLOCKSOURCE_MASK(64), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + .mult = 1, + .shift = 0, +}; + +static int numachip2_set_next_event(unsigned long delta, struct clock_event_device *ced) +{ + numachip2_write64_lcsr(NUMACHIP2_TIMER_DEADLINE + numachip2_timer(), + delta); + return 0; +} + +static struct clock_event_device numachip2_clockevent = { + .name = "numachip2", + .rating = 400, + .set_next_event = numachip2_set_next_event, + .features = CLOCK_EVT_FEAT_ONESHOT, + .mult = 1, + .shift = 0, + .min_delta_ns = 1250, + .max_delta_ns = LONG_MAX, +}; + +static void numachip_timer_interrupt(void) +{ + struct clock_event_device *ced = this_cpu_ptr(&cpu_ced); + + ced->event_handler(ced); +} + +static __init void numachip_timer_each(struct work_struct *work) +{ + unsigned local_apicid = __this_cpu_read(x86_cpu_to_apicid) & 0xff; + struct clock_event_device *ced = this_cpu_ptr(&cpu_ced); + + /* Setup IPI vector to local core and relative timing mode */ + numachip2_write64_lcsr(NUMACHIP2_TIMER_INT + numachip2_timer(), + (3 << 22) | (X86_PLATFORM_IPI_VECTOR << 14) | + (local_apicid << 6)); + + *ced = numachip2_clockevent; + ced->cpumask = cpumask_of(smp_processor_id()); + clockevents_register_device(ced); +} + +static int __init numachip_timer_init(void) +{ + if (numachip_system != 2) + return -ENODEV; + + /* Reset timer */ + numachip2_write64_lcsr(NUMACHIP2_TIMER_RESET, 0); + clocksource_register_hz(&numachip2_clocksource, NSEC_PER_SEC); + + /* Setup per-cpu clockevents */ + x86_platform_ipi_callback = numachip_timer_interrupt; + schedule_on_each_cpu(&numachip_timer_each); + + return 0; +} + +arch_initcall(numachip_timer_init); -- cgit v1.2.3 From ef34cc3428a716f86ee72aa5a37fa6c0025e4363 Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Wed, 23 Sep 2015 09:38:13 +0800 Subject: x86/numachip: Fix timer build conflict Fix Numachip build conflict from: ce2e572 x86/numachip: Introduce Numachip2 timer mechanisms drivers/built-in.o:(.discard+0x1b): multiple definition of `__pcpu_unique_cpu_ced' arch/x86/built-in.o:(.discard+0xa0da): first defined here Ensure cpu_ced is unique by prefixing with 'numachip2'. Signed-off-by: Daniel J Blueman Cc: Cc: Cc: Steffen Persvold Signed-off-by: Thomas Gleixner --- drivers/clocksource/numachip.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clocksource/numachip.c b/drivers/clocksource/numachip.c index 088e5fac8b3f..4e0f11fd2617 100644 --- a/drivers/clocksource/numachip.c +++ b/drivers/clocksource/numachip.c @@ -19,7 +19,7 @@ #include #include -static DEFINE_PER_CPU(struct clock_event_device, cpu_ced); +static DEFINE_PER_CPU(struct clock_event_device, numachip2_ced); static cycles_t numachip2_timer_read(struct clocksource *cs) { @@ -56,7 +56,7 @@ static struct clock_event_device numachip2_clockevent = { static void numachip_timer_interrupt(void) { - struct clock_event_device *ced = this_cpu_ptr(&cpu_ced); + struct clock_event_device *ced = this_cpu_ptr(&numachip2_ced); ced->event_handler(ced); } @@ -64,7 +64,7 @@ static void numachip_timer_interrupt(void) static __init void numachip_timer_each(struct work_struct *work) { unsigned local_apicid = __this_cpu_read(x86_cpu_to_apicid) & 0xff; - struct clock_event_device *ced = this_cpu_ptr(&cpu_ced); + struct clock_event_device *ced = this_cpu_ptr(&numachip2_ced); /* Setup IPI vector to local core and relative timing mode */ numachip2_write64_lcsr(NUMACHIP2_TIMER_INT + numachip2_timer(), -- cgit v1.2.3 From d786ad32c305ca0f6be1924558866fe9f901e291 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 29 Sep 2015 22:37:02 +0200 Subject: x86/apic: Deinline various functions __x2apic_disable: 178 bytes, 3 calls __x2apic_enable: 117 bytes, 3 calls __smp_spurious_interrupt: 110 bytes, 2 calls __smp_error_interrupt: 208 bytes, 2 calls Reduces code size by about 850 bytes. Signed-off-by: Denys Vlasenko Cc: Borislav Petkov Cc: Andy Lutomirski Link: http://lkml.kernel.org/r/1443559022-23793-1-git-send-email-dvlasenk@redhat.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/apic.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 24e94ce454e2..2f69e3b184f6 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1431,7 +1431,7 @@ enum { }; static int x2apic_state; -static inline void __x2apic_disable(void) +static void __x2apic_disable(void) { u64 msr; @@ -1447,7 +1447,7 @@ static inline void __x2apic_disable(void) printk_once(KERN_INFO "x2apic disabled\n"); } -static inline void __x2apic_enable(void) +static void __x2apic_enable(void) { u64 msr; @@ -1807,7 +1807,7 @@ int apic_version[MAX_LOCAL_APIC]; /* * This interrupt should _never_ happen with our APIC/SMP architecture */ -static inline void __smp_spurious_interrupt(u8 vector) +static void __smp_spurious_interrupt(u8 vector) { u32 v; @@ -1848,7 +1848,7 @@ __visible void smp_trace_spurious_interrupt(struct pt_regs *regs) /* * This interrupt should never happen with our APIC/SMP architecture */ -static inline void __smp_error_interrupt(struct pt_regs *regs) +static void __smp_error_interrupt(struct pt_regs *regs) { u32 v; u32 i = 0; -- cgit v1.2.3 From e02ae3871355194a61b03a07d96fd71e81d7eff9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 28 Sep 2015 12:26:31 +0200 Subject: x86/x2apic: Make stub functions available even if !CONFIG_X86_LOCAL_APIC Some CONFIG_X86_X2APIC functions, especially x2apic_enabled(), are not declared if !CONFIG_X86_LOCAL_APIC. However, the same stubs that work for !CONFIG_X86_X2APIC are okay even if there is no local APIC support at all. Avoid the introduction of #ifdefs by moving the x2apic declarations completely outside the CONFIG_X86_LOCAL_APIC block. (Unfortunately, diff generation messes up the actual change that this patch makes). There is no semantic change because CONFIG_X86_X2APIC depends on CONFIG_X86_LOCAL_APIC. Reported-by: Fengguang Wu Signed-off-by: Paolo Bonzini Cc: Feng Wu Link: http://lkml.kernel.org/r/1443435991-35750-1-git-send-email-pbonzini@redhat.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/apic.h | 110 ++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index ebf6d5e5668c..a30316bf801a 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -115,6 +115,59 @@ static inline bool apic_is_x2apic_enabled(void) return msr & X2APIC_ENABLE; } +extern void enable_IR_x2apic(void); + +extern int get_physical_broadcast(void); + +extern int lapic_get_maxlvt(void); +extern void clear_local_APIC(void); +extern void disconnect_bsp_APIC(int virt_wire_setup); +extern void disable_local_APIC(void); +extern void lapic_shutdown(void); +extern void sync_Arb_IDs(void); +extern void init_bsp_APIC(void); +extern void setup_local_APIC(void); +extern void init_apic_mappings(void); +void register_lapic_address(unsigned long address); +extern void setup_boot_APIC_clock(void); +extern void setup_secondary_APIC_clock(void); +extern int APIC_init_uniprocessor(void); + +#ifdef CONFIG_X86_64 +static inline int apic_force_enable(unsigned long addr) +{ + return -1; +} +#else +extern int apic_force_enable(unsigned long addr); +#endif + +extern int apic_bsp_setup(bool upmode); +extern void apic_ap_setup(void); + +/* + * On 32bit this is mach-xxx local + */ +#ifdef CONFIG_X86_64 +extern int apic_is_clustered_box(void); +#else +static inline int apic_is_clustered_box(void) +{ + return 0; +} +#endif + +extern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask); + +#else /* !CONFIG_X86_LOCAL_APIC */ +static inline void lapic_shutdown(void) { } +#define local_apic_timer_c2_ok 1 +static inline void init_apic_mappings(void) { } +static inline void disable_local_APIC(void) { } +# define setup_boot_APIC_clock x86_init_noop +# define setup_secondary_APIC_clock x86_init_noop +#endif /* !CONFIG_X86_LOCAL_APIC */ + #ifdef CONFIG_X86_X2APIC /* * Make previous memory operations globally visible before @@ -186,67 +239,14 @@ static inline int x2apic_enabled(void) } #define x2apic_supported() (cpu_has_x2apic) -#else +#else /* !CONFIG_X86_X2APIC */ static inline void check_x2apic(void) { } static inline void x2apic_setup(void) { } static inline int x2apic_enabled(void) { return 0; } #define x2apic_mode (0) #define x2apic_supported() (0) -#endif - -extern void enable_IR_x2apic(void); - -extern int get_physical_broadcast(void); - -extern int lapic_get_maxlvt(void); -extern void clear_local_APIC(void); -extern void disconnect_bsp_APIC(int virt_wire_setup); -extern void disable_local_APIC(void); -extern void lapic_shutdown(void); -extern void sync_Arb_IDs(void); -extern void init_bsp_APIC(void); -extern void setup_local_APIC(void); -extern void init_apic_mappings(void); -void register_lapic_address(unsigned long address); -extern void setup_boot_APIC_clock(void); -extern void setup_secondary_APIC_clock(void); -extern int APIC_init_uniprocessor(void); - -#ifdef CONFIG_X86_64 -static inline int apic_force_enable(unsigned long addr) -{ - return -1; -} -#else -extern int apic_force_enable(unsigned long addr); -#endif - -extern int apic_bsp_setup(bool upmode); -extern void apic_ap_setup(void); - -/* - * On 32bit this is mach-xxx local - */ -#ifdef CONFIG_X86_64 -extern int apic_is_clustered_box(void); -#else -static inline int apic_is_clustered_box(void) -{ - return 0; -} -#endif - -extern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask); - -#else /* !CONFIG_X86_LOCAL_APIC */ -static inline void lapic_shutdown(void) { } -#define local_apic_timer_c2_ok 1 -static inline void init_apic_mappings(void) { } -static inline void disable_local_APIC(void) { } -# define setup_boot_APIC_clock x86_init_noop -# define setup_secondary_APIC_clock x86_init_noop -#endif /* !CONFIG_X86_LOCAL_APIC */ +#endif /* !CONFIG_X86_X2APIC */ #ifdef CONFIG_X86_64 #define SET_APIC_ID(x) (apic->set_apic_id(x)) -- cgit v1.2.3 From a7e705af524d165fe7bc303aee82225c66734885 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Thu, 1 Oct 2015 10:55:29 +0800 Subject: x86/irq: Drop unlikely before IS_ERR_OR_NULL IS_ERR_OR_NULL already contain an unlikely compiler flag. Drop it. Signed-off-by: Geliang Tang Cc: Brian Gerst Cc: Andy Lutomirski Link: http://lkml.kernel.org/r/03d18502ed7ed417f136c091f417d2d88c147ec6.1443667610.git.geliangtang@163.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/irq_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index c767cf2bc80a..206d0b90a3ab 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -72,7 +72,7 @@ bool handle_irq(struct irq_desc *desc, struct pt_regs *regs) { stack_overflow_check(regs); - if (unlikely(IS_ERR_OR_NULL(desc))) + if (IS_ERR_OR_NULL(desc)) return false; generic_handle_irq_desc(desc); -- cgit v1.2.3 From 4faefda97bc1be6ca909ba0fd0927ea78f37f67e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 9 Oct 2015 17:24:45 +0300 Subject: x86/io_apic: Make eoi_ioapic_pin() static We have to define internally used function as static, otherwise the following warning will be generated: arch/x86/kernel/apic/io_apic.c:532:6: warning: no previous prototype for 'eoi_ioapic_pin' [-Wmissing-prototypes] Signed-off-by: Andy Shevchenko Reviewed-by: Jiang Liu Link: http://lkml.kernel.org/r/1444400685-98611-1-git-send-email-andriy.shevchenko@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/io_apic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 5c60bb162622..b5a0e3c5e930 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -529,7 +529,7 @@ static void __eoi_ioapic_pin(int apic, int pin, int vector) } } -void eoi_ioapic_pin(int vector, struct mp_chip_data *data) +static void eoi_ioapic_pin(int vector, struct mp_chip_data *data) { unsigned long flags; struct irq_pin_list *entry; -- cgit v1.2.3