From mboxrd@z Thu Jan 1 00:00:00 1970 From: Christoffer Dall Subject: [PATCH v4 02/10] ARM: KVM: Hypervisor identity mapping Date: Sat, 06 Aug 2011 12:39:10 +0200 Message-ID: <20110806103910.27198.11538.stgit@localhost6.localdomain6> References: <20110806103821.27198.41231.stgit@localhost6.localdomain6> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Cc: catalin.marinas@arm.com, tech@virtualopensystems.com, android-virt@lists.cs.columbia.edu To: kvm@vger.kernel.org Return-path: Received: from mail-fx0-f46.google.com ([209.85.161.46]:55484 "EHLO mail-fx0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751796Ab1HHVpE (ORCPT ); Mon, 8 Aug 2011 17:45:04 -0400 Received: by mail-fx0-f46.google.com with SMTP id 19so5784476fxh.19 for ; Mon, 08 Aug 2011 14:45:04 -0700 (PDT) In-Reply-To: <20110806103821.27198.41231.stgit@localhost6.localdomain6> Sender: kvm-owner@vger.kernel.org List-ID: Adds support in the identity mapping feature that allows KVM to setup identity mapping for the Hyp mode with the AP[1] bit set as required by the specification and also supports freeing created sub pmd's after finished use. These two functions: - hyp_identity_mapping_add(pgd, addr, end); - hyp_identity_mapping_del(pgd, addr, end); are essentially calls the same function as the non-hyp versions but with a different argument value. KVM calls these functions to setup and teardown the identity mapping used to initialize the hypervisor. Note, the hyp-version of the _del function actually frees the pmd's pointed to by the pgd as opposed to the non-hyp version which just clears them. Signed-off-by: Christoffer Dall --- arch/arm/include/asm/pgtable-3level-hwdef.h | 1 + arch/arm/include/asm/pgtable.h | 6 +++ arch/arm/mm/idmap.c | 47 ++++++++++++++++++++++++++- 3 files changed, 53 insertions(+), 1 deletions(-) diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h index 7c238a3..8ed298f 100644 --- a/arch/arm/include/asm/pgtable-3level-hwdef.h +++ b/arch/arm/include/asm/pgtable-3level-hwdef.h @@ -49,6 +49,7 @@ #endif #define PMD_SECT_AP_WRITE (_AT(pmdval_t, 0)) #define PMD_SECT_AP_READ (_AT(pmdval_t, 0)) +#define PMD_SECT_AP1 (_AT(pmdval_t, 1) << 6) #define PMD_SECT_TEX(x) (_AT(pmdval_t, 0)) /* diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 9645e52..da74cd1 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -409,6 +409,12 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) void identity_mapping_add(pgd_t *, unsigned long, unsigned long); void identity_mapping_del(pgd_t *, unsigned long, unsigned long); +#ifdef CONFIG_KVM_ARM_HOST +void hyp_identity_mapping_add(pgd_t *, unsigned long, unsigned long); +void hyp_identity_mapping_del(pgd_t *pgd, unsigned long addr, + unsigned long end); +#endif + #endif /* !__ASSEMBLY__ */ #endif /* CONFIG_MMU */ diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index 24e0655..83dc20d 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c @@ -56,11 +56,16 @@ static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end, } while (pud++, addr = next, addr != end); } -void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) +static void __identity_mapping_add(pgd_t *pgd, unsigned long addr, + unsigned long end, bool hyp_mapping) { unsigned long prot, next; prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF; + + if (hyp_mapping) + prot |= PMD_SECT_AP1; + if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) prot |= PMD_BIT4; @@ -71,6 +76,12 @@ void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) } while (pgd++, addr = next, addr != end); } +void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) +{ + __identity_mapping_add(pgd, addr, end, false); +} + + #ifdef CONFIG_SMP static void idmap_del_pmd(pud_t *pud, unsigned long addr, unsigned long end) { @@ -105,6 +116,40 @@ void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end) } #endif +#ifdef CONFIG_KVM_ARM_HOST +void hyp_identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) +{ + __identity_mapping_add(pgd, addr, end, true); +} + +static void hyp_idmap_del_pmd(pgd_t *pgd, unsigned long addr) +{ + pmd_t *pmd; + + pmd = pmd_offset(pgd, addr); + pmd_free(NULL, pmd); +} + +/* + * This version actually frees the underlying pmds for all pgds in range and + * clear the pgds themselves afterwards. + */ +void hyp_identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end) +{ + unsigned long next; + pgd_t *next_pgd; + + do { + next = pgd_addr_end(addr, end); + next_pgd = pgd + pgd_index(addr); + if (!pgd_none_or_clear_bad(next_pgd)) { + hyp_idmap_del_pmd(next_pgd, addr); + pgd_clear(next_pgd); + } + } while (addr = next, addr < end); +} +#endif + /* * In order to soft-boot, we need to insert a 1:1 mapping in place of * the user-mode pages. This will then ensure that we have predictable