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.


Refactoring and additions to direct paging (nested and passthrough)
[palacios.git] / palacios / src / palacios / vmm_direct_paging_32pae.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_32PAE_H__
22 #define __VMM_DIRECT_PAGING_32PAE_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 /* This always builds 3 level page tables - no large pages */
31
32 static inline int handle_passthrough_pagefault_32pae(struct guest_info * info, 
33                                                      addr_t fault_addr, 
34                                                      pf_error_t error_code,
35                                                      addr_t *actual_start, addr_t *actual_end) {
36     pdpe32pae_t * pdpe = NULL;
37     pde32pae_t * pde = NULL;
38     pte32pae_t * pte = NULL;
39     addr_t host_addr = 0;
40
41     int pdpe_index = PDPE32PAE_INDEX(fault_addr);
42     int pde_index = PDE32PAE_INDEX(fault_addr);
43     int pte_index = PTE32PAE_INDEX(fault_addr);
44     
45
46     struct v3_mem_region * region =  v3_get_mem_region(info->vm_info, info->vcpu_id, fault_addr);
47   
48     if (region == NULL) {
49         PrintError(info->vm_info, info, "Invalid region in passthrough page fault 32PAE, addr=%p\n", 
50                    (void *)fault_addr);
51         return -1;
52     }
53
54     PrintDebug(info->vm_info, info, "Direct Paging 32PAE page fault handler=%p\n", (void *)fault_addr);
55
56     // Lookup the correct PDPE address based on the PAGING MODE
57     if (info->shdw_pg_mode == SHADOW_PAGING) {
58         pdpe = CR3_TO_PDPE32PAE_VA(info->ctrl_regs.cr3);
59     } else {
60         pdpe = CR3_TO_PDPE32PAE_VA(info->direct_map_pt);
61     }
62  
63     PrintDebug(info->vm_info, info, "Top level pdpe error pdp address=%p\n", (void *)pdpe);
64     // Fix up the PDPE entry
65     if (pdpe[pdpe_index].present == 0) {
66         pde = (pde32pae_t *)create_generic_pt_page(info);
67         PrintDebug(info->vm_info, info, "Creating a new pd page=%p\n", (void *)pde);
68         pdpe[pdpe_index].present = 1;
69         // Set default PDPE Flags...
70         pdpe[pdpe_index].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));    
71     } else {
72         pde = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pdpe[pdpe_index].pd_base_addr));
73     }
74     PrintDebug(info->vm_info, info, "Handling pde error pd base address =%p\n", (void *)pde);
75
76     *actual_start = BASE_TO_PAGE_ADDR_4KB(PAGE_BASE_ADDR_4KB(fault_addr));
77     *actual_end = BASE_TO_PAGE_ADDR_4KB(PAGE_BASE_ADDR_4KB(fault_addr)+1)-1;
78
79     // Fix up the PDE entry
80     if (pde[pde_index].present == 0) {
81         pte = (pte32pae_t *)create_generic_pt_page(info);
82         PrintDebug(info->vm_info, info, "Creating a new pt page=%p\n", (void *)pte);
83         pde[pde_index].present = 1;
84         pde[pde_index].writable = 1;
85         pde[pde_index].user_page = 1;
86
87         pde[pde_index].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
88     } else {
89         pte = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pde[pde_index].pt_base_addr));
90     }
91
92     PrintDebug(info->vm_info, info, "Handling pte error pt base address=%p\n", (void *)pte);
93
94
95     // Fix up the PTE entry
96     if (pte[pte_index].present == 0) {
97         pte[pte_index].user_page = 1;
98
99         if ((region->flags.alloced == 1) && 
100             (region->flags.read == 1)) {
101
102             pte[pte_index].present = 1;
103
104             if (region->flags.write == 1) {
105                 pte[pte_index].writable = 1;
106             } else {
107                 pte[pte_index].writable = 0;
108             }
109
110             if (v3_gpa_to_hpa(info, fault_addr, &host_addr) == -1) {
111                 PrintError(info->vm_info, info, "Could not translate fault address (%p)\n", (void *)fault_addr);
112                 return -1;
113             }
114
115             pte[pte_index].page_base_addr = PAGE_BASE_ADDR(host_addr);
116             PrintDebug(info->vm_info, info, "PTE mapped to =%p\n", (void *)host_addr);
117             PrintDebug(info->vm_info, info, "PTE is =%llx\n", *(uint64_t *)&(pte[pte_index]));
118         } else {
119             return region->unhandled(info, fault_addr, fault_addr, region, error_code);
120         }
121     } else {
122         return region->unhandled(info, fault_addr, fault_addr, region, error_code);
123     }
124    
125     PrintDebug(info->vm_info, info, "Handler ends with fault address=%p\n", (void *)fault_addr);
126
127     return 0;
128 }
129
130
131 static inline int invalidate_addr_32pae_internal(struct guest_info * info, addr_t inv_addr,
132                                                  addr_t *actual_start, uint64_t *actual_size) {
133     pdpe32pae_t * pdpe = NULL;
134     pde32pae_t * pde = NULL;
135     pte32pae_t * pte = NULL;
136
137
138     // TODO:
139     // Call INVLPGA
140
141     // clear the page table entry
142     int pdpe_index = PDPE32PAE_INDEX(inv_addr);
143     int pde_index = PDE32PAE_INDEX(inv_addr);
144     int pte_index = PTE32PAE_INDEX(inv_addr);
145
146     
147     // Lookup the correct PDE address based on the PAGING MODE
148     if (info->shdw_pg_mode == SHADOW_PAGING) {
149         pdpe = CR3_TO_PDPE32PAE_VA(info->ctrl_regs.cr3);
150     } else {
151         pdpe = CR3_TO_PDPE32PAE_VA(info->direct_map_pt);
152     }    
153
154
155     if (pdpe[pdpe_index].present == 0) {
156         *actual_start = BASE_TO_PAGE_ADDR_1GB(PAGE_BASE_ADDR_1GB(inv_addr));
157         *actual_size = PAGE_SIZE_1GB;
158         return 0;
159     }
160
161     pde = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pdpe[pdpe_index].pd_base_addr));
162
163     if (pde[pde_index].present == 0) {
164         *actual_start = BASE_TO_PAGE_ADDR_2MB(PAGE_BASE_ADDR_2MB(inv_addr));
165         *actual_size = PAGE_SIZE_2MB;
166         return 0;
167     } else if (pde[pde_index].large_page) {
168         pde[pde_index].present = 0;
169         *actual_start = BASE_TO_PAGE_ADDR_2MB(PAGE_BASE_ADDR_2MB(inv_addr));
170         *actual_size = PAGE_SIZE_2MB;
171         return 0;
172     }
173
174     pte = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pde[pde_index].pt_base_addr));
175
176     pte[pte_index].present = 0;
177
178     *actual_start = BASE_TO_PAGE_ADDR_4KB(PAGE_BASE_ADDR_4KB(inv_addr));
179     *actual_size = PAGE_SIZE_4KB;
180     return 0;
181 }
182
183
184
185 static inline int invalidate_addr_32pae(struct guest_info * core, addr_t inv_addr,
186                                         addr_t *actual_start, addr_t *actual_end)
187 {
188   uint64_t len;
189   int rc;
190   
191   rc = invalidate_addr_32pae_internal(core,inv_addr,actual_start,&len);
192
193   *actual_end = *actual_start + len - 1;
194
195   return rc;
196     
197
198 }
199    
200 static inline int invalidate_addr_32pae_range(struct guest_info * core, addr_t inv_addr_start, addr_t inv_addr_end,
201                                               addr_t *actual_start, addr_t *actual_end)
202 {
203   addr_t next;
204   addr_t start;
205   uint64_t len;
206   int rc;
207   
208   for (next=inv_addr_start; next<=inv_addr_end; ) {
209     rc = invalidate_addr_32pae_internal(core,next,&start, &len);
210     if (next==inv_addr_start) { 
211       // first iteration, capture where we start invalidating
212       *actual_start = start;
213     }
214     if (rc) { 
215       return rc;
216     }
217     next = start + len;
218     *actual_end = next;
219   }
220   // last iteration, actual_end is off by one
221   (*actual_end)--;
222   return 0;
223 }
224
225 #endif