diff options
-rw-r--r-- | arch/arm/kvm/mmu.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index b0de86b56c13..cb79a5dd6d96 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c | |||
@@ -307,6 +307,17 @@ out: | |||
307 | return err; | 307 | return err; |
308 | } | 308 | } |
309 | 309 | ||
310 | static phys_addr_t kvm_kaddr_to_phys(void *kaddr) | ||
311 | { | ||
312 | if (!is_vmalloc_addr(kaddr)) { | ||
313 | BUG_ON(!virt_addr_valid(kaddr)); | ||
314 | return __pa(kaddr); | ||
315 | } else { | ||
316 | return page_to_phys(vmalloc_to_page(kaddr)) + | ||
317 | offset_in_page(kaddr); | ||
318 | } | ||
319 | } | ||
320 | |||
310 | /** | 321 | /** |
311 | * create_hyp_mappings - duplicate a kernel virtual address range in Hyp mode | 322 | * create_hyp_mappings - duplicate a kernel virtual address range in Hyp mode |
312 | * @from: The virtual kernel start address of the range | 323 | * @from: The virtual kernel start address of the range |
@@ -318,16 +329,27 @@ out: | |||
318 | */ | 329 | */ |
319 | int create_hyp_mappings(void *from, void *to) | 330 | int create_hyp_mappings(void *from, void *to) |
320 | { | 331 | { |
321 | unsigned long phys_addr = virt_to_phys(from); | 332 | phys_addr_t phys_addr; |
333 | unsigned long virt_addr; | ||
322 | unsigned long start = KERN_TO_HYP((unsigned long)from); | 334 | unsigned long start = KERN_TO_HYP((unsigned long)from); |
323 | unsigned long end = KERN_TO_HYP((unsigned long)to); | 335 | unsigned long end = KERN_TO_HYP((unsigned long)to); |
324 | 336 | ||
325 | /* Check for a valid kernel memory mapping */ | 337 | start = start & PAGE_MASK; |
326 | if (!virt_addr_valid(from) || !virt_addr_valid(to - 1)) | 338 | end = PAGE_ALIGN(end); |
327 | return -EINVAL; | ||
328 | 339 | ||
329 | return __create_hyp_mappings(hyp_pgd, start, end, | 340 | for (virt_addr = start; virt_addr < end; virt_addr += PAGE_SIZE) { |
330 | __phys_to_pfn(phys_addr), PAGE_HYP); | 341 | int err; |
342 | |||
343 | phys_addr = kvm_kaddr_to_phys(from + virt_addr - start); | ||
344 | err = __create_hyp_mappings(hyp_pgd, virt_addr, | ||
345 | virt_addr + PAGE_SIZE, | ||
346 | __phys_to_pfn(phys_addr), | ||
347 | PAGE_HYP); | ||
348 | if (err) | ||
349 | return err; | ||
350 | } | ||
351 | |||
352 | return 0; | ||
331 | } | 353 | } |
332 | 354 | ||
333 | /** | 355 | /** |