From: Jack Lange Date: Fri, 14 Mar 2008 22:59:33 +0000 (+0000) Subject: working paged real mode X-Git-Tag: working-cdboot-physical-but-not-qemu~56 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=158640d601f6c710cfce7bc4a6bd8f7e7847b7a3 working paged real mode --- diff --git a/palacios/build/Makefile b/palacios/build/Makefile index ab3ad93..1406a31 100644 --- a/palacios/build/Makefile +++ b/palacios/build/Makefile @@ -1,6 +1,6 @@ # Makefile for GeekOS kernel, userspace, and tools # Copyright (c) 2004,2005 David H. Hovemeyer -# $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 diff --git a/palacios/build/vm_kernel b/palacios/build/vm_kernel index 417ac70..9898214 100755 Binary files a/palacios/build/vm_kernel and b/palacios/build/vm_kernel differ diff --git a/palacios/include/geekos/svm.h b/palacios/include/geekos/svm.h index 6bb2389..0b91f45 100644 --- a/palacios/include/geekos/svm.h +++ b/palacios/include/geekos/svm.h @@ -48,166 +48,10 @@ -/******************************************/ -/* 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 index 0000000..0afbe64 --- /dev/null +++ b/palacios/include/geekos/svm_handler.h @@ -0,0 +1,193 @@ +#ifndef __SVM_HANDLER_H +#define __SVM_HANDLER_H +#include +#include +#include + + + + + +/******************************************/ +/* 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 diff --git a/palacios/include/geekos/tss.h b/palacios/include/geekos/tss.h index 66ea118..9bab863 100644 --- a/palacios/include/geekos/tss.h +++ b/palacios/include/geekos/tss.h @@ -1,7 +1,7 @@ /* * x86 TSS data structure and routines * Copyright (c) 2001,2004 David H. Hovemeyer - * $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 */ diff --git a/palacios/include/geekos/vm_guest.h b/palacios/include/geekos/vm_guest.h index 15b6cca..6a6d86b 100644 --- a/palacios/include/geekos/vm_guest.h +++ b/palacios/include/geekos/vm_guest.h @@ -1,22 +1,39 @@ #ifndef __VM_GUEST_H #define __VM_GUEST_H -#include -#include +#include +#include +#include +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; diff --git a/palacios/include/geekos/vmcb.h b/palacios/include/geekos/vmcb.h index 894c12e..8bce011 100644 --- a/palacios/include/geekos/vmcb.h +++ b/palacios/include/geekos/vmcb.h @@ -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 { diff --git a/palacios/include/geekos/vmm.h b/palacios/include/geekos/vmm.h index 181155f..3b80c46 100644 --- a/palacios/include/geekos/vmm.h +++ b/palacios/include/geekos/vmm.h @@ -8,6 +8,7 @@ #include #include +#include /* utility definitions */ #define PrintDebug(fmt, args...) \ @@ -69,17 +70,6 @@ -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 index 0000000..db37060 --- /dev/null +++ b/palacios/include/geekos/vmm_debug.h @@ -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 index 0000000..fde2ea6 --- /dev/null +++ b/palacios/include/geekos/vmm_io.h @@ -0,0 +1,51 @@ +#ifndef __VMM_IO_H +#define __VMM_IO_H + +#include + +#include + +// 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 diff --git a/palacios/src/geekos/gdt.c b/palacios/src/geekos/gdt.c index d206939..707e34a 100644 --- a/palacios/src/geekos/gdt.c +++ b/palacios/src/geekos/gdt.c @@ -1,7 +1,7 @@ /* * Initialize kernel GDT. * Copyright (c) 2001,2004 David H. Hovemeyer - * $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 #include +#include /* * 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 - * $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" diff --git a/palacios/src/geekos/main.c b/palacios/src/geekos/main.c index 87bea69..18071b9 100644 --- a/palacios/src/geekos/main.c +++ b/palacios/src/geekos/main.c @@ -3,7 +3,7 @@ * Copyright (c) 2001,2003,2004 David H. Hovemeyer * Copyright (c) 2003, Jeffrey K. Hollingsworth * Copyright (c) 2004, Iulian Neamtiu - * $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". @@ -37,17 +37,6 @@ #include - - -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); } diff --git a/palacios/src/geekos/svm.c b/palacios/src/geekos/svm.c index 6d9d487..ed78fe1 100644 --- a/palacios/src/geekos/svm.c +++ b/palacios/src/geekos/svm.c @@ -4,7 +4,14 @@ #include #include #include +#include +#include + + +/* TEMPORARY BECAUSE SVM IS WEIRD */ +#include +/* ** */ 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 index 0000000..ea2a7b8 --- /dev/null +++ b/palacios/src/geekos/svm_handler.c @@ -0,0 +1,59 @@ +#include +#include + + + + +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; +} diff --git a/palacios/src/geekos/svm_lowlevel.asm b/palacios/src/geekos/svm_lowlevel.asm index fcb495f..7aa128f 100644 --- a/palacios/src/geekos/svm_lowlevel.asm +++ b/palacios/src/geekos/svm_lowlevel.asm @@ -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 diff --git a/palacios/src/geekos/tss.c b/palacios/src/geekos/tss.c index 350cb98..3a72fb0 100644 --- a/palacios/src/geekos/tss.c +++ b/palacios/src/geekos/tss.c @@ -1,7 +1,7 @@ /* * x86 TSS data structure and routines * Copyright (c) 2001,2004 David H. Hovemeyer - * $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 index 0000000..cac8e6e --- /dev/null +++ b/palacios/src/geekos/vmm_debug.c @@ -0,0 +1,34 @@ +#include +#include + + +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=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 index 0000000..9508ad1 --- /dev/null +++ b/palacios/src/geekos/vmm_io.c @@ -0,0 +1,79 @@ +#include +#include +#include + +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); + } +}