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 debugging
[palacios.git] / palacios / src / palacios / vmm_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 #include <palacios/vmm.h>
20
21
22 #include <palacios/vmm_sym_swap.h>
23 #include <palacios/vmm_list.h>
24 #include <palacios/vm_guest.h>
25
26 #ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
27 #include <palacios/vmm_telemetry.h>
28 #endif
29
30 // This is a hack and 32 bit linux specific.... need to fix...
31 struct swap_pte {
32     uint32_t present    : 1;
33     uint32_t dev_index  : 8;
34     uint32_t pg_index   : 23;
35 };
36
37
38 struct shadow_pointer {
39     uint32_t pg_index;
40     uint32_t dev_index;
41
42     pte32_t * shadow_pte;
43     
44     addr_t guest_pte;
45     
46     struct list_head node;
47 };
48
49
50 static uint_t swap_hash_fn(addr_t key) {
51     return v3_hash_long(key, 32);
52 }
53
54
55 static int swap_eq_fn(addr_t key1, addr_t key2) {
56     return (key1 == key2);
57 }
58
59
60
61 static inline uint32_t get_pg_index(pte32_t * pte) {
62     return ((struct swap_pte *)pte)->pg_index;
63 }
64
65
66 static inline uint32_t get_dev_index(pte32_t * pte) {
67     return ((struct swap_pte *)pte)->dev_index;
68 }
69
70
71
72 #ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
73 static void telemetry_cb(struct guest_info * info, void * private_data, char * hdr) {
74     struct v3_sym_swap_state * swap_state = &(info->swap_state);
75
76     V3_Print("%sSymbiotic Swap:\n", hdr);
77     V3_Print("%s\tRead faults=%d\n", hdr, swap_state->read_faults);
78     V3_Print("%s\tWrite faults=%d\n", hdr, swap_state->write_faults);
79     V3_Print("%s\tMapped Pages=%d\n", hdr, swap_state->mapped_pages);
80     V3_Print("%s\tFlushes=%d\n", hdr, swap_state->flushes);
81 }
82 #endif
83
84
85 int v3_init_sym_swap(struct guest_info * info) {
86     struct v3_sym_swap_state * swap_state = &(info->swap_state);
87
88     memset(swap_state, 0, sizeof(struct v3_sym_swap_state));
89     swap_state->shdw_ptr_ht = v3_create_htable(0, swap_hash_fn, swap_eq_fn);
90
91 #ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
92     if (info->enable_telemetry) {
93         v3_add_telemetry_cb(info, telemetry_cb, NULL);
94     }
95 #endif
96
97     PrintDebug("Initialized Symbiotic Swap\n");
98
99     return 0;
100 }
101
102
103 int v3_register_swap_disk(struct guest_info * info, int dev_index, 
104                           struct v3_swap_ops * ops, void * private_data) {
105     struct v3_sym_swap_state * swap_state = &(info->swap_state);
106
107     swap_state->devs[dev_index].present = 1;
108     swap_state->devs[dev_index].private_data = private_data;
109     swap_state->devs[dev_index].ops = ops;
110
111     return 0;
112 }
113
114
115
116
117 int v3_swap_in_notify(struct guest_info * info, int pg_index, int dev_index) {
118     struct list_head * shdw_ptr_list = NULL;
119     struct v3_sym_swap_state * swap_state = &(info->swap_state);
120     struct shadow_pointer * tmp_shdw_ptr = NULL;
121     struct shadow_pointer * shdw_ptr = NULL;
122     struct swap_pte guest_pte = {0, dev_index, pg_index};
123
124     shdw_ptr_list = (struct list_head * )v3_htable_search(swap_state->shdw_ptr_ht, *(addr_t *)&(guest_pte));
125
126     if (shdw_ptr_list == NULL) {
127         return 0;
128     }
129
130     list_for_each_entry_safe(shdw_ptr, tmp_shdw_ptr, shdw_ptr_list, node) {
131         if ((shdw_ptr->pg_index == pg_index) &&
132             (shdw_ptr->dev_index == dev_index)) {
133
134             // Trigger faults for next shadow access
135             shdw_ptr->shadow_pte->present = 0;
136
137             // Delete entry from list
138             list_del(&(shdw_ptr->node));
139             V3_Free(shdw_ptr);
140         }
141     }
142
143     return 0;
144 }
145
146
147
148 int v3_swap_flush(struct guest_info * info) {
149     struct v3_sym_swap_state * swap_state = &(info->swap_state);
150     struct hashtable_iter * ht_iter = v3_create_htable_iter(swap_state->shdw_ptr_ht);
151
152     //    PrintDebug("Flushing Symbiotic Swap table\n");
153
154 #ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
155     swap_state->flushes++;
156 #endif
157
158     if (!ht_iter) {
159         PrintError("NULL iterator in swap flush!! Probably will crash soon...\n");
160     }
161
162     while (ht_iter->entry) {
163         struct shadow_pointer * tmp_shdw_ptr = NULL;
164         struct shadow_pointer * shdw_ptr = NULL;
165         struct list_head * shdw_ptr_list = (struct list_head *)v3_htable_get_iter_value(ht_iter);
166
167         // delete all swapped entries
168         // we can leave the list_head structures and reuse them for the next round
169         
170         list_for_each_entry_safe(shdw_ptr, tmp_shdw_ptr, shdw_ptr_list, node) {
171             if (shadw_ptr == NULL) {
172                 PrintError("Null shadow pointer in swap flush!! Probably crashing soon...\n");
173             }
174
175             // Trigger faults for next shadow access
176             shdw_ptr->shadow_pte->present = 0;
177             
178             // Delete entry from list
179             list_del(&(shdw_ptr->node));
180             V3_Free(shdw_ptr);
181         }
182
183         v3_htable_iter_advance(ht_iter);
184     }
185
186     return 0;
187 }
188
189 int v3_get_vaddr_perms(struct guest_info * info, addr_t vaddr, pte32_t * guest_pte, pf_error_t * page_perms) {
190     uint32_t pte_val = *(uint32_t *)guest_pte;
191
192     // symcall to check if page is in cache or on swap disk
193     if (v3_sym_call3(info, SYMCALL_MEM_LOOKUP, (uint64_t *)&vaddr, (uint64_t *)&pte_val, (uint64_t *)page_perms) == -1) {
194         PrintError("Sym call error?? that's weird... \n");
195         return -1;
196     }
197
198     V3_Print("page perms = %x\n", *(uint32_t *)page_perms);
199
200     return 0;
201 }
202
203
204
205 addr_t v3_get_swapped_pg_addr(struct guest_info * info, pte32_t * shadow_pte, pte32_t * guest_pte) {
206     struct list_head * shdw_ptr_list = NULL;
207     struct v3_sym_swap_state * swap_state = &(info->swap_state);
208     struct shadow_pointer * shdw_ptr = NULL;
209     void * swp_page_ptr = NULL;
210     int dev_index = get_dev_index(guest_pte);
211     struct v3_swap_dev * swp_dev = &(swap_state->devs[dev_index]);
212
213     if (! swp_dev->present ) {
214         return 0;
215     }
216
217
218
219     swp_page_ptr = swp_dev->ops->get_swap_entry(get_pg_index(guest_pte), swp_dev->private_data);
220
221     if (swp_page_ptr == NULL) {
222         PrintError("Swapped out page not found on swap device\n");
223         return 0;
224     }
225
226     shdw_ptr_list = (struct list_head *)v3_htable_search(swap_state->shdw_ptr_ht, (addr_t)*(uint32_t *)guest_pte);
227
228     if (shdw_ptr_list == NULL) {
229         shdw_ptr_list = (struct list_head *)V3_Malloc(sizeof(struct list_head *));
230         INIT_LIST_HEAD(shdw_ptr_list);
231         v3_htable_insert(swap_state->shdw_ptr_ht, (addr_t)*(uint32_t *)guest_pte, (addr_t)shdw_ptr_list);
232     }
233
234     shdw_ptr = (struct shadow_pointer *)V3_Malloc(sizeof(struct shadow_pointer));
235
236     shdw_ptr->shadow_pte = shadow_pte;
237     shdw_ptr->guest_pte = *(uint32_t *)guest_pte;
238     shdw_ptr->pg_index = get_pg_index(guest_pte);
239     shdw_ptr->dev_index = get_dev_index(guest_pte);
240
241     // We don't check for conflicts, because it should not happen...
242     list_add(&(shdw_ptr->node), shdw_ptr_list);
243
244     return PAGE_BASE_ADDR((addr_t)V3_PAddr(swp_page_ptr));
245 }