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.


minor changes to organization
Kyle Hale [Fri, 17 Jun 2011 19:51:21 +0000 (14:51 -0500)]
24 files changed:
Kconfig
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vm_guest_mem.h
palacios/include/palacios/vmm_ctrl_regs.h
palacios/include/palacios/vmm_decoder.h
palacios/include/palacios/vmm_execve_hook.h [new file with mode: 0644]
palacios/include/palacios/vmm_instr_decoder.h
palacios/include/palacios/vmm_intr.h
palacios/include/palacios/vmm_linux_syscall_map.h [new file with mode: 0644]
palacios/include/palacios/vmm_mpi_accel.h [new file with mode: 0644]
palacios/include/palacios/vmm_process_environment.h [new file with mode: 0644]
palacios/include/palacios/vmm_syscall_hijack.h [new file with mode: 0644]
palacios/src/extensions/Kconfig
palacios/src/extensions/Makefile
palacios/src/palacios/Makefile
palacios/src/palacios/svm.c
palacios/src/palacios/svm_handler.c
palacios/src/palacios/vm_guest.c
palacios/src/palacios/vm_guest_mem.c
palacios/src/palacios/vmm_ctrl_regs.c
palacios/src/palacios/vmm_decoder.c
palacios/src/palacios/vmm_intr.c
palacios/src/palacios/vmm_v3dec.c
palacios/src/palacios/vmm_xed.c

diff --git a/Kconfig b/Kconfig
index 71f5f9b..acf7ebf 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -163,6 +163,15 @@ config EXPERIMENTAL
          The purpose of this option is to allow features under development to be committed to the mainline
          to more easily track changes and provide access to multiple developers
 
+
+config INSPECTOR
+       bool "Enable VM inspection"
+       depends on EXPERIMENTAL
+       default n
+       help 
+         Enable inspection framework for vm internal state
+
+
 endmenu
 
 
@@ -402,6 +411,16 @@ config DEBUG_DEV_MGR
        help 
          This turns on debugging for the device manager
 
+
+config DEBUG_SYSCALL_HIJACK
+        bool "Enable Syscall Hijack Debug in Palacios"
+        default n
+        depends on DEBUG_ON && SYSCALL_HIJACK
+        help
+          Enable Debugging printouts for syscall hijacking
+          code in Palacios
+
+
 endmenu
 
 
index 4360a64..5792543 100644 (file)
 struct v3_sym_core_state;
 #endif
 
+#ifdef V3_CONFIG_SYSCALL_HIJACK
+#include <palacios/vmm_syscall_hijack.h>
+#include <palacios/vmm_execve_hook.h>
+#endif
+
 
 
 #include <palacios/vmm_config.h>
@@ -90,6 +95,12 @@ struct guest_info {
     /* This structure is how we get exceptions for the guest */
     struct v3_excp_state excp_state;
 
+#ifdef V3_CONFIG_SYSCALL_HIJACK
+    struct v3_syscall_hook_map sc_hook_map;
+    struct v3_execve_varchunk var_dump;
+    struct v3_exec_hooks exec_hooks;
+#endif
+
 
     v3_cpu_mode_t cpu_mode;
     v3_mem_mode_t mem_mode;
index db6a6a0..6d983ae 100644 (file)
@@ -99,6 +99,9 @@ int v3_hva_to_gva(struct guest_info * guest_info, addr_t host_va, addr_t  * gues
 
 
 
+// KCH
+// Check if pte for this gva has certain permissions
+int v3_gva_can_access(struct guest_info * core, addr_t gva);
 
 
 
index e072a04..0b3336a 100644 (file)
 
 #define EFER_MSR                 0xc0000080
 
+// KCH: for system-call interposition
+#define STAR_MSR                 0xc0000081 /* Legacy mode SYSCALL target */
+#define LSTAR_MSR                0xc0000082 /* Long mode SYSCALL target */
+#define CSTAR_MSR                0xc0000083 /* compat mode SYSCALL target */
+#define SF_MASK_MSR              0xc0000084 /* EFLAGS mask for syscall */
+#define FS_BASE_MSR              0xc0000100 /* 64-bit FS base */
+#define GS_BASE_MSR              0xc0000101 /* 64-bit GS base */
+#define KERN_GS_BASE_MSR         0xc0000102 /* swapGS GS shadow */
+
+/* Intel specific */
+#define IA32_SYSENTER_CS_MSR     0x00000174
+#define IA32_SYSENTER_ESP_MSR    0x00000175
+#define IA32_SYSENTER_EIP_MSR    0x00000176
+
 struct cr0_real {
     uint_t pe    : 1;
     uint_t mp    : 1;
@@ -215,6 +229,16 @@ int v3_handle_cr4_read(struct guest_info * info);
 int v3_handle_efer_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data);
 int v3_handle_efer_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data);
 
+int v3_handle_star_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data);
+int v3_handle_star_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data);
+int v3_handle_lstar_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data);
+int v3_handle_lstar_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data);
+int v3_handle_cstar_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data);
+int v3_handle_cstar_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data);
+
+int v3_handle_seeip_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data);
+int v3_handle_seeip_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data);
+
 int v3_handle_vm_cr_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data);
 int v3_handle_vm_cr_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data);
 
