# 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".
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
# ----------------------------------------------------------------------
# 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
-/******************************************/
-/* 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
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
--- /dev/null
+#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
/*
* 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".
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 */
#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;
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 {
#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;
--- /dev/null
+#ifndef __VMM_DEBUG_H
+#define __VMM_DEBUG_H
+
+
+
+
+
+void PrintDebugHex(unsigned char x);
+void PrintDebugMemDump(unsigned char *start, int n);
+
+
+
+
+#endif
--- /dev/null
+#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
/*
* 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".
#include <geekos/gdt.h>
#include <libc/string.h>
+#include <geekos/debug.h>
/*
* This is defined in lowlevel.asm.
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,
s_GDT[i].granularity,
s_GDT[i].baseHigh );
} else {
- Print("%d: Not Present\n",i);
+ PrintBoth("%d: Not Present\n",i);
}
}
}
/*
* 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".
{
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"
* 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
}
-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()
{
unsigned char init;
- SerialPrint("Starting To Buzz\n");
+ PrintBoth("Starting To Buzz\n");
init=MyIn_Byte(SPEAKER_PORT);
}
}
-extern void RunVM();
-
-int vmRunning = 0;
-void RunVM() {
- vmRunning = 1;
-
- while(1);
-}
{
struct Kernel_Thread * key_thread;
struct Kernel_Thread * spkr_thread;
- // struct Kernel_Thread * vm_thread;
- // struct VMDescriptor vm;
ulong_t doIBuzz = 0;
-#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);
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);
}
#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;
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 */
// 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;
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;
}
// 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;
/* 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;
+ /* ** */
+ }
+
+
/* ** */
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;
- // 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);
{
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;
--- /dev/null
+#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;
+}
%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
;CLGI equ db 0x0F,0x01,0xDD
+align 8
+DisableInts:
+ cli
+ ret
+align 8
GetGDTR:
push ebp
mov ebp, esp
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
; I think its safe to say that there are some pretty serious register issues...
+align 8
launch_svm:
push ebp
mov ebp, esp
-; 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
/*
* 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".
*/
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;
+}
+
+
+
+/* ** */
--- /dev/null
+#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");
+ }
+}
--- /dev/null
+#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);
+ }
+}