From patchwork Thu Mar 17 13:33:36 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 64000 Delivered-To: patch@linaro.org Received: by 10.112.199.169 with SMTP id jl9csp471746lbc; Thu, 17 Mar 2016 06:33:49 -0700 (PDT) X-Received: by 10.66.123.17 with SMTP id lw17mr15149576pab.108.1458221628928; Thu, 17 Mar 2016 06:33:48 -0700 (PDT) Return-Path: Received: from ml01.01.org (ml01.01.org. [2001:19d0:306:5::1]) by mx.google.com with ESMTPS id o86si12560905pfa.162.2016.03.17.06.33.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Mar 2016 06:33:48 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 2001:19d0:306:5::1 as permitted sender) client-ip=2001:19d0:306:5::1; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 2001:19d0:306:5::1 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dkim=neutral (body hash did not verify) header.i=@linaro.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 39B081A1E2B; Thu, 17 Mar 2016 06:34:08 -0700 (PDT) X-Original-To: edk2-devel@lists.01.org Delivered-To: edk2-devel@lists.01.org Received: from mail-wm0-x22d.google.com (mail-wm0-x22d.google.com [IPv6:2a00:1450:400c:c09::22d]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 3FACC1A1E24 for ; Thu, 17 Mar 2016 06:34:06 -0700 (PDT) Received: by mail-wm0-x22d.google.com with SMTP id l68so117465081wml.1 for ; Thu, 17 Mar 2016 06:33:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=/LpNufUM1o2SK3WnHVOOBQGSpIVMH+MULHHrm3r9uUo=; b=QbePPS2Xyd+md5WGNM699bT0r/ki5xEsHiaKm7DczlJyWgnfNgoudojIDZfmHV1fXR ISf2GxX4IVhQfHZLpARWlnjZJ8TGQMHAuUFBZ3Vg7sCe1Sb2diVmJBfAyzBhRaecSZ77 a1az49HFQqUyW9SV6qnlw6q2S6ZvZTGVINgqk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=/LpNufUM1o2SK3WnHVOOBQGSpIVMH+MULHHrm3r9uUo=; b=aS1FtgMgrrs5+c53YyyP71e+7tahialXuSKPv31LNiVn1EWPD3aDxBt5DJySRjMw8V OENVeWU+jo8u7gCX8Wtn+zb7kIVQ0bKx9aWSqaosKZ8pKpJ3Od2llX7ZiVTKPdv4VEfu NuE4Nsjtaue9LqWwrnZzs+XNho5oEqLELPmeYHe6tDuE/fLjL6fC0Gfj0bR71dC38Ml3 zEtZ0k9hh+sXM6CNlLP3BYzWgfURLz4o3UpaiiXslLgWQ5ZTAlZJxj4Sr3SFhsKpDg0K HyB+BhxXe1jH6PCuHR7gM6Cwi0neg9QbSXZAWLnw69dxB8+14TpXjq69KduvNMebIwT0 kh9g== X-Gm-Message-State: AD7BkJKLB4bSE44/8tXb9rFSvgHe4vBbRSl40okgKgCJoIZHc9FyRLLXaYOsuS/JdcjEDnQV X-Received: by 10.28.88.15 with SMTP id m15mr34891424wmb.60.1458221624947; Thu, 17 Mar 2016 06:33:44 -0700 (PDT) Received: from localhost.localdomain ([195.55.142.58]) by smtp.gmail.com with ESMTPSA id n66sm8209386wmg.20.2016.03.17.06.33.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 17 Mar 2016 06:33:44 -0700 (PDT) From: Ard Biesheuvel To: edk2-devel@lists.01.org, leif.lindholm@linaro.org, eugene@hp.com Date: Thu, 17 Mar 2016 14:33:36 +0100 Message-Id: <1458221616-7151-1-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1458220815-6944-1-git-send-email-ard.biesheuvel@linaro.org> References: <1458220815-6944-1-git-send-email-ard.biesheuvel@linaro.org> Subject: [edk2] [PATCH 7/7] ArmPkg/ArmExceptionLib: reimplement register stack/unstack routines X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Ard Biesheuvel MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" This replaces the somewhat opaque preprocessor based stack/unstack macros with open coded ldp/stp sequences to preserve the interrupted context before handing over to the exception handler in C. This removes various arithmetic operations on the stack pointer, and reduces the exception return critical section to its minimum size (i.e., the bare minimum required to populate the ELR and SPSR registers and invoke the eret). Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel --- ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S | 235 +++++++++----------- 1 file changed, 109 insertions(+), 126 deletions(-) -- 2.5.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel diff --git a/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S b/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S index 0fd304db2dbf..fef7d908c1cc 100644 --- a/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S +++ b/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S @@ -107,54 +107,6 @@ GCC_ASM_EXPORT(CommonCExceptionHandler) #define FP_CONTEXT_SIZE (32 * 16) #define SYS_CONTEXT_SIZE ( 6 * 8) // 5 SYS regs + Alignment requirement (ie: the stack must be aligned on 0x10) -// Cannot str x31 directly -#define ALL_GP_REGS \ - REG_PAIR (x0, x1, 0x000, GP_CONTEXT_SIZE); \ - REG_PAIR (x2, x3, 0x010, GP_CONTEXT_SIZE); \ - REG_PAIR (x4, x5, 0x020, GP_CONTEXT_SIZE); \ - REG_PAIR (x6, x7, 0x030, GP_CONTEXT_SIZE); \ - REG_PAIR (x8, x9, 0x040, GP_CONTEXT_SIZE); \ - REG_PAIR (x10, x11, 0x050, GP_CONTEXT_SIZE); \ - REG_PAIR (x12, x13, 0x060, GP_CONTEXT_SIZE); \ - REG_PAIR (x14, x15, 0x070, GP_CONTEXT_SIZE); \ - REG_PAIR (x16, x17, 0x080, GP_CONTEXT_SIZE); \ - REG_PAIR (x18, x19, 0x090, GP_CONTEXT_SIZE); \ - REG_PAIR (x20, x21, 0x0a0, GP_CONTEXT_SIZE); \ - REG_PAIR (x22, x23, 0x0b0, GP_CONTEXT_SIZE); \ - REG_PAIR (x24, x25, 0x0c0, GP_CONTEXT_SIZE); \ - REG_PAIR (x26, x27, 0x0d0, GP_CONTEXT_SIZE); \ - REG_PAIR (x28, x29, 0x0e0, GP_CONTEXT_SIZE); \ - REG_ONE (x30, 0x0f0, GP_CONTEXT_SIZE); - -// In order to save the SP we need to put it somewhere else first. -// STR only works with XZR/WZR directly -#define SAVE_SP \ - add x1, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE); \ - REG_ONE (x1, 0x0f8, GP_CONTEXT_SIZE); - -#define ALL_FP_REGS \ - REG_PAIR (q0, q1, 0x000, FP_CONTEXT_SIZE); \ - REG_PAIR (q2, q3, 0x020, FP_CONTEXT_SIZE); \ - REG_PAIR (q4, q5, 0x040, FP_CONTEXT_SIZE); \ - REG_PAIR (q6, q7, 0x060, FP_CONTEXT_SIZE); \ - REG_PAIR (q8, q9, 0x080, FP_CONTEXT_SIZE); \ - REG_PAIR (q10, q11, 0x0a0, FP_CONTEXT_SIZE); \ - REG_PAIR (q12, q13, 0x0c0, FP_CONTEXT_SIZE); \ - REG_PAIR (q14, q15, 0x0e0, FP_CONTEXT_SIZE); \ - REG_PAIR (q16, q17, 0x100, FP_CONTEXT_SIZE); \ - REG_PAIR (q18, q19, 0x120, FP_CONTEXT_SIZE); \ - REG_PAIR (q20, q21, 0x140, FP_CONTEXT_SIZE); \ - REG_PAIR (q22, q23, 0x160, FP_CONTEXT_SIZE); \ - REG_PAIR (q24, q25, 0x180, FP_CONTEXT_SIZE); \ - REG_PAIR (q26, q27, 0x1a0, FP_CONTEXT_SIZE); \ - REG_PAIR (q28, q29, 0x1c0, FP_CONTEXT_SIZE); \ - REG_PAIR (q30, q31, 0x1e0, FP_CONTEXT_SIZE); - -#define ALL_SYS_REGS \ - REG_PAIR (x1, x2, 0x000, SYS_CONTEXT_SIZE); \ - REG_PAIR (x3, x4, 0x010, SYS_CONTEXT_SIZE); \ - REG_ONE (x5, 0x020, SYS_CONTEXT_SIZE); - // // There are two methods for installing AArch64 exception vectors: // 1. Install a copy of the vectors to a location specified by a PCD @@ -170,18 +122,35 @@ ASM_PFX(ExceptionHandlersStart): VECTOR_BASE(ExceptionHandlersStart) #endif -#undef REG_PAIR -#undef REG_ONE -#define REG_PAIR(REG1, REG2, OFFSET, CONTEXT_SIZE) stp REG1, REG2, [sp, #(OFFSET-CONTEXT_SIZE)] -#define REG_ONE(REG1, OFFSET, CONTEXT_SIZE) stur REG1, [sp, #(OFFSET-CONTEXT_SIZE)] - .macro ExceptionEntry, val // Move the stackpointer so we can reach our structure with the str instruction. sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE) - // Save all the General regs before touching x0 and x1. - // This does not save r31(SP) as it is special. We do that later. - ALL_GP_REGS + // Push some GP registers so we can record the exception context + stp x0, x1, [sp, #-GP_CONTEXT_SIZE]! + stp x2, x3, [sp, #0x10] + stp x4, x5, [sp, #0x20] + stp x6, x7, [sp, #0x30] + + EL1_OR_EL2_OR_EL3(x1) +1:mrs x2, elr_el1 // Exception Link Register + mrs x3, spsr_el1 // Saved Processor Status Register 32bit + mrs x5, esr_el1 // EL1 Exception syndrome register 32bit + mrs x6, far_el1 // EL1 Fault Address Register + b 4f + +2:mrs x2, elr_el2 // Exception Link Register + mrs x3, spsr_el2 // Saved Processor Status Register 32bit + mrs x5, esr_el2 // EL2 Exception syndrome register 32bit + mrs x6, far_el2 // EL2 Fault Address Register + b 4f + +3:mrs x2, elr_el3 // Exception Link Register + mrs x3, spsr_el3 // Saved Processor Status Register 32bit + mrs x5, esr_el3 // EL3 Exception syndrome register 32bit + mrs x6, far_el3 // EL3 Fault Address Register + +4:mrs x4, fpsr // Floating point Status Register 32bit // Record the type of exception that occurred. mov x0, #\val @@ -278,49 +247,44 @@ ASM_PFX(ExceptionHandlersEnd): ASM_PFX(CommonExceptionEntry): - /* NOTE: - We have to break up the save code because the immediate value to be used - with the SP is too big to do it all in one step so we need to shuffle the SP - along as we go. (we only have 9bits of immediate to work with) */ - - // Save the current Stack pointer before we start modifying it. - SAVE_SP - - // Preserve the stack pointer we came in with before we modify it - EL1_OR_EL2_OR_EL3(x1) -1:mrs x1, elr_el1 // Exception Link Register - mrs x2, spsr_el1 // Saved Processor Status Register 32bit - mrs x4, esr_el1 // EL1 Exception syndrome register 32bit - mrs x5, far_el1 // EL1 Fault Address Register - b 4f -2:mrs x1, elr_el2 // Exception Link Register - mrs x2, spsr_el2 // Saved Processor Status Register 32bit - mrs x4, esr_el2 // EL2 Exception syndrome register 32bit - mrs x5, far_el2 // EL2 Fault Address Register - b 4f - -3:mrs x1, elr_el3 // Exception Link Register - mrs x2, spsr_el3 // Saved Processor Status Register 32bit - mrs x4, esr_el3 // EL3 Exception syndrome register 32bit - mrs x5, far_el3 // EL3 Fault Address Register - -4:mrs x3, fpsr // Floating point Status Register 32bit - - // Adjust SP to save next set - add sp, sp, #FP_CONTEXT_SIZE - - // Push FP regs to Stack. - ALL_FP_REGS - - // Adjust SP to save next set - add sp, sp, #SYS_CONTEXT_SIZE + // Stack the remaining GP registers + stp x8, x9, [sp, #0x40] + stp x10, x11, [sp, #0x50] + stp x12, x13, [sp, #0x60] + stp x14, x15, [sp, #0x70] + stp x16, x17, [sp, #0x80] + stp x18, x19, [sp, #0x90] + stp x20, x21, [sp, #0xa0] + stp x22, x23, [sp, #0xb0] + stp x24, x25, [sp, #0xc0] + stp x26, x27, [sp, #0xd0] + stp x28, x29, [sp, #0xe0] + add x28, sp, #GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE + stp x30, x28, [sp, #0xf0] // Save the SYS regs - ALL_SYS_REGS + stp x2, x3, [x28, #-SYS_CONTEXT_SIZE]! + stp x4, x5, [x28, #0x10] + str x6, [x28, #0x20] - // Point to top of struct after all regs saved - sub sp, sp, #(GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE) + // Push FP regs to Stack. + stp q0, q1, [x28, #-FP_CONTEXT_SIZE]! + stp q2, q3, [x28, #0x20] + stp q4, q5, [x28, #0x40] + stp q6, q7, [x28, #0x60] + stp q8, q9, [x28, #0x80] + stp q10, q11, [x28, #0xa0] + stp q12, q13, [x28, #0xc0] + stp q14, q15, [x28, #0xe0] + stp q16, q17, [x28, #0x100] + stp q18, q19, [x28, #0x120] + stp q20, q21, [x28, #0x140] + stp q22, q23, [x28, #0x160] + stp q24, q25, [x28, #0x180] + stp q26, q27, [x28, #0x1a0] + stp q28, q29, [x28, #0x1c0] + stp q30, q31, [x28, #0x1e0] // x0 still holds the exception type. // Set x1 to point to the top of our struct on the Stack @@ -337,13 +301,44 @@ ASM_PFX(CommonExceptionEntry): // We do not try to recover. bl ASM_PFX(CommonCExceptionHandler) // Call exception handler - -// Defines for popping from stack - -#undef REG_PAIR -#undef REG_ONE -#define REG_PAIR(REG1, REG2, OFFSET, CONTEXT_SIZE) ldp REG1, REG2, [sp, #(OFFSET-CONTEXT_SIZE)] -#define REG_ONE(REG1, OFFSET, CONTEXT_SIZE) ldur REG1, [sp, #(OFFSET-CONTEXT_SIZE)] + // Pop as many GP regs as we can before entering the critical section below + ldp x2, x3, [sp, #0x10] + ldp x4, x5, [sp, #0x20] + ldp x6, x7, [sp, #0x30] + ldp x8, x9, [sp, #0x40] + ldp x10, x11, [sp, #0x50] + ldp x12, x13, [sp, #0x60] + ldp x14, x15, [sp, #0x70] + ldp x16, x17, [sp, #0x80] + ldp x18, x19, [sp, #0x90] + ldp x20, x21, [sp, #0xa0] + ldp x22, x23, [sp, #0xb0] + ldp x24, x25, [sp, #0xc0] + ldp x26, x27, [sp, #0xd0] + ldp x0, x1, [sp], #0xe0 + + // Pop FP regs from Stack. + ldp q2, q3, [x28, #0x20] + ldp q4, q5, [x28, #0x40] + ldp q6, q7, [x28, #0x60] + ldp q8, q9, [x28, #0x80] + ldp q10, q11, [x28, #0xa0] + ldp q12, q13, [x28, #0xc0] + ldp q14, q15, [x28, #0xe0] + ldp q16, q17, [x28, #0x100] + ldp q18, q19, [x28, #0x120] + ldp q20, q21, [x28, #0x140] + ldp q22, q23, [x28, #0x160] + ldp q24, q25, [x28, #0x180] + ldp q26, q27, [x28, #0x1a0] + ldp q28, q29, [x28, #0x1c0] + ldp q30, q31, [x28, #0x1e0] + ldp q0, q1, [x28], #FP_CONTEXT_SIZE + + // Pop the SYS regs we need + ldp x29, x30, [x28] + ldr x28, [x28, #0x10] + msr fpsr, x28 // // Disable interrupt(IRQ and FIQ) before restoring context, @@ -353,35 +348,23 @@ ASM_PFX(CommonExceptionEntry): msr daifset, #3 isb - // Adjust SP to pop system registers - add sp, sp, #(GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE) - ALL_SYS_REGS - - EL1_OR_EL2_OR_EL3(x6) -1:msr elr_el1, x1 // Exception Link Register - msr spsr_el1,x2 // Saved Processor Status Register 32bit + EL1_OR_EL2_OR_EL3(x28) +1:msr elr_el1, x29 // Exception Link Register + msr spsr_el1,x30 // Saved Processor Status Register 32bit b 4f -2:msr elr_el2, x1 // Exception Link Register - msr spsr_el2,x2 // Saved Processor Status Register 32bit +2:msr elr_el2, x29 // Exception Link Register + msr spsr_el2,x30 // Saved Processor Status Register 32bit b 4f -3:msr elr_el3, x1 // Exception Link Register - msr spsr_el3,x2 // Saved Processor Status Register 32bit -4:msr fpsr, x3 // Floating point Status Register 32bit - - // pop all regs and return from exception. - sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE) - ALL_GP_REGS +3:msr elr_el3, x29 // Exception Link Register + msr spsr_el3,x30 // Saved Processor Status Register 32bit +4: - // Adjust SP to pop next set - add sp, sp, #FP_CONTEXT_SIZE - // Pop FP regs to Stack. - ALL_FP_REGS + // pop remaining GP regs and return from exception. + ldr x30, [sp, #GP_CONTEXT_SIZE - 0xf0] + ldp x28, x29, [sp], #GP_CONTEXT_SIZE - 0xe0 // Adjust SP to be where we started from when we came into the handler. // The handler can not change the SP. - add sp, sp, #SYS_CONTEXT_SIZE + add sp, sp, #FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE eret - -#undef REG_PAIR -#undef REG_ONE