From: Jack Lange Date: Sun, 26 Apr 2009 18:58:50 +0000 (-0500) Subject: updated IO and MSRs to allow hooking/unhooking dynamic at runtime X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=29e825c5f095066bbb5ebbec5a5af1419d883264 updated IO and MSRs to allow hooking/unhooking dynamic at runtime --- diff --git a/palacios/include/palacios/svm_io.h b/palacios/include/palacios/svm_io.h index 4d691b4..81dec75 100644 --- a/palacios/include/palacios/svm_io.h +++ b/palacios/include/palacios/svm_io.h @@ -39,10 +39,12 @@ struct svm_io_info { uint_t addr32 : 1 PACKED; // 32 bit addr uint_t addr64 : 1 PACKED; // 64 bit addr uint_t rsvd2 : 6 PACKED; // Should be Zero - ushort_t port PACKED; // port number + uint16_t port PACKED; // port number }; +int v3_init_svm_io_map(struct guest_info * info); + int v3_handle_svm_io_in(struct guest_info * info); int v3_handle_svm_io_ins(struct guest_info * info); int v3_handle_svm_io_out(struct guest_info * info); diff --git a/palacios/include/palacios/svm_msr.h b/palacios/include/palacios/svm_msr.h index 30975f1..6972afd 100644 --- a/palacios/include/palacios/svm_msr.h +++ b/palacios/include/palacios/svm_msr.h @@ -25,7 +25,7 @@ #include -addr_t v3_init_svm_msr_map(struct guest_info * info); +int v3_init_svm_msr_map(struct guest_info * info); int v3_handle_msr_write(struct guest_info * info); diff --git a/palacios/include/palacios/vm_guest.h b/palacios/include/palacios/vm_guest.h index 63decc2..1f0293f 100644 --- a/palacios/include/palacios/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -138,7 +138,7 @@ struct guest_info { // This structure is how we get exceptions for the guest struct v3_excp_state excp_state; - v3_io_map_t io_map; + struct v3_io_map io_map; struct v3_msr_map msr_map; diff --git a/palacios/include/palacios/vmm_io.h b/palacios/include/palacios/vmm_io.h index 20dd301..e2f4be5 100644 --- a/palacios/include/palacios/vmm_io.h +++ b/palacios/include/palacios/vmm_io.h @@ -27,7 +27,7 @@ #include #include -typedef struct rb_root v3_io_map_t; + struct guest_info; @@ -39,8 +39,8 @@ void v3_init_io_map(struct guest_info * info); /* External API */ int v3_hook_io_port(struct guest_info * info, uint_t port, - int (*read)(ushort_t port, void * dst, uint_t length, void * priv_data), - int (*write)(ushort_t port, void * src, uint_t length, void * priv_data), + int (*read)(uint16_t port, void * dst, uint_t length, void * priv_data), + int (*write)(uint16_t port, void * src, uint_t length, void * priv_data), void * priv_data); int v3_unhook_io_port(struct guest_info * info, uint_t port); @@ -48,14 +48,17 @@ int v3_unhook_io_port(struct guest_info * info, uint_t port); + struct v3_io_hook { - ushort_t port; + uint16_t port; // Reads data into the IO port (IN, INS) - int (*read)(ushort_t port, void * dst, uint_t length, void * priv_data); + int (*read)(uint16_t port, void * dst, uint_t length, void * priv_data); // Writes data from the IO port (OUT, OUTS) - int (*write)(ushort_t port, void * src, uint_t length, void * priv_data); + int (*write)(uint16_t port, void * src, uint_t length, void * priv_data); + + void * priv_data; @@ -63,6 +66,13 @@ struct v3_io_hook { }; +struct v3_io_map { + struct rb_root map; + + int (*update_map)(struct guest_info * info, uint16_t port, int hook_read, int hook_write); + + void * arch_data; +}; struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint_t port); @@ -72,14 +82,14 @@ void v3_print_io_map(struct guest_info * info); -void v3_outb(ushort_t port, uchar_t value); -uchar_t v3_inb(ushort_t port); +void v3_outb(uint16_t port, uint8_t value); +uint8_t v3_inb(uint16_t port); -void v3_outw(ushort_t port, ushort_t value); -ushort_t v3_inw(ushort_t port); +void v3_outw(uint16_t port, uint16_t value); +uint16_t v3_inw(uint16_t port); -void v3_outdw(ushort_t port, uint_t value); -uint_t v3_indw(ushort_t port); +void v3_outdw(uint16_t port, uint_t value); +uint_t v3_indw(uint16_t port); diff --git a/palacios/include/palacios/vmm_msr.h b/palacios/include/palacios/vmm_msr.h index 00e1425..ef66a60 100644 --- a/palacios/include/palacios/vmm_msr.h +++ b/palacios/include/palacios/vmm_msr.h @@ -28,6 +28,7 @@ struct guest_info; + struct v3_msr { union { @@ -41,7 +42,6 @@ struct v3_msr { } __attribute__((packed)); - typedef struct v3_msr v3_msr_t; struct v3_msr_hook { @@ -62,6 +62,10 @@ struct v3_msr_hook; struct v3_msr_map { uint_t num_hooks; struct list_head hook_list; + + int (*update_map)(struct guest_info * info, uint_t msr, int hook_read, int hook_write); + void * arch_data; + }; diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index d617b61..c577a7d 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -42,6 +42,7 @@ #include #include +#include extern void v3_stgi(); @@ -164,37 +165,16 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) { guest_state->dr7 = 0x0000000000000400LL; - if ( !RB_EMPTY_ROOT(&(vm_info->io_map)) ) { - struct v3_io_hook * iter; - struct rb_node * io_node = v3_rb_first(&(vm_info->io_map)); - addr_t io_port_bitmap; - int i = 0; - - io_port_bitmap = (addr_t)V3_VAddr(V3_AllocPages(3)); - memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3); - - ctrl_area->IOPM_BASE_PA = (addr_t)V3_PAddr((void *)io_port_bitmap); - - //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap); - - do { - iter = rb_entry(io_node, struct v3_io_hook, tree_node); - - ushort_t port = iter->port; - uchar_t * bitmap = (uchar_t *)io_port_bitmap; - //PrintDebug("%d: Hooking Port %d\n", i, port); + v3_init_svm_io_map(vm_info); + ctrl_area->IOPM_BASE_PA = (addr_t)V3_PAddr(vm_info->io_map.arch_data); + ctrl_area->instrs.IOIO_PROT = 1; - bitmap += (port / 8); - // PrintDebug("Setting Bit for port 0x%x\n", port); - *bitmap |= 1 << (port % 8); - i++; - } while ((io_node = v3_rb_next(io_node))); - //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2); + v3_init_svm_msr_map(vm_info); + ctrl_area->MSRPM_BASE_PA = (addr_t)V3_PAddr(vm_info->msr_map.arch_data); + ctrl_area->instrs.MSR_PROT = 1; - ctrl_area->instrs.IOIO_PROT = 1; - } PrintDebug("Exiting on interrupts\n"); @@ -267,11 +247,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) { guest_state->g_pat = 0x7040600070406ULL; } - if (vm_info->msr_map.num_hooks > 0) { - PrintDebug("Hooking %d msrs\n", vm_info->msr_map.num_hooks); - ctrl_area->MSRPM_BASE_PA = v3_init_svm_msr_map(vm_info); - ctrl_area->instrs.MSR_PROT = 1; - } + /* Safety locations for fs/gs */ // vm_info->fs = 0; @@ -285,17 +261,17 @@ static int init_svm_guest(struct guest_info *info, struct v3_vm_config * config_ PrintDebug("Allocating VMCB\n"); info->vmm_data = (void*)Allocate_VMCB(); + Init_VMCB_BIOS((vmcb_t*)(info->vmm_data), info); + v3_config_devices(info, config_ptr); PrintDebug("Initializing VMCB (addr=%p)\n", (void *)info->vmm_data); - Init_VMCB_BIOS((vmcb_t*)(info->vmm_data), info); - - + info->run_state = VM_STOPPED; // info->rip = 0; - + info->vm_regs.rdi = 0; info->vm_regs.rsi = 0; info->vm_regs.rbp = 0; @@ -304,7 +280,7 @@ static int init_svm_guest(struct guest_info *info, struct v3_vm_config * config_ info->vm_regs.rdx = 0; info->vm_regs.rcx = 0; info->vm_regs.rax = 0; - + return 0; } diff --git a/palacios/src/palacios/svm_io.c b/palacios/src/palacios/svm_io.c index 12610a1..4c85ec7 100644 --- a/palacios/src/palacios/svm_io.c +++ b/palacios/src/palacios/svm_io.c @@ -29,6 +29,29 @@ #endif +static int update_map(struct guest_info * info, uint16_t port, int hook_read, int hook_write) { + uchar_t * bitmap = (uint8_t *)(info->io_map.arch_data);; + int major = port / 8; + int minor = port % 8; + + if ((hook_read == 0) && (hook_write == 0)) { + *(bitmap + major) &= ~(0x1 << minor); + } else { + *(bitmap + major) |= (0x1 << minor); + } + + return 0; +} + + +int v3_init_svm_io_map(struct guest_info * info) { + info->io_map.update_map = update_map; + + info->io_map.arch_data = V3_VAddr(V3_AllocPages(3)); + memset(info->io_map.arch_data, 0, PAGE_SIZE_4KB * 3); + + return 0; +} diff --git a/palacios/src/palacios/svm_msr.c b/palacios/src/palacios/svm_msr.c index ee14a14..dcc653e 100644 --- a/palacios/src/palacios/svm_msr.c +++ b/palacios/src/palacios/svm_msr.c @@ -53,38 +53,38 @@ static int get_bitmap_index(uint_t msr) { } +static int update_map(struct guest_info * info, uint_t msr, int hook_reads, int hook_writes) { + int index = get_bitmap_index(msr); + uint_t major = index / 4; + uint_t minor = (index % 4) * 2; + uchar_t val = 0; + uchar_t mask = 0x3; + uint8_t * bitmap = (uint8_t *)(info->msr_map.arch_data); + + if (hook_reads) { + val |= 0x1; + } + + if (hook_writes) { + val |= 0x2; + } -addr_t v3_init_svm_msr_map(struct guest_info * info) { - uchar_t * msr_bitmap = (uchar_t*)V3_VAddr(V3_AllocPages(2)); - struct v3_msr_map * msr_map = &(info->msr_map); - struct v3_msr_hook * hook = NULL; - - - memset(msr_bitmap, 0, PAGE_SIZE * 2); - - list_for_each_entry(hook, &(msr_map->hook_list), link) { - int index = get_bitmap_index(hook->msr); - uint_t byte_offset = index / 4; - uint_t bit_offset = (index % 4) * 2; - uchar_t val = 0; - uchar_t mask = ~0x3; - - if (hook->read) { - val |= 0x1; - } + *(bitmap + major) &= ~(mask << minor); + *(bitmap + major) |= (val << minor); + + return 0; +} - if (hook->write) { - val |= 0x2; - } - val = val << bit_offset; - mask = mask << bit_offset; +int v3_init_svm_msr_map(struct guest_info * info) { + struct v3_msr_map * msr_map = &(info->msr_map); + + msr_map->update_map = update_map; - *(msr_bitmap + byte_offset) &= mask; - *(msr_bitmap + byte_offset) |= val; - } + msr_map->arch_data = V3_VAddr(V3_AllocPages(2)); + memset(msr_map->arch_data, 0, PAGE_SIZE_4KB * 2); - return (addr_t)V3_PAddr(msr_bitmap); + return 0; } diff --git a/palacios/src/palacios/vmm_intr.c b/palacios/src/palacios/vmm_intr.c index 865a9fd..875534a 100644 --- a/palacios/src/palacios/vmm_intr.c +++ b/palacios/src/palacios/vmm_intr.c @@ -177,21 +177,14 @@ int v3_raise_irq(struct guest_info * info, int irq) { int v3_intr_pending(struct guest_info * info) { struct v3_intr_state * intr_state = &(info->intr_state); struct intr_controller * ctrl = NULL; - struct rflags * flags = (struct rflags *)&(info->ctrl_regs.rflags); // PrintDebug("[intr_pending]\n"); - // Check if the guest has interrupts enabled - if (flags->intr == 0) { - //return 0; - } - list_for_each_entry(ctrl, &(intr_state->controller_list), ctrl_node) { if (ctrl->ctrl_ops->intr_pending(ctrl->priv_data) == 1) { return 1; } } - return 0; } diff --git a/palacios/src/palacios/vmm_io.c b/palacios/src/palacios/vmm_io.c index 9756eb4..9f44fbd 100644 --- a/palacios/src/palacios/vmm_io.c +++ b/palacios/src/palacios/vmm_io.c @@ -30,19 +30,23 @@ #endif -static int default_write(ushort_t port, void *src, uint_t length, void * priv_data); -static int default_read(ushort_t port, void * dst, uint_t length, void * priv_data); +static int default_write(uint16_t port, void *src, uint_t length, void * priv_data); +static int default_read(uint16_t port, void * dst, uint_t length, void * priv_data); void v3_init_io_map(struct guest_info * info) { - info->io_map.rb_node = NULL; + + info->io_map.map.rb_node = NULL; + info->io_map.arch_data = NULL; + info->io_map.update_map = NULL; + } static inline struct v3_io_hook * __insert_io_hook(struct guest_info * info, struct v3_io_hook * hook) { - struct rb_node ** p = &(info->io_map.rb_node); + struct rb_node ** p = &(info->io_map.map.rb_node); struct rb_node * parent = NULL; struct v3_io_hook * tmp_hook = NULL; @@ -71,14 +75,14 @@ static inline struct v3_io_hook * insert_io_hook(struct guest_info * info, struc return ret; } - v3_rb_insert_color(&(hook->tree_node), &(info->io_map)); + v3_rb_insert_color(&(hook->tree_node), &(info->io_map.map)); return NULL; } struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint_t port) { - struct rb_node * n = info->io_map.rb_node; + struct rb_node * n = info->io_map.map.rb_node; struct v3_io_hook * hook = NULL; while (n) { @@ -102,8 +106,8 @@ struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint_t port) { int v3_hook_io_port(struct guest_info * info, uint_t port, - int (*read)(ushort_t port, void * dst, uint_t length, void * priv_data), - int (*write)(ushort_t port, void * src, uint_t length, void * priv_data), + int (*read)(uint16_t port, void * dst, uint_t length, void * priv_data), + int (*write)(uint16_t port, void * src, uint_t length, void * priv_data), void * priv_data) { struct v3_io_hook * io_hook = (struct v3_io_hook *)V3_Malloc(sizeof(struct v3_io_hook)); @@ -129,6 +133,15 @@ int v3_hook_io_port(struct guest_info * info, uint_t port, return -1; } + + if (info->io_map.update_map(info, port, + ((read == NULL) ? 0 : 1), + ((write == NULL) ? 0 : 1)) == -1) { + V3_Free(io_hook); + return -1; + } + + return 0; } @@ -139,7 +152,10 @@ int v3_unhook_io_port(struct guest_info * info, uint_t port) { return -1; } - v3_rb_erase(&(hook->tree_node), &(info->io_map)); + v3_rb_erase(&(hook->tree_node), &(info->io_map.map)); + + // set the arch map to default (this should be 1, 1) + info->io_map.update_map(info, port, 0, 0); V3_Free(hook); @@ -153,7 +169,7 @@ int v3_unhook_io_port(struct guest_info * info, uint_t port) { void v3_print_io_map(struct guest_info * info) { struct v3_io_hook * tmp_hook = NULL; - struct rb_node * node = v3_rb_first(&(info->io_map)); + struct rb_node * node = v3_rb_first(&(info->io_map.map)); PrintDebug("VMM IO Map\n"); @@ -171,7 +187,7 @@ void v3_print_io_map(struct guest_info * info) { /* * Write a byte to an I/O port. */ -void v3_outb(ushort_t port, uchar_t value) { +void v3_outb(uint16_t port, uint8_t value) { __asm__ __volatile__ ( "outb %b0, %w1" : @@ -182,8 +198,8 @@ void v3_outb(ushort_t port, uchar_t value) { /* * Read a byte from an I/O port. */ -uchar_t v3_inb(ushort_t port) { - uchar_t value; +uint8_t v3_inb(uint16_t port) { + uint8_t value; __asm__ __volatile__ ( "inb %w1, %b0" @@ -197,7 +213,7 @@ uchar_t v3_inb(ushort_t port) { /* * Write a word to an I/O port. */ -void v3_outw(ushort_t port, ushort_t value) { +void v3_outw(uint16_t port, uint16_t value) { __asm__ __volatile__ ( "outw %w0, %w1" : @@ -208,8 +224,8 @@ void v3_outw(ushort_t port, ushort_t value) { /* * Read a word from an I/O port. */ -ushort_t v3_inw(ushort_t port) { - ushort_t value; +uint16_t v3_inw(uint16_t port) { + uint16_t value; __asm__ __volatile__ ( "inw %w1, %w0" @@ -223,7 +239,7 @@ ushort_t v3_inw(ushort_t port) { /* * Write a double word to an I/O port. */ -void v3_outdw(ushort_t port, uint_t value) { +void v3_outdw(uint16_t port, uint_t value) { __asm__ __volatile__ ( "outl %0, %1" : @@ -234,7 +250,7 @@ void v3_outdw(ushort_t port, uint_t value) { /* * Read a double word from an I/O port. */ -uint_t v3_indw(ushort_t port) { +uint_t v3_indw(uint16_t port) { uint_t value; __asm__ __volatile__ ( @@ -250,7 +266,7 @@ uint_t v3_indw(ushort_t port) { /* FIX ME */ -static int default_write(ushort_t port, void *src, uint_t length, void * priv_data) { +static int default_write(uint16_t port, void *src, uint_t length, void * priv_data) { /* if (length == 1) { @@ -276,10 +292,10 @@ static int default_write(ushort_t port, void *src, uint_t length, void * priv_da return 0; } -static int default_read(ushort_t port, void * dst, uint_t length, void * priv_data) { +static int default_read(uint16_t port, void * dst, uint_t length, void * priv_data) { /* - uchar_t value; + uint8_t value; __asm__ __volatile__ ( "inb %w1, %b0" diff --git a/palacios/src/palacios/vmm_msr.c b/palacios/src/palacios/vmm_msr.c index 105bfe6..5fe5ffd 100644 --- a/palacios/src/palacios/vmm_msr.c +++ b/palacios/src/palacios/vmm_msr.c @@ -28,6 +28,9 @@ void v3_init_msr_map(struct guest_info * info) { INIT_LIST_HEAD(&(msr_map->hook_list)); msr_map->num_hooks = 0; + + msr_map->arch_data = NULL; + msr_map->update_map = NULL; } @@ -40,6 +43,7 @@ int v3_hook_msr(struct guest_info * info, uint_t msr, struct v3_msr_hook * hook = NULL; hook = (struct v3_msr_hook *)V3_Malloc(sizeof(struct v3_msr_hook)); + if (hook == NULL) { PrintError("Could not allocate msr hook for MSR %d\n", msr); return -1; @@ -54,6 +58,9 @@ int v3_hook_msr(struct guest_info * info, uint_t msr, list_add(&(hook->link), &(msr_map->hook_list)); + msr_map->update_map(info, msr, + (read == NULL) ? 0 : 1, + (write == NULL) ? 0 : 1); return 0; }