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.


symbiotic swap 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 // This is a hack and 32 bit linux specific.... need to fix...
27 struct swap_pte {
28     uint32_t present    : 1;
29     uint32_t dev_index  : 8;
30     uint32_t pg_index   : 23;
31 };
32
33
34 struct shadow_pointer {
35     uint32_t pg_index;
36     uint32_t dev_index;
37
38     pte32_t * shadow_pte;
39     
40     addr_t guest_pte;
41     
42     struct list_head node;
43 };
44
45
46 static uint_t swap_hash_fn(addr_t key) {
47     return v3_hash_long(key, 32);
48 }
49
50
51 static int swap_eq_fn(addr_t key1, addr_t key2) {
52     return (key1 == key2);
53 }
54
55
56
57 static inline uint32_t get_pg_index(pte32_t * pte) {
58     return ((struct swap_pte *)pte)->pg_index;
59 }
60
61
62 static inline uint32_t get_dev_index(pte32_t * pte) {
63     return ((struct swap_pte *)pte)->dev_index;
64 }
65
66
67
68 int v3_init_sym_swap(struct guest_info * info) {
69     memset(&(info->swap_state), 0, sizeof(struct v3_sym_swap_state));
70     info->swap_state.shdw_ptr_ht = v3_create_htable(0, swap_hash_fn, swap_eq_fn);
71
72     PrintDebug("Initialized Symbiotic Swap\n");
73
74     return 0;
75 }
76
77
78 int v3_register_swap_disk(struct guest_info * info, int dev_index, 
79                           struct v3_swap_ops * ops, void * private_data) {
80     struct v3_sym_swap_state * swap_state = &(info->swap_state);
81
82     swap_state->devs[dev_index].present = 1;
83     swap_state->devs[dev_index].private_data = private_data;
84     swap_state->devs[dev_index].ops = ops;
85
86     return 0;
87 }
88
89
90
91
92 int v3_swap_in_notify(struct guest_info * info, int pg_index, int dev_index) {
93     struct list_head * shdw_ptr_list = NULL;
94     struct v3_sym_swap_state * swap_state = &(info->swap_state);
95     struct shadow_pointer * tmp_shdw_ptr = NULL;
96     struct shadow_pointer * shdw_ptr = NULL;
97     struct swap_pte guest_pte = {0, dev_index, pg_index};
98
99     shdw_ptr_list = (struct list_head * )v3_htable_search(swap_state->shdw_ptr_ht, *(addr_t *)&(guest_pte));
100
101     if (shdw_ptr_list == NULL) {
102         return 0;
103     }
104
105     list_for_each_entry_safe(shdw_ptr, tmp_shdw_ptr, shdw_ptr_list, node) {
106         if ((shdw_ptr->pg_index == pg_index) &&
107             (shdw_ptr->dev_index == dev_index)) {
108
109             // Trigger faults for next shadow access
110             shdw_ptr->shadow_pte->present = 0;
111
112             // Delete entry from list
113             list_del(&(shdw_ptr->node));
114             V3_Free(shdw_ptr);
115         }
116     }
117
118     return 0;
119 }
120
121
122
123 int v3_swap_flush(struct guest_info * info) {
124     struct v3_sym_swap_state * swap_state = &(info->swap_state);
125     struct hashtable_iter * ht_iter = v3_create_htable_iter(swap_state->shdw_ptr_ht);
126
127     PrintDebug("Flushing Symbiotic Swap table\n");
128
129     while (ht_iter->entry) {
130         struct shadow_pointer * tmp_shdw_ptr = NULL;
131         struct shadow_pointer * shdw_ptr = NULL;
132         struct list_head * shdw_ptr_list = (struct list_head *)v3_htable_get_iter_value(ht_iter);
133
134         // delete all swapped entries
135         // we can leave the list_head structures and reuse them for the next round
136         
137         list_for_each_entry_safe(shdw_ptr, tmp_shdw_ptr, shdw_ptr_list, node) {
138             // Trigger faults for next shadow access
139             shdw_ptr->shadow_pte->present = 0;
140             
141             // Delete entry from list
142             list_del(&(shdw_ptr->node));
143             V3_Free(shdw_ptr);      
144         }
145
146         v3_htable_iter_advance(ht_iter);
147     }
148
149     return 0;
150 }
151
152
153 addr_t v3_get_swapped_pg_addr(struct guest_info * info, pte32_t * shadow_pte, pte32_t * guest_pte) {
154     struct list_head * shdw_ptr_list = NULL;
155     struct v3_sym_swap_state * swap_state = &(info->swap_state);
156     struct shadow_pointer * shdw_ptr = NULL;
157     void * swp_page_ptr = NULL;
158     int dev_index = get_dev_index(guest_pte);
159     struct v3_swap_dev * swp_dev = &(swap_state->devs[dev_index]);
160
161     if (! swp_dev->present ) {
162         return 0;
163     }
164
165     swp_page_ptr = swp_dev->ops->get_swap_entry(get_pg_index(guest_pte), swp_dev->private_data);
166
167     if (swp_page_ptr == NULL) {
168         PrintError("Swapped out page not found on swap device\n");
169         return 0;
170     }
171
172     shdw_ptr_list = (struct list_head *)v3_htable_search(swap_state->shdw_ptr_ht, (addr_t)*(uint32_t *)guest_pte);
173
174     if (shdw_ptr_list == NULL) {
175         shdw_ptr_list = (struct list_head *)V3_Malloc(sizeof(struct list_head *));
176         INIT_LIST_HEAD(shdw_ptr_list);
177         v3_htable_insert(swap_state->shdw_ptr_ht, (addr_t)*(uint32_t *)guest_pte, (addr_t)shdw_ptr_list);
178     }
179
180     shdw_ptr = (struct shadow_pointer *)V3_Malloc(sizeof(struct shadow_pointer));
181
182     shdw_ptr->shadow_pte = shadow_pte;
183     shdw_ptr->guest_pte = *(uint32_t *)guest_pte;
184     shdw_ptr->pg_index = get_pg_index(guest_pte);
185     shdw_ptr->dev_index = get_dev_index(guest_pte);
186
187     // We don't check for conflicts, because it should not happen...
188     list_add(&(shdw_ptr->node), shdw_ptr_list);
189
190     return PAGE_BASE_ADDR((addr_t)V3_PAddr(swp_page_ptr));
191 }