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.


telemetry updates
[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\tFlushes=%d\n", hdr, swap_state->flushes);
80 }
81 #endif
82
83
84 int v3_init_sym_swap(struct guest_info * info) {
85     struct v3_sym_swap_state * swap_state = &(info->swap_state);
86
87     memset(swap_state, 0, sizeof(struct v3_sym_swap_state));
88     swap_state->shdw_ptr_ht = v3_create_htable(0, swap_hash_fn, swap_eq_fn);
89
90 #ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
91     if (info->enable_telemetry) {
92         v3_add_telemetry_cb(info, telemetry_cb, NULL);
93     }
94 #endif
95
96     PrintDebug("Initialized Symbiotic Swap\n");
97
98     return 0;
99 }
100
101
102 int v3_register_swap_disk(struct guest_info * info, int dev_index, 
103                           struct v3_swap_ops * ops, void * private_data) {
104     struct v3_sym_swap_state * swap_state = &(info->swap_state);
105
106     swap_state->devs[dev_index].present = 1;
107     swap_state->devs[dev_index].private_data = private_data;
108     swap_state->devs[dev_index].ops = ops;
109
110     return 0;
111 }
112
113
114
115
116 int v3_swap_in_notify(struct guest_info * info, int pg_index, int dev_index) {
117     struct list_head * shdw_ptr_list = NULL;
118     struct v3_sym_swap_state * swap_state = &(info->swap_state);
119     struct shadow_pointer * tmp_shdw_ptr = NULL;
120     struct shadow_pointer * shdw_ptr = NULL;
121     struct swap_pte guest_pte = {0, dev_index, pg_index};
122
123     shdw_ptr_list = (struct list_head * )v3_htable_search(swap_state->shdw_ptr_ht, *(addr_t *)&(guest_pte));
124
125     if (shdw_ptr_list == NULL) {
126         return 0;
127     }
128
129     list_for_each_entry_safe(shdw_ptr, tmp_shdw_ptr, shdw_ptr_list, node) {
130         if ((shdw_ptr->pg_index == pg_index) &&
131             (shdw_ptr->dev_index == dev_index)) {
132
133             // Trigger faults for next shadow access
134             shdw_ptr->shadow_pte->present = 0;
135
136             // Delete entry from list
137             list_del(&(shdw_ptr->node));
138             V3_Free(shdw_ptr);
139         }
140     }
141
142     return 0;
143 }
144
145
146
147 int v3_swap_flush(struct guest_info * info) {
148     struct v3_sym_swap_state * swap_state = &(info->swap_state);
149     struct hashtable_iter * ht_iter = v3_create_htable_iter(swap_state->shdw_ptr_ht);
150
151     PrintDebug("Flushing Symbiotic Swap table\n");
152
153 #ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
154     swap_state->flushes++;
155 #endif
156
157     while (ht_iter->entry) {
158         struct shadow_pointer * tmp_shdw_ptr = NULL;
159         struct shadow_pointer * shdw_ptr = NULL;
160         struct list_head * shdw_ptr_list = (struct list_head *)v3_htable_get_iter_value(ht_iter);
161
162         // delete all swapped entries
163         // we can leave the list_head structures and reuse them for the next round
164         
165         list_for_each_entry_safe(shdw_ptr, tmp_shdw_ptr, shdw_ptr_list, node) {
166             // Trigger faults for next shadow access
167             shdw_ptr->shadow_pte->present = 0;
168             
169             // Delete entry from list
170             list_del(&(shdw_ptr->node));
171             V3_Free(shdw_ptr);      
172         }
173
174         v3_htable_iter_advance(ht_iter);
175     }
176
177     return 0;
178 }
179
180
181 addr_t v3_get_swapped_pg_addr(struct guest_info * info, pte32_t * shadow_pte, pte32_t * guest_pte) {
182     struct list_head * shdw_ptr_list = NULL;
183     struct v3_sym_swap_state * swap_state = &(info->swap_state);
184     struct shadow_pointer * shdw_ptr = NULL;
185     void * swp_page_ptr = NULL;
186     int dev_index = get_dev_index(guest_pte);
187     struct v3_swap_dev * swp_dev = &(swap_state->devs[dev_index]);
188
189     if (! swp_dev->present ) {
190         return 0;
191     }
192
193     swp_page_ptr = swp_dev->ops->get_swap_entry(get_pg_index(guest_pte), swp_dev->private_data);
194
195     if (swp_page_ptr == NULL) {
196         PrintError("Swapped out page not found on swap device\n");
197         return 0;
198     }
199
200     shdw_ptr_list = (struct list_head *)v3_htable_search(swap_state->shdw_ptr_ht, (addr_t)*(uint32_t *)guest_pte);
201
202     if (shdw_ptr_list == NULL) {
203         shdw_ptr_list = (struct list_head *)V3_Malloc(sizeof(struct list_head *));
204         INIT_LIST_HEAD(shdw_ptr_list);
205         v3_htable_insert(swap_state->shdw_ptr_ht, (addr_t)*(uint32_t *)guest_pte, (addr_t)shdw_ptr_list);
206     }
207
208     shdw_ptr = (struct shadow_pointer *)V3_Malloc(sizeof(struct shadow_pointer));
209
210     shdw_ptr->shadow_pte = shadow_pte;
211     shdw_ptr->guest_pte = *(uint32_t *)guest_pte;
212     shdw_ptr->pg_index = get_pg_index(guest_pte);
213     shdw_ptr->dev_index = get_dev_index(guest_pte);
214
215     // We don't check for conflicts, because it should not happen...
216     list_add(&(shdw_ptr->node), shdw_ptr_list);
217
218     return PAGE_BASE_ADDR((addr_t)V3_PAddr(swp_page_ptr));
219 }