Skip to contentSkip to conversation

enable x2APIC without interrupt remapping under KVM

PATCH Superseded Gleb Natapov 4 participants 11 messages Jun 30, 2009

Subsystems (2)

v4 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

PATCH v4 1/1 enable x2APIC without interrupt remapping under KVM

KVM would like to provide x2APIC interface to a guest without emulating interrupt remapping device. The reason KVM prefers guest to use x2APIC is that x2APIC interface is better virtualizable and provides better performance than mmio xAPIC interface:

- msr exits are faster than mmio (no page table walk, emulation)
- no need to read back ICR to look at the busy bit
- one 64 bit ICR write instead of two 32 bit writes
- shared code with the Hyper-V paravirt interface

Included patch changes x2APIC enabling logic to enable it even if IR initialization failed, but kernel runs under KVM and no apic id is greater than 255 (if there is one spec requires BIOS to move to x2apic mode before starting an OS).

arch/x86/kernel/apic/apic.c +48 -35
index 8c7c042..351d55a 100644
@@ -49,6 +49,7 @@
 #include <asm/mtrr.h>
 #include <asm/smp.h>
 #include <asm/mce.h>
+#include <asm/kvm_para.h>
 
 unsigned int num_processors;
 
@@ -1363,52 +1364,75 @@ void enable_x2apic(void)
 }
 #endif /* CONFIG_X86_X2APIC */
 
-void __init enable_IR_x2apic(void)
+int __init enable_IR(void)
 {
 #ifdef CONFIG_INTR_REMAP
 	int ret;
-	unsigned long flags;
-	struct IO_APIC_route_entry **ioapic_entries = NULL;
 
 	ret = dmar_table_init();
 	if (ret) {
 		pr_debug("dmar_table_init() failed with %d:\n", ret);
-		goto ir_failed;
+		return 0;
 	}
 
 	if (!intr_remapping_supported()) {
 		pr_debug("intr-remapping not supported\n");
-		goto ir_failed;
+		return 0;
 	}
 
-
 	if (!x2apic_preenabled && skip_ioapic_setup) {
 		pr_info("Skipped enabling intr-remap because of skipping "
 			"io-apic setup\n");
-		return;
+		return 0;
 	}
 
+	if (enable_intr_remapping(x2apic_supported()))
+		return 0;
+
+	pr_info("Enabled Interrupt-remapping\n");
+
+	return 1;
+
+#endif
+	return 0;
+}
+
+void __init enable_IR_x2apic(void)
+{
+	unsigned long flags;
+	struct IO_APIC_route_entry **ioapic_entries = NULL;
+	int ret, x2apic_enabled = 0;
+
 	ioapic_entries = alloc_ioapic_entries();
 	if (!ioapic_entries) {
-		pr_info("Allocate ioapic_entries failed: %d\n", ret);
-		goto end;
+		 pr_info("Allocate ioapic_entries failed\n");
+		 goto out;
 	}
 
 	ret = save_IO_APIC_setup(ioapic_entries);
 	if (ret) {
 		pr_info("Saving IO-APIC state failed: %d\n", ret);
-		goto end;
+		goto out;
 	}
 
 	local_irq_save(flags);
-	mask_IO_APIC_setup(ioapic_entries);
 	mask_8259A();
+	mask_IO_APIC_setup(ioapic_entries);
 
-	ret = enable_intr_remapping(x2apic_supported());
-	if (ret)
-		goto end_restore;
+	ret = enable_IR();
+	if (!ret) {
+		/* IR is required if x2apic is enabled by BIOS even
+		 * when running in kvm since this indicates present
+		 * of APIC ID > 255 */
+	       	if (x2apic_preenabled || !kvm_para_available())
+			goto nox2apic;
+		else
+			/* without IR all CPUs can be addressed by IOAPIC/MSI
+			 * only in physical mode */
+			x2apic_phys = 1;
+	}
 
-	pr_info("Enabled Interrupt-remapping\n");
+	x2apic_enabled = 1;
 
 	if (x2apic_supported() && !x2apic_mode) {
 		x2apic_mode = 1;
@@ -1416,41 +1440,30 @@ void __init enable_IR_x2apic(void)
 		pr_info("Enabled x2apic\n");
 	}
 
-end_restore:
-	if (ret)
-		/*
-		 * IR enabling failed
-		 */
+nox2apic:
+	if (!ret) /* IR enabling failed */
 		restore_IO_APIC_setup(ioapic_entries);
-
 	unmask_8259A();
 	local_irq_restore(flags);
 
-end:
+out:
 	if (ioapic_entries)
 		free_ioapic_entries(ioapic_entries);
 
-	if (!ret)
+	if (x2apic_enabled)
 		return;
 
-ir_failed:
-	if (x2apic_preenabled)
+	if (x2apic_preenabled) {
+#ifdef CONFIG_INTR_REMAP
 		panic("x2apic enabled by bios. But IR enabling failed");
-	else if (cpu_has_x2apic)
-		pr_info("Not enabling x2apic,Intr-remapping\n");
 #else
-	if (!cpu_has_x2apic)
-		return;
-
-	if (x2apic_preenabled)
 		panic("x2apic enabled prior OS handover,"
-		      " enable CONFIG_X86_X2APIC, CONFIG_INTR_REMAP");
+				" enable CONFIG_X86_X2APIC, CONFIG_INTR_REMAP");
 #endif
-
-	return;
+	} else if (cpu_has_x2apic)
+		pr_info("Not enabling x2apic,Intr-remapping\n");
 }
 