index 7b703a8..7f33fde 100644 (file)
@@ -34,7 +34,7 @@ typedef enum { V3_INVALID_OP,
               V3_OP_SETB, V3_OP_SETBE, V3_OP_SETL, V3_OP_SETLE, V3_OP_SETNB, 
               V3_OP_SETNBE, V3_OP_SETNL, V3_OP_SETNLE, V3_OP_SETNO, V3_OP_SETNP,
               V3_OP_SETNS, V3_OP_SETNZ, V3_OP_SETO, V3_OP_SETP, V3_OP_SETS, 
-              V3_OP_SETZ, V3_OP_MOVS, V3_OP_STOS, V3_OP_MOVZX, V3_OP_MOVSX } v3_op_type_t;
+              V3_OP_SETZ, V3_OP_MOVS, V3_OP_STOS, V3_OP_MOVZX, V3_OP_MOVSX, V3_OP_INT } v3_op_type_t;
 
 
 typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND, IMM_OPERAND} v3_operand_type_t;
diff --git a/palacios/include/palacios/vmm_execve_hook.h b/palacios/include/palacios/vmm_execve_hook.h
new file mode 100644 (file)
index 0000000..4341a30
--- /dev/null
@@ -0,0 +1,51 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.norhtwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+#ifndef __VMM_EXECVE_HOOK_H__
+#define __VMM_EXECVE_HOOK_H__
+
+#ifdef __V3VEE__
+
+
+struct v3_exec_hooks {
+    struct list_head hook_list;
+    struct hashtable * bin_table;
+};
+
+struct exec_hook {
+    int (*handler)(struct guest_info * core, void * priv_data);
+    struct list_head hook_node;
+    void * priv_data;
+};
+
+
+int v3_init_exec_hooks (struct guest_info * core);
+int v3_deinit_exec_hooks (struct guest_info * core);
+
+int v3_hook_executable (struct guest_info * core, 
+    const uchar_t * binfile,
+    int (*handler)(struct guest_info * core, void * priv_data),
+    void * priv_data);
+
+
+#endif
+
+
+#endif
index 623ca4d..60ff80a 100644 (file)
@@ -28,6 +28,7 @@ typedef enum {
     SMSW,
     CLTS,
     INVLPG,
+    INT, // KCH: adding software interrupts
 
     MOV_CR2,
     MOV_2CR,
@@ -310,6 +311,7 @@ static int get_operand_width(struct guest_info * info, struct x86_instr * instr,
                    return -1;
            }
 
+    case INT: // KCH
        case MOV_DR2:
        case MOV_2DR:
        case MOV_CR2:
@@ -1336,7 +1338,10 @@ static op_form_t op_code_to_form(uint8_t * instr, int * length) {
 
        case 0xf4:
            return HLT;
-
+    
+    // KCH
+    case 0xcd:
+        return INT;
 
        case 0xf6: {
            struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
@@ -1499,6 +1504,7 @@ static char * op_form_to_str(op_form_t form) {
        case SETO: return "SETO";
        case STOS_8: return "STOS_8";
        case STOS: return "STOS";
+    case INT: return "INT"; // KCH
 
        case INVALID_INSTR:
        default:
index 626b98b..62c8667 100644 (file)
@@ -41,6 +41,13 @@ struct v3_irq_hook {
     void * priv_data;
 };
 
+// KCH
+struct v3_swintr_hook {
+    int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data);
+    void * priv_data;
+};
+
+
 #define MAX_IRQ 256
 
 
@@ -58,6 +65,11 @@ struct v3_intr_core_state {
     uint_t irq_started;
     uint_t irq_vector;
 
+    // KCH: for injecting SW Interrupts
+    uint_t swintr_posted;
+    uint_t swintr_vector;
+    struct v3_swintr_hook * swintr_hooks[256];
+
     uint8_t virq_map[MAX_IRQ / 8];
 
     v3_lock_t irq_lock;
@@ -94,7 +106,6 @@ struct intr_router_ops {
 
 void v3_clear_pending_intr(struct guest_info * core);
 
-
 void * v3_register_intr_controller(struct guest_info * info, struct intr_ctrl_ops * ops, void * priv_data);
 void * v3_register_intr_router(struct v3_vm_info * vm, struct intr_router_ops * ops, void * priv_data);
 
@@ -113,7 +124,6 @@ int v3_injecting_intr(struct guest_info * info, uint_t intr_num, v3_intr_type_t
 */
 
 
-
 int v3_hook_irq(struct v3_vm_info * vm, 
                uint_t irq,
                int (*handler)(struct v3_vm_info * vm, struct v3_interrupt * intr, void * priv_data),
@@ -122,6 +132,16 @@ int v3_hook_irq(struct v3_vm_info * vm,
 int v3_hook_passthrough_irq(struct v3_vm_info * vm, uint_t irq);
 
 
+int v3_hook_swintr(struct guest_info * core,
+        uint8_t vector,
+        int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data),
+        void * priv_data);
+
+int v3_hook_passthrough_swintr(struct guest_info * core, uint8_t vector);
+
+
+int v3_signal_swintr(struct guest_info * core, int vec);
+int v3_handle_swintr(struct guest_info * core);
 
 #endif // !__V3VEE__
 
diff --git a/palacios/include/palacios/vmm_linux_syscall_map.h b/palacios/include/palacios/vmm_linux_syscall_map.h
new file mode 100644 (file)
index 0000000..0a40146
--- /dev/null
@@ -0,0 +1,32 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.northwestern.edu> 
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __VMM_LINUX_SYSCALL_MAP_H__
+#define __VMM_LINUX_SYSCALL_MAP_H__
+
+#ifdef __V3VEE__
+
+#include <palacios/vmm_types.h>
+
+char * get_linux_syscall_name32 (uint_t syscall_nr);
+char * get_linux_syscall_name64 (uint_t syscall_nr);
+
+#endif
+
+#endif
diff --git a/palacios/include/palacios/vmm_mpi_accel.h b/palacios/include/palacios/vmm_mpi_accel.h
new file mode 100644 (file)
index 0000000..5958e4b
--- /dev/null
@@ -0,0 +1,33 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.northwestern.edu> 
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __VMM_MPI_ACCEL_H__
+#define __VMM_MPI_ACCEL_H__
+
+
+#ifdef __V3VEE__
+
+int v3_init_mpi_accel (struct guest_info * core);
+int v3_deinit_mpi_accel (struct guest_info * core);
+int v3_mpi_preload_handler (struct guest_info * core, void * priv_data);
+
+
+#endif
+
+#endif
diff --git a/palacios/include/palacios/vmm_process_environment.h b/palacios/include/palacios/vmm_process_environment.h
new file mode 100644 (file)
index 0000000..f3cfb10
--- /dev/null
@@ -0,0 +1,41 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.northwestern.edu> 
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __VMM_PROCESS_ENVIRONMENT_H__
+#define __VMM_PROCESS_ENVIRONMENT_H__
+
+#ifdef __V3VEE__
+
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_types.h>
+#include <palacios/vm_guest.h>
+
+
+int v3_replace_arg (struct guest_info * core, uint_t argnum, const char * newval);
+int v3_replace_env (struct guest_info * core, const char * envname, const char * newval);
+
+int v3_inject_strings (struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt);
+
+addr_t v3_prepare_guest_stack (struct guest_info * core, uint_t bytes_needed);
+
+#endif
+
+#endif 
+
diff --git a/palacios/include/palacios/vmm_syscall_hijack.h b/palacios/include/palacios/vmm_syscall_hijack.h
new file mode 100644 (file)
index 0000000..14e00f8
--- /dev/null
@@ -0,0 +1,67 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.northwestern.edu> 
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __VMM_SYSCALL_HIJACK_H__
+#define __VMM_SYSCALL_HIJACK_H__
+
+
+#ifdef __V3VEE__
+
+
+struct v3_syscall_hook_map {
+    /* 512 is an arbitrary number, I'm not sure that
+        there is a hard limit on the number of syscalls
+        an OS can provide */
+    struct v3_syscall_hook * syscall_hooks[512];
+};
+
+struct v3_syscall_hook {
+    int (*handler)(struct guest_info * core, uint_t syscall_nr, void * priv_data);
+    void * priv_data;
+};
+
+
+struct v3_execve_varchunk {
+    char ** argv;
+    char ** envp;
+    uint_t argc;
+    uint_t envc;
+    uint_t bytes;
+    int active;
+};
+    
+
+int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_data);
+
+
+int v3_hook_syscall (struct guest_info * core,
+    uint_t syscall_nr,
+    int (*handler)(struct guest_info * core, uint_t syscall_nr, void * priv_data), 
+    void * priv_data);
+
+int v3_hook_passthrough_syscall (struct guest_info * core, uint_t syscall_nr);
+
+int v3_sysopen_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data);
+int v3_sysmount_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data);
+int v3_sysexecve_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data);
+
+
+#endif
+
+#endif
index c7b7d69..22d1dcc 100644 (file)
@@ -38,4 +38,48 @@ config EXT_INSPECTOR
        help
          Provides the inspection extension
 
+config SW_INTERRUPTS
+    bool "Enable interception and hooking of software interrupts"
+    default n
+    help
+      This feature will cause the VMM to intercept the execution
+      of software interrupts (i.e. the INTn instruction) and enable
+      any INT vector to be hooked
+
+config SWINTR_PASSTHROUGH
+    bool "Hook all unhandled sofware interrupts for passthrough"
+    depends on SW_INTERRUPTS
+    default n
+    help
+      If enabled, this will cause all software interrupts 
+      (INT instruction vectors) to be hooked for passthrough.
+      May reduce performance but useful for debugging.
+
+config SYSCALL_HIJACK
+    bool "Enable System Call Hijacking"
+    depends on SW_INTERRUPTS
+    default n
+    help
+      Enable the VMM to hijack system calls executed by the guest.
+      If enabled, the VMM will hook execution of INT 80
+      (support for Fast-System Calls coming soon)
+
+config SYSCALL_PASSTHROUGH
+    bool "Hook all unhandled system calls for passthrough"
+    depends on SYSCALL_HIJACK
+    default n
+    help
+      If enabled, this option will cause all system calls
+      that are not explicitly hooked to be hooked for 
+      passthrough. This is useful for debugging.
+
+config HIJACK_SYSCALL_MSR
+    bool "Intercept Syscall-related MSR reads & writes"
+    depends on SYSCALL_HIJACK 
+    default n
+    help
+      Allow the VMM to intercept reads and writes to MSRs
+      related to SYSCALL and SYSENTER instructions. Specifically,
+      it will intercept R/W to STAR, CSTAR, and LSTAR.
+
 endmenu
index ab31a13..ca51193 100644 (file)
@@ -3,3 +3,9 @@ obj-$(V3_CONFIG_EXT_MTRRS) += ext_mtrr.o
 obj-$(V3_CONFIG_EXT_VTSC) += ext_vtsc.o
 obj-$(V3_CONFIG_EXT_VTIME) += ext_vtime.o
 obj-$(V3_CONFIG_EXT_INSPECTOR) += ext_inspector.o
+
+obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_syscall_hijack.o 
+obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_linux_syscall_map.o
+obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_mpi_accel.o
+obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_process_environment.o
+obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_execve_hook.o
index 4c55738..4985623 100644 (file)
@@ -71,5 +71,4 @@ obj-$(V3_CONFIG_SYMBIOTIC) += vmm_symbiotic.o vmm_symspy.o
 obj-$(V3_CONFIG_SYMCALL) += vmm_symcall.o
 obj-$(V3_CONFIG_SYMMOD) += vmm_symmod.o
 
-
 obj-y += mmu/
index dffbdb8..a2cbbc1 100644 (file)
@@ -136,6 +136,11 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) {
     ctrl_area->instrs.PAUSE = 1;
     ctrl_area->instrs.shutdown_evts = 1;
 
+    /* KCH: intercept SW Interrupts (INT instr) */
+#ifdef V3_CONFIG_SW_INTERRUPTS
+    ctrl_area->instrs.INTn = 1;
+#endif
+
 
     /* DEBUG FOR RETURN CODE */
     ctrl_area->exit_code = 1;
@@ -224,6 +229,37 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) {
                &v3_handle_efer_write, 
                core);
 
+#ifdef V3_CONFIG_HIJACK_SYSCALL_MSR
+    /* KCH: we're not hooking these to TRAP them,
+            instead, we're going to catch the target EIP.
+            Hopefully this EIP is the entry point in the ELF located in the 
+            vsyscall page. We can inject checks into the code segment such that
+            we don't have to exit on uninteresting system calls. This should
+            give us much better performance than INT 80, and should even obviate
+            the need to deal with software interrupts at all */
+    v3_hook_msr(core->vm_info, STAR_MSR,
+        &v3_handle_star_read,
+        &v3_handle_star_write,
+        core);
+    v3_hook_msr(core->vm_info, LSTAR_MSR,
+        &v3_handle_lstar_read,
+        &v3_handle_lstar_write,
+        core);
+    v3_hook_msr(core->vm_info, CSTAR_MSR,
+        &v3_handle_cstar_read,
+        &v3_handle_cstar_write,
+        core);
+    
+    /* KCH: this probably isn't necessary, as
+        SYSENTER is only used in legacy mode. In fact,
+        in long mode it results in an illegal instruction
+        exception */
+    v3_hook_msr(core->vm_info, IA32_SYSENTER_EIP_MSR,
+        &v3_handle_seeip_read,
+        &v3_handle_seeip_write,
+        core);
+#endif
+
     if (core->shdw_pg_mode == SHADOW_PAGING) {
        PrintDebug("Creating initial shadow page table\n");
        
@@ -423,9 +459,23 @@ static int update_irq_entry_state(struct guest_info * info) {
            case V3_NMI:
                guest_ctrl->EVENTINJ.type = SVM_INJECTION_NMI;
                break;
-           case V3_SOFTWARE_INTR:
-               guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR;
-               break;
+           case V3_SOFTWARE_INTR: {
+#ifdef CONFIG_DEBUG_INTERRUPTS
+            PrintDebug("Caught an injected software interrupt\n");
+            PrintDebug("\ttype: %d, vector: %d\n", SVM_INJECTION_SOFT_INTR, info->intr_core_state.swintr_vector);
+#endif
+            guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR;
+            guest_ctrl->EVENTINJ.vector = info->intr_core_state.swintr_vector;
+            guest_ctrl->EVENTINJ.valid = 1;
+            
+            /* reset the software interrupt state. 
+                we can do this because we know only one
+                sw int can be posted at a time on a given 
+                core, unlike irqs */
+            info->intr_core_state.swintr_posted = 0;
+            info->intr_core_state.swintr_vector = 0;
+            break;
+        }
            case V3_VIRTUAL_IRQ:
                guest_ctrl->EVENTINJ.type = SVM_INJECTION_IRQ;
                break;
index a84d2e1..da85eb2 100644 (file)
@@ -33,6 +33,7 @@
 #include <palacios/vmm_hypercall.h>
 #include <palacios/vmm_cpuid.h>
 #include <palacios/vmm_direct_paging.h>
+#include <palacios/vmm_syscall_hijack.h>
 
 #ifndef V3_CONFIG_DEBUG_SVM
 #undef PrintDebug
@@ -193,6 +194,15 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
                    }
            break;
            }
+    case VMEXIT_SWINT:
+#ifdef CONFIG_DEBUG_INTERRUPTS
+        PrintDebug("Intercepted SW Interrupt\n");
+#endif
+        if (v3_handle_swintr(info) == -1) {
+            PrintError("Error handling software interrupt\n");
+            return -1;
+        }
+        break;
        case VMEXIT_INVLPG: 
            if (info->shdw_pg_mode == SHADOW_PAGING) {
 #ifdef V3_CONFIG_DEBUG_SHADOW_PAGING
index 62d2a94..6f40a87 100644 (file)
 #include <palacios/vmm_xed.h>
 #include <palacios/vmm_direct_paging.h>
 
+#ifdef V3_CONFIG_SYSCALL_HIJACK
+#include <palacios/vmm_syscall_hijack.h>
+#include <palacios/vmm_mpi_accel.h>
+#endif
+
 
 
 v3_cpu_mode_t v3_get_vm_cpu_mode(struct guest_info * info) {
@@ -680,6 +685,12 @@ int v3_init_core(struct guest_info * core) {
     v3_init_symbiotic_core(core);
 #endif
 
+// KCH
+#ifdef V3_CONFIG_SYSCALL_HIJACK
+    v3_init_exec_hooks(core);
+    v3_init_mpi_accel(core);
+#endif  
+
     // init SVM/VMX
 
 
index 8cc497a..caf8a89 100644 (file)
@@ -168,15 +168,15 @@ int v3_gva_to_gpa(struct guest_info * guest_info, addr_t gva, addr_t * gpa) {
     switch (guest_info->cpu_mode) {
        case PROTECTED:
            if (v3_translate_guest_pt_32(guest_info, guest_cr3, gva, gpa) == -1) {
-               PrintDebug("Could not translate addr (%p) through 32 bit guest PT at %p\n", 
-                          (void *)gva, (void *)(addr_t)guest_cr3);
+               /*PrintDebug("Could not translate addr (%p) through 32 bit guest PT at %p\n", 
+                          (void *)gva, (void *)(addr_t)guest_cr3);*/
                return -1;
            }
            break;
        case PROTECTED_PAE:
            if (v3_translate_guest_pt_32pae(guest_info, guest_cr3, gva, gpa) == -1) {
-               PrintDebug("Could not translate addr (%p) through 32 bitpae guest PT at %p\n", 
-                          (void *)gva, (void *)(addr_t)guest_cr3);
+               /*PrintDebug("Could not translate addr (%p) through 32 bitpae guest PT at %p\n", 
+                          (void *)gva, (void *)(addr_t)guest_cr3);*/
                return -1;
            }
            break;
@@ -184,8 +184,8 @@ int v3_gva_to_gpa(struct guest_info * guest_info, addr_t gva, addr_t * gpa) {
        case LONG_32_COMPAT:
        case LONG_16_COMPAT:
            if (v3_translate_guest_pt_64(guest_info, guest_cr3, gva, gpa) == -1) {
-               PrintDebug("Could not translate addr (%p) through 64 bit guest PT at %p\n", 
-                          (void *)gva, (void *)(addr_t)guest_cr3);
+               /*PrintDebug("Could not translate addr (%p) through 64 bit guest PT at %p\n", 
+                          (void *)gva, (void *)(addr_t)guest_cr3);*/
                return -1;
            }
            break;
@@ -266,8 +266,8 @@ int v3_gva_to_hva(struct guest_info * guest_info, addr_t gva, addr_t * hva) {
     *hva = 0;
 
     if (v3_gva_to_gpa(guest_info, gva, &gpa) != 0) {
-       PrintError("In GVA->HVA: Invalid GVA(%p)->GPA lookup\n", 
-                  (void *)gva);
+       /*PrintError("In GVA->HVA: Invalid GVA(%p)->GPA lookup\n", 
+                  (void *)gva);*/
        return -1;
     }
 
@@ -317,6 +317,56 @@ int v3_hva_to_gva(struct guest_info * guest_info, addr_t hva, addr_t * gva) {
 
 
 
+/* KCH: currently only checks if we can perform a user-mode write
+   return 1 on success */
+int v3_gva_can_access(struct guest_info * core, addr_t gva) {
+
+    v3_reg_t guest_cr3 = 0;
+    pf_error_t access_type;
+    pt_access_status_t access_status;
+
+    access_type.write = 1;
+    access_type.user = 1;
+    
+    if (core->mem_mode == PHYSICAL_MEM) {
+        return -1;
+    }
+    
+    if (core->shdw_pg_mode == SHADOW_PAGING) {
+        guest_cr3 = core->shdw_pg_state.guest_cr3;
+    } else {
+        guest_cr3 = core->ctrl_regs.cr3;
+    }
+    
+    // guest is in paged mode
+    switch (core->cpu_mode) {
+    case PROTECTED:
+        if (v3_check_guest_pt_32(core, guest_cr3, gva, access_type, &access_status) == -1) {
+            return -1;
+        }
+        break;
+    case PROTECTED_PAE:
+        if (v3_check_guest_pt_32pae(core, guest_cr3, gva, access_type, &access_status) == -1) {
+            return -1;
+        }
+        break;
+    case LONG:
+    case LONG_32_COMPAT:
+    case LONG_16_COMPAT:
+        if (v3_check_guest_pt_64(core, guest_cr3, gva, access_type, &access_status) == -1) {
+            return -1;
+        }
+        break;
+    default:
+        return -1;
+    }
+
+    if (access_status != PT_ACCESS_OK) {
+        return 0;
+    } else {
+        return 1;
+    }
+}
 
 
 
index d5a8650..4c84e2e 100644 (file)
@@ -582,6 +582,78 @@ int v3_handle_efer_write(struct guest_info * core, uint_t msr, struct v3_msr src
     return 0;
 }
 
+
+/* KCH: all of the star handlers are for syscall interposition */
+int v3_handle_star_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) {
+
+#ifdef CONFIG_DEBUG_SYSCALL_HIJACK
+    PrintDebug("STAR Read\n");
+#endif
+
+    return 0;
+}
+
+
+int v3_handle_star_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
+    
+#ifdef V3_CONFIG_DEBUG_SYSCALL_HIJACK
+    PrintDebug("STAR Write\n");
+#endif
+    return 0;
+}
+
+
+int v3_handle_lstar_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) {
+
+#ifdef V3_CONFIG_DEBUG_SYSCALL_HIJACK
+    PrintDebug("LSTAR Read\n");
+#endif
+    return 0;
+}
+
+
+int v3_handle_lstar_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
+    
+#ifdef V3_CONFIG_DEBUG_SYSCALL_HIJACK
+    ulong_t entry = ((ulong_t)src.hi << 32) | (ulong_t)src.lo;
+    PrintDebug("LSTAR Write\n");
+    PrintDebug("\tKernel syscall entry point: 0x%lx\n", entry);
+#endif
+    
+    return 0;
+}
+
+
+int v3_handle_cstar_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) {
+
+#ifdef V3_CONFIG_DEBUG_SYSCALL_HIJACK
+    PrintDebug("CSTAR Read\n");
+#endif
+    return 0;
+}
+
+
+int v3_handle_cstar_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
+    
+#ifdef V3_CONFIG_DEBUG_SYSCALL_HIJACK
+    PrintDebug("CSTAR Write\n");
+#endif
+    return 0;
+}
+
+int v3_handle_seeip_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) {
+    /* we don't care about reads */
+    return 0;
+}
+
+int v3_handle_seeip_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
+#ifdef V3_CONFIG_DEBUG_SYSALL_HIJACK
+    PrintDebug("SYSENTER_EIP Write\n");
+#endif
+    return 0;
+}
+
+
 int v3_handle_vm_cr_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) {
     /* tell the guest that the BIOS disabled SVM, that way it doesn't get 
      * confused by the fact that CPUID reports SVM as available but it still
index a2f260c..1783ca1 100644 (file)
@@ -146,6 +146,7 @@ static char * op_type_to_str(v3_op_type_t type) {
        case V3_OP_STOS: return "V3_OP_STOS"; 
        case V3_OP_MOVZX: return "V3_OP_MOVZX"; 
        case V3_OP_MOVSX: return "V3_OP_MOVSX";
+    case V3_OP_INT: return "V3_OP_INT"; // KCH
        case V3_INVALID_OP: 
        default:
            return "V3_INVALID_OP";
index 8c4e1c2..f8dbd68 100644 (file)
@@ -25,6 +25,8 @@
 #include <palacios/vmm_ctrl_regs.h>
 
 #include <palacios/vmm_lock.h>
+#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_decoder.h>
 
 #ifndef V3_CONFIG_DEBUG_INTERRUPTS
 #undef PrintDebug
@@ -33,7 +35,6 @@
 
 
 
-
 struct intr_controller {
     struct intr_ctrl_ops * ctrl_ops;
     
@@ -50,6 +51,8 @@ struct intr_router {
 
 };
 
+
+
 void v3_init_intr_controllers(struct guest_info * info) {
     struct v3_intr_core_state * intr_state = &(info->intr_core_state);
 
@@ -95,6 +98,7 @@ void v3_deinit_intr_routers(struct v3_vm_info * vm) {
     }  
 }
 
+
 void * v3_register_intr_controller(struct guest_info * info, struct intr_ctrl_ops * ops, void * priv_data) {
     struct intr_controller * ctrlr = (struct intr_controller *)V3_Malloc(sizeof(struct intr_controller));
 
@@ -106,6 +110,7 @@ void * v3_register_intr_controller(struct guest_info * info, struct intr_ctrl_op
     return (void *)ctrlr;
 }
 
+
 void v3_remove_intr_controller(struct guest_info * core, void * handle) {
     struct v3_intr_core_state * intr_state = &(core->intr_core_state);
     struct intr_controller * ctrlr = handle;
@@ -128,6 +133,7 @@ void v3_remove_intr_controller(struct guest_info * core, void * handle) {
     V3_Free(ctrlr);
 }
 
+
 void * v3_register_intr_router(struct v3_vm_info * vm, struct intr_router_ops * ops, void * priv_data) {
     struct intr_router * router = (struct intr_router *)V3_Malloc(sizeof(struct intr_router));
 
@@ -139,6 +145,7 @@ void * v3_register_intr_router(struct v3_vm_info * vm, struct intr_router_ops *
     return (void *)router;
 }
 
+
 void v3_remove_intr_router(struct v3_vm_info * vm, void * handle) {
     struct intr_router * router = handle;
     struct intr_router * tmp = NULL;
@@ -161,9 +168,7 @@ void v3_remove_intr_router(struct v3_vm_info * vm, void * handle) {
 }
 
 
-
-static inline struct v3_irq_hook * get_irq_hook(struct v3_vm_info * vm, uint_t irq) {
-    V3_ASSERT(irq <= 256);
+static inline struct v3_irq_hook * get_irq_hook(struct v3_vm_info * vm, uint8_t irq) {
     return vm->intr_routers.hooks[irq];
 }
 
@@ -199,7 +204,6 @@ int v3_hook_irq(struct v3_vm_info * vm,
 }
 
 
-
 static int passthrough_irq_handler(struct v3_vm_info * vm, struct v3_interrupt * intr, void * priv_data) {
     PrintDebug("[passthrough_irq_handler] raise_irq=%d (guest=0x%p)\n", 
               intr->irq, (void *)vm);
@@ -207,6 +211,7 @@ static int passthrough_irq_handler(struct v3_vm_info * vm, struct v3_interrupt *
     return v3_raise_irq(vm, intr->irq);
 }
 
+
 int v3_hook_passthrough_irq(struct v3_vm_info * vm, uint_t irq) {
     int rc = v3_hook_irq(vm, irq, passthrough_irq_handler, NULL);
 
@@ -220,9 +225,6 @@ int v3_hook_passthrough_irq(struct v3_vm_info * vm, uint_t irq) {
 }
 
 
-
-
-
 int v3_deliver_irq(struct v3_vm_info * vm, struct v3_interrupt * intr) {
     PrintDebug("v3_deliver_irq: irq=%d state=0x%p, \n", intr->irq, (void *)intr);
   
@@ -237,9 +239,6 @@ int v3_deliver_irq(struct v3_vm_info * vm, struct v3_interrupt * intr) {
 }
 
 
-
-
-
 int v3_raise_virq(struct guest_info * info, int irq) {
     struct v3_intr_core_state * intr_state = &(info->intr_core_state);
     int major = irq / 8;
@@ -250,6 +249,7 @@ int v3_raise_virq(struct guest_info * info, int irq) {
     return 0;
 }
 
+
 int v3_lower_virq(struct guest_info * info, int irq) {
     struct v3_intr_core_state * intr_state = &(info->intr_core_state);
     int major = irq / 8;
@@ -277,6 +277,7 @@ int v3_lower_irq(struct v3_vm_info * vm, int irq) {
     return 0;
 }
 
+
 int v3_raise_irq(struct v3_vm_info * vm, int irq) {
     struct intr_router * router = NULL;
     struct v3_intr_routers * routers = &(vm->intr_routers);
@@ -294,11 +295,131 @@ int v3_raise_irq(struct v3_vm_info * vm, int irq) {
 }
 
 
+int v3_signal_swintr(struct guest_info * core, int vector) {
+    struct v3_intr_core_state * intr_state = &(core->intr_core_state);
+
+    PrintDebug("Signaling software interrupt in vmm_intr.c\n");
+    PrintDebug("\tINT vector: %d\n", vector);
+    
+    intr_state->swintr_posted = 1;
+    intr_state->swintr_vector = vector;
+    return 0;
+}
+
+
+int v3_handle_swintr(struct guest_info * core) {
+
+    int ret = 0;
+    void * instr_ptr = NULL;
+    struct x86_instr instr;
+
+    if (core->mem_mode == PHYSICAL_MEM) { 
+        ret = v3_gpa_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr);
+    } else { 
+        ret = v3_gva_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr);
+    }
+    
+    if (ret == -1) {
+        PrintError("V3 SWintr Handler: Could not translate Instruction Address (%p)\n", (void *)core->rip);
+        return -1;
+    }
+
+    if (v3_decode(core, (addr_t)instr_ptr, &instr) == -1) {
+        PrintError("V3 SWintr Handler: Decoding Error\n");
+        return -1;
+    }
+
+    uint8_t vector = instr.dst_operand.operand;
+
+    struct v3_swintr_hook * hook = core->intr_core_state.swintr_hooks[vector];
+    if (hook == NULL) {
+#ifdef V3_CONFIG_SWINTR_PASSTHROUGH
+        if (v3_hook_passthrough_swintr(core, vector) == -1) {
+            PrintDebug("V3 SWintr Handler: Error hooking passthrough swintr\n");
+            return -1;
+        }
+        hook = core->intr_core_state.swintr_hooks[vector];
+#else
+        core->rip += instr.instr_length;
+        return v3_signal_swintr(core, vector);
+#endif
+    }
+
+    ret = hook->handler(core, vector, NULL);
+    if (ret == -1) {
+        PrintDebug("V3 SWintr Handler: Error in swintr hook\n");
+        return -1;
+    }
+
+    /* KCH: at some point we may need to prioritize swints 
+       so that they finish in time for the next
+       instruction... */
+    core->rip += instr.instr_length;
+    return v3_signal_swintr(core, vector);
+}
+
+
+static inline struct v3_swintr_hook * get_swintr_hook(struct guest_info * core, uint8_t vector) {
+    return core->intr_core_state.swintr_hooks[vector];
+}
+
+
+int v3_hook_swintr(struct guest_info * core,
+        uint8_t vector,
+        int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data),
+        void * priv_data) 
+{
+
+    struct v3_swintr_hook * hook = (struct v3_swintr_hook *)V3_Malloc(sizeof(struct v3_swintr_hook));
+
+    if (hook == NULL) { 
+        return -1; 
+    }
+
+    if (get_swintr_hook(core, vector) != NULL) {
+        PrintError("SWINT %d already hooked\n", vector);
+        return -1;
+    }
+
+    hook->handler = handler;
+    hook->priv_data = priv_data;
+  
+    core->intr_core_state.swintr_hooks[vector] = hook;
+
+    return 0;
+}
+    
+
+static int passthrough_swintr_handler(struct guest_info * core, uint8_t vector, void * priv_data) {
+
+    PrintDebug("[passthrough_swint_handler] INT vector=%d (guest=0x%p)\n", 
+              vector, (void *)core);
+
+    return 0;
+}
+
+
+int v3_hook_passthrough_swintr(struct guest_info * core, uint8_t vector) {
+
+    int rc = v3_hook_swintr(core, vector, passthrough_swintr_handler, NULL);
+
+    if (rc) { 
+        PrintError("guest_swintr_injection: failed to hook swint 0x%x (guest=0x%p)\n", vector, (void *)core);
+        return -1;
+    } else {
+        PrintDebug("guest_swintr_injection: hooked swint 0x%x (guest=0x%p)\n", vector, (void *)core);
+        return 0;
+    }
+
+    /* shouldn't get here */
+    return 0;
+}
+
+
 void v3_clear_pending_intr(struct guest_info * core) {
     struct v3_intr_core_state * intr_state = &(core->intr_core_state);
 
     intr_state->irq_pending = 0;
-
 }
 
 
