diff options
| author | Christoffer Dall <c.dall@virtualopensystems.com> | 2013-01-20 18:28:04 -0500 |
|---|---|---|
| committer | Christoffer Dall <c.dall@virtualopensystems.com> | 2013-01-23 13:29:08 -0500 |
| commit | cc577c26e2e9740b046591a72e77213c556bff19 (patch) | |
| tree | cec417a8f5de11b352146d69fc6c92e2c2de5b78 | |
| parent | 6abc749f635005be78dfcb562c2235511965db6d (diff) | |
ARM: Add page table and page defines needed by KVM
KVM uses the stage-2 page tables and the Hyp page table format,
so we define the fields and page protection flags needed by KVM.
The nomenclature is this:
- page_hyp: PL2 code/data mappings
- page_hyp_device: PL2 device mappings (vgic access)
- page_s2: Stage-2 code/data page mappings
- page_s2_device: Stage-2 device mappings (vgic access)
Reviewed-by: Will Deacon <will.deacon@arm.com>
Reviewed-by: Marcelo Tosatti <mtosatti@redhat.com>
Christoffer Dall <c.dall@virtualopensystems.com>
| -rw-r--r-- | arch/arm/include/asm/pgtable-3level.h | 18 | ||||
| -rw-r--r-- | arch/arm/include/asm/pgtable.h | 7 | ||||
| -rw-r--r-- | arch/arm/mm/mmu.c | 22 |
3 files changed, 47 insertions, 0 deletions
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h index a3f37929940a..6ef8afd1b64c 100644 --- a/arch/arm/include/asm/pgtable-3level.h +++ b/arch/arm/include/asm/pgtable-3level.h | |||
| @@ -104,11 +104,29 @@ | |||
| 104 | */ | 104 | */ |
| 105 | #define L_PGD_SWAPPER (_AT(pgdval_t, 1) << 55) /* swapper_pg_dir entry */ | 105 | #define L_PGD_SWAPPER (_AT(pgdval_t, 1) << 55) /* swapper_pg_dir entry */ |
| 106 | 106 | ||
| 107 | /* | ||
| 108 | * 2nd stage PTE definitions for LPAE. | ||
| 109 | */ | ||
| 110 | #define L_PTE_S2_MT_UNCACHED (_AT(pteval_t, 0x5) << 2) /* MemAttr[3:0] */ | ||
| 111 | #define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* MemAttr[3:0] */ | ||
| 112 | #define L_PTE_S2_MT_WRITEBACK (_AT(pteval_t, 0xf) << 2) /* MemAttr[3:0] */ | ||
| 113 | #define L_PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[1] */ | ||
| 114 | #define L_PTE_S2_RDWR (_AT(pteval_t, 2) << 6) /* HAP[2:1] */ | ||
| 115 | |||
| 116 | /* | ||
| 117 | * Hyp-mode PL2 PTE definitions for LPAE. | ||
| 118 | */ | ||
| 119 | #define L_PTE_HYP L_PTE_USER | ||
| 120 | |||
| 107 | #ifndef __ASSEMBLY__ | 121 | #ifndef __ASSEMBLY__ |
| 108 | 122 | ||
| 109 | #define pud_none(pud) (!pud_val(pud)) | 123 | #define pud_none(pud) (!pud_val(pud)) |
| 110 | #define pud_bad(pud) (!(pud_val(pud) & 2)) | 124 | #define pud_bad(pud) (!(pud_val(pud) & 2)) |
| 111 | #define pud_present(pud) (pud_val(pud)) | 125 | #define pud_present(pud) (pud_val(pud)) |
| 126 | #define pmd_table(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \ | ||
| 127 | PMD_TYPE_TABLE) | ||
| 128 | #define pmd_sect(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \ | ||
| 129 | PMD_TYPE_SECT) | ||
| 112 | 130 | ||
| 113 | #define pud_clear(pudp) \ | 131 | #define pud_clear(pudp) \ |
| 114 | do { \ | 132 | do { \ |
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 9c82f988c0e3..f30ac3b55ba9 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h | |||
| @@ -70,6 +70,9 @@ extern void __pgd_error(const char *file, int line, pgd_t); | |||
| 70 | 70 | ||
| 71 | extern pgprot_t pgprot_user; | 71 | extern pgprot_t pgprot_user; |
| 72 | extern pgprot_t pgprot_kernel; | 72 | extern pgprot_t pgprot_kernel; |
| 73 | extern pgprot_t pgprot_hyp_device; | ||
| 74 | extern pgprot_t pgprot_s2; | ||
| 75 | extern pgprot_t pgprot_s2_device; | ||
| 73 | 76 | ||
| 74 | #define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b)) | 77 | #define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b)) |
| 75 | 78 | ||
| @@ -82,6 +85,10 @@ extern pgprot_t pgprot_kernel; | |||
| 82 | #define PAGE_READONLY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY) | 85 | #define PAGE_READONLY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY) |
| 83 | #define PAGE_KERNEL _MOD_PROT(pgprot_kernel, L_PTE_XN) | 86 | #define PAGE_KERNEL _MOD_PROT(pgprot_kernel, L_PTE_XN) |
| 84 | #define PAGE_KERNEL_EXEC pgprot_kernel | 87 | #define PAGE_KERNEL_EXEC pgprot_kernel |
| 88 | #define PAGE_HYP _MOD_PROT(pgprot_kernel, L_PTE_HYP) | ||
| 89 | #define PAGE_HYP_DEVICE _MOD_PROT(pgprot_hyp_device, L_PTE_HYP) | ||
| 90 | #define PAGE_S2 _MOD_PROT(pgprot_s2, L_PTE_S2_RDONLY) | ||
| 91 | #define PAGE_S2_DEVICE _MOD_PROT(pgprot_s2_device, L_PTE_USER | L_PTE_S2_RDONLY) | ||
| 85 | 92 | ||
| 86 | #define __PAGE_NONE __pgprot(_L_PTE_DEFAULT | L_PTE_RDONLY | L_PTE_XN | L_PTE_NONE) | 93 | #define __PAGE_NONE __pgprot(_L_PTE_DEFAULT | L_PTE_RDONLY | L_PTE_XN | L_PTE_NONE) |
| 87 | #define __PAGE_SHARED __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_XN) | 94 | #define __PAGE_SHARED __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_XN) |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 9f0610243bd6..1f51d712b55a 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
| @@ -57,6 +57,9 @@ static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK; | |||
| 57 | static unsigned int ecc_mask __initdata = 0; | 57 | static unsigned int ecc_mask __initdata = 0; |
| 58 | pgprot_t pgprot_user; | 58 | pgprot_t pgprot_user; |
| 59 | pgprot_t pgprot_kernel; | 59 | pgprot_t pgprot_kernel; |
| 60 | pgprot_t pgprot_hyp_device; | ||
| 61 | pgprot_t pgprot_s2; | ||
| 62 | pgprot_t pgprot_s2_device; | ||
| 60 | 63 | ||
| 61 | EXPORT_SYMBOL(pgprot_user); | 64 | EXPORT_SYMBOL(pgprot_user); |
| 62 | EXPORT_SYMBOL(pgprot_kernel); | 65 | EXPORT_SYMBOL(pgprot_kernel); |
| @@ -66,34 +69,46 @@ struct cachepolicy { | |||
| 66 | unsigned int cr_mask; | 69 | unsigned int cr_mask; |
| 67 | pmdval_t pmd; | 70 | pmdval_t pmd; |
| 68 | pteval_t pte; | 71 | pteval_t pte; |
| 72 | pteval_t pte_s2; | ||
| 69 | }; | 73 | }; |
| 70 | 74 | ||
| 75 | #ifdef CONFIG_ARM_LPAE | ||
| 76 | #define s2_policy(policy) policy | ||
| 77 | #else | ||
| 78 | #define s2_policy(policy) 0 | ||
| 79 | #endif | ||
| 80 | |||
| 71 | static struct cachepolicy cache_policies[] __initdata = { | 81 | static struct cachepolicy cache_policies[] __initdata = { |
| 72 | { | 82 | { |
| 73 | .policy = "uncached", | 83 | .policy = "uncached", |
| 74 | .cr_mask = CR_W|CR_C, | 84 | .cr_mask = CR_W|CR_C, |
| 75 | .pmd = PMD_SECT_UNCACHED, | 85 | .pmd = PMD_SECT_UNCACHED, |
| 76 | .pte = L_PTE_MT_UNCACHED, | 86 | .pte = L_PTE_MT_UNCACHED, |
| 87 | .pte_s2 = s2_policy(L_PTE_S2_MT_UNCACHED), | ||
| 77 | }, { | 88 | }, { |
| 78 | .policy = "buffered", | 89 | .policy = "buffered", |
| 79 | .cr_mask = CR_C, | 90 | .cr_mask = CR_C, |
| 80 | .pmd = PMD_SECT_BUFFERED, | 91 | .pmd = PMD_SECT_BUFFERED, |
| 81 | .pte = L_PTE_MT_BUFFERABLE, | 92 | .pte = L_PTE_MT_BUFFERABLE, |
| 93 | .pte_s2 = s2_policy(L_PTE_S2_MT_UNCACHED), | ||
| 82 | }, { | 94 | }, { |
| 83 | .policy = "writethrough", | 95 | .policy = "writethrough", |
| 84 | .cr_mask = 0, | 96 | .cr_mask = 0, |
| 85 | .pmd = PMD_SECT_WT, | 97 | .pmd = PMD_SECT_WT, |
| 86 | .pte = L_PTE_MT_WRITETHROUGH, | 98 | .pte = L_PTE_MT_WRITETHROUGH, |
| 99 | .pte_s2 = s2_policy(L_PTE_S2_MT_WRITETHROUGH), | ||
| 87 | }, { | 100 | }, { |
| 88 | .policy = "writeback", | 101 | .policy = "writeback", |
| 89 | .cr_mask = 0, | 102 | .cr_mask = 0, |
| 90 | .pmd = PMD_SECT_WB, | 103 | .pmd = PMD_SECT_WB, |
| 91 | .pte = L_PTE_MT_WRITEBACK, | 104 | .pte = L_PTE_MT_WRITEBACK, |
| 105 | .pte_s2 = s2_policy(L_PTE_S2_MT_WRITEBACK), | ||
| 92 | }, { | 106 | }, { |
| 93 | .policy = "writealloc", | 107 | .policy = "writealloc", |
| 94 | .cr_mask = 0, | 108 | .cr_mask = 0, |
| 95 | .pmd = PMD_SECT_WBWA, | 109 | .pmd = PMD_SECT_WBWA, |
| 96 | .pte = L_PTE_MT_WRITEALLOC, | 110 | .pte = L_PTE_MT_WRITEALLOC, |
| 111 | .pte_s2 = s2_policy(L_PTE_S2_MT_WRITEBACK), | ||
| 97 | } | 112 | } |
| 98 | }; | 113 | }; |
| 99 | 114 | ||
| @@ -310,6 +325,7 @@ static void __init build_mem_type_table(void) | |||
| 310 | struct cachepolicy *cp; | 325 | struct cachepolicy *cp; |
| 311 | unsigned int cr = get_cr(); | 326 | unsigned int cr = get_cr(); |
| 312 | pteval_t user_pgprot, kern_pgprot, vecs_pgprot; | 327 | pteval_t user_pgprot, kern_pgprot, vecs_pgprot; |
| 328 | pteval_t hyp_device_pgprot, s2_pgprot, s2_device_pgprot; | ||
| 313 | int cpu_arch = cpu_architecture(); | 329 | int cpu_arch = cpu_architecture(); |
| 314 | int i; | 330 | int i; |
| 315 | 331 | ||
| @@ -421,6 +437,8 @@ static void __init build_mem_type_table(void) | |||
| 421 | */ | 437 | */ |
| 422 | cp = &cache_policies[cachepolicy]; | 438 | cp = &cache_policies[cachepolicy]; |
| 423 | vecs_pgprot = kern_pgprot = user_pgprot = cp->pte; | 439 | vecs_pgprot = kern_pgprot = user_pgprot = cp->pte; |
| 440 | s2_pgprot = cp->pte_s2; | ||
| 441 | hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte; | ||
| 424 | 442 | ||
| 425 | /* | 443 | /* |
| 426 | * ARMv6 and above have extended page tables. | 444 | * ARMv6 and above have extended page tables. |
| @@ -444,6 +462,7 @@ static void __init build_mem_type_table(void) | |||
| 444 | user_pgprot |= L_PTE_SHARED; | 462 | user_pgprot |= L_PTE_SHARED; |
| 445 | kern_pgprot |= L_PTE_SHARED; | 463 | kern_pgprot |= L_PTE_SHARED; |
| 446 | vecs_pgprot |= L_PTE_SHARED; | 464 | vecs_pgprot |= L_PTE_SHARED; |
| 465 | s2_pgprot |= L_PTE_SHARED; | ||
| 447 | mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S; | 466 | mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S; |
| 448 | mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED; | 467 | mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED; |
| 449 | mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; | 468 | mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; |
| @@ -498,6 +517,9 @@ static void __init build_mem_type_table(void) | |||
| 498 | pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot); | 517 | pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot); |
| 499 | pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | | 518 | pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | |
| 500 | L_PTE_DIRTY | kern_pgprot); | 519 | L_PTE_DIRTY | kern_pgprot); |
| 520 | pgprot_s2 = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | s2_pgprot); | ||
| 521 | pgprot_s2_device = __pgprot(s2_device_pgprot); | ||
| 522 | pgprot_hyp_device = __pgprot(hyp_device_pgprot); | ||
| 501 | 523 | ||
| 502 | mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; | 524 | mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; |
| 503 | mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; | 525 | mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; |
