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.


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