Commit 36901316 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'x86-apic-2022-12-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 apic update from Thomas Gleixner:
 "A set of changes for the x86 APIC code:

   - Handle the case where x2APIC is enabled and locked by the BIOS on a
     kernel with CONFIG_X86_X2APIC=n gracefully.

     Instead of a panic which does not make it to the graphical console
     during very early boot, simply disable the local APIC completely
     and boot with the PIC and very limited functionality, which allows
     to diagnose the issue

   - Convert x86 APIC device tree bindings to YAML

   - Extend x86 APIC device tree bindings to configure interrupt
     delivery mode and handle this in during init. This allows to boot
     with device tree on platforms which lack a legacy PIC"

* tag 'x86-apic-2022-12-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/of: Add support for boot time interrupt delivery mode configuration
  x86/of: Replace printk(KERN_LVL) with pr_lvl()
  dt-bindings: x86: apic: Introduce new optional bool property for lapic
  dt-bindings: x86: apic: Convert Intel's APIC bindings to YAML schema
  x86/of: Remove unused early_init_dt_add_memory_arch()
  x86/apic: Handle no CONFIG_X86_X2APIC on systems with x2APIC enabled by BIOS
parents 08d72bd2 28332755
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 = <P S>;
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";
# 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 <rtanwar@maxlinear.com>
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>;
};
# 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 <rtanwar@maxlinear.com>
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
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
- interrupt-controller
- '#interrupt-cells'
additionalProperties: false
examples:
- |
lapic0: interrupt-controller@fee00000 {
compatible = "intel,ce4100-lapic";
reg = <0xfee00000 0x1000>;
interrupt-controller;
#interrupt-cells = <2>;
intel,virtual-wire-mode;
};
...@@ -463,8 +463,8 @@ config X86_X2APIC ...@@ -463,8 +463,8 @@ config X86_X2APIC
Some Intel systems circa 2022 and later are locked into x2APIC mode 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 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 enabled in the BIOS. They will boot with very reduced functionality
this option. without enabling this option.
If you don't know what to do here, say N. If you don't know what to do here, say N.
......
...@@ -249,7 +249,6 @@ static inline u64 native_x2apic_icr_read(void) ...@@ -249,7 +249,6 @@ static inline u64 native_x2apic_icr_read(void)
extern int x2apic_mode; extern int x2apic_mode;
extern int x2apic_phys; extern int x2apic_phys;
extern void __init x2apic_set_max_apicid(u32 apicid); extern void __init x2apic_set_max_apicid(u32 apicid);
extern void __init check_x2apic(void);
extern void x2apic_setup(void); extern void x2apic_setup(void);
static inline int x2apic_enabled(void) static inline int x2apic_enabled(void)
{ {
...@@ -258,13 +257,13 @@ 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)) #define x2apic_supported() (boot_cpu_has(X86_FEATURE_X2APIC))
#else /* !CONFIG_X86_X2APIC */ #else /* !CONFIG_X86_X2APIC */
static inline void check_x2apic(void) { }
static inline void x2apic_setup(void) { } static inline void x2apic_setup(void) { }
static inline int x2apic_enabled(void) { return 0; } static inline int x2apic_enabled(void) { return 0; }
#define x2apic_mode (0) #define x2apic_mode (0)
#define x2apic_supported() (0) #define x2apic_supported() (0)
#endif /* !CONFIG_X86_X2APIC */ #endif /* !CONFIG_X86_X2APIC */
extern void __init check_x2apic(void);
struct irq_data; struct irq_data;
......
...@@ -1931,16 +1931,19 @@ void __init check_x2apic(void) ...@@ -1931,16 +1931,19 @@ void __init check_x2apic(void)
} }
} }
#else /* CONFIG_X86_X2APIC */ #else /* CONFIG_X86_X2APIC */
static int __init validate_x2apic(void) void __init check_x2apic(void)
{ {
if (!apic_is_x2apic_enabled()) 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 try_to_enable_x2apic(int remap_mode) { }
static inline void __x2apic_enable(void) { } static inline void __x2apic_enable(void) { }
......
...@@ -31,11 +31,6 @@ char __initdata cmd_line[COMMAND_LINE_SIZE]; ...@@ -31,11 +31,6 @@ char __initdata cmd_line[COMMAND_LINE_SIZE];
int __initdata of_ioapic; int __initdata of_ioapic;
void __init early_init_dt_add_memory_arch(u64 base, u64 size)
{
BUG();
}
void __init add_dtb(u64 data) void __init add_dtb(u64 data)
{ {
initial_dtb = data + offsetof(struct setup_data, data); initial_dtb = data + offsetof(struct setup_data, data);
...@@ -167,7 +162,14 @@ static void __init dtb_lapic_setup(void) ...@@ -167,7 +162,14 @@ static void __init dtb_lapic_setup(void)
return; return;
} }
smp_found_config = 1; 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); register_lapic_address(lapic_addr);
} }
...@@ -248,7 +250,7 @@ static void __init dtb_add_ioapic(struct device_node *dn) ...@@ -248,7 +250,7 @@ static void __init dtb_add_ioapic(struct device_node *dn)
ret = of_address_to_resource(dn, 0, &r); ret = of_address_to_resource(dn, 0, &r);
if (ret) { 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; return;
} }
mp_register_ioapic(++ioapic_id, r.start, gsi_top, &cfg); mp_register_ioapic(++ioapic_id, r.start, gsi_top, &cfg);
...@@ -265,7 +267,7 @@ static void __init dtb_ioapic_setup(void) ...@@ -265,7 +267,7 @@ static void __init dtb_ioapic_setup(void)
of_ioapic = 1; of_ioapic = 1;
return; 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 #else
static void __init dtb_ioapic_setup(void) {} static void __init dtb_ioapic_setup(void) {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment