[-- Attachment #1: setup-hubless-init --] [-- Type: text/plain, Size: 1643 bytes --] Add more support for UV systems that do not contain a UV Hub (AKA "hubless"). This update adds support for additional functions required: Use PCH NMI handler instead of a UV Hub NMI handler. Initialize the UV BIOS callback interface used to support specific UV functions. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- arch/x86/kernel/apic/x2apic_uv_x.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -1477,6 +1477,20 @@ static void __init build_socket_tables(v } } +/* Initialize UV hubless systems */ +static __init int uv_system_init_hubless(void) +{ + int rc; + + /* Setup PCH NMI handler */ + uv_nmi_setup_hubless(); + + /* Init kernel/BIOS interface */ + rc = uv_bios_init(); + + return rc; +} + static void __init uv_system_init_hub(void) { struct uv_hub_info_s hub_info = {0}; @@ -1616,8 +1630,8 @@ static void __init uv_system_init_hub(vo } /* - * There is a small amount of UV specific code needed to initialize a - * UV system that does not have a "UV HUB" (referred to as "hubless"). + * There is a different code path needed to initialize a UV system that does + * not have a "UV HUB" (referred to as "hubless"). */ void __init uv_system_init(void) { @@ -1627,7 +1641,7 @@ void __init uv_system_init(void) if (is_uv_system()) uv_system_init_hub(); else - uv_nmi_setup_hubless(); + uv_system_init_hubless(); } apic_driver(apic_x2apic_uv_x); --
[-- Attachment #1: setup-hubless-init --] [-- Type: text/plain, Size: 2124 bytes --] Add more support for UV systems that do not contain a UV Hub (AKA "hubless"). This update adds support for additional functions required: Use PCH NMI handler instead of a UV Hub NMI handler. Initialize the UV BIOS callback interface used to support specific UV functions. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> To: Thomas Gleixner <tglx@linutronix.de> To: Ingo Molnar <mingo@redhat.com> To: H. Peter Anvin <hpa@zytor.com> To: Andrew Morton <akpm@linux-foundation.org> To: Borislav Petkov <bp@alien8.de> To: Christoph Hellwig <hch@infradead.org> Cc: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Steve Wahl <steve.wahl@hpe.com> Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org Cc: stable@vger.kernel.org --- arch/x86/kernel/apic/x2apic_uv_x.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -1457,6 +1457,20 @@ static void __init build_socket_tables(v } } +/* Initialize UV hubless systems */ +static __init int uv_system_init_hubless(void) +{ + int rc; + + /* Setup PCH NMI handler */ + uv_nmi_setup_hubless(); + + /* Init kernel/BIOS interface */ + rc = uv_bios_init(); + + return rc; +} + static void __init uv_system_init_hub(void) { struct uv_hub_info_s hub_info = {0}; @@ -1596,8 +1610,8 @@ static void __init uv_system_init_hub(vo } /* - * There is a small amount of UV specific code needed to initialize a - * UV system that does not have a "UV HUB" (referred to as "hubless"). + * There is a different code path needed to initialize a UV system that does + * not have a "UV HUB" (referred to as "hubless"). */ void __init uv_system_init(void) { @@ -1607,7 +1621,7 @@ void __init uv_system_init(void) if (is_uv_system()) uv_system_init_hub(); else - uv_nmi_setup_hubless(); + uv_system_init_hubless(); } apic_driver(apic_x2apic_uv_x); --
These patches support upcoming UV systems that do not have a UV HUB. * Save OEM_ID from ACPI MADT probe * Return UV Hubless System Type * Add return code to UV BIOS Init function * Setup UV functions for Hubless UV Systems * Add UV Hubbed/Hubless Proc FS Files * Decode UVsystab Info * Account for UV Hubless in is_uvX_hub Ops --
[-- Attachment #1: save-oem_id --] [-- Type: text/plain, Size: 2229 bytes --] Save the OEM_ID and OEM_TABLE_ID passed to the apic driver probe function for later use. Also, convert the char list arg passed from the kernel to a true null-terminated string. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> To: Thomas Gleixner <tglx@linutronix.de> To: Ingo Molnar <mingo@redhat.com> To: H. Peter Anvin <hpa@zytor.com> To: Andrew Morton <akpm@linux-foundation.org> To: Borislav Petkov <bp@alien8.de> To: Christoph Hellwig <hch@infradead.org> Cc: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Steve Wahl <steve.wahl@hpe.com> Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org --- arch/x86/kernel/apic/x2apic_uv_x.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -14,6 +14,7 @@ #include <linux/memory.h> #include <linux/export.h> #include <linux/pci.h> +#include <linux/acpi.h> #include <asm/e820/api.h> #include <asm/uv/uv_mmrs.h> @@ -31,6 +32,10 @@ static u64 gru_dist_base, gru_first_no static u64 gru_dist_lmask, gru_dist_umask; static union uvh_apicid uvh_apicid; +/* Unpack OEM/TABLE ID's to be NULL terminated strings */ +static u8 oem_id[ACPI_OEM_ID_SIZE + 1]; +static u8 oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; + /* Information derived from CPUID: */ static struct { unsigned int apicid_shift; @@ -248,11 +253,20 @@ static void __init uv_set_apicid_hibit(v } } -static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static void __init uv_stringify(int len, char *to, char *from) +{ + /* Relies on 'to' being NULL chars so result will be NULL terminated */ + strncpy(to, from, len-1); +} + +static int __init uv_acpi_madt_oem_check(char *_oem_id, char *_oem_table_id) { int pnodeid; int uv_apic; + uv_stringify(sizeof(oem_id), oem_id, _oem_id); + uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id); + if (strncmp(oem_id, "SGI", 3) != 0) { if (strncmp(oem_id, "NSGI", 4) == 0) { uv_hubless_system = true; --
[-- Attachment #1: mod-is_uv_hubless --] [-- Type: text/plain, Size: 3965 bytes --] Return the type of UV hubless system for UV specific code that depends on that. Use a define to indicate the change in arg type for this function in uv.h. Add a function to convert UV system type to bit pattern needed for is_uv_hubless(). Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> To: Thomas Gleixner <tglx@linutronix.de> To: Ingo Molnar <mingo@redhat.com> To: H. Peter Anvin <hpa@zytor.com> To: Andrew Morton <akpm@linux-foundation.org> To: Borislav Petkov <bp@alien8.de> To: Christoph Hellwig <hch@infradead.org> Cc: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Steve Wahl <steve.wahl@hpe.com> Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org --- v2: remove is_uv_hubless define; remove leading '_' from _is_uv_hubless --- arch/x86/include/asm/uv/uv.h | 12 ++++++++++-- arch/x86/kernel/apic/x2apic_uv_x.c | 27 ++++++++++++++++++--------- 2 files changed, 28 insertions(+), 11 deletions(-) --- linux.orig/arch/x86/include/asm/uv/uv.h +++ linux/arch/x86/include/asm/uv/uv.h @@ -12,6 +12,14 @@ struct mm_struct; #ifdef CONFIG_X86_UV #include <linux/efi.h> +static inline int uv(int uvtype) +{ + /* uv(0) is "any" */ + if (uvtype >= 0 && uvtype <= 30) + return 1 << uvtype; + return 1; +} + extern unsigned long uv_systab_phys; extern enum uv_system_type get_uv_system_type(void); @@ -20,7 +28,7 @@ static inline bool is_early_uv_system(vo return uv_systab_phys && uv_systab_phys != EFI_INVALID_TABLE_ADDR; } extern int is_uv_system(void); -extern int is_uv_hubless(void); +extern int is_uv_hubless(int uvtype); extern void uv_cpu_init(void); extern void uv_nmi_init(void); extern void uv_system_init(void); @@ -32,7 +40,7 @@ extern const struct cpumask *uv_flush_tl static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } static inline bool is_early_uv_system(void) { return 0; } static inline int is_uv_system(void) { return 0; } -static inline int is_uv_hubless(void) { return 0; } +static inline int is_uv_hubless(int uv) { return 0; } static inline void uv_cpu_init(void) { } static inline void uv_system_init(void) { } static inline const struct cpumask * --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -26,7 +26,7 @@ static DEFINE_PER_CPU(int, x2apic_extra_bits); static enum uv_system_type uv_system_type; -static bool uv_hubless_system; +static int uv_hubless_system; static u64 gru_start_paddr, gru_end_paddr; static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr; static u64 gru_dist_lmask, gru_dist_umask; @@ -268,11 +268,20 @@ static int __init uv_acpi_madt_oem_check uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id); if (strncmp(oem_id, "SGI", 3) != 0) { - if (strncmp(oem_id, "NSGI", 4) == 0) { - uv_hubless_system = true; - pr_info("UV: OEM IDs %s/%s, HUBLESS\n", - oem_id, oem_table_id); - } + if (strncmp(oem_id, "NSGI", 4) != 0) + return 0; + + /* UV4 Hubless, CH, (0x11:UV4+Any) */ + if (strncmp(oem_id, "NSGI4", 5) == 0) + uv_hubless_system = 0x11; + + /* UV3 Hubless, UV300/MC990X w/o hub (0x9:UV3+Any) */ + else + uv_hubless_system = 0x9; + + pr_info("UV: OEM IDs %s/%s, HUBLESS(0x%x)\n", + oem_id, oem_table_id, uv_hubless_system); + return 0; } @@ -350,9 +359,9 @@ int is_uv_system(void) } EXPORT_SYMBOL_GPL(is_uv_system); -int is_uv_hubless(void) +int is_uv_hubless(int uvtype) { - return uv_hubless_system; + return (uv_hubless_system & uvtype); } EXPORT_SYMBOL_GPL(is_uv_hubless); @@ -1592,7 +1601,7 @@ static void __init uv_system_init_hub(vo */ void __init uv_system_init(void) { - if (likely(!is_uv_system() && !is_uv_hubless())) + if (likely(!is_uv_system() && !is_uv_hubless(1))) return; if (is_uv_system()) --
[-- Attachment #1: add-bios_init-rc --] [-- Type: text/plain, Size: 2356 bytes --] Add a return code to the UV BIOS init function that indicates the successful initialization of the kernel/BIOS callback interface. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> To: Thomas Gleixner <tglx@linutronix.de> To: Ingo Molnar <mingo@redhat.com> To: H. Peter Anvin <hpa@zytor.com> To: Andrew Morton <akpm@linux-foundation.org> To: Borislav Petkov <bp@alien8.de> To: Christoph Hellwig <hch@infradead.org> Cc: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Steve Wahl <steve.wahl@hpe.com> Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org --- arch/x86/include/asm/uv/bios.h | 2 +- arch/x86/platform/uv/bios_uv.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) --- linux.orig/arch/x86/include/asm/uv/bios.h +++ linux/arch/x86/include/asm/uv/bios.h @@ -138,7 +138,7 @@ extern s64 uv_bios_change_memprotect(u64 extern s64 uv_bios_reserved_page_pa(u64, u64 *, u64 *, u64 *); extern int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus); -extern void uv_bios_init(void); +extern int uv_bios_init(void); extern unsigned long sn_rtc_cycles_per_second; extern int uv_type; --- linux.orig/arch/x86/platform/uv/bios_uv.c +++ linux/arch/x86/platform/uv/bios_uv.c @@ -184,20 +184,20 @@ int uv_bios_set_legacy_vga_target(bool d } EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target); -void uv_bios_init(void) +int uv_bios_init(void) { uv_systab = NULL; if ((uv_systab_phys == EFI_INVALID_TABLE_ADDR) || !uv_systab_phys || efi_runtime_disabled()) { pr_crit("UV: UVsystab: missing\n"); - return; + return -EEXIST; } uv_systab = ioremap(uv_systab_phys, sizeof(struct uv_systab)); if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) { pr_err("UV: UVsystab: bad signature!\n"); iounmap(uv_systab); - return; + return -EINVAL; } /* Starting with UV4 the UV systab size is variable */ @@ -208,8 +208,9 @@ void uv_bios_init(void) uv_systab = ioremap(uv_systab_phys, size); if (!uv_systab) { pr_err("UV: UVsystab: ioremap(%d) failed!\n", size); - return; + return -EFAULT; } } pr_info("UV: UVsystab: Revision:%x\n", uv_systab->revision); + return 0; } --
[-- Attachment #1: setup-hubless-init --] [-- Type: text/plain, Size: 2097 bytes --] Add more support for UV systems that do not contain a UV Hub (AKA "hubless"). This update adds support for additional functions required: Use PCH NMI handler instead of a UV Hub NMI handler. Initialize the UV BIOS callback interface used to support specific UV functions. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> To: Thomas Gleixner <tglx@linutronix.de> To: Ingo Molnar <mingo@redhat.com> To: H. Peter Anvin <hpa@zytor.com> To: Andrew Morton <akpm@linux-foundation.org> To: Borislav Petkov <bp@alien8.de> To: Christoph Hellwig <hch@infradead.org> Cc: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Steve Wahl <steve.wahl@hpe.com> Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org --- arch/x86/kernel/apic/x2apic_uv_x.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -1457,6 +1457,20 @@ static void __init build_socket_tables(v } } +/* Initialize UV hubless systems */ +static __init int uv_system_init_hubless(void) +{ + int rc; + + /* Setup PCH NMI handler */ + uv_nmi_setup_hubless(); + + /* Init kernel/BIOS interface */ + rc = uv_bios_init(); + + return rc; +} + static void __init uv_system_init_hub(void) { struct uv_hub_info_s hub_info = {0}; @@ -1596,8 +1610,8 @@ static void __init uv_system_init_hub(vo } /* - * There is a small amount of UV specific code needed to initialize a - * UV system that does not have a "UV HUB" (referred to as "hubless"). + * There is a different code path needed to initialize a UV system that does + * not have a "UV HUB" (referred to as "hubless"). */ void __init uv_system_init(void) { @@ -1607,7 +1621,7 @@ void __init uv_system_init(void) if (is_uv_system()) uv_system_init_hub(); else - uv_nmi_setup_hubless(); + uv_system_init_hubless(); } apic_driver(apic_x2apic_uv_x); --
[-- Attachment #1: add-procfs-files --] [-- Type: text/plain, Size: 5616 bytes --] Indicate to UV user utilities that UV hubless support is available on this system via the existing /proc infterface. The current interface is maintained with the addition of new /proc leaves ("hubbed" and "hubless") that contain the specific type of UV arch this one is. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> To: Thomas Gleixner <tglx@linutronix.de> To: Ingo Molnar <mingo@redhat.com> To: H. Peter Anvin <hpa@zytor.com> To: Andrew Morton <akpm@linux-foundation.org> To: Borislav Petkov <bp@alien8.de> To: Christoph Hellwig <hch@infradead.org> Cc: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Steve Wahl <steve.wahl@hpe.com> Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org --- v2: remove is_uv_hubbed define; remove leading '_' from _is_uv_hubbed --- arch/x86/include/asm/uv/uv.h | 4 + arch/x86/kernel/apic/x2apic_uv_x.c | 93 ++++++++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 1 deletion(-) --- linux.orig/arch/x86/include/asm/uv/uv.h +++ linux/arch/x86/include/asm/uv/uv.h @@ -12,6 +12,8 @@ struct mm_struct; #ifdef CONFIG_X86_UV #include <linux/efi.h> +#define UV_PROC_NODE "sgi_uv" + static inline int uv(int uvtype) { /* uv(0) is "any" */ @@ -28,6 +30,7 @@ static inline bool is_early_uv_system(vo return uv_systab_phys && uv_systab_phys != EFI_INVALID_TABLE_ADDR; } extern int is_uv_system(void); +extern int is_uv_hubbed(int uvtype); extern int is_uv_hubless(int uvtype); extern void uv_cpu_init(void); extern void uv_nmi_init(void); @@ -40,6 +43,7 @@ extern const struct cpumask *uv_flush_tl static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } static inline bool is_early_uv_system(void) { return 0; } static inline int is_uv_system(void) { return 0; } +static inline int is_uv_hubbed(int uv) { return 0; } static inline int is_uv_hubless(int uv) { return 0; } static inline void uv_cpu_init(void) { } static inline void uv_system_init(void) { } --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -26,6 +26,7 @@ static DEFINE_PER_CPU(int, x2apic_extra_bits); static enum uv_system_type uv_system_type; +static int uv_hubbed_system; static int uv_hubless_system; static u64 gru_start_paddr, gru_end_paddr; static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr; @@ -309,6 +310,24 @@ static int __init uv_acpi_madt_oem_check if (uv_hub_info->hub_revision == 0) goto badbios; + switch (uv_hub_info->hub_revision) { + case UV4_HUB_REVISION_BASE: + uv_hubbed_system = 0x11; + break; + + case UV3_HUB_REVISION_BASE: + uv_hubbed_system = 0x9; + break; + + case UV2_HUB_REVISION_BASE: + uv_hubbed_system = 0x5; + break; + + case UV1_HUB_REVISION_BASE: + uv_hubbed_system = 0x3; + break; + } + pnodeid = early_get_pnodeid(); early_get_apic_socketid_shift(); @@ -359,6 +378,12 @@ int is_uv_system(void) } EXPORT_SYMBOL_GPL(is_uv_system); +int is_uv_hubbed(int uvtype) +{ + return (uv_hubbed_system & uvtype); +} +EXPORT_SYMBOL_GPL(is_uv_hubbed); + int is_uv_hubless(int uvtype) { return (uv_hubless_system & uvtype); @@ -1457,6 +1482,68 @@ static void __init build_socket_tables(v } } +/* Setup user proc fs files */ +static int proc_hubbed_show(struct seq_file *file, void *data) +{ + seq_printf(file, "0x%x\n", uv_hubbed_system); + return 0; +} + +static int proc_hubless_show(struct seq_file *file, void *data) +{ + seq_printf(file, "0x%x\n", uv_hubless_system); + return 0; +} + +static int proc_oemid_show(struct seq_file *file, void *data) +{ + seq_printf(file, "%s/%s\n", oem_id, oem_table_id); + return 0; +} + +static int proc_hubbed_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_hubbed_show, (void *)NULL); +} + +static int proc_hubless_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_hubless_show, (void *)NULL); +} + +static int proc_oemid_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_oemid_show, (void *)NULL); +} + +/* (struct is "non-const" as open function is set at runtime) */ +static struct file_operations proc_version_fops = { + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_oemid_fops = { + .open = proc_oemid_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static __init void uv_setup_proc_files(int hubless) +{ + struct proc_dir_entry *pde; + char *name = hubless ? "hubless" : "hubbed"; + + pde = proc_mkdir(UV_PROC_NODE, NULL); + proc_create("oemid", 0, pde, &proc_oemid_fops); + proc_create(name, 0, pde, &proc_version_fops); + if (hubless) + proc_version_fops.open = proc_hubless_open; + else + proc_version_fops.open = proc_hubbed_open; +} + /* Initialize UV hubless systems */ static __init int uv_system_init_hubless(void) { @@ -1468,6 +1555,10 @@ static __init int uv_system_init_hubless /* Init kernel/BIOS interface */ rc = uv_bios_init(); + /* Create user access node if UVsystab available */ + if (rc >= 0) + uv_setup_proc_files(1); + return rc; } @@ -1596,7 +1687,7 @@ static void __init uv_system_init_hub(vo uv_nmi_setup(); uv_cpu_init(); uv_scir_register_cpu_notifier(); - proc_mkdir("sgi_uv", NULL); + uv_setup_proc_files(0); /* Register Legacy VGA I/O redirection handler: */ pci_register_set_vga_state(uv_set_vga_state); --
[-- Attachment #1: decode-hubless-uvst --] [-- Type: text/plain, Size: 1659 bytes --] Decode the hubless UVsystab passed from BIOS to the kernel saving pertinent info in a similar manner that hubbed UVsystabs are decoded. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> To: Thomas Gleixner <tglx@linutronix.de> To: Ingo Molnar <mingo@redhat.com> To: H. Peter Anvin <hpa@zytor.com> To: Andrew Morton <akpm@linux-foundation.org> To: Borislav Petkov <bp@alien8.de> To: Christoph Hellwig <hch@infradead.org> Cc: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Steve Wahl <steve.wahl@hpe.com> Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org --- arch/x86/kernel/apic/x2apic_uv_x.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -1303,7 +1303,8 @@ static int __init decode_uv_systab(void) struct uv_systab *st; int i; - if (uv_hub_info->hub_revision < UV4_HUB_REVISION_BASE) + /* Select only UV4 (hubbed or hubless) and higher */ + if (is_uv_hubbed(-2) < uv(4) && is_uv_hubless(-2) < uv(4)) return 0; /* No extended UVsystab required */ st = uv_systab; @@ -1554,8 +1555,15 @@ static __init int uv_system_init_hubless /* Init kernel/BIOS interface */ rc = uv_bios_init(); + if (rc < 0) + return rc; - /* Create user access node if UVsystab available */ + /* Process UVsystab */ + rc = decode_uv_systab(); + if (rc < 0) + return rc; + + /* Create user access node */ if (rc >= 0) uv_setup_proc_files(1); --
[-- Attachment #1: check-efi-boot --] [-- Type: text/plain, Size: 2032 bytes --] Change to checking for EFI Boot type from previous check on if this is a KDUMP kernel. This allows for KDUMP kernels that can handle EFI reboots. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> To: Thomas Gleixner <tglx@linutronix.de> To: Ingo Molnar <mingo@redhat.com> To: H. Peter Anvin <hpa@zytor.com> To: Andrew Morton <akpm@linux-foundation.org> To: Borislav Petkov <bp@alien8.de> To: Christoph Hellwig <hch@infradead.org> Cc: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Steve Wahl <steve.wahl@hpe.com> Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org --- arch/x86/kernel/apic/x2apic_uv_x.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -15,6 +15,7 @@ #include <linux/export.h> #include <linux/pci.h> #include <linux/acpi.h> +#include <linux/efi.h> #include <asm/e820/api.h> #include <asm/uv/uv_mmrs.h> @@ -1483,6 +1484,14 @@ static void __init build_socket_tables(v } } +/* Check which reboot to use */ +static void check_efi_reboot(void) +{ + /* If EFI reboot not available, use ACPI reboot */ + if (!efi_enabled(EFI_BOOT)) + reboot_type = BOOT_ACPI; +} + /* Setup user proc fs files */ static int proc_hubbed_show(struct seq_file *file, void *data) { @@ -1571,6 +1580,8 @@ static __init int uv_system_init_hubless if (rc >= 0) uv_setup_proc_files(1); + check_efi_reboot(); + return rc; } @@ -1704,12 +1715,7 @@ static void __init uv_system_init_hub(vo /* Register Legacy VGA I/O redirection handler: */ pci_register_set_vga_state(uv_set_vga_state); - /* - * For a kdump kernel the reset must be BOOT_ACPI, not BOOT_EFI, as - * EFI is not enabled in the kdump kernel: - */ - if (is_kdump_kernel()) - reboot_type = BOOT_ACPI; + check_efi_reboot(); } /* --
[-- Attachment #1: mod-is_uvX_hub --] [-- Type: text/plain, Size: 3674 bytes --] The references in the is_uvX_hub() function uses the hub_info pointer which will be NULL when the system is hubless. This change avoids that NULL dereference. It is also an optimization in performance. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> To: Thomas Gleixner <tglx@linutronix.de> To: Ingo Molnar <mingo@redhat.com> To: H. Peter Anvin <hpa@zytor.com> To: Andrew Morton <akpm@linux-foundation.org> To: Borislav Petkov <bp@alien8.de> To: Christoph Hellwig <hch@infradead.org> Cc: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Steve Wahl <steve.wahl@hpe.com> Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org --- v2: Add WARNING that the is UVx supported defines will be removed. --- arch/x86/include/asm/uv/.uv_hub.h.swp |binary arch/x86/include/asm/uv/uv_hub.h | 61 ++++++++++++--------------------------- 1 file changed, 20 insertions(+), 41 deletions(-) Binary files linux.orig/arch/x86/include/asm/uv/.uv_hub.h.swp and linux/arch/x86/include/asm/uv/.uv_hub.h.swp differ --- linux.orig/arch/x86/include/asm/uv/uv_hub.h +++ linux/arch/x86/include/asm/uv/uv_hub.h @@ -19,6 +19,7 @@ #include <linux/topology.h> #include <asm/types.h> #include <asm/percpu.h> +#include <asm/uv/uv.h> #include <asm/uv/uv_mmrs.h> #include <asm/uv/bios.h> #include <asm/irq_vectors.h> @@ -243,83 +244,61 @@ static inline int uv_hub_info_check(int #define UV4_HUB_REVISION_BASE 7 #define UV4A_HUB_REVISION_BASE 8 /* UV4 (fixed) rev 2 */ -#ifdef UV1_HUB_IS_SUPPORTED +/* WARNING: UVx_HUB_IS_SUPPORTED defines are deprecated and will be removed */ static inline int is_uv1_hub(void) { - return uv_hub_info->hub_revision < UV2_HUB_REVISION_BASE; -} +#ifdef UV1_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(1)); #else -static inline int is_uv1_hub(void) -{ return 0; -} #endif +} -#ifdef UV2_HUB_IS_SUPPORTED static inline int is_uv2_hub(void) { - return ((uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE) && - (uv_hub_info->hub_revision < UV3_HUB_REVISION_BASE)); -} +#ifdef UV2_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(2)); #else -static inline int is_uv2_hub(void) -{ return 0; -} #endif +} -#ifdef UV3_HUB_IS_SUPPORTED static inline int is_uv3_hub(void) { - return ((uv_hub_info->hub_revision >= UV3_HUB_REVISION_BASE) && - (uv_hub_info->hub_revision < UV4_HUB_REVISION_BASE)); -} +#ifdef UV3_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(3)); #else -static inline int is_uv3_hub(void) -{ return 0; -} #endif +} /* First test "is UV4A", then "is UV4" */ -#ifdef UV4A_HUB_IS_SUPPORTED -static inline int is_uv4a_hub(void) -{ - return (uv_hub_info->hub_revision >= UV4A_HUB_REVISION_BASE); -} -#else static inline int is_uv4a_hub(void) { +#ifdef UV4A_HUB_IS_SUPPORTED + if (is_uv_hubbed(uv(4))) + return (uv_hub_info->hub_revision == UV4A_HUB_REVISION_BASE); +#endif return 0; } -#endif -#ifdef UV4_HUB_IS_SUPPORTED static inline int is_uv4_hub(void) { - return uv_hub_info->hub_revision >= UV4_HUB_REVISION_BASE; -} +#ifdef UV4_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(4)); #else -static inline int is_uv4_hub(void) -{ return 0; -} #endif +} static inline int is_uvx_hub(void) { - if (uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE) - return uv_hub_info->hub_revision; - - return 0; + return (is_uv_hubbed(-2) >= uv(2)); } static inline int is_uv_hub(void) { -#ifdef UV1_HUB_IS_SUPPORTED - return uv_hub_info->hub_revision; -#endif - return is_uvx_hub(); + return is_uv1_hub() || is_uvx_hub(); } union uvh_apicid { --
Mike,
On Thu, 5 Sep 2019, Mike Travis wrote:
> These patches support upcoming UV systems that do not have a UV HUB.
>
> * Save OEM_ID from ACPI MADT probe
> * Return UV Hubless System Type
> * Add return code to UV BIOS Init function
> * Setup UV functions for Hubless UV Systems
> * Add UV Hubbed/Hubless Proc FS Files
> * Decode UVsystab Info
> * Account for UV Hubless in is_uvX_hub Ops
Can you please in future mark the next version of a patch or patch series
with [PATCH V2 n/M] so its clear that this is something different and also
add a quick summary what changed vs. V1? Adding to each patch which changed
a short change info _after_ the '---' discard line is also good practice
and helps reviewers to figure out which part needs to be looked at.
Thanks
tglx
On 9/5/2019 12:02 PM, Thomas Gleixner wrote:
> Mike,
>
> On Thu, 5 Sep 2019, Mike Travis wrote:
>
>> These patches support upcoming UV systems that do not have a UV HUB.
>>
>> * Save OEM_ID from ACPI MADT probe
>> * Return UV Hubless System Type
>> * Add return code to UV BIOS Init function
>> * Setup UV functions for Hubless UV Systems
>> * Add UV Hubbed/Hubless Proc FS Files
>> * Decode UVsystab Info
>> * Account for UV Hubless in is_uvX_hub Ops
>
> Can you please in future mark the next version of a patch or patch series
> with [PATCH V2 n/M] so its clear that this is something different and also
> add a quick summary what changed vs. V1? Adding to each patch which changed
> a short change info _after_ the '---' discard line is also good practice
> and helps reviewers to figure out which part needs to be looked at.
>
> Thanks
>
> tglx
>
Yeah, I noticed that the V2: tag for the removal that Greg requested was
missing in the copy sent to me. Sorry I didn't catch that earlier.
The "[PATCH V2 n/M]" is something I hadn't been aware but I am now.
Should I resend the patches again with those updates?
Thanks.
On Thu, 5 Sep 2019, Mike Travis wrote:
> On 9/5/2019 12:02 PM, Thomas Gleixner wrote:
> > Mike,
> >
> > On Thu, 5 Sep 2019, Mike Travis wrote:
> >
> > > These patches support upcoming UV systems that do not have a UV HUB.
> > >
> > > * Save OEM_ID from ACPI MADT probe
> > > * Return UV Hubless System Type
> > > * Add return code to UV BIOS Init function
> > > * Setup UV functions for Hubless UV Systems
> > > * Add UV Hubbed/Hubless Proc FS Files
> > > * Decode UVsystab Info
> > > * Account for UV Hubless in is_uvX_hub Ops
> >
> > Can you please in future mark the next version of a patch or patch series
> > with [PATCH V2 n/M] so its clear that this is something different and also
> > add a quick summary what changed vs. V1? Adding to each patch which changed
> > a short change info _after_ the '---' discard line is also good practice
> > and helps reviewers to figure out which part needs to be looked at.
> >
> > Thanks
> >
> > tglx
> >
>
> Yeah, I noticed that the V2: tag for the removal that Greg requested was
> missing in the copy sent to me. Sorry I didn't catch that earlier.
>
> The "[PATCH V2 n/M]" is something I hadn't been aware but I am now.
>
> Should I resend the patches again with those updates?
No, please provide a summary of changes as a reply to the cover letter and
point out which patches were actually changed vs. v1.
Thanks,
tglx
On 9/5/2019 11:47 AM, Mike Travis wrote: > > These patches support upcoming UV systems that do not have a UV HUB. > > [1/8] Save OEM_ID from ACPI MADT probe > > [2/8] Return UV Hubless System Type V2: Remove is_uv_hubless define Remove leading '_' from _is_uv_hubless > [3/8] Add return code to UV BIOS Init function > > [4/8] Setup UV functions for Hubless UV Systems > > [5/8] Add UV Hubbed/Hubless Proc FS Files V2: Remove is_uv_hubbed define Remove leading '_' from _is_uv_hubbed > [6/8] Decode UVsystab Info V2: Removed redundant error message after call to uv_bios_init. Removed redundant error message after call to decode_uv_systab. Clarify selection of UV4 and higher when checking for extended UVsystab in decode_uv_systab(). > [7/8] Check EFI Boot to set reboot type > > [8/8] Account for UV Hubless in is_uvX_hub Ops V2: Add WARNING that the is UVx supported defines will be removed. --
[-- Attachment #1: save-oem_id --] [-- Type: text/plain, Size: 1776 bytes --] Save the OEM_ID and OEM_TABLE_ID passed to the apic driver probe function for later use. Also, convert the char list arg passed from the kernel to a true null-terminated string. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- arch/x86/kernel/apic/x2apic_uv_x.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -14,6 +14,7 @@ #include <linux/memory.h> #include <linux/export.h> #include <linux/pci.h> +#include <linux/acpi.h> #include <asm/e820/api.h> #include <asm/uv/uv_mmrs.h> @@ -31,6 +32,10 @@ static u64 gru_dist_base, gru_first_no static u64 gru_dist_lmask, gru_dist_umask; static union uvh_apicid uvh_apicid; +/* Unpack OEM/TABLE ID's to be NULL terminated strings */ +static u8 oem_id[ACPI_OEM_ID_SIZE + 1]; +static u8 oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; + /* Information derived from CPUID: */ static struct { unsigned int apicid_shift; @@ -248,11 +253,20 @@ static void __init uv_set_apicid_hibit(v } } -static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static void __init uv_stringify(int len, char *to, char *from) +{ + /* Relies on 'to' being NULL chars so result will be NULL terminated */ + strncpy(to, from, len-1); +} + +static int __init uv_acpi_madt_oem_check(char *_oem_id, char *_oem_table_id) { int pnodeid; int uv_apic; + uv_stringify(sizeof(oem_id), oem_id, _oem_id); + uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id); + if (strncmp(oem_id, "SGI", 3) != 0) { if (strncmp(oem_id, "NSGI", 4) == 0) { uv_hubless_system = true; --
[-- Attachment #1: mod-is_uv_hubless --] [-- Type: text/plain, Size: 3439 bytes --] Return the type of UV hubless system for UV specific code that depends on that. Add a function to convert UV system type to bit pattern needed for is_uv_hubless(). Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- V2: Remove is_uv_hubless define Remove leading '_' from _is_uv_hubless --- arch/x86/include/asm/uv/uv.h | 12 ++++++++++-- arch/x86/kernel/apic/x2apic_uv_x.c | 27 ++++++++++++++++++--------- 2 files changed, 28 insertions(+), 11 deletions(-) --- linux.orig/arch/x86/include/asm/uv/uv.h +++ linux/arch/x86/include/asm/uv/uv.h @@ -12,6 +12,14 @@ struct mm_struct; #ifdef CONFIG_X86_UV #include <linux/efi.h> +static inline int uv(int uvtype) +{ + /* uv(0) is "any" */ + if (uvtype >= 0 && uvtype <= 30) + return 1 << uvtype; + return 1; +} + extern unsigned long uv_systab_phys; extern enum uv_system_type get_uv_system_type(void); @@ -20,7 +28,7 @@ static inline bool is_early_uv_system(vo return uv_systab_phys && uv_systab_phys != EFI_INVALID_TABLE_ADDR; } extern int is_uv_system(void); -extern int is_uv_hubless(void); +extern int is_uv_hubless(int uvtype); extern void uv_cpu_init(void); extern void uv_nmi_init(void); extern void uv_system_init(void); @@ -32,7 +40,7 @@ extern const struct cpumask *uv_flush_tl static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } static inline bool is_early_uv_system(void) { return 0; } static inline int is_uv_system(void) { return 0; } -static inline int is_uv_hubless(void) { return 0; } +static inline int is_uv_hubless(int uv) { return 0; } static inline void uv_cpu_init(void) { } static inline void uv_system_init(void) { } static inline const struct cpumask * --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -26,7 +26,7 @@ static DEFINE_PER_CPU(int, x2apic_extra_bits); static enum uv_system_type uv_system_type; -static bool uv_hubless_system; +static int uv_hubless_system; static u64 gru_start_paddr, gru_end_paddr; static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr; static u64 gru_dist_lmask, gru_dist_umask; @@ -268,11 +268,20 @@ static int __init uv_acpi_madt_oem_check uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id); if (strncmp(oem_id, "SGI", 3) != 0) { - if (strncmp(oem_id, "NSGI", 4) == 0) { - uv_hubless_system = true; - pr_info("UV: OEM IDs %s/%s, HUBLESS\n", - oem_id, oem_table_id); - } + if (strncmp(oem_id, "NSGI", 4) != 0) + return 0; + + /* UV4 Hubless, CH, (0x11:UV4+Any) */ + if (strncmp(oem_id, "NSGI4", 5) == 0) + uv_hubless_system = 0x11; + + /* UV3 Hubless, UV300/MC990X w/o hub (0x9:UV3+Any) */ + else + uv_hubless_system = 0x9; + + pr_info("UV: OEM IDs %s/%s, HUBLESS(0x%x)\n", + oem_id, oem_table_id, uv_hubless_system); + return 0; } @@ -350,9 +359,9 @@ int is_uv_system(void) } EXPORT_SYMBOL_GPL(is_uv_system); -int is_uv_hubless(void) +int is_uv_hubless(int uvtype) { - return uv_hubless_system; + return (uv_hubless_system & uvtype); } EXPORT_SYMBOL_GPL(is_uv_hubless); @@ -1592,7 +1601,7 @@ static void __init uv_system_init_hub(vo */ void __init uv_system_init(void) { - if (likely(!is_uv_system() && !is_uv_hubless())) + if (likely(!is_uv_system() && !is_uv_hubless(1))) return; if (is_uv_system()) --
[-- Attachment #1: add-bios_init-rc --] [-- Type: text/plain, Size: 1903 bytes --] Add a return code to the UV BIOS init function that indicates the successful initialization of the kernel/BIOS callback interface. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- arch/x86/include/asm/uv/bios.h | 2 +- arch/x86/platform/uv/bios_uv.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) --- linux.orig/arch/x86/include/asm/uv/bios.h +++ linux/arch/x86/include/asm/uv/bios.h @@ -138,7 +138,7 @@ extern s64 uv_bios_change_memprotect(u64 extern s64 uv_bios_reserved_page_pa(u64, u64 *, u64 *, u64 *); extern int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus); -extern void uv_bios_init(void); +extern int uv_bios_init(void); extern unsigned long sn_rtc_cycles_per_second; extern int uv_type; --- linux.orig/arch/x86/platform/uv/bios_uv.c +++ linux/arch/x86/platform/uv/bios_uv.c @@ -184,20 +184,20 @@ int uv_bios_set_legacy_vga_target(bool d } EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target); -void uv_bios_init(void) +int uv_bios_init(void) { uv_systab = NULL; if ((uv_systab_phys == EFI_INVALID_TABLE_ADDR) || !uv_systab_phys || efi_runtime_disabled()) { pr_crit("UV: UVsystab: missing\n"); - return; + return -EEXIST; } uv_systab = ioremap(uv_systab_phys, sizeof(struct uv_systab)); if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) { pr_err("UV: UVsystab: bad signature!\n"); iounmap(uv_systab); - return; + return -EINVAL; } /* Starting with UV4 the UV systab size is variable */ @@ -208,8 +208,9 @@ void uv_bios_init(void) uv_systab = ioremap(uv_systab_phys, size); if (!uv_systab) { pr_err("UV: UVsystab: ioremap(%d) failed!\n", size); - return; + return -EFAULT; } } pr_info("UV: UVsystab: Revision:%x\n", uv_systab->revision); + return 0; } --
[-- Attachment #1: setup-hubless-init --] [-- Type: text/plain, Size: 1644 bytes --] Add more support for UV systems that do not contain a UV Hub (AKA "hubless"). This update adds support for additional functions required: Use PCH NMI handler instead of a UV Hub NMI handler. Initialize the UV BIOS callback interface used to support specific UV functions. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- arch/x86/kernel/apic/x2apic_uv_x.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -1457,6 +1457,20 @@ static void __init build_socket_tables(v } } +/* Initialize UV hubless systems */ +static __init int uv_system_init_hubless(void) +{ + int rc; + + /* Setup PCH NMI handler */ + uv_nmi_setup_hubless(); + + /* Init kernel/BIOS interface */ + rc = uv_bios_init(); + + return rc; +} + static void __init uv_system_init_hub(void) { struct uv_hub_info_s hub_info = {0}; @@ -1596,8 +1610,8 @@ static void __init uv_system_init_hub(vo } /* - * There is a small amount of UV specific code needed to initialize a - * UV system that does not have a "UV HUB" (referred to as "hubless"). + * There is a different code path needed to initialize a UV system that does + * not have a "UV HUB" (referred to as "hubless"). */ void __init uv_system_init(void) { @@ -1607,7 +1621,7 @@ void __init uv_system_init(void) if (is_uv_system()) uv_system_init_hub(); else - uv_nmi_setup_hubless(); + uv_system_init_hubless(); } apic_driver(apic_x2apic_uv_x); --
[-- Attachment #1: add-procfs-files --] [-- Type: text/plain, Size: 5176 bytes --] Indicate to UV user utilities that UV hubless support is available on this system via the existing /proc infterface. The current interface is maintained with the addition of new /proc leaves ("hubbed", "hubless", and "oemid") that contain the specific type of UV arch this one is. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- V2: Remove is_uv_hubbed define Remove leading '_' from _is_uv_hubbed --- arch/x86/include/asm/uv/uv.h | 4 + arch/x86/kernel/apic/x2apic_uv_x.c | 93 ++++++++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 1 deletion(-) --- linux.orig/arch/x86/include/asm/uv/uv.h +++ linux/arch/x86/include/asm/uv/uv.h @@ -12,6 +12,8 @@ struct mm_struct; #ifdef CONFIG_X86_UV #include <linux/efi.h> +#define UV_PROC_NODE "sgi_uv" + static inline int uv(int uvtype) { /* uv(0) is "any" */ @@ -28,6 +30,7 @@ static inline bool is_early_uv_system(vo return uv_systab_phys && uv_systab_phys != EFI_INVALID_TABLE_ADDR; } extern int is_uv_system(void); +extern int is_uv_hubbed(int uvtype); extern int is_uv_hubless(int uvtype); extern void uv_cpu_init(void); extern void uv_nmi_init(void); @@ -40,6 +43,7 @@ extern const struct cpumask *uv_flush_tl static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } static inline bool is_early_uv_system(void) { return 0; } static inline int is_uv_system(void) { return 0; } +static inline int is_uv_hubbed(int uv) { return 0; } static inline int is_uv_hubless(int uv) { return 0; } static inline void uv_cpu_init(void) { } static inline void uv_system_init(void) { } --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -26,6 +26,7 @@ static DEFINE_PER_CPU(int, x2apic_extra_bits); static enum uv_system_type uv_system_type; +static int uv_hubbed_system; static int uv_hubless_system; static u64 gru_start_paddr, gru_end_paddr; static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr; @@ -309,6 +310,24 @@ static int __init uv_acpi_madt_oem_check if (uv_hub_info->hub_revision == 0) goto badbios; + switch (uv_hub_info->hub_revision) { + case UV4_HUB_REVISION_BASE: + uv_hubbed_system = 0x11; + break; + + case UV3_HUB_REVISION_BASE: + uv_hubbed_system = 0x9; + break; + + case UV2_HUB_REVISION_BASE: + uv_hubbed_system = 0x5; + break; + + case UV1_HUB_REVISION_BASE: + uv_hubbed_system = 0x3; + break; + } + pnodeid = early_get_pnodeid(); early_get_apic_socketid_shift(); @@ -359,6 +378,12 @@ int is_uv_system(void) } EXPORT_SYMBOL_GPL(is_uv_system); +int is_uv_hubbed(int uvtype) +{ + return (uv_hubbed_system & uvtype); +} +EXPORT_SYMBOL_GPL(is_uv_hubbed); + int is_uv_hubless(int uvtype) { return (uv_hubless_system & uvtype); @@ -1457,6 +1482,68 @@ static void __init build_socket_tables(v } } +/* Setup user proc fs files */ +static int proc_hubbed_show(struct seq_file *file, void *data) +{ + seq_printf(file, "0x%x\n", uv_hubbed_system); + return 0; +} + +static int proc_hubless_show(struct seq_file *file, void *data) +{ + seq_printf(file, "0x%x\n", uv_hubless_system); + return 0; +} + +static int proc_oemid_show(struct seq_file *file, void *data) +{ + seq_printf(file, "%s/%s\n", oem_id, oem_table_id); + return 0; +} + +static int proc_hubbed_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_hubbed_show, (void *)NULL); +} + +static int proc_hubless_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_hubless_show, (void *)NULL); +} + +static int proc_oemid_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_oemid_show, (void *)NULL); +} + +/* (struct is "non-const" as open function is set at runtime) */ +static struct file_operations proc_version_fops = { + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_oemid_fops = { + .open = proc_oemid_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static __init void uv_setup_proc_files(int hubless) +{ + struct proc_dir_entry *pde; + char *name = hubless ? "hubless" : "hubbed"; + + pde = proc_mkdir(UV_PROC_NODE, NULL); + proc_create("oemid", 0, pde, &proc_oemid_fops); + proc_create(name, 0, pde, &proc_version_fops); + if (hubless) + proc_version_fops.open = proc_hubless_open; + else + proc_version_fops.open = proc_hubbed_open; +} + /* Initialize UV hubless systems */ static __init int uv_system_init_hubless(void) { @@ -1468,6 +1555,10 @@ static __init int uv_system_init_hubless /* Init kernel/BIOS interface */ rc = uv_bios_init(); + /* Create user access node if UVsystab available */ + if (rc >= 0) + uv_setup_proc_files(1); + return rc; } @@ -1596,7 +1687,7 @@ static void __init uv_system_init_hub(vo uv_nmi_setup(); uv_cpu_init(); uv_scir_register_cpu_notifier(); - proc_mkdir("sgi_uv", NULL); + uv_setup_proc_files(0); /* Register Legacy VGA I/O redirection handler: */ pci_register_set_vga_state(uv_set_vga_state); --
[-- Attachment #1: decode-hubless-uvst --] [-- Type: text/plain, Size: 1467 bytes --] Decode the hubless UVsystab passed from BIOS to the kernel saving pertinent info in a similar manner that hubbed UVsystabs are decoded. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- V2: Removed redundant error message after call to uv_bios_init. Removed redundant error message after call to decode_uv_systab. Clarify selection of UV4 and higher when checking for extended UVsystab in decode_uv_systab(). --- arch/x86/kernel/apic/x2apic_uv_x.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -1303,7 +1303,8 @@ static int __init decode_uv_systab(void) struct uv_systab *st; int i; - if (uv_hub_info->hub_revision < UV4_HUB_REVISION_BASE) + /* If system is uv3 or lower, there is no extended UVsystab */ + if (is_uv_hubbed(0xfffffe) < uv(4) && is_uv_hubless(0xfffffe) < uv(4)) return 0; /* No extended UVsystab required */ st = uv_systab; @@ -1554,8 +1555,15 @@ static __init int uv_system_init_hubless /* Init kernel/BIOS interface */ rc = uv_bios_init(); + if (rc < 0) + return rc; - /* Create user access node if UVsystab available */ + /* Process UVsystab */ + rc = decode_uv_systab(); + if (rc < 0) + return rc; + + /* Create user access node */ if (rc >= 0) uv_setup_proc_files(1); --
[-- Attachment #1: check-efi-boot --] [-- Type: text/plain, Size: 1579 bytes --] Change to checking for EFI Boot type from previous check on if this is a KDUMP kernel. This allows for KDUMP kernels that can handle EFI reboots. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- arch/x86/kernel/apic/x2apic_uv_x.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -15,6 +15,7 @@ #include <linux/export.h> #include <linux/pci.h> #include <linux/acpi.h> +#include <linux/efi.h> #include <asm/e820/api.h> #include <asm/uv/uv_mmrs.h> @@ -1483,6 +1484,14 @@ static void __init build_socket_tables(v } } +/* Check which reboot to use */ +static void check_efi_reboot(void) +{ + /* If EFI reboot not available, use ACPI reboot */ + if (!efi_enabled(EFI_BOOT)) + reboot_type = BOOT_ACPI; +} + /* Setup user proc fs files */ static int proc_hubbed_show(struct seq_file *file, void *data) { @@ -1571,6 +1580,8 @@ static __init int uv_system_init_hubless if (rc >= 0) uv_setup_proc_files(1); + check_efi_reboot(); + return rc; } @@ -1704,12 +1715,7 @@ static void __init uv_system_init_hub(vo /* Register Legacy VGA I/O redirection handler: */ pci_register_set_vga_state(uv_set_vga_state); - /* - * For a kdump kernel the reset must be BOOT_ACPI, not BOOT_EFI, as - * EFI is not enabled in the kdump kernel: - */ - if (is_kdump_kernel()) - reboot_type = BOOT_ACPI; + check_efi_reboot(); } /* --
[-- Attachment #1: mod-is_uvX_hub --] [-- Type: text/plain, Size: 3221 bytes --] The references in the is_uvX_hub() function uses the hub_info pointer which will be NULL when the system is hubless. This change avoids that NULL dereference. It is also an optimization in performance. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- V2: Add WARNING that the is UVx supported defines will be removed. --- arch/x86/include/asm/uv/.uv_hub.h.swp |binary arch/x86/include/asm/uv/uv_hub.h | 61 ++++++++++++--------------------------- 1 file changed, 20 insertions(+), 41 deletions(-) Binary files linux.orig/arch/x86/include/asm/uv/.uv_hub.h.swp and linux/arch/x86/include/asm/uv/.uv_hub.h.swp differ --- linux.orig/arch/x86/include/asm/uv/uv_hub.h +++ linux/arch/x86/include/asm/uv/uv_hub.h @@ -19,6 +19,7 @@ #include <linux/topology.h> #include <asm/types.h> #include <asm/percpu.h> +#include <asm/uv/uv.h> #include <asm/uv/uv_mmrs.h> #include <asm/uv/bios.h> #include <asm/irq_vectors.h> @@ -243,83 +244,61 @@ static inline int uv_hub_info_check(int #define UV4_HUB_REVISION_BASE 7 #define UV4A_HUB_REVISION_BASE 8 /* UV4 (fixed) rev 2 */ -#ifdef UV1_HUB_IS_SUPPORTED +/* WARNING: UVx_HUB_IS_SUPPORTED defines are deprecated and will be removed */ static inline int is_uv1_hub(void) { - return uv_hub_info->hub_revision < UV2_HUB_REVISION_BASE; -} +#ifdef UV1_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(1)); #else -static inline int is_uv1_hub(void) -{ return 0; -} #endif +} -#ifdef UV2_HUB_IS_SUPPORTED static inline int is_uv2_hub(void) { - return ((uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE) && - (uv_hub_info->hub_revision < UV3_HUB_REVISION_BASE)); -} +#ifdef UV2_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(2)); #else -static inline int is_uv2_hub(void) -{ return 0; -} #endif +} -#ifdef UV3_HUB_IS_SUPPORTED static inline int is_uv3_hub(void) { - return ((uv_hub_info->hub_revision >= UV3_HUB_REVISION_BASE) && - (uv_hub_info->hub_revision < UV4_HUB_REVISION_BASE)); -} +#ifdef UV3_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(3)); #else -static inline int is_uv3_hub(void) -{ return 0; -} #endif +} /* First test "is UV4A", then "is UV4" */ -#ifdef UV4A_HUB_IS_SUPPORTED -static inline int is_uv4a_hub(void) -{ - return (uv_hub_info->hub_revision >= UV4A_HUB_REVISION_BASE); -} -#else static inline int is_uv4a_hub(void) { +#ifdef UV4A_HUB_IS_SUPPORTED + if (is_uv_hubbed(uv(4))) + return (uv_hub_info->hub_revision == UV4A_HUB_REVISION_BASE); +#endif return 0; } -#endif -#ifdef UV4_HUB_IS_SUPPORTED static inline int is_uv4_hub(void) { - return uv_hub_info->hub_revision >= UV4_HUB_REVISION_BASE; -} +#ifdef UV4_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(4)); #else -static inline int is_uv4_hub(void) -{ return 0; -} #endif +} static inline int is_uvx_hub(void) { - if (uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE) - return uv_hub_info->hub_revision; - - return 0; + return (is_uv_hubbed(-2) >= uv(2)); } static inline int is_uv_hub(void) { -#ifdef UV1_HUB_IS_SUPPORTED - return uv_hub_info->hub_revision; -#endif - return is_uvx_hub(); + return is_uv1_hub() || is_uvx_hub(); } union uvh_apicid { --
On 9/5/2019 11:47 AM, Mike Travis wrote: > > These patches support upcoming UV systems that do not have a UV HUB. > > [1/8] Save OEM_ID from ACPI MADT probe > > [2/8] Return UV Hubless System Type V2: Remove is_uv_hubless define Remove leading '_' from _is_uv_hubless > [3/8] Add return code to UV BIOS Init function > > [4/8] Setup UV functions for Hubless UV Systems > > [5/8] Add UV Hubbed/Hubless Proc FS Files V2: Remove is_uv_hubbed define Remove leading '_' from _is_uv_hubbed > [6/8] Decode UVsystab Info V2: Removed redundant error message after call to uv_bios_init. Removed redundant error message after call to decode_uv_systab. Clarify selection of UV4 and higher when checking for extended UVsystab in decode_uv_systab(). > [7/8] Check EFI Boot to set reboot type > > [8/8] Account for UV Hubless in is_uvX_hub Ops V2: Add WARNING that the is UVx supported defines will be removed. --
[-- Attachment #1: save-oem_id --] [-- Type: text/plain, Size: 1776 bytes --] Save the OEM_ID and OEM_TABLE_ID passed to the apic driver probe function for later use. Also, convert the char list arg passed from the kernel to a true null-terminated string. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- arch/x86/kernel/apic/x2apic_uv_x.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -14,6 +14,7 @@ #include <linux/memory.h> #include <linux/export.h> #include <linux/pci.h> +#include <linux/acpi.h> #include <asm/e820/api.h> #include <asm/uv/uv_mmrs.h> @@ -31,6 +32,10 @@ static u64 gru_dist_base, gru_first_no static u64 gru_dist_lmask, gru_dist_umask; static union uvh_apicid uvh_apicid; +/* Unpack OEM/TABLE ID's to be NULL terminated strings */ +static u8 oem_id[ACPI_OEM_ID_SIZE + 1]; +static u8 oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; + /* Information derived from CPUID: */ static struct { unsigned int apicid_shift; @@ -248,11 +253,20 @@ static void __init uv_set_apicid_hibit(v } } -static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static void __init uv_stringify(int len, char *to, char *from) +{ + /* Relies on 'to' being NULL chars so result will be NULL terminated */ + strncpy(to, from, len-1); +} + +static int __init uv_acpi_madt_oem_check(char *_oem_id, char *_oem_table_id) { int pnodeid; int uv_apic; + uv_stringify(sizeof(oem_id), oem_id, _oem_id); + uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id); + if (strncmp(oem_id, "SGI", 3) != 0) { if (strncmp(oem_id, "NSGI", 4) == 0) { uv_hubless_system = true; --
[-- Attachment #1: mod-is_uv_hubless --] [-- Type: text/plain, Size: 3439 bytes --] Return the type of UV hubless system for UV specific code that depends on that. Add a function to convert UV system type to bit pattern needed for is_uv_hubless(). Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- V2: Remove is_uv_hubless define Remove leading '_' from _is_uv_hubless --- arch/x86/include/asm/uv/uv.h | 12 ++++++++++-- arch/x86/kernel/apic/x2apic_uv_x.c | 27 ++++++++++++++++++--------- 2 files changed, 28 insertions(+), 11 deletions(-) --- linux.orig/arch/x86/include/asm/uv/uv.h +++ linux/arch/x86/include/asm/uv/uv.h @@ -12,6 +12,14 @@ struct mm_struct; #ifdef CONFIG_X86_UV #include <linux/efi.h> +static inline int uv(int uvtype) +{ + /* uv(0) is "any" */ + if (uvtype >= 0 && uvtype <= 30) + return 1 << uvtype; + return 1; +} + extern unsigned long uv_systab_phys; extern enum uv_system_type get_uv_system_type(void); @@ -20,7 +28,7 @@ static inline bool is_early_uv_system(vo return uv_systab_phys && uv_systab_phys != EFI_INVALID_TABLE_ADDR; } extern int is_uv_system(void); -extern int is_uv_hubless(void); +extern int is_uv_hubless(int uvtype); extern void uv_cpu_init(void); extern void uv_nmi_init(void); extern void uv_system_init(void); @@ -32,7 +40,7 @@ extern const struct cpumask *uv_flush_tl static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } static inline bool is_early_uv_system(void) { return 0; } static inline int is_uv_system(void) { return 0; } -static inline int is_uv_hubless(void) { return 0; } +static inline int is_uv_hubless(int uv) { return 0; } static inline void uv_cpu_init(void) { } static inline void uv_system_init(void) { } static inline const struct cpumask * --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -26,7 +26,7 @@ static DEFINE_PER_CPU(int, x2apic_extra_bits); static enum uv_system_type uv_system_type; -static bool uv_hubless_system; +static int uv_hubless_system; static u64 gru_start_paddr, gru_end_paddr; static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr; static u64 gru_dist_lmask, gru_dist_umask; @@ -268,11 +268,20 @@ static int __init uv_acpi_madt_oem_check uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id); if (strncmp(oem_id, "SGI", 3) != 0) { - if (strncmp(oem_id, "NSGI", 4) == 0) { - uv_hubless_system = true; - pr_info("UV: OEM IDs %s/%s, HUBLESS\n", - oem_id, oem_table_id); - } + if (strncmp(oem_id, "NSGI", 4) != 0) + return 0; + + /* UV4 Hubless, CH, (0x11:UV4+Any) */ + if (strncmp(oem_id, "NSGI4", 5) == 0) + uv_hubless_system = 0x11; + + /* UV3 Hubless, UV300/MC990X w/o hub (0x9:UV3+Any) */ + else + uv_hubless_system = 0x9; + + pr_info("UV: OEM IDs %s/%s, HUBLESS(0x%x)\n", + oem_id, oem_table_id, uv_hubless_system); + return 0; } @@ -350,9 +359,9 @@ int is_uv_system(void) } EXPORT_SYMBOL_GPL(is_uv_system); -int is_uv_hubless(void) +int is_uv_hubless(int uvtype) { - return uv_hubless_system; + return (uv_hubless_system & uvtype); } EXPORT_SYMBOL_GPL(is_uv_hubless); @@ -1592,7 +1601,7 @@ static void __init uv_system_init_hub(vo */ void __init uv_system_init(void) { - if (likely(!is_uv_system() && !is_uv_hubless())) + if (likely(!is_uv_system() && !is_uv_hubless(1))) return; if (is_uv_system()) --
[-- Attachment #1: add-bios_init-rc --] [-- Type: text/plain, Size: 1903 bytes --] Add a return code to the UV BIOS init function that indicates the successful initialization of the kernel/BIOS callback interface. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- arch/x86/include/asm/uv/bios.h | 2 +- arch/x86/platform/uv/bios_uv.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) --- linux.orig/arch/x86/include/asm/uv/bios.h +++ linux/arch/x86/include/asm/uv/bios.h @@ -138,7 +138,7 @@ extern s64 uv_bios_change_memprotect(u64 extern s64 uv_bios_reserved_page_pa(u64, u64 *, u64 *, u64 *); extern int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus); -extern void uv_bios_init(void); +extern int uv_bios_init(void); extern unsigned long sn_rtc_cycles_per_second; extern int uv_type; --- linux.orig/arch/x86/platform/uv/bios_uv.c +++ linux/arch/x86/platform/uv/bios_uv.c @@ -184,20 +184,20 @@ int uv_bios_set_legacy_vga_target(bool d } EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target); -void uv_bios_init(void) +int uv_bios_init(void) { uv_systab = NULL; if ((uv_systab_phys == EFI_INVALID_TABLE_ADDR) || !uv_systab_phys || efi_runtime_disabled()) { pr_crit("UV: UVsystab: missing\n"); - return; + return -EEXIST; } uv_systab = ioremap(uv_systab_phys, sizeof(struct uv_systab)); if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) { pr_err("UV: UVsystab: bad signature!\n"); iounmap(uv_systab); - return; + return -EINVAL; } /* Starting with UV4 the UV systab size is variable */ @@ -208,8 +208,9 @@ void uv_bios_init(void) uv_systab = ioremap(uv_systab_phys, size); if (!uv_systab) { pr_err("UV: UVsystab: ioremap(%d) failed!\n", size); - return; + return -EFAULT; } } pr_info("UV: UVsystab: Revision:%x\n", uv_systab->revision); + return 0; } --
[-- Attachment #1: setup-hubless-init --] [-- Type: text/plain, Size: 1644 bytes --] Add more support for UV systems that do not contain a UV Hub (AKA "hubless"). This update adds support for additional functions required: Use PCH NMI handler instead of a UV Hub NMI handler. Initialize the UV BIOS callback interface used to support specific UV functions. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- arch/x86/kernel/apic/x2apic_uv_x.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -1457,6 +1457,20 @@ static void __init build_socket_tables(v } } +/* Initialize UV hubless systems */ +static __init int uv_system_init_hubless(void) +{ + int rc; + + /* Setup PCH NMI handler */ + uv_nmi_setup_hubless(); + + /* Init kernel/BIOS interface */ + rc = uv_bios_init(); + + return rc; +} + static void __init uv_system_init_hub(void) { struct uv_hub_info_s hub_info = {0}; @@ -1596,8 +1610,8 @@ static void __init uv_system_init_hub(vo } /* - * There is a small amount of UV specific code needed to initialize a - * UV system that does not have a "UV HUB" (referred to as "hubless"). + * There is a different code path needed to initialize a UV system that does + * not have a "UV HUB" (referred to as "hubless"). */ void __init uv_system_init(void) { @@ -1607,7 +1621,7 @@ void __init uv_system_init(void) if (is_uv_system()) uv_system_init_hub(); else - uv_nmi_setup_hubless(); + uv_system_init_hubless(); } apic_driver(apic_x2apic_uv_x); --
[-- Attachment #1: add-procfs-files --] [-- Type: text/plain, Size: 5176 bytes --] Indicate to UV user utilities that UV hubless support is available on this system via the existing /proc infterface. The current interface is maintained with the addition of new /proc leaves ("hubbed", "hubless", and "oemid") that contain the specific type of UV arch this one is. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- V2: Remove is_uv_hubbed define Remove leading '_' from _is_uv_hubbed --- arch/x86/include/asm/uv/uv.h | 4 + arch/x86/kernel/apic/x2apic_uv_x.c | 93 ++++++++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 1 deletion(-) --- linux.orig/arch/x86/include/asm/uv/uv.h +++ linux/arch/x86/include/asm/uv/uv.h @@ -12,6 +12,8 @@ struct mm_struct; #ifdef CONFIG_X86_UV #include <linux/efi.h> +#define UV_PROC_NODE "sgi_uv" + static inline int uv(int uvtype) { /* uv(0) is "any" */ @@ -28,6 +30,7 @@ static inline bool is_early_uv_system(vo return uv_systab_phys && uv_systab_phys != EFI_INVALID_TABLE_ADDR; } extern int is_uv_system(void); +extern int is_uv_hubbed(int uvtype); extern int is_uv_hubless(int uvtype); extern void uv_cpu_init(void); extern void uv_nmi_init(void); @@ -40,6 +43,7 @@ extern const struct cpumask *uv_flush_tl static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } static inline bool is_early_uv_system(void) { return 0; } static inline int is_uv_system(void) { return 0; } +static inline int is_uv_hubbed(int uv) { return 0; } static inline int is_uv_hubless(int uv) { return 0; } static inline void uv_cpu_init(void) { } static inline void uv_system_init(void) { } --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -26,6 +26,7 @@ static DEFINE_PER_CPU(int, x2apic_extra_bits); static enum uv_system_type uv_system_type; +static int uv_hubbed_system; static int uv_hubless_system; static u64 gru_start_paddr, gru_end_paddr; static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr; @@ -309,6 +310,24 @@ static int __init uv_acpi_madt_oem_check if (uv_hub_info->hub_revision == 0) goto badbios; + switch (uv_hub_info->hub_revision) { + case UV4_HUB_REVISION_BASE: + uv_hubbed_system = 0x11; + break; + + case UV3_HUB_REVISION_BASE: + uv_hubbed_system = 0x9; + break; + + case UV2_HUB_REVISION_BASE: + uv_hubbed_system = 0x5; + break; + + case UV1_HUB_REVISION_BASE: + uv_hubbed_system = 0x3; + break; + } + pnodeid = early_get_pnodeid(); early_get_apic_socketid_shift(); @@ -359,6 +378,12 @@ int is_uv_system(void) } EXPORT_SYMBOL_GPL(is_uv_system); +int is_uv_hubbed(int uvtype) +{ + return (uv_hubbed_system & uvtype); +} +EXPORT_SYMBOL_GPL(is_uv_hubbed); + int is_uv_hubless(int uvtype) { return (uv_hubless_system & uvtype); @@ -1457,6 +1482,68 @@ static void __init build_socket_tables(v } } +/* Setup user proc fs files */ +static int proc_hubbed_show(struct seq_file *file, void *data) +{ + seq_printf(file, "0x%x\n", uv_hubbed_system); + return 0; +} + +static int proc_hubless_show(struct seq_file *file, void *data) +{ + seq_printf(file, "0x%x\n", uv_hubless_system); + return 0; +} + +static int proc_oemid_show(struct seq_file *file, void *data) +{ + seq_printf(file, "%s/%s\n", oem_id, oem_table_id); + return 0; +} + +static int proc_hubbed_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_hubbed_show, (void *)NULL); +} + +static int proc_hubless_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_hubless_show, (void *)NULL); +} + +static int proc_oemid_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_oemid_show, (void *)NULL); +} + +/* (struct is "non-const" as open function is set at runtime) */ +static struct file_operations proc_version_fops = { + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_oemid_fops = { + .open = proc_oemid_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static __init void uv_setup_proc_files(int hubless) +{ + struct proc_dir_entry *pde; + char *name = hubless ? "hubless" : "hubbed"; + + pde = proc_mkdir(UV_PROC_NODE, NULL); + proc_create("oemid", 0, pde, &proc_oemid_fops); + proc_create(name, 0, pde, &proc_version_fops); + if (hubless) + proc_version_fops.open = proc_hubless_open; + else + proc_version_fops.open = proc_hubbed_open; +} + /* Initialize UV hubless systems */ static __init int uv_system_init_hubless(void) { @@ -1468,6 +1555,10 @@ static __init int uv_system_init_hubless /* Init kernel/BIOS interface */ rc = uv_bios_init(); + /* Create user access node if UVsystab available */ + if (rc >= 0) + uv_setup_proc_files(1); + return rc; } @@ -1596,7 +1687,7 @@ static void __init uv_system_init_hub(vo uv_nmi_setup(); uv_cpu_init(); uv_scir_register_cpu_notifier(); - proc_mkdir("sgi_uv", NULL); + uv_setup_proc_files(0); /* Register Legacy VGA I/O redirection handler: */ pci_register_set_vga_state(uv_set_vga_state); --
[-- Attachment #1: decode-hubless-uvst --] [-- Type: text/plain, Size: 1467 bytes --] Decode the hubless UVsystab passed from BIOS to the kernel saving pertinent info in a similar manner that hubbed UVsystabs are decoded. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- V2: Removed redundant error message after call to uv_bios_init. Removed redundant error message after call to decode_uv_systab. Clarify selection of UV4 and higher when checking for extended UVsystab in decode_uv_systab(). --- arch/x86/kernel/apic/x2apic_uv_x.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -1303,7 +1303,8 @@ static int __init decode_uv_systab(void) struct uv_systab *st; int i; - if (uv_hub_info->hub_revision < UV4_HUB_REVISION_BASE) + /* If system is uv3 or lower, there is no extended UVsystab */ + if (is_uv_hubbed(0xfffffe) < uv(4) && is_uv_hubless(0xfffffe) < uv(4)) return 0; /* No extended UVsystab required */ st = uv_systab; @@ -1554,8 +1555,15 @@ static __init int uv_system_init_hubless /* Init kernel/BIOS interface */ rc = uv_bios_init(); + if (rc < 0) + return rc; - /* Create user access node if UVsystab available */ + /* Process UVsystab */ + rc = decode_uv_systab(); + if (rc < 0) + return rc; + + /* Create user access node */ if (rc >= 0) uv_setup_proc_files(1); --
[-- Attachment #1: check-efi-boot --] [-- Type: text/plain, Size: 1579 bytes --] Change to checking for EFI Boot type from previous check on if this is a KDUMP kernel. This allows for KDUMP kernels that can handle EFI reboots. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- arch/x86/kernel/apic/x2apic_uv_x.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -15,6 +15,7 @@ #include <linux/export.h> #include <linux/pci.h> #include <linux/acpi.h> +#include <linux/efi.h> #include <asm/e820/api.h> #include <asm/uv/uv_mmrs.h> @@ -1483,6 +1484,14 @@ static void __init build_socket_tables(v } } +/* Check which reboot to use */ +static void check_efi_reboot(void) +{ + /* If EFI reboot not available, use ACPI reboot */ + if (!efi_enabled(EFI_BOOT)) + reboot_type = BOOT_ACPI; +} + /* Setup user proc fs files */ static int proc_hubbed_show(struct seq_file *file, void *data) { @@ -1571,6 +1580,8 @@ static __init int uv_system_init_hubless if (rc >= 0) uv_setup_proc_files(1); + check_efi_reboot(); + return rc; } @@ -1704,12 +1715,7 @@ static void __init uv_system_init_hub(vo /* Register Legacy VGA I/O redirection handler: */ pci_register_set_vga_state(uv_set_vga_state); - /* - * For a kdump kernel the reset must be BOOT_ACPI, not BOOT_EFI, as - * EFI is not enabled in the kdump kernel: - */ - if (is_kdump_kernel()) - reboot_type = BOOT_ACPI; + check_efi_reboot(); } /* --
[-- Attachment #1: mod-is_uvX_hub --] [-- Type: text/plain, Size: 3221 bytes --] The references in the is_uvX_hub() function uses the hub_info pointer which will be NULL when the system is hubless. This change avoids that NULL dereference. It is also an optimization in performance. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- V2: Add WARNING that the is UVx supported defines will be removed. --- arch/x86/include/asm/uv/.uv_hub.h.swp |binary arch/x86/include/asm/uv/uv_hub.h | 61 ++++++++++++--------------------------- 1 file changed, 20 insertions(+), 41 deletions(-) Binary files linux.orig/arch/x86/include/asm/uv/.uv_hub.h.swp and linux/arch/x86/include/asm/uv/.uv_hub.h.swp differ --- linux.orig/arch/x86/include/asm/uv/uv_hub.h +++ linux/arch/x86/include/asm/uv/uv_hub.h @@ -19,6 +19,7 @@ #include <linux/topology.h> #include <asm/types.h> #include <asm/percpu.h> +#include <asm/uv/uv.h> #include <asm/uv/uv_mmrs.h> #include <asm/uv/bios.h> #include <asm/irq_vectors.h> @@ -243,83 +244,61 @@ static inline int uv_hub_info_check(int #define UV4_HUB_REVISION_BASE 7 #define UV4A_HUB_REVISION_BASE 8 /* UV4 (fixed) rev 2 */ -#ifdef UV1_HUB_IS_SUPPORTED +/* WARNING: UVx_HUB_IS_SUPPORTED defines are deprecated and will be removed */ static inline int is_uv1_hub(void) { - return uv_hub_info->hub_revision < UV2_HUB_REVISION_BASE; -} +#ifdef UV1_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(1)); #else -static inline int is_uv1_hub(void) -{ return 0; -} #endif +} -#ifdef UV2_HUB_IS_SUPPORTED static inline int is_uv2_hub(void) { - return ((uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE) && - (uv_hub_info->hub_revision < UV3_HUB_REVISION_BASE)); -} +#ifdef UV2_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(2)); #else -static inline int is_uv2_hub(void) -{ return 0; -} #endif +} -#ifdef UV3_HUB_IS_SUPPORTED static inline int is_uv3_hub(void) { - return ((uv_hub_info->hub_revision >= UV3_HUB_REVISION_BASE) && - (uv_hub_info->hub_revision < UV4_HUB_REVISION_BASE)); -} +#ifdef UV3_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(3)); #else -static inline int is_uv3_hub(void) -{ return 0; -} #endif +} /* First test "is UV4A", then "is UV4" */ -#ifdef UV4A_HUB_IS_SUPPORTED -static inline int is_uv4a_hub(void) -{ - return (uv_hub_info->hub_revision >= UV4A_HUB_REVISION_BASE); -} -#else static inline int is_uv4a_hub(void) { +#ifdef UV4A_HUB_IS_SUPPORTED + if (is_uv_hubbed(uv(4))) + return (uv_hub_info->hub_revision == UV4A_HUB_REVISION_BASE); +#endif return 0; } -#endif -#ifdef UV4_HUB_IS_SUPPORTED static inline int is_uv4_hub(void) { - return uv_hub_info->hub_revision >= UV4_HUB_REVISION_BASE; -} +#ifdef UV4_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(4)); #else -static inline int is_uv4_hub(void) -{ return 0; -} #endif +} static inline int is_uvx_hub(void) { - if (uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE) - return uv_hub_info->hub_revision; - - return 0; + return (is_uv_hubbed(-2) >= uv(2)); } static inline int is_uv_hub(void) { -#ifdef UV1_HUB_IS_SUPPORTED - return uv_hub_info->hub_revision; -#endif - return is_uvx_hub(); + return is_uv1_hub() || is_uvx_hub(); } union uvh_apicid { --
On 9/5/2019 11:47 AM, Mike Travis wrote: > > These patches support upcoming UV systems that do not have a UV HUB. > > [1/8] Save OEM_ID from ACPI MADT probe > > [2/8] Return UV Hubless System Type V2: Remove is_uv_hubless define Remove leading '_' from _is_uv_hubless > [3/8] Add return code to UV BIOS Init function > > [4/8] Setup UV functions for Hubless UV Systems > > [5/8] Add UV Hubbed/Hubless Proc FS Files V2: Remove is_uv_hubbed define Remove leading '_' from _is_uv_hubbed > [6/8] Decode UVsystab Info V2: Removed redundant error message after call to uv_bios_init. Removed redundant error message after call to decode_uv_systab. Clarify selection of UV4 and higher when checking for extended UVsystab in decode_uv_systab(). > [7/8] Check EFI Boot to set reboot type > > [8/8] Account for UV Hubless in is_uvX_hub Ops V2: Add WARNING that the is UVx supported defines will be removed. --
[-- Attachment #1: save-oem_id --] [-- Type: text/plain, Size: 1776 bytes --] Save the OEM_ID and OEM_TABLE_ID passed to the apic driver probe function for later use. Also, convert the char list arg passed from the kernel to a true null-terminated string. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- arch/x86/kernel/apic/x2apic_uv_x.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -14,6 +14,7 @@ #include <linux/memory.h> #include <linux/export.h> #include <linux/pci.h> +#include <linux/acpi.h> #include <asm/e820/api.h> #include <asm/uv/uv_mmrs.h> @@ -31,6 +32,10 @@ static u64 gru_dist_base, gru_first_no static u64 gru_dist_lmask, gru_dist_umask; static union uvh_apicid uvh_apicid; +/* Unpack OEM/TABLE ID's to be NULL terminated strings */ +static u8 oem_id[ACPI_OEM_ID_SIZE + 1]; +static u8 oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; + /* Information derived from CPUID: */ static struct { unsigned int apicid_shift; @@ -248,11 +253,20 @@ static void __init uv_set_apicid_hibit(v } } -static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static void __init uv_stringify(int len, char *to, char *from) +{ + /* Relies on 'to' being NULL chars so result will be NULL terminated */ + strncpy(to, from, len-1); +} + +static int __init uv_acpi_madt_oem_check(char *_oem_id, char *_oem_table_id) { int pnodeid; int uv_apic; + uv_stringify(sizeof(oem_id), oem_id, _oem_id); + uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id); + if (strncmp(oem_id, "SGI", 3) != 0) { if (strncmp(oem_id, "NSGI", 4) == 0) { uv_hubless_system = true; --
[-- Attachment #1: mod-is_uv_hubless --] [-- Type: text/plain, Size: 3439 bytes --] Return the type of UV hubless system for UV specific code that depends on that. Add a function to convert UV system type to bit pattern needed for is_uv_hubless(). Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- V2: Remove is_uv_hubless define Remove leading '_' from _is_uv_hubless --- arch/x86/include/asm/uv/uv.h | 12 ++++++++++-- arch/x86/kernel/apic/x2apic_uv_x.c | 27 ++++++++++++++++++--------- 2 files changed, 28 insertions(+), 11 deletions(-) --- linux.orig/arch/x86/include/asm/uv/uv.h +++ linux/arch/x86/include/asm/uv/uv.h @@ -12,6 +12,14 @@ struct mm_struct; #ifdef CONFIG_X86_UV #include <linux/efi.h> +static inline int uv(int uvtype) +{ + /* uv(0) is "any" */ + if (uvtype >= 0 && uvtype <= 30) + return 1 << uvtype; + return 1; +} + extern unsigned long uv_systab_phys; extern enum uv_system_type get_uv_system_type(void); @@ -20,7 +28,7 @@ static inline bool is_early_uv_system(vo return uv_systab_phys && uv_systab_phys != EFI_INVALID_TABLE_ADDR; } extern int is_uv_system(void); -extern int is_uv_hubless(void); +extern int is_uv_hubless(int uvtype); extern void uv_cpu_init(void); extern void uv_nmi_init(void); extern void uv_system_init(void); @@ -32,7 +40,7 @@ extern const struct cpumask *uv_flush_tl static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } static inline bool is_early_uv_system(void) { return 0; } static inline int is_uv_system(void) { return 0; } -static inline int is_uv_hubless(void) { return 0; } +static inline int is_uv_hubless(int uv) { return 0; } static inline void uv_cpu_init(void) { } static inline void uv_system_init(void) { } static inline const struct cpumask * --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -26,7 +26,7 @@ static DEFINE_PER_CPU(int, x2apic_extra_bits); static enum uv_system_type uv_system_type; -static bool uv_hubless_system; +static int uv_hubless_system; static u64 gru_start_paddr, gru_end_paddr; static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr; static u64 gru_dist_lmask, gru_dist_umask; @@ -268,11 +268,20 @@ static int __init uv_acpi_madt_oem_check uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id); if (strncmp(oem_id, "SGI", 3) != 0) { - if (strncmp(oem_id, "NSGI", 4) == 0) { - uv_hubless_system = true; - pr_info("UV: OEM IDs %s/%s, HUBLESS\n", - oem_id, oem_table_id); - } + if (strncmp(oem_id, "NSGI", 4) != 0) + return 0; + + /* UV4 Hubless, CH, (0x11:UV4+Any) */ + if (strncmp(oem_id, "NSGI4", 5) == 0) + uv_hubless_system = 0x11; + + /* UV3 Hubless, UV300/MC990X w/o hub (0x9:UV3+Any) */ + else + uv_hubless_system = 0x9; + + pr_info("UV: OEM IDs %s/%s, HUBLESS(0x%x)\n", + oem_id, oem_table_id, uv_hubless_system); + return 0; } @@ -350,9 +359,9 @@ int is_uv_system(void) } EXPORT_SYMBOL_GPL(is_uv_system); -int is_uv_hubless(void) +int is_uv_hubless(int uvtype) { - return uv_hubless_system; + return (uv_hubless_system & uvtype); } EXPORT_SYMBOL_GPL(is_uv_hubless); @@ -1592,7 +1601,7 @@ static void __init uv_system_init_hub(vo */ void __init uv_system_init(void) { - if (likely(!is_uv_system() && !is_uv_hubless())) + if (likely(!is_uv_system() && !is_uv_hubless(1))) return; if (is_uv_system()) --
[-- Attachment #1: add-bios_init-rc --] [-- Type: text/plain, Size: 1903 bytes --] Add a return code to the UV BIOS init function that indicates the successful initialization of the kernel/BIOS callback interface. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- arch/x86/include/asm/uv/bios.h | 2 +- arch/x86/platform/uv/bios_uv.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) --- linux.orig/arch/x86/include/asm/uv/bios.h +++ linux/arch/x86/include/asm/uv/bios.h @@ -138,7 +138,7 @@ extern s64 uv_bios_change_memprotect(u64 extern s64 uv_bios_reserved_page_pa(u64, u64 *, u64 *, u64 *); extern int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus); -extern void uv_bios_init(void); +extern int uv_bios_init(void); extern unsigned long sn_rtc_cycles_per_second; extern int uv_type; --- linux.orig/arch/x86/platform/uv/bios_uv.c +++ linux/arch/x86/platform/uv/bios_uv.c @@ -184,20 +184,20 @@ int uv_bios_set_legacy_vga_target(bool d } EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target); -void uv_bios_init(void) +int uv_bios_init(void) { uv_systab = NULL; if ((uv_systab_phys == EFI_INVALID_TABLE_ADDR) || !uv_systab_phys || efi_runtime_disabled()) { pr_crit("UV: UVsystab: missing\n"); - return; + return -EEXIST; } uv_systab = ioremap(uv_systab_phys, sizeof(struct uv_systab)); if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) { pr_err("UV: UVsystab: bad signature!\n"); iounmap(uv_systab); - return; + return -EINVAL; } /* Starting with UV4 the UV systab size is variable */ @@ -208,8 +208,9 @@ void uv_bios_init(void) uv_systab = ioremap(uv_systab_phys, size); if (!uv_systab) { pr_err("UV: UVsystab: ioremap(%d) failed!\n", size); - return; + return -EFAULT; } } pr_info("UV: UVsystab: Revision:%x\n", uv_systab->revision); + return 0; } --
[-- Attachment #1: setup-hubless-init --] [-- Type: text/plain, Size: 1644 bytes --] Add more support for UV systems that do not contain a UV Hub (AKA "hubless"). This update adds support for additional functions required: Use PCH NMI handler instead of a UV Hub NMI handler. Initialize the UV BIOS callback interface used to support specific UV functions. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- arch/x86/kernel/apic/x2apic_uv_x.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -1457,6 +1457,20 @@ static void __init build_socket_tables(v } } +/* Initialize UV hubless systems */ +static __init int uv_system_init_hubless(void) +{ + int rc; + + /* Setup PCH NMI handler */ + uv_nmi_setup_hubless(); + + /* Init kernel/BIOS interface */ + rc = uv_bios_init(); + + return rc; +} + static void __init uv_system_init_hub(void) { struct uv_hub_info_s hub_info = {0}; @@ -1596,8 +1610,8 @@ static void __init uv_system_init_hub(vo } /* - * There is a small amount of UV specific code needed to initialize a - * UV system that does not have a "UV HUB" (referred to as "hubless"). + * There is a different code path needed to initialize a UV system that does + * not have a "UV HUB" (referred to as "hubless"). */ void __init uv_system_init(void) { @@ -1607,7 +1621,7 @@ void __init uv_system_init(void) if (is_uv_system()) uv_system_init_hub(); else - uv_nmi_setup_hubless(); + uv_system_init_hubless(); } apic_driver(apic_x2apic_uv_x); --
[-- Attachment #1: add-procfs-files --] [-- Type: text/plain, Size: 5176 bytes --] Indicate to UV user utilities that UV hubless support is available on this system via the existing /proc infterface. The current interface is maintained with the addition of new /proc leaves ("hubbed", "hubless", and "oemid") that contain the specific type of UV arch this one is. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- V2: Remove is_uv_hubbed define Remove leading '_' from _is_uv_hubbed --- arch/x86/include/asm/uv/uv.h | 4 + arch/x86/kernel/apic/x2apic_uv_x.c | 93 ++++++++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 1 deletion(-) --- linux.orig/arch/x86/include/asm/uv/uv.h +++ linux/arch/x86/include/asm/uv/uv.h @@ -12,6 +12,8 @@ struct mm_struct; #ifdef CONFIG_X86_UV #include <linux/efi.h> +#define UV_PROC_NODE "sgi_uv" + static inline int uv(int uvtype) { /* uv(0) is "any" */ @@ -28,6 +30,7 @@ static inline bool is_early_uv_system(vo return uv_systab_phys && uv_systab_phys != EFI_INVALID_TABLE_ADDR; } extern int is_uv_system(void); +extern int is_uv_hubbed(int uvtype); extern int is_uv_hubless(int uvtype); extern void uv_cpu_init(void); extern void uv_nmi_init(void); @@ -40,6 +43,7 @@ extern const struct cpumask *uv_flush_tl static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } static inline bool is_early_uv_system(void) { return 0; } static inline int is_uv_system(void) { return 0; } +static inline int is_uv_hubbed(int uv) { return 0; } static inline int is_uv_hubless(int uv) { return 0; } static inline void uv_cpu_init(void) { } static inline void uv_system_init(void) { } --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -26,6 +26,7 @@ static DEFINE_PER_CPU(int, x2apic_extra_bits); static enum uv_system_type uv_system_type; +static int uv_hubbed_system; static int uv_hubless_system; static u64 gru_start_paddr, gru_end_paddr; static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr; @@ -309,6 +310,24 @@ static int __init uv_acpi_madt_oem_check if (uv_hub_info->hub_revision == 0) goto badbios; + switch (uv_hub_info->hub_revision) { + case UV4_HUB_REVISION_BASE: + uv_hubbed_system = 0x11; + break; + + case UV3_HUB_REVISION_BASE: + uv_hubbed_system = 0x9; + break; + + case UV2_HUB_REVISION_BASE: + uv_hubbed_system = 0x5; + break; + + case UV1_HUB_REVISION_BASE: + uv_hubbed_system = 0x3; + break; + } + pnodeid = early_get_pnodeid(); early_get_apic_socketid_shift(); @@ -359,6 +378,12 @@ int is_uv_system(void) } EXPORT_SYMBOL_GPL(is_uv_system); +int is_uv_hubbed(int uvtype) +{ + return (uv_hubbed_system & uvtype); +} +EXPORT_SYMBOL_GPL(is_uv_hubbed); + int is_uv_hubless(int uvtype) { return (uv_hubless_system & uvtype); @@ -1457,6 +1482,68 @@ static void __init build_socket_tables(v } } +/* Setup user proc fs files */ +static int proc_hubbed_show(struct seq_file *file, void *data) +{ + seq_printf(file, "0x%x\n", uv_hubbed_system); + return 0; +} + +static int proc_hubless_show(struct seq_file *file, void *data) +{ + seq_printf(file, "0x%x\n", uv_hubless_system); + return 0; +} + +static int proc_oemid_show(struct seq_file *file, void *data) +{ + seq_printf(file, "%s/%s\n", oem_id, oem_table_id); + return 0; +} + +static int proc_hubbed_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_hubbed_show, (void *)NULL); +} + +static int proc_hubless_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_hubless_show, (void *)NULL); +} + +static int proc_oemid_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_oemid_show, (void *)NULL); +} + +/* (struct is "non-const" as open function is set at runtime) */ +static struct file_operations proc_version_fops = { + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_oemid_fops = { + .open = proc_oemid_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static __init void uv_setup_proc_files(int hubless) +{ + struct proc_dir_entry *pde; + char *name = hubless ? "hubless" : "hubbed"; + + pde = proc_mkdir(UV_PROC_NODE, NULL); + proc_create("oemid", 0, pde, &proc_oemid_fops); + proc_create(name, 0, pde, &proc_version_fops); + if (hubless) + proc_version_fops.open = proc_hubless_open; + else + proc_version_fops.open = proc_hubbed_open; +} + /* Initialize UV hubless systems */ static __init int uv_system_init_hubless(void) { @@ -1468,6 +1555,10 @@ static __init int uv_system_init_hubless /* Init kernel/BIOS interface */ rc = uv_bios_init(); + /* Create user access node if UVsystab available */ + if (rc >= 0) + uv_setup_proc_files(1); + return rc; } @@ -1596,7 +1687,7 @@ static void __init uv_system_init_hub(vo uv_nmi_setup(); uv_cpu_init(); uv_scir_register_cpu_notifier(); - proc_mkdir("sgi_uv", NULL); + uv_setup_proc_files(0); /* Register Legacy VGA I/O redirection handler: */ pci_register_set_vga_state(uv_set_vga_state); --
[-- Attachment #1: decode-hubless-uvst --] [-- Type: text/plain, Size: 1467 bytes --] Decode the hubless UVsystab passed from BIOS to the kernel saving pertinent info in a similar manner that hubbed UVsystabs are decoded. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- V2: Removed redundant error message after call to uv_bios_init. Removed redundant error message after call to decode_uv_systab. Clarify selection of UV4 and higher when checking for extended UVsystab in decode_uv_systab(). --- arch/x86/kernel/apic/x2apic_uv_x.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -1303,7 +1303,8 @@ static int __init decode_uv_systab(void) struct uv_systab *st; int i; - if (uv_hub_info->hub_revision < UV4_HUB_REVISION_BASE) + /* If system is uv3 or lower, there is no extended UVsystab */ + if (is_uv_hubbed(0xfffffe) < uv(4) && is_uv_hubless(0xfffffe) < uv(4)) return 0; /* No extended UVsystab required */ st = uv_systab; @@ -1554,8 +1555,15 @@ static __init int uv_system_init_hubless /* Init kernel/BIOS interface */ rc = uv_bios_init(); + if (rc < 0) + return rc; - /* Create user access node if UVsystab available */ + /* Process UVsystab */ + rc = decode_uv_systab(); + if (rc < 0) + return rc; + + /* Create user access node */ if (rc >= 0) uv_setup_proc_files(1); --
[-- Attachment #1: check-efi-boot --] [-- Type: text/plain, Size: 1579 bytes --] Change to checking for EFI Boot type from previous check on if this is a KDUMP kernel. This allows for KDUMP kernels that can handle EFI reboots. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- arch/x86/kernel/apic/x2apic_uv_x.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) --- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c +++ linux/arch/x86/kernel/apic/x2apic_uv_x.c @@ -15,6 +15,7 @@ #include <linux/export.h> #include <linux/pci.h> #include <linux/acpi.h> +#include <linux/efi.h> #include <asm/e820/api.h> #include <asm/uv/uv_mmrs.h> @@ -1483,6 +1484,14 @@ static void __init build_socket_tables(v } } +/* Check which reboot to use */ +static void check_efi_reboot(void) +{ + /* If EFI reboot not available, use ACPI reboot */ + if (!efi_enabled(EFI_BOOT)) + reboot_type = BOOT_ACPI; +} + /* Setup user proc fs files */ static int proc_hubbed_show(struct seq_file *file, void *data) { @@ -1571,6 +1580,8 @@ static __init int uv_system_init_hubless if (rc >= 0) uv_setup_proc_files(1); + check_efi_reboot(); + return rc; } @@ -1704,12 +1715,7 @@ static void __init uv_system_init_hub(vo /* Register Legacy VGA I/O redirection handler: */ pci_register_set_vga_state(uv_set_vga_state); - /* - * For a kdump kernel the reset must be BOOT_ACPI, not BOOT_EFI, as - * EFI is not enabled in the kdump kernel: - */ - if (is_kdump_kernel()) - reboot_type = BOOT_ACPI; + check_efi_reboot(); } /* --
[-- Attachment #1: mod-is_uvX_hub --] [-- Type: text/plain, Size: 3221 bytes --] The references in the is_uvX_hub() function uses the hub_info pointer which will be NULL when the system is hubless. This change avoids that NULL dereference. It is also an optimization in performance. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> --- V2: Add WARNING that the is UVx supported defines will be removed. --- arch/x86/include/asm/uv/.uv_hub.h.swp |binary arch/x86/include/asm/uv/uv_hub.h | 61 ++++++++++++--------------------------- 1 file changed, 20 insertions(+), 41 deletions(-) Binary files linux.orig/arch/x86/include/asm/uv/.uv_hub.h.swp and linux/arch/x86/include/asm/uv/.uv_hub.h.swp differ --- linux.orig/arch/x86/include/asm/uv/uv_hub.h +++ linux/arch/x86/include/asm/uv/uv_hub.h @@ -19,6 +19,7 @@ #include <linux/topology.h> #include <asm/types.h> #include <asm/percpu.h> +#include <asm/uv/uv.h> #include <asm/uv/uv_mmrs.h> #include <asm/uv/bios.h> #include <asm/irq_vectors.h> @@ -243,83 +244,61 @@ static inline int uv_hub_info_check(int #define UV4_HUB_REVISION_BASE 7 #define UV4A_HUB_REVISION_BASE 8 /* UV4 (fixed) rev 2 */ -#ifdef UV1_HUB_IS_SUPPORTED +/* WARNING: UVx_HUB_IS_SUPPORTED defines are deprecated and will be removed */ static inline int is_uv1_hub(void) { - return uv_hub_info->hub_revision < UV2_HUB_REVISION_BASE; -} +#ifdef UV1_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(1)); #else -static inline int is_uv1_hub(void) -{ return 0; -} #endif +} -#ifdef UV2_HUB_IS_SUPPORTED static inline int is_uv2_hub(void) { - return ((uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE) && - (uv_hub_info->hub_revision < UV3_HUB_REVISION_BASE)); -} +#ifdef UV2_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(2)); #else -static inline int is_uv2_hub(void) -{ return 0; -} #endif +} -#ifdef UV3_HUB_IS_SUPPORTED static inline int is_uv3_hub(void) { - return ((uv_hub_info->hub_revision >= UV3_HUB_REVISION_BASE) && - (uv_hub_info->hub_revision < UV4_HUB_REVISION_BASE)); -} +#ifdef UV3_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(3)); #else -static inline int is_uv3_hub(void) -{ return 0; -} #endif +} /* First test "is UV4A", then "is UV4" */ -#ifdef UV4A_HUB_IS_SUPPORTED -static inline int is_uv4a_hub(void) -{ - return (uv_hub_info->hub_revision >= UV4A_HUB_REVISION_BASE); -} -#else static inline int is_uv4a_hub(void) { +#ifdef UV4A_HUB_IS_SUPPORTED + if (is_uv_hubbed(uv(4))) + return (uv_hub_info->hub_revision == UV4A_HUB_REVISION_BASE); +#endif return 0; } -#endif -#ifdef UV4_HUB_IS_SUPPORTED static inline int is_uv4_hub(void) { - return uv_hub_info->hub_revision >= UV4_HUB_REVISION_BASE; -} +#ifdef UV4_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(4)); #else -static inline int is_uv4_hub(void) -{ return 0; -} #endif +} static inline int is_uvx_hub(void) { - if (uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE) - return uv_hub_info->hub_revision; - - return 0; + return (is_uv_hubbed(-2) >= uv(2)); } static inline int is_uv_hub(void) { -#ifdef UV1_HUB_IS_SUPPORTED - return uv_hub_info->hub_revision; -#endif - return is_uvx_hub(); + return is_uv1_hub() || is_uvx_hub(); } union uvh_apicid { --
* Mike Travis <mike.travis@hpe.com> wrote:
> @@ -1596,7 +1687,7 @@ static void __init uv_system_init_hub(vo
> uv_nmi_setup();
> uv_cpu_init();
> uv_scir_register_cpu_notifier();
> - proc_mkdir("sgi_uv", NULL);
> + uv_setup_proc_files(0);
This slipped through previously: platform drivers have absolutely no
business mucking in /proc.
Please describe the hardware via sysfs as pretty much everyone else does.
Thanks,
Ingo
* Mike Travis <mike.travis@hpe.com> wrote:
> +/* Initialize UV hubless systems */
> +static __init int uv_system_init_hubless(void)
> +{
> + int rc;
> +
> + /* Setup PCH NMI handler */
> + uv_nmi_setup_hubless();
> +
> + /* Init kernel/BIOS interface */
> + rc = uv_bios_init();
> +
> + return rc;
> +}
Am I the only one who immediately sees the trivial C transformation
through which this function could lose a local variable and become 4
lines shorter?
And this function got two Reviewed-by tags...
Thanks,
Ingo
On 9/10/2019 11:04 PM, Ingo Molnar wrote:
>
> * Mike Travis <mike.travis@hpe.com> wrote:
>
>> @@ -1596,7 +1687,7 @@ static void __init uv_system_init_hub(vo
>> uv_nmi_setup();
>> uv_cpu_init();
>> uv_scir_register_cpu_notifier();
>> - proc_mkdir("sgi_uv", NULL);
>> + uv_setup_proc_files(0);
>
> This slipped through previously: platform drivers have absolutely no
> business mucking in /proc.
>
> Please describe the hardware via sysfs as pretty much everyone else does.
>
> Thanks,
>
> Ingo
>
If I was doing it now I definitely would put it in the sysfs realm. The
problem is Jack did it back in (I think) 2007. The earliest commit I
could find:
commit a3d732f93785da17e0137210deadb4616f5536fc
Author: Cliff Wickman <cpw@sgi.com>
Date: Mon Nov 10 16:16:31 2008 -0600
x86, UV: fix redundant creation of sgi_uv
Impact: fix double entry creation in /proc
And in the past 12 years probably a hundred user programs are now keying
of the presence of /proc/sgi_uv to signal this is indeed a UV system.
Changing the location of this node also affects all the UV utilities
including those not written by us.
On 9/10/2019 11:07 PM, Ingo Molnar wrote: > > * Mike Travis <mike.travis@hpe.com> wrote: > >> +/* Initialize UV hubless systems */ >> +static __init int uv_system_init_hubless(void) >> +{ >> + int rc; >> + >> + /* Setup PCH NMI handler */ >> + uv_nmi_setup_hubless(); >> + >> + /* Init kernel/BIOS interface */ >> + rc = uv_bios_init(); >> + >> + return rc; >> +} This looks like an excessive cleanup error by me. The original was: > +static __init int uv_system_init_hubless(void) > +{ > + int rc; > + > + /* Setup PCH NMI handler */ > + uv_nmi_setup_hubless(); > + > + /* Init kernel/BIOS interface */ > + rc = uv_bios_init(); > + > + /* Create user access node if UVsystab available */ > + if (rc >= 0) > + uv_setup_proc_files(1); > + > + return rc; > +} > + Hubbed UV's do not have a non-UV BIOS, but hubless systems in theory can. So uv_bios_init can fail on hubless systems if it has some other BIOS (unlikely but possible). So I removed too much in this cleanup. I'll send another patch set to puts this back. Thanks, Mike > > Am I the only one who immediately sees the trivial C transformation > through which this function could lose a local variable and become 4 > lines shorter? > > And this function got two Reviewed-by tags... > > Thanks, > > Ingo >
On 9/11/2019 1:44 PM, Mike Travis wrote: > > > On 9/10/2019 11:07 PM, Ingo Molnar wrote: >> >> * Mike Travis <mike.travis@hpe.com> wrote: >> >>> +/* Initialize UV hubless systems */ >>> +static __init int uv_system_init_hubless(void) >>> +{ >>> + int rc; >>> + >>> + /* Setup PCH NMI handler */ >>> + uv_nmi_setup_hubless(); >>> + >>> + /* Init kernel/BIOS interface */ >>> + rc = uv_bios_init(); >>> + >>> + return rc; >>> +} > > This looks like an excessive cleanup error by me. The original was: > >> +static __init int uv_system_init_hubless(void) >> +{ >> + int rc; >> + >> + /* Setup PCH NMI handler */ >> + uv_nmi_setup_hubless(); >> + >> + /* Init kernel/BIOS interface */ >> + rc = uv_bios_init(); >> + >> + /* Create user access node if UVsystab available */ >> + if (rc >= 0) >> + uv_setup_proc_files(1); >> + >> + return rc; >> +} >> + > > Hubbed UV's do not have a non-UV BIOS, but hubless systems in theory > can. So uv_bios_init can fail on hubless systems if it has some other > BIOS (unlikely but possible). So I removed too much in this cleanup. > I'll send another patch set that puts this back. I discovered the problem... In a rearrangement of the patches this change does happen but in a later patch [5/8]: /* Initialize UV hubless systems */ static __init int uv_system_init_hubless(void) { @@ -1468,6 +1555,10 @@ static __init int uv_system_init_hubless /* Init kernel/BIOS interface */ rc = uv_bios_init(); + /* Create user access node if UVsystab available */ + if (rc >= 0) + uv_setup_proc_files(1); + return rc; } The mistake you saw [in patch 3/8] is very short lived... Hopefully no need for another patch set? > > Thanks, > Mike > >> >> Am I the only one who immediately sees the trivial C transformation >> through which this function could lose a local variable and become 4 >> lines shorter? >> >> And this function got two Reviewed-by tags... >> >> Thanks, >> >> Ingo >>
The following commit has been merged into the x86/platform branch of tip: Commit-ID: 8785968bce1cc7368ea95c3e1e5b9210f56f6667 Gitweb: https://git.kernel.org/tip/8785968bce1cc7368ea95c3e1e5b9210f56f6667 Author: Mike Travis <mike.travis@hpe.com> AuthorDate: Tue, 10 Sep 2019 09:58:44 -05:00 Committer: Ingo Molnar <mingo@kernel.org> CommitterDate: Mon, 07 Oct 2019 13:42:10 +02:00 x86/platform/uv: Add UV Hubbed/Hubless Proc FS Files Indicate to UV user utilities that UV hubless support is available on this system via the existing /proc infterface. The current interface is maintained with the addition of new /proc leaves ("hubbed", "hubless", and "oemid") that contain the specific type of UV arch this one is. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Christoph Hellwig <hch@infradead.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Justin Ernst <justin.ernst@hpe.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: https://lkml.kernel.org/r/20190910145840.055590900@stormcage.eag.rdlabs.hpecorp.net Signed-off-by: Ingo Molnar <mingo@kernel.org> --- arch/x86/include/asm/uv/uv.h | 4 +- arch/x86/kernel/apic/x2apic_uv_x.c | 93 ++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h index 792faab..45ea95c 100644 --- a/arch/x86/include/asm/uv/uv.h +++ b/arch/x86/include/asm/uv/uv.h @@ -12,6 +12,8 @@ struct mm_struct; #ifdef CONFIG_X86_UV #include <linux/efi.h> +#define UV_PROC_NODE "sgi_uv" + static inline int uv(int uvtype) { /* uv(0) is "any" */ @@ -28,6 +30,7 @@ static inline bool is_early_uv_system(void) return uv_systab_phys && uv_systab_phys != EFI_INVALID_TABLE_ADDR; } extern int is_uv_system(void); +extern int is_uv_hubbed(int uvtype); extern int is_uv_hubless(int uvtype); extern void uv_cpu_init(void); extern void uv_nmi_init(void); @@ -40,6 +43,7 @@ extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } static inline bool is_early_uv_system(void) { return 0; } static inline int is_uv_system(void) { return 0; } +static inline int is_uv_hubbed(int uv) { return 0; } static inline int is_uv_hubless(int uv) { return 0; } static inline void uv_cpu_init(void) { } static inline void uv_system_init(void) { } diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 14554a3..b505905 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -26,6 +26,7 @@ static DEFINE_PER_CPU(int, x2apic_extra_bits); static enum uv_system_type uv_system_type; +static int uv_hubbed_system; static int uv_hubless_system; static u64 gru_start_paddr, gru_end_paddr; static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr; @@ -309,6 +310,24 @@ static int __init uv_acpi_madt_oem_check(char *_oem_id, char *_oem_table_id) if (uv_hub_info->hub_revision == 0) goto badbios; + switch (uv_hub_info->hub_revision) { + case UV4_HUB_REVISION_BASE: + uv_hubbed_system = 0x11; + break; + + case UV3_HUB_REVISION_BASE: + uv_hubbed_system = 0x9; + break; + + case UV2_HUB_REVISION_BASE: + uv_hubbed_system = 0x5; + break; + + case UV1_HUB_REVISION_BASE: + uv_hubbed_system = 0x3; + break; + } + pnodeid = early_get_pnodeid(); early_get_apic_socketid_shift(); @@ -359,6 +378,12 @@ int is_uv_system(void) } EXPORT_SYMBOL_GPL(is_uv_system); +int is_uv_hubbed(int uvtype) +{ + return (uv_hubbed_system & uvtype); +} +EXPORT_SYMBOL_GPL(is_uv_hubbed); + int is_uv_hubless(int uvtype) { return (uv_hubless_system & uvtype); @@ -1457,6 +1482,68 @@ static void __init build_socket_tables(void) } } +/* Setup user proc fs files */ +static int proc_hubbed_show(struct seq_file *file, void *data) +{ + seq_printf(file, "0x%x\n", uv_hubbed_system); + return 0; +} + +static int proc_hubless_show(struct seq_file *file, void *data) +{ + seq_printf(file, "0x%x\n", uv_hubless_system); + return 0; +} + +static int proc_oemid_show(struct seq_file *file, void *data) +{ + seq_printf(file, "%s/%s\n", oem_id, oem_table_id); + return 0; +} + +static int proc_hubbed_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_hubbed_show, (void *)NULL); +} + +static int proc_hubless_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_hubless_show, (void *)NULL); +} + +static int proc_oemid_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_oemid_show, (void *)NULL); +} + +/* (struct is "non-const" as open function is set at runtime) */ +static struct file_operations proc_version_fops = { + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_oemid_fops = { + .open = proc_oemid_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static __init void uv_setup_proc_files(int hubless) +{ + struct proc_dir_entry *pde; + char *name = hubless ? "hubless" : "hubbed"; + + pde = proc_mkdir(UV_PROC_NODE, NULL); + proc_create("oemid", 0, pde, &proc_oemid_fops); + proc_create(name, 0, pde, &proc_version_fops); + if (hubless) + proc_version_fops.open = proc_hubless_open; + else + proc_version_fops.open = proc_hubbed_open; +} + /* Initialize UV hubless systems */ static __init int uv_system_init_hubless(void) { @@ -1468,6 +1555,10 @@ static __init int uv_system_init_hubless(void) /* Init kernel/BIOS interface */ rc = uv_bios_init(); + /* Create user access node if UVsystab available */ + if (rc >= 0) + uv_setup_proc_files(1); + return rc; } @@ -1596,7 +1687,7 @@ static void __init uv_system_init_hub(void) uv_nmi_setup(); uv_cpu_init(); uv_scir_register_cpu_notifier(); - proc_mkdir("sgi_uv", NULL); + uv_setup_proc_files(0); /* Register Legacy VGA I/O redirection handler: */ pci_register_set_vga_state(uv_set_vga_state);
The following commit has been merged into the x86/platform branch of tip: Commit-ID: 2bcf26528787d92333ed0dfd6abc9835b8e97eab Gitweb: https://git.kernel.org/tip/2bcf26528787d92333ed0dfd6abc9835b8e97eab Author: Mike Travis <mike.travis@hpe.com> AuthorDate: Tue, 10 Sep 2019 09:58:43 -05:00 Committer: Ingo Molnar <mingo@kernel.org> CommitterDate: Mon, 07 Oct 2019 13:42:10 +02:00 x86/platform/uv: Setup UV functions for Hubless UV Systems Add more support for UV systems that do not contain a UV Hub (AKA "hubless"). This update adds support for additional functions required: Use PCH NMI handler instead of a UV Hub NMI handler. Initialize the UV BIOS callback interface used to support specific UV functions. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Christoph Hellwig <hch@infradead.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Justin Ernst <justin.ernst@hpe.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: https://lkml.kernel.org/r/20190910145839.975787119@stormcage.eag.rdlabs.hpecorp.net Signed-off-by: Ingo Molnar <mingo@kernel.org> --- arch/x86/kernel/apic/x2apic_uv_x.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 43fad61..14554a3 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -1457,6 +1457,20 @@ static void __init build_socket_tables(void) } } +/* Initialize UV hubless systems */ +static __init int uv_system_init_hubless(void) +{ + int rc; + + /* Setup PCH NMI handler */ + uv_nmi_setup_hubless(); + + /* Init kernel/BIOS interface */ + rc = uv_bios_init(); + + return rc; +} + static void __init uv_system_init_hub(void) { struct uv_hub_info_s hub_info = {0}; @@ -1596,8 +1610,8 @@ static void __init uv_system_init_hub(void) } /* - * There is a small amount of UV specific code needed to initialize a - * UV system that does not have a "UV HUB" (referred to as "hubless"). + * There is a different code path needed to initialize a UV system that does + * not have a "UV HUB" (referred to as "hubless"). */ void __init uv_system_init(void) { @@ -1607,7 +1621,7 @@ void __init uv_system_init(void) if (is_uv_system()) uv_system_init_hub(); else - uv_nmi_setup_hubless(); + uv_system_init_hubless(); } apic_driver(apic_x2apic_uv_x);
The following commit has been merged into the x86/platform branch of tip: Commit-ID: 4fb7d08707565d27ec84a364d011043ade8c38b4 Gitweb: https://git.kernel.org/tip/4fb7d08707565d27ec84a364d011043ade8c38b4 Author: Mike Travis <mike.travis@hpe.com> AuthorDate: Tue, 10 Sep 2019 09:58:47 -05:00 Committer: Ingo Molnar <mingo@kernel.org> CommitterDate: Mon, 07 Oct 2019 13:42:11 +02:00 x86/platform/uv: Account for UV Hubless in is_uvX_hub Ops The references in the is_uvX_hub() function uses the hub_info pointer which will be NULL when the system is hubless. This change avoids that NULL dereference. It is also an optimization in performance. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Christoph Hellwig <hch@infradead.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Justin Ernst <justin.ernst@hpe.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: https://lkml.kernel.org/r/20190910145840.294981941@stormcage.eag.rdlabs.hpecorp.net Signed-off-by: Ingo Molnar <mingo@kernel.org> --- arch/x86/include/asm/uv/uv_hub.h | 61 ++++++++++--------------------- 1 file changed, 20 insertions(+), 41 deletions(-) diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h index 44cf6d6..950cd13 100644 --- a/arch/x86/include/asm/uv/uv_hub.h +++ b/arch/x86/include/asm/uv/uv_hub.h @@ -19,6 +19,7 @@ #include <linux/topology.h> #include <asm/types.h> #include <asm/percpu.h> +#include <asm/uv/uv.h> #include <asm/uv/uv_mmrs.h> #include <asm/uv/bios.h> #include <asm/irq_vectors.h> @@ -243,83 +244,61 @@ static inline int uv_hub_info_check(int version) #define UV4_HUB_REVISION_BASE 7 #define UV4A_HUB_REVISION_BASE 8 /* UV4 (fixed) rev 2 */ -#ifdef UV1_HUB_IS_SUPPORTED +/* WARNING: UVx_HUB_IS_SUPPORTED defines are deprecated and will be removed */ static inline int is_uv1_hub(void) { - return uv_hub_info->hub_revision < UV2_HUB_REVISION_BASE; -} +#ifdef UV1_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(1)); #else -static inline int is_uv1_hub(void) -{ return 0; -} #endif +} -#ifdef UV2_HUB_IS_SUPPORTED static inline int is_uv2_hub(void) { - return ((uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE) && - (uv_hub_info->hub_revision < UV3_HUB_REVISION_BASE)); -} +#ifdef UV2_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(2)); #else -static inline int is_uv2_hub(void) -{ return 0; -} #endif +} -#ifdef UV3_HUB_IS_SUPPORTED static inline int is_uv3_hub(void) { - return ((uv_hub_info->hub_revision >= UV3_HUB_REVISION_BASE) && - (uv_hub_info->hub_revision < UV4_HUB_REVISION_BASE)); -} +#ifdef UV3_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(3)); #else -static inline int is_uv3_hub(void) -{ return 0; -} #endif +} /* First test "is UV4A", then "is UV4" */ -#ifdef UV4A_HUB_IS_SUPPORTED -static inline int is_uv4a_hub(void) -{ - return (uv_hub_info->hub_revision >= UV4A_HUB_REVISION_BASE); -} -#else static inline int is_uv4a_hub(void) { +#ifdef UV4A_HUB_IS_SUPPORTED + if (is_uv_hubbed(uv(4))) + return (uv_hub_info->hub_revision == UV4A_HUB_REVISION_BASE); +#endif return 0; } -#endif -#ifdef UV4_HUB_IS_SUPPORTED static inline int is_uv4_hub(void) { - return uv_hub_info->hub_revision >= UV4_HUB_REVISION_BASE; -} +#ifdef UV4_HUB_IS_SUPPORTED + return is_uv_hubbed(uv(4)); #else -static inline int is_uv4_hub(void) -{ return 0; -} #endif +} static inline int is_uvx_hub(void) { - if (uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE) - return uv_hub_info->hub_revision; - - return 0; + return (is_uv_hubbed(-2) >= uv(2)); } static inline int is_uv_hub(void) { -#ifdef UV1_HUB_IS_SUPPORTED - return uv_hub_info->hub_revision; -#endif - return is_uvx_hub(); + return is_uv1_hub() || is_uvx_hub(); } union uvh_apicid {
The following commit has been merged into the x86/platform branch of tip: Commit-ID: f5a8f0ecb436a15f50215f27ab70a2e8626a6135 Gitweb: https://git.kernel.org/tip/f5a8f0ecb436a15f50215f27ab70a2e8626a6135 Author: Mike Travis <mike.travis@hpe.com> AuthorDate: Tue, 10 Sep 2019 09:58:45 -05:00 Committer: Ingo Molnar <mingo@kernel.org> CommitterDate: Mon, 07 Oct 2019 13:42:11 +02:00 x86/platform/uv: Decode UVsystab Info Decode the hubless UVsystab passed from BIOS to the kernel saving pertinent info in a similar manner that hubbed UVsystabs are decoded. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Christoph Hellwig <hch@infradead.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Justin Ernst <justin.ernst@hpe.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: https://lkml.kernel.org/r/20190910145840.135325066@stormcage.eag.rdlabs.hpecorp.net Signed-off-by: Ingo Molnar <mingo@kernel.org> --- arch/x86/kernel/apic/x2apic_uv_x.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index b505905..ec940ad 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -1303,7 +1303,8 @@ static int __init decode_uv_systab(void) struct uv_systab *st; int i; - if (uv_hub_info->hub_revision < UV4_HUB_REVISION_BASE) + /* If system is uv3 or lower, there is no extended UVsystab */ + if (is_uv_hubbed(0xfffffe) < uv(4) && is_uv_hubless(0xfffffe) < uv(4)) return 0; /* No extended UVsystab required */ st = uv_systab; @@ -1554,8 +1555,15 @@ static __init int uv_system_init_hubless(void) /* Init kernel/BIOS interface */ rc = uv_bios_init(); + if (rc < 0) + return rc; - /* Create user access node if UVsystab available */ + /* Process UVsystab */ + rc = decode_uv_systab(); + if (rc < 0) + return rc; + + /* Create user access node */ if (rc >= 0) uv_setup_proc_files(1);
The following commit has been merged into the x86/platform branch of tip: Commit-ID: df55029f7ea65d8c653a79dd728918dfe25b1356 Gitweb: https://git.kernel.org/tip/df55029f7ea65d8c653a79dd728918dfe25b1356 Author: Mike Travis <mike.travis@hpe.com> AuthorDate: Tue, 10 Sep 2019 09:58:46 -05:00 Committer: Ingo Molnar <mingo@kernel.org> CommitterDate: Mon, 07 Oct 2019 13:42:11 +02:00 x86/platform/uv: Check EFI Boot to set reboot type Change to checking for EFI Boot type from previous check on if this is a KDUMP kernel. This allows for KDUMP kernels that can handle EFI reboots. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Christoph Hellwig <hch@infradead.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Justin Ernst <justin.ernst@hpe.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: https://lkml.kernel.org/r/20190910145840.215091717@stormcage.eag.rdlabs.hpecorp.net Signed-off-by: Ingo Molnar <mingo@kernel.org> --- arch/x86/kernel/apic/x2apic_uv_x.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index ec940ad..d5b51a7 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -15,6 +15,7 @@ #include <linux/export.h> #include <linux/pci.h> #include <linux/acpi.h> +#include <linux/efi.h> #include <asm/e820/api.h> #include <asm/uv/uv_mmrs.h> @@ -1483,6 +1484,14 @@ static void __init build_socket_tables(void) } } +/* Check which reboot to use */ +static void check_efi_reboot(void) +{ + /* If EFI reboot not available, use ACPI reboot */ + if (!efi_enabled(EFI_BOOT)) + reboot_type = BOOT_ACPI; +} + /* Setup user proc fs files */ static int proc_hubbed_show(struct seq_file *file, void *data) { @@ -1567,6 +1576,8 @@ static __init int uv_system_init_hubless(void) if (rc >= 0) uv_setup_proc_files(1); + check_efi_reboot(); + return rc; } @@ -1700,12 +1711,7 @@ static void __init uv_system_init_hub(void) /* Register Legacy VGA I/O redirection handler: */ pci_register_set_vga_state(uv_set_vga_state); - /* - * For a kdump kernel the reset must be BOOT_ACPI, not BOOT_EFI, as - * EFI is not enabled in the kdump kernel: - */ - if (is_kdump_kernel()) - reboot_type = BOOT_ACPI; + check_efi_reboot(); } /*
The following commit has been merged into the x86/platform branch of tip: Commit-ID: 9743cb68f736d986481edba4d00de454d2faa0ec Gitweb: https://git.kernel.org/tip/9743cb68f736d986481edba4d00de454d2faa0ec Author: Mike Travis <mike.travis@hpe.com> AuthorDate: Tue, 10 Sep 2019 09:58:42 -05:00 Committer: Ingo Molnar <mingo@kernel.org> CommitterDate: Mon, 07 Oct 2019 13:42:10 +02:00 x86/platform/uv: Add return code to UV BIOS Init function Add a return code to the UV BIOS init function that indicates the successful initialization of the kernel/BIOS callback interface. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Christoph Hellwig <hch@infradead.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Justin Ernst <justin.ernst@hpe.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: https://lkml.kernel.org/r/20190910145839.895739629@stormcage.eag.rdlabs.hpecorp.net Signed-off-by: Ingo Molnar <mingo@kernel.org> --- arch/x86/include/asm/uv/bios.h | 2 +- arch/x86/platform/uv/bios_uv.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/uv/bios.h b/arch/x86/include/asm/uv/bios.h index 6e7caf6..389174e 100644 --- a/arch/x86/include/asm/uv/bios.h +++ b/arch/x86/include/asm/uv/bios.h @@ -138,7 +138,7 @@ extern s64 uv_bios_change_memprotect(u64, u64, enum uv_memprotect); extern s64 uv_bios_reserved_page_pa(u64, u64 *, u64 *, u64 *); extern int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus); -extern void uv_bios_init(void); +extern int uv_bios_init(void); extern unsigned long sn_rtc_cycles_per_second; extern int uv_type; diff --git a/arch/x86/platform/uv/bios_uv.c b/arch/x86/platform/uv/bios_uv.c index c2ee319..ece9cb9 100644 --- a/arch/x86/platform/uv/bios_uv.c +++ b/arch/x86/platform/uv/bios_uv.c @@ -184,20 +184,20 @@ int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus) } EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target); -void uv_bios_init(void) +int uv_bios_init(void) { uv_systab = NULL; if ((uv_systab_phys == EFI_INVALID_TABLE_ADDR) || !uv_systab_phys || efi_runtime_disabled()) { pr_crit("UV: UVsystab: missing\n"); - return; + return -EEXIST; } uv_systab = ioremap(uv_systab_phys, sizeof(struct uv_systab)); if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) { pr_err("UV: UVsystab: bad signature!\n"); iounmap(uv_systab); - return; + return -EINVAL; } /* Starting with UV4 the UV systab size is variable */ @@ -208,8 +208,9 @@ void uv_bios_init(void) uv_systab = ioremap(uv_systab_phys, size); if (!uv_systab) { pr_err("UV: UVsystab: ioremap(%d) failed!\n", size); - return; + return -EFAULT; } } pr_info("UV: UVsystab: Revision:%x\n", uv_systab->revision); + return 0; }
The following commit has been merged into the x86/platform branch of tip: Commit-ID: 61e5ddca9c2a312f933bf5b12bc08484189fefe6 Gitweb: https://git.kernel.org/tip/61e5ddca9c2a312f933bf5b12bc08484189fefe6 Author: Mike Travis <mike.travis@hpe.com> AuthorDate: Tue, 10 Sep 2019 09:58:40 -05:00 Committer: Ingo Molnar <mingo@kernel.org> CommitterDate: Mon, 07 Oct 2019 13:42:09 +02:00 x86/platform/uv: Save OEM_ID from ACPI MADT probe Save the OEM_ID and OEM_TABLE_ID passed to the apic driver probe function for later use. Also, convert the char list arg passed from the kernel to a true null-terminated string. Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Christoph Hellwig <hch@infradead.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Justin Ernst <justin.ernst@hpe.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: https://lkml.kernel.org/r/20190910145839.732237241@stormcage.eag.rdlabs.hpecorp.net Signed-off-by: Ingo Molnar <mingo@kernel.org> --- arch/x86/kernel/apic/x2apic_uv_x.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index e6230af..66b38a6 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -14,6 +14,7 @@ #include <linux/memory.h> #include <linux/export.h> #include <linux/pci.h> +#include <linux/acpi.h> #include <asm/e820/api.h> #include <asm/uv/uv_mmrs.h> @@ -31,6 +32,10 @@ static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr; static u64 gru_dist_lmask, gru_dist_umask; static union uvh_apicid uvh_apicid; +/* Unpack OEM/TABLE ID's to be NULL terminated strings */ +static u8 oem_id[ACPI_OEM_ID_SIZE + 1]; +static u8 oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; + /* Information derived from CPUID: */ static struct { unsigned int apicid_shift; @@ -248,11 +253,20 @@ static void __init uv_set_apicid_hibit(void) } } -static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static void __init uv_stringify(int len, char *to, char *from) +{ + /* Relies on 'to' being NULL chars so result will be NULL terminated */ + strncpy(to, from, len-1); +} + +static int __init uv_acpi_madt_oem_check(char *_oem_id, char *_oem_table_id) { int pnodeid; int uv_apic; + uv_stringify(sizeof(oem_id), oem_id, _oem_id); + uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id); + if (strncmp(oem_id, "SGI", 3) != 0) { if (strncmp(oem_id, "NSGI", 4) == 0) { uv_hubless_system = true;
The following commit has been merged into the x86/platform branch of tip: Commit-ID: 0959f8256ada0431c1470d89e5a2811ff2305c88 Gitweb: https://git.kernel.org/tip/0959f8256ada0431c1470d89e5a2811ff2305c88 Author: Mike Travis <mike.travis@hpe.com> AuthorDate: Tue, 10 Sep 2019 09:58:41 -05:00 Committer: Ingo Molnar <mingo@kernel.org> CommitterDate: Mon, 07 Oct 2019 13:42:10 +02:00 x86/platform/uv: Return UV Hubless System Type Return the type of UV hubless system for UV specific code that depends on that. Add a function to convert UV system type to bit pattern needed for is_uv_hubless(). Signed-off-by: Mike Travis <mike.travis@hpe.com> Reviewed-by: Steve Wahl <steve.wahl@hpe.com> Reviewed-by: Dimitri Sivanich <dimitri.sivanich@hpe.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Christoph Hellwig <hch@infradead.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Hedi Berriche <hedi.berriche@hpe.com> Cc: Justin Ernst <justin.ernst@hpe.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Russ Anderson <russ.anderson@hpe.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: https://lkml.kernel.org/r/20190910145839.814880843@stormcage.eag.rdlabs.hpecorp.net Signed-off-by: Ingo Molnar <mingo@kernel.org> --- arch/x86/include/asm/uv/uv.h | 12 ++++++++++-- arch/x86/kernel/apic/x2apic_uv_x.c | 27 ++++++++++++++++++--------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h index 6bc6d89..792faab 100644 --- a/arch/x86/include/asm/uv/uv.h +++ b/arch/x86/include/asm/uv/uv.h @@ -12,6 +12,14 @@ struct mm_struct; #ifdef CONFIG_X86_UV #include <linux/efi.h> +static inline int uv(int uvtype) +{ + /* uv(0) is "any" */ + if (uvtype >= 0 && uvtype <= 30) + return 1 << uvtype; + return 1; +} + extern unsigned long uv_systab_phys; extern enum uv_system_type get_uv_system_type(void); @@ -20,7 +28,7 @@ static inline bool is_early_uv_system(void) return uv_systab_phys && uv_systab_phys != EFI_INVALID_TABLE_ADDR; } extern int is_uv_system(void); -extern int is_uv_hubless(void); +extern int is_uv_hubless(int uvtype); extern void uv_cpu_init(void); extern void uv_nmi_init(void); extern void uv_system_init(void); @@ -32,7 +40,7 @@ extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } static inline bool is_early_uv_system(void) { return 0; } static inline int is_uv_system(void) { return 0; } -static inline int is_uv_hubless(void) { return 0; } +static inline int is_uv_hubless(int uv) { return 0; } static inline void uv_cpu_init(void) { } static inline void uv_system_init(void) { } static inline const struct cpumask * diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 66b38a6..43fad61 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -26,7 +26,7 @@ static DEFINE_PER_CPU(int, x2apic_extra_bits); static enum uv_system_type uv_system_type; -static bool uv_hubless_system; +static int uv_hubless_system; static u64 gru_start_paddr, gru_end_paddr; static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr; static u64 gru_dist_lmask, gru_dist_umask; @@ -268,11 +268,20 @@ static int __init uv_acpi_madt_oem_check(char *_oem_id, char *_oem_table_id) uv_stringify(sizeof(oem_table_id), oem_table_id, _oem_table_id); if (strncmp(oem_id, "SGI", 3) != 0) { - if (strncmp(oem_id, "NSGI", 4) == 0) { - uv_hubless_system = true; - pr_info("UV: OEM IDs %s/%s, HUBLESS\n", - oem_id, oem_table_id); - } + if (strncmp(oem_id, "NSGI", 4) != 0) + return 0; + + /* UV4 Hubless, CH, (0x11:UV4+Any) */ + if (strncmp(oem_id, "NSGI4", 5) == 0) + uv_hubless_system = 0x11; + + /* UV3 Hubless, UV300/MC990X w/o hub (0x9:UV3+Any) */ + else + uv_hubless_system = 0x9; + + pr_info("UV: OEM IDs %s/%s, HUBLESS(0x%x)\n", + oem_id, oem_table_id, uv_hubless_system); + return 0; } @@ -350,9 +359,9 @@ int is_uv_system(void) } EXPORT_SYMBOL_GPL(is_uv_system); -int is_uv_hubless(void) +int is_uv_hubless(int uvtype) { - return uv_hubless_system; + return (uv_hubless_system & uvtype); } EXPORT_SYMBOL_GPL(is_uv_hubless); @@ -1592,7 +1601,7 @@ static void __init uv_system_init_hub(void) */ void __init uv_system_init(void) { - if (likely(!is_uv_system() && !is_uv_hubless())) + if (likely(!is_uv_system() && !is_uv_hubless(1))) return; if (is_uv_system())