Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


working paged real mode
Jack Lange [Fri, 14 Mar 2008 22:59:33 +0000 (22:59 +0000)]
19 files changed:
palacios/build/Makefile
palacios/build/vm_kernel
palacios/include/geekos/svm.h
palacios/include/geekos/svm_handler.h [new file with mode: 0644]
palacios/include/geekos/tss.h
palacios/include/geekos/vm_guest.h
palacios/include/geekos/vmcb.h
palacios/include/geekos/vmm.h
palacios/include/geekos/vmm_debug.h [new file with mode: 0644]
palacios/include/geekos/vmm_io.h [new file with mode: 0644]
palacios/src/geekos/gdt.c
palacios/src/geekos/int.c
palacios/src/geekos/main.c
palacios/src/geekos/svm.c
palacios/src/geekos/svm_handler.c [new file with mode: 0644]
palacios/src/geekos/svm_lowlevel.asm
palacios/src/geekos/tss.c
palacios/src/geekos/vmm_debug.c [new file with mode: 0644]
palacios/src/geekos/vmm_io.c [new file with mode: 0644]

index ab3ad93..1406a31 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile for GeekOS kernel, userspace, and tools
 # Copyright (c) 2004,2005 David H. Hovemeyer <daveho@cs.umd.edu>
-# $Revision: 1.16 $
+# $Revision: 1.17 $
 
 # This is free software.  You are permitted to use,
 # redistribute, and modify it as specified in the file "COPYING".
@@ -85,8 +85,8 @@ KERNEL_C_SRCS := idt.c int.c trap.c irq.c io.c \
        synch.c kthread.c \
        serial.c  reboot.c \
         paging.c vmx.c vmcs_gen.c vmcs.c \
-        svm.c vmm.c vmm_util.c vmm_stubs.c \
-       vmcb.c vmm_mem.c vm_guest.c vmm_paging.c \
+        svm.c svm_handler.c vmm.c vmm_util.c vmm_stubs.c \
+       vmcb.c vmm_mem.c vm_guest.c vmm_paging.c vmm_io.c vmm_debug.c \
        debug.c\
        main.c
 
@@ -182,7 +182,7 @@ NUMSECS := $(PERL) $(PROJECT_ROOT)/scripts/numsecs
 # ----------------------------------------------------------------------
 
 # Flags used for all C source files
-GENERAL_OPTS := -O -Wall $(EXTRA_C_OPTS) $(JRLDEBUG) $(PADFLAGS)
+GENERAL_OPTS := -O -Wall $(EXTRA_C_OPTS) $(JRLDEBUG) $(PADFLAGS) -fPIC
 CC_GENERAL_OPTS := $(GENERAL_OPTS) -Werror 
 
 # Flags used for kernel C source files
index 417ac70..9898214 100755 (executable)
Binary files a/palacios/build/vm_kernel and b/palacios/build/vm_kernel differ
index 6bb2389..0b91f45 100644 (file)
 
 
 
-/******************************************/
-/* SVM Intercept Exit Codes               */
-/* AMD Arch Vol 3, Appendix C, pg 477-478 */
-/******************************************/
-#define VMEXIT_CR_READ_MASK 0xfffffff0
-#define VMEXIT_CR0_READ   0x00000000
-#define VMEXIT_CR1_READ   0x00000001
-#define VMEXIT_CR2_READ   0x00000002
-#define VMEXIT_CR3_READ   0x00000003
-#define VMEXIT_CR4_READ   0x00000004
-#define VMEXIT_CR5_READ   0x00000005
-#define VMEXIT_CR6_READ   0x00000006
-#define VMEXIT_CR7_READ   0x00000007
-#define VMEXIT_CR8_READ   0x00000008
-#define VMEXIT_CR9_READ   0x00000009
-#define VMEXIT_CR10_READ  0x0000000a
-#define VMEXIT_CR11_READ  0x0000000b
-#define VMEXIT_CR12_READ  0x0000000c
-#define VMEXIT_CR13_READ  0x0000000d
-#define VMEXIT_CR14_READ  0x0000000e
-#define VMEXIT_CR15_READ  0x0000000f
-
-#define VMEXIT_CR_WRITE_MASK 0xffffffe0
-#define VMEXIT_CR0_WRITE   0x00000010
-#define VMEXIT_CR1_WRITE   0x00000011
-#define VMEXIT_CR2_WRITE   0x00000012
-#define VMEXIT_CR3_WRITE   0x00000013
-#define VMEXIT_CR4_WRITE   0x00000014
-#define VMEXIT_CR5_WRITE   0x00000015
-#define VMEXIT_CR6_WRITE   0x00000016
-#define VMEXIT_CR7_WRITE   0x00000017
-#define VMEXIT_CR8_WRITE   0x00000018
-#define VMEXIT_CR9_WRITE   0x00000019
-#define VMEXIT_CR10_WRITE  0x0000001a
-#define VMEXIT_CR11_WRITE  0x0000001b
-#define VMEXIT_CR12_WRITE  0x0000001c
-#define VMEXIT_CR13_WRITE  0x0000001d
-#define VMEXIT_CR14_WRITE  0x0000001e
-#define VMEXIT_CR15_WRITE  0x0000001f
-
-#define VMEXIT_DR_READ_MASK 0xffffffd0
-#define VMEXIT_DR0_READ   0x00000020
-#define VMEXIT_DR1_READ   0x00000021
-#define VMEXIT_DR2_READ   0x00000022
-#define VMEXIT_DR3_READ   0x00000023
-#define VMEXIT_DR4_READ   0x00000024
-#define VMEXIT_DR5_READ   0x00000025
-#define VMEXIT_DR6_READ   0x00000026
-#define VMEXIT_DR7_READ   0x00000027
-#define VMEXIT_DR8_READ   0x00000028
-#define VMEXIT_DR9_READ   0x00000029
-#define VMEXIT_DR10_READ  0x0000002a
-#define VMEXIT_DR11_READ  0x0000002b
-#define VMEXIT_DR12_READ  0x0000002c
-#define VMEXIT_DR13_READ  0x0000002d
-#define VMEXIT_DR14_READ  0x0000002e
-#define VMEXIT_DR15_READ  0x0000002f
-
-#define VMEXIT_DR_WRITE_MASK     0xffffffc0
-#define VMEXIT_DR0_WRITE   0x0000003f
-#define VMEXIT_DR1_WRITE   0x00000031
-#define VMEXIT_DR2_WRITE   0x00000032
-#define VMEXIT_DR3_WRITE   0x00000033
-#define VMEXIT_DR4_WRITE   0x00000034
-#define VMEXIT_DR5_WRITE   0x00000035
-#define VMEXIT_DR6_WRITE   0x00000036
-#define VMEXIT_DR7_WRITE   0x00000037
-#define VMEXIT_DR8_WRITE   0x00000038
-#define VMEXIT_DR9_WRITE   0x00000039
-#define VMEXIT_DR10_WRITE  0x0000003a
-#define VMEXIT_DR11_WRITE  0x0000003b
-#define VMEXIT_DR12_WRITE  0x0000003c
-#define VMEXIT_DR13_WRITE  0x0000003d
-#define VMEXIT_DR14_WRITE  0x0000003e
-#define VMEXIT_DR15_WRITE  0x0000003f
-
-#define VMEXIT_EXCP_MASK   0xffffffa0
-#define VMEXIT_EXCP0       0x00000040
-#define VMEXIT_EXCP1       0x00000041
-#define VMEXIT_EXCP2       0x00000042
-#define VMEXIT_EXCP3       0x00000043
-#define VMEXIT_EXCP4       0x00000044
-#define VMEXIT_EXCP5       0x00000045
-#define VMEXIT_EXCP6       0x00000046
-#define VMEXIT_EXCP7       0x00000047
-#define VMEXIT_EXCP8       0x00000048
-#define VMEXIT_EXCP9       0x00000049
-#define VMEXIT_EXCP10      0x0000004a
-#define VMEXIT_EXCP11      0x0000004b
-#define VMEXIT_EXCP12      0x0000004c
-#define VMEXIT_EXCP13      0x0000004d
-#define VMEXIT_EXCP14      0x0000004e
-#define VMEXIT_EXCP15      0x0000004f
-#define VMEXIT_EXCP16      0x00000050
-#define VMEXIT_EXCP17      0x00000051
-#define VMEXIT_EXCP18      0x00000052
-#define VMEXIT_EXCP19      0x00000053
-#define VMEXIT_EXCP20      0x00000054
-#define VMEXIT_EXCP21      0x00000055
-#define VMEXIT_EXCP22      0x00000056
-#define VMEXIT_EXCP23      0x00000057
-#define VMEXIT_EXCP24      0x00000058
-#define VMEXIT_EXCP25      0x00000059
-#define VMEXIT_EXCP26      0x0000005a
-#define VMEXIT_EXCP27      0x0000005b
-#define VMEXIT_EXCP28      0x0000005c
-#define VMEXIT_EXCP29      0x0000005d
-#define VMEXIT_EXCP30      0x0000005e
-#define VMEXIT_EXCP31      0x0000005f
-
-
-#define VMEXIT_INTR                 0x00000060
-#define VMEXIT_NMI                  0x00000061
-#define VMEXIT_SMI                  0x00000062
-#define VMEXIT_INIT                 0x00000063
-#define VMEXIT_VINITR               0x00000064
-#define VMEXIT_CR0_SEL_WRITE        0x00000065
-#define VMEXIT_IDTR_READ            0x00000066
-#define VMEXIT_GDTR_READ            0x00000067
-#define VMEXIT_LDTR_READ            0x00000068
-#define VMEXIT_TR_READ              0x00000069
-#define VMEXIT_IDTR_WRITE           0x0000006a
-#define VMEXIT_GDTR_WRITE           0x0000006b
-#define VMEXIT_LDTR_WRITE           0x0000006c
-#define VMEXIT_TR_WRITE             0x0000006d
-#define VMEXIT_RDTSC                0x0000006e
-#define VMEXIT_RDPMC                0x0000006f
-#define VMEXIT_PUSHF                0x00000070
-#define VMEXIT_POPF                 0x00000071
-#define VMEXIT_CPUID                0x00000072
-#define VMEXIT_RSM                  0x00000073
-#define VMEXIT_IRET                 0x00000074
-#define VMEXIT_SWINT                0x00000075
-#define VMEXIT_INVD                 0x00000076
-#define VMEXIT_PAUSE                0x00000077
-#define VMEXIT_HLT                  0x00000078
-#define VMEXIT_INVLPG               0x00000079
-#define VMEXIT_INVLPGA              0x0000007a
-#define VMEXIT_IOIO                 0x0000007b
-#define VMEXIT_MSR                  0x0000007c
-#define VMEXIT_TASK_SWITCH          0x0000007d
-#define VMEXIT_FERR_FREEZE          0x0000007e
-#define VMEXIT_SHUTDOWN             0x0000007f
-#define VMEXIT_VMRUN                0x00000080
-#define VMEXIT_VMMCALL              0x00000081
-#define VMEXIT_VMLOAD               0x00000082
-#define VMEXIT_VMSAVE               0x00000083
-#define VMEXIT_STGI                 0x00000084
-#define VMEXIT_CLGI                 0x00000085
-#define VMEXIT_SKINIT               0x00000086
-#define VMEXIT_RDTSCP               0x00000087
-#define VMEXIT_ICEBP                0x00000088
-#define VMEXIT_WBINVD               0x00000089
-#define VMEXIT_MONITOR              0x0000008a
-#define VMEXIT_MWAIT                0x0000008b
-#define VMEXIT_MWAIT_CONDITIONAL    0x0000008c
-
-#define VMEXIT_INVALID_VMCB         -1
-
-/******************************************/
+
+#define SVM_HANDLER_SUCCESS   0x0
+#define SVM_HANDLER_ERROR     0x1
+#define SVM_HANDLER_HALT      0x2
 
 
 
