From e3998434da4f5b1f57f8d6a8a9f8502ee3723bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Jo=C5=84czyk?= Date: Tue, 29 Nov 2022 22:50:08 +0100 Subject: [PATCH 1/6] x86/apic: Handle no CONFIG_X86_X2APIC on systems with x2APIC enabled by BIOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A kernel that was compiled without CONFIG_X86_X2APIC was unable to boot on platforms that have x2APIC already enabled in the BIOS before starting the kernel. The kernel was supposed to panic with an approprite error message in validate_x2apic() due to the missing X2APIC support. However, validate_x2apic() was run too late in the boot cycle, and the kernel tried to initialize the APIC nonetheless. This resulted in an earlier panic in setup_local_APIC() because the APIC was not registered. In my experiments, a panic message in setup_local_APIC() was not visible in the graphical console, which resulted in a hang with no indication what has gone wrong. Instead of calling panic(), disable the APIC, which results in a somewhat working system with the PIC only (and no SMP). This way the user is able to diagnose the problem more easily. Disabling X2APIC mode is not an option because it's impossible on systems with locked x2APIC. The proper place to disable the APIC in this case is in check_x2apic(), which is called early from setup_arch(). Doing this in __apic_intr_mode_select() is too late. Make check_x2apic() unconditionally available and remove the empty stub. Reported-by: Paul Menzel Reported-by: Robert Elliott (Servers) Signed-off-by: Mateusz Jończyk Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/lkml/d573ba1c-0dc4-3016-712a-cc23a8a33d42@molgen.mpg.de Link: https://lore.kernel.org/lkml/20220911084711.13694-3-mat.jonczyk@o2.pl Link: https://lore.kernel.org/all/20221129215008.7247-1-mat.jonczyk@o2.pl --- arch/x86/Kconfig | 4 ++-- arch/x86/include/asm/apic.h | 3 +-- arch/x86/kernel/apic/apic.c | 13 ++++++++----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 67745ceab0db..b2c0fce3f257 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -462,8 +462,8 @@ config X86_X2APIC Some Intel systems circa 2022 and later are locked into x2APIC mode and can not fall back to the legacy APIC modes if SGX or TDX are - enabled in the BIOS. They will be unable to boot without enabling - this option. + enabled in the BIOS. They will boot with very reduced functionality + without enabling this option. If you don't know what to do here, say N. diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 3415321c8240..3216da7074ba 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -249,7 +249,6 @@ static inline u64 native_x2apic_icr_read(void) extern int x2apic_mode; extern int x2apic_phys; extern void __init x2apic_set_max_apicid(u32 apicid); -extern void __init check_x2apic(void); extern void x2apic_setup(void); static inline int x2apic_enabled(void) { @@ -258,13 +257,13 @@ static inline int x2apic_enabled(void) #define x2apic_supported() (boot_cpu_has(X86_FEATURE_X2APIC)) #else /* !CONFIG_X86_X2APIC */ -static inline void check_x2apic(void) { } static inline void x2apic_setup(void) { } static inline int x2apic_enabled(void) { return 0; } #define x2apic_mode (0) #define x2apic_supported() (0) #endif /* !CONFIG_X86_X2APIC */ +extern void __init check_x2apic(void); struct irq_data; diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index c6876d3ea4b1..20d9a604da7c 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1931,16 +1931,19 @@ void __init check_x2apic(void) } } #else /* CONFIG_X86_X2APIC */ -static int __init validate_x2apic(void) +void __init check_x2apic(void) { if (!apic_is_x2apic_enabled()) - return 0; + return; /* - * Checkme: Can we simply turn off x2apic here instead of panic? + * Checkme: Can we simply turn off x2APIC here instead of disabling the APIC? */ - panic("BIOS has enabled x2apic but kernel doesn't support x2apic, please disable x2apic in BIOS.\n"); + pr_err("Kernel does not support x2APIC, please recompile with CONFIG_X86_X2APIC.\n"); + pr_err("Disabling APIC, expect reduced performance and functionality.\n"); + + disable_apic = 1; + setup_clear_cpu_cap(X86_FEATURE_APIC); } -early_initcall(validate_x2apic); static inline void try_to_enable_x2apic(int remap_mode) { } static inline void __x2apic_enable(void) { } From 9b09927c0cdec4d4e75f7f9e621eaec179a888fd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 24 Nov 2022 20:48:24 +0200 Subject: [PATCH 2/6] x86/of: Remove unused early_init_dt_add_memory_arch() Recently objtool started complaining about dead code in the object files, in particular vmlinux.o: warning: objtool: early_init_dt_scan_memory+0x191: unreachable instruction when CONFIG_OF=y. Indeed, early_init_dt_scan() is not used on x86 and making it compile (with help of CONFIG_OF) will abrupt the code flow since in the middle of it there is a BUG() instruction. Remove the pointless function. Signed-off-by: Andy Shevchenko Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/r/20221124184824.9548-1-andriy.shevchenko@linux.intel.com --- arch/x86/kernel/devicetree.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 5cd51f25f446..59438d2b204c 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -31,11 +31,6 @@ char __initdata cmd_line[COMMAND_LINE_SIZE]; int __initdata of_ioapic; -void __init early_init_dt_add_memory_arch(u64 base, u64 size) -{ - BUG(); -} - void __init add_dtb(u64 data) { initial_dtb = data + offsetof(struct setup_data, data); From 2b822f474621bb2f4f21dd6dae6900e2ccca7e95 Mon Sep 17 00:00:00 2001 From: Rahul Tanwar Date: Thu, 24 Nov 2022 16:41:40 +0800 Subject: [PATCH 3/6] dt-bindings: x86: apic: Convert Intel's APIC bindings to YAML schema The DT bindings for X86 local APIC (lapic) and I/O APIC (ioapic) are outdated. Rework them: - Convert the bindings for lapic and ioapic from text to YAML schema. - Separate lapic & ioapic schemas. - Add missing but required standard properties - Add missing descriptions Suggested-by: Andy Shevchenko Signed-off-by: Rahul Tanwar Signed-off-by: Thomas Gleixner Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20221124084143.21841-2-rtanwar@maxlinear.com --- .../intel,ce4100-ioapic.txt | 26 -------- .../intel,ce4100-ioapic.yaml | 60 +++++++++++++++++++ .../intel,ce4100-lapic.yaml | 57 ++++++++++++++++++ 3 files changed, 117 insertions(+), 26 deletions(-) delete mode 100644 Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.txt create mode 100644 Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.yaml create mode 100644 Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml diff --git a/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.txt b/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.txt deleted file mode 100644 index 7d19f494f19a..000000000000 --- a/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.txt +++ /dev/null @@ -1,26 +0,0 @@ -Interrupt chips ---------------- - -* Intel I/O Advanced Programmable Interrupt Controller (IO APIC) - - Required properties: - -------------------- - compatible = "intel,ce4100-ioapic"; - #interrupt-cells = <2>; - - Device's interrupt property: - - interrupts =

; - - The first number (P) represents the interrupt pin which is wired to the - IO APIC. The second number (S) represents the sense of interrupt which - should be configured and can be one of: - 0 - Edge Rising - 1 - Level Low - 2 - Level High - 3 - Edge Falling - -* Local APIC - Required property: - - compatible = "intel,ce4100-lapic"; diff --git a/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.yaml b/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.yaml new file mode 100644 index 000000000000..39ab8cdd19b4 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.yaml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/interrupt-controller/intel,ce4100-ioapic.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Intel I/O Advanced Programmable Interrupt Controller (IO APIC) + +maintainers: + - Rahul Tanwar + +description: | + Intel's Advanced Programmable Interrupt Controller (APIC) is a + family of interrupt controllers. The APIC is a split + architecture design, with a local component (LAPIC) integrated + into the processor itself and an external I/O APIC. Local APIC + (lapic) receives interrupts from the processor's interrupt pins, + from internal sources and from an external I/O APIC (ioapic). + And it sends these to the processor core for handling. + See [1] Chapter 8 for more details. + + Many of the Intel's generic devices like hpet, ioapic, lapic have + the ce4100 name in their compatible property names because they + first appeared in CE4100 SoC. + + This schema defines bindings for I/O APIC interrupt controller. + + [1] https://pdos.csail.mit.edu/6.828/2008/readings/ia32/IA32-3A.pdf + +properties: + compatible: + const: intel,ce4100-ioapic + + reg: + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - interrupt-controller + - '#interrupt-cells' + +additionalProperties: false + +examples: + - | + ioapic1: interrupt-controller@fec00000 { + compatible = "intel,ce4100-ioapic"; + reg = <0xfec00000 0x1000>; + interrupt-controller; + #interrupt-cells = <2>; + }; diff --git a/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml b/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml new file mode 100644 index 000000000000..55184cb49432 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/interrupt-controller/intel,ce4100-lapic.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Intel Local Advanced Programmable Interrupt Controller (LAPIC) + +maintainers: + - Rahul Tanwar + +description: | + Intel's Advanced Programmable Interrupt Controller (APIC) is a + family of interrupt controllers. The APIC is a split + architecture design, with a local component (LAPIC) integrated + into the processor itself and an external I/O APIC. Local APIC + (lapic) receives interrupts from the processor's interrupt pins, + from internal sources and from an external I/O APIC (ioapic). + And it sends these to the processor core for handling. + See [1] Chapter 8 for more details. + + Many of the Intel's generic devices like hpet, ioapic, lapic have + the ce4100 name in their compatible property names because they + first appeared in CE4100 SoC. + + This schema defines bindings for local APIC interrupt controller. + + [1] https://pdos.csail.mit.edu/6.828/2008/readings/ia32/IA32-3A.pdf + +properties: + compatible: + const: intel,ce4100-lapic + + reg: + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + +required: + - compatible + - reg + - interrupt-controller + - '#interrupt-cells' + +additionalProperties: false + +examples: + - | + lapic0: interrupt-controller@fee00000 { + compatible = "intel,ce4100-lapic"; + reg = <0xfee00000 0x1000>; + interrupt-controller; + #interrupt-cells = <2>; + }; From b3a9801cccefda304263b4e84e9dfe49057f3c29 Mon Sep 17 00:00:00 2001 From: Rahul Tanwar Date: Thu, 24 Nov 2022 16:41:41 +0800 Subject: [PATCH 4/6] dt-bindings: x86: apic: Introduce new optional bool property for lapic X86 defines a few possible interrupt delivery modes. With respect to boot/init time, mainly two interrupt delivery modes are possible. - PIC Mode: Legacy external 8259 compliant PIC interrupt controller - Virtual Wire Mode: Use lapic as virtual wire interrupt delivery mode ACPI and MPS spec compliant systems provide this information, but for OF based systems, it is by default set to PIC mode. In fact it is hardcoded to legacy PIC mode for OF based x86 systems with no option to choose the configuration between PIC mode & virtual wire mode. For this purpose, introduce a new boolean property for the lapic interrupt controller node which allows to configure it for virtual wire mode as well. Property name: 'intel,virtual-wire-mode' Type: Boolean If not present/not defined, interrupt delivery mode defaults to legacy PIC mode. If present/defined, interrupt delivery mode is set to virtual wire mode. Suggested-by: Andy Shevchenko Signed-off-by: Rahul Tanwar Signed-off-by: Thomas Gleixner Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20221124084143.21841-3-rtanwar@maxlinear.com --- .../interrupt-controller/intel,ce4100-lapic.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml b/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml index 55184cb49432..d2d0145cb889 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml @@ -39,6 +39,19 @@ properties: '#interrupt-cells': const: 2 + intel,virtual-wire-mode: + description: Intel defines a few possible interrupt delivery + modes. With respect to boot/init time, mainly two interrupt + delivery modes are possible. + PIC Mode - Legacy external 8259 compliant PIC interrupt controller. + Virtual Wire Mode - use lapic as virtual wire interrupt delivery mode. + For ACPI or MPS spec compliant systems, it is figured out by some read + only bit field/s available in their respective defined data structures. + For OF based systems, it is by default set to PIC mode. + But if this optional boolean property is set, then the interrupt delivery + mode is configured to virtual wire compatibility mode. + type: boolean + required: - compatible - reg @@ -54,4 +67,5 @@ examples: reg = <0xfee00000 0x1000>; interrupt-controller; #interrupt-cells = <2>; + intel,virtual-wire-mode; }; From 535403323b4dcdc363e7ea265df62481b903826b Mon Sep 17 00:00:00 2001 From: Rahul Tanwar Date: Thu, 24 Nov 2022 16:41:42 +0800 Subject: [PATCH 5/6] x86/of: Replace printk(KERN_LVL) with pr_lvl() Use pr_lvl() instead of the deprecated printk(KERN_LVL). Just a upgrade of print utilities usage. no functional changes. Suggested-by: Andy Shevchenko Signed-off-by: Rahul Tanwar Signed-off-by: Thomas Gleixner Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20221124084143.21841-4-rtanwar@maxlinear.com --- arch/x86/kernel/devicetree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 59438d2b204c..484783fe3658 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -243,7 +243,7 @@ static void __init dtb_add_ioapic(struct device_node *dn) ret = of_address_to_resource(dn, 0, &r); if (ret) { - printk(KERN_ERR "Can't obtain address from device node %pOF.\n", dn); + pr_err("Can't obtain address from device node %pOF.\n", dn); return; } mp_register_ioapic(++ioapic_id, r.start, gsi_top, &cfg); @@ -260,7 +260,7 @@ static void __init dtb_ioapic_setup(void) of_ioapic = 1; return; } - printk(KERN_ERR "Error: No information about IO-APIC in OF.\n"); + pr_err("Error: No information about IO-APIC in OF.\n"); } #else static void __init dtb_ioapic_setup(void) {} From 2833275568755eb937a52c358bf8bfa7125a463e Mon Sep 17 00:00:00 2001 From: Rahul Tanwar Date: Thu, 24 Nov 2022 16:41:43 +0800 Subject: [PATCH 6/6] x86/of: Add support for boot time interrupt delivery mode configuration Presently, init/boot time interrupt delivery mode is enumerated only for ACPI enabled systems by parsing MADT table or for older systems by parsing MP table. But for OF based x86 systems, it is assumed & hardcoded to be legacy PIC mode. This causes a boot time crash for platforms which do not provide a 8259 compliant legacy PIC. Add support for configuration of init time interrupt delivery mode for x86 OF based systems by introducing a new optional boolean property 'intel,virtual-wire-mode' for the local APIC interrupt-controller node. This property emulates IMCRP Bit 7 of MP feature info byte 2 of MP floating pointer structure. Defaults to legacy PIC mode if absent. Configures it to virtual wire compatibility mode if present. Signed-off-by: Rahul Tanwar Signed-off-by: Thomas Gleixner Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20221124084143.21841-5-rtanwar@maxlinear.com --- arch/x86/kernel/devicetree.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 484783fe3658..28da5dd83fc0 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -162,7 +162,14 @@ static void __init dtb_lapic_setup(void) return; } smp_found_config = 1; - pic_mode = 1; + if (of_property_read_bool(dn, "intel,virtual-wire-mode")) { + pr_info("Virtual Wire compatibility mode.\n"); + pic_mode = 0; + } else { + pr_info("IMCR and PIC compatibility mode.\n"); + pic_mode = 1; + } + register_lapic_address(lapic_addr); }