From patchwork Sat Sep 15 15:34:49 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoffer Dall X-Patchwork-Id: 1461811 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 9193B3FC33 for ; Sat, 15 Sep 2012 15:35:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752897Ab2IOPe6 (ORCPT ); Sat, 15 Sep 2012 11:34:58 -0400 Received: from mail-qa0-f53.google.com ([209.85.216.53]:41991 "EHLO mail-qa0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752919Ab2IOPev (ORCPT ); Sat, 15 Sep 2012 11:34:51 -0400 Received: by mail-qa0-f53.google.com with SMTP id s11so598535qaa.19 for ; Sat, 15 Sep 2012 08:34:50 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=subject:to:from:date:message-id:in-reply-to:references:user-agent :mime-version:content-type:content-transfer-encoding :x-gm-message-state; bh=MTeBGEzTW+f2BEmBLJIETiAN1l2XSUEqXFdRfzWHKg0=; b=PPJpHrAIqLXhGqKlnVAHG+Atnwkb3WQeti9sgBvzxrATa//hNQfN3xjQ+8jhubgDeB 4Cq/bLi9X9c2gubYqbbbIThB3/Fef4pwXa1JzwCqlO8pIEBI/5i497tguAzj0gT7c4fL KdSoxTLnMjqL7PY4DKXSpmrNRVfQ2cTILKd80OY9os6sFmXjc5urZLCu/VD05RV7/l6d Ub1hmy+NDn0MnCOB02v+oYzFNa7Z95HavZTbxffqn6xeQlxppcB8/bTl08xnKekOChT7 2didREB92eeFKOoXi9vYepkZso7SW5OrMvYiUnKBIVHkTmOowO/CU0BeeRxQBpSPVrfY 44HQ== Received: by 10.224.28.14 with SMTP id k14mr15368224qac.72.1347723290760; Sat, 15 Sep 2012 08:34:50 -0700 (PDT) Received: from [127.0.1.1] (pool-72-80-83-148.nycmny.fios.verizon.net. [72.80.83.148]) by mx.google.com with ESMTPS id ez6sm6992947qab.17.2012.09.15.08.34.49 (version=TLSv1/SSLv3 cipher=OTHER); Sat, 15 Sep 2012 08:34:50 -0700 (PDT) Subject: [PATCH 03/15] ARM: Section based HYP idmap To: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu From: Christoffer Dall Date: Sat, 15 Sep 2012 11:34:49 -0400 Message-ID: <20120915153449.21241.26746.stgit@ubuntu> In-Reply-To: <20120915153359.21241.86002.stgit@ubuntu> References: <20120915153359.21241.86002.stgit@ubuntu> User-Agent: StGit/0.15 MIME-Version: 1.0 X-Gm-Message-State: ALoCoQlrtsPfXt1dXcJOb8jhOD5bajcP85+t77PbXY4M8/2RUge96IXhKUgSdLALSOIbXGNzEA6J Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Marc Zyngier Add a HYP pgd to the core code (so it can benefit all Linux hypervisors). Populate this pgd with an identity mapping of the code contained in the .hyp.idmap.text section Offer a method to drop the this identity mapping through hyp_idmap_teardown and re-create it through hyp_idmap_setup. Make all the above depend on CONFIG_ARM_VIRT_EXT Cc: Will Deacon Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall --- arch/arm/include/asm/idmap.h | 7 ++ arch/arm/include/asm/pgtable-3level-hwdef.h | 1 arch/arm/kernel/vmlinux.lds.S | 6 ++ arch/arm/mm/idmap.c | 88 +++++++++++++++++++++++---- 4 files changed, 89 insertions(+), 13 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/arch/arm/include/asm/idmap.h b/arch/arm/include/asm/idmap.h index bf863ed..a1ab8d6 100644 --- a/arch/arm/include/asm/idmap.h +++ b/arch/arm/include/asm/idmap.h @@ -11,4 +11,11 @@ extern pgd_t *idmap_pgd; void setup_mm_for_reboot(void); +#ifdef CONFIG_ARM_VIRT_EXT +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/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h index d795282..a2d404e 100644 --- a/arch/arm/include/asm/pgtable-3level-hwdef.h +++ b/arch/arm/include/asm/pgtable-3level-hwdef.h @@ -44,6 +44,7 @@ #define PMD_SECT_XN (_AT(pmdval_t, 1) << 54) #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/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 36ff15b..12fd2eb 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -19,7 +19,11 @@ ALIGN_FUNCTION(); \ VMLINUX_SYMBOL(__idmap_text_start) = .; \ *(.idmap.text) \ - VMLINUX_SYMBOL(__idmap_text_end) = .; + VMLINUX_SYMBOL(__idmap_text_end) = .; \ + ALIGN_FUNCTION(); \ + VMLINUX_SYMBOL(__hyp_idmap_text_start) = .; \ + *(.hyp.idmap.text) \ + VMLINUX_SYMBOL(__hyp_idmap_text_end) = .; #ifdef CONFIG_HOTPLUG_CPU #define ARM_CPU_DISCARD(x) diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index ab88ed4..7a944af 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c @@ -1,4 +1,6 @@ +#include #include +#include #include #include @@ -59,11 +61,20 @@ static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end, } while (pud++, addr = next, addr != end); } -static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) +static void identity_mapping_add(pgd_t *pgd, const char *text_start, + const char *text_end, unsigned long prot) { - unsigned long prot, next; + unsigned long addr, end; + unsigned long next; + + addr = virt_to_phys(text_start); + end = virt_to_phys(text_end); + + pr_info("Setting up static %sidentity map for 0x%llx - 0x%llx\n", + prot ? "HYP " : "", + (long long)addr, (long long)end); + prot |= PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF; - prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF; if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) prot |= PMD_BIT4; @@ -78,24 +89,77 @@ extern char __idmap_text_start[], __idmap_text_end[]; static int __init init_static_idmap(void) { - phys_addr_t idmap_start, idmap_end; - idmap_pgd = pgd_alloc(&init_mm); if (!idmap_pgd) return -ENOMEM; - /* Add an identity mapping for the physical address of the section. */ - idmap_start = virt_to_phys((void *)__idmap_text_start); - idmap_end = virt_to_phys((void *)__idmap_text_end); - - pr_info("Setting up static identity map for 0x%llx - 0x%llx\n", - (long long)idmap_start, (long long)idmap_end); - identity_mapping_add(idmap_pgd, idmap_start, idmap_end); + identity_mapping_add(idmap_pgd, __idmap_text_start, + __idmap_text_end, 0); return 0; } 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) +{ + pud_t *pud; + pmd_t *pmd; + + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); + pud_clear(pud); + clean_pmd_entry(pmd); + pmd_free(NULL, (pmd_t *)((unsigned long)pmd & PAGE_MASK)); +} + +extern char __hyp_idmap_text_start[], __hyp_idmap_text_end[]; + +/* + * This version actually frees the underlying pmds for all pgds in range and + * clear the pgds themselves afterwards. + */ +void hyp_idmap_teardown(void) +{ + unsigned long addr, end; + unsigned long next; + pgd_t *pgd = hyp_pgd; + + addr = virt_to_phys(__hyp_idmap_text_start); + end = virt_to_phys(__hyp_idmap_text_end); + + pgd += pgd_index(addr); + do { + next = pgd_addr_end(addr, end); + if (!pgd_none_or_clear_bad(pgd)) + hyp_idmap_del_pmd(pgd, addr); + } while (pgd++, addr = next, addr < end); +} +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; + + hyp_idmap_setup(); + + return 0; +} +early_initcall(hyp_init_static_idmap); +#endif + /* * In order to soft-boot, we need to switch to a 1:1 mapping for the * cpu_reset functions. This will then ensure that we have predictable