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.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
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.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
19 #include <palacios/vmm.h>
22 #include <palacios/vmm_sym_swap.h>
23 #include <palacios/vmm_list.h>
26 // This is a hack and 32 bit linux specific.... need to fix...
29 uint32_t dev_index : 8;
30 uint32_t pg_index : 23;
34 struct shadow_pointer {
42 struct list_head node;
46 static uint_t swap_hash_fn(addr_t key) {
47 return v3_hash_long(key, 32);
51 static int swap_eq_fn(addr_t key1, addr_t key2) {
52 return (key1 == key2);
57 static inline uint32_t get_pg_index(pte32_t * pte) {
58 return ((struct swap_pte *)pte)->pg_index;
62 static inline uint32_t get_dev_index(pte32_t * pte) {
63 return ((struct swap_pte *)pte)->dev_index;
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);
72 PrintDebug("Initialized Symbiotic Swap\n");
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);
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;
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};
99 shdw_ptr_list = (struct list_head * )v3_htable_search(swap_state->shdw_ptr_ht, *(addr_t *)&(guest_pte));
101 if (shdw_ptr_list == NULL) {
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)) {
109 // Trigger faults for next shadow access
110 shdw_ptr->shadow_pte->present = 0;
112 // Delete entry from list
113 list_del(&(shdw_ptr->node));
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);
127 PrintDebug("Flushing Symbiotic Swap table\n");
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);
134 // delete all swapped entries
135 // we can leave the list_head structures and reuse them for the next round
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;
141 // Delete entry from list
142 list_del(&(shdw_ptr->node));
146 v3_htable_iter_advance(ht_iter);
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]);
161 if (! swp_dev->present ) {
165 swp_page_ptr = swp_dev->ops->get_swap_entry(get_pg_index(guest_pte), swp_dev->private_data);
167 if (swp_page_ptr == NULL) {
168 PrintError("Swapped out page not found on swap device\n");
172 shdw_ptr_list = (struct list_head *)v3_htable_search(swap_state->shdw_ptr_ht, (addr_t)*(uint32_t *)guest_pte);
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);
179 shdw_ptr = (struct shadow_pointer *)V3_Malloc(sizeof(struct shadow_pointer));
181 shdw_ptr->shadow_pte = shadow_pte;
182 shdw_ptr->guest_pte = *(uint32_t *)guest_pte;
183 shdw_ptr->pg_index = get_pg_index(guest_pte);
184 shdw_ptr->dev_index = get_dev_index(guest_pte);
186 // We don't check for conflicts, because it should not happen...
187 list_add(&(shdw_ptr->node), shdw_ptr_list);
189 return PAGE_BASE_ADDR((addr_t)V3_PAddr(swp_page_ptr));