diff options
Diffstat (limited to 'arch/x86/xen/mmu.c')
| -rw-r--r-- | arch/x86/xen/mmu.c | 75 |
1 files changed, 32 insertions, 43 deletions
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 3525ef523a74..df40bf74ea75 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
| @@ -179,50 +179,56 @@ out: | |||
| 179 | preempt_enable(); | 179 | preempt_enable(); |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | pteval_t xen_pte_val(pte_t pte) | 182 | /* Assume pteval_t is equivalent to all the other *val_t types. */ |
| 183 | static pteval_t pte_mfn_to_pfn(pteval_t val) | ||
| 184 | { | ||
| 185 | if (val & _PAGE_PRESENT) { | ||
| 186 | unsigned long mfn = (val & PTE_MASK) >> PAGE_SHIFT; | ||
| 187 | pteval_t flags = val & ~PTE_MASK; | ||
| 188 | val = (mfn_to_pfn(mfn) << PAGE_SHIFT) | flags; | ||
| 189 | } | ||
| 190 | |||
| 191 | return val; | ||
| 192 | } | ||
| 193 | |||
| 194 | static pteval_t pte_pfn_to_mfn(pteval_t val) | ||
| 183 | { | 195 | { |
| 184 | pteval_t ret = pte.pte; | 196 | if (val & _PAGE_PRESENT) { |
| 197 | unsigned long pfn = (val & PTE_MASK) >> PAGE_SHIFT; | ||
| 198 | pteval_t flags = val & ~PTE_MASK; | ||
| 199 | val = (pfn_to_mfn(pfn) << PAGE_SHIFT) | flags; | ||
| 200 | } | ||
| 185 | 201 | ||
| 186 | if (ret & _PAGE_PRESENT) | 202 | return val; |
| 187 | ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT; | 203 | } |
| 188 | 204 | ||
| 189 | return ret; | 205 | pteval_t xen_pte_val(pte_t pte) |
| 206 | { | ||
| 207 | return pte_mfn_to_pfn(pte.pte); | ||
| 190 | } | 208 | } |
| 191 | 209 | ||
| 192 | pgdval_t xen_pgd_val(pgd_t pgd) | 210 | pgdval_t xen_pgd_val(pgd_t pgd) |
| 193 | { | 211 | { |
| 194 | pgdval_t ret = pgd.pgd; | 212 | return pte_mfn_to_pfn(pgd.pgd); |
| 195 | if (ret & _PAGE_PRESENT) | ||
| 196 | ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT; | ||
| 197 | return ret; | ||
| 198 | } | 213 | } |
| 199 | 214 | ||
| 200 | pte_t xen_make_pte(pteval_t pte) | 215 | pte_t xen_make_pte(pteval_t pte) |
| 201 | { | 216 | { |
| 202 | if (pte & _PAGE_PRESENT) { | 217 | pte = pte_pfn_to_mfn(pte); |
| 203 | pte = phys_to_machine(XPADDR(pte)).maddr; | 218 | return native_make_pte(pte); |
| 204 | pte &= ~(_PAGE_PCD | _PAGE_PWT); | ||
| 205 | } | ||
| 206 | |||
| 207 | return (pte_t){ .pte = pte }; | ||
| 208 | } | 219 | } |
| 209 | 220 | ||
| 210 | pgd_t xen_make_pgd(pgdval_t pgd) | 221 | pgd_t xen_make_pgd(pgdval_t pgd) |
| 211 | { | 222 | { |
| 212 | if (pgd & _PAGE_PRESENT) | 223 | pgd = pte_pfn_to_mfn(pgd); |
| 213 | pgd = phys_to_machine(XPADDR(pgd)).maddr; | 224 | return native_make_pgd(pgd); |
| 214 | |||
| 215 | return (pgd_t){ pgd }; | ||
| 216 | } | 225 | } |
| 217 | 226 | ||
| 218 | pmdval_t xen_pmd_val(pmd_t pmd) | 227 | pmdval_t xen_pmd_val(pmd_t pmd) |
| 219 | { | 228 | { |
| 220 | pmdval_t ret = native_pmd_val(pmd); | 229 | return pte_mfn_to_pfn(pmd.pmd); |
| 221 | if (ret & _PAGE_PRESENT) | ||
| 222 | ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT; | ||
| 223 | return ret; | ||
| 224 | } | 230 | } |
| 225 | #ifdef CONFIG_X86_PAE | 231 | |
| 226 | void xen_set_pud(pud_t *ptr, pud_t val) | 232 | void xen_set_pud(pud_t *ptr, pud_t val) |
| 227 | { | 233 | { |
| 228 | struct multicall_space mcs; | 234 | struct multicall_space mcs; |
| @@ -267,17 +273,9 @@ void xen_pmd_clear(pmd_t *pmdp) | |||
| 267 | 273 | ||
| 268 | pmd_t xen_make_pmd(pmdval_t pmd) | 274 | pmd_t xen_make_pmd(pmdval_t pmd) |
| 269 | { | 275 | { |
| 270 | if (pmd & _PAGE_PRESENT) | 276 | pmd = pte_pfn_to_mfn(pmd); |
| 271 | pmd = phys_to_machine(XPADDR(pmd)).maddr; | ||
| 272 | |||
| 273 | return native_make_pmd(pmd); | 277 | return native_make_pmd(pmd); |
| 274 | } | 278 | } |
| 275 | #else /* !PAE */ | ||
| 276 | void xen_set_pte(pte_t *ptep, pte_t pte) | ||
| 277 | { | ||
| 278 | *ptep = pte; | ||
| 279 | } | ||
| 280 | #endif /* CONFIG_X86_PAE */ | ||
| 281 | 279 | ||
| 282 | /* | 280 | /* |
| 283 | (Yet another) pagetable walker. This one is intended for pinning a | 281 | (Yet another) pagetable walker. This one is intended for pinning a |
| @@ -430,8 +428,6 @@ static int pin_page(struct page *page, enum pt_level level) | |||
| 430 | read-only, and can be pinned. */ | 428 | read-only, and can be pinned. */ |
| 431 | void xen_pgd_pin(pgd_t *pgd) | 429 | void xen_pgd_pin(pgd_t *pgd) |
| 432 | { | 430 | { |
| 433 | unsigned level; | ||
| 434 | |||
| 435 | xen_mc_batch(); | 431 | xen_mc_batch(); |
| 436 | 432 | ||
| 437 | if (pgd_walk(pgd, pin_page, TASK_SIZE)) { | 433 | if (pgd_walk(pgd, pin_page, TASK_SIZE)) { |
| @@ -441,14 +437,7 @@ void xen_pgd_pin(pgd_t *pgd) | |||
| 441 | xen_mc_batch(); | 437 | xen_mc_batch(); |
| 442 | } | 438 | } |
| 443 | 439 | ||
| 444 | #ifdef CONFIG_X86_PAE | 440 | xen_do_pin(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(pgd))); |
| 445 | level = MMUEXT_PIN_L3_TABLE; | ||
| 446 | #else | ||
| 447 | level = MMUEXT_PIN_L2_TABLE; | ||
| 448 | #endif | ||
| 449 | |||
| 450 | xen_do_pin(level, PFN_DOWN(__pa(pgd))); | ||
| 451 | |||
| 452 | xen_mc_issue(0); | 441 | xen_mc_issue(0); |
| 453 | } | 442 | } |
| 454 | 443 | ||
