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.


a4117b823602a44ea69ed45aaa9480f9f5730685
[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
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     while (ht_iter->entry) {
159         struct shadow_pointer * tmp_shdw_ptr = NULL;
160         struct shadow_pointer * shdw_ptr = NULL;
161         struct list_head * shdw_ptr_list = (struct list_head *)v3_htable_get_iter_value(ht_iter);
162
163         // delete all swapped entries
164         // we can leave the list_head structures and reuse them for the next round
165         
166         list_for_each_entry_safe(shdw_ptr, tmp_shdw_ptr, shdw_ptr_list, node) {
167             // Trigger faults for next shadow access
168             shdw_ptr->shadow_pte->present = 0;
169             
170             // Delete entry from list
171             list_del(&(shdw_ptr->node));
172             V3_Free(shdw_ptr);      
173         }
174
175         v3_htable_iter_advance(ht_iter);
176     }
177
178     return 0;
179 }
180
181 int v3_get_vaddr_perms(struct guest_info * info, addr_t vaddr, pte32_t * guest_pte, pf_error_t * page_perms) {
182     uint32_t pte_val = *(uint32_t *)guest_pte;
183
184     // symcall to check if page is in cache or on swap disk
185     if (v3_sym_call3(info, SYMCALL_MEM_LOOKUP, (uint64_t *)&vaddr, (uint64_t *)&pte_val, (uint64_t *)page_perms) == -1) {
186         PrintError("Sym call error?? that's weird... \n");
187         return -1;
188     }
189
190     V3_Print("page perms = %x\n", *(uint32_t *)page_perms);
191
192     return 0;
193 }
194
195
196
197 addr_t v3_get_swapped_pg_addr(struct guest_info * info, pte32_t * shadow_pte, pte32_t * guest_pte) {
198     struct list_head * shdw_ptr_list = NULL;
199     struct v3_sym_swap_state * swap_state = &(info->swap_state);
200     struct shadow_pointer * shdw_ptr = NULL;
201     void * swp_page_ptr = NULL;
202     int dev_index = get_dev_index(guest_pte);
203     struct v3_swap_dev * swp_dev = &(swap_state->devs[dev_index]);
204
205     if (! swp_dev->present ) {
206         return 0;
207     }
208
209
210
211     swp_page_ptr = swp_dev->ops->get_swap_entry(get_pg_index(guest_pte), swp_dev->private_data);
212
213     if (swp_page_ptr == NULL) {
214         PrintError("Swapped out page not found on swap device\n");
215         return 0;
216     }
217
218     shdw_ptr_list = (struct list_head *)v3_htable_search(swap_state->shdw_ptr_ht, (addr_t)*(uint32_t *)guest_pte);
219
220     if (shdw_ptr_list == NULL) {
221         shdw_ptr_list = (struct list_head *)V3_Malloc(sizeof(struct list_head *));
222         INIT_LIST_HEAD(shdw_ptr_list);
223         v3_htable_insert(swap_state->shdw_ptr_ht, (addr_t)*(uint32_t *)guest_pte, (addr_t)shdw_ptr_list);
224     }
225
226     shdw_ptr = (struct shadow_pointer *)V3_Malloc(sizeof(struct shadow_pointer));
227
228     shdw_ptr->shadow_pte = shadow_pte;
229     shdw_ptr->guest_pte = *(uint32_t *)guest_pte;
230     shdw_ptr->pg_index = get_pg_index(guest_pte);
231     shdw_ptr->dev_index = get_dev_index(guest_pte);
232
233     // We don't check for conflicts, because it should not happen...
234     list_add(&(shdw_ptr->node), shdw_ptr_list);
235
236     return PAGE_BASE_ADDR((addr_t)V3_PAddr(swp_page_ptr));
237 }