@@ -218,11 +62,12 @@ int is_svm_capable();
 
 vmcb_t * Allocate_VMCB();
 void Init_VMCB(vmcb_t * vmcb, guest_info_t vm_info);
+void Init_VMCB_pe(vmcb_t * vmcb, guest_info_t vm_info);
 
 int init_svm_guest(struct guest_info *info);
 int start_svm_guest(struct guest_info * info);
 
-int handle_svm_exit(struct VMM_GPRs gprs);
+
 
 
 #endif
diff --git a/palacios/include/geekos/svm_handler.h b/palacios/include/geekos/svm_handler.h
new file mode 100644 (file)
index 0000000..0afbe64
--- /dev/null
@@ -0,0 +1,193 @@
+#ifndef __SVM_HANDLER_H
+#define __SVM_HANDLER_H
+#include <geekos/svm.h>
+#include <geekos/vmcb.h>
+#include <geekos/vmm.h>
+
+
+
+
+
+/******************************************/
+/* SVM Intercept Exit Codes               */
+/* AMD Arch Vol 3, Appendix C, pg 477-478 */
+/******************************************/
+#define VMEXIT_CR_READ_MASK 0xfffffff0
+#define VMEXIT_CR0_READ   0x00000000
+#define VMEXIT_CR1_READ   0x00000001
+#define VMEXIT_CR2_READ   0x00000002
+#define VMEXIT_CR3_READ   0x00000003
+#define VMEXIT_CR4_READ   0x00000004
+#define VMEXIT_CR5_READ   0x00000005
+#define VMEXIT_CR6_READ   0x00000006
+#define VMEXIT_CR7_READ   0x00000007
+#define VMEXIT_CR8_READ   0x00000008
+#define VMEXIT_CR9_READ   0x00000009
+#define VMEXIT_CR10_READ  0x0000000a
+#define VMEXIT_CR11_READ  0x0000000b
+#define VMEXIT_CR12_READ  0x0000000c
+#define VMEXIT_CR13_READ  0x0000000d
+#define VMEXIT_CR14_READ  0x0000000e
+#define VMEXIT_CR15_READ  0x0000000f
+
+#define VMEXIT_CR_WRITE_MASK 0xffffffe0
+#define VMEXIT_CR0_WRITE   0x00000010
+#define VMEXIT_CR1_WRITE   0x00000011
+#define VMEXIT_CR2_WRITE   0x00000012
+#define VMEXIT_CR3_WRITE   0x00000013
+#define VMEXIT_CR4_WRITE   0x00000014
+#define VMEXIT_CR5_WRITE   0x00000015
+#define VMEXIT_CR6_WRITE   0x00000016
+#define VMEXIT_CR7_WRITE   0x00000017
+#define VMEXIT_CR8_WRITE   0x00000018
+#define VMEXIT_CR9_WRITE   0x00000019
+#define VMEXIT_CR10_WRITE  0x0000001a
+#define VMEXIT_CR11_WRITE  0x0000001b
+#define VMEXIT_CR12_WRITE  0x0000001c
+#define VMEXIT_CR13_WRITE  0x0000001d
+#define VMEXIT_CR14_WRITE  0x0000001e
+#define VMEXIT_CR15_WRITE  0x0000001f
+
+#define VMEXIT_DR_READ_MASK 0xffffffd0
+#define VMEXIT_DR0_READ   0x00000020
+#define VMEXIT_DR1_READ   0x00000021
+#define VMEXIT_DR2_READ   0x00000022
+#define VMEXIT_DR3_READ   0x00000023
+#define VMEXIT_DR4_READ   0x00000024
+#define VMEXIT_DR5_READ   0x00000025
+#define VMEXIT_DR6_READ   0x00000026
+#define VMEXIT_DR7_READ   0x00000027
+#define VMEXIT_DR8_READ   0x00000028
+#define VMEXIT_DR9_READ   0x00000029
+#define VMEXIT_DR10_READ  0x0000002a
+#define VMEXIT_DR11_READ  0x0000002b
+#define VMEXIT_DR12_READ  0x0000002c
+#define VMEXIT_DR13_READ  0x0000002d
+#define VMEXIT_DR14_READ  0x0000002e
+#define VMEXIT_DR15_READ  0x0000002f
+
+#define VMEXIT_DR_WRITE_MASK     0xffffffc0
+#define VMEXIT_DR0_WRITE   0x0000003f
+#define VMEXIT_DR1_WRITE   0x00000031
+#define VMEXIT_DR2_WRITE   0x00000032
+#define VMEXIT_DR3_WRITE   0x00000033
+#define VMEXIT_DR4_WRITE   0x00000034
+#define VMEXIT_DR5_WRITE   0x00000035
+#define VMEXIT_DR6_WRITE   0x00000036
+#define VMEXIT_DR7_WRITE   0x00000037
+#define VMEXIT_DR8_WRITE   0x00000038
+#define VMEXIT_DR9_WRITE   0x00000039
+#define VMEXIT_DR10_WRITE  0x0000003a
+#define VMEXIT_DR11_WRITE  0x0000003b
+#define VMEXIT_DR12_WRITE  0x0000003c
+#define VMEXIT_DR13_WRITE  0x0000003d
+#define VMEXIT_DR14_WRITE  0x0000003e
+#define VMEXIT_DR15_WRITE  0x0000003f
+
+#define VMEXIT_EXCP_MASK   0xffffffa0
+#define VMEXIT_EXCP0       0x00000040
+#define VMEXIT_EXCP1       0x00000041
+#define VMEXIT_EXCP2       0x00000042
+#define VMEXIT_EXCP3       0x00000043
+#define VMEXIT_EXCP4       0x00000044
+#define VMEXIT_EXCP5       0x00000045
+#define VMEXIT_EXCP6       0x00000046
+#define VMEXIT_EXCP7       0x00000047
+#define VMEXIT_EXCP8       0x00000048
+#define VMEXIT_EXCP9       0x00000049
+#define VMEXIT_EXCP10      0x0000004a
+#define VMEXIT_EXCP11      0x0000004b
+#define VMEXIT_EXCP12      0x0000004c
+#define VMEXIT_EXCP13      0x0000004d
+#define VMEXIT_EXCP14      0x0000004e
+#define VMEXIT_EXCP15      0x0000004f
+#define VMEXIT_EXCP16      0x00000050
+#define VMEXIT_EXCP17      0x00000051
+#define VMEXIT_EXCP18      0x00000052
+#define VMEXIT_EXCP19      0x00000053
+#define VMEXIT_EXCP20      0x00000054
+#define VMEXIT_EXCP21      0x00000055
+#define VMEXIT_EXCP22      0x00000056
+#define VMEXIT_EXCP23      0x00000057
+#define VMEXIT_EXCP24      0x00000058
+#define VMEXIT_EXCP25      0x00000059
+#define VMEXIT_EXCP26      0x0000005a
+#define VMEXIT_EXCP27      0x0000005b
+#define VMEXIT_EXCP28      0x0000005c
+#define VMEXIT_EXCP29      0x0000005d
+#define VMEXIT_EXCP30      0x0000005e
+#define VMEXIT_EXCP31      0x0000005f
+
+
+#define VMEXIT_INTR                 0x00000060
+#define VMEXIT_NMI                  0x00000061
+#define VMEXIT_SMI                  0x00000062
+#define VMEXIT_INIT                 0x00000063
+#define VMEXIT_VINITR               0x00000064
+#define VMEXIT_CR0_SEL_WRITE        0x00000065
+#define VMEXIT_IDTR_READ            0x00000066
+#define VMEXIT_GDTR_READ            0x00000067
+#define VMEXIT_LDTR_READ            0x00000068
+#define VMEXIT_TR_READ              0x00000069
+#define VMEXIT_IDTR_WRITE           0x0000006a
+#define VMEXIT_GDTR_WRITE           0x0000006b
+#define VMEXIT_LDTR_WRITE           0x0000006c
+#define VMEXIT_TR_WRITE             0x0000006d
+#define VMEXIT_RDTSC                0x0000006e
+#define VMEXIT_RDPMC                0x0000006f
+#define VMEXIT_PUSHF                0x00000070
+#define VMEXIT_POPF                 0x00000071
+#define VMEXIT_CPUID                0x00000072
+#define VMEXIT_RSM                  0x00000073
+#define VMEXIT_IRET                 0x00000074
+#define VMEXIT_SWINT                0x00000075
+#define VMEXIT_INVD                 0x00000076
+#define VMEXIT_PAUSE                0x00000077
+#define VMEXIT_HLT                  0x00000078
+#define VMEXIT_INVLPG               0x00000079
+#define VMEXIT_INVLPGA              0x0000007a
+#define VMEXIT_IOIO                 0x0000007b
+#define VMEXIT_MSR                  0x0000007c
+#define VMEXIT_TASK_SWITCH          0x0000007d
+#define VMEXIT_FERR_FREEZE          0x0000007e
+#define VMEXIT_SHUTDOWN             0x0000007f
+#define VMEXIT_VMRUN                0x00000080
+#define VMEXIT_VMMCALL              0x00000081
+#define VMEXIT_VMLOAD               0x00000082
+#define VMEXIT_VMSAVE               0x00000083
+#define VMEXIT_STGI                 0x00000084
+#define VMEXIT_CLGI                 0x00000085
+#define VMEXIT_SKINIT               0x00000086
+#define VMEXIT_RDTSCP               0x00000087
+#define VMEXIT_ICEBP                0x00000088
+#define VMEXIT_WBINVD               0x00000089
+#define VMEXIT_MONITOR              0x0000008a
+#define VMEXIT_MWAIT                0x0000008b
+#define VMEXIT_MWAIT_CONDITIONAL    0x0000008c
+
+#define VMEXIT_INVALID_VMCB         -1
+
+/******************************************/
+
+
+struct svm_io_info {
+  uint_t type        : 1       PACKED;  // (0=out, 1=in)
+  uint_t rsvd        : 1       PACKED;  // Must be Zero
+  uint_t str         : 1       PACKED;  // string based io
+  uint_t rep         : 1       PACKED;  // repeated io
+  uint_t sz8         : 1       PACKED;  // 8 bit op size
+  uint_t sz16        : 1       PACKED;  // 16 bit op size
+  uint_t sz32        : 1       PACKED;  // 32 bit op size
+  uint_t A16         : 1       PACKED;  // 16 bit addr
+  uint_t A32         : 1       PACKED;  // 32 bit addr
+  uint_t A64         : 1       PACKED;  // 64 bit addr
+  uint_t rsvd2       : 6       PACKED;  // Should be Zero
+  ushort_t port                PACKED;  // port number
+};
+
+
+int handle_svm_io(guest_info_t * info);
+
+int handle_svm_exit(guest_info_t * info);
+
+#endif
index 66ea118..9bab863 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * x86 TSS data structure and routines
  * Copyright (c) 2001,2004 David H. Hovemeyer <daveho@cs.umd.edu>
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
@@ -86,4 +86,16 @@ struct TSS {
 void Init_TSS(void);
 void Set_Kernel_Stack_Pointer(ulong_t esp0);
 
+
+
+/* JRL THIS FUCKING SUCKS */
+
+uint_t GetTR_Base();
+uint_t GetTR_Limit();
+ushort_t GetTR_Selector();
+
+
+
+/* ** */
+
 #endif  /* GEEKOS_TSS_H */
index 15b6cca..6a6d86b 100644 (file)
@@ -1,22 +1,39 @@
 #ifndef __VM_GUEST_H
 #define __VM_GUEST_H
 
-#include <geekos/svm.h>
-#include <geekos/vmx.h>
+#include <geekos/vmm_mem.h>
+#include <geekos/ktypes.h>
+#include <geekos/vmm_io.h>
 
+struct guest_gprs {
+  ullong_t rbx;
+  ullong_t rcx;
+  ullong_t rdx;
+  ullong_t rsi;
+  ullong_t rdi;
+  ullong_t rbp;
 
+};
 
 
 
-typedef struct guest_state {
-  reg_ex_t rip;
-  reg_ex_t rsp;
 
-  
-  void * arch_data;
-} guest_state_t;
+typedef struct guest_info {
+  ullong_t rip;
+  ullong_t rsp;
 
+  vmm_mem_list_t mem_list;
+  vmm_mem_layout_t mem_layout;
 
+  vmm_io_map_t io_map;
+  // device_map
+
+
+  struct guest_gprs vm_regs;
+
+  void * page_tables;
+  void * vmm_data;
+} guest_info_t;
 
 
 
index 894c12e..8bce011 100644 (file)
@@ -294,7 +294,7 @@ struct vmcb_selector {
   ushort_t selector                   PACKED;
 
   /* These attributes are basically a direct map of the attribute fields of a segment desc.
-   * The segment limit in the middle is removed and the fields are pused together
+   * The segment limit in the middle is removed and the fields are fused together
    * There IS empty space at the end... See AMD Arch vol3, sect. 4.7.1,  pg 78
    */
   union {
index 181155f..3b80c46 100644 (file)
@@ -8,6 +8,7 @@
 #include <geekos/vmm_mem.h>
 #include <geekos/vmm_paging.h>
 
+#include <geekos/vm_guest.h>
 
 /* utility definitions */
 #define PrintDebug(fmt, args...)                       \
 
 
 
-typedef struct guest_info {
-  ullong_t rip;
-  ullong_t rsp;
-
-  vmm_mem_list_t mem_list;
-  vmm_mem_layout_t mem_layout;
-  // device_map
-
-  pml4e64_t * page_tables;
-  void * vmm_data;
-} guest_info_t;
 
 
 
diff --git a/palacios/include/geekos/vmm_debug.h b/palacios/include/geekos/vmm_debug.h
new file mode 100644 (file)
index 0000000..db37060
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __VMM_DEBUG_H
+#define __VMM_DEBUG_H
+
+
+
+
+
+void PrintDebugHex(unsigned char x);
+void PrintDebugMemDump(unsigned char *start, int n);
+
+
+
+
+#endif
diff --git a/palacios/include/geekos/vmm_io.h b/palacios/include/geekos/vmm_io.h
new file mode 100644 (file)
index 0000000..fde2ea6
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef __VMM_IO_H
+#define __VMM_IO_H
+
+#include <geekos/ktypes.h>
+
+#include <geekos/vmm_util.h>
+
+// FOREACH_IO_HOOK(vmm_io_map_t io_map, vmm_io_hook_t * io_hook)
+#define FOREACH_IO_HOOK(io_map, io_hook) for (io_hook = io_map.head; io_hook != NULL; io_hook = io_hook->next)
+
+
+typedef struct vmm_io_hook {
+  ushort_t port;
+
+  // Reads data into the IO port (IN, INS)
+  int (*read)(ushort_t port, void * dst, uint_t length);
+
+  // Writes data from the IO port (OUT, OUTS)
+  int (*write)(ushort_t port, void * src, uint_t length);
+
+  struct vmm_io_hook * next;
+  struct vmm_io_hook * prev;
+
+} vmm_io_hook_t;
+
+
+typedef struct vmm_io_map {
+  uint_t num_ports;
+
+
+  vmm_io_hook_t * head;
+
+} vmm_io_map_t;
+
+
+void add_io_hook(vmm_io_map_t * io_map, vmm_io_hook_t * io_hook);
+
+
+
+
+/* External API */
+void hook_io_port(vmm_io_map_t * io_map, uint_t port, 
+                 int (*read)(ushort_t port, void * dst, uint_t length),
+                 int (*write)(ushort_t port, void * src, uint_t length));
+
+void init_vmm_io_map(vmm_io_map_t * io_map);
+
+void PrintDebugIOMap(vmm_io_map_t * io_map);
+
+
+#endif
index d206939..707e34a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Initialize kernel GDT.
  * Copyright (c) 2001,2004 David H. Hovemeyer <daveho@cs.umd.edu>
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
@@ -14,6 +14,7 @@
 #include <geekos/gdt.h>
 #include <libc/string.h>
 
+#include <geekos/debug.h>
 
 /*
  * This is defined in lowlevel.asm.
@@ -45,11 +46,11 @@ static int s_numAllocated = 0;
 void DumpGDT()
 {
   int i;
-  Print("GDT Contents:\n");
+  PrintBoth("GDT Contents:\n");
 
   for (i=0;i<NUM_GDT_ENTRIES;i++) { 
     if (s_GDT[i].present) { 
-      Print("%d: base=%u, limit=%u, sizeLow=%u,  baseLow=%u, type=%u, system=%u, dpl=%u, preent=%u, sizeHigh=%u, avail=%u, reserved=%u, dbBit=%u, granularity=%u, baseHigh=%u\n", 
+      PrintBoth("%d: base=%u, limit=%u, sizeLow=%u,  baseLow=%u, type=%u, system=%u, dpl=%u, preent=%u, sizeHigh=%u, avail=%u, reserved=%u, dbBit=%u, granularity=%u, baseHigh=%u\n", 
            i,
            (s_GDT[i].baseHigh<<24) + s_GDT[i].baseLow,
            (s_GDT[i].sizeHigh<<16) + s_GDT[i].sizeLow,
@@ -66,7 +67,7 @@ void DumpGDT()
            s_GDT[i].granularity,
            s_GDT[i].baseHigh  );
     } else {
-      Print("%d: Not Present\n",i);
+      PrintBoth("%d: Not Present\n",i);
     }
   }
 }
index 1799cfe..84431cf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * GeekOS interrupt handling data structures and functions
  * Copyright (c) 2001,2003 David H. Hovemeyer <daveho@cs.umd.edu>
- * $Revision: 1.4 $
+ * $Revision: 1.5 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
@@ -397,7 +397,7 @@ void Dump_Interrupt_State(struct Interrupt_State* state)
 {
     uint_t errorCode = state->errorCode;
 
-   Print("eax=%08x ebx=%08x ecx=%08x edx=%08x\n"
+   PrintBoth("eax=%08x ebx=%08x ecx=%08x edx=%08x\n"
           "esi=%08x edi=%08x ebp=%08x\n"
           "eip=%08x cs=%08x eflags=%08x\n"
           "Interrupt number=%d (%s), error code=%d\n"
index 87bea69..18071b9 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (c) 2001,2003,2004 David H. Hovemeyer <daveho@cs.umd.edu>
  * Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
  * Copyright (c) 2004, Iulian Neamtiu <neamtiu@cs.umd.edu>
- * $Revision: 1.18 $
+ * $Revision: 1.19 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
 #include <geekos/vmm_stubs.h>
 
 
-
-
-extern void Get_MSR(ulong_t msr, unsigned int *val1, unsigned int *val2);
-extern void Set_MSR(ulong_t msr, ulong_t val1, ulong_t val2);
-extern uint_t Get_EIP();
-extern uint_t Get_ESP();
-extern uint_t Get_EBP();
-
-
-int foo=42;
-
 #define SPEAKER_PORT 0x61
 
 
@@ -97,10 +86,34 @@ inline uchar_t MyIn_Byte(ushort_t port)
 }
 
 
-extern void MyBuzzVM();
 
-#define MYBUZZVM_START MyBuzzVM
-#define MYBUZZVM_LEN   0x3d
+int IO_Read(ushort_t port, void * dst, uint_t length) {
+  uchar_t * iter = dst;
+  uint_t i;
+
+  for (i = 0; i < length; i++) {
+    *iter = MyIn_Byte(port);    
+    iter++;
+  }
+  
+  return 0;
+}
+
+
+
+int IO_Write(ushort_t port, void * src, uint_t length) {
+  uchar_t * iter = src;
+  uint_t i;
+
+
+  for (i = 0; i < length; i++) {
+    MyOut_Byte(port, *iter);    
+    iter++;
+  }
+
+  return 0;
+}
+
 
 void BuzzVM()
 {
@@ -109,7 +122,7 @@ void BuzzVM()
   unsigned char init;
   
     
-  SerialPrint("Starting To Buzz\n");
+  PrintBoth("Starting To Buzz\n");
 
   init=MyIn_Byte(SPEAKER_PORT);
 
@@ -125,15 +138,7 @@ void BuzzVM()
   }
 }
 
-extern void RunVM();
-
-int vmRunning = 0;
 
-void RunVM() {
-  vmRunning = 1;
-
-  while(1);
-}
 
 
 
@@ -221,8 +226,6 @@ void Main(struct Boot_Info* bootInfo)
 {
   struct Kernel_Thread * key_thread;
   struct Kernel_Thread * spkr_thread;
-  // struct Kernel_Thread * vm_thread;
-  // struct VMDescriptor    vm;
 
   ulong_t doIBuzz = 0;
 
@@ -248,20 +251,18 @@ void Main(struct Boot_Info* bootInfo)
 
 
   
-#if 0
-  SerialPrint("Dumping VM kernel Code (first 512 bytes @ 0x%x)\n",VM_KERNEL_START);
-  SerialMemDump((unsigned char *)VM_KERNEL_START, 512);
+#if 1
+  SerialPrint("Dumping VM kernel Code (first 128 bytes @ 0x%x)\n", 0x100000);
+  SerialMemDump((unsigned char *)0x100000, 128);
   /*
     SerialPrint("Dumping kernel Code (first 512 bytes @ 0x%x)\n",KERNEL_START);
     SerialMemDump((unsigned char *)VM_KERNEL_START, 512);
   */
 #endif
 
-#if 0
-  SerialPrint("Dumping GUEST KERNEL CODE (first 512*2 bytes @ 0x100000)\n");
-  SerialMemDump((unsigned char *)0x100000, 512*2);
-#endif
 
+
+  SerialPrintLevel(1000,"Launching Noisemaker and keyboard listener threads\n");
   key_thread = Start_Kernel_Thread(Keyboard_Listener, (ulong_t)&doIBuzz, PRIORITY_NORMAL, false);
   spkr_thread = Start_Kernel_Thread(Buzzer, (ulong_t)&doIBuzz, PRIORITY_NORMAL, false);
 
@@ -286,71 +287,58 @@ void Main(struct Boot_Info* bootInfo)
     os_hooks.free = &VMM_Free;
 
 
+    //   DumpGDT();
     Init_VMM(&os_hooks, &vmm_ops);
   
 
     init_mem_layout(&(vm_info.mem_layout));
     init_mem_list(&(vm_info.mem_list));
+    init_vmm_io_map(&(vm_info.io_map));
 
-
+    
     add_mem_list_pages(&(vm_info.mem_list), vm_range_start, (vm_range_end - vm_range_start) / PAGE_SIZE);
     //    add_unmapped_mem_range(&(vm_info.mem_layout), 0, 256);
     //add_shared_mem_range(&(vm_info.mem_layout), guest_kernel_start, (guest_kernel_end - guest_kernel_start) / PAGE_SIZE, guest_kernel_start);
     //add_guest_mem_range(&(vm_info.mem_layout), guest_kernel_end, 20);
+    
+    if (0) {
+      
+      //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x800000, 0x10000);    
+      add_shared_mem_range(&(vm_info.mem_layout), 0, 0x1000000, 0);
+      
+      rip = (ulong_t)(void*)&BuzzVM;
+      //  rip -= 0x10000;
+      //    rip = (addr_t)(void*)&exit_test;
+      //  rip -= 0x2000;
+      vm_info.rip = rip;
+      rsp = (addr_t)Alloc_Page();
+      
+      vm_info.rsp = (rsp +4092 );// - 0x2000;
+      
+            
+    } else {
+      add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x1000, 0x100000);
+
+      
+
+      hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write);
+
+      vm_info.rip = 0x0;
+      vm_info.rsp = 0x0;
+    }
 
-    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x1000000, 0);
-
-    rip = (ulong_t)(void*)&BuzzVM;
-    vm_info.rip = rip;
-    rsp = (ulong_t)Alloc_Page();
-    vm_info.rsp = rsp;
-
-
-    SerialPrint("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", rip, rsp);
+    PrintBoth("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", (uint_t)vm_info.rip,(uint_t)vm_info.rsp);
     (vmm_ops).init_guest(&vm_info);
