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.


217373ab037330bdc9080ede1d90da499d106b3a
[palacios.git] / palacios / src / palacios / vmm_direct_paging_64.h
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, Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
11  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
12  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
13  * All rights reserved.
14  *
15  * Author: Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
16  *
17  * This is free software.  You are permitted to use,
18  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
19  */
20
21 #ifndef __VMM_DIRECT_PAGING_64_H__
22 #define __VMM_DIRECT_PAGING_64_H__
23
24 #include <palacios/vmm_mem.h>
25 #include <palacios/vmm_paging.h>
26 #include <palacios/vmm.h>
27 #include <palacios/vm_guest_mem.h>
28 #include <palacios/vm_guest.h>
29
30 // Reference: AMD Software Developer Manual Vol.2 Ch.5 "Page Translation and Protection"
31
32 static inline int handle_passthrough_pagefault_64(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
33     pml4e64_t * pml      = NULL;
34     pdpe64_t * pdpe      = NULL;
35     pde64_t * pde        = NULL;
36     pde64_2MB_t * pde2mb = NULL;
37     pte64_t * pte        = NULL;
38     addr_t host_addr     = 0;
39
40     int pml_index  = PML4E64_INDEX(fault_addr);
41     int pdpe_index = PDPE64_INDEX(fault_addr);
42     int pde_index  = PDE64_INDEX(fault_addr);
43     int pte_index  = PTE64_INDEX(fault_addr);
44
45     struct v3_mem_region * region =  v3_get_mem_region(core->vm_info, core->vcpu_id, fault_addr);
46     int page_size = PAGE_SIZE_4KB;
47
48     if (region == NULL) {
49         PrintError("%s: invalid region, addr=%p\n", __FUNCTION__, (void *)fault_addr);
50         return -1;
51     }
52
53     /*  Check if:
54      *  1. the guest is configured to use large pages and 
55      *  2. the memory regions can be referenced by a large page
56      */
57     if ((core->use_large_pages == 1) || (core->use_giant_pages == 1)) {
58         page_size = v3_get_max_page_size(core, fault_addr, LONG);
59     }
60
61     PrintDebug("Using page size of %dKB\n", page_size / 1024);
62
63  
64     // Lookup the correct PML address based on the PAGING MODE
65     if (core->shdw_pg_mode == SHADOW_PAGING) {
66         pml = CR3_TO_PML4E64_VA(core->ctrl_regs.cr3);
67     } else {
68         pml = CR3_TO_PML4E64_VA(core->direct_map_pt);
69     }
70
71     //Fix up the PML entry
72     if (pml[pml_index].present == 0) {
73         pdpe = (pdpe64_t *)create_generic_pt_page();
74    
75         // Set default PML Flags...
76         pml[pml_index].present = 1;
77         pml[pml_index].writable = 1;
78         pml[pml_index].user_page = 1;
79
80         pml[pml_index].pdp_base_addr = PAGE_BASE_ADDR_4KB((addr_t)V3_PAddr(pdpe));    
81     } else {
82         pdpe = V3_VAddr((void*)BASE_TO_PAGE_ADDR_4KB(pml[pml_index].pdp_base_addr));
83     }
84
85     // Fix up the PDPE entry
86     if (pdpe[pdpe_index].present == 0) {
87         pde = (pde64_t *)create_generic_pt_page();
88         
89         // Set default PDPE Flags...
90         pdpe[pdpe_index].present = 1;
91         pdpe[pdpe_index].writable = 1;
92         pdpe[pdpe_index].user_page = 1;
93
94         pdpe[pdpe_index].pd_base_addr = PAGE_BASE_ADDR_4KB((addr_t)V3_PAddr(pde));    
95     } else {
96         pde = V3_VAddr((void*)BASE_TO_PAGE_ADDR_4KB(pdpe[pdpe_index].pd_base_addr));
97     }
98
99     // Fix up the 2MiB PDE and exit here
100     if (page_size == PAGE_SIZE_2MB) {
101         pde2mb = (pde64_2MB_t *)pde; // all but these two lines are the same for PTE
102         pde2mb[pde_index].large_page = 1;
103
104         if (pde2mb[pde_index].present == 0) {
105             pde2mb[pde_index].user_page = 1;
106
107             if ( (region->flags.alloced == 1) && 
108                  (region->flags.read == 1)) {
109                 // Full access
110                 pde2mb[pde_index].present = 1;
111
112                 if (region->flags.write == 1) {
113                     pde2mb[pde_index].writable = 1;
114                 } else {
115                     pde2mb[pde_index].writable = 0;
116                 }
117
118                 if (v3_gpa_to_hpa(core, fault_addr, &host_addr) == -1) {
119                     PrintError("Error Could not translate fault addr (%p)\n", (void *)fault_addr);
120                     return -1;
121                 }
122
123                 pde2mb[pde_index].page_base_addr = PAGE_BASE_ADDR_2MB(host_addr);
124             } else {
125                 return region->unhandled(core, fault_addr, fault_addr, region, error_code);
126             }
127         } else {
128             // We fix all permissions on the first pass, 
129             // so we only get here if its an unhandled exception
130
131             return region->unhandled(core, fault_addr, fault_addr, region, error_code);
132         }
133
134         // All done
135         return 0;
136     } 
137
138     // Continue with the 4KiB page heirarchy
139     
140     // Fix up the PDE entry
141     if (pde[pde_index].present == 0) {
142         pte = (pte64_t *)create_generic_pt_page();
143         
144         pde[pde_index].present = 1;
145         pde[pde_index].writable = 1;
146         pde[pde_index].user_page = 1;
147         
148         pde[pde_index].pt_base_addr = PAGE_BASE_ADDR_4KB((addr_t)V3_PAddr(pte));
149     } else {
150         pte = V3_VAddr((void*)BASE_TO_PAGE_ADDR_4KB(pde[pde_index].pt_base_addr));
151     }
152
153     // Fix up the PTE entry
154     if (pte[pte_index].present == 0) {
155         pte[pte_index].user_page = 1;
156         
157         if ((region->flags.alloced == 1) && 
158             (region->flags.read == 1)) {
159             // Full access
160             pte[pte_index].present = 1;
161
162             if (region->flags.write == 1) {
163                 pte[pte_index].writable = 1;
164             } else {
165                 pte[pte_index].writable = 0;
166             }
167
168             if (v3_gpa_to_hpa(core, fault_addr, &host_addr) == -1) {
169                 PrintError("Error Could not translate fault addr (%p)\n", (void *)fault_addr);
170                 return -1;
171             }
172
173             pte[pte_index].page_base_addr = PAGE_BASE_ADDR_4KB(host_addr);
174         } else {
175             return region->unhandled(core, fault_addr, fault_addr, region, error_code);
176         }
177     } else {
178         // We fix all permissions on the first pass, 
179         // so we only get here if its an unhandled exception
180
181         return region->unhandled(core, fault_addr, fault_addr, region, error_code);
182     }
183
184     return 0;
185 }
186
187 static inline int invalidate_addr_64(struct guest_info * core, addr_t inv_addr) {
188     pml4e64_t * pml = NULL;
189     pdpe64_t * pdpe = NULL;
190     pde64_t * pde = NULL;
191     pte64_t * pte = NULL;
192
193
194     // TODO:
195     // Call INVLPGA
196
197     // clear the page table entry
198     int pml_index = PML4E64_INDEX(inv_addr);
199     int pdpe_index = PDPE64_INDEX(inv_addr);
200     int pde_index = PDE64_INDEX(inv_addr);
201     int pte_index = PTE64_INDEX(inv_addr);
202
203     
204     // Lookup the correct PDE address based on the PAGING MODE
205     if (core->shdw_pg_mode == SHADOW_PAGING) {
206         pml = CR3_TO_PML4E64_VA(core->ctrl_regs.cr3);
207     } else {
208         pml = CR3_TO_PML4E64_VA(core->direct_map_pt);
209     }
210
211     if (pml[pml_index].present == 0) {
212         return 0;
213     }
214
215     pdpe = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pml[pml_index].pdp_base_addr));
216
217     if (pdpe[pdpe_index].present == 0) {
218         return 0;
219     } else if (pdpe[pdpe_index].large_page == 1) { // 1GiB
220         pdpe[pdpe_index].present = 0;
221         pdpe[pdpe_index].writable = 0;
222         pdpe[pdpe_index].user_page = 0;
223         return 0;
224     }
225
226     pde = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pdpe[pdpe_index].pd_base_addr));
227
228     if (pde[pde_index].present == 0) {
229         return 0;
230     } else if (pde[pde_index].large_page == 1) { // 2MiB
231         pde[pde_index].present = 0;
232         pde[pde_index].writable = 0;
233         pde[pde_index].user_page = 0;
234         return 0;
235     }
236
237     pte = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pde[pde_index].pt_base_addr));
238
239     pte[pte_index].present = 0; // 4KiB
240     pte[pte_index].writable = 0;
241     pte[pte_index].user_page = 0;
242
243     return 0;
244 }
245
246
247
248 #endif