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 371958370de4..580906989db1 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c | |||
| @@ -334,6 +334,17 @@ out: | |||
| 334 | return err; | 334 | return err; |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | static phys_addr_t kvm_kaddr_to_phys(void *kaddr) | ||
| 338 | { | ||
| 339 | if (!is_vmalloc_addr(kaddr)) { | ||
| 340 | BUG_ON(!virt_addr_valid(kaddr)); | ||
| 341 | return __pa(kaddr); | ||
| 342 | } else { | ||
| 343 | return page_to_phys(vmalloc_to_page(kaddr)) + | ||
| 344 | offset_in_page(kaddr); | ||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 337 | /** | 348 | /** |
| 338 | * create_hyp_mappings - duplicate a kernel virtual address range in Hyp mode | 349 | * create_hyp_mappings - duplicate a kernel virtual address range in Hyp mode |
| 339 | * @from: The virtual kernel start address of the range | 350 | * @from: The virtual kernel start address of the range |
| @@ -345,16 +356,27 @@ out: | |||
| 345 | */ | 356 | */ |
| 346 | int create_hyp_mappings(void *from, void *to) | 357 | int create_hyp_mappings(void *from, void *to) |
| 347 | { | 358 | { |
| 348 | unsigned long phys_addr = virt_to_phys(from); | 359 | phys_addr_t phys_addr; |
| 360 | unsigned long virt_addr; | ||
| 349 | unsigned long start = KERN_TO_HYP((unsigned long)from); | 361 | unsigned long start = KERN_TO_HYP((unsigned long)from); |
| 350 | unsigned long end = KERN_TO_HYP((unsigned long)to); | 362 | unsigned long end = KERN_TO_HYP((unsigned long)to); |
| 351 | 363 | ||
| 352 | /* Check for a valid kernel memory mapping */ | 364 | start = start & PAGE_MASK; |
| 353 | if (!virt_addr_valid(from) || !virt_addr_valid(to - 1)) | 365 | end = PAGE_ALIGN(end); |
| 354 | return -EINVAL; | ||
| 355 | 366 | ||
| 356 | return __create_hyp_mappings(hyp_pgd, start, end, | 367 | for (virt_addr = start; virt_addr < end; virt_addr += PAGE_SIZE) { |
| 357 | __phys_to_pfn(phys_addr), PAGE_HYP); | 368 | int err; |
| 369 | |||
| 370 | phys_addr = kvm_kaddr_to_phys(from + virt_addr - start); | ||
| 371 | err = __create_hyp_mappings(hyp_pgd, virt_addr, | ||
| 372 | virt_addr + PAGE_SIZE, | ||
| 373 | __phys_to_pfn(phys_addr), | ||
| 374 | PAGE_HYP); | ||
| 375 | if (err) | ||
| 376 | return err; | ||
| 377 | } | ||
| 378 | |||
| 379 | return 0; | ||
| 358 | } | 380 | } |
| 359 | 381 | ||
| 360 | /** | 382 | /** |