-
 #ifdef CONFIG_X86_64
 /*
  * Detect and enable local APICs on non-SMP boards.

--
Gleb.

#1 lore raw
Quoted 98 lines · Gleb Natapov

KVM would like to provide x2APIC interface to a guest without emulating interrupt remapping device. The reason KVM prefers guest to use x2APIC is that x2APIC interface is better virtualizable and provides better performance than mmio xAPIC interface:

- msr exits are faster than mmio (no page table walk, emulation)
- no need to read back ICR to look at the busy bit
- one 64 bit ICR write instead of two 32 bit writes
- shared code with the Hyper-V paravirt interface

Included patch changes x2APIC enabling logic to enable it even if IR initialization failed, but kernel runs under KVM and no apic id is greater than 255 (if there is one spec requires BIOS to move to x2apic mode before starting an OS).

arch/x86/kernel/apic/apic.c +4 -6
index 8c7c042..351d55a 100644
@@ -49,6 +49,7 @@
  #include <asm/mtrr.h>
  #include <asm/smp.h>
  #include <asm/mce.h>
+#include <asm/kvm_para.h>
 
  unsigned int num_processors;
 
@@ -1363,52 +1364,75 @@ void enable_x2apic(void)
  }
  #endif /* CONFIG_X86_X2APIC */
 
-void __init enable_IR_x2apic(void)
+int __init enable_IR(void)
  {
  #ifdef CONFIG_INTR_REMAP
        int ret;
-       unsigned long flags;
-       struct IO_APIC_route_entry **ioapic_entries = NULL;
 
        ret = dmar_table_init();
        if (ret) {
                pr_debug("dmar_table_init() failed with %d:\n", ret);
-               goto ir_failed;
+               return 0;
        }
 
        if (!intr_remapping_supported()) {
                pr_debug("intr-remapping not supported\n");
-               goto ir_failed;
+               return 0;
        }
 
-
        if (!x2apic_preenabled && skip_ioapic_setup) {

               pr_info("Skipped enabling intr-remap because of skipping " "io-apic setup\n");
-               return;
+               return 0;
       }

+       if (enable_intr_remapping(x2apic_supported()))
+               return 0;

arch/x86/kernel/apic/apic.c +15 -0
+
+       pr_info("Enabled Interrupt-remapping\n");
+
+       return 1;
+
+#endif
+       return 0;
+}
+
+void __init enable_IR_x2apic(void)
+{
+       unsigned long flags;
+       struct IO_APIC_route_entry **ioapic_entries = NULL;
+       int ret, x2apic_enabled = 0;
+

       ioapic_entries = alloc_ioapic_entries();
       if (!ioapic_entries) {
-               pr_info("Allocate ioapic_entries failed: %d\n", ret);
-               goto end;
+                pr_info("Allocate ioapic_entries failed\n");
+                goto out;
       }

       ret = save_IO_APIC_setup(ioapic_entries);
       if (ret) {
               pr_info("Saving IO-APIC state failed: %d\n", ret);
-               goto end;
+               goto out;
       }

       local_irq_save(flags);
-       mask_IO_APIC_setup(ioapic_entries);
       mask_8259A();
+       mask_IO_APIC_setup(ioapic_entries);

Quoted 15 lines

-       ret = enable_intr_remapping(x2apic_supported());
-       if (ret)
-               goto end_restore;
+       ret = enable_IR();
+       if (!ret) {
+               /* IR is required if x2apic is enabled by BIOS even
+                * when running in kvm since this indicates present
+                * of APIC ID > 255 */
+               if (x2apic_preenabled || !kvm_para_available())
+                       goto nox2apic;
+               else
+                       /* without IR all CPUs can be addressed by IOAPIC/MSI
+                        * only in physical mode */
+                       x2apic_phys = 1;
+       }

how about kexec second kernel in KVM ?

x2apic_preenabled will be set in second kernel.

YH

#2 lore raw
Quoted 117 lines · Yinghai Lu
Quoted 98 lines · Gleb Natapov

KVM would like to provide x2APIC interface to a guest without emulating interrupt remapping device. The reason KVM prefers guest to use x2APIC is that x2APIC interface is better virtualizable and provides better performance than mmio xAPIC interface:

- msr exits are faster than mmio (no page table walk, emulation)
- no need to read back ICR to look at the busy bit
- one 64 bit ICR write instead of two 32 bit writes
- shared code with the Hyper-V paravirt interface

Included patch changes x2APIC enabling logic to enable it even if IR initialization failed, but kernel runs under KVM and no apic id is greater than 255 (if there is one spec requires BIOS to move to x2apic mode before starting an OS).

arch/x86/kernel/apic/apic.c +4 -6
index 8c7c042..351d55a 100644
@@ -49,6 +49,7 @@
  #include <asm/mtrr.h>
  #include <asm/smp.h>
  #include <asm/mce.h>
+#include <asm/kvm_para.h>
 
  unsigned int num_processors;
 
@@ -1363,52 +1364,75 @@ void enable_x2apic(void)
  }
  #endif /* CONFIG_X86_X2APIC */
 