-    SerialPrint("Starting Guest\n");
+    PrintBoth("Starting Guest\n");
     (vmm_ops).start_guest(&vm_info);
-    
   }
 
 
-  SerialPrintLevel(1000,"Launching Noisemaker and keyboard listener threads\n");
-  
-
-
-
-
-
-
-  /*
-  // jump into vmxassist
-  vm.entry_ip=(uint_t)0x00107fd0;
-  vm.exit_eip=0;
-  // Put the stack at 512K
-  vm.guest_esp=(uint_t)4096 + 8192 - 4;
-  *(unsigned int *)(vm.guest_esp) = 1024 * 1024;
-  vm.guest_esp -= 4;
-  *(unsigned int *)(vm.guest_esp) = 8;
-  vm.guest_esp -= 4;
-  *(unsigned int *)(vm.guest_esp) = vm.guest_esp + 4;;
-  vm.guest_esp -= 4;
-  *(unsigned int *)(vm.guest_esp) = vm.entry_ip;
-  //  vm.guest_esp -= 4;
-
-  SerialMemDump((unsigned char *)vm.entry_ip, 512);
-  */
-  // vm_thread = Start_Kernel_Thread(VM_Thread, (ulong_t)&vm,PRIORITY_NORMAL,false);
-
   
-  SerialPrintLevel(1000,"Next: setup GDT\n");
-
 
 
   TODO("Write a Virtual Machine Monitor");
   
