Skip to contentSkip to conversation

kexec: apic-virtwire-on-shutdown.i386.patch

PATCH In review Eric W. Biederman 2 participants 7 messages Aug 20, 2004 – Aug 30, 2004

lore
Share & tools
lore
#0 lore raw

PATCH 3/14 kexec: apic-virtwire-on-shutdown.i386.patch

Restore the local apic to virtual wire mode on reboot.

arch/i386/kernel/apic.c +30 -0
diff -uNr linux-2.6.8.1-mm2-i8259-sysfs.x86_64/arch/i386/kernel/apic.c linux-2.6.8.1-mm2-apic-virtwire-on-shutdown.i386/arch/i386/kernel/apic.c
@@ -202,6 +202,36 @@
 		outb(0x70, 0x22);
 		outb(0x00, 0x23);
 	}
+	else {
+		/* Go back to Virtual Wire compatibility mode */
+		unsigned long value;
+
+		/* For the spurious interrupt use vector F, and enable it */
+		value = apic_read(APIC_SPIV);
+		value &= ~APIC_VECTOR_MASK;
+		value |= APIC_SPIV_APIC_ENABLED;
+		value |= 0xf;
+		apic_write_around(APIC_SPIV, value);
+
+		/* For LVT0 make it edge triggered, active high, external and enabled */
+		value = apic_read(APIC_LVT0);
+		value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
+			APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+			APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
+		value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+		value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXINT);
+		apic_write_around(APIC_LVT0, value);
+
+		/* For LVT1 make it edge triggered, active high, nmi and enabled */
+		value = apic_read(APIC_LVT1);
+		value &= ~(
+			APIC_MODE_MASK | APIC_SEND_PENDING |
+			APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+			APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
+		value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+		value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
+		apic_write_around(APIC_LVT1, value);
+	}
 }
 
 void disable_local_APIC(void)
include/asm-i386/apicdef.h +1 -0
diff -uNr linux-2.6.8.1-mm2-i8259-sysfs.x86_64/include/asm-i386/apicdef.h linux-2.6.8.1-mm2-apic-virtwire-on-shutdown.i386/include/asm-i386/apicdef.h
@@ -86,6 +86,7 @@
 #define			APIC_LVT_REMOTE_IRR		(1<<14)
 #define			APIC_INPUT_POLARITY		(1<<13)
 #define			APIC_SEND_PENDING		(1<<12)
+#define			APIC_MODE_MASK			0x700
 #define			GET_APIC_DELIVERY_MODE(x)	(((x)>>8)&0x7)
 #define			SET_APIC_DELIVERY_MODE(x,y)	(((x)&~0x700)|((y)<<8))
 #define				APIC_MODE_FIXED		0x0
#1 lore raw
Quoted 1 line · Eric W. Biederman

Restore the local apic to virtual wire mode on reboot.

Hmm, perhaps you should check for the through-I/O-APIC Virtual Wire mode.
I've seen reports from such systems in the past. They may not necessarily handle the through-Local-APIC mode correctly.

Maciej

#2 lore raw
Quoted 7 lines · Maciej W. Rozycki
Quoted 1 line · Eric W. Biederman

Restore the local apic to virtual wire mode on reboot.

Hmm, perhaps you should check for the through-I/O-APIC Virtual Wire mode.
I've seen reports from such systems in the past. They may not necessarily handle the through-Local-APIC mode correctly.

I do that however is done as a separate patch.

The local apic still needs to be put into virtual wire mode in that case.

Eric

#3 lore raw
Quoted 2 lines · Eric W. Biederman

The local apic still needs to be put into virtual wire mode in that case.

Well, depending on actual wiring you may need to mask LINT0 in this case
to avoid duplicate interrupts. I think the safest approach would be remembering the initial values of LVT0 and LVT1 registers of the BSP -- they are just four bytes each, so it would not be a terrible memory waste.

Maciej

#4 lore raw
Quoted 9 lines · Maciej W. Rozycki
Quoted 2 lines · Eric W. Biederman

The local apic still needs to be put into virtual wire mode in that case.

Well, depending on actual wiring you may need to mask LINT0 in this case
to avoid duplicate interrupts. I think the safest approach would be remembering the initial values of LVT0 and LVT1 registers of the BSP -- they are just four bytes each, so it would not be a terrible memory waste.

If I was seeing problems I guess I would worry about it. As I have tested on both Opteron's which require the ioapic to be in virtual wire mode, and on Xeons which require the local apic to be in virtual wire mode and both work I am not too concerned.

I don't think the configuration you are worrying about where both the ioapic and the local apic can both be put into virtual wire mode is valid according to the mp specification. Although that is probably a grey area in the specification.

It is more code to save off and then restore the registers, then simply hard coding a value into them.

It is nice to have hard coded values when you can as then you don't have to guess how something was configured on this occasion.

As my code is simpler than your suggestion and it works I'm not a fan of changing it until I see a case where it breaks.

Eric

#5 lore raw
Quoted 4 lines · Eric W. Biederman

I don't think the configuration you are worrying about where both the ioapic and the local apic can both be put into virtual wire mode is valid according to the mp specification. Although that is probably a grey area in the specification.

The spec doesn't preclude a configuration where the master i8259A is
wired both to an I/O APIC input and to local APIC inputs. If this is the case, it's a sole discretion of the system manufacturer to choose which route for the "virtual wire" is used.

I don't insist on doing exact LVT restoration as at this stage it
shouldn't really matter and the firmware should reinitialize the APIC subsystem completely anyway. I just wanted to be sure you are aware of the issue.

Maciej

#6 lore raw
Quoted 12 lines · Maciej W. Rozycki
Quoted 4 lines · Eric W. Biederman

I don't think the configuration you are worrying about where both the ioapic and the local apic can both be put into virtual wire mode is valid according to the mp specification. Although that is probably a grey area in the specification.

The spec doesn't preclude a configuration where the master i8259A is
wired both to an I/O APIC input and to local APIC inputs. If this is the case, it's a sole discretion of the system manufacturer to choose which route for the "virtual wire" is used.

Quoted 4 lines

I don't insist on doing exact LVT restoration as at this stage it
shouldn't really matter and the firmware should reinitialize the APIC subsystem completely anyway. I just wanted to be sure you are aware of the issue.

Thanks. I will keep it in mind.

Actually now that I think about it I believe recent Intel chipsets Tumwater/Lindenhurst work both ways but they have a bug that can be triggered unless you are using the IOAPIC in virtual wire mode.

In practice I still don't think it matters as everything across the hub interface and PCI-e is message based and I don't think 2 messages are generated. Still I will give it some thought.

Eric