[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [patch 2/2] Preserve correct PIC vectors across Xen vmxassist 16/32-bit transitions



Hi,

On Tue, 2007-05-22 at 14:54 +0100, Stephen C. Tweedie wrote:

> The following two patches --- one to the HV, one to the tools --- allow
> rawhide isos to boot under Xen full virtualisation.

And this is the userland tools side of the fix.

> So the fix here is ... secondly to have vmxassist use that sequence to reset 
> the PIC
> vectors appropriately whenever we transition between 16 and 32-bit mode.

This code teaches vmxassist:

1) to remember how the guest has set up the virtual PIC interrupt
vectors; and
2) to reprogram the vPIC to point to the true guest vector when entering
32-bit mode, and to point back to the vmxassist bounce-irq traps when
reentering 16-bit mode.

--Stephen
--- xen-3.1.0-testing.hg-rc7.irq/tools/firmware/vmxassist/vm86.c.~1~    
2007-05-03 17:49:28.000000000 +0100
+++ xen-3.1.0-testing.hg-rc7.irq/tools/firmware/vmxassist/vm86.c        
2007-05-22 14:03:59.000000000 +0100
@@ -1020,6 +1020,7 @@ real_mode(struct regs *regs)
  * when we transitioned to protected mode and we should abandon the
  * emulator. No instructions are emulated when in VM86_PROTECTED mode.
  */
+static void reset_PIC_translation(int mode);
 void
 set_mode(struct regs *regs, enum vm86_mode newmode)
 {
@@ -1028,6 +1029,7 @@ set_mode(struct regs *regs, enum vm86_mo
                if ((mode == VM86_PROTECTED_TO_REAL) ||
                    (mode == VM86_REAL_TO_PROTECTED)) {
                        regs->eflags &= ~EFLAGS_TF;
+                       reset_PIC_translation(newmode);
                        real_mode(regs);
                } else if (mode != VM86_REAL)
                        panic("unexpected real mode transition");
@@ -1058,6 +1060,7 @@ set_mode(struct regs *regs, enum vm86_mo
        case VM86_PROTECTED:
                if (mode != VM86_REAL_TO_PROTECTED)
                        panic("unexpected protected mode transition");
+               reset_PIC_translation(newmode);
                protected_mode(regs);
                break;
        }
@@ -1157,25 +1160,16 @@ interrupt(struct regs *regs, int n)
  * careful and make sure the emulated program isn't remapping the
  * interrupt vectors. The following simple state machine catches
  * these attempts and rewrites them.
+ *
+ * We also have to be careful to record the intended vector, so that we
+ * can restore it on transition to 32-bit mode.
  */
-static int
-outbyte(struct regs *regs, unsigned prefix, unsigned opc)
+
+static int PIC_vector[2] = {0};
+       
+static int translate_PIC_vector(int port, int al)
 {
        static char icw2[2] = { 0 };
-       int al, port;
-
-       switch (opc) {
-       case 0xE6: /* outb port, al */
-               port = fetch8(regs);
-               break;
-       case 0xEE: /* outb (%dx), al */
-               port = MASK16(regs->edx);
-               break;
-       default:
-               return 0;
-       }
-
-       al = regs->eax & 0xFF;
 
        switch (port) {
        case PIC_MASTER + PIC_CMD:
@@ -1187,6 +1181,7 @@ outbyte(struct regs *regs, unsigned pref
                        icw2[0] = 0;
                        printf("Remapping master: ICW2 0x%x -> 0x%x\n",
                                al, NR_EXCEPTION_HANDLER);
+                       PIC_vector[0] = al & 0xf8;
                        al = NR_EXCEPTION_HANDLER;
                }
                break;
@@ -1200,11 +1195,58 @@ outbyte(struct regs *regs, unsigned pref
                        icw2[1] = 0;
                        printf("Remapping slave: ICW2 0x%x -> 0x%x\n",
                                al, NR_EXCEPTION_HANDLER+8);
+                       PIC_vector[1] = al & 0xf8;
                        al = NR_EXCEPTION_HANDLER+8;
                }
                break;
+       default:
+               return 0; 
+       }
+
+       outb(port, al);
+       return 1;
+}
+
+static void reset_PIC_translation(int mode)
+{
+       int vec0, vec1;
+       
+       if (mode == VM86_PROTECTED)
+               vec0 = PIC_vector[0], vec1 = PIC_vector[1];
+       else if (mode == VM86_REAL)
+               vec0 = NR_EXCEPTION_HANDLER, vec1 = NR_EXCEPTION_HANDLER+8;
+       else
+               panic("reset_PIC_translation");
+       /* Use a non-standard, modified PIC initialisation sequence
+        * (supported by the HV vpic.c) to rewrite the icw2 irq vector
+        * without fully reinitialising the entire PIC state */
+       outb(0x20, 0xff);
+       outb(0x21, vec0);
+       outb(0xa0, 0xff);
+       outb(0xa1, vec1);
+}
+
+static int
+outbyte(struct regs *regs, unsigned prefix, unsigned opc)
+{
+       int al, port;
+
+       switch (opc) {
+       case 0xE6: /* outb port, al */
+               port = fetch8(regs);
+               break;
+       case 0xEE: /* outb (%dx), al */
+               port = MASK16(regs->edx);
+               break;
+       default:
+               return 0;
        }
 
+       al = regs->eax & 0xFF;
+
+       if (translate_PIC_vector(port, al))
+               return 1;
+       
        outb(port, al);
        return 1;
 }
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.