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.


initial checkin of symbiotic swap interface
Jack Lange [Mon, 17 Aug 2009 19:42:08 +0000 (14:42 -0500)]
Kconfig
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmm_sym_swap.h
palacios/src/devices/sym_swap.c
palacios/src/palacios/vmm_shadow_paging_32.h
palacios/src/palacios/vmm_sym_swap.c

diff --git a/Kconfig b/Kconfig
index a31a781..8050708 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -243,7 +243,7 @@ config SYMBIOTIC
 config SYMBIOTIC_SWAP
        bool "Symbiotic Swap"
        default n
-       depends on SYMBIOTIC
+       depends on SYMBIOTIC && EXPERIMENTAL
        help 
          This enables the symbiotic swap architecture
 
index bbfc22d..831d146 100644 (file)
 #include <palacios/vmm_time.h>
 #include <palacios/vmm_host_events.h>
 #include <palacios/vmm_msr.h>
-#include <palacios/vmm_profiler.h>
 #include <palacios/vmm_hypercall.h>
 
 
+#ifdef CONFIG_PROFILE_VMM
+#include <palacios/vmm_profiler.h>
+#endif
+
+#ifdef CONFIG_SYMBIOTIC_SWAP
+#include <palacios/vmm_sym_swap.h>
+#endif
+
 
 struct v3_gprs {
     v3_reg_t rdi;
@@ -115,6 +122,9 @@ struct v3_intr_state;
 struct v3_profiler;
 #endif
 
+#ifdef CONFIG_SYMBIOTIC_SWAP
+struct v3_sym_swap_state;
+#endif
 
 
 struct guest_info {
@@ -174,6 +184,11 @@ struct guest_info {
     struct v3_profiler profiler;
 #endif
 
+
+#ifdef CONFIG_SYMBIOTIC_SWAP
+    struct v3_sym_swap_state swap_state;
+#endif
+
     void * decoder_state;
 };
 
@@ -195,6 +210,4 @@ void v3_print_GPRs(struct guest_info * info);
 
 #endif // ! __V3VEE__
 
-
-
 #endif
index 6931ea1..cb0b41d 100644 (file)
 #ifdef __V3VEE__ 
 #ifdef CONFIG_SYMBIOTIC_SWAP
 
-#include <palacios/vmm.h>
+#include <palacios/vmm_types.h>
+#include <palacios/vmm_paging.h>
 
-static inline int is_swapped_pte32(pte32_t * pte) {
-    return (*(uint32_t *)pte != 0);
-}
+
+struct v3_swap_ops {
+    void * (*get_swap_entry)(uint32_t pg_index, void * private_data);
+};
 
 
 struct v3_swap_dev {
-    addr_t (*get_page)(int index);
+    uint8_t present;
 
+    struct v3_swap_ops * ops;
+
+    void * private_data;
 };
 
 
 struct v3_sym_swap_state {
-    struct v3_swap_dev[256];
-
+    struct v3_swap_dev devs[256];
 };
 
 
+static inline int is_swapped_pte32(pte32_t * pte) {
+    return ((pte->present == 0) && (*(uint32_t *)pte != 0));
+}
+
+
+
+
 int v3_init_sym_swap(struct guest_info * info);
 
-addr_t v3_get_swapped_pg_addr(pte32_t * pte);
+addr_t v3_get_swapped_pg_addr(struct guest_info * info, pte32_t * pte);
 
+int v3_register_swap_disk(struct guest_info * info, int dev_index, 
+                         struct v3_swap_ops * ops, void * private_data);
 
+int v3_swap_out_notify(struct guest_info * info, int pg_index, int dev_index);
 
 #endif
 #endif
-
 #endif
index f2057f4..d0442d7 100644 (file)
 #include <palacios/vmm.h>
 #include <palacios/vmm_dev_mgr.h>
 #include <devices/lnx_virtio_blk.h>
+#include <palacios/vmm_sym_swap.h>
 
 #define SWAP_CAPACITY (150 * 1024 * 1024)
 
 
+
 /* This is the first page that linux writes to the swap area */
 /* Taken from Linux */
 union swap_header {
@@ -45,20 +47,73 @@ union swap_header {
     } info;
 };
 
+
+
 struct swap_state {
-    
+    int active;
+
     struct vm_device * blk_dev;
 
     uint_t swapped_pages;
     uint_t unswapped_pages;
 
+
     uint64_t capacity;
     uint8_t * swap_space;
     addr_t swap_base_addr;
+
+    uint8_t usage_map[0]; // This must be the last structure member
 };
 
 
 
+
+static inline void set_index_usage(struct swap_state * swap, uint32_t index, int used) {
+    int major = index / 8;
+    int minor = index % 8;
+
+    if (used) {
+       swap->usage_map[major] |= (1 << minor);
+    } else {
+       swap->usage_map[major] &= ~(1 << minor);
+    }
+}
+
+static inline int get_index_usage(struct swap_state * swap, uint32_t index) {
+    int major = index / 8;
+    int minor = index % 8;
+    return swap->usage_map[major] & (1 << minor);
+}
+
+
+static inline uint32_t get_swap_index_from_offset(uint32_t offset) {
+    // CAREFUL: The index might be offset by 1, because the first 4K is the header
+    return (offset / 4096);
+}
+
+
+/*
+  static inline uint32_t get_swap_index(uint32_t offset) {
+  // CAREFUL: The index might be offset by 1, because the first 4K is the header
+  return (swap_addr - swap->swap_space) / 4096;
+  }
+*/
+
+
+static inline void * get_swap_entry(uint32_t pg_index, void * private_data) {
+    struct swap_state * swap = (struct swap_state *)private_data;
+    void * pg_addr = NULL;
+
+    if (get_index_usage(swap, pg_index)) {
+       // CAREFUL: The index might be offset by 1, because the first 4K is the header
+       pg_addr = (void *)(swap->swap_space + (pg_index * 4096));
+    }
+
+    return pg_addr;
+}
+
+
+
 static uint64_t swap_get_capacity(void * private_data) {
     struct vm_device * dev = (struct vm_device *)private_data;
     struct swap_state * swap = (struct swap_state *)(dev->private_data);
@@ -68,11 +123,18 @@ static uint64_t swap_get_capacity(void * private_data) {
     return swap->capacity / HD_SECTOR_SIZE;
 }
 
+
+static struct v3_swap_ops swap_ops = {
+    .get_swap_entry = get_swap_entry,
+};
+
+
+
 static int swap_read(uint8_t * buf, int sector_count, uint64_t lba,  void * private_data) {
     struct vm_device * dev = (struct vm_device *)private_data;
     struct swap_state * swap = (struct swap_state *)(dev->private_data);
-    int offset = lba * HD_SECTOR_SIZE;
-    int length = sector_count * HD_SECTOR_SIZE;
+    uint32_t offset = lba * HD_SECTOR_SIZE;
+    uint32_t length = sector_count * HD_SECTOR_SIZE;
 
     
     PrintDebug("SymSwap: Reading %d bytes to %p from %p\n", length,
@@ -86,42 +148,60 @@ static int swap_read(uint8_t * buf, int sector_count, uint64_t lba,  void * priv
 
     swap->unswapped_pages += (length / 4096);
 
+    set_index_usage(swap, get_swap_index_from_offset(offset), 0);
+
+
+    // Notify the shadow paging layer
+
     PrintDebug("Swapped in %d pages\n", length / 4096);
 
     return 0;
 }
 
+
+
+
 static int swap_write(uint8_t * buf, int sector_count, uint64_t lba, void * private_data) {
     struct vm_device * dev = (struct vm_device *)private_data;
     struct swap_state * swap = (struct swap_state *)(dev->private_data);
-    int offset = lba * HD_SECTOR_SIZE;
-    int length = sector_count * HD_SECTOR_SIZE;
+    uint32_t offset = lba * HD_SECTOR_SIZE;
+    uint32_t length = sector_count * HD_SECTOR_SIZE;
+
     /*
       PrintDebug("SymSwap: Writing %d bytes to %p from %p\n", length, 
       (void *)(swap->swap_space + offset), buf);
     */
+
     if (length % 4096) {
        PrintError("Swapping out length that is not a page multiple\n");
     }
 
-    if (offset == 0) {
-       // This is the swap header page 
-       union swap_header * hdr;
+    if ((swap->active == 0) && (offset == 0)) {
+       // This is the swap header page
+       union swap_header * hdr = (union swap_header *)buf;
+
        if (length != 4096) {
            PrintError("Initializing Swap space by not writing page multiples. This sucks...\n");
            return -1;
        }
 
-       hdr = (union swap_header *)buf;
-       
+       swap->active = 1;
 
        PrintDebug("Swap Type=%d (magic=%s)\n", hdr->info.type, hdr->magic.magic);
+
+       if (v3_register_swap_disk(dev->vm, hdr->info.type, &swap_ops, dev) == -1) {
+           PrintError("Error registering symbiotic swap disk\n");
+           return -1;
+       }
+
     }
 
     memcpy(swap->swap_space + offset, buf, length);
 
     swap->swapped_pages += (length / 4096);
 
+    set_index_usage(swap, get_swap_index_from_offset(offset), 1);
+
     PrintDebug("Swapped out %d pages\n", length / 4096);
 
     return 0;
@@ -151,6 +231,8 @@ static struct v3_device_ops dev_ops = {
 
 
 
+
+
 static int swap_init(struct guest_info * vm, void * cfg_data) {
     struct swap_state * swap = NULL;
     struct vm_device * virtio_blk = v3_find_dev(vm, (char *)cfg_data);
@@ -167,7 +249,7 @@ static int swap_init(struct guest_info * vm, void * cfg_data) {
        return -1;
     }
 
-    swap = (struct swap_state *)V3_Malloc(sizeof(struct swap_state));
+    swap = (struct swap_state *)V3_Malloc(sizeof(struct swap_state) + ((SWAP_CAPACITY / 4096) / 8));
 
     swap->blk_dev = virtio_blk;
     swap->capacity = SWAP_CAPACITY;
@@ -175,10 +257,13 @@ static int swap_init(struct guest_info * vm, void * cfg_data) {
     swap->swapped_pages = 0;
     swap->unswapped_pages = 0;
 
+    swap->active = 0;
+
     swap->swap_base_addr = (addr_t)V3_AllocPages(swap->capacity / 4096);
     swap->swap_space = (uint8_t *)V3_VAddr((void *)(swap->swap_base_addr));
     memset(swap->swap_space, 0, SWAP_CAPACITY);
 
+    memset(swap->usage_map, 0, ((SWAP_CAPACITY / 4096) / 8));
 
     struct vm_device * dev = v3_allocate_device("SYM_SWAP", &dev_ops, swap);
 
index 4c8922b..4614232 100644 (file)
@@ -36,11 +36,6 @@ static inline int activate_shadow_pt_32(struct guest_info * info) {
     return 0;
 }
 
-#ifdef CONFIG_SYMBIOTIC_SWAP
-static inline int is_swapped_pte32(pte32_t * pte) {
-    return (*(uint32_t *)pte != 0);
-}
-#endif
 
 
 
@@ -229,16 +224,14 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * info, addr_t fault
 
        PrintDebug("Access error injecting pf to guest (guest access error=%d) (pf error code=%d)\n", 
                   guest_pte_access, *(uint_t*)&error_code);
-#ifdef CONFIG_SYMBIOTIC_SWAP_
-       if (is_swapped_pg(guest_pte)) {
-           PrintError("Page fault on swapped out page\n");
+#ifdef CONFIG_SYMBIOTIC_SWAP
+       if (is_swapped_pte32(guest_pte)) {
+           PrintError("Page fault on swapped out page (pte=%x)\n", *(uint32_t *)guest_pte);
 
            if (inject_guest_pf(info, fault_addr, error_code) == -1) {
                PrintError("Could not inject guest page fault\n");
                return -1;
            }
-
-
        } else {
            if (inject_guest_pf(info, fault_addr, error_code) == -1) {
                PrintError("Could not inject guest page fault\n");
index bb79343..7748ee4 100644 (file)
  * 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>
+
+// this is hardcoded in linux, but we should expose it via a sym interface
+#define SWAP_DEV_SHIFT 5 
+
+int v3_init_sym_swap(struct guest_info * info) {
+
+    memset(&(info->swap_state), 0, sizeof(struct v3_sym_swap_state));
+
+    return 0;
+}
+
+
+int v3_register_swap_disk(struct guest_info * info, int dev_index, 
+                         struct v3_swap_ops * ops, void * private_data) {
+    struct v3_sym_swap_state * swap_state = &(info->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;
+}
+
+
+addr_t v3_get_swapped_pg_addr(struct guest_info * info, pte32_t * pte) {
+    struct v3_sym_swap_state * swap_state = &(info->swap_state);
+    uint32_t dev_index = *(uint32_t *)pte & ((1 << SWAP_DEV_SHIFT) - 1);
+    uint32_t pg_index = (*(uint32_t *)pte) >> SWAP_DEV_SHIFT;
+    struct v3_swap_dev * swp_dev = &(swap_state->devs[dev_index]);
+
+    return (addr_t)swp_dev->ops->get_swap_entry(pg_index, swp_dev->private_data);
+}
+
+
+
+int v3_swap_out_notify(struct guest_info * info, int pg_index, int dev_index) {
+    return -1;
+}