Changes V8 --> V9:
No functionality change, update and modify the comments.
- [01/12] patch: modify the comments of apic_intr_mode_select().
Currently, the check logic of BIOS is based on the original code,
Baoquan and I have discussed it in V8 for readability, I am not sure
that I can clean up it correctly, So keep it like before.
- [06/12] patch: update the comments of init_apic_mappings()
- [11/12] patch: update the comments of native_smp_prepare_cpus().
- Post the patch putting acpi_early_init() earlier independently
suggested by Rafael and Baoquan.
- Rebase it
[Background]
MP specification defines three different interrupt delivery modes as follows:
1. PIC Mode
2. Virtual Wire Mode
3. Symmetric I/O Mode
They will be setup in the different periods of booting time:
1. *PIC Mode*, the default interrupt delivery modes, will be set first.
2. *Virtual Wire Mode* will be setup during ISA IRQ initialization( step 1
in the figure.1).
3. *Symmetric I/O Mode*'s setup is related to the system
3.1 In SMP-capable system, setup during prepares CPUs(step 2)
3.2 In UP system, setup during initializes itself(step 3).
start_kernel
+---------------+
|
+--> .......
|
| setup_arch
+--> +-------+
|
| init_IRQ
+-> +--+-----+
| | init_ISA_irqs
| +------> +-+--------+
| | +----------------+
+---> +------> | 1.init_bsp_APIC|
| ....... +----------------+
+--->
| rest_init
+--->---+-----+
| | kernel_init
| +> ----+-----+
| | kernel_init_freeable
| +-> ----+-------------+
| | smp_prepare_cpus
| +---> +----+---------+
| | | +-------------------+
| | +-> |2. apic_bsp_setup |
| | +-------------------+
| |
v | smp_init
+---> +---+----+
| +-------------------+
+--> |3. apic_bsp_setup |
+-------------------+
figure.1 The flow chart of the kernel startup process
[Problem]
1. Cause kernel in an unmatched mode at the beginning of booting time.
2. Cause the dump-capture kernel hangs with 'notsc' option inherited
from 1st kernel option.
3. Cause the code hard to read and maintain.
As Ingo's and Eric's discusses[1,2], it need to be refactor.
[Solution]
1. Construct a selector to unify these switches
+------------+
|disable_apic+--------------------+
+------------+ true |
|false |
| |
+------------v------------------+ |
|!boot_cpu_has(X86_FEATURE_APIC)+-------+
+-------------------------------+ true |
|false |
| |
+-------v---------+ v
|!smp_found_config| PIC MODE
+---------------+-+
|false |true
| |
v +---v---------+
SYMMETRIC IO MODE | !acpi_lapic |
+------+------+
|
v
VIRTUAL WIRE MODE
2. Unifying these setup steps of SMP-capable and UP system
start_kernel
---------------+
|
|
|
| x86_late_time_init
+---->---+------------+
| |
| | +------------------------+
| +----> | 4. init_interrupt_mode |
| +------------------------+
v
3. Execute the function as soon as possible.
[Link]
[1]. https://lkml.org/lkml/2016/8/2/929
[2]. https://lkml.org/lkml/2016/8/1/506
[History patches]
For previous discussion, please refer to:
V8: https://lkml.org/lkml/2017/8/27/265
V7: https://lkml.org/lkml/2017/7/14/20
V6: https://lkml.org/lkml/2017/7/3/269
V5: https://lkml.org/lkml/2017/6/30/17
V3: https://lkml.org/lkml/2017/5/10/323
V2: https://www.spinics.net/lists/kernel/msg2491620.html
V1: https://lkml.org/lkml/2017/3/29/481
Changes V7 --> V8:
- Change the order of [12/13] patch and [11/13]patch suggested by Rafael J. Wysocki.
- Fix some comments.
- Do more tests in Thinkpad x121e -- Thanks for Borislav Petkov's help.
Changes V6 --> V7:
- add a new patch: p12
Changes V5 --> V6:
- change the check order for X86_32 in apic_intr_mode_select()
- replace the apic_printk with pr_info in apic_intr_mode_init()
- add a separate helper function for get the logical apicid
- remove the extra argument upmode in apic_intr_mode_select()
- cleanup the logic of apic_intr_mode_init()
- replcae the 'ticks = jiffies' with 'end = jiffies + 4'
- rewrite the 9th and 10th patches's changelog
Changes V4 --> V5:
- remove the RFC presix
- remove the 1/12 patch in V4
- merge 2 patches together for SMP-capable system
- replace the *_interrupt_* with *_intr_*
- replace the pr_info with apic_printk in apic_intr_mode_init()
- add a patch for PV xen to bypass intr_mode_init()
Changes V3 --> V4:
- Move interrupt_mode_init to x86_init_ops instead of the use of
header files
- Replace "return" with "break" in case of APIC_SYMMETRIC_IO_NO_ROUTING
- Setup upmode earlier for UP system.
- Check interrupt mode before per cpu clock event setup.
Changes V2 --> V3:
- Rebase the patches.
- Change two function name:
apic_bsp_mode_check --> apic_interrupt_mode_select
init_interrupt_mode --> apic_interrupt_mode_init
- Find a new waiting way to check whether timer IRQs work or not
- Refine the switch logic in apic_interrupt_mode_init()
- Consistently start sentences with upper case letters
- Fix some typos and comments
- Try my best to rewrite some changelog again
Changes since V1:
- Move the initialization from init_IRQ() to x86_late_time_init()
- Use a threshold to refactor the check logic in timer_irq_works()
- Rename the framework to a selector
- Split two patches
- Consistently start sentences with upper case letters
- Fix some typos
- Rewrite the changelog
Cc: [email protected]
Cc: [email protected]
Cc: Juergen Gross <[email protected]>
Cc: [email protected]
Cc: Rafael J. Wysocki <[email protected]>
Cc: Zheng, Lv <[email protected]>
Dou Liyang (12):
x86/apic: Construct a selector for the interrupt delivery mode
x86/apic: Prepare for unifying the interrupt delivery modes setup
x86/apic: Split local APIC timer setup from the APIC setup
x86/apic: Move logical APIC ID away from apic_bsp_setup()
x86/apic: Unify interrupt mode setup for SMP-capable system
x86/apic: Mark the apic_intr_mode extern for sanity check cleanup
x86/apic: Unify interrupt mode setup for UP system
x86/ioapic: Refactor the delay logic in timer_irq_works()
x86/init: add intr_mode_init to x86_init_ops
x86/xen: Bypass intr mode setup in enlighten_pv system
x86/time: Initialize interrupt mode behind timer init
x86/apic: Remove the init_bsp_APIC()
arch/x86/include/asm/apic.h | 15 +++-
arch/x86/include/asm/x86_init.h | 2 +
arch/x86/kernel/apic/apic.c | 188 ++++++++++++++++++++--------------------
arch/x86/kernel/apic/io_apic.c | 45 +++++++++-
arch/x86/kernel/irqinit.c | 3 -
arch/x86/kernel/smpboot.c | 85 ++++++------------
arch/x86/kernel/time.c | 5 ++
arch/x86/kernel/x86_init.c | 1 +
arch/x86/xen/enlighten_pv.c | 1 +
9 files changed, 184 insertions(+), 161 deletions(-)
--
2.5.5
Now, there are many switches in kernel which are used to determine
the final interrupt delivery mode, as shown below:
1) kconfig:
CONFIG_X86_64; CONFIG_X86_LOCAL_APIC; CONFIG_x86_IO_APIC
2) kernel option: disable_apic; skip_ioapic_setup
3) CPU Capability: boot_cpu_has(X86_FEATURE_APIC)
4) MP table: smp_found_config
5) ACPI: acpi_lapic; acpi_ioapic; nr_ioapic
These switches are disordered and scattered and there are also some
dependencies with each other. These make the code difficult to
maintain and read.
Construct a selector to unify them into a single function, then,
Use this selector to get an interrupt delivery mode directly.
Signed-off-by: Dou Liyang <[email protected]>
---
arch/x86/kernel/apic/apic.c | 52 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index d705c76..39cb8c1 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1218,6 +1218,58 @@ void __init sync_Arb_IDs(void)
APIC_INT_LEVELTRIG | APIC_DM_INIT);
}
+enum apic_intr_mode {
+ APIC_PIC,
+ APIC_VIRTUAL_WIRE,
+ APIC_SYMMETRIC_IO,
+};
+
+static int __init apic_intr_mode_select(void)
+{
+ /* Check kernel option */
+ if (disable_apic) {
+ pr_info("APIC disabled via kernel command line\n");
+ return APIC_PIC;
+ }
+
+ /* Check BIOS */
+#ifdef CONFIG_X86_64
+ /* On 64-bit, the APIC must be integrated, Check local APIC only */
+ if (!boot_cpu_has(X86_FEATURE_APIC)) {
+ disable_apic = 1;
+ pr_info("APIC disabled by BIOS\n");
+ return APIC_PIC;
+ }
+#else
+ /* On 32-bit, the APIC may be integrated APIC or 82489DX */
+
+ /* Neither 82489DX nor integrated APIC ? */
+ if (!boot_cpu_has(X86_FEATURE_APIC) && !smp_found_config) {
+ disable_apic = 1;
+ return APIC_PIC;
+ }
+
+ /* If the BIOS pretends there is an integrated APIC ? */
+ if (!boot_cpu_has(X86_FEATURE_APIC) &&
+ APIC_INTEGRATED(boot_cpu_apic_version)) {
+ disable_apic = 1;
+ pr_err(FW_BUG "Local APIC %d not detected, force emulation\n",
+ boot_cpu_physical_apicid);
+ return APIC_PIC;
+ }
+#endif
+
+ /* Check MP table or ACPI MADT configuration */
+ if (!smp_found_config) {
+ disable_ioapic_support();
+ if (!acpi_lapic)
+ pr_info("APIC: ACPI MADT or MP tables are not detected\n");
+ return APIC_VIRTUAL_WIRE;
+ }
+
+ return APIC_SYMMETRIC_IO;
+}
+
/*
* An initial setup of the virtual wire mode.
*/
--
2.5.5
There are three positions for initializing the interrupt delivery
modes:
1) In IRQ initial function, may setup the through-local-APIC
virtual wire mode.
2) In an SMP-capable system, will try to switch to symmetric I/O
model when preparing the cpus in native_smp_prepare_cpus().
3) In UP system with UP_LATE_INIT=y, will set up local APIC and
I/O APIC in smp_init().
Switching to symmetric I/O mode is so late, which causes kernel
in an unmatched mode at the beginning of booting time. And it
causes the dump-capture kernel hangs with 'notsc' option inherited
from 1st kernel option.
Provide a new function to unify that three positions. Preparatory
patch to initialize an interrupt mode directly.
Signed-off-by: Dou Liyang <[email protected]>
---
arch/x86/include/asm/apic.h | 2 ++
arch/x86/kernel/apic/apic.c | 16 ++++++++++++++++
2 files changed, 18 insertions(+)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 5f01671..1a970f5 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -128,6 +128,7 @@ extern void disable_local_APIC(void);
extern void lapic_shutdown(void);
extern void sync_Arb_IDs(void);
extern void init_bsp_APIC(void);
+extern void apic_intr_mode_init(void);
extern void setup_local_APIC(void);
extern void init_apic_mappings(void);
void register_lapic_address(unsigned long address);
@@ -170,6 +171,7 @@ static inline void disable_local_APIC(void) { }
# define setup_boot_APIC_clock x86_init_noop
# define setup_secondary_APIC_clock x86_init_noop
static inline void lapic_update_tsc_freq(void) { }
+static inline void apic_intr_mode_init(void) { }
#endif /* !CONFIG_X86_LOCAL_APIC */
#ifdef CONFIG_X86_X2APIC
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 39cb8c1..08585bc 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1319,6 +1319,22 @@ void __init init_bsp_APIC(void)
apic_write(APIC_LVT1, value);
}
+/* Init the interrupt delivery mode for the BSP */
+void __init apic_intr_mode_init(void)
+{
+ switch (apic_intr_mode_select()) {
+ case APIC_PIC:
+ pr_info("APIC: Keep in PIC mode(8259)\n");
+ return;
+ case APIC_VIRTUAL_WIRE:
+ pr_info("APIC: Switch to virtual wire mode setup\n");
+ return;
+ case APIC_SYMMETRIC_IO:
+ pr_info("APIC: Switch to symmectic I/O mode setup\n");
+ return;
+ }
+}
+
static void lapic_setup_esr(void)
{
unsigned int oldvalue, value, maxlvt;
--
2.5.5
In the SMP-capable system, Linux enables and setups the interrupt
delivery mode by native_smp_prepare_cpus().
This design mixs the APIC and SMP together, it has highly coupling.
Make the initialization of interrupt mode independent, Unify and
refine it to apic_intr_mode_init() for SMP-capable system.
Signed-off-by: Dou Liyang <[email protected]>
---
arch/x86/kernel/apic/apic.c | 38 +++++++++++++++++++++++++++++++++++---
arch/x86/kernel/smpboot.c | 14 ++------------
2 files changed, 37 insertions(+), 15 deletions(-)
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index eafed8f..7ae97c2 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1221,7 +1221,9 @@ void __init sync_Arb_IDs(void)
enum apic_intr_mode {
APIC_PIC,
APIC_VIRTUAL_WIRE,
+ APIC_VIRTUAL_WIRE_NO_CONFIG,
APIC_SYMMETRIC_IO,
+ APIC_SYMMETRIC_IO_NO_ROUTING,
};
static int __init apic_intr_mode_select(void)
@@ -1262,11 +1264,27 @@ static int __init apic_intr_mode_select(void)
/* Check MP table or ACPI MADT configuration */
if (!smp_found_config) {
disable_ioapic_support();
- if (!acpi_lapic)
+ if (!acpi_lapic) {
pr_info("APIC: ACPI MADT or MP tables are not detected\n");
+ return APIC_VIRTUAL_WIRE_NO_CONFIG;
+ }
return APIC_VIRTUAL_WIRE;
}
+#ifdef CONFIG_SMP
+ /* If SMP should be disabled, then really disable it! */
+ if (!setup_max_cpus) {
+ pr_info("APIC: SMP mode deactivated\n");
+ return APIC_SYMMETRIC_IO_NO_ROUTING;
+ }
+
+ if (read_apic_id() != boot_cpu_physical_apicid) {
+ panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
+ read_apic_id(), boot_cpu_physical_apicid);
+ /* Or can we switch back to PIC here? */
+ }
+#endif
+
return APIC_SYMMETRIC_IO;
}
@@ -1322,17 +1340,31 @@ void __init init_bsp_APIC(void)
/* Init the interrupt delivery mode for the BSP */
void __init apic_intr_mode_init(void)
{
+ bool upmode = false;
+
switch (apic_intr_mode_select()) {
case APIC_PIC:
pr_info("APIC: Keep in PIC mode(8259)\n");
return;
case APIC_VIRTUAL_WIRE:
pr_info("APIC: Switch to virtual wire mode setup\n");
- return;
+ default_setup_apic_routing();
+ break;
+ case APIC_VIRTUAL_WIRE_NO_CONFIG:
+ pr_info("APIC: Switch to virtual wire mode setup with no configuration\n");
+ upmode = true;
+ default_setup_apic_routing();
+ break;
case APIC_SYMMETRIC_IO:
pr_info("APIC: Switch to symmectic I/O mode setup\n");
- return;
+ default_setup_apic_routing();
+ break;
+ case APIC_SYMMETRIC_IO_NO_ROUTING:
+ pr_info("APIC: Switch to symmectic I/O mode setup in no SMP routine\n");
+ break;
}
+
+ apic_bsp_setup(upmode);
}
static void lapic_setup_esr(void)
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 82f2e79..73d95f2 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1333,18 +1333,17 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
set_cpu_sibling_map(0);
+ apic_intr_mode_init();
+
switch (smp_sanity_check(max_cpus)) {
case SMP_NO_CONFIG:
disable_smp();
- if (APIC_init_uniprocessor())
- pr_notice("Local APIC not detected. Using dummy APIC emulation.\n");
return;
case SMP_NO_APIC:
disable_smp();
return;
case SMP_FORCE_UP:
disable_smp();
- apic_bsp_setup(false);
/* Setup local timer */
x86_init.timers.setup_percpu_clockev();
return;
@@ -1352,15 +1351,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
break;
}
- if (read_apic_id() != boot_cpu_physical_apicid) {
- panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
- read_apic_id(), boot_cpu_physical_apicid);
- /* Or can we switch back to PIC here? */
- }
-
- default_setup_apic_routing();
- apic_bsp_setup(false);
-
/* Setup local timer */
x86_init.timers.setup_percpu_clockev();
--
2.5.5
apic_bsp_setup() sets up the local APIC, I/O APIC and APIC timer.
The local APIC and I/O APIC setup belongs to interrupt delivery mode
setup. Setting up the local APIC timer for booting CPU is another job
and has nothing to do with interrupt delivery mode setup.
Split local APIC timer setup from the APIC setup, keep it in the
original position for SMP and UP kernel for preparation.
Signed-off-by: Dou Liyang <[email protected]>
---
arch/x86/kernel/apic/apic.c | 4 ++--
arch/x86/kernel/smpboot.c | 5 +++++
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 08585bc..ad37324 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -2397,8 +2397,6 @@ int __init apic_bsp_setup(bool upmode)
end_local_APIC_setup();
irq_remap_enable_fault_handling();
setup_IO_APIC();
- /* Setup local timer */
- x86_init.timers.setup_percpu_clockev();
return id;
}
@@ -2438,6 +2436,8 @@ int __init APIC_init_uniprocessor(void)
default_setup_apic_routing();
apic_bsp_setup(true);
+ /* Setup local timer */
+ x86_init.timers.setup_percpu_clockev();
return 0;
}
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index cd6622c..dde8f1c 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1337,6 +1337,8 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
case SMP_FORCE_UP:
disable_smp();
apic_bsp_setup(false);
+ /* Setup local timer */
+ x86_init.timers.setup_percpu_clockev();
return;
case SMP_OK:
break;
@@ -1351,6 +1353,9 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
default_setup_apic_routing();
cpu0_logical_apicid = apic_bsp_setup(false);
+ /* Setup local timer */
+ x86_init.timers.setup_percpu_clockev();
+
pr_info("CPU0: ");
print_cpu_info(&cpu_data(0));
--
2.5.5
In UniProcessor kernel with UP_LATE_INIT=y, it enables and setups
interrupt delivery mode in up_late_init().
Unify it to apic_intr_mode_init(), remove APIC_init_uniprocessor().
Signed-off-by: Dou Liyang <[email protected]>
---
arch/x86/include/asm/apic.h | 1 -
arch/x86/kernel/apic/apic.c | 47 ++++++---------------------------------------
2 files changed, 6 insertions(+), 42 deletions(-)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 01f3fc8..983a0dc 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -144,7 +144,6 @@ void register_lapic_address(unsigned long address);
extern void setup_boot_APIC_clock(void);
extern void setup_secondary_APIC_clock(void);
extern void lapic_update_tsc_freq(void);
-extern int APIC_init_uniprocessor(void);
#ifdef CONFIG_X86_64
static inline int apic_force_enable(unsigned long addr)
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 21d584d..efc5fbd 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1334,7 +1334,7 @@ void __init init_bsp_APIC(void)
/* Init the interrupt delivery mode for the BSP */
void __init apic_intr_mode_init(void)
{
- bool upmode = false;
+ bool upmode = IS_ENABLED(CONFIG_UP_LATE_INIT);
apic_intr_mode = apic_intr_mode_select();
@@ -2420,51 +2420,16 @@ void __init apic_bsp_setup(bool upmode)
setup_IO_APIC();
}
-/*
- * This initializes the IO-APIC and APIC hardware if this is
- * a UP kernel.
- */
-int __init APIC_init_uniprocessor(void)
+#ifdef CONFIG_UP_LATE_INIT
+void __init up_late_init(void)
{
- if (disable_apic) {
- pr_info("Apic disabled\n");
- return -1;
- }
-#ifdef CONFIG_X86_64
- if (!boot_cpu_has(X86_FEATURE_APIC)) {
- disable_apic = 1;
- pr_info("Apic disabled by BIOS\n");
- return -1;
- }
-#else
- if (!smp_found_config && !boot_cpu_has(X86_FEATURE_APIC))
- return -1;
+ apic_intr_mode_init();
- /*
- * Complain if the BIOS pretends there is one.
- */
- if (!boot_cpu_has(X86_FEATURE_APIC) &&
- APIC_INTEGRATED(boot_cpu_apic_version)) {
- pr_err("BIOS bug, local APIC 0x%x not detected!...\n",
- boot_cpu_physical_apicid);
- return -1;
- }
-#endif
-
- if (!smp_found_config)
- disable_ioapic_support();
+ if (apic_intr_mode == APIC_PIC)
+ return;
- default_setup_apic_routing();
- apic_bsp_setup(true);
/* Setup local timer */
x86_init.timers.setup_percpu_clockev();
- return 0;
-}
-
-#ifdef CONFIG_UP_LATE_INIT
-void __init up_late_init(void)
-{
- APIC_init_uniprocessor();
}
#endif
--
2.5.5
Calling native_smp_prepare_cpus() to prepare for SMP bootup, does
some sanity checking, enables APIC mode and disables SMP feature.
Now, APIC mode setup has been unified to apic_intr_mode_init(),
some sanity checks are redundant and need to be cleanup.
Mark the apic_intr_mode extern to refine the switch and remove
the redundant sanity check.
Signed-off-by: Dou Liyang <[email protected]>
---
arch/x86/include/asm/apic.h | 9 +++++++
arch/x86/kernel/apic/apic.c | 16 +++++--------
arch/x86/kernel/smpboot.c | 57 +++++++--------------------------------------
3 files changed, 24 insertions(+), 58 deletions(-)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 4e550c7..01f3fc8 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -53,6 +53,15 @@ extern int local_apic_timer_c2_ok;
extern int disable_apic;
extern unsigned int lapic_timer_frequency;
+extern enum apic_intr_mode_id apic_intr_mode;
+enum apic_intr_mode_id {
+ APIC_PIC,
+ APIC_VIRTUAL_WIRE,
+ APIC_VIRTUAL_WIRE_NO_CONFIG,
+ APIC_SYMMETRIC_IO,
+ APIC_SYMMETRIC_IO_NO_ROUTING
+};
+
#ifdef CONFIG_SMP
extern void __inquire_remote_apic(int apicid);
#else /* CONFIG_SMP */
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 7ae97c2..21d584d 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1218,13 +1218,7 @@ void __init sync_Arb_IDs(void)
APIC_INT_LEVELTRIG | APIC_DM_INIT);
}
-enum apic_intr_mode {
- APIC_PIC,
- APIC_VIRTUAL_WIRE,
- APIC_VIRTUAL_WIRE_NO_CONFIG,
- APIC_SYMMETRIC_IO,
- APIC_SYMMETRIC_IO_NO_ROUTING,
-};
+enum apic_intr_mode_id apic_intr_mode;
static int __init apic_intr_mode_select(void)
{
@@ -1342,7 +1336,9 @@ void __init apic_intr_mode_init(void)
{
bool upmode = false;
- switch (apic_intr_mode_select()) {
+ apic_intr_mode = apic_intr_mode_select();
+
+ switch (apic_intr_mode) {
case APIC_PIC:
pr_info("APIC: Keep in PIC mode(8259)\n");
return;
@@ -1974,8 +1970,8 @@ void __init init_apic_mappings(void)
* yeah -- we lie about apic_version
* in case if apic was disabled via boot option
* but it's not a problem for SMP compiled kernel
- * since smp_sanity_check is prepared for such a case
- * and disable smp mode
+ * since apic_intr_mode_select is prepared for such
+ * a case and disable smp mode
*/
boot_cpu_apic_version = GET_APIC_VERSION(apic_read(APIC_LVR));
}
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 73d95f2..fa535d4 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1187,17 +1187,10 @@ static __init void disable_smp(void)
cpumask_set_cpu(0, topology_core_cpumask(0));
}
-enum {
- SMP_OK,
- SMP_NO_CONFIG,
- SMP_NO_APIC,
- SMP_FORCE_UP,
-};
-
/*
* Various sanity checks.
*/
-static int __init smp_sanity_check(unsigned max_cpus)
+static void __init smp_sanity_check(void)
{
preempt_disable();
@@ -1235,16 +1228,6 @@ static int __init smp_sanity_check(unsigned max_cpus)
}
/*
- * If we couldn't find an SMP configuration at boot time,
- * get out of here now!
- */
- if (!smp_found_config && !acpi_lapic) {
- preempt_enable();
- pr_notice("SMP motherboard not detected\n");
- return SMP_NO_CONFIG;
- }
-
- /*
* Should not be necessary because the MP table should list the boot
* CPU too, but we do it for the sake of robustness anyway.
*/
@@ -1254,29 +1237,6 @@ static int __init smp_sanity_check(unsigned max_cpus)
physid_set(hard_smp_processor_id(), phys_cpu_present_map);
}
preempt_enable();
-
- /*
- * If we couldn't find a local APIC, then get out of here now!
- */
- if (APIC_INTEGRATED(boot_cpu_apic_version) &&
- !boot_cpu_has(X86_FEATURE_APIC)) {
- if (!disable_apic) {
- pr_err("BIOS bug, local APIC #%d not detected!...\n",
- boot_cpu_physical_apicid);
- pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n");
- }
- return SMP_NO_APIC;
- }
-
- /*
- * If SMP should be disabled, then really disable it!
- */
- if (!max_cpus) {
- pr_info("SMP mode deactivated\n");
- return SMP_FORCE_UP;
- }
-
- return SMP_OK;
}
static void __init smp_cpu_index_default(void)
@@ -1335,19 +1295,20 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
apic_intr_mode_init();
- switch (smp_sanity_check(max_cpus)) {
- case SMP_NO_CONFIG:
- disable_smp();
- return;
- case SMP_NO_APIC:
+ smp_sanity_check();
+
+ switch (apic_intr_mode) {
+ case APIC_PIC:
+ case APIC_VIRTUAL_WIRE_NO_CONFIG:
disable_smp();
return;
- case SMP_FORCE_UP:
+ case APIC_SYMMETRIC_IO_NO_ROUTING:
disable_smp();
/* Setup local timer */
x86_init.timers.setup_percpu_clockev();
return;
- case SMP_OK:
+ case APIC_VIRTUAL_WIRE:
+ case APIC_SYMMETRIC_IO:
break;
}
--
2.5.5
X86 and XEN initialize interrupt delivery mode in different way.
Ordinary conditional function calls will make the code mess.
Add an unconditional x86_init_ops function which defaults to the
standard function and can be overridden by the early platform code.
Signed-off-by: Dou Liyang <[email protected]>
---
arch/x86/include/asm/x86_init.h | 2 ++
arch/x86/kernel/apic/apic.c | 2 +-
arch/x86/kernel/smpboot.c | 2 +-
arch/x86/kernel/x86_init.c | 1 +
4 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 7ba7e90..f45acdf 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -50,11 +50,13 @@ struct x86_init_resources {
* are set up.
* @intr_init: interrupt init code
* @trap_init: platform specific trap setup
+ * @intr_mode_init: interrupt delivery mode setup
*/
struct x86_init_irqs {
void (*pre_vector_init)(void);
void (*intr_init)(void);
void (*trap_init)(void);
+ void (*intr_mode_init)(void);
};
/**
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index efc5fbd..8dbcff2 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -2423,7 +2423,7 @@ void __init apic_bsp_setup(bool upmode)
#ifdef CONFIG_UP_LATE_INIT
void __init up_late_init(void)
{
- apic_intr_mode_init();
+ x86_init.irqs.intr_mode_init();
if (apic_intr_mode == APIC_PIC)
return;
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index fa535d4..76fc857 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1293,7 +1293,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
set_cpu_sibling_map(0);
- apic_intr_mode_init();
+ x86_init.irqs.intr_mode_init();
smp_sanity_check();
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index a088b2c..a7889b9 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -55,6 +55,7 @@ struct x86_init_ops x86_init __initdata = {
.pre_vector_init = init_ISA_irqs,
.intr_init = native_init_IRQ,
.trap_init = x86_init_noop,
+ .intr_mode_init = apic_intr_mode_init
},
.oem = {
--
2.5.5
The init_bsp_APIC() which works for the virtual wire mode is used
in ISA irq initialization at the booting time.
Currently, enable and setup the interrupt mode has been unified
and advanced just behind the timer IRQ setup. Kernel switches to
the final interrupt delivery mode directly. So init_bsp_APIC()
is redundant.
Remove the init_bsp_APIC() function.
Signed-off-by: Dou Liyang <[email protected]>
---
arch/x86/include/asm/apic.h | 1 -
arch/x86/kernel/apic/apic.c | 49 ---------------------------------------------
arch/x86/kernel/irqinit.c | 3 ---
3 files changed, 53 deletions(-)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 983a0dc..7d247b2 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -136,7 +136,6 @@ extern void disconnect_bsp_APIC(int virt_wire_setup);
extern void disable_local_APIC(void);
extern void lapic_shutdown(void);
extern void sync_Arb_IDs(void);
-extern void init_bsp_APIC(void);
extern void apic_intr_mode_init(void);
extern void setup_local_APIC(void);
extern void init_apic_mappings(void);
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 3d08649..a4ee367 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1282,55 +1282,6 @@ static int __init apic_intr_mode_select(void)
return APIC_SYMMETRIC_IO;
}
-/*
- * An initial setup of the virtual wire mode.
- */
-void __init init_bsp_APIC(void)
-{
- unsigned int value;
-
- /*
- * Don't do the setup now if we have a SMP BIOS as the
- * through-I/O-APIC virtual wire mode might be active.
- */
- if (smp_found_config || !boot_cpu_has(X86_FEATURE_APIC))
- return;
-
- /*
- * Do not trust the local APIC being empty at bootup.
- */
- clear_local_APIC();
-
- /*
- * Enable APIC.
- */
- value = apic_read(APIC_SPIV);
- value &= ~APIC_VECTOR_MASK;
- value |= APIC_SPIV_APIC_ENABLED;
-
-#ifdef CONFIG_X86_32
- /* This bit is reserved on P4/Xeon and should be cleared */
- if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
- (boot_cpu_data.x86 == 15))
- value &= ~APIC_SPIV_FOCUS_DISABLED;
- else
-#endif
- value |= APIC_SPIV_FOCUS_DISABLED;
- value |= SPURIOUS_APIC_VECTOR;
- apic_write(APIC_SPIV, value);
-
- /*
- * Set up the virtual wire mode.
- */
- apic_write(APIC_LVT0, APIC_DM_EXTINT);
- value = APIC_DM_NMI;
- if (!lapic_is_integrated()) /* 82489DX */
- value |= APIC_LVT_LEVEL_TRIGGER;
- if (apic_extnmi == APIC_EXTNMI_NONE)
- value |= APIC_LVT_MASKED;
- apic_write(APIC_LVT1, value);
-}
-
/* Init the interrupt delivery mode for the BSP */
void __init apic_intr_mode_init(void)
{
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index 1add9e0..beafcf5 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -60,9 +60,6 @@ void __init init_ISA_irqs(void)
struct irq_chip *chip = legacy_pic->chip;
int i;
-#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
- init_bsp_APIC();
-#endif
legacy_pic->init(0);
for (i = 0; i < nr_legacy_irqs(); i++)
--
2.5.5
In start_kernel(), firstly, it works on the default interrupy mode, then
switch to the final mode. Normally, Booting with BIOS reset is OK.
But, At dump-capture kernel, it boot up without BIOS reset, default mode
may not be compatible with the actual registers, that causes the delivery
interrupt to fail.
Try to set up the final mode as soon as possible. according to the parts
which split from that initialization:
1) Set up the APIC/IOAPIC (including testing whether the timer
interrupt works)
2) Calibrate TSC
3) Set up the local APIC timer
-- From Thomas Gleixner
Initializing the mode should be earlier than calibrating TSC as soon as
possible and needs testing whether the timer interrupt works at the same
time.
call it behind timers init, which meets the above conditions.
Signed-off-by: Dou Liyang <[email protected]>
---
arch/x86/kernel/apic/apic.c | 2 --
arch/x86/kernel/smpboot.c | 7 +++----
arch/x86/kernel/time.c | 5 +++++
3 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 8dbcff2..3d08649 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -2423,8 +2423,6 @@ void __init apic_bsp_setup(bool upmode)
#ifdef CONFIG_UP_LATE_INIT
void __init up_late_init(void)
{
- x86_init.irqs.intr_mode_init();
-
if (apic_intr_mode == APIC_PIC)
return;
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 76fc857..6263d63 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1260,8 +1260,9 @@ static void __init smp_get_logical_apicid(void)
}
/*
- * Prepare for SMP bootup. The MP table or ACPI has been read
- * earlier. Just do some sanity checking here and enable APIC mode.
+ * Prepare for SMP bootup.
+ * @max_cpus: configured maximum number of CPUs, It is a legacy parameter
+ * for common interface support.
*/
void __init native_smp_prepare_cpus(unsigned int max_cpus)
{
@@ -1293,8 +1294,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
set_cpu_sibling_map(0);
- x86_init.irqs.intr_mode_init();
-
smp_sanity_check();
switch (apic_intr_mode) {
diff --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c
index e0754cd..3ceb834 100644
--- a/arch/x86/kernel/time.c
+++ b/arch/x86/kernel/time.c
@@ -84,6 +84,11 @@ void __init hpet_time_init(void)
static __init void x86_late_time_init(void)
{
x86_init.timers.timer_init();
+ /*
+ * After PIT/HPET timers init, select and setup
+ * the final interrupt mode for delivering IRQs.
+ */
+ x86_init.irqs.intr_mode_init();
tsc_init();
}
--
2.5.5
apic_bsp_setup() sets and returns logical APIC ID for initializing
cpu0_logical_apicid in SMP-capable system.
The id has nothing to do with the initialization of local APIC and
I/O APIC. And apic_bsp_setup() should be called for interrupt mode
setup intently.
Move the id setup into a separate helper function for cleanup and
mark apic_bsp_setup() void.
Signed-off-by: Dou Liyang <[email protected]>
---
arch/x86/include/asm/apic.h | 2 +-
arch/x86/kernel/apic/apic.c | 10 +---------
arch/x86/kernel/smpboot.c | 12 +++++++++++-
3 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 1a970f5..4e550c7 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -146,7 +146,7 @@ static inline int apic_force_enable(unsigned long addr)
extern int apic_force_enable(unsigned long addr);
#endif
-extern int apic_bsp_setup(bool upmode);
+extern void apic_bsp_setup(bool upmode);
extern void apic_ap_setup(void);
/*
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index ad37324..eafed8f 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -2379,25 +2379,17 @@ static void __init apic_bsp_up_setup(void)
* Returns:
* apic_id of BSP APIC
*/
-int __init apic_bsp_setup(bool upmode)
+void __init apic_bsp_setup(bool upmode)
{
- int id;
-
connect_bsp_APIC();
if (upmode)
apic_bsp_up_setup();
setup_local_APIC();
- if (x2apic_mode)
- id = apic_read(APIC_LDR);
- else
- id = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
-
enable_IO_APIC();
end_local_APIC_setup();
irq_remap_enable_fault_handling();
setup_IO_APIC();
- return id;
}
/*
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index dde8f1c..82f2e79 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1291,6 +1291,14 @@ static void __init smp_cpu_index_default(void)
}
}
+static void __init smp_get_logical_apicid(void)
+{
+ if (x2apic_mode)
+ cpu0_logical_apicid = apic_read(APIC_LDR);
+ else
+ cpu0_logical_apicid = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
+}
+
/*
* Prepare for SMP bootup. The MP table or ACPI has been read
* earlier. Just do some sanity checking here and enable APIC mode.
@@ -1351,11 +1359,13 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
}
default_setup_apic_routing();
- cpu0_logical_apicid = apic_bsp_setup(false);
+ apic_bsp_setup(false);
/* Setup local timer */
x86_init.timers.setup_percpu_clockev();
+ smp_get_logical_apicid();
+
pr_info("CPU0: ");
print_cpu_info(&cpu_data(0));
--
2.5.5
XEN PV overrides smp_prepare_cpus(). xen_pv_smp_prepare_cpus()
initializes interrupts in the XEN PV specific way and does not invoke
native_smp_prepare_cpus(). As a consequence, x86_init.intr_mode_init() is
not invoked either.
The invocation of x86_init.intr_mode_init() will be moved from
native_smp_prepare_cpus() in a follow up patch to solve <INSERT
REASON/PROBLEM>.
That move would cause the invocation of x86_init.intr_mode_init() for XEN
PV platforms. To prevent that, override the default x86_init.intr_mode_init()
callback with a noop().
[Rewrited by Thomas Gleixner <[email protected]>]
Signed-off-by: Dou Liyang <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: Juergen Gross <[email protected]>
---
arch/x86/xen/enlighten_pv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index ae2a2e2..934dc7f 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -1232,6 +1232,7 @@ asmlinkage __visible void __init xen_start_kernel(void)
x86_platform.get_nmi_reason = xen_get_nmi_reason;
x86_init.resources.memory_setup = xen_memory_setup;
+ x86_init.irqs.intr_mode_init = x86_init_noop;
x86_init.oem.arch_setup = xen_arch_setup;
x86_init.oem.banner = xen_banner;
--
2.5.5
Linux uses acpi_early_init() to put the ACPI table management into the
late stage from the early stage. This two stages are different. the
mapped ACPI tables in early stage is temporary and should be unmapped,
but in late stage, it is permanent and don't need to be unmapped.
Originally, mapping and parsing the DMAR table should be in the late stage.
However, Initializing interrupt delivery mode earlier will move it into
the early stage. This causes an ACPI error warning when Linux reallocates
the ACPI root tables.
Commit b064a8fa77df ("ACPI / init: Switch over platform to the ACPI mode
later") splits the ACPI early initialization code into acpi_early_init()
and acpi_subsystem_init(). This makes acpi_early_init() more independently
So, invoke acpi_early_init() earlier before late_time_init(), Keep the DMAR
be mapped and parsed in late stage like before.
Reported-by: Xiaolong Ye <[email protected]>
Signed-off-by: Dou Liyang <[email protected]>
Cc: [email protected]
Cc: Rafael J. Wysocki <[email protected]>
Cc: Zheng, Lv <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: [email protected]
Cc: Michael Ellerman <[email protected]>
Cc: Will Deacon <[email protected]>
Cc: [email protected]
Cc: Tony Luck <[email protected]>
Cc: Fenghua Yu <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
init/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/init/main.c b/init/main.c
index 0ee9c686..2fb98a4 100644
--- a/init/main.c
+++ b/init/main.c
@@ -664,12 +664,12 @@ asmlinkage __visible void __init start_kernel(void)
debug_objects_mem_init();
setup_per_cpu_pageset();
numa_policy_init();
+ acpi_early_init();
if (late_time_init)
late_time_init();
calibrate_delay();
pidmap_init();
anon_vma_init();
- acpi_early_init();
#ifdef CONFIG_X86
if (efi_enabled(EFI_RUNTIME_SERVICES))
efi_enter_virtual_mode();
--
2.5.5
Kernel use timer_irq_works() to detects the timer IRQs. It calls
mdelay(10) to delay ten ticks and check whether the timer IRQ work
or not. The mdelay() depends on the loops_per_jiffy which is set up
in calibrate_delay(). Current kernel defaults the IRQ 0 is available
when it calibrates delay.
But it is wrong in the dump-capture kernel with 'notsc' option inherited
from 1st kernel option. dump-capture kernel can't make sure the timer IRQ
works well.
The correct design is making the interrupt mode setup and checking timer
IRQ works in advance of calibrate_delay(). That results in the mdelay()
being unusable in timer_irq_works().
Preparatory patch to make the setup in advance. Refactor the delay logic
by waiting for some cycles. In the system with X86_FEATURE_TSC feature,
Use rdtsc(), others will call __delay() directly.
Note: regard 4G as the max CPU frequence of current single CPU.
Signed-off-by: Dou Liyang <[email protected]>
---
arch/x86/kernel/apic/io_apic.c | 45 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 43 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 70e48aa..f8f2487 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1585,6 +1585,43 @@ static int __init notimercheck(char *s)
}
__setup("no_timer_check", notimercheck);
+static void __init delay_with_tsc(void)
+{
+ unsigned long long start, now;
+ unsigned long end = jiffies + 4;
+
+ start = rdtsc();
+
+ /*
+ * We don't know the TSC frequency yet, but waiting for
+ * 40000000000/HZ TSC cycles is safe:
+ * 4 GHz == 10 jiffies
+ * 1 GHz == 40 jiffies
+ */
+ do {
+ rep_nop();
+ now = rdtsc();
+ } while ((now - start) < 40000000000UL / HZ &&
+ time_before_eq(jiffies, end));
+}
+
+static void __init delay_without_tsc(void)
+{
+ unsigned long end = jiffies + 4;
+ int band = 1;
+
+ /*
+ * We don't know any frequency yet, but waiting for
+ * 40940000000/HZ cycles is safe:
+ * 4 GHz == 10 jiffies
+ * 1 GHz == 40 jiffies
+ * 1 << 1 + 1 << 2 +...+ 1 << 11 = 4094
+ */
+ do {
+ __delay(((1U << band++) * 10000000UL) / HZ);
+ } while (band < 12 && time_before_eq(jiffies, end));
+}
+
/*
* There is a nasty bug in some older SMP boards, their mptable lies
* about the timer IRQ. We do the following to work around the situation:
@@ -1603,8 +1640,12 @@ static int __init timer_irq_works(void)
local_save_flags(flags);
local_irq_enable();
- /* Let ten ticks pass... */
- mdelay((10 * 1000) / HZ);
+
+ if (boot_cpu_has(X86_FEATURE_TSC))
+ delay_with_tsc();
+ else
+ delay_without_tsc();
+
local_irq_restore(flags);
/*
--
2.5.5
On 13/09/17 11:12, Dou Liyang wrote:
> XEN PV overrides smp_prepare_cpus(). xen_pv_smp_prepare_cpus()
> initializes interrupts in the XEN PV specific way and does not invoke
> native_smp_prepare_cpus(). As a consequence, x86_init.intr_mode_init() is
> not invoked either.
>
> The invocation of x86_init.intr_mode_init() will be moved from
> native_smp_prepare_cpus() in a follow up patch to solve <INSERT
> REASON/PROBLEM>.
I asked you to be more specific here before. So: what will be solved?
Can I select a problem I like? ;-)
> That move would cause the invocation of x86_init.intr_mode_init() for XEN
> PV platforms. To prevent that, override the default x86_init.intr_mode_init()
> callback with a noop().
>
> [Rewrited by Thomas Gleixner <[email protected]>]
Rewritten?
> Signed-off-by: Dou Liyang <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Cc: Juergen Gross <[email protected]>
Regarding the changes below:
Acked-by: Juergen Gross <[email protected]>
Juergen
> ---
> arch/x86/xen/enlighten_pv.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
> index ae2a2e2..934dc7f 100644
> --- a/arch/x86/xen/enlighten_pv.c
> +++ b/arch/x86/xen/enlighten_pv.c
> @@ -1232,6 +1232,7 @@ asmlinkage __visible void __init xen_start_kernel(void)
> x86_platform.get_nmi_reason = xen_get_nmi_reason;
>
> x86_init.resources.memory_setup = xen_memory_setup;
> + x86_init.irqs.intr_mode_init = x86_init_noop;
> x86_init.oem.arch_setup = xen_arch_setup;
> x86_init.oem.banner = xen_banner;
>
>
Hi Juergen,
At 09/13/2017 05:45 PM, Juergen Gross wrote:
> On 13/09/17 11:12, Dou Liyang wrote:
>> XEN PV overrides smp_prepare_cpus(). xen_pv_smp_prepare_cpus()
>> initializes interrupts in the XEN PV specific way and does not invoke
>> native_smp_prepare_cpus(). As a consequence, x86_init.intr_mode_init() is
>> not invoked either.
>>
>> The invocation of x86_init.intr_mode_init() will be moved from
>> native_smp_prepare_cpus() in a follow up patch to solve <INSERT
>> REASON/PROBLEM>.
>
> I asked you to be more specific here before. So: what will be solved?
> Can I select a problem I like? ;-)
Oops, I am sorry I missed it. I will modify it.
...to solve the dump-capture kernel hangs, if there is a notsc option
in its command line.
>
>> That move would cause the invocation of x86_init.intr_mode_init() for XEN
>> PV platforms. To prevent that, override the default x86_init.intr_mode_init()
>> callback with a noop().
>>
>> [Rewrited by Thomas Gleixner <[email protected]>]
>
> Rewritten?
Yeah, yeah. poor english skill :-).
>
>> Signed-off-by: Dou Liyang <[email protected]>
>> Cc: [email protected]
>> Cc: [email protected]
>> Cc: Juergen Gross <[email protected]>
>
> Regarding the changes below:
>
> Acked-by: Juergen Gross <[email protected]>
>
Thank you for your acked, I will re-post it.
Thanks,
dou.
>
> Juergen
>
>> ---
>> arch/x86/xen/enlighten_pv.c | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
>> index ae2a2e2..934dc7f 100644
>> --- a/arch/x86/xen/enlighten_pv.c
>> +++ b/arch/x86/xen/enlighten_pv.c
>> @@ -1232,6 +1232,7 @@ asmlinkage __visible void __init xen_start_kernel(void)
>> x86_platform.get_nmi_reason = xen_get_nmi_reason;
>>
>> x86_init.resources.memory_setup = xen_memory_setup;
>> + x86_init.irqs.intr_mode_init = x86_init_noop;
>> x86_init.oem.arch_setup = xen_arch_setup;
>> x86_init.oem.banner = xen_banner;
>>
>>
>
>
>
>
XEN PV overrides smp_prepare_cpus(). xen_pv_smp_prepare_cpus()
initializes interrupts in the XEN PV specific way and does not invoke
native_smp_prepare_cpus(). As a consequence, x86_init.intr_mode_init() is
not invoked either.
The invocation of x86_init.intr_mode_init() will be moved from
native_smp_prepare_cpus() in a follow up patch to solve the dump-capture
kernel hangs, if there is a notsc option in its command line.
That move would cause the invocation of x86_init.intr_mode_init() for XEN
PV platforms. To prevent that, override the default x86_init.intr_mode_init()
callback with a noop().
[Rewritten by Thomas Gleixner <[email protected]>]
Signed-off-by: Dou Liyang <[email protected]>
Acked-by: Juergen Gross <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: Juergen Gross <[email protected]>
---
V10 --> V9:
--Modify the changelog, suggested by Juergen
arch/x86/xen/enlighten_pv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index ae2a2e2..934dc7f 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -1232,6 +1232,7 @@ asmlinkage __visible void __init xen_start_kernel(void)
x86_platform.get_nmi_reason = xen_get_nmi_reason;
x86_init.resources.memory_setup = xen_memory_setup;
+ x86_init.irqs.intr_mode_init = x86_init_noop;
x86_init.oem.arch_setup = xen_arch_setup;
x86_init.oem.banner = xen_banner;
--
2.5.5
Hi Rafael, Zheng,
Welcome any comments!
Now, our patches are in tip tree, they are based on this
independent patch, we hope it can be merged earlier than our
patches to avoid ACPI Error. we need your advice and confirmation.
Thanks,
dou.
At 09/13/2017 05:17 PM, Dou Liyang wrote:
> Linux uses acpi_early_init() to put the ACPI table management into the
> late stage from the early stage. This two stages are different. the
> mapped ACPI tables in early stage is temporary and should be unmapped,
> but in late stage, it is permanent and don't need to be unmapped.
>
> Originally, mapping and parsing the DMAR table should be in the late stage.
> However, Initializing interrupt delivery mode earlier will move it into
> the early stage. This causes an ACPI error warning when Linux reallocates
> the ACPI root tables.
>
> Commit b064a8fa77df ("ACPI / init: Switch over platform to the ACPI mode
> later") splits the ACPI early initialization code into acpi_early_init()
> and acpi_subsystem_init(). This makes acpi_early_init() more independently
>
> So, invoke acpi_early_init() earlier before late_time_init(), Keep the DMAR
> be mapped and parsed in late stage like before.
>
> Reported-by: Xiaolong Ye <[email protected]>
> Signed-off-by: Dou Liyang <[email protected]>
> Cc: [email protected]
> Cc: Rafael J. Wysocki <[email protected]>
> Cc: Zheng, Lv <[email protected]>
> Cc: Thomas Gleixner <[email protected]>
> Cc: Ingo Molnar <[email protected]>
> Cc: "H. Peter Anvin" <[email protected]>
> Cc: [email protected]
> Cc: Michael Ellerman <[email protected]>
> Cc: Will Deacon <[email protected]>
> Cc: [email protected]
> Cc: Tony Luck <[email protected]>
> Cc: Fenghua Yu <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Cc: [email protected]
> Cc: [email protected]
> ---
> init/main.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/init/main.c b/init/main.c
> index 0ee9c686..2fb98a4 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -664,12 +664,12 @@ asmlinkage __visible void __init start_kernel(void)
> debug_objects_mem_init();
> setup_per_cpu_pageset();
> numa_policy_init();
> + acpi_early_init();
> if (late_time_init)
> late_time_init();
> calibrate_delay();
> pidmap_init();
> anon_vma_init();
> - acpi_early_init();
> #ifdef CONFIG_X86
> if (efi_enabled(EFI_RUNTIME_SERVICES))
> efi_enter_virtual_mode();
>
On Wed, 27 Sep 2017, Dou Liyang wrote:
> Hi Rafael, Zheng,
>
> Welcome any comments!
>
> Now, our patches are in tip tree, they are based on this
> independent patch, we hope it can be merged earlier than our
> patches to avoid ACPI Error. we need your advice and confirmation.
You should have included that patch into your APIC series so I would have
been aware that it's required for the APIC changes to work on all
platforms.
But not a big problem. I merge it through tip/x86/apic so the stuff works
as expected.
Thanks,
tglx
Hi Thomas,
At 09/27/2017 03:19 PM, Thomas Gleixner wrote:
> On Wed, 27 Sep 2017, Dou Liyang wrote:
>
>> Hi Rafael, Zheng,
>>
>> Welcome any comments!
>>
>> Now, our patches are in tip tree, they are based on this
>> independent patch, we hope it can be merged earlier than our
>> patches to avoid ACPI Error. we need your advice and confirmation.
>
> You should have included that patch into your APIC series so I would have
> been aware that it's required for the APIC changes to work on all
> platforms.
>
> But not a big problem. I merge it through tip/x86/apic so the stuff works
> as expected.
>
Yeah, thank you so much.
Thanks,
dou.
On Wed, Sep 13, 2017 at 05:17:54PM +0800, Dou Liyang wrote:
> Linux uses acpi_early_init() to put the ACPI table management into the
> late stage from the early stage. This two stages are different. the
> mapped ACPI tables in early stage is temporary and should be unmapped,
> but in late stage, it is permanent and don't need to be unmapped.
>
> Originally, mapping and parsing the DMAR table should be in the late stage.
> However, Initializing interrupt delivery mode earlier will move it into
> the early stage. This causes an ACPI error warning when Linux reallocates
> the ACPI root tables.
>
> Commit b064a8fa77df ("ACPI / init: Switch over platform to the ACPI mode
> later") splits the ACPI early initialization code into acpi_early_init()
> and acpi_subsystem_init(). This makes acpi_early_init() more independently
>
> So, invoke acpi_early_init() earlier before late_time_init(), Keep the DMAR
> be mapped and parsed in late stage like before.
>
> Reported-by: Xiaolong Ye <[email protected]>
> Signed-off-by: Dou Liyang <[email protected]>
> Cc: [email protected]
> Cc: Rafael J. Wysocki <[email protected]>
> Cc: Zheng, Lv <[email protected]>
> Cc: Thomas Gleixner <[email protected]>
> Cc: Ingo Molnar <[email protected]>
> Cc: "H. Peter Anvin" <[email protected]>
> Cc: [email protected]
> Cc: Michael Ellerman <[email protected]>
> Cc: Will Deacon <[email protected]>
> Cc: [email protected]
> Cc: Tony Luck <[email protected]>
> Cc: Fenghua Yu <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Cc: [email protected]
> Cc: [email protected]
> ---
> init/main.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/init/main.c b/init/main.c
> index 0ee9c686..2fb98a4 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -664,12 +664,12 @@ asmlinkage __visible void __init start_kernel(void)
> debug_objects_mem_init();
> setup_per_cpu_pageset();
> numa_policy_init();
> + acpi_early_init();
> if (late_time_init)
> late_time_init();
> calibrate_delay();
> pidmap_init();
> anon_vma_init();
> - acpi_early_init();
> #ifdef CONFIG_X86
> if (efi_enabled(EFI_RUNTIME_SERVICES))
> efi_enter_virtual_mode();
> --
Tested-by: Borislav Petkov <[email protected]>
This one fixes the early ioremap leak check I get here with tip/master:
Debug warning: early ioremap leak of 1 areas detected.
please boot with early_ioremap_debug and report the dmesg.
------------[ cut here ]------------
WARNING: CPU: 3 PID: 1 at mm/early_ioremap.c:98 check_early_ioremap_leak+0x31/0x39
Modules linked in:
CPU: 3 PID: 1 Comm: swapper/0 Not tainted 4.14.0-rc2+ #1
Hardware name: LENOVO 2320CTO/2320CTO, BIOS G2ET86WW (2.06 ) 11/13/2012
task: ffff8802138e0000 task.stack: ffffc90000c90000
RIP: 0010:check_early_ioremap_leak+0x31/0x39
RSP: 0000:ffffc90000c93ea8 EFLAGS: 00010296
RAX: 0000000000000071 RBX: 0000000000000000 RCX: 0000000000000000
RDX: ffff8802138e0000 RSI: 0000000000000001 RDI: 0000000000000282
RBP: ffffffff82089d8e R08: ffffffff810cc9c5 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: ffffffff82182d30
R13: 0000000000000008 R14: ffffffff8205d7f6 R15: 0000000000000000
FS: 0000000000000000(0000) GS:ffff88021d380000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 0000000001c10001 CR4: 00000000001606e0
Call Trace:
do_one_initcall+0x4b/0x18c
kernel_init_freeable+0x120/0x1a2
? rest_init+0xd0/0xd0
kernel_init+0xa/0x100
ret_from_fork+0x2a/0x40
Code: d2 31 c0 48 83 3c d5 a0 3a 11 82 00 74 02 ff c0 48 ff c2 48 83 fa 08 75 ea 85 c0 74 15 89 c6 48 c7 c7 20 c7 a6 81 e8 bc 2b 04 ff <0f> ff b8 01 00 00 00 c3 0f 1f 44 00 00 41 57 48 89 f1 41 56 41
---[ end trace f7d67c4805284a92 ]---
Booting with early_ioremap_debug showed this last ioremap call in the Intel
iommu code ioremapping the DMAR table but not unmapping it:
__early_ioremap(dafdb000, 00001000) [0] => 00000000 + ffffffffff200000
------------[ cut here ]------------
WARNING: CPU: 0 PID: 0 at mm/early_ioremap.c:161 __early_ioremap+0x150/0x17f
Modules linked in:
CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 4.14.0-rc2+ #2
Hardware name: LENOVO 2320CTO/2320CTO, BIOS G2ET86WW (2.06 ) 11/13/2012
task: ffffffff81c15500 task.stack: ffffffff81c00000
RIP: 0010:__early_ioremap+0x150/0x17f
RSP: 0000:ffffffff81c03d70 EFLAGS: 00010282
RAX: 0000000000000046 RBX: 00000000dafda000 RCX: 0000000000000000
RDX: 0000000000000002 RSI: 0000000000000001 RDI: 0000000000000001
RBP: 0000000000000001 R08: 0000000000000001 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: 00000000dafdb000
R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
FS: 0000000000000000(0000) GS:ffff88021d200000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffff88021e5ff000 CR3: 0000000001c10001 CR4: 00000000000606b0
Call Trace:
acpi_tb_acquire_table+0x39/0x64
acpi_tb_validate_table+0x21/0x33
acpi_tb_get_table+0x25/0x5e
acpi_get_table+0x59/0x82
dmar_table_detect+0x1a/0x43
dmar_table_init+0x73/0x13e
? dmar_free_dev_scope+0xe0/0xe0
? intel_iommu_setup+0x211/0x211
? iommu_calculate_agaw+0x20/0x20
? dmar_walk_remapping_entries+0x170/0x170
? detect_intel_iommu+0xca/0xca
intel_prepare_irq_remapping+0x3a/0x22a
irq_remapping_prepare+0x1a/0x2a
enable_IR_x2apic+0x21/0x198
default_setup_apic_routing+0x12/0x6f
apic_intr_mode_init+0x14b/0x181
x86_late_time_init+0x11/0x16
start_kernel+0x3ae/0x44c
secondary_startup_64+0xa5/0xa5
Code: 1a 74 2b 42 ff 34 ed 20 3a 11 82 45 89 f0 48 c7 c6 90 df 81 81 48 c7 c7 c0 c7 a6 81 4c 8b 4c 24 08 48 8b 4c 24 10 e8 64 2a 04 ff <0f> ff 58 48 8b 04 24 4a 03 04 ed 20 3a 11 82 4a 89 04 ed a0 3a
---[ end trace 52caafcde4fdbc68 ]---
DMAR: Host address width 36
DMAR: DRHD base: 0x000000fed90000 flags: 0x0
DMAR: dmar0: reg_base_addr fed90000 ver 1:0 cap c0000020e60262 ecap f0101a
DMAR: DRHD base: 0x000000fed91000 flags: 0x1
DMAR: dmar1: reg_base_addr fed91000 ver 1:0 cap c9008020660262 ecap f0105a
DMAR: RMRR base: 0x000000da2ba000 end: 0x000000da2d0fff
DMAR: RMRR base: 0x000000db800000 end: 0x000000df9fffff
DMAR-IR: IOAPIC id 2 under DRHD base 0xfed91000 IOMMU 1
DMAR-IR: HPET id 0 under DRHD base 0xfed91000
DMAR-IR: Queued invalidation will be enabled to support x2apic and Intr-remapping.
DMAR-IR: Enabled IRQ remapping in x2apic mode
x2apic enabled
Switched APIC routing to cluster x2apic.
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
Hi Borislav,
At 09/27/2017 05:02 PM, Borislav Petkov wrote:
> On Wed, Sep 13, 2017 at 05:17:54PM +0800, Dou Liyang wrote:
>> Linux uses acpi_early_init() to put the ACPI table management into the
>> late stage from the early stage. This two stages are different. the
>> mapped ACPI tables in early stage is temporary and should be unmapped,
>> but in late stage, it is permanent and don't need to be unmapped.
>>
>> Originally, mapping and parsing the DMAR table should be in the late stage.
>> However, Initializing interrupt delivery mode earlier will move it into
>> the early stage. This causes an ACPI error warning when Linux reallocates
>> the ACPI root tables.
>>
>> Commit b064a8fa77df ("ACPI / init: Switch over platform to the ACPI mode
>> later") splits the ACPI early initialization code into acpi_early_init()
>> and acpi_subsystem_init(). This makes acpi_early_init() more independently
>>
>> So, invoke acpi_early_init() earlier before late_time_init(), Keep the DMAR
>> be mapped and parsed in late stage like before.
>>
>> Reported-by: Xiaolong Ye <[email protected]>
>> Signed-off-by: Dou Liyang <[email protected]>
>> Cc: [email protected]
>> Cc: Rafael J. Wysocki <[email protected]>
>> Cc: Zheng, Lv <[email protected]>
>> Cc: Thomas Gleixner <[email protected]>
>> Cc: Ingo Molnar <[email protected]>
>> Cc: "H. Peter Anvin" <[email protected]>
>> Cc: [email protected]
>> Cc: Michael Ellerman <[email protected]>
>> Cc: Will Deacon <[email protected]>
>> Cc: [email protected]
>> Cc: Tony Luck <[email protected]>
>> Cc: Fenghua Yu <[email protected]>
>> Cc: [email protected]
>> Cc: [email protected]
>> Cc: [email protected]
>> Cc: [email protected]
>> ---
>> init/main.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/init/main.c b/init/main.c
>> index 0ee9c686..2fb98a4 100644
>> --- a/init/main.c
>> +++ b/init/main.c
>> @@ -664,12 +664,12 @@ asmlinkage __visible void __init start_kernel(void)
>> debug_objects_mem_init();
>> setup_per_cpu_pageset();
>> numa_policy_init();
>> + acpi_early_init();
>> if (late_time_init)
>> late_time_init();
>> calibrate_delay();
>> pidmap_init();
>> anon_vma_init();
>> - acpi_early_init();
>> #ifdef CONFIG_X86
>> if (efi_enabled(EFI_RUNTIME_SERVICES))
>> efi_enter_virtual_mode();
>> --
>
> Tested-by: Borislav Petkov <[email protected]>
>
Thank you for testing.
> This one fixes the early ioremap leak check I get here with tip/master:
>
Indeed.
Thanks,
dou.
> Debug warning: early ioremap leak of 1 areas detected.
> please boot with early_ioremap_debug and report the dmesg.
> ------------[ cut here ]------------
> WARNING: CPU: 3 PID: 1 at mm/early_ioremap.c:98 check_early_ioremap_leak+0x31/0x39
> Modules linked in:
> CPU: 3 PID: 1 Comm: swapper/0 Not tainted 4.14.0-rc2+ #1
> Hardware name: LENOVO 2320CTO/2320CTO, BIOS G2ET86WW (2.06 ) 11/13/2012
> task: ffff8802138e0000 task.stack: ffffc90000c90000
> RIP: 0010:check_early_ioremap_leak+0x31/0x39
> RSP: 0000:ffffc90000c93ea8 EFLAGS: 00010296
> RAX: 0000000000000071 RBX: 0000000000000000 RCX: 0000000000000000
> RDX: ffff8802138e0000 RSI: 0000000000000001 RDI: 0000000000000282
> RBP: ffffffff82089d8e R08: ffffffff810cc9c5 R09: 0000000000000000
> R10: 0000000000000000 R11: 0000000000000000 R12: ffffffff82182d30
> R13: 0000000000000008 R14: ffffffff8205d7f6 R15: 0000000000000000
> FS: 0000000000000000(0000) GS:ffff88021d380000(0000) knlGS:0000000000000000
> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 0000000000000000 CR3: 0000000001c10001 CR4: 00000000001606e0
> Call Trace:
> do_one_initcall+0x4b/0x18c
> kernel_init_freeable+0x120/0x1a2
> ? rest_init+0xd0/0xd0
> kernel_init+0xa/0x100
> ret_from_fork+0x2a/0x40
> Code: d2 31 c0 48 83 3c d5 a0 3a 11 82 00 74 02 ff c0 48 ff c2 48 83 fa 08 75 ea 85 c0 74 15 89 c6 48 c7 c7 20 c7 a6 81 e8 bc 2b 04 ff <0f> ff b8 01 00 00 00 c3 0f 1f 44 00 00 41 57 48 89 f1 41 56 41
> ---[ end trace f7d67c4805284a92 ]---
>
> Booting with early_ioremap_debug showed this last ioremap call in the Intel
> iommu code ioremapping the DMAR table but not unmapping it:
>
> __early_ioremap(dafdb000, 00001000) [0] => 00000000 + ffffffffff200000
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 0 at mm/early_ioremap.c:161 __early_ioremap+0x150/0x17f
> Modules linked in:
> CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 4.14.0-rc2+ #2
> Hardware name: LENOVO 2320CTO/2320CTO, BIOS G2ET86WW (2.06 ) 11/13/2012
> task: ffffffff81c15500 task.stack: ffffffff81c00000
> RIP: 0010:__early_ioremap+0x150/0x17f
> RSP: 0000:ffffffff81c03d70 EFLAGS: 00010282
> RAX: 0000000000000046 RBX: 00000000dafda000 RCX: 0000000000000000
> RDX: 0000000000000002 RSI: 0000000000000001 RDI: 0000000000000001
> RBP: 0000000000000001 R08: 0000000000000001 R09: 0000000000000000
> R10: 0000000000000000 R11: 0000000000000000 R12: 00000000dafdb000
> R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
> FS: 0000000000000000(0000) GS:ffff88021d200000(0000) knlGS:0000000000000000
> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: ffff88021e5ff000 CR3: 0000000001c10001 CR4: 00000000000606b0
> Call Trace:
> acpi_tb_acquire_table+0x39/0x64
> acpi_tb_validate_table+0x21/0x33
> acpi_tb_get_table+0x25/0x5e
> acpi_get_table+0x59/0x82
> dmar_table_detect+0x1a/0x43
> dmar_table_init+0x73/0x13e
> ? dmar_free_dev_scope+0xe0/0xe0
> ? intel_iommu_setup+0x211/0x211
> ? iommu_calculate_agaw+0x20/0x20
> ? dmar_walk_remapping_entries+0x170/0x170
> ? detect_intel_iommu+0xca/0xca
> intel_prepare_irq_remapping+0x3a/0x22a
> irq_remapping_prepare+0x1a/0x2a
> enable_IR_x2apic+0x21/0x198
> default_setup_apic_routing+0x12/0x6f
> apic_intr_mode_init+0x14b/0x181
> x86_late_time_init+0x11/0x16
> start_kernel+0x3ae/0x44c
> secondary_startup_64+0xa5/0xa5
> Code: 1a 74 2b 42 ff 34 ed 20 3a 11 82 45 89 f0 48 c7 c6 90 df 81 81 48 c7 c7 c0 c7 a6 81 4c 8b 4c 24 08 48 8b 4c 24 10 e8 64 2a 04 ff <0f> ff 58 48 8b 04 24 4a 03 04 ed 20 3a 11 82 4a 89 04 ed a0 3a
> ---[ end trace 52caafcde4fdbc68 ]---
> DMAR: Host address width 36
> DMAR: DRHD base: 0x000000fed90000 flags: 0x0
> DMAR: dmar0: reg_base_addr fed90000 ver 1:0 cap c0000020e60262 ecap f0101a
> DMAR: DRHD base: 0x000000fed91000 flags: 0x1
> DMAR: dmar1: reg_base_addr fed91000 ver 1:0 cap c9008020660262 ecap f0105a
> DMAR: RMRR base: 0x000000da2ba000 end: 0x000000da2d0fff
> DMAR: RMRR base: 0x000000db800000 end: 0x000000df9fffff
> DMAR-IR: IOAPIC id 2 under DRHD base 0xfed91000 IOMMU 1
> DMAR-IR: HPET id 0 under DRHD base 0xfed91000
> DMAR-IR: Queued invalidation will be enabled to support x2apic and Intr-remapping.
> DMAR-IR: Enabled IRQ remapping in x2apic mode
> x2apic enabled
> Switched APIC routing to cluster x2apic.
>