Enable Symbiotic module loading
-config SYMBIOTIC_SWAP
- bool "Symbiotic Swap"
+config SWAPBYPASS
+ bool "SwapBypass"
default n
depends on SYMBIOTIC && SYMCALL && EXPERIMENTAL
help
- This enables the symbiotic swap architecture
+ This enables the SwapBypass architecture
-config SYMBIOTIC_SWAP_TELEMETRY
- bool "Enable Symbiotic Swap Telemetry"
+config SWAPBYPASS_TELEMETRY
+ bool "Enable SwapBypass Telemetry"
default n
- depends on TELEMETRY && SYMBIOTIC_SWAP
+ depends on TELEMETRY && SWAPBYPASS
help
- Enable the telemetry information for the symbiotic swap subsystem
+ Enable the telemetry information for the SwapBypass subsystem
endmenu
#include <palacios/vmm_telemetry.h>
#endif
-#ifdef CONFIG_SYMBIOTIC_SWAP
-#include <palacios/vmm_sym_swap.h>
-#endif
struct v3_intr_state;
-#ifdef CONFIG_SYMBIOTIC_SWAP
-struct v3_sym_swap_state;
-#endif
#ifdef CONFIG_SYMBIOTIC
// Symbiotic state
struct v3_sym_vm_state sym_vm_state;
-#ifdef CONFIG_SYMBIOTIC_SWAP
- struct v3_sym_swap_state swap_state;
-#endif
#endif
--- /dev/null
+/*
+ * 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) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __VMM_SWAPBYPASS_H__
+#define __VMM_SWAPBYPASS_H__
+
+#ifdef __V3VEE__
+
+#include <palacios/vmm_types.h>
+
+
+struct v3_swap_ops {
+ void * (*get_swap_entry)(uint32_t pg_index, void * private_data);
+};
+
+
+
+
+int v3_register_swap_disk(struct v3_vm_info * vm, int dev_index,
+ struct v3_swap_ops * ops, void * private_data);
+
+int v3_swap_in_notify(struct v3_vm_info * vm, int pg_index, int dev_index);
+
+
+int v3_swap_flush(struct v3_vm_info * vm);
+
+
+
+#endif
+#endif
+++ /dev/null
-/*
- * 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) 2008, Jack Lange <jarusl@cs.northwestern.edu>
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software. You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#ifndef __VMM_SYM_SWAP_H__
-#define __VMM_SYM_SWAP_H__
-
-#ifdef __V3VEE__
-
-#include <palacios/vmm_types.h>
-#include <palacios/vmm_paging.h>
-#include <palacios/vmm_hashtable.h>
-
-
-struct v3_swap_ops {
- void * (*get_swap_entry)(uint32_t pg_index, void * private_data);
-};
-
-
-struct v3_swap_dev {
- uint8_t present;
-
- struct v3_swap_ops * ops;
-
- void * private_data;
-};
-
-
-struct v3_sym_swap_state {
- struct v3_swap_dev devs[256];
-
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
- uint32_t read_faults;
- uint32_t write_faults;
- uint32_t flushes;
- uint32_t mapped_pages;
- uint32_t list_size;
-#endif
-
- // shadow pointers
- struct hashtable * shdw_ptr_ht;
-};
-
-// Present = 0 and Dirty = 0
-// fixme
-static inline int is_swapped_pte32(pte32_t * pte) {
- return ((pte->present == 0) && (*(uint32_t *)pte != 0));
-}
-
-
-
-int v3_init_sym_swap(struct v3_vm_info * vm);
-
-int v3_register_swap_disk(struct v3_vm_info * vm, int dev_index,
- struct v3_swap_ops * ops, void * private_data);
-
-int v3_swap_in_notify(struct v3_vm_info * vm, int pg_index, int dev_index);
-
-
-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 v3_vm_info * vm, pte32_t * guest_pte);
-addr_t v3_map_swp_page(struct v3_vm_info * vm, pte32_t * shadow_pte, pte32_t * guest_pte, void * swp_page_ptr);
-
-int v3_swap_flush(struct v3_vm_info * vm);
-
-
-
-#endif
-#endif
help
Includes the temporary RAM disk
-config SYM_SWAP
- bool "Symbiotic Swap disk"
+config SWAPBYPASS_DISK_CACHE
+ bool "SwapBypass disk cache"
default y
- depends on SYMBIOTIC_SWAP && (LINUX_VIRTIO_BLOCK || IDE)
+ depends on SWAPBYPASS && (LINUX_VIRTIO_BLOCK || IDE)
help
- Includes the symbiotic ram based swap disk
+ Includes the SwapBypass ram based swap disk cache
-config SYM_SWAP2
- bool "Symbiotic Swap disk v2"
+config SWAPBYPASS_DISK_CACHE2
+ bool "SwapBypass disk cache v2"
default y
- depends on SYMBIOTIC_SWAP && (LINUX_VIRTIO_BLOCK || IDE)
+ depends on SWAPBYPASS && (LINUX_VIRTIO_BLOCK || IDE)
help
- Includes the symbiotic ram based swap disk
+ Includes the SwapBypass ram based swap disk cache
config DISK_MODEL
bool "Disk Performance Model"
obj-$(CONFIG_OS_DEBUG) += os_debug.o
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_SWAPBYPASS_DISK_CACHE) += swapbypass_cache.o
+obj-$(CONFIG_SWAPBYPASS_DISK_CACHE2) += swapbypass_cache2.o
obj-$(CONFIG_DISK_MODEL) += disk_model.o
obj-$(CONFIG_NE2K) += ne2k.o
#include <palacios/vmm.h>
#include <palacios/vmm_dev_mgr.h>
-#include <palacios/vmm_sym_swap.h>
+#include <palacios/vmm_swapbypass.h>
#include <palacios/vm_guest.h>
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
#include <palacios/vmm_telemetry.h>
#endif
union swap_header * hdr;
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
uint32_t pages_in;
uint32_t pages_out;
#endif
int i = 0;
// Notify the shadow paging layer
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
swap->pages_in += length / 4096;
#endif
if ((swap->active == 1) && (offset != 0)) {
int i = 0;
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
swap->pages_out += length / 4096;
#endif
};
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
static void telemetry_cb(struct v3_vm_info * vm, void * private_data, char * hdr) {
struct vm_device * dev = (struct vm_device *)private_data;
struct swap_state * swap = (struct swap_state *)(dev->private_data);
return -1;
}
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
if (vm->enable_telemetry == 1) {
v3_add_telemetry_cb(vm, telemetry_cb, dev);
}
return 0;
}
-device_register("SYM_SWAP", swap_init)
+device_register("SWAPBYPASS_CACHE", swap_init)
#include <palacios/vmm.h>
#include <palacios/vmm_dev_mgr.h>
-#include <palacios/vmm_sym_swap.h>
+#include <palacios/vmm_swapbypass.h>
#include <palacios/vm_guest.h>
#include <palacios/vmm_hashtable.h>
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
#include <palacios/vmm_telemetry.h>
#endif
struct v3_dev_blk_ops * ops;
void * private_data;
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
uint32_t pages_in;
uint32_t pages_out;
#endif
swap->unswapped_pages += (length / 4096);
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
swap->pages_in += length / 4096;
#endif
swap->swapped_pages += written_pages;
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
swap->pages_out += length / 4096;
#endif
};
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
static void telemetry_cb(struct v3_vm_info * vm, void * private_data, char * hdr) {
struct swap_state * swap = (struct swap_state *)private_data;
}
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
if (vm->enable_telemetry == 1) {
v3_add_telemetry_cb(vm, telemetry_cb, swap);
return 0;
}
-device_register("SWAPCACHE", swap_init)
+device_register("SWAPBYPASS_CACHE2", swap_init)
obj-$(CONFIG_SYMCALL) += vmm_symcall.o
obj-$(CONFIG_SYMMOD) += vmm_symmod.o
-obj-$(CONFIG_SYMBIOTIC_SWAP) += vmm_sym_swap.o vmm_shdw_pg_swapbypass.o
+obj-$(CONFIG_SWAPBYPASS) += vmm_shdw_pg_swapbypass.o
v3_init_dev_mgr(vm);
-#ifdef CONFIG_SYMBIOTIC_SWAP
- PrintDebug("initializing symbiotic swap\n");
- v3_init_sym_swap(vm);
-#endif
-
-
-
// init SVM/VMX
#ifdef CONFIG_SVM
if ((cpu_type == V3_SVM_CPU) || (cpu_type == V3_SVM_REV3_CPU)) {
*/
#include <palacios/vmm_shadow_paging.h>
+#include <palacios/vmm_swapbypass.h>
#include <palacios/vmm_ctrl_regs.h>
#include <palacios/vm_guest.h>
#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_paging.h>
+#include <palacios/vmm_hashtable.h>
+
+
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#include <palacios/vmm_telemetry.h>
+#endif
+
+
+
+
+
+
+// This is a hack and 32 bit linux specific.... need to fix...
+struct swap_pte {
+ uint32_t present : 1;
+ uint32_t dev_index : 8;
+ uint32_t pg_index : 23;
+};
+
+
+struct shadow_pointer {
+ uint32_t pg_index;
+ uint32_t dev_index;
+
+ pte32_t * shadow_pte;
+
+ addr_t guest_pte;
+
+ struct list_head node;
+};
+
+
+
+
+
struct shadow_page_data {
v3_reg_t cr3;
};
+struct v3_swap_dev {
+ uint8_t present;
+
+ struct v3_swap_ops * ops;
+
+ void * private_data;
+};
+
+
+struct swapbypass_vm_state {
+ struct v3_swap_dev devs[256];
+
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+ uint32_t read_faults;
+ uint32_t write_faults;
+ uint32_t flushes;
+ uint32_t mapped_pages;
+ uint32_t list_size;
+#endif
+
+ // shadow pointers
+ struct hashtable * shdw_ptr_ht;
+};
+
+
+
+
+static uint_t swap_hash_fn(addr_t key) {
+ return v3_hash_long(key, 32);
+}
+
+
+static int swap_eq_fn(addr_t key1, addr_t key2) {
+ return (key1 == key2);
+}
+
+
+
+static inline uint32_t get_pg_index(pte32_t * pte) {
+ return ((struct swap_pte *)pte)->pg_index;
+}
+
+
+static inline uint32_t get_dev_index(pte32_t * pte) {
+ return ((struct swap_pte *)pte)->dev_index;
+}
+
+
+// Present = 0 and Dirty = 0
+// fixme
+static inline int is_swapped_pte32(pte32_t * pte) {
+ return ((pte->present == 0) && (*(uint32_t *)pte != 0));
+}
+
+
+
static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core);
+
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+static void telemetry_cb(struct v3_vm_info * vm, void * private_data, char * hdr) {
+ struct swapbypass_vm_state * swap_state = (struct swapbypass_vm_state *)(vm->shdw_impl.impl_data);
+
+ V3_Print("%sSymbiotic Swap:\n", hdr);
+ V3_Print("%s\tRead faults=%d\n", hdr, swap_state->read_faults);
+ 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
+
+
+
+
+
+
+
+
+
+static int get_vaddr_perms(struct guest_info * info, addr_t vaddr, pte32_t * guest_pte, pf_error_t * page_perms) {
+ uint64_t pte_val = (uint64_t)*(uint32_t *)guest_pte;
+
+ // symcall to check if page is in cache or on swap disk
+ if (v3_sym_call3(info, SYMCALL_MEM_LOOKUP, (uint64_t *)&vaddr, (uint64_t *)&pte_val, (uint64_t *)page_perms) == -1) {
+ PrintError("Sym call error?? that's weird... \n");
+ return -1;
+ }
+
+ // V3_Print("page perms = %x\n", *(uint32_t *)page_perms);
+
+ if (vaddr == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static addr_t get_swapped_pg_addr(struct v3_vm_info * vm, pte32_t * guest_pte) {
+ struct swapbypass_vm_state * swap_state = (struct swapbypass_vm_state *)(vm->shdw_impl.impl_data);
+ 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);
+}
+
+
+
+static addr_t map_swp_page(struct v3_vm_info * vm, pte32_t * shadow_pte, pte32_t * guest_pte, void * swp_page_ptr) {
+ struct swapbypass_vm_state * swap_state = (struct swapbypass_vm_state *)(vm->shdw_impl.impl_data);
+ struct list_head * shdw_ptr_list = NULL;
+ struct shadow_pointer * shdw_ptr = NULL;
+
+
+
+ if (swp_page_ptr == NULL) {
+ // PrintError("Swapped out page not found on swap device\n");
+ return 0;
+ }
+
+ shdw_ptr_list = (struct list_head *)v3_htable_search(swap_state->shdw_ptr_ht, (addr_t)*(uint32_t *)guest_pte);
+
+ if (shdw_ptr_list == NULL) {
+ shdw_ptr_list = (struct list_head *)V3_Malloc(sizeof(struct list_head *));
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+ swap_state->list_size++;
+#endif
+ 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");
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+ telemetry_cb(vm, NULL, "");
+#endif
+ 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);
+ shdw_ptr->dev_index = get_dev_index(guest_pte);
+
+ // We don't check for conflicts, because it should not happen...
+ list_add(&(shdw_ptr->node), shdw_ptr_list);
+
+ return PAGE_BASE_ADDR((addr_t)V3_PAddr(swp_page_ptr));
+}
+
+
+
+
+
#include "vmm_shdw_pg_swapbypass_32.h"
#include "vmm_shdw_pg_swapbypass_32pae.h"
#include "vmm_shdw_pg_swapbypass_64.h"
+
+
+
+int v3_register_swap_disk(struct v3_vm_info * vm, int dev_index,
+ struct v3_swap_ops * ops, void * private_data) {
+ struct swapbypass_vm_state * swap_state = (struct swapbypass_vm_state *)(vm->shdw_impl.impl_data);
+
+ swap_state->devs[dev_index].present = 1;
+ swap_state->devs[dev_index].private_data = private_data;
+ swap_state->devs[dev_index].ops = ops;
+
+ return 0;
+}
+
+
+
+
+int v3_swap_in_notify(struct v3_vm_info * vm, int pg_index, int dev_index) {
+ struct list_head * shdw_ptr_list = NULL;
+ struct swapbypass_vm_state * swap_state = (struct swapbypass_vm_state *)(vm->shdw_impl.impl_data);
+ struct shadow_pointer * tmp_shdw_ptr = NULL;
+ struct shadow_pointer * shdw_ptr = NULL;
+ struct swap_pte guest_pte = {0, dev_index, pg_index};
+
+ shdw_ptr_list = (struct list_head * )v3_htable_search(swap_state->shdw_ptr_ht, *(addr_t *)&(guest_pte));
+
+ if (shdw_ptr_list == NULL) {
+ return 0;
+ }
+
+ list_for_each_entry_safe(shdw_ptr, tmp_shdw_ptr, shdw_ptr_list, node) {
+ if ((shdw_ptr->pg_index == pg_index) &&
+ (shdw_ptr->dev_index == dev_index)) {
+
+ // Trigger faults for next shadow access
+ shdw_ptr->shadow_pte->present = 0;
+
+ // Delete entry from list
+ list_del(&(shdw_ptr->node));
+ V3_Free(shdw_ptr);
+ }
+ }
+
+ return 0;
+}
+
+
+
+int v3_swap_flush(struct v3_vm_info * vm) {
+ struct swapbypass_vm_state * swap_state = (struct swapbypass_vm_state *)(vm->shdw_impl.impl_data);
+ struct hashtable_iter * ht_iter = v3_create_htable_iter(swap_state->shdw_ptr_ht);
+
+ // PrintDebug("Flushing Symbiotic Swap table\n");
+
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+ swap_state->flushes++;
+#endif
+
+ if (!ht_iter) {
+ PrintError("NULL iterator in swap flush!! Probably will crash soon...\n");
+ }
+
+ while (ht_iter->entry) {
+ struct shadow_pointer * tmp_shdw_ptr = NULL;
+ struct shadow_pointer * shdw_ptr = NULL;
+ struct list_head * shdw_ptr_list = (struct list_head *)v3_htable_get_iter_value(ht_iter);
+
+ // delete all swapped entries
+ // we can leave the list_head structures and reuse them for the next round
+
+ list_for_each_entry_safe(shdw_ptr, tmp_shdw_ptr, shdw_ptr_list, node) {
+ if (shdw_ptr == NULL) {
+ PrintError("Null shadow pointer in swap flush!! Probably crashing soon...\n");
+ }
+
+ // Trigger faults for next shadow access
+ shdw_ptr->shadow_pte->present = 0;
+
+ // Delete entry from list
+ list_del(&(shdw_ptr->node));
+ V3_Free(shdw_ptr);
+ }
+
+ v3_htable_iter_advance(ht_iter);
+ }
+
+ V3_Free(ht_iter);
+
+ return 0;
+}
+
+
+
+
+
+
+
static int sb_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
+ struct v3_shdw_impl_state * impl_state = &(vm->shdw_impl);
+ struct swapbypass_vm_state * sb_state = NULL;
+
+ memset(sb_state, 0, sizeof(struct swapbypass_vm_state));
+ sb_state->shdw_ptr_ht = v3_create_htable(0, swap_hash_fn, swap_eq_fn);
+
+#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+ if (vm->enable_telemetry) {
+ v3_add_telemetry_cb(vm, telemetry_cb, NULL);
+ }
+#endif
+
+ impl_state->impl_data = sb_state;
+
+ PrintDebug("Initialized SwapBypass\n");
+
- V3_Print("SWAPBYPASS initialization\n");
return 0;
}
V3_Print("SWAPBYPASS local initialization\n");
-
swapbypass_state = (struct swapbypass_local_state *)V3_Malloc(sizeof(struct swapbypass_local_state));
INIT_LIST_HEAD(&(swapbypass_state->page_list));
#endif
- swp_pg_addr = v3_get_swapped_pg_addr(info->vm_info, guest_pte);
+ swp_pg_addr = get_swapped_pg_addr(info->vm_info, guest_pte);
if (swp_pg_addr != 0) {
PrintDebug("Swapped page address=%p\n", (void *)swp_pg_addr);
}
*/
- int sym_ret = v3_get_vaddr_perms(info, fault_addr, guest_pte, &swap_perms);
+ int sym_ret = get_vaddr_perms(info, fault_addr, guest_pte, &swap_perms);
if (sym_ret == -1) {
PrintError("Symcall error...\n");
(error_code.user == 0) ) ) {
addr_t swp_pg_pa = 0;
- swp_pg_pa = v3_map_swp_page(info->vm_info, shadow_pte, guest_pte, (void *)swp_pg_addr);
+ swp_pg_pa = map_swp_page(info->vm_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);
+++ /dev/null
-/*
- * 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) 2008, Jack Lange <jarusl@cs.northwestern.edu>
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software. You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-#include <palacios/vmm.h>
-
-
-#include <palacios/vmm_sym_swap.h>
-#include <palacios/vmm_list.h>
-#include <palacios/vm_guest.h>
-
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
-#include <palacios/vmm_telemetry.h>
-#endif
-
-// This is a hack and 32 bit linux specific.... need to fix...
-struct swap_pte {
- uint32_t present : 1;
- uint32_t dev_index : 8;
- uint32_t pg_index : 23;
-};
-
-
-struct shadow_pointer {
- uint32_t pg_index;
- uint32_t dev_index;
-
- pte32_t * shadow_pte;
-
- addr_t guest_pte;
-
- struct list_head node;
-};
-
-
-static uint_t swap_hash_fn(addr_t key) {
- return v3_hash_long(key, 32);
-}
-
-
-static int swap_eq_fn(addr_t key1, addr_t key2) {
- return (key1 == key2);
-}
-
-
-
-static inline uint32_t get_pg_index(pte32_t * pte) {
- return ((struct swap_pte *)pte)->pg_index;
-}
-
-
-static inline uint32_t get_dev_index(pte32_t * pte) {
- return ((struct swap_pte *)pte)->dev_index;
-}
-
-
-
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
-static void telemetry_cb(struct v3_vm_info * vm, void * private_data, char * hdr) {
- struct v3_sym_swap_state * swap_state = &(vm->swap_state);
-
- V3_Print("%sSymbiotic Swap:\n", hdr);
- V3_Print("%s\tRead faults=%d\n", hdr, swap_state->read_faults);
- 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
-
-
-int v3_init_sym_swap(struct v3_vm_info * vm) {
- struct v3_sym_swap_state * swap_state = &(vm->swap_state);
-
- memset(swap_state, 0, sizeof(struct v3_sym_swap_state));
- swap_state->shdw_ptr_ht = v3_create_htable(0, swap_hash_fn, swap_eq_fn);
-
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
- if (vm->enable_telemetry) {
- v3_add_telemetry_cb(vm, telemetry_cb, NULL);
- }
-#endif
-
- PrintDebug("Initialized Symbiotic Swap\n");
-
- return 0;
-}
-
-
-int v3_register_swap_disk(struct v3_vm_info * vm, int dev_index,
- struct v3_swap_ops * ops, void * private_data) {
- struct v3_sym_swap_state * swap_state = &(vm->swap_state);
-
- swap_state->devs[dev_index].present = 1;
- swap_state->devs[dev_index].private_data = private_data;
- swap_state->devs[dev_index].ops = ops;
-
- return 0;
-}
-
-
-
-
-int v3_swap_in_notify(struct v3_vm_info * vm, int pg_index, int dev_index) {
- struct list_head * shdw_ptr_list = NULL;
- struct v3_sym_swap_state * swap_state = &(vm->swap_state);
- struct shadow_pointer * tmp_shdw_ptr = NULL;
- struct shadow_pointer * shdw_ptr = NULL;
- struct swap_pte guest_pte = {0, dev_index, pg_index};
-
- shdw_ptr_list = (struct list_head * )v3_htable_search(swap_state->shdw_ptr_ht, *(addr_t *)&(guest_pte));
-
- if (shdw_ptr_list == NULL) {
- return 0;
- }
-
- list_for_each_entry_safe(shdw_ptr, tmp_shdw_ptr, shdw_ptr_list, node) {
- if ((shdw_ptr->pg_index == pg_index) &&
- (shdw_ptr->dev_index == dev_index)) {
-
- // Trigger faults for next shadow access
- shdw_ptr->shadow_pte->present = 0;
-
- // Delete entry from list
- list_del(&(shdw_ptr->node));
- V3_Free(shdw_ptr);
- }
- }
-
- return 0;
-}
-
-
-
-int v3_swap_flush(struct v3_vm_info * vm) {
- struct v3_sym_swap_state * swap_state = &(vm->swap_state);
- struct hashtable_iter * ht_iter = v3_create_htable_iter(swap_state->shdw_ptr_ht);
-
- // PrintDebug("Flushing Symbiotic Swap table\n");
-
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
- swap_state->flushes++;
-#endif
-
- if (!ht_iter) {
- PrintError("NULL iterator in swap flush!! Probably will crash soon...\n");
- }
-
- while (ht_iter->entry) {
- struct shadow_pointer * tmp_shdw_ptr = NULL;
- struct shadow_pointer * shdw_ptr = NULL;
- struct list_head * shdw_ptr_list = (struct list_head *)v3_htable_get_iter_value(ht_iter);
-
- // delete all swapped entries
- // we can leave the list_head structures and reuse them for the next round
-
- list_for_each_entry_safe(shdw_ptr, tmp_shdw_ptr, shdw_ptr_list, node) {
- if (shdw_ptr == NULL) {
- PrintError("Null shadow pointer in swap flush!! Probably crashing soon...\n");
- }
-
- // Trigger faults for next shadow access
- shdw_ptr->shadow_pte->present = 0;
-
- // Delete entry from list
- list_del(&(shdw_ptr->node));
- V3_Free(shdw_ptr);
- }
-
- v3_htable_iter_advance(ht_iter);
- }
-
- V3_Free(ht_iter);
-
- return 0;
-}
-
-int v3_get_vaddr_perms(struct guest_info * info, addr_t vaddr, pte32_t * guest_pte, pf_error_t * page_perms) {
- uint64_t pte_val = (uint64_t)*(uint32_t *)guest_pte;
-
- // symcall to check if page is in cache or on swap disk
- if (v3_sym_call3(info, SYMCALL_MEM_LOOKUP, (uint64_t *)&vaddr, (uint64_t *)&pte_val, (uint64_t *)page_perms) == -1) {
- PrintError("Sym call error?? that's weird... \n");
- return -1;
- }
-
- // 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 v3_vm_info * vm, pte32_t * guest_pte) {
- struct v3_sym_swap_state * swap_state = &(vm->swap_state);
- 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 v3_vm_info * vm, 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 = &(vm->swap_state);
- struct shadow_pointer * shdw_ptr = NULL;
-
-
-
- if (swp_page_ptr == NULL) {
- // PrintError("Swapped out page not found on swap device\n");
- return 0;
- }
-
- shdw_ptr_list = (struct list_head *)v3_htable_search(swap_state->shdw_ptr_ht, (addr_t)*(uint32_t *)guest_pte);
-
- if (shdw_ptr_list == NULL) {
- shdw_ptr_list = (struct list_head *)V3_Malloc(sizeof(struct list_head *));
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
- swap_state->list_size++;
-#endif
- 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");
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
- telemetry_cb(vm, NULL, "");
-#endif
- 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);
- shdw_ptr->dev_index = get_dev_index(guest_pte);
-
- // We don't check for conflicts, because it should not happen...
- list_add(&(shdw_ptr->node), shdw_ptr_list);
-
- 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;
-}
-
-
-*/