diff options
Diffstat (limited to 'drivers/lguest/page_tables.c')
-rw-r--r-- | drivers/lguest/page_tables.c | 45 |
1 files changed, 19 insertions, 26 deletions
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index 8aaad65c3bb5..cf94326f1b59 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c | |||
@@ -380,7 +380,7 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode) | |||
380 | * And we copy the flags to the shadow PMD entry. The page | 380 | * And we copy the flags to the shadow PMD entry. The page |
381 | * number in the shadow PMD is the page we just allocated. | 381 | * number in the shadow PMD is the page we just allocated. |
382 | */ | 382 | */ |
383 | native_set_pmd(spmd, __pmd(__pa(ptepage) | pmd_flags(gpmd))); | 383 | set_pmd(spmd, __pmd(__pa(ptepage) | pmd_flags(gpmd))); |
384 | } | 384 | } |
385 | 385 | ||
386 | /* | 386 | /* |
@@ -447,7 +447,7 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode) | |||
447 | * we will come back here when a write does actually occur, so | 447 | * we will come back here when a write does actually occur, so |
448 | * we can update the Guest's _PAGE_DIRTY flag. | 448 | * we can update the Guest's _PAGE_DIRTY flag. |
449 | */ | 449 | */ |
450 | native_set_pte(spte, gpte_to_spte(cpu, pte_wrprotect(gpte), 0)); | 450 | set_pte(spte, gpte_to_spte(cpu, pte_wrprotect(gpte), 0)); |
451 | 451 | ||
452 | /* | 452 | /* |
453 | * Finally, we write the Guest PTE entry back: we've set the | 453 | * Finally, we write the Guest PTE entry back: we've set the |
@@ -528,7 +528,7 @@ static void release_pmd(pmd_t *spmd) | |||
528 | /* Now we can free the page of PTEs */ | 528 | /* Now we can free the page of PTEs */ |
529 | free_page((long)ptepage); | 529 | free_page((long)ptepage); |
530 | /* And zero out the PMD entry so we never release it twice. */ | 530 | /* And zero out the PMD entry so we never release it twice. */ |
531 | native_set_pmd(spmd, __pmd(0)); | 531 | set_pmd(spmd, __pmd(0)); |
532 | } | 532 | } |
533 | } | 533 | } |
534 | 534 | ||
@@ -833,15 +833,15 @@ static void do_set_pte(struct lg_cpu *cpu, int idx, | |||
833 | */ | 833 | */ |
834 | if (pte_flags(gpte) & (_PAGE_DIRTY | _PAGE_ACCESSED)) { | 834 | if (pte_flags(gpte) & (_PAGE_DIRTY | _PAGE_ACCESSED)) { |
835 | check_gpte(cpu, gpte); | 835 | check_gpte(cpu, gpte); |
836 | native_set_pte(spte, | 836 | set_pte(spte, |
837 | gpte_to_spte(cpu, gpte, | 837 | gpte_to_spte(cpu, gpte, |
838 | pte_flags(gpte) & _PAGE_DIRTY)); | 838 | pte_flags(gpte) & _PAGE_DIRTY)); |
839 | } else { | 839 | } else { |
840 | /* | 840 | /* |
841 | * Otherwise kill it and we can demand_page() | 841 | * Otherwise kill it and we can demand_page() |
842 | * it in later. | 842 | * it in later. |
843 | */ | 843 | */ |
844 | native_set_pte(spte, __pte(0)); | 844 | set_pte(spte, __pte(0)); |
845 | } | 845 | } |
846 | #ifdef CONFIG_X86_PAE | 846 | #ifdef CONFIG_X86_PAE |
847 | } | 847 | } |
@@ -983,25 +983,22 @@ static unsigned long setup_pagetables(struct lguest *lg, | |||
983 | */ | 983 | */ |
984 | for (i = j = 0; i < mapped_pages && j < PTRS_PER_PMD; | 984 | for (i = j = 0; i < mapped_pages && j < PTRS_PER_PMD; |
985 | i += PTRS_PER_PTE, j++) { | 985 | i += PTRS_PER_PTE, j++) { |
986 | /* FIXME: native_set_pmd is overkill here. */ | 986 | pmd = pfn_pmd(((unsigned long)&linear[i] - mem_base)/PAGE_SIZE, |
987 | native_set_pmd(&pmd, __pmd(((unsigned long)(linear + i) | 987 | __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER)); |
988 | - mem_base) | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER)); | ||
989 | 988 | ||
990 | if (copy_to_user(&pmds[j], &pmd, sizeof(pmd)) != 0) | 989 | if (copy_to_user(&pmds[j], &pmd, sizeof(pmd)) != 0) |
991 | return -EFAULT; | 990 | return -EFAULT; |
992 | } | 991 | } |
993 | 992 | ||
994 | /* One PGD entry, pointing to that PMD page. */ | 993 | /* One PGD entry, pointing to that PMD page. */ |
995 | set_pgd(&pgd, __pgd(((u32)pmds - mem_base) | _PAGE_PRESENT)); | 994 | pgd = __pgd(((unsigned long)pmds - mem_base) | _PAGE_PRESENT); |
996 | /* Copy it in as the first PGD entry (ie. addresses 0-1G). */ | 995 | /* Copy it in as the first PGD entry (ie. addresses 0-1G). */ |
997 | if (copy_to_user(&pgdir[0], &pgd, sizeof(pgd)) != 0) | 996 | if (copy_to_user(&pgdir[0], &pgd, sizeof(pgd)) != 0) |
998 | return -EFAULT; | 997 | return -EFAULT; |
999 | /* | 998 | /* |
1000 | * And the third PGD entry (ie. addresses 3G-4G). | 999 | * And the other PGD entry to make the linear mapping at PAGE_OFFSET |
1001 | * | ||
1002 | * FIXME: This assumes that PAGE_OFFSET for the Guest is 0xC0000000. | ||
1003 | */ | 1000 | */ |
1004 | if (copy_to_user(&pgdir[3], &pgd, sizeof(pgd)) != 0) | 1001 | if (copy_to_user(&pgdir[KERNEL_PGD_BOUNDARY], &pgd, sizeof(pgd))) |
1005 | return -EFAULT; | 1002 | return -EFAULT; |
1006 | #else | 1003 | #else |
1007 | /* | 1004 | /* |
@@ -1141,15 +1138,13 @@ void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages) | |||
1141 | { | 1138 | { |
1142 | pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages); | 1139 | pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages); |
1143 | pte_t regs_pte; | 1140 | pte_t regs_pte; |
1144 | unsigned long pfn; | ||
1145 | 1141 | ||
1146 | #ifdef CONFIG_X86_PAE | 1142 | #ifdef CONFIG_X86_PAE |
1147 | pmd_t switcher_pmd; | 1143 | pmd_t switcher_pmd; |
1148 | pmd_t *pmd_table; | 1144 | pmd_t *pmd_table; |
1149 | 1145 | ||
1150 | /* FIXME: native_set_pmd is overkill here. */ | 1146 | switcher_pmd = pfn_pmd(__pa(switcher_pte_page) >> PAGE_SHIFT, |
1151 | native_set_pmd(&switcher_pmd, pfn_pmd(__pa(switcher_pte_page) >> | 1147 | PAGE_KERNEL_EXEC); |
1152 | PAGE_SHIFT, PAGE_KERNEL_EXEC)); | ||
1153 | 1148 | ||
1154 | /* Figure out where the pmd page is, by reading the PGD, and converting | 1149 | /* Figure out where the pmd page is, by reading the PGD, and converting |
1155 | * it to a virtual address. */ | 1150 | * it to a virtual address. */ |
@@ -1157,7 +1152,7 @@ void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages) | |||
1157 | pgdirs[cpu->cpu_pgd].pgdir[SWITCHER_PGD_INDEX]) | 1152 | pgdirs[cpu->cpu_pgd].pgdir[SWITCHER_PGD_INDEX]) |
1158 | << PAGE_SHIFT); | 1153 | << PAGE_SHIFT); |
1159 | /* Now write it into the shadow page table. */ | 1154 | /* Now write it into the shadow page table. */ |
1160 | native_set_pmd(&pmd_table[SWITCHER_PMD_INDEX], switcher_pmd); | 1155 | set_pmd(&pmd_table[SWITCHER_PMD_INDEX], switcher_pmd); |
1161 | #else | 1156 | #else |
1162 | pgd_t switcher_pgd; | 1157 | pgd_t switcher_pgd; |
1163 | 1158 | ||
@@ -1179,10 +1174,8 @@ void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages) | |||
1179 | * page is already mapped there, we don't have to copy them out | 1174 | * page is already mapped there, we don't have to copy them out |
1180 | * again. | 1175 | * again. |
1181 | */ | 1176 | */ |
1182 | pfn = __pa(cpu->regs_page) >> PAGE_SHIFT; | 1177 | regs_pte = pfn_pte(__pa(cpu->regs_page) >> PAGE_SHIFT, PAGE_KERNEL); |
1183 | native_set_pte(®s_pte, pfn_pte(pfn, PAGE_KERNEL)); | 1178 | set_pte(&switcher_pte_page[pte_index((unsigned long)pages)], regs_pte); |
1184 | native_set_pte(&switcher_pte_page[pte_index((unsigned long)pages)], | ||
1185 | regs_pte); | ||
1186 | } | 1179 | } |
1187 | /*:*/ | 1180 | /*:*/ |
1188 | 1181 | ||
@@ -1209,7 +1202,7 @@ static __init void populate_switcher_pte_page(unsigned int cpu, | |||
1209 | 1202 | ||
1210 | /* The first entries are easy: they map the Switcher code. */ | 1203 | /* The first entries are easy: they map the Switcher code. */ |
1211 | for (i = 0; i < pages; i++) { | 1204 | for (i = 0; i < pages; i++) { |
1212 | native_set_pte(&pte[i], mk_pte(switcher_page[i], | 1205 | set_pte(&pte[i], mk_pte(switcher_page[i], |
1213 | __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED))); | 1206 | __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED))); |
1214 | } | 1207 | } |
1215 | 1208 | ||
@@ -1217,14 +1210,14 @@ static __init void populate_switcher_pte_page(unsigned int cpu, | |||
1217 | i = pages + cpu*2; | 1210 | i = pages + cpu*2; |
1218 | 1211 | ||
1219 | /* First page (Guest registers) is writable from the Guest */ | 1212 | /* First page (Guest registers) is writable from the Guest */ |
1220 | native_set_pte(&pte[i], pfn_pte(page_to_pfn(switcher_page[i]), | 1213 | set_pte(&pte[i], pfn_pte(page_to_pfn(switcher_page[i]), |
1221 | __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_RW))); | 1214 | __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_RW))); |
1222 | 1215 | ||
1223 | /* | 1216 | /* |
1224 | * The second page contains the "struct lguest_ro_state", and is | 1217 | * The second page contains the "struct lguest_ro_state", and is |
1225 | * read-only. | 1218 | * read-only. |
1226 | */ | 1219 | */ |
1227 | native_set_pte(&pte[i+1], pfn_pte(page_to_pfn(switcher_page[i+1]), | 1220 | set_pte(&pte[i+1], pfn_pte(page_to_pfn(switcher_page[i+1]), |
1228 | __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED))); | 1221 | __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED))); |
1229 | } | 1222 | } |
1230 | 1223 | ||