-  
-  /* Now this thread is done. */
+
   Exit(0);
 }
index 6d9d487..ed78fe1 100644 (file)
@@ -4,7 +4,14 @@
 #include <geekos/vmcb.h>
 #include <geekos/vmm_mem.h>
 #include <geekos/vmm_paging.h>
+#include <geekos/svm_handler.h>
 
+#include <geekos/vmm_debug.h>
+
+
+/* TEMPORARY BECAUSE SVM IS WEIRD */
+#include <geekos/tss.h>
+/* ** */
 
 extern struct vmm_os_hooks * os_hooks;
 
@@ -13,11 +20,14 @@ extern uint_t cpuid_edx(uint_t op);
 extern void Get_MSR(uint_t MSR, uint_t * high_byte, uint_t * low_byte); 
 extern void Set_MSR(uint_t MSR, uint_t high_byte, uint_t low_byte);
 extern uint_t launch_svm(vmcb_t * vmcb_addr);
+extern void safe_svm_launch(vmcb_t * vmcb_addr, struct guest_gprs * gprs);
+
 extern uint_t Get_CR3();
 
 extern void GetGDTR(void * gdt);
 extern void GetIDTR(void * idt);
 
+extern void DisableInts();
 
 /* Checks machine SVM capability */
 /* Implemented from: AMD Arch Manual 3, sect 15.4 */ 
