From patchwork Mon Dec 19 07:13:47 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pratyush Anand X-Patchwork-Id: 9479773 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 16397601C0 for ; Mon, 19 Dec 2016 07:16:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 05E6B28429 for ; Mon, 19 Dec 2016 07:16:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EEEBE28451; Mon, 19 Dec 2016 07:16:32 +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=-3.7 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 140502847A for ; Mon, 19 Dec 2016 07:16:31 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1cIs9g-0004QM-6k; Mon, 19 Dec 2016 07:14:40 +0000 Received: from mail-qt0-f169.google.com ([209.85.216.169]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1cIs9N-0004K9-PE for linux-arm-kernel@lists.infradead.org; Mon, 19 Dec 2016 07:14:25 +0000 Received: by mail-qt0-f169.google.com with SMTP id w33so139178624qtc.3 for ; Sun, 18 Dec 2016 23:14:05 -0800 (PST) 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=n2wR1WwubFr1c9mDdUMLLxjri6QN6YQiIn1s+d+m6ko=; b=G73KTb+lpeSmsw2sfhXTqW7oAFEy8txetgyz5TxkZVmEbk3jjqg0CnWFKytXA4dixn d4PvFTUVKw4prPhB3tn/GWWs3fMU51ShPBCV82umgABg47zgGCGfL08CT1It315RFyhp MSlpik7eFnsVdp34+9yXPl/Uk/W452Nq5SEdXziT25Z47oWC4z2pHXGi12+oFvox05y6 D5eaYadv/DbKZcCHS5T4YVNnVvQ1dtqSgmU7P329O3ewZFFaw0P4Mby/eSNksRh5cT3Q zq18rhDROhk89LS6u+hfEAIjq7SVwjtnQMWC9VaO8xpQKHFeqRp7lOxXo3Wl3cn/BkVA jafQ== X-Gm-Message-State: AIkVDXIQEENQXOcSu3oDZYLsyWaZNIAvaB6r81REFx/vW35R0023/Ni+Ygt9M3ZiimC3Num8 X-Received: by 10.237.48.139 with SMTP id 11mr13574491qtf.219.1482131644980; Sun, 18 Dec 2016 23:14:04 -0800 (PST) Received: from localhost ([122.180.237.189]) by smtp.gmail.com with ESMTPSA id c198sm9864946qka.48.2016.12.18.23.14.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 18 Dec 2016 23:14:04 -0800 (PST) From: Pratyush Anand To: kexec@lists.infradead.org, geoff@infradead.org, james.morse@arm.com Subject: [PATCH V2 2/2] arm64: enable d-cache support during purgatory sha verification Date: Mon, 19 Dec 2016 12:43:47 +0530 Message-Id: X-Mailer: git-send-email 2.7.4 In-Reply-To: References: In-Reply-To: References: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20161218_231422_018946_0B868F91 X-CRM114-Status: GOOD ( 21.93 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, Pratyush Anand , 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 --- purgatory/arch/arm64/Makefile | 1 + purgatory/arch/arm64/cache.S | 281 +++++++++++++++++++++++++++++++++ purgatory/arch/arm64/purgatory-arm64.c | 5 + 3 files changed, 287 insertions(+) create mode 100644 purgatory/arch/arm64/cache.S 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..48123866ad5f --- /dev/null +++ b/purgatory/arch/arm64/cache.S @@ -0,0 +1,281 @@ +/* + * 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 . + */ + +#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 4 +#define MEMORY_ATTRIBUTES (0xFF << (MT_NORMAL*8)) + +/* + * 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(); }