diff options
-rw-r--r-- | arch/arm/kvm/mmu.c | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index 0bf2c8551f75..2f12e4056408 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c | |||
@@ -85,34 +85,42 @@ static void free_ptes(pmd_t *pmd, unsigned long addr) | |||
85 | } | 85 | } |
86 | } | 86 | } |
87 | 87 | ||
88 | static void free_hyp_pgd_entry(unsigned long addr) | ||
89 | { | ||
90 | pgd_t *pgd; | ||
91 | pud_t *pud; | ||
92 | pmd_t *pmd; | ||
93 | unsigned long hyp_addr = KERN_TO_HYP(addr); | ||
94 | |||
95 | pgd = hyp_pgd + pgd_index(hyp_addr); | ||
96 | pud = pud_offset(pgd, hyp_addr); | ||
97 | |||
98 | if (pud_none(*pud)) | ||
99 | return; | ||
100 | BUG_ON(pud_bad(*pud)); | ||
101 | |||
102 | pmd = pmd_offset(pud, hyp_addr); | ||
103 | free_ptes(pmd, addr); | ||
104 | pmd_free(NULL, pmd); | ||
105 | pud_clear(pud); | ||
106 | } | ||
107 | |||
88 | /** | 108 | /** |
89 | * free_hyp_pmds - free a Hyp-mode level-2 tables and child level-3 tables | 109 | * free_hyp_pmds - free a Hyp-mode level-2 tables and child level-3 tables |
90 | * | 110 | * |
91 | * Assumes this is a page table used strictly in Hyp-mode and therefore contains | 111 | * Assumes this is a page table used strictly in Hyp-mode and therefore contains |
92 | * only mappings in the kernel memory area, which is above PAGE_OFFSET. | 112 | * either mappings in the kernel memory area (above PAGE_OFFSET), or |
113 | * device mappings in the vmalloc range (from VMALLOC_START to VMALLOC_END). | ||
93 | */ | 114 | */ |
94 | void free_hyp_pmds(void) | 115 | void free_hyp_pmds(void) |
95 | { | 116 | { |
96 | pgd_t *pgd; | ||
97 | pud_t *pud; | ||
98 | pmd_t *pmd; | ||
99 | unsigned long addr; | 117 | unsigned long addr; |
100 | 118 | ||
101 | mutex_lock(&kvm_hyp_pgd_mutex); | 119 | mutex_lock(&kvm_hyp_pgd_mutex); |
102 | for (addr = PAGE_OFFSET; addr != 0; addr += PGDIR_SIZE) { | 120 | for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += PGDIR_SIZE) |
103 | unsigned long hyp_addr = KERN_TO_HYP(addr); | 121 | free_hyp_pgd_entry(addr); |
104 | pgd = hyp_pgd + pgd_index(hyp_addr); | 122 | for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE) |
105 | pud = pud_offset(pgd, hyp_addr); | 123 | free_hyp_pgd_entry(addr); |
106 | |||
107 | if (pud_none(*pud)) | ||
108 | continue; | ||
109 | BUG_ON(pud_bad(*pud)); | ||
110 | |||
111 | pmd = pmd_offset(pud, hyp_addr); | ||
112 | free_ptes(pmd, addr); | ||
113 | pmd_free(NULL, pmd); | ||
114 | pud_clear(pud); | ||
115 | } | ||
116 | mutex_unlock(&kvm_hyp_pgd_mutex); | 124 | mutex_unlock(&kvm_hyp_pgd_mutex); |
117 | } | 125 | } |
118 | 126 | ||