@@ -69,7 +79,7 @@ void Init_SVM(struct vmm_ctrl_ops * vmm_ops) {
 
 
   // Setup the host state save area
-  host_state = os_hooks->allocate_pages(1);
+  host_state = os_hooks->allocate_pages(4);
   
   msr.e_reg.high = 0;
   msr.e_reg.low = (uint_t)host_state;
@@ -98,16 +108,23 @@ int init_svm_guest(struct guest_info *info) {
   PrintDebug("Generating Guest nested page tables\n");
   print_mem_list(&(info->mem_list));
   print_mem_layout(&(info->mem_layout));
-  info->page_tables = generate_guest_page_tables_64(&(info->mem_layout), &(info->mem_list));
-  //PrintDebugPageTables(info->page_tables);
+  info->page_tables = NULL;
+  //info->page_tables = generate_guest_page_tables_64(&(info->mem_layout), &(info->mem_list));
+  info->page_tables = generate_guest_page_tables(&(info->mem_layout), &(info->mem_list));
+  PrintDebugPageTables(info->page_tables);
 
   
 
   PrintDebug("Initializing VMCB (addr=%x)\n", info->vmm_data);
   Init_VMCB((vmcb_t*)(info->vmm_data), *info);
-
-
   
+  
+  info->vm_regs.rbx = 0;
+  info->vm_regs.rcx = 0;
+  info->vm_regs.rdx = 0;
+  info->vm_regs.rsi = 0;
+  info->vm_regs.rdi = 0;
+  info->vm_regs.rbp = 0;
 
   return 0;
 }
@@ -115,53 +132,145 @@ int init_svm_guest(struct guest_info *info) {
 
 // can we start a kernel thread here...
 int start_svm_guest(struct guest_info *info) {
-  vmcb_ctrl_t * guest_ctrl = 0;
 
-  ulong_t exit_code = 0;
+
 
   PrintDebug("Launching SVM VM (vmcb=%x)\n", info->vmm_data);
-  // PrintDebugVMCB((vmcb_t*)(info->vmm_data));
+  //PrintDebugVMCB((vmcb_t*)(info->vmm_data));
 
+  while (1) {
 
-  launch_svm((vmcb_t*)(info->vmm_data));
+    safe_svm_launch((vmcb_t*)(info->vmm_data), &(info->vm_regs));
+    //launch_svm((vmcb_t*)(info->vmm_data));
+    PrintDebug("SVM Returned\n");
 
-  guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
+    if (handle_svm_exit(info) != 0) {
+      break;
+    }
+  }
+  return 0;
+}
 
 
-  PrintDebug("SVM Returned: (Exit Code=%x) (VMCB=%x)\n",&(guest_ctrl->exit_code), info->vmm_data); 
 
+vmcb_t * Allocate_VMCB() {
+  vmcb_t * vmcb_page = (vmcb_t*)os_hooks->allocate_pages(1);
 
-  exit_code = guest_ctrl->exit_code;
 
-  PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); 
+  memset(vmcb_page, 0, 4096);
 
-  return 0;
+  return vmcb_page;
 }
 
 
 
-/** 
- *  We handle the svm exits here
- *  This function should probably be moved to another file to keep things managable....
- */
-int handle_svm_exit(struct VMM_GPRs guest_gprs) {
+void Init_VMCB(vmcb_t * vmcb, guest_info_t vm_info) {
+  vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
+  vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
+  uint_t i;
 
-  return 0;
-}
 
+  guest_state->rsp = vm_info.rsp;
+  guest_state->rip = vm_info.rip;
 
-vmcb_t * Allocate_VMCB() {
-  vmcb_t * vmcb_page = (vmcb_t*)os_hooks->allocate_pages(1);
 
 
-  memset(vmcb_page, 0, 4096);
+  ctrl_area->cr_writes.crs.cr0 = 1;
+
+  guest_state->efer |= EFER_MSR_svm_enable;
+  guest_state->rflags = 0x00000002; // The reserved bit is always 1
+  ctrl_area->svm_instrs.instrs.VMRUN = 1;
+  // guest_state->cr0 = 0x00000001;    // PE 
+  ctrl_area->guest_ASID = 1;
 
-  return vmcb_page;
-}
 
+  ctrl_area->exceptions.ex_names.de = 1;
+  ctrl_area->exceptions.ex_names.df = 1;
+  ctrl_area->exceptions.ex_names.pf = 1;
+  ctrl_area->exceptions.ex_names.ts = 1;
+  ctrl_area->exceptions.ex_names.ss = 1;
+  ctrl_area->exceptions.ex_names.ac = 1;
+  ctrl_area->exceptions.ex_names.mc = 1;
+  ctrl_area->exceptions.ex_names.gp = 1;
+  ctrl_area->exceptions.ex_names.ud = 1;
+  ctrl_area->exceptions.ex_names.np = 1;
+  ctrl_area->exceptions.ex_names.of = 1;
+  ctrl_area->exceptions.ex_names.nmi = 1;
 
+  guest_state->cs.selector = 0x0000;
+  guest_state->cs.limit=~0u;
+  guest_state->cs.base = guest_state->cs.selector<<4;
+  guest_state->cs.attrib.raw = 0xf3;
 
-void Init_VMCB(vmcb_t *vmcb, guest_info_t vm_info) {
+  
+  struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
+  for ( i = 0; segregs[i] != NULL; i++) {
+    struct vmcb_selector * seg = segregs[i];
+    
+    seg->selector = 0x0000;
+    seg->base = seg->selector << 4;
+    seg->attrib.raw = 0xf3;
+    seg->limit = ~0u;
+  }
+  
+  if (vm_info.io_map.num_ports > 0) {
+    vmm_io_hook_t * iter;
+    addr_t io_port_bitmap;
+    
+    io_port_bitmap = (addr_t)os_hooks->allocate_pages(3);
+    memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
+    
+    ctrl_area->IOPM_BASE_PA = io_port_bitmap;
+
+    //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
+
+    FOREACH_IO_HOOK(vm_info.io_map, iter) {
+      ushort_t port = iter->port;
+      uchar_t * bitmap = (uchar_t *)io_port_bitmap;
+
+      bitmap += (port / 8);
+      PrintDebug("Setting Bit in block %x\n", bitmap);
+      *bitmap |= 1 << (port % 8);
+    }
+
+    memset((uchar_t*)io_port_bitmap, 0xff, PAGE_SIZE * 2);
+    //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
+
+    ctrl_area->instrs.instrs.IOIO_PROT = 1;
+  }
+
+  ctrl_area->instrs.instrs.INTR = 1;
+
+  // also determine if CPU supports nested paging
+  if (vm_info.page_tables) {
+    //   if (0) {
+    // Flush the TLB on entries/exits
+    //ctrl_area->TLB_CONTROL = 1;
+
+    // Enable Nested Paging
+    //ctrl_area->NP_ENABLE = 1;
+
+    //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
+
+        // Set the Nested Page Table pointer
+    //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
+    ctrl_area->N_CR3 = 0;
+    guest_state->cr3 = (addr_t)(vm_info.page_tables);
+
+    //   ctrl_area->N_CR3 = Get_CR3();
+    // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
+
+    guest_state->g_pat = 0x7040600070406ULL;
+
+    //PrintDebug("Set Nested CR3: lo: 0x%x  hi: 0x%x\n", (uint_t)*(&(ctrl_area->N_CR3)), (uint_t)*((unsigned char *)&(ctrl_area->N_CR3) + 4));
+  guest_state->cr0 |= 0x80000000;
+  }
+
+
+
+}
+
+void Init_VMCB_pe(vmcb_t *vmcb, guest_info_t vm_info) {
   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
   uint_t i = 0;
@@ -175,27 +284,42 @@ void Init_VMCB(vmcb_t *vmcb, guest_info_t vm_info) {
   /* Note: That means its probably wrong */
 
   // set the segment registers to mirror ours
-  guest_state->cs.selector = 0;
+  guest_state->cs.selector = 1<<3;
   guest_state->cs.attrib.fields.type = 0xa; // Code segment+read
   guest_state->cs.attrib.fields.S = 1;
   guest_state->cs.attrib.fields.P = 1;
   guest_state->cs.attrib.fields.db = 1;
-  guest_state->cs.limit = 0xffffffff;
+  guest_state->cs.attrib.fields.G = 1;
+  guest_state->cs.limit = 0xfffff;
   guest_state->cs.base = 0;
   
   struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
   for ( i = 0; segregs[i] != NULL; i++) {
     struct vmcb_selector * seg = segregs[i];
     
-    seg->selector = 0;
+    seg->selector = 2<<3;
     seg->attrib.fields.type = 0x2; // Data Segment+read/write
     seg->attrib.fields.S = 1;
     seg->attrib.fields.P = 1;
     seg->attrib.fields.db = 1;
-    seg->limit = 0xffffffff;
+    seg->attrib.fields.G = 1;
+    seg->limit = 0xfffff;
     seg->base = 0;
   }
 
+
+  {
+    /* JRL THIS HAS TO GO */
+    
+    guest_state->tr.selector = GetTR_Selector();
+    guest_state->tr.attrib.fields.type = 0x9; 
+    guest_state->tr.attrib.fields.P = 1;
+    guest_state->tr.limit = GetTR_Limit();
+    guest_state->tr.base = GetTR_Base();// - 0x2000;
+    /* ** */
+  }
+
+
   /* ** */
 
 
@@ -206,14 +330,13 @@ void Init_VMCB(vmcb_t *vmcb, guest_info_t vm_info) {
   ctrl_area->guest_ASID = 1;
 
 
-  //  guest_state->cpl = 3;
-
-
+  //  guest_state->cpl = 0;
 
 
 
   // Setup exits
 
+  ctrl_area->cr_writes.crs.cr4 = 1;
   
   ctrl_area->exceptions.ex_names.de = 1;
   ctrl_area->exceptions.ex_names.df = 1;
@@ -230,7 +353,7 @@ void Init_VMCB(vmcb_t *vmcb, guest_info_t vm_info) {
 
   
 
-  // ctrl_area->instrs.instrs.IOIO_PROT = 1;
+  ctrl_area->instrs.instrs.IOIO_PROT = 1;
   ctrl_area->IOPM_BASE_PA = (uint_t)os_hooks->allocate_pages(3);
   
   {
@@ -241,22 +364,44 @@ void Init_VMCB(vmcb_t *vmcb, guest_info_t vm_info) {
 
   ctrl_area->instrs.instrs.INTR = 1;
 
-  /*
+  
   {
-    reg_ex_t gdt;
-    reg_ex_t idt;
+    char gdt_buf[6];
+    char idt_buf[6];
+
+    memset(gdt_buf, 0, 6);
+    memset(idt_buf, 0, 6);
+
+
+    uint_t gdt_base, idt_base;
+    ushort_t gdt_limit, idt_limit;
     
-    GetGDTR(&(gdt.r_reg));
-    PrintDebug("GDT: hi: %x, lo: %x\n", gdt.e_reg.high, gdt.e_reg.low);
+    GetGDTR(gdt_buf);
+    gdt_base = *(ulong_t*)((uchar_t*)gdt_buf + 2) & 0xffffffff;
+    gdt_limit = *(ushort_t*)(gdt_buf) & 0xffff;
+    PrintDebug("GDT: base: %x, limit: %x\n", gdt_base, gdt_limit);
+
+    GetIDTR(idt_buf);
+    idt_base = *(ulong_t*)(idt_buf + 2) & 0xffffffff;
+    idt_limit = *(ushort_t*)(idt_buf) & 0xffff;
+    PrintDebug("IDT: base: %x, limit: %x\n",idt_base, idt_limit);
+
+
+    // gdt_base -= 0x2000;
+    //idt_base -= 0x2000;
+
+    guest_state->gdtr.base = gdt_base;
+    guest_state->gdtr.limit = gdt_limit;
+    guest_state->idtr.base = idt_base;
+    guest_state->idtr.limit = idt_limit;
 
-    GetIDTR(&(idt.r_reg));
 
   }
-  */
+  
 
   // also determine if CPU supports nested paging
-    if (vm_info.page_tables) {
-  //  if (0) {
+  if (vm_info.page_tables) {
+    //   if (0) {
     // Flush the TLB on entries/exits
     ctrl_area->TLB_CONTROL = 1;
 
diff --git a/palacios/src/geekos/svm_handler.c b/palacios/src/geekos/svm_handler.c
new file mode 100644 (file)
index 0000000..ea2a7b8
--- /dev/null
@@ -0,0 +1,59 @@
+#include <geekos/svm_handler.h>
+#include <geekos/vmm.h>
+
+
+
+
+int handle_svm_exit(guest_info_t * info) {
+  vmcb_ctrl_t * guest_ctrl = 0;
+  vmcb_saved_state_t * guest_state = 0;
+  ulong_t exit_code = 0;
+  
+  guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
+  guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
+  
+  PrintDebug("SVM Returned: (Exit Code=%x) (VMCB=%x)\n",&(guest_ctrl->exit_code), info->vmm_data); 
+  PrintDebug("RIP: %x\n", guest_state->rip);
+  
+  
+  exit_code = guest_ctrl->exit_code;
+  
+  //  PrintDebugVMCB((vmcb_t*)(info->vmm_data));
+  PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); 
+  PrintDebug("io_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1));
+  PrintDebug("io_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
+
+  PrintDebug("io_info2 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info2));
+  PrintDebug("io_info2 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
+  if (exit_code == VMEXIT_IOIO) {
+    handle_svm_io(info);
+  }
+
+
+  return 0;
+}
+
+
+
+// This should package up an IO request and call vmm_handle_io
+int handle_svm_io(guest_info_t * info) {
+  vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
+  vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
+
+  PrintDebug("Ctrl Area=%x\n", ctrl_area);
+
+  //  struct svm_io_info * io_info = (struct svm_io_info *)&(ctrl_area->exit_info1);
+
+
+
+  //  PrintDebugVMCB((vmcb_t*)(info->vmm_data));
+
+  guest_state->rip = ctrl_area->exit_info2;
+
+
+  
+
+  //  PrintDebug("Exit On Port %d\n", io_info->port);
+
+  return 0;
+}
index fcb495f..7aa128f 100644 (file)
@@ -8,22 +8,59 @@
 %include "symbol.asm"
 
 
+EXPORT DisableInts
+
 EXPORT GetGDTR
 EXPORT GetIDTR
+EXPORT GetTR
 
-
+EXPORT exit_test
 
 EXTERN handle_svm_exit
 
 EXPORT launch_svm
+EXPORT safe_svm_launch
 
 
+;; These need to be kept similar with the svm return values in svm.h
+SVM_HANDLER_SUCCESS  equ 0x00
+SVM_HANDLER_ERROR equ  0x1
+SVM_HANDLER_HALT equ 0x2
+
 [BITS 32]
 
+
+; Save and restore registers needed by SVM
+%macro Save_SVM_Registers 1
+       mov     [%1], ebx
+       mov     [%1 + 8], ecx
+       mov     [%1 + 16], edx
+       mov     [%1 + 24], esi
+       mov     [%1 + 32], edi
+       mov     [%1 + 40], ebp
+%endmacro
+
+
+%macro Restore_SVM_Registers 1
+       mov     ebx, [%1]
+       mov     ecx, [%1 + 8]
+       mov     edx, [%1 + 16]
+       mov     esi, [%1 + 24]
+       mov     edi, [%1 + 32]
+       mov     ebp, [%1 + 40]
+%endmacro
+
 %macro vmrun 0
        db      00fh, 001h, 0d8h
 %endmacro
 
+%macro vmsave 0
+       db      00fh, 001h, 0dbh
+%endmacro
+
+%macro vmload 0
+       db      00fh, 001h, 0dah
+%endmacro
 
 ;VMRUN  equ db 0Fh, 01h, D8h
 ;VMLOAD equ db 0x0F,0x01,0xDA
@@ -32,8 +69,13 @@ EXPORT launch_svm
 ;CLGI   equ db 0x0F,0x01,0xDD
 
 
+align 8
+DisableInts:
+       cli
+       ret
 
 
+align 8
 GetGDTR:
        push    ebp
        mov     ebp, esp
@@ -46,13 +88,28 @@ GetGDTR:
        ret
 
 
-
+align 8
 GetIDTR:
        push    ebp
        mov     ebp, esp
        pusha   
+
        mov     ebx, [ebp + 8]
-       sgdt    [ebx]
+       sidt    [ebx]
+       
+       popa
+       pop     ebp
+       ret
+
+
+
+align 8
+GetTR:
+       push    ebp
+       mov     ebp, esp
+       pusha   
+       mov     ebx, [ebp + 8]
+       str     [ebx]
        
        popa
        pop     ebp
@@ -61,6 +118,7 @@ GetIDTR:
 
 
 ; I think its safe to say that there are some pretty serious register issues...
+align 8
 launch_svm:
        push    ebp
        mov     ebp, esp
@@ -75,49 +133,72 @@ launch_svm:
 
 
 
-; eventual svm_launch
-;   pusha
-;   pushf
-;
-; .vmm_loop
-;      vmrun
-;      push guest GPRs
-;      call handle_svm_exit
-;      jz .vmm_loop
-;  popf
-;  popa
-;  ret
-;
-;
-;
 
+exit_test: 
+       mov     cr4, eax
+       ret
 
 
 ;; Need to check this..
-;; Since RAX/EAX is saved in the VMCB, we should probably just 
-;;      do our own replacement for pusha/popa that excludes [e|r]ax
+;; save_svm_launch(rax, struct guest_gprs * regs)
+align 8
 safe_svm_launch:
        push    ebp
        mov     ebp, esp
        pushf
-       pusha
+       pusha                   ;; Save Host state
 
-.vmm_loop:
-       mov     eax, [ebp + 8]
+
+       push    dword [ebp + 12]  ;; pointer to the guest GPR save area
+       push    dword [ebp + 8]   ;; pointer to the VMCB pointer
+
+       mov     eax, [esp + 4]    ;; mov guest GPR pointer to eax
+
+       Restore_SVM_Registers eax ;; Restore Guest GPR state
+       pop     eax               ;; pop VMCB pointer into eax
+
+       vmload
        vmrun
-       pusha
-       call    handle_svm_exit
-       and     eax, eax
-       popa                    ;; restore the guest GPRs, (DOES THIS AFFECT E/RFLAGS?)
-       jz      .vmm_loop
+       vmsave
 
-       ;; HOW DO WE GET THE RETURN VALUE OF HANDLE_SVM_EXIT BACK TO THE CALLER
+       pop     eax               ;; pop Guest GPR pointer into eax
+       Save_SVM_Registers eax    ;; save guest GPRs
+
+       popa                      ;; Restore Host state
        popf
-       popa
-       pop     ebp
+       pop     ebp
        ret
 
 
+
+;;align 8
+;;safe_svm_launch:
+;;     push    ebp
+;;     mov     ebp, esp
+;;     pushf
+;;     pusha
+;;
+;.vmm_loop:
+;      mov     eax, [ebp + 8]
+;      vmrun
+;      Save_SVM_Registers
+;
+;      call    handle_svm_exit
+;
+;      mov     [ebp + 12], eax
+;
+;      and     eax, eax
+;
+;      Restore_SVM_Registers
+;
+;      jz      .vmm_loop
+;
+;      popa
+;      popf
+;      pop     ebp
+;      ret
+
+
 %endif
 
 
index 350cb98..3a72fb0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * x86 TSS data structure and routines
  * Copyright (c) 2001,2004 David H. Hovemeyer <daveho@cs.umd.edu>
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
@@ -82,3 +82,21 @@ void Set_Kernel_Stack_Pointer(ulong_t esp0)
      */
     Load_Task_Register();
 }
+
+
+/* JRL THIS FUCKING SUCKS */
+
+uint_t GetTR_Base() {
+  return (uint_t)(&s_theTSS);
+}
+uint_t GetTR_Limit() {
+  return  sizeof(struct TSS);
+}
+
+ushort_t GetTR_Selector() {
+  return s_tssSelector;
+}
+
+
+
+/* ** */
diff --git a/palacios/src/geekos/vmm_debug.c b/palacios/src/geekos/vmm_debug.c
new file mode 100644 (file)
index 0000000..cac8e6e
--- /dev/null
@@ -0,0 +1,34 @@
+#include <geekos/vmm_debug.h>
+#include <geekos/vmm.h>
+
+
+void PrintDebugHex(unsigned char x)
+{
+  unsigned char z;
+  
+  z = (x>>4) & 0xf ;
+  PrintDebug("%x", z);
+  z = x & 0xf;
+  PrintDebug("%x", z);
+}
+
+void PrintDebugMemDump(unsigned char *start, int n)
+{
+  int i, j;
+
+  for (i=0;i<n;i+=16) {
+    PrintDebug("%8x", (unsigned)(start+i));
+    for (j=i; j<i+16 && j<n; j+=2) {
+      PrintDebug(" ");
+      PrintDebugHex(*((unsigned char *)(start+j)));
+      if ((j+1)<n) { 
+       PrintDebugHex(*((unsigned char *)(start+j+1)));
+      }
+    }
+    PrintDebug(" ");
+    for (j=i; j<i+16 && j<n;j++) {
+      PrintDebug("%c", ((start[j]>=32) && (start[j]<=126)) ? start[j] : '.');
+    }
+    PrintDebug("\n");
+  }
+}
diff --git a/palacios/src/geekos/vmm_io.c b/palacios/src/geekos/vmm_io.c
new file mode 100644 (file)
index 0000000..9508ad1
--- /dev/null
@@ -0,0 +1,79 @@
+#include <geekos/vmm_io.h>
+#include <geekos/string.h>
+#include <geekos/vmm.h>
+
+extern struct vmm_os_hooks * os_hooks;
+
+void init_vmm_io_map(vmm_io_map_t * io_map) {
+  io_map->num_ports = 0;
+  io_map->head = NULL;
+}
+
+
+
+void add_io_hook(vmm_io_map_t * io_map, vmm_io_hook_t * io_hook) {
+  vmm_io_hook_t * tmp_hook = io_map->head;
+
+  if (!tmp_hook) {
+    io_map->head = io_hook;
+    io_map->num_ports = 1;
+    return;
+  } else {
+    while ((tmp_hook->next)  && 
+          (tmp_hook->next->port <= io_hook->port)) {
+      tmp_hook = tmp_hook->next;
+    }
+    
+    if (tmp_hook->port == io_hook->port) {
+      tmp_hook->read = io_hook->read;
+      tmp_hook->write = io_hook->write;
+      
+      VMMFree(io_hook);
+      return;
+    } else if (!tmp_hook->next) {
+      tmp_hook->next = io_hook;
+      io_hook->prev = tmp_hook;
+      io_map->num_ports++;
+      
+      return;
+    } else {
+      io_hook->next = tmp_hook->next;
+      io_hook->prev = tmp_hook;
+      
+      tmp_hook->next = io_hook;
+      if (io_hook->next) {
+       io_hook->next->prev = io_hook;
+      }
+      
+      io_map->num_ports++;
+      return;
+    }
+  }
+}
+
+void hook_io_port(vmm_io_map_t * io_map, uint_t port, 
+                 int (*read)(ushort_t port, void * dst, uint_t length),
+                 int (*write)(ushort_t port, void * src, uint_t length)) {
+  vmm_io_hook_t * io_hook = os_hooks->malloc(sizeof(vmm_io_hook_t));
+
+  io_hook->port = port;
+  io_hook->read = read;
+  io_hook->write = write;
+  io_hook->next = NULL;
+  io_hook->prev = NULL;
+
+  add_io_hook(io_map, io_hook);
+
+  return;
+}
+
+
+void PrintDebugIOMap(vmm_io_map_t * io_map) {
+  vmm_io_hook_t * iter = io_map->head;
+
+  PrintDebug("VMM IO Map (Entries=%d)\n", io_map->num_ports);
+
+  while (iter) {
+    PrintDebug("IO Port: %hu (Read=%x) (Write=%x)\n", iter->port, iter->read, iter->write);
+  }
+}