[snip] >> >> static int exit_hyp_mode(void) >> { >> - phys_addr_t exit_phys_addr, exit_end_phys_addr; >> + phys_addr_t exit_phys_addr; >> int cpu; >> >> exit_phys_addr = virt_to_phys(__kvm_hyp_exit); >> - exit_end_phys_addr = virt_to_phys(__kvm_hyp_exit_end); >> BUG_ON(exit_phys_addr & 0x1f); >> >> /* >> - * Create identity mapping for the exit code. >> - */ >> - hyp_idmap_add(kvm_hyp_pgd_get(), >> - (unsigned long)exit_phys_addr, >> - (unsigned long)exit_end_phys_addr); >> - >> - /* >> * Execute the exit code on each CPU. >> * >> * Note: The stack is not mapped yet, so don't do anything else than > > this exit code will now fail because we called hyp_idmap_teardown() > above, right? > > so I guess we could not call the teardown() function, but then we may > have a conflict if the physical RAM base happens to overlap with the > kernel address for Hyp code? > > Seems like we will have to make the hyp_init_static_idmap exported to > support this. > > I'm thinking otherwise maybe we want the generic code to only manage > the idmap-Hyp page table and then let callers provide its own hyp_pgd > to work on. But this requires being able to switch between the two > which requires a reserved virtual address range mapped the same in > both page tables right? > > Other suggestions? (drop KVM module support, sad???) > I applied with the following fixup to kvm-a15-v9-stage. diff --git a/arch/arm/include/asm/idmap.h b/arch/arm/include/asm/idmap.h index 61c034e..a1ab8d6 100644 --- a/arch/arm/include/asm/idmap.h +++ b/arch/arm/include/asm/idmap.h @@ -15,6 +15,7 @@ void setup_mm_for_reboot(void); extern pgd_t *hyp_pgd; void hyp_idmap_teardown(void); +void hyp_idmap_setup(void); #endif #endif /* __ASM_IDMAP_H */ diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index bcb512e..62cc23c 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -821,6 +821,13 @@ static int exit_hyp_mode(void) phys_addr_t exit_phys_addr; int cpu; + /* + * TODO: flush Hyp TLB in case idmap code overlaps. + * Note that we should do this in the monitor code when switching the + * HVBAR, but this is going away and should be rather done in the Hyp + * mode change of HVBAR. + */ + hyp_idmap_setup(); exit_phys_addr = virt_to_phys(__kvm_hyp_exit); BUG_ON(exit_phys_addr & 0x1f); diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S index 6f7ed62..4db26cb 100644 --- a/arch/arm/kvm/init.S +++ b/arch/arm/kvm/init.S @@ -139,6 +139,7 @@ __do_hyp_exit: isb mcr p15, 4, sp, c1, c0, 0 @ HSCR + mcr p15, 4, r0, c8, c7, 0 @ Flush Hyp TLB, r0 ignored isb eret diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index a244aee..cbd5793 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -69,6 +69,7 @@ void free_hyp_pmds(void) pmd = pmd_offset(pud, addr); free_ptes(pmd, addr); pmd_free(NULL, pmd); + pud_clear(pud); } mutex_unlock(&kvm_hyp_pgd_mutex); } diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index 60557e3..7a944af 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c @@ -102,6 +102,7 @@ early_initcall(init_static_idmap); #ifdef CONFIG_ARM_VIRT_EXT pgd_t *hyp_pgd; +EXPORT_SYMBOL_GPL(hyp_pgd); static void hyp_idmap_del_pmd(pgd_t *pgd, unsigned long addr) { @@ -139,14 +140,20 @@ void hyp_idmap_teardown(void) } EXPORT_SYMBOL_GPL(hyp_idmap_teardown); +void hyp_idmap_setup(void) +{ + identity_mapping_add(hyp_pgd, __hyp_idmap_text_start, + __hyp_idmap_text_end, PMD_SECT_AP1); +} +EXPORT_SYMBOL_GPL(hyp_idmap_setup); + static int __init hyp_init_static_idmap(void) { hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL); if (!hyp_pgd) return -ENOMEM; - identity_mapping_add(hyp_pgd, __hyp_idmap_text_start, - __hyp_idmap_text_end, PMD_SECT_AP1); + hyp_idmap_setup(); return 0; } -Christoffer