* [PATCH 1/4] x86: Cleanup Numachip support
@ 2015-09-20 17:01 Daniel J Blueman
2015-09-20 17:02 ` [PATCH 2/4] x86: Add Numachip2 APIC support Daniel J Blueman
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Daniel J Blueman @ 2015-09-20 17:01 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin
Cc: Daniel J Blueman, x86, linux-kernel, Daniel Lezcano, Steffen Persvold
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 <daniel@numascale.com>
Acked-by: Steffen Persvold <sp@numascale.com>
---
arch/x86/include/asm/numachip/numachip_csr.h | 118 +--------------------------
arch/x86/kernel/apic/apic_numachip.c | 103 ++++++++++-------------
2 files changed, 43 insertions(+), 178 deletions(-)
diff --git a/arch/x86/include/asm/numachip/numachip_csr.h b/arch/x86/include/asm/numachip/numachip_csr.h
index 660f843..7469b13 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 <linux/numa.h>
-#include <linux/percpu.h>
#include <linux/io.h>
-#include <linux/swab.h>
-#include <asm/types.h>
-#include <asm/processor.h>
#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 b548fd3..8729249 100644
--- a/arch/x86/kernel/apic/apic_numachip.c
+++ b/arch/x86/kernel/apic/apic_numachip.c
@@ -11,30 +11,20 @@
*
*/
-#include <linux/errno.h>
-#include <linux/threads.h>
-#include <linux/cpumask.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ctype.h>
#include <linux/init.h>
-#include <linux/hardirq.h>
-#include <linux/delay.h>
#include <asm/numachip/numachip.h>
#include <asm/numachip/numachip_csr.h>
-#include <asm/smp.h>
-#include <asm/apic.h>
#include <asm/ipi.h>
#include <asm/apic_flat_64.h>
#include <asm/pgtable.h>
+#include <asm/pci_x86.h>
-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 +124,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 +147,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 +200,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 +223,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);
--
2.5.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/4] x86: Add Numachip2 APIC support
2015-09-20 17:01 [PATCH 1/4] x86: Cleanup Numachip support Daniel J Blueman
@ 2015-09-20 17:02 ` Daniel J Blueman
2015-09-22 20:33 ` [tip:x86/apic] x86/numachip: " tip-bot for Daniel J Blueman
2015-09-20 17:02 ` [PATCH 3/4] x86: Add Numachip IPI optimisations Daniel J Blueman
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Daniel J Blueman @ 2015-09-20 17:02 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin
Cc: Daniel J Blueman, x86, linux-kernel, Daniel Lezcano, Steffen Persvold
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 <daniel@numascale.com>
Acked-by: Steffen Persvold <sp@numascale.com>
---
arch/x86/include/asm/numachip/numachip.h | 1 +
arch/x86/include/asm/numachip/numachip_csr.h | 34 ++++++++++
arch/x86/kernel/apic/apic_numachip.c | 93 ++++++++++++++++++++++++++++
3 files changed, 128 insertions(+)
diff --git a/arch/x86/include/asm/numachip/numachip.h b/arch/x86/include/asm/numachip/numachip.h
index 1c6f7f6..c64373a 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 7469b13..c7efc25 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 <linux/smp.h>
#include <linux/io.h>
#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 8729249..dfe2b1c 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);
@@ -129,6 +148,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;
@@ -154,6 +178,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;
}
@@ -175,6 +206,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,
@@ -225,3 +267,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);
--
2.5.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/4] x86: Add Numachip IPI optimisations
2015-09-20 17:01 [PATCH 1/4] x86: Cleanup Numachip support Daniel J Blueman
2015-09-20 17:02 ` [PATCH 2/4] x86: Add Numachip2 APIC support Daniel J Blueman
@ 2015-09-20 17:02 ` Daniel J Blueman
2015-09-22 20:34 ` [tip:x86/apic] x86/numachip: " tip-bot for Daniel J Blueman
2015-09-20 17:02 ` [PATCH 4/4] x86: Introduce Numachip2 timer mechanisms Daniel J Blueman
2015-09-22 20:33 ` [tip:x86/apic] x86/numachip: Cleanup Numachip support tip-bot for Daniel J Blueman
3 siblings, 1 reply; 9+ messages in thread
From: Daniel J Blueman @ 2015-09-20 17:02 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin
Cc: Daniel J Blueman, x86, linux-kernel, Daniel Lezcano, Steffen Persvold
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 <daniel@numascale.com>
Acked-by: Steffen Persvold <sp@numascale.com>
---
arch/x86/include/asm/numachip/numachip_csr.h | 1 +
arch/x86/kernel/apic/apic_numachip.c | 36 ++++++++++++++++++++++++----
2 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/arch/x86/include/asm/numachip/numachip_csr.h b/arch/x86/include/asm/numachip/numachip_csr.h
index c7efc25..75379f6 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 dfe2b1c..81bc216 100644
--- a/arch/x86/kernel/apic/apic_numachip.c
+++ b/arch/x86/kernel/apic/apic_numachip.c
@@ -95,9 +95,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);
}
@@ -217,6 +232,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,
@@ -262,8 +288,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);
@@ -313,8 +339,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);
--
2.5.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/4] x86: Introduce Numachip2 timer mechanisms
2015-09-20 17:01 [PATCH 1/4] x86: Cleanup Numachip support Daniel J Blueman
2015-09-20 17:02 ` [PATCH 2/4] x86: Add Numachip2 APIC support Daniel J Blueman
2015-09-20 17:02 ` [PATCH 3/4] x86: Add Numachip IPI optimisations Daniel J Blueman
@ 2015-09-20 17:02 ` Daniel J Blueman
2015-09-21 10:02 ` [PATCH v2] " Daniel J Blueman
2015-09-22 20:33 ` [tip:x86/apic] x86/numachip: Cleanup Numachip support tip-bot for Daniel J Blueman
3 siblings, 1 reply; 9+ messages in thread
From: Daniel J Blueman @ 2015-09-20 17:02 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin
Cc: Daniel J Blueman, x86, linux-kernel, Daniel Lezcano, Steffen Persvold
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.
Signed-off-by: Daniel J Blueman <daniel@numascale.com>
Acked-by: Steffen Persvold <sp@numascale.com>
---
arch/x86/include/asm/numachip/numachip_csr.h | 9 +++++++++
drivers/clocksource/Makefile | 1 +
2 files changed, 10 insertions(+)
diff --git a/arch/x86/include/asm/numachip/numachip_csr.h b/arch/x86/include/asm/numachip/numachip_csr.h
index e09d845..29719ee 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 5c00863..57dfad3 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 0000000..5e4f90e
--- /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 <linux/clockchips.h>
+
+#include <asm/irq.h>
+#include <asm/numachip/numachip.h>
+#include <asm/numachip/numachip_csr.h>
+
+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(),
+ | (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);
--
2.5.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2] x86: Introduce Numachip2 timer mechanisms
2015-09-20 17:02 ` [PATCH 4/4] x86: Introduce Numachip2 timer mechanisms Daniel J Blueman
@ 2015-09-21 10:02 ` Daniel J Blueman
2015-09-22 20:34 ` [tip:x86/apic] x86/numachip: " tip-bot for Daniel J Blueman
0 siblings, 1 reply; 9+ messages in thread
From: Daniel J Blueman @ 2015-09-21 10:02 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin
Cc: Daniel J Blueman, x86, linux-kernel, Daniel Lezcano
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.
v2: Fix whitespace and wrapping issue
Signed-off-by: Daniel J Blueman <daniel@numascale.com>
Acked-by: Steffen Persvold <sp@numascale.com>
---
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 e09d845..29719ee 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 5c00863..57dfad3 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 0000000..088e5fa
--- /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 <linux/clockchips.h>
+
+#include <asm/irq.h>
+#include <asm/numachip/numachip.h>
+#include <asm/numachip/numachip_csr.h>
+
+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);
--
2.5.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [tip:x86/apic] x86/numachip: Cleanup Numachip support
2015-09-20 17:01 [PATCH 1/4] x86: Cleanup Numachip support Daniel J Blueman
` (2 preceding siblings ...)
2015-09-20 17:02 ` [PATCH 4/4] x86: Introduce Numachip2 timer mechanisms Daniel J Blueman
@ 2015-09-22 20:33 ` tip-bot for Daniel J Blueman
3 siblings, 0 replies; 9+ messages in thread
From: tip-bot for Daniel J Blueman @ 2015-09-22 20:33 UTC (permalink / raw)
To: linux-tip-commits
Cc: daniel, mingo, daniel.lezcano, sp, linux-kernel, tglx, hpa
Commit-ID: db1003a719d75cebe5843a7906c02c29bec9922c
Gitweb: http://git.kernel.org/tip/db1003a719d75cebe5843a7906c02c29bec9922c
Author: Daniel J Blueman <daniel@numascale.com>
AuthorDate: Mon, 21 Sep 2015 01:01:59 +0800
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 22 Sep 2015 22:25:32 +0200
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 <daniel@numascale.com>
Acked-by: Steffen Persvold <sp@numascale.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: http://lkml.kernel.org/r/1442768522-19217-1-git-send-email-daniel@numascale.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
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 660f843..7469b13 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 <linux/numa.h>
-#include <linux/percpu.h>
#include <linux/io.h>
-#include <linux/swab.h>
-#include <asm/types.h>
-#include <asm/processor.h>
#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 b548fd3..eeefbb1 100644
--- a/arch/x86/kernel/apic/apic_numachip.c
+++ b/arch/x86/kernel/apic/apic_numachip.c
@@ -11,30 +11,20 @@
*
*/
-#include <linux/errno.h>
-#include <linux/threads.h>
-#include <linux/cpumask.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ctype.h>
#include <linux/init.h>
-#include <linux/hardirq.h>
-#include <linux/delay.h>
#include <asm/numachip/numachip.h>
#include <asm/numachip/numachip_csr.h>
-#include <asm/smp.h>
-#include <asm/apic.h>
#include <asm/ipi.h>
#include <asm/apic_flat_64.h>
#include <asm/pgtable.h>
+#include <asm/pci_x86.h>
-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);
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [tip:x86/apic] x86/numachip: Add Numachip2 APIC support
2015-09-20 17:02 ` [PATCH 2/4] x86: Add Numachip2 APIC support Daniel J Blueman
@ 2015-09-22 20:33 ` tip-bot for Daniel J Blueman
0 siblings, 0 replies; 9+ messages in thread
From: tip-bot for Daniel J Blueman @ 2015-09-22 20:33 UTC (permalink / raw)
To: linux-tip-commits
Cc: tglx, daniel, linux-kernel, hpa, sp, mingo, daniel.lezcano
Commit-ID: d9d4dee6cedfa17e5eedcba242dca3091bf73bc3
Gitweb: http://git.kernel.org/tip/d9d4dee6cedfa17e5eedcba242dca3091bf73bc3
Author: Daniel J Blueman <daniel@numascale.com>
AuthorDate: Mon, 21 Sep 2015 01:02:00 +0800
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 22 Sep 2015 22:25:33 +0200
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 <daniel@numascale.com>
Acked-by: Steffen Persvold <sp@numascale.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: http://lkml.kernel.org/r/1442768522-19217-2-git-send-email-daniel@numascale.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
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 1c6f7f6..c64373a 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 7469b13..e08b803 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 <linux/smp.h>
#include <linux/io.h>
#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 eeefbb1..3cb9294 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);
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [tip:x86/apic] x86/numachip: Add Numachip IPI optimisations
2015-09-20 17:02 ` [PATCH 3/4] x86: Add Numachip IPI optimisations Daniel J Blueman
@ 2015-09-22 20:34 ` tip-bot for Daniel J Blueman
0 siblings, 0 replies; 9+ messages in thread
From: tip-bot for Daniel J Blueman @ 2015-09-22 20:34 UTC (permalink / raw)
To: linux-tip-commits
Cc: daniel, linux-kernel, mingo, tglx, sp, hpa, daniel.lezcano
Commit-ID: ad03a9c25d258641556c7198e26fd882c741987a
Gitweb: http://git.kernel.org/tip/ad03a9c25d258641556c7198e26fd882c741987a
Author: Daniel J Blueman <daniel@numascale.com>
AuthorDate: Mon, 21 Sep 2015 01:02:01 +0800
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 22 Sep 2015 22:25:33 +0200
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 <daniel@numascale.com>
Acked-by: Steffen Persvold <sp@numascale.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: http://lkml.kernel.org/r/1442768522-19217-3-git-send-email-daniel@numascale.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
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 e08b803..e09d845 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 3cb9294..38dd5ef 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);
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [tip:x86/apic] x86/numachip: Introduce Numachip2 timer mechanisms
2015-09-21 10:02 ` [PATCH v2] " Daniel J Blueman
@ 2015-09-22 20:34 ` tip-bot for Daniel J Blueman
0 siblings, 0 replies; 9+ messages in thread
From: tip-bot for Daniel J Blueman @ 2015-09-22 20:34 UTC (permalink / raw)
To: linux-tip-commits
Cc: daniel, sp, tglx, mingo, linux-kernel, hpa, daniel.lezcano
Commit-ID: ce2e572cfe7b2fc3f0e9da4aa7bc61a2c2c51fc7
Gitweb: http://git.kernel.org/tip/ce2e572cfe7b2fc3f0e9da4aa7bc61a2c2c51fc7
Author: Daniel J Blueman <daniel@numascale.com>
AuthorDate: Mon, 21 Sep 2015 18:02:25 +0800
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitDate: Tue, 22 Sep 2015 22:25:33 +0200
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 <daniel@numascale.com>
Acked-by: Steffen Persvold <sp@numascale.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: http://lkml.kernel.org/r/1442829745-29311-1-git-send-email-daniel@numascale.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/include/asm/numachip/numachip_csr.h | 9 +++
drivers/clocksource/Makefile | 1 +
drivers/clocksource/numachip.c | 95 ++++++++++++++++++++++++++++
3 files changed, 105 insertions(+)
diff --git a/arch/x86/include/asm/numachip/numachip_csr.h b/arch/x86/include/asm/numachip/numachip_csr.h
index e09d845..29719ee 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 5c00863..57dfad3 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 0000000..088e5fa
--- /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 <linux/clockchips.h>
+
+#include <asm/irq.h>
+#include <asm/numachip/numachip.h>
+#include <asm/numachip/numachip_csr.h>
+
+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);
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2015-09-22 20:34 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-20 17:01 [PATCH 1/4] x86: Cleanup Numachip support Daniel J Blueman
2015-09-20 17:02 ` [PATCH 2/4] x86: Add Numachip2 APIC support Daniel J Blueman
2015-09-22 20:33 ` [tip:x86/apic] x86/numachip: " tip-bot for Daniel J Blueman
2015-09-20 17:02 ` [PATCH 3/4] x86: Add Numachip IPI optimisations Daniel J Blueman
2015-09-22 20:34 ` [tip:x86/apic] x86/numachip: " tip-bot for Daniel J Blueman
2015-09-20 17:02 ` [PATCH 4/4] x86: Introduce Numachip2 timer mechanisms Daniel J Blueman
2015-09-21 10:02 ` [PATCH v2] " Daniel J Blueman
2015-09-22 20:34 ` [tip:x86/apic] x86/numachip: " tip-bot for Daniel J Blueman
2015-09-22 20:33 ` [tip:x86/apic] x86/numachip: Cleanup Numachip support tip-bot for Daniel J Blueman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).