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.


f2057f40b40ca757aeda9540b9c338ad7a7bd638
[palacios.git] / palacios / src / devices / sym_swap.c
1 /* 
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
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.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm.h>
21 #include <palacios/vmm_dev_mgr.h>
22 #include <devices/lnx_virtio_blk.h>
23
24 #define SWAP_CAPACITY (150 * 1024 * 1024)
25
26
27 /* This is the first page that linux writes to the swap area */
28 /* Taken from Linux */
29 union swap_header {
30     struct {
31         char reserved[PAGE_SIZE - 10];
32         char magic[10];                 /* SWAP-SPACE or SWAPSPACE2 */
33     } magic;
34     struct {
35         char                    bootbits[1024]; /* Space for disklabel etc. */
36         uint32_t                version;
37         uint32_t                last_page;
38         uint32_t                nr_badpages;
39         unsigned char           sws_uuid[16];
40         unsigned char           sws_volume[16];
41         uint32_t                type;           // The index into the swap_map
42         uint32_t                padding[116];
43         //              uint32_t                padding[117];
44         uint32_t                badpages[1];
45     } info;
46 };
47
48 struct swap_state {
49     
50     struct vm_device * blk_dev;
51
52     uint_t swapped_pages;
53     uint_t unswapped_pages;
54
55     uint64_t capacity;
56     uint8_t * swap_space;
57     addr_t swap_base_addr;
58 };
59
60
61
62 static uint64_t swap_get_capacity(void * private_data) {
63     struct vm_device * dev = (struct vm_device *)private_data;
64     struct swap_state * swap = (struct swap_state *)(dev->private_data);
65
66     PrintDebug("SymSwap: Getting Capacity %d\n", (uint32_t)(swap->capacity));
67
68     return swap->capacity / HD_SECTOR_SIZE;
69 }
70
71 static int swap_read(uint8_t * buf, int sector_count, uint64_t lba,  void * private_data) {
72     struct vm_device * dev = (struct vm_device *)private_data;
73     struct swap_state * swap = (struct swap_state *)(dev->private_data);
74     int offset = lba * HD_SECTOR_SIZE;
75     int length = sector_count * HD_SECTOR_SIZE;
76
77     
78     PrintDebug("SymSwap: Reading %d bytes to %p from %p\n", length,
79                buf, (void *)(swap->swap_space + offset));
80     
81     if (length % 4096) {
82         PrintError("Swapping in length that is not a page multiple\n");
83     }
84
85     memcpy(buf, swap->swap_space + offset, length);
86
87     swap->unswapped_pages += (length / 4096);
88
89     PrintDebug("Swapped in %d pages\n", length / 4096);
90
91     return 0;
92 }
93
94 static int swap_write(uint8_t * buf, int sector_count, uint64_t lba, void * private_data) {
95     struct vm_device * dev = (struct vm_device *)private_data;
96     struct swap_state * swap = (struct swap_state *)(dev->private_data);
97     int offset = lba * HD_SECTOR_SIZE;
98     int length = sector_count * HD_SECTOR_SIZE;
99     /*
100       PrintDebug("SymSwap: Writing %d bytes to %p from %p\n", length, 
101       (void *)(swap->swap_space + offset), buf);
102     */
103     if (length % 4096) {
104         PrintError("Swapping out length that is not a page multiple\n");
105     }
106
107     if (offset == 0) {
108         // This is the swap header page 
109         union swap_header * hdr;
110         if (length != 4096) {
111             PrintError("Initializing Swap space by not writing page multiples. This sucks...\n");
112             return -1;
113         }
114
115         hdr = (union swap_header *)buf;
116         
117
118         PrintDebug("Swap Type=%d (magic=%s)\n", hdr->info.type, hdr->magic.magic);
119     }
120
121     memcpy(swap->swap_space + offset, buf, length);
122
123     swap->swapped_pages += (length / 4096);
124
125     PrintDebug("Swapped out %d pages\n", length / 4096);
126
127     return 0;
128 }
129
130
131 static int swap_free(struct vm_device * dev) {
132     return -1;
133 }
134
135
136 static struct v3_hd_ops hd_ops = {
137     .read = swap_read, 
138     .write = swap_write, 
139     .get_capacity = swap_get_capacity,
140 };
141
142
143
144 static struct v3_device_ops dev_ops = {
145     .free = swap_free,
146     .reset = NULL,
147     .start = NULL,
148     .stop = NULL,
149 };
150
151
152
153
154 static int swap_init(struct guest_info * vm, void * cfg_data) {
155     struct swap_state * swap = NULL;
156     struct vm_device * virtio_blk = v3_find_dev(vm, (char *)cfg_data);
157
158     if (!virtio_blk) {
159         PrintError("could not find Virtio backend\n");
160         return -1;
161     }
162
163     PrintDebug("Creating Swap Device\n");
164
165     if (virtio_blk == NULL) {
166         PrintError("Swap device requires a virtio block device\n");
167         return -1;
168     }
169
170     swap = (struct swap_state *)V3_Malloc(sizeof(struct swap_state));
171
172     swap->blk_dev = virtio_blk;
173     swap->capacity = SWAP_CAPACITY;
174
175     swap->swapped_pages = 0;
176     swap->unswapped_pages = 0;
177
178     swap->swap_base_addr = (addr_t)V3_AllocPages(swap->capacity / 4096);
179     swap->swap_space = (uint8_t *)V3_VAddr((void *)(swap->swap_base_addr));
180     memset(swap->swap_space, 0, SWAP_CAPACITY);
181
182
183     struct vm_device * dev = v3_allocate_device("SYM_SWAP", &dev_ops, swap);
184
185     if (v3_attach_device(vm, dev) == -1) {
186         PrintError("Could not attach device %s\n", "SYM_SWAP");
187         return -1;
188     }
189
190
191     v3_virtio_register_harddisk(virtio_blk, &hd_ops, dev);
192
193     return 0;
194 }
195
196
197
198 device_register("SYM_SWAP", swap_init)