From patchwork Mon Oct 22 06:49:11 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoffer Dall X-Patchwork-Id: 1623881 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id CAA21E00B1 for ; Mon, 22 Oct 2012 06:52:12 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TQBpD-0007xV-N3; Mon, 22 Oct 2012 06:49:23 +0000 Received: from mail-vc0-f177.google.com ([209.85.220.177]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TQBos-0007vk-I7 for linux-arm-kernel@lists.infradead.org; Mon, 22 Oct 2012 06:49:03 +0000 Received: by mail-vc0-f177.google.com with SMTP id p16so2566643vcq.36 for ; Sun, 21 Oct 2012 23:49:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=subject:to:from:cc:date:message-id:in-reply-to:references :user-agent:mime-version:content-type:content-transfer-encoding :x-gm-message-state; bh=sL5/SUAGYKHrs8LcFPODu9M29L630lwKGY9t2ViGIso=; b=MObVa41aT31GVufoA+dpgtqMTaND3rfwazc2Z3TsKkWhKYSYmTIChc314uNE8aqEpE zJ1/+cKMROYpHv8io5RZQdprVYSxkhr+Ef7pQ13eF6WvBYrqlWW5oenva1dSvlaqeE/K F5qLAvsdHn5lsVzj0XVZeN9dzlbCZaGSPR31H7DydoKuhIhjOGJR7yjoYD4VXlLOvHYQ AS3qd4noSZsb8itMIAWqaPvI2mHkLceWoSf70OEgRMv2TwetcvNuGaGDxTcGZy5g/7W3 ROQsH/Xln/NpHUD7HE2WomSEQnrHx4rkDdKVQzxhGC7+QVvyl/Y5OKH70dpgMOWABuyR cmew== Received: by 10.58.74.196 with SMTP id w4mr14116952vev.7.1350888542202; Sun, 21 Oct 2012 23:49:02 -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 y7sm9503850vdt.1.2012.10.21.23.49.01 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 21 Oct 2012 23:49:01 -0700 (PDT) Subject: [PATCH v3 02/14] 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: Mon, 22 Oct 2012 02:49:11 -0400 Message-ID: <20121022064911.18444.55821.stgit@ubuntu> In-Reply-To: <20121022064831.18444.73273.stgit@ubuntu> References: <20121022064831.18444.73273.stgit@ubuntu> User-Agent: StGit/0.15 MIME-Version: 1.0 X-Gm-Message-State: ALoCoQlFvOt9f2jPOJ345uK7Hw7tqHCeO0oI2+OdJjYytYpePiBtwtODbtRVSkGkYzX3Q7VOsQlV X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.220.177 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Marc Zyngier , Marcelo Tosatti , Will Deacon X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add a method (hyp_idmap_setup) to populate a hyp 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. Make all the above depend on CONFIG_ARM_VIRT_EXT and CONFIG_ARM_LPAE. Cc: Will Deacon Reviewed-by: Marcelo Tosatti Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall --- arch/arm/include/asm/idmap.h | 5 ++ arch/arm/include/asm/pgtable-3level-hwdef.h | 1 arch/arm/kernel/vmlinux.lds.S | 6 ++ arch/arm/mm/idmap.c | 74 +++++++++++++++++++++++---- 4 files changed, 73 insertions(+), 13 deletions(-) diff --git a/arch/arm/include/asm/idmap.h b/arch/arm/include/asm/idmap.h index bf863ed..36708ba 100644 --- a/arch/arm/include/asm/idmap.h +++ b/arch/arm/include/asm/idmap.h @@ -11,4 +11,9 @@ extern pgd_t *idmap_pgd; void setup_mm_for_reboot(void); +#ifdef CONFIG_ARM_VIRT_EXT +void hyp_idmap_teardown(pgd_t *hyp_pgd); +void hyp_idmap_setup(pgd_t *hyp_pgd); +#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..ea7430e 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c @@ -1,4 +1,6 @@ +#include #include +#include #include #include @@ -6,6 +8,7 @@ #include #include #include +#include pgd_t *idmap_pgd; @@ -59,11 +62,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 +90,62 @@ 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); +#if defined(CONFIG_ARM_VIRT_EXT) && defined(CONFIG_ARM_LPAE) +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(pgd_t *hyp_pgd) +{ + 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(pgd_t *hyp_pgd) +{ + identity_mapping_add(hyp_pgd, __hyp_idmap_text_start, + __hyp_idmap_text_end, PMD_SECT_AP1); +} +EXPORT_SYMBOL_GPL(hyp_idmap_setup); +#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