if ((os_hooks) && (os_hooks)->malloc) { \
var = (os_hooks)->malloc(size); \
} \
+ if (!var) PrintError("MALLOC FAILURE. Memory LEAK!!\n"); \
var; \
})
})
/**
+ * list_first_entry - get the struct for the first entry
+ * @ptr: the list_head head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_first_entry(head, type, member) \
+({ \
+ type * first = NULL; \
+ if ((head)->next != (head)) { \
+ first = list_entry((head)->next, type, member); \
+ } \
+ first; \
+ })
+
+
+
+
+/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list.
uint32_t write_faults;
uint32_t flushes;
uint32_t mapped_pages;
+ uint32_t list_size;
#endif
// shadow pointers
int v3_get_vaddr_perms(struct guest_info * info, addr_t vaddr, pte32_t * guest_pte, pf_error_t * page_perms);
-addr_t v3_get_swapped_pg_addr(struct guest_info * info, pte32_t * shadow_pte, pte32_t * guest_pte);
+addr_t v3_get_swapped_pg_addr(struct guest_info * info, pte32_t * guest_pte);
+addr_t v3_map_swp_page(struct guest_info * info, pte32_t * shadow_pte, pte32_t * guest_pte, void * swp_page_ptr);
int v3_swap_flush(struct guest_info * info);
help
Includes the symbiotic ram based swap disk
+config SYM_SWAP2
+ bool "Symbiotic Swap disk v2"
+ default y
+ depends on SYMBIOTIC_SWAP && (LINUX_VIRTIO_BLOCK || IDE)
+ help
+ Includes the symbiotic ram based swap disk
+
+config DISK_MODEL
+ bool "Disk Performance Model"
+ default y
+ depends on LINUX_VIRTIO_BLOCK || IDE
+ help
+ Includes Performance model filter for disk operations
+
config CGA
bool "CGA"
default n
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_PIIX3) += piix3.o
obj-$(CONFIG_SYM_SWAP) += sym_swap.o
+obj-$(CONFIG_SYM_SWAP2) += sym_swap2.o
+obj-$(CONFIG_DISK_MODEL) += disk_model.o
obj-$(CONFIG_NE2K) += ne2k.o
drive_id->lba_enable = 1;
// Drive Capacity (28 bit LBA)
- drive_id->lba_capacity = drive->ops->get_capacity(drive->private_data);
+ drive_id->lba_capacity = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
// Drive Capacity (48 bit LBA)
- drive_id->lba_capacity_2 = drive->ops->get_capacity(drive->private_data);
+ drive_id->lba_capacity_2 = drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE;
// lower byte is the maximum multiple sector size...
}
return 0;
+
+
+
}
if ((lba_addr.addr + sect_cnt) >
- drive->ops->get_capacity(drive->private_data)) {
+ drive->ops->get_capacity(drive->private_data) / HD_SECTOR_SIZE) {
PrintError("IDE: request size exceeds disk capacity (lba=%d) (sect_cnt=%d) (ReadEnd=%d) (capacity=%p)\n",
lba_addr.addr, sect_cnt,
lba_addr.addr + (sect_cnt * HD_SECTOR_SIZE),
drive->num_sectors = 63;
drive->num_heads = 16;
- drive->num_cylinders = ops->get_capacity(private_data) / (drive->num_sectors * drive->num_heads);
+ drive->num_cylinders = (ops->get_capacity(private_data) / HD_SECTOR_SIZE) / (drive->num_sectors * drive->num_heads);
} else {
PrintError("invalid IDE drive type\n");
return -1;
}
+#include <palacios/vmm_telemetry.h>
static int key_event_handler(struct guest_info * info,
}
#endif
- else if (evt->scan_code == 0x42) { // F8 Sym test2
+ else if (evt->scan_code == 0x42) { // F8 debug toggle
extern int v3_dbg_enable;
PrintDebug("Toggling Debugging\n");
v3_dbg_enable ^= 1;
+ } else if (evt->scan_code == 0x41) { // F7 telemetry dump
+ v3_print_telemetry(info);
+
}
pbar->size = (uint16_t)~PCI_IO_BASE(max_val) + 1;
-
V3_Print("IO Bar with %d (%x) ports %x->%x\n", pbar->size, pbar->size, pbar->addr, pbar->addr + pbar->size);
// setup a set of null io hooks
}
}
-
-
// Initially the virtual bars match the physical ones
state->virt_bars[bar_num].type, state->virt_bars[bar_num].addr,
state->virt_bars[bar_num].size);
-
-
// Update the pci subsystem versions
*dst = bar_val;
static uint64_t blk_get_capacity(void * private_data) {
struct blk_state * blk = (struct blk_state *)private_data;
- PrintDebug("SymBlk: Getting Capacity %d\n", (uint32_t)(blk->capacity));
+ // PrintDebug("SymBlk: Getting Capacity %d\n", (uint32_t)(blk->capacity));
return blk->capacity;
}
static int blk_read(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data) {
struct blk_state * blk = (struct blk_state *)private_data;
+ // PrintDebug("TmpDisk Reading %d bytes to %p (lba=%p)\n", (uint32_t)num_bytes, buf, (void *)(addr_t)lba);
+
if (lba + num_bytes > blk->capacity) {
PrintError("TMPDISK Read past end of disk\n");
return -1;
static int blk_write(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data) {
struct blk_state * blk = (struct blk_state *)private_data;
+ // PrintDebug("TmpDisk Writing %d bytes to %p (lba=%p)\n", (uint32_t)num_bytes, buf, (void *)(addr_t)lba);
+
if (lba + num_bytes > blk->capacity) {
PrintError("TMPDISK Write past end of disk\n");
return -1;
rdtscll(info->time_state.cached_host_tsc);
- // guest_ctrl->TSC_OFFSET = info->time_state.guest_tsc - info->time_state.cached_host_tsc;
+ guest_ctrl->TSC_OFFSET = info->time_state.guest_tsc - info->time_state.cached_host_tsc;
v3_svm_launch((vmcb_t *)V3_PAddr(info->vmm_data), &(info->vm_regs), (vmcb_t *)host_vmcbs[info->cpu_id]);
#ifdef CONFIG_SYMBIOTIC_SWAP
if (is_swapped_pte32(guest_pte)) {
+
pf_error_t swap_perms;
+
+ /*
+ int sym_ret = v3_get_vaddr_perms(info, fault_addr, guest_pte, &swap_perms);
+ sym_ret = 0;
+ */
+ addr_t swp_pg_addr = 0;
+
+
+
#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
if (error_code.write == 0) {
info->swap_state.read_faults++;
}
#endif
- if (v3_get_vaddr_perms(info, fault_addr, guest_pte, &swap_perms) == -1) {
- PrintError("Error getting Swapped page permissions\n");
- return -1;
- }
+ swp_pg_addr = v3_get_swapped_pg_addr(info, guest_pte);
- // swap_perms.write == 1 || error_code.write == 0
- // swap_perms.user == 0 || error_code.user == 1
+ if (swp_pg_addr != 0) {
+ PrintDebug("Swapped page address=%p\n", (void *)swp_pg_addr);
- // This checks for permissions violations that require a guest PF injection
- if ( (swap_perms.present == 1) &&
- ( (swap_perms.write == 1) ||
- (error_code.write == 0) ) &&
- ( (swap_perms.user == 1) ||
- (error_code.user == 0) ) ) {
- addr_t swp_pg_addr = 0;
+ /*
+ if (info->cpl == 0) {
+ PrintError("Swapped Page fault in kernel mode.... bad...\n");
+ goto inject;
+ }
+ */
- PrintDebug("Page fault on swapped out page (vaddr=%p) (pte=%x) (error_code=%x)\n",
- (void *)fault_addr, *(uint32_t *)guest_pte, *(uint32_t *)&error_code);
+ int sym_ret = v3_get_vaddr_perms(info, fault_addr, guest_pte, &swap_perms);
- swp_pg_addr = v3_get_swapped_pg_addr(info, shadow_pte, guest_pte);
+ if (sym_ret == -1) {
+ PrintError("Symcall error...\n");
+ return -1;
+ } else if (sym_ret == 0) {
- PrintDebug("Swapped page address=%p\n", (void *)swp_pg_addr);
- if (swp_pg_addr != 0) {
- shadow_pte->writable = swap_perms.write;
- shadow_pte->user_page = swap_perms.user;
-
- shadow_pte->write_through = 0;
- shadow_pte->cache_disable = 0;
- shadow_pte->global_page = 0;
-
- shadow_pte->present = 1;
+ if (swap_perms.present == 0) {
+ PrintError("Nonpresent swapped page\n");
+ }
- shadow_pte->page_base_addr = swp_pg_addr;
+ // swap_perms.write ==1 || error_code.write == 0
+ // swap_perms.user == 0 || error_code.user == 1
+ // This checks for permissions violations that require a guest PF injection
+ if ( (swap_perms.present == 1) &&
+ ( (swap_perms.write == 1) ||
+ (error_code.write == 0) ) &&
+ ( (swap_perms.user == 1) ||
+ (error_code.user == 0) ) ) {
+ addr_t swp_pg_pa = 0;
+
+ swp_pg_pa = v3_map_swp_page(info, shadow_pte, guest_pte, (void *)swp_pg_addr);
+
+ PrintDebug("Page fault on swapped out page (vaddr=%p) (pte=%x) (error_code=%x)\n",
+ (void *)fault_addr, *(uint32_t *)guest_pte, *(uint32_t *)&error_code);
+
+ shadow_pte->writable = swap_perms.write;
+ shadow_pte->user_page = swap_perms.user;
+
+ shadow_pte->write_through = 0;
+ shadow_pte->cache_disable = 0;
+ shadow_pte->global_page = 0;
+
+ shadow_pte->present = 1;
+
+ shadow_pte->page_base_addr = swp_pg_pa;
+
#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
- info->swap_state.mapped_pages++;
+ info->swap_state.mapped_pages++;
#endif
-
- return 0;
+ // PrintError("Swap fault handled\n");
+ return 0;
+ }
}
} else {
PrintDebug("Not a sym swappable page\n");
}
+
}
#endif
-
+ // inject:
if (inject_guest_pf(info, fault_addr, error_code) == -1) {
PrintError("Could not inject guest page fault for vaddr %p\n", (void *)fault_addr);
V3_Print("%s\tWrite faults=%d\n", hdr, swap_state->write_faults);
V3_Print("%s\tMapped Pages=%d\n", hdr, swap_state->mapped_pages);
V3_Print("%s\tFlushes=%d\n", hdr, swap_state->flushes);
+ V3_Print("%s\tlist size=%d\n", hdr, swap_state->list_size);
}
#endif
// V3_Print("page perms = %x\n", *(uint32_t *)page_perms);
+ if (vaddr == 0) {
+ return 1;
+ }
+
return 0;
}
-addr_t v3_get_swapped_pg_addr(struct guest_info * info, pte32_t * shadow_pte, pte32_t * guest_pte) {
- struct list_head * shdw_ptr_list = NULL;
+addr_t v3_get_swapped_pg_addr(struct guest_info * info, pte32_t * guest_pte) {
struct v3_sym_swap_state * swap_state = &(info->swap_state);
- struct shadow_pointer * shdw_ptr = NULL;
- void * swp_page_ptr = NULL;
int dev_index = get_dev_index(guest_pte);
struct v3_swap_dev * swp_dev = &(swap_state->devs[dev_index]);
+
if (! swp_dev->present ) {
return 0;
}
+ return (addr_t)swp_dev->ops->get_swap_entry(get_pg_index(guest_pte), swp_dev->private_data);
+}
+
+
+addr_t v3_map_swp_page(struct guest_info * info, pte32_t * shadow_pte, pte32_t * guest_pte, void * swp_page_ptr) {
+ struct list_head * shdw_ptr_list = NULL;
+ struct v3_sym_swap_state * swap_state = &(info->swap_state);
+ struct shadow_pointer * shdw_ptr = NULL;
- swp_page_ptr = swp_dev->ops->get_swap_entry(get_pg_index(guest_pte), swp_dev->private_data);
if (swp_page_ptr == NULL) {
- PrintError("Swapped out page not found on swap device\n");
+ // PrintError("Swapped out page not found on swap device\n");
return 0;
}
if (shdw_ptr_list == NULL) {
shdw_ptr_list = (struct list_head *)V3_Malloc(sizeof(struct list_head *));
+ swap_state->list_size++;
INIT_LIST_HEAD(shdw_ptr_list);
v3_htable_insert(swap_state->shdw_ptr_ht, (addr_t)*(uint32_t *)guest_pte, (addr_t)shdw_ptr_list);
}
shdw_ptr = (struct shadow_pointer *)V3_Malloc(sizeof(struct shadow_pointer));
+ if (shdw_ptr == NULL) {
+ PrintError("MEMORY LEAK\n");
+ telemetry_cb(info, NULL, "");
+ return 0;
+ }
+
shdw_ptr->shadow_pte = shadow_pte;
shdw_ptr->guest_pte = *(uint32_t *)guest_pte;
shdw_ptr->pg_index = get_pg_index(guest_pte);
return PAGE_BASE_ADDR((addr_t)V3_PAddr(swp_page_ptr));
}
+
+
+
+/*
+int v3_is_mapped_fault(struct guest_info * info, pte32_t * shadow_pte, pte32_t * guest_pte) {
+ struct list_head * shdw_ptr_list = NULL;
+
+ shdw_ptr_list = (struct list_head * )v3_htable_search(swap_state->shdw_ptr_ht, *(addr_t *)&(guest_pte));
+
+
+ if (shdw_ptr_list != NULL) {
+ PrintError("We faulted on a mapped in page....\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+*/
update_irq_entry_state(info);
#endif
+ {
+ addr_t guest_cr3;
+ vmcs_read(VMCS_GUEST_CR3, &guest_cr3);
+ vmcs_write(VMCS_GUEST_CR3, guest_cr3);
+ }
rdtscll(info->time_state.cached_host_tsc);
/* Update guest state */
v3_vmx_save_vmcs(info);
+ // info->cpl = info->segments.cs.selector & 0x3;
+
info->mem_mode = v3_get_vm_mem_mode(info);
info->cpu_mode = v3_get_vm_cpu_mode(info);