aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/kvm/mmu.c44
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
88static 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 */
94void free_hyp_pmds(void) 115void 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