From patchwork Tue May 23 05:02:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pratyush Anand X-Patchwork-Id: 9741907 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C4E1B6034C for ; Tue, 23 May 2017 05:03:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BA9FB28791 for ; Tue, 23 May 2017 05:03:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AD26D28793; Tue, 23 May 2017 05:03:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.4 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_SORBS_SPAM autolearn=no version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D8F0D28791 for ; Tue, 23 May 2017 05:03:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=qlFbqg5IjYkiB+YmDQo2023ftPJXXLF9trW0kvgy1y4=; b=i3v1fNdEcdysHIccd6W/vf+oVI WURl8LX2R5Y+v9UGGyFYYIGVaivNRvdWouRqU9wkpQJdxcDq2PYjK+IqHRvVxqsGIHewxLSlkPFQW mpIwfzyyzaV2h4Tp4FTms0ujTOcqh57Wi123dwwoiJhb2Nz11ZOEJk6m3uVm836bLjZ1BejFZOeHV o8oGkBdaGkODilPkaQ7g/Cg8ILfRRtapRd2UW/OwkFI3wr4N6khFz2pM+rlpDyCH4he6Fjaa43Ymp vac76Z6Cu1DBGPPNthCPGKdjxX3lzDhZwWxmqD3K02bjfr3D9eM3fj6r/7ujK7gcna0X1SYjbCrGK jwYnieyA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dD1yo-0001S9-H6; Tue, 23 May 2017 05:03:34 +0000 Received: from mail-pf0-f169.google.com ([209.85.192.169]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dD1yM-0000o1-Qf for linux-arm-kernel@lists.infradead.org; Tue, 23 May 2017 05:03:15 +0000 Received: by mail-pf0-f169.google.com with SMTP id 9so102542114pfj.1 for ; Mon, 22 May 2017 22:02:46 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=ppw/LjMJ492Z/4czqy8BHumwDWaqgFjOl4MA+8KZp6M=; b=V0UBigLgvlxkxN/B/T+S85I8OWTawZros0ypHN8gMrndIf+H/zsksKd9jC6XhqNA4d tk+YUBU3J3tdI7PvPlwPzWnQfwQzA82CnxwCnS9t0wlftwu1s8SfeJ9b9FXKA8h5Lkvq u87Bf+YSVr6RFRJHWYUFSTWlJHVjdb8v9Dj4T7y0JLiTGfKc3Czs1btTniTKpNsQ1L+k W2vBoPzbejOcUKN5jPaBkSnDGzfddzhZKbu66n6vJ2dkuNlsWemlvYzCTEX3lfPQUY9V KMmO037znE+YDto05o0HsJg8M8laOWWWrvnt7iFQgV5Bm8bLLOngn85uQY6gKNQMWKHi jZPQ== X-Gm-Message-State: AODbwcBnhqN07GRuAAiiR7G8sP8tDoDBEgsC7EZ+OMEsHlr8Cq8n5qnM ZRGEgf5qjjGAPxpZ X-Received: by 10.99.157.196 with SMTP id i187mr25419875pgd.132.1495515765888; Mon, 22 May 2017 22:02:45 -0700 (PDT) Received: from localhost ([122.162.132.203]) by smtp.gmail.com with ESMTPSA id t79sm29836435pfk.106.2017.05.22.22.02.44 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 22 May 2017 22:02:45 -0700 (PDT) From: Pratyush Anand To: horms@verge.net.au, james.morse@arm.com Subject: [PATCH v3 2/2] arm64: enable d-cache support during purgatory sha verification Date: Tue, 23 May 2017 10:32:09 +0530 Message-Id: <800735a0173aa7204006a189e19d32e338e31507.1495514291.git.panand@redhat.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: References: In-Reply-To: References: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170522_220307_092935_C256E3EC X-CRM114-Status: GOOD ( 21.71 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, Pratyush Anand , bhe@redhat.com, kexec@lists.infradead.org, dyoung@redhat.com, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP If a platform supports 4K page table then enable D-cache in purgatory before SHA verification. Disable it before switching to kernel. Signed-off-by: Pratyush Anand --- kexec/arch/arm64/kexec-mmu.h | 20 ++- purgatory/arch/arm64/Makefile | 1 + purgatory/arch/arm64/cache.S | 264 +++++++++++++++++++++++++++++++++ purgatory/arch/arm64/purgatory-arm64.c | 5 + 4 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 purgatory/arch/arm64/cache.S diff --git a/kexec/arch/arm64/kexec-mmu.h b/kexec/arch/arm64/kexec-mmu.h index 55354b5e3002..6f0a8e90a205 100644 --- a/kexec/arch/arm64/kexec-mmu.h +++ b/kexec/arch/arm64/kexec-mmu.h @@ -1,5 +1,24 @@ #if !defined(KEXEC_MMU_H) #define KEXEC_MMU_H + +#define SCTLR_ELx_I (1 << 12) +#define SCTLR_ELx_C (1 << 2) +#define SCTLR_ELx_M (1 << 0) +#define SCTLR_ELx_FLAGS (SCTLR_ELx_M | SCTLR_ELx_C | SCTLR_ELx_I) +#define TCR_SHARED_NONE (0 << 12) +#define TCR_ORGN_WBWA (1 << 10) +#define TCR_IRGN_WBWA (1 << 8) +#define TCR_T0SZ_48 16 +#define TCR_TG0_4K (0 << 14) +#define TCR_FLAGS (TCR_SHARED_NONE | TCR_ORGN_WBWA |\ + TCR_IRGN_WBWA | TCR_T0SZ_48 | TCR_TG0_4K) +#define TCR_IPS_EL1_SHIFT 32 +#define TCR_IPS_EL2_SHIFT 16 +#define ID_AA64MMFR0_TGRAN4_SHIFT 28 +#define ID_AA64MMFR0_PARANGE_MASK 0xF +#define MT_NORMAL 0 +#define MEMORY_ATTRIBUTES (0xFF << (MT_NORMAL*8)) + /* * kexec creates identity page table to be used in purgatory so that * dcache verification becomes faster. @@ -26,7 +45,6 @@ #define PMD_TYPE_SECT (1UL << 0) #define PMD_SECT_AF (1UL << 10) #define PMD_ATTRINDX(t) ((unsigned long)(t) << 2) -#define MT_NORMAL 0 #define PMD_FLAGS_NORMAL (PMD_TYPE_SECT | PMD_SECT_AF) #define MMU_FLAGS_NORMAL (PMD_ATTRINDX(MT_NORMAL) | PMD_FLAGS_NORMAL) #define SECTION_SHIFT PMD_SHIFT diff --git a/purgatory/arch/arm64/Makefile b/purgatory/arch/arm64/Makefile index 636abeab17b2..db28a0de6891 100644 --- a/purgatory/arch/arm64/Makefile +++ b/purgatory/arch/arm64/Makefile @@ -11,6 +11,7 @@ arm64_PURGATORY_EXTRA_CFLAGS = \ arm64_PURGATORY_SRCS += \ purgatory/arch/arm64/entry.S \ + purgatory/arch/arm64/cache.S \ purgatory/arch/arm64/purgatory-arm64.c dist += \ diff --git a/purgatory/arch/arm64/cache.S b/purgatory/arch/arm64/cache.S new file mode 100644 index 000000000000..bb5e08397ef9 --- /dev/null +++ b/purgatory/arch/arm64/cache.S @@ -0,0 +1,264 @@ +/* + * Some of the routines have been copied from Linux Kernel, therefore + * copying the license as well. + * + * Copyright (C) 2001 Deep Blue Solutions Ltd. + * Copyright (C) 2012 ARM Ltd. + * Copyright (C) 2016 Pratyush Anand + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "../../../kexec/arch/arm64/kexec-mmu.h" +/* + * dcache_line_size - get the minimum D-cache line size from the CTR register. + */ + .macro dcache_line_size, reg, tmp + mrs \tmp, ctr_el0 // read CTR + ubfm \tmp, \tmp, #16, #19 // cache line size encoding + mov \reg, #4 // bytes per word + lsl \reg, \reg, \tmp // actual cache line size + .endm + +/* + * flush_dcache_range(start, end) + * - x0 - start - start address of region + * - x1 - end - end address of region + * + */ +flush_dcache_range: + dcache_line_size x2, x3 + sub x3, x2, #1 + bic x0, x0, x3 +1: dc civac, x0 // clean & invalidate D line / unified line + add x0, x0, x2 + cmp x0, x1 + b.lo 1b + dsb sy + ret + +/* + * invalidate_tlbs_el1() + */ +invalidate_tlbs_el1: + dsb nshst + tlbi vmalle1 + dsb nsh + isb + ret + +/* + * invalidate_tlbs_el2() + */ +invalidate_tlbs_el2: + dsb nshst + tlbi alle2 + dsb nsh + isb + ret +/* + * is_4k_page_not_supported - return nonzero if 4k page is not supported + */ +is_4k_page_not_supported: + mrs x0, ID_AA64MMFR0_EL1 + and x0, x0, #(0xF << ID_AA64MMFR0_TGRAN4_SHIFT) + ret + +/* + * get_ips_bits - return supported IPS bits + */ +get_ips_bits: + mrs x0, ID_AA64MMFR0_EL1 + and x0, x0, #ID_AA64MMFR0_PARANGE_MASK + ret + +/* + * get_current_el - Get information about current exception level + */ +get_current_el: + mrs x0, CurrentEL + lsr x0, x0, #2 + ret + +/* + * invalidate_icache - Invalidate I-cache + */ +invalidate_icache: + ic iallu + dsb nsh + isb + ret + +/* + * set_mair_tcr_ttbr_sctlr_el1(page_table, tcr_flags) - sets MAIR, TCR , TTBR and SCTLR registers + * x0 - page_table - Page Table Base + * x1 - tcr_flags - TCR Flags to be set + */ +set_mair_tcr_ttbr_sctlr_el1: + ldr x2, =MEMORY_ATTRIBUTES + msr mair_el1, x2 + msr tcr_el1, x1 + msr ttbr0_el1, x0 + isb + mrs x0, sctlr_el1 + ldr x3, =SCTLR_ELx_FLAGS + orr x0, x0, x3 + msr sctlr_el1, x0 + isb + ret + +/* + * set_mair_tcr_ttbr_sctlr_el2(page_table, tcr_flags) - sets MAIR, TCR , TTBR and SCTLR registers + * x0 - page_table - Page Table Base + * x1 - tcr_flags - TCR Flags to be set + */ +set_mair_tcr_ttbr_sctlr_el2: + ldr x2, =MEMORY_ATTRIBUTES + msr mair_el2, x2 + msr tcr_el2, x1 + msr ttbr0_el2, x0 + isb + mrs x0, sctlr_el2 + ldr x3, =SCTLR_ELx_FLAGS + orr x0, x0, x3 + msr sctlr_el2, x0 + isb + ret + +/* + * reset_sctlr_el1 - disables cache and mmu + */ +reset_sctlr_el1: + mrs x0, sctlr_el1 + bic x0, x0, #SCTLR_ELx_C + bic x0, x0, #SCTLR_ELx_M + msr sctlr_el1, x0 + isb + ret + +/* + * reset_sctlr_el2 - disables cache and mmu + */ +reset_sctlr_el2: + mrs x0, sctlr_el2 + bic x0, x0, #SCTLR_ELx_C + bic x0, x0, #SCTLR_ELx_M + msr sctlr_el2, x0 + isb + ret + +.globl enable_dcache +/* + * x6 - pgtble_base + * x7 - tcr_flags + * x8 - current_el + */ +enable_dcache: + stp x29, x30, [sp,#-16]! + stp x6, x7, [sp,#-16]! + stp x8, x9, [sp,#-16]! + bl is_4k_page_not_supported + cmp x0, #0 + b.ne 1f + ldr x6, pgtble_base + ldr x7, =TCR_FLAGS + bl get_current_el + mov x8, x0 + cmp x8, #2 + b.ne 2f + bl invalidate_tlbs_el2 + bl get_ips_bits + lsl x1, x0, #TCR_IPS_EL2_SHIFT + orr x1, x1, x7 + mov x0, x6 + bl set_mair_tcr_ttbr_sctlr_el2 + b 1f +2: + cmp x8, #1 + b.ne 1f + bl invalidate_tlbs_el1 + bl get_ips_bits + lsl x1, x0, #TCR_IPS_EL1_SHIFT + orr x1, x1, x7 + mov x0, x6 + bl set_mair_tcr_ttbr_sctlr_el1 +1: + ldp x8, x9, [sp],#16 + ldp x6, x7, [sp],#16 + ldp x29, x30, [sp],#16 + ret + +.extern sha256_regions +.globl disable_dcache +/* + * x6 - pgtble_base + * x7 - current_el + */ +disable_dcache: + stp x29, x30, [sp,#-16]! + stp x6, x7, [sp,#-16]! + bl is_4k_page_not_supported + cmp x0, #0 + b.ne 1f + ldr x6, pgtble_base + bl get_current_el + mov x7, x0 + cmp x7, #2 + b.ne 2f + bl reset_sctlr_el2 + b 3f +2: + cmp x7, #1 + b.ne 1f + bl reset_sctlr_el1 +3: + /* + * we can only branch to function which does not use stack, until + * all memories are flushed. + */ + bl invalidate_icache + /* flush d cache for purgatory region */ + ldr x0, purgatory_base + ldr x1, purgatory_len + add x1, x1, x0 + bl flush_dcache_range + /* flush d cache for rest of the regions */ + ldr x6, =sha256_regions +4: + ldp x0, x1, [x6],#16 + cmp x1, #0 + b.eq 1f + add x1, x1, x0 + bl flush_dcache_range + b 4b +1: + ldp x6, x7, [sp],#16 + ldp x29, x30, [sp],#16 + ret + +.align 3 + +.globl pgtble_base +pgtble_base: + .quad 0 + .size pgtble_base, .-pgtble_base + +.globl purgatory_base +purgatory_base: + .quad 0 + .size purgatory_base, .-purgatory_base + +.globl purgatory_len +purgatory_len: + .quad 0 + .size purgatory_len, .-purgatory_len diff --git a/purgatory/arch/arm64/purgatory-arm64.c b/purgatory/arch/arm64/purgatory-arm64.c index fe50fcf8ebc3..638fb11d9843 100644 --- a/purgatory/arch/arm64/purgatory-arm64.c +++ b/purgatory/arch/arm64/purgatory-arm64.c @@ -5,6 +5,9 @@ #include #include +void enable_dcache(void); +void disable_dcache(void); + void putchar(int ch) { /* Nothing for now */ @@ -12,8 +15,10 @@ void putchar(int ch) void post_verification_setup_arch(void) { + disable_dcache(); } void setup_arch(void) { + enable_dcache(); }