-void __init enable_IR_x2apic(void)
+int __init enable_IR(void)
  {
  #ifdef CONFIG_INTR_REMAP
        int ret;
-       unsigned long flags;
-       struct IO_APIC_route_entry **ioapic_entries = NULL;
 
        ret = dmar_table_init();
        if (ret) {
                pr_debug("dmar_table_init() failed with %d:\n", ret);
-               goto ir_failed;
+               return 0;
        }
 
        if (!intr_remapping_supported()) {
                pr_debug("intr-remapping not supported\n");
-               goto ir_failed;
+               return 0;
        }
 
-
        if (!x2apic_preenabled && skip_ioapic_setup) {

               pr_info("Skipped enabling intr-remap because of skipping " "io-apic setup\n");
-               return;
+               return 0;
       }

+       if (enable_intr_remapping(x2apic_supported()))
+               return 0;

arch/x86/kernel/apic/apic.c +15 -0
+
+       pr_info("Enabled Interrupt-remapping\n");
+
+       return 1;
+
+#endif
+       return 0;
+}
+
+void __init enable_IR_x2apic(void)
+{
+       unsigned long flags;
+       struct IO_APIC_route_entry **ioapic_entries = NULL;
+       int ret, x2apic_enabled = 0;
+

       ioapic_entries = alloc_ioapic_entries();
       if (!ioapic_entries) {
-               pr_info("Allocate ioapic_entries failed: %d\n", ret);
-               goto end;
+                pr_info("Allocate ioapic_entries failed\n");
+                goto out;
       }

       ret = save_IO_APIC_setup(ioapic_entries);
       if (ret) {
               pr_info("Saving IO-APIC state failed: %d\n", ret);
-               goto end;
+               goto out;
       }

       local_irq_save(flags);
-       mask_IO_APIC_setup(ioapic_entries);
       mask_8259A();
+       mask_IO_APIC_setup(ioapic_entries);

Quoted 15 lines

-       ret = enable_intr_remapping(x2apic_supported());
-       if (ret)
-               goto end_restore;
+       ret = enable_IR();
+       if (!ret) {
+               /* IR is required if x2apic is enabled by BIOS even
+                * when running in kvm since this indicates present
+                * of APIC ID > 255 */
+               if (x2apic_preenabled || !kvm_para_available())
+                       goto nox2apic;
+               else
+                       /* without IR all CPUs can be addressed by IOAPIC/MSI
+                        * only in physical mode */
+                       x2apic_phys = 1;
+       }

how about kexec second kernel in KVM ?

Quoted 2 lines

x2apic_preenabled will be set in second kernel.

Yes, bummer. But the similar problem exist now and without KVM. After running x2apic enabled kernel you can't kexec kernel without x2apic support. Shouldn't apic be reset to its initial state on reboot?

--
Gleb.

#3 lore raw

2009/6/30 Gleb Natapov <[email protected]>:

Quoted 8 lines
Quoted 5 lines

how about kexec second kernel in KVM ?

x2apic_preenabled will be set in second kernel.

Yes, bummer. But the similar problem exist now and without KVM. After running x2apic enabled kernel you can't kexec kernel without x2apic support.

if the first kernel enable x2apic and intr_remapping, and second kernel has x2apic and intr_remap support.
we can kexec the second kernel.

restoring to original state is not possible for kdump case.

maybe with minor change to your patch, you could kexec the in kexec second kernel with x2apic support.

YH

#4 lore raw
Quoted 7 lines · Yinghai Lu

2009/6/30 Gleb Natapov <[email protected]>:

Quoted 5 lines
Quoted 5 lines

how about kexec second kernel in KVM ?

x2apic_preenabled will be set in second kernel.

Quoted 8 lines
Quoted 3 lines

Yes, bummer. But the similar problem exist now and without KVM. After running x2apic enabled kernel you can't kexec kernel without x2apic support.

if the first kernel enable x2apic and intr_remapping, and second kernel has x2apic and intr_remap support.
we can kexec the second kernel.

And if it hasn't we cannot, that is what I am trying to point out.

Quoted 2 lines

restoring to original state is not possible for kdump case.

Shouldn't it be enough to run UP kernel for kdump? So kdump can reset BSP apic to xAPIC mode before starting a kernel with maxcpus=1.

Quoted 3 lines

maybe with minor change to your patch, you could kexec the in kexec second kernel with x2apic support.

My patch can easily avoid the issue by checking max_physical_apicid > 255 instead of x2apic_preenabled.

--
Gleb.

#5 lore raw
In reply to Yinghai Lu
Quoted 4 lines · Yinghai Lu

how about kexec second kernel in KVM ?

x2apic_preenabled will be set in second kernel.

By the way anybody knows why kexec does not use BIOS reset code (cmos 0xf offset) to jump into new kernel after hard reset?

--
Gleb.

#6 lore raw
Quoted 7 lines · Gleb Natapov
Quoted 4 lines · Yinghai Lu

how about kexec second kernel in KVM ?

x2apic_preenabled will be set in second kernel.

By the way anybody knows why kexec does not use BIOS reset code (cmos 0xf offset) to jump into new kernel after hard reset?

After a hard reset. That simply isn't possible. A hard reset clears everything even memory.

You might be able to get a full cpu reset but not a reset of the I/O devices.

The premise of kexec is that we are doing things on our own, and don't get a 3rd piece of software involved that has not been heavily tested on the path we want to use. Occassionally it is a pain to do everything ourselves but at least when we do and we test it we know it is going to work.

Cpu designers lately seem fond of adding features that require all kind of coordination to turn on and off. We handle the hardware virtualization mode features now, and if x2apic has similar problems being turned on and off I am certain we can handle that case in a similar fashion.

When we can my preference is to keep code like that out of the kexec on panic path if we can figure out how to write the software to do something reasonable.

Once we figure out how to work without putting the interrupt controllers in legacy mode to handle the timer interrupts I expect all kinds of things will become simpler.

Eric

#7 lore raw
Quoted 10 lines · Eric W. Biederman
Quoted 7 lines · Gleb Natapov
Quoted 5 lines · Yinghai Lu

how about kexec second kernel in KVM ?

x2apic_preenabled will be set in second kernel.

Quoted 8 lines
Quoted 3 lines

By the way anybody knows why kexec does not use BIOS reset code (cmos 0xf offset) to jump into new kernel after hard reset?

After a hard reset. That simply isn't possible. A hard reset clears everything even memory.

So the jump-to-vector reset code cannot work on real hardware? It works in qemu, but of course that's easy.

Quoted 15 lines

You might be able to get a full cpu reset but not a reset of the I/O devices.

The premise of kexec is that we are doing things on our own, and don't get a 3rd piece of software involved that has not been heavily tested on the path we want to use. Occassionally it is a pain to do everything ourselves but at least when we do and we test it we know it is going to work.

Cpu designers lately seem fond of adding features that require all kind of coordination to turn on and off. We handle the hardware virtualization mode features now, and if x2apic has similar problems being turned on and off I am certain we can handle that case in a similar fashion.

Quoted 8 lines

When we can my preference is to keep code like that out of the kexec on panic path if we can figure out how to write the software to do something reasonable.

Once we figure out how to work without putting the interrupt controllers in legacy mode to handle the timer interrupts I expect all kinds of things will become simpler.

I think it makes sense to add full reset support as a non-default option. Leaving hardware running and dmaing left and right has its risks.

Signature · 2 lines
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
#8 lore raw
Quoted 2 lines · Avi Kivity

So the jump-to-vector reset code cannot work on real hardware? It works in qemu, but of course that's easy.

In general yes. Nothing regularly uses that path so there is little point adding a new users if we can avoid it.

Heck there are machines with unreliable cmos.

Quoted 19 lines
Quoted 19 lines

You might be able to get a full cpu reset but not a reset of the I/O devices.

The premise of kexec is that we are doing things on our own, and don't get a 3rd piece of software involved that has not been heavily tested on the path we want to use. Occassionally it is a pain to do everything ourselves but at least when we do and we test it we know it is going to work.

Cpu designers lately seem fond of adding features that require all kind of coordination to turn on and off. We handle the hardware virtualization mode features now, and if x2apic has similar problems being turned on and off I am certain we can handle that case in a similar fashion.

When we can my preference is to keep code like that out of the kexec on panic path if we can figure out how to write the software to do something reasonable.

Quoted 7 lines
Quoted 4 lines

Once we figure out how to work without putting the interrupt controllers in legacy mode to handle the timer interrupts I expect all kinds of things will become simpler.

I think it makes sense to add full reset support as a non-default option. Leaving hardware running and dmaing left and right has its risks.

It is easy enough to do that in user space in /sbin/kexec if that proves useful for some reason.

As for the leaving hardware running and dmaing left and right. You are talking about the kexec on panic code path. On a normal reboot we do our darndest to cleanly shut everything down properly.

We avoid the dmaing left and right problem by reserving a chunk of memory at boot time and we probably should be reserving a chunk of the iommus as well for that purpose.

Hardware resets in general don't preserve the contents of memory.

In general the kexec on panic path is about teaching drivers to initialize in the worst possible scenario and using those drivers that can to get information out of the system.

At the same time 99% of the code that runs is in user space so it should be easy to jump through whatever hoops make sense in the user space component. While keeping the kexec on panic code path as slim as possible.

Eric

#9 lore raw
In reply to Eric W. Biederman
Quoted 5 lines · Eric W. Biederman
Quoted 3 lines · Gleb Natapov
Quoted 2 lines · Yinghai Lu

how about kexec second kernel in KVM ?

Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

x2apic_preenabled will be set in second kernel.

By the way anybody knows why kexec does not use BIOS reset code (cmos 0xf offset) to jump into new kernel after hard reset?

After a hard reset. That simply isn't possible. A hard reset clears everything even memory.

I mean "soft reset". At least on 286 in order to move from protected mode to real mode "soft reset" was issued via kbd controller or via triple fault. BIOS reset code was used to avoid POST. Obviously back than this kind of reset haven't cleared memory. I'll try to check what happens on a modern HW.

BTW Linux sets BIOS reset code to "return by long jump" in smpboot_setup_warm_reset() for some reason.

Quoted 15 lines

You might be able to get a full cpu reset but not a reset of the I/O devices.

The premise of kexec is that we are doing things on our own, and don't get a 3rd piece of software involved that has not been heavily tested on the path we want to use. Occassionally it is a pain to do everything ourselves but at least when we do and we test it we know it is going to work.

Cpu designers lately seem fond of adding features that require all kind of coordination to turn on and off. We handle the hardware virtualization mode features now, and if x2apic has similar problems being turned on and off I am certain we can handle that case in a similar fashion.

Quoted 8 lines

When we can my preference is to keep code like that out of the kexec on panic path if we can figure out how to write the software to do something reasonable.

Once we figure out how to work without putting the interrupt controllers in legacy mode to handle the timer interrupts I expect all kinds of things will become simpler.

If the "soft reset" method can work it worth to implemented. I am not suggesting we should make it default (just line --real-mode is not default).

--
Gleb.

#10 lore raw
In reply to Gleb Natapov
Quoted 7 lines · Gleb Natapov
Quoted 4 lines · Yinghai Lu

how about kexec second kernel in KVM ?

x2apic_preenabled will be set in second kernel.

By the way anybody knows why kexec does not use BIOS reset code (cmos 0xf offset) to jump into new kernel after hard reset?

What I said before plus the fact that kexec grew up on systems that don't have a BIOS. So the option of using that piece of was not there.

Eric