@@ -328,6 +449,11 @@ v3_intr_type_t v3_intr_pending(struct guest_info * info) {
        }
     }
 
+    // KCH: added for SWintr injection
+    if (intr_state->swintr_posted == 1) {
+        ret = V3_SOFTWARE_INTR;
+    }
+        
     v3_unlock_irqrestore(intr_state->irq_lock, irq_state);
 
     return ret;
@@ -402,9 +528,6 @@ intr_type_t v3_get_intr_type(struct guest_info * info) {
 */
 
 
-
-
-
 int v3_injecting_intr(struct guest_info * info, uint_t intr_num, v3_intr_type_t type) {
     struct v3_intr_core_state * intr_state = &(info->intr_core_state);
 
index 2de8b00..f10bed9 100644 (file)
@@ -506,6 +506,10 @@ static v3_op_type_t op_form_to_type(op_form_t form) {
        case MOV_2CR:
            return V3_OP_MOV2CR;
 
+    // KCH: for syscall interposition
+    case INT:
+        return V3_OP_INT;
+
 
        case MOV_MEM2_8:
        case MOV_MEM2:
index 1a80d18..9c0fc33 100644 (file)
@@ -443,6 +443,19 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins
 
 
                case XED_OPERAND_IMM0:
+                   {
+                v3_op->size = xed_decoded_inst_get_immediate_width(&xed_instr);
+
+                if (v3_op->size > 4) {
+                    PrintError("Unhandled 64 bit immediates\n");
+                    return -1;
+                }
+                v3_op->operand = xed_decoded_inst_get_unsigned_immediate(&xed_instr);
+
+                v3_op->type = IMM_OPERAND;
+
+                   }
+                   break;
                case XED_OPERAND_AGEN:
                case XED_OPERAND_PTR:
                case XED_OPERAND_RELBR:
@@ -581,7 +594,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins
 
            instr->third_operand.type = REG_OPERAND;
 
-           PrintDebug("Operand 3 mode: %s\n", xed_operand_action_enum_t2str(xed_operand_rw(op)));
+           PrintDebug("Operand 2 mode: %s\n", xed_operand_action_enum_t2str(xed_operand_rw(op)));
 
 
            if (xed_operand_read(op)) {
@@ -1270,6 +1283,10 @@ static v3_op_type_t get_opcode(xed_iform_enum_t iform) {
        case XED_IFORM_INVLPG_MEMb:
            return V3_OP_INVLPG;
 
+    // KCH
+    case XED_IFORM_INT_IMM:
+        return V3_OP_INT;
+
 
            /* Data Instructions */