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.


added linux swap header
[palacios.git] / palacios / src / devices / sym_swap.c
index 9bb795f..f2057f4 100644 (file)
 
 #include <palacios/vmm.h>
 #include <palacios/vmm_dev_mgr.h>
-
-
-
+#include <devices/lnx_virtio_blk.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 {
+    struct {
+       char reserved[PAGE_SIZE - 10];
+       char magic[10];                 /* SWAP-SPACE or SWAPSPACE2 */
+    } magic;
+    struct {
+       char                    bootbits[1024]; /* Space for disklabel etc. */
+       uint32_t                version;
+       uint32_t                last_page;
+       uint32_t                nr_badpages;
+       unsigned char           sws_uuid[16];
+       unsigned char           sws_volume[16];
+       uint32_t                type;           // The index into the swap_map
+       uint32_t                padding[116];
+       //              uint32_t                padding[117];
+       uint32_t                badpages[1];
+    } info;
+};
 
 struct swap_state {
     
     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;
 };
 
 
 
+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);
+
+    PrintDebug("SymSwap: Getting Capacity %d\n", (uint32_t)(swap->capacity));
+
+    return swap->capacity / HD_SECTOR_SIZE;
+}
+
+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;
+
+    
+    PrintDebug("SymSwap: Reading %d bytes to %p from %p\n", length,
+              buf, (void *)(swap->swap_space + offset));
+    
+    if (length % 4096) {
+       PrintError("Swapping in length that is not a page multiple\n");
+    }
+
+    memcpy(buf, swap->swap_space + offset, length);
+
+    swap->unswapped_pages += (length / 4096);
+
+    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;
+    /*
+      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 (length != 4096) {
+           PrintError("Initializing Swap space by not writing page multiples. This sucks...\n");
+           return -1;
+       }
+
+       hdr = (union swap_header *)buf;
+       
+
+       PrintDebug("Swap Type=%d (magic=%s)\n", hdr->info.type, hdr->magic.magic);
+    }
+
+    memcpy(swap->swap_space + offset, buf, length);
+
+    swap->swapped_pages += (length / 4096);
+
+    PrintDebug("Swapped out %d pages\n", length / 4096);
+
+    return 0;
+}
+
 
 static int swap_free(struct vm_device * dev) {
     return -1;
 }
 
 
+static struct v3_hd_ops hd_ops = {
+    .read = swap_read, 
+    .write = swap_write, 
+    .get_capacity = swap_get_capacity,
+};
+
+
 
 static struct v3_device_ops dev_ops = {
     .free = swap_free,
@@ -67,6 +170,15 @@ static int swap_init(struct guest_info * vm, void * cfg_data) {
     swap = (struct swap_state *)V3_Malloc(sizeof(struct swap_state));
 
     swap->blk_dev = virtio_blk;
+    swap->capacity = SWAP_CAPACITY;
+
+    swap->swapped_pages = 0;
+    swap->unswapped_pages = 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);
+
 
     struct vm_device * dev = v3_allocate_device("SYM_SWAP", &dev_ops, swap);
 
@@ -75,6 +187,9 @@ static int swap_init(struct guest_info * vm, void * cfg_data) {
        return -1;
     }
 
+
+    v3_virtio_register_harddisk(virtio_blk, &hd_ops, dev);
+
     return 0;
 }