2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <palacios/vmm_symspy.h>
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_msr.h>
23 #include <palacios/vm_guest.h>
24 #include <palacios/vmm_sprintf.h>
26 #define SYMSPY_GLOBAL_MSR 0x534
27 #define SYMSPY_LOCAL_MSR 0x535
30 static int symspy_msr_read(struct guest_info * core, uint_t msr,
31 struct v3_msr * dst, void * priv_data) {
32 struct v3_symspy_global_state * global_state = &(core->vm_info->sym_vm_state.symspy_state);
33 struct v3_symspy_local_state * local_state = &(core->sym_core_state.symspy_state);
36 case SYMSPY_GLOBAL_MSR:
37 dst->value = global_state->global_guest_pa;
39 case SYMSPY_LOCAL_MSR:
40 dst->value = local_state->local_guest_pa;
50 static int symspy_msr_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
52 if (msr == SYMSPY_GLOBAL_MSR) {
53 struct v3_symspy_global_state * global_state = &(core->vm_info->sym_vm_state.symspy_state);
55 PrintDebug(core->vm_info, core, "Symbiotic Glbal MSR write for page %p\n", (void *)(addr_t)src.value);
57 if (global_state->active == 1) {
59 struct v3_mem_region * old_reg = v3_get_mem_region(core->vm_info, core->vcpu_id,
60 (addr_t)global_state->global_guest_pa);
62 if (old_reg == NULL) {
63 PrintError(core->vm_info, core, "Could not find previously active symbiotic page (%p)\n",
64 (void *)(addr_t)global_state->global_guest_pa);
68 v3_delete_mem_region(core->vm_info, old_reg);
71 global_state->global_guest_pa = src.value;
72 global_state->global_guest_pa &= ~0xfffLL;
74 global_state->active = 1;
77 v3_add_shadow_mem(core->vm_info, V3_MEM_CORE_ANY, (addr_t)global_state->global_guest_pa,
78 (addr_t)(global_state->global_guest_pa + PAGE_SIZE_4KB - 1),
79 global_state->global_page_pa);
80 } else if (msr == SYMSPY_LOCAL_MSR) {
81 struct v3_symspy_local_state * local_state = &(core->sym_core_state.symspy_state);
83 PrintDebug(core->vm_info, core, "Symbiotic Local MSR write for page %p\n", (void *)(addr_t)src.value);
85 if (local_state->active == 1) {
87 struct v3_mem_region * old_reg = v3_get_mem_region(core->vm_info, core->vcpu_id,
88 (addr_t)local_state->local_guest_pa);
90 if (old_reg == NULL) {
91 PrintError(core->vm_info, core, "Could not find previously active symbiotic page (%p)\n",
92 (void *)(addr_t)local_state->local_guest_pa);
96 v3_delete_mem_region(core->vm_info, old_reg);
99 local_state->local_guest_pa = src.value;
100 local_state->local_guest_pa &= ~0xfffLL;
102 local_state->active = 1;
105 v3_add_shadow_mem(core->vm_info, core->vcpu_id, (addr_t)local_state->local_guest_pa,
106 (addr_t)(local_state->local_guest_pa + PAGE_SIZE_4KB - 1),
107 local_state->local_page_pa);
109 PrintError(core->vm_info, core, "Invalid Symbiotic MSR write (0x%x)\n", msr);
118 int v3_init_symspy_vm(struct v3_vm_info * vm, struct v3_symspy_global_state * state) {
120 state->global_page_pa = (addr_t)V3_AllocPages(1);
121 if (!state->global_page_pa) {
122 PrintError(vm, VCORE_NONE, "Cannot allocate page\n");
126 state->sym_page = (struct v3_symspy_global_page *)V3_VAddr((void *)state->global_page_pa);
127 memset(state->sym_page, 0, PAGE_SIZE_4KB);
129 memcpy(&(state->sym_page->magic), "V3V", 3);
131 v3_hook_msr(vm, SYMSPY_LOCAL_MSR, symspy_msr_read, symspy_msr_write, NULL);
132 v3_hook_msr(vm, SYMSPY_GLOBAL_MSR, symspy_msr_read, symspy_msr_write, NULL);
139 int v3_init_symspy_core(struct guest_info * core, struct v3_symspy_local_state * state) {
140 state->local_page_pa = (addr_t)V3_AllocPages(1);
142 if (!state->local_page_pa) {
143 PrintError(core->vm_info, core, "Cannot allocate page\n");
146 state->local_page = (struct v3_symspy_local_page *)V3_VAddr((void *)state->local_page_pa);
147 memset(state->local_page, 0, PAGE_SIZE_4KB);
149 snprintf((uint8_t *)&(state->local_page->magic), 8, "V3V.%d", core->vcpu_id);
156 int v3_sym_map_pci_passthrough(struct v3_vm_info * vm, uint_t bus, uint_t dev, uint_t fn) {
157 struct v3_symspy_global_state * global_state = &(vm->sym_vm_state.symspy_state);
158 uint_t dev_index = (bus << 8) + (dev << 3) + fn;
159 uint_t major = dev_index / 8;
160 uint_t minor = dev_index % 8;
163 PrintError(vm, VCORE_NONE, "Invalid PCI bus %d\n", bus);
167 PrintDebug(vm, VCORE_NONE, "Setting passthrough pci map for index=%d\n", dev_index);
169 global_state->sym_page->pci_pt_map[major] |= 0x1 << minor;
171 PrintDebug(vm, VCORE_NONE, "pt_map entry=%x\n", global_state->sym_page->pci_pt_map[major]);
173 PrintDebug(vm, VCORE_NONE, "pt map vmm addr=%p\n", global_state->sym_page->pci_pt_map);
178 int v3_sym_unmap_pci_passthrough(struct v3_vm_info * vm, uint_t bus, uint_t dev, uint_t fn) {
179 struct v3_symspy_global_state * global_state = &(vm->sym_vm_state.symspy_state);
180 uint_t dev_index = (bus << 8) + (dev << 3) + fn;
181 uint_t major = dev_index / 8;
182 uint_t minor = dev_index % 8;
185 PrintError(vm, VCORE_NONE, "Invalid PCI bus %d\n", bus);
189 global_state->sym_page->pci_pt_map[major] &= ~(0x1 << minor);
195 struct v3_symspy_global_page * v3_sym_get_symspy_vm(struct v3_vm_info * vm) {
196 return vm->sym_vm_state.symspy_state.sym_page;
199 struct v3_symspy_local_page * v3_sym_get_symspy_core(struct guest_info * core) {
200 return core->sym_core_state.symspy_state.local_page;