lapic and ioapic support that's Not Good Enough.
authorRonald G. Minnich <rminnich@gmail.com>
Fri, 16 Oct 2015 17:04:11 +0000 (10:04 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 2 Nov 2015 23:53:50 +0000 (18:53 -0500)
I really hate to do this, but I think I'm going to have to bring in the
whole enchilada from linux :-(

The linux kernel is just not happy with the level of support I'm providing.
We've tried counseling and adjustment, but this relationship is not working.

Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/vmm/intel/vmx.c
tests/vmm/vmrunkernel.c
user/vmm/decode.c

index d87596d..1ebbe2e 100644 (file)
@@ -1146,6 +1146,9 @@ struct emmsr emmsrs[] = {
        // mostly harmless.
        {MSR_TSC_AUX, "MSR_TSC_AUX", emsr_fakewrite},
        {MSR_RAPL_POWER_UNIT, "MSR_RAPL_POWER_UNIT", emsr_readzero},
+
+       // TBD
+       {MSR_IA32_TSC_DEADLINE, "MSR_IA32_TSC_DEADLINE", emsr_fakewrite},
 };
 
 static uint64_t set_low32(uint64_t hi, uint32_t lo)
index bf963d8..9ceefab 100644 (file)
@@ -24,6 +24,7 @@
 #include <vmm/virtio_config.h>
 
 int msrio(struct vmctl *vcpu, uint32_t opcode);
+#if 0
 /* Kind of sad what a total clusterf the pc world is. By 1999, you could just scan the hardware 
  * and work it out. But 2005, that was no longer possible. How sad. 
  * so we have to fake acpi to make it all work. !@#$!@#$#.
@@ -83,6 +84,7 @@ struct acpi_madt_local_apic Apic0 = {.header = {.type = ACPI_MADT_TYPE_LOCAL_API
                                     .processor_id = 0, .id = 0};
 struct acpi_madt_io_apic Apic1 = {.header = {.type = ACPI_MADT_TYPE_IO_APIC, .length = sizeof(struct acpi_madt_io_apic)},
                                  .id = 1, .address = 0xfec00000, .global_irq_base = 0};
+#endif
 
 /* this test will run the "kernel" in the negative address space. We hope. */
 void *low1m;
@@ -261,10 +263,12 @@ static void gencsum(uint8_t *target, void *data, int len)
 int main(int argc, char **argv)
 {
        void *a = (void *)0xe0000;
+#if 0
        struct acpi_table_rsdp *r;
        struct acpi_table_fadt *f;
        struct acpi_table_madt *m;
        struct acpi_table_xsdt *x;
+#endif
        uint64_t virtiobase = 0x100000000ULL;
        // lowmem is a bump allocated pointer to 2M at the "physbase" of memory 
        void *lowmem = (void *) 0x1000000;
@@ -360,6 +364,7 @@ printf("%p %p %p %p\n", PGSIZE, PGSHIFT, PML1_SHIFT, PML1_PTE_REACH);
                exit(1);
        }
        memset(low1m, 0xff, MiB-4096);
+#if 0
        r = a;
        fprintf(stderr, "install rsdp to %p\n", r);
        *r = rsdp;
@@ -426,6 +431,7 @@ printf("%p %p %p %p\n", PGSIZE, PGSHIFT, PML1_SHIFT, PML1_PTE_REACH);
        }
 
        hexdump(stdout, r, a-(void *)r);
+#endif
 
        if (ros_syscall(SYS_setup_vmm, nr_gpcs, vmmflags, 0, 0, 0, 0) != nr_gpcs) {
                perror("Guest pcore setup failed");
@@ -533,6 +539,7 @@ printf("%p %p %p %p\n", PGSIZE, PGSHIFT, PML1_SHIFT, PML1_PTE_REACH);
                                if (debug) printf("DO SOME VIRTIO\n");
                                // Lucky for us the various virtio ops are well-defined.
                                virtio_mmio(&vmctl, gpa, regx, regp, store);
+#if 0
                        } else if ((gpa & 0xfee00000) == 0xfee00000) {
                                // until we fix our include mess, just put the proto here.
                                int apic(struct vmctl *v, uint64_t gpa, int destreg, uint64_t *regp, int store);
@@ -541,6 +548,7 @@ printf("%p %p %p %p\n", PGSIZE, PGSHIFT, PML1_SHIFT, PML1_PTE_REACH);
                                // until we fix our include mess, just put the proto here.
                                int ioapic(struct vmctl *v, uint64_t gpa, int destreg, uint64_t *regp, int store);
                                ioapic(&vmctl, gpa, regx, regp, store);
+#endif
                        } else if (gpa < 4096) {
                                uint64_t val = 0;
                                memmove(&val, &low4k[gpa], size);
index 4aa0420..f1575dc 100644 (file)
@@ -44,7 +44,11 @@ int debug_decode = 0;
 static char *modrmreg[] = {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"};
 
 // Since we at most have to decode less than half of each instruction, I'm trying to be dumb here.
-// Fortunately, for me, what's not hard.
+// Fortunately, for me, that's not hard.
+// I'm trying to avoid the whole Big Fun of full instruction decode, and in most of these
+// cases we only have to know register, address, operation size, and instruction length.
+// The ugly messiness of the SIB and all that are not yet needed. Maybe they
+// never will be.
 
 // Target size -- 1, 2, 4, or 8 bytes. We have yet to see 64 bytes. 
 // TODO: if we ever see it, test the prefix. Since this only supports the low 1M,
@@ -62,6 +66,10 @@ static int target(void *insn, int *store)
                s = s == 4 ? 2 : 4;
                return s;
        }
+       if (*byte == 0x44) {
+               byte++;
+               word++;
+       }
        switch(*byte) {
        case 0x3a:
        case 0x8a:
@@ -117,6 +125,12 @@ static int insize(void *rip)
 {
        uint8_t *kva = rip;
        int advance = 3;
+       int extra = 0;
+       if (kva[0] == 0x44) {
+               extra = 1;
+               kva++;
+       }
+
        /* the dreaded mod/rm byte. */
        int mod = kva[1]>>6;
        int rm = kva[1] & 7;
@@ -127,7 +141,7 @@ static int insize(void *rip)
        case 0x0f: 
                break;
        case 0x81:
-               advance = 6;
+               advance = 6 + extra;
                break;
        case 0x3a:
        case 0x8a:
@@ -136,16 +150,16 @@ static int insize(void *rip)
        case 0x8b:
                switch (mod) {
                case 0: 
-                       advance = 2 + (rm == 4);
+                       advance = 2 + (rm == 4) + extra;
                        break;
                case 1:
-                       advance = 3 + (rm == 4);
+                       advance = 3 + (rm == 4) + extra;
                        break;
                case 2: 
-                       advance = 6 + (rm == 4);
+                       advance = 6 + (rm == 4) + extra;
                        break;
                case 3:
-                       advance = 2;
+                       advance = 2 + extra;
                        break;
                }
                break;
@@ -193,11 +207,11 @@ int decode(struct vmctl *v, uint64_t *gpa, uint8_t *destreg, uint64_t **regp, in
        if (*size < 0)
                return -1;
 
-       uint16_t ins = *(uint16_t *)kva;
-       DPRINTF("ins is %04x\n", ins);
-       
        *advance = insize(kva);
 
+       uint16_t ins = *(uint16_t *)(kva + 8*(kva[0] == 0x44));
+       DPRINTF("ins is %04x\n", ins);
+               
        *destreg = (ins>>11) & 7;
        // Our primitive approach wins big here.
        // We don't have to decode the register or the offset used