From patchwork Mon Oct 3 17:51:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Schwierzeck X-Patchwork-Id: 677786 X-Patchwork-Delegate: daniel.schwierzeck@googlemail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 3snqQp4J86z9s65 for ; Tue, 4 Oct 2016 04:53:22 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=OruR66Y8; dkim-atps=neutral Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id C2153B382C; Mon, 3 Oct 2016 19:52:38 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id YnikOYvUp-Qb; Mon, 3 Oct 2016 19:52:38 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id C6432B3865; Mon, 3 Oct 2016 19:52:15 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 98226B3832 for ; Mon, 3 Oct 2016 19:52:08 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id LuV78t65XA02 for ; Mon, 3 Oct 2016 19:52:08 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-wm0-f68.google.com (mail-wm0-f68.google.com [74.125.82.68]) by theia.denx.de (Postfix) with ESMTPS id 11D91B3838 for ; Mon, 3 Oct 2016 19:51:53 +0200 (CEST) Received: by mail-wm0-f68.google.com with SMTP id b184so15840610wma.3 for ; Mon, 03 Oct 2016 10:51:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=GjCcr4UfZp13BQta8Olrd2SJZIYQ4G7bWWeeQ9vau8Q=; b=OruR66Y8hkxL4bBvpqA5W04hzZy5zoCR5lhEl+3PLEjRADNkg8q54gbOka1p3DZ78K hphwHkDimFLwCOudAmKKsZ414acBTJAlFm8YfYkA4+oLNrQD9raxgB7UBVsGqV3oMUvD o3mqX3hGo7Z8K393vQL3wEwPneIE1Ykr9CP+J9zNn3SBeBenSaMHV5Nr8R0p/2wfsx0D zqHcNg6LesKmjIS2xWr5MzJFqBi1r50SFveNZSTcCgLadOe1mZ/bQ+AxCZsie1aSQEFS 4BsSj5IKAO+gD2ygM78OFY/sZd2zYkjIM+qdl/dm8FCXsY4s9EPjJwYnW2vakDias3gL GgGQ== 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=GjCcr4UfZp13BQta8Olrd2SJZIYQ4G7bWWeeQ9vau8Q=; b=aGoJ/deCsOl607Dj0WTaMtXoTbHklYOFJ5GJj1vXbFk0kQrwKVHeqdJmNv/2n2jznA yxRbxxuiotxtELW4dK7gOlHbuhGXAF5/ulbXmzsS3V0l+51M2Q7KkHHJB3RUMFNKYYos Ii07lxYS4F+SO1kOqS2/TD1K+tu5yOShrI4lyGWFi9qTV4aHH+C/b/njSotkQ0ypP0b+ WwTxfElB+AJ3pnFs/Ov3IzjfFtbRoMQK0aaPWe3/WD7ZnNyyLMTlD0ynyFejAXiVb5Tp o0cYYfFacfxYdJkXX5yicRNg6X2QP3alC492PLKWS8SbSJEDujPbFQ7u4BiFSBfxjEGf aTpg== X-Gm-Message-State: AA6/9Rm73xSjYoFRTbRSIVU9WRExNmpUOcrm5B9IXOdV9LgkM0vKw+yP6kUmd3ylFs48fw== X-Received: by 10.28.161.133 with SMTP id k127mr11247342wme.103.1475517112460; Mon, 03 Oct 2016 10:51:52 -0700 (PDT) Received: from workstation.zombienet.local (p2003005F2C3A130062A44CFFFE5E9229.dip0.t-ipconnect.de. [2003:5f:2c3a:1300:62a4:4cff:fe5e:9229]) by smtp.gmail.com with ESMTPSA id v189sm19972120wmv.12.2016.10.03.10.51.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 03 Oct 2016 10:51:51 -0700 (PDT) From: Daniel Schwierzeck To: u-boot@lists.denx.de Date: Mon, 3 Oct 2016 19:51:29 +0200 Message-Id: <20161003175130.22471-9-daniel.schwierzeck@gmail.com> X-Mailer: git-send-email 2.10.0 In-Reply-To: <20161003175130.22471-1-daniel.schwierzeck@gmail.com> References: <20161003175130.22471-1-daniel.schwierzeck@gmail.com> Cc: Marek Vasut , Purna Chandra Mandal , Wills Wang Subject: [U-Boot] [PATCH v2 8/9] MIPS: add handling for generic and EJTAG exceptions X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Add exception handlers for generic and EJTAG exceptions. Most of the assembly code is imported from Linux kernel and adapted to U-Boot. The exception vector table will be reserved above the stack before U-Boot is relocated. The exception handlers will be installed and activated after relocation in the initr_traps hook function. Generic exceptions are handled by showing a CPU register dump similar to Linux kernel. For example: malta # md 1 00000001: Ooops: $ 0 : 00000000 00000000 00000009 00000004 $ 4 : 8ff7e108 00000000 0000003a 00000000 $ 8 : 00000008 00000001 8ff7cd18 00000004 $12 : 00000002 00000000 00000005 0000003a $16 : 00000004 00000040 00000001 00000001 $20 : 00000000 8fff53c0 00000008 00000004 $24 : ffffffff 8ffdea44 $28 : 90001650 8ff7cd00 00000004 8ffe6818 Hi : 00000000 Lo : 00000004 epc : 8ffe6848 (text bfc28848) ra : 8ffe6818 (text bfc28818) Status: 00000006 Cause : 00000410 (ExcCode 04) BadVA : 8ff9e928 PrId : 00019300 ### ERROR ### Please RESET the board ### EJTAG exceptions are checked for SDBBP and delegated to the SDBBP handler if necessary. Otherwise the debug mode will simply be exited. The SDBBP handler currently prints the contents of registers c0_depc and c0_debug. This could be extended in the future to handle semi-hosting according to the MIPS UHI specification. Signed-off-by: Daniel Schwierzeck Reviewed-by: Paul Burton Tested-by: Paul Burton --- Changes in v2: - reordered macros in genex.S to allow side-by-side diff with Linux's arch/mips/include/asm/stackframe.h - sync'ed genex.S with Linux v4.8-rc8 to incorporate changes for MIPS r6 - add execution_hazard_barrier() after clearing c0 status.BEV arch/mips/include/asm/system.h | 8 ++ arch/mips/include/asm/u-boot-mips.h | 4 + arch/mips/lib/Makefile | 2 + arch/mips/lib/genex.S | 224 ++++++++++++++++++++++++++++++++++++ arch/mips/lib/traps.c | 106 +++++++++++++++++ 5 files changed, 344 insertions(+) create mode 100644 arch/mips/lib/genex.S create mode 100644 arch/mips/lib/traps.c diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h index e6435cc..c9c5961 100644 --- a/arch/mips/include/asm/system.h +++ b/arch/mips/include/asm/system.h @@ -262,4 +262,12 @@ extern void __die_if_kernel(const char *, struct pt_regs *, const char *where, #define die_if_kernel(msg, regs) \ __die_if_kernel(msg, regs, __FILE__ ":"__FUNCTION__, __LINE__) +static inline void execution_hazard_barrier(void) +{ + __asm__ __volatile__( + ".set noreorder\n" + "ehb\n" + ".set reorder"); +} + #endif /* _ASM_SYSTEM_H */ diff --git a/arch/mips/include/asm/u-boot-mips.h b/arch/mips/include/asm/u-boot-mips.h index 1f527bb..71ff41d 100644 --- a/arch/mips/include/asm/u-boot-mips.h +++ b/arch/mips/include/asm/u-boot-mips.h @@ -5,4 +5,8 @@ #ifndef _U_BOOT_MIPS_H_ #define _U_BOOT_MIPS_H_ +void exc_handler(void); +void except_vec3_generic(void); +void except_vec_ejtag_debug(void); + #endif /* _U_BOOT_MIPS_H_ */ diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 02607f7..659c6ad 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -7,7 +7,9 @@ obj-y += cache.o obj-y += cache_init.o +obj-y += genex.o obj-y += stack.o +obj-y += traps.o obj-$(CONFIG_CMD_BOOTM) += bootm.o diff --git a/arch/mips/lib/genex.S b/arch/mips/lib/genex.S new file mode 100644 index 0000000..2d6d7b0 --- /dev/null +++ b/arch/mips/lib/genex.S @@ -0,0 +1,224 @@ +/* + * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2002, 2007 Maciej W. Rozycki + * Copyright (C) 2001, 2012 MIPS Technologies, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +#define STATMASK 0x1f + + .set noreorder + + /* + * Macros copied and adapted from Linux MIPS + */ + .macro SAVE_AT + .set push + .set noat + LONG_S $1, PT_R1(sp) + .set pop + .endm + + .macro SAVE_TEMP +#if __mips_isa_rev < 6 + mfhi v1 +#endif +#ifdef CONFIG_32BIT + LONG_S $8, PT_R8(sp) + LONG_S $9, PT_R9(sp) +#endif + LONG_S $10, PT_R10(sp) + LONG_S $11, PT_R11(sp) + LONG_S $12, PT_R12(sp) +#if __mips_isa_rev < 6 + LONG_S v1, PT_HI(sp) + mflo v1 +#endif + LONG_S $13, PT_R13(sp) + LONG_S $14, PT_R14(sp) + LONG_S $15, PT_R15(sp) + LONG_S $24, PT_R24(sp) +#if __mips_isa_rev < 6 + LONG_S v1, PT_LO(sp) +#endif + .endm + + .macro SAVE_STATIC + LONG_S $16, PT_R16(sp) + LONG_S $17, PT_R17(sp) + LONG_S $18, PT_R18(sp) + LONG_S $19, PT_R19(sp) + LONG_S $20, PT_R20(sp) + LONG_S $21, PT_R21(sp) + LONG_S $22, PT_R22(sp) + LONG_S $23, PT_R23(sp) + LONG_S $30, PT_R30(sp) + .endm + + .macro SAVE_SOME + .set push + .set noat + PTR_SUBU k1, sp, PT_SIZE + LONG_S sp, PT_R29(k1) + move sp, k1 + + LONG_S $3, PT_R3(sp) + LONG_S $0, PT_R0(sp) + mfc0 v1, CP0_STATUS + LONG_S $2, PT_R2(sp) + LONG_S v1, PT_STATUS(sp) + LONG_S $4, PT_R4(sp) + mfc0 v1, CP0_CAUSE + LONG_S $5, PT_R5(sp) + LONG_S v1, PT_CAUSE(sp) + LONG_S $6, PT_R6(sp) + MFC0 v1, CP0_EPC + LONG_S $7, PT_R7(sp) +#ifdef CONFIG_64BIT + LONG_S $8, PT_R8(sp) + LONG_S $9, PT_R9(sp) +#endif + LONG_S v1, PT_EPC(sp) + LONG_S $25, PT_R25(sp) + LONG_S $28, PT_R28(sp) + LONG_S $31, PT_R31(sp) + .set pop + .endm + + .macro RESTORE_AT + .set push + .set noat + LONG_L $1, PT_R1(sp) + .set pop + .endm + + .macro RESTORE_TEMP +#if __mips_isa_rev < 6 + LONG_L $24, PT_LO(sp) + mtlo $24 + LONG_L $24, PT_HI(sp) + mthi $24 +#endif +#ifdef CONFIG_32BIT + LONG_L $8, PT_R8(sp) + LONG_L $9, PT_R9(sp) +#endif + LONG_L $10, PT_R10(sp) + LONG_L $11, PT_R11(sp) + LONG_L $12, PT_R12(sp) + LONG_L $13, PT_R13(sp) + LONG_L $14, PT_R14(sp) + LONG_L $15, PT_R15(sp) + LONG_L $24, PT_R24(sp) + .endm + + .macro RESTORE_STATIC + LONG_L $16, PT_R16(sp) + LONG_L $17, PT_R17(sp) + LONG_L $18, PT_R18(sp) + LONG_L $19, PT_R19(sp) + LONG_L $20, PT_R20(sp) + LONG_L $21, PT_R21(sp) + LONG_L $22, PT_R22(sp) + LONG_L $23, PT_R23(sp) + LONG_L $30, PT_R30(sp) + .endm + + .macro RESTORE_SOME + .set push + .set reorder + .set noat + mfc0 a0, CP0_STATUS + ori a0, STATMASK + xori a0, STATMASK + mtc0 a0, CP0_STATUS + li v1, ST0_CU1 | ST0_FR | ST0_IM + and a0, v1 + LONG_L v0, PT_STATUS(sp) + nor v1, $0, v1 + and v0, v1 + or v0, a0 + mtc0 v0, CP0_STATUS + LONG_L v1, PT_EPC(sp) + MTC0 v1, CP0_EPC + LONG_L $31, PT_R31(sp) + LONG_L $28, PT_R28(sp) + LONG_L $25, PT_R25(sp) +#ifdef CONFIG_64BIT + LONG_L $8, PT_R8(sp) + LONG_L $9, PT_R9(sp) +#endif + LONG_L $7, PT_R7(sp) + LONG_L $6, PT_R6(sp) + LONG_L $5, PT_R5(sp) + LONG_L $4, PT_R4(sp) + LONG_L $3, PT_R3(sp) + LONG_L $2, PT_R2(sp) + .set pop + .endm + + .macro RESTORE_SP + LONG_L sp, PT_R29(sp) + .endm + +NESTED(except_vec3_generic, 0, sp) + PTR_LA k1, handle_reserved + jr k1 + nop + END(except_vec3_generic) + +NESTED(except_vec_ejtag_debug, 0, sp) + PTR_LA k1, handle_ejtag_debug + jr k1 + nop + END(except_vec_ejtag_debug) + +NESTED(handle_reserved, PT_SIZE, sp) + SAVE_SOME + SAVE_AT + SAVE_TEMP + SAVE_STATIC + + PTR_LA t9, do_reserved + jr t9 + move a0, sp + END(handle_reserved) + +NESTED(handle_ejtag_debug, PT_SIZE, sp) + .set push + .set noat + MTC0 k1, CP0_DESAVE + + /* Check for SDBBP */ + MFC0 k1, CP0_DEBUG + sll k1, k1, 30 + bgez k1, ejtag_return + nop + + SAVE_SOME + SAVE_AT + SAVE_TEMP + SAVE_STATIC + + PTR_LA t9, do_ejtag_debug + jalr t9 + move a0, sp + + RESTORE_TEMP + RESTORE_STATIC + RESTORE_AT + RESTORE_SOME + RESTORE_SP + +ejtag_return: + MFC0 k1, CP0_DESAVE + deret + .set pop + END(handle_ejtag_debug) diff --git a/arch/mips/lib/traps.c b/arch/mips/lib/traps.c new file mode 100644 index 0000000..18622c2 --- /dev/null +++ b/arch/mips/lib/traps.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 1994 - 1999, 2000, 01, 06 Ralf Baechle + * Copyright (C) 1995, 1996 Paul M. Antoine + * Copyright (C) 1998 Ulf Carlsson + * Copyright (C) 1999 Silicon Graphics, Inc. + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2002, 2003, 2004, 2005, 2007 Maciej W. Rozycki + * Copyright (C) 2000, 2001, 2012 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2014, Imagination Technologies Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static void show_regs(const struct pt_regs *regs) +{ + const int field = 2 * sizeof(unsigned long); + unsigned int cause = regs->cp0_cause; + unsigned int exccode; + int i; + + /* + * Saved main processor registers + */ + for (i = 0; i < 32; ) { + if ((i % 4) == 0) + printf("$%2d :", i); + if (i == 0) + printf(" %0*lx", field, 0UL); + else if (i == 26 || i == 27) + printf(" %*s", field, ""); + else + printf(" %0*lx", field, regs->regs[i]); + + i++; + if ((i % 4) == 0) + puts("\n"); + } + + printf("Hi : %0*lx\n", field, regs->hi); + printf("Lo : %0*lx\n", field, regs->lo); + + /* + * Saved cp0 registers + */ + printf("epc : %0*lx (text %0*lx)\n", field, regs->cp0_epc, + field, regs->cp0_epc - gd->reloc_off); + printf("ra : %0*lx (text %0*lx)\n", field, regs->regs[31], + field, regs->regs[31] - gd->reloc_off); + + printf("Status: %08x\n", (uint32_t) regs->cp0_status); + + exccode = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE; + printf("Cause : %08x (ExcCode %02x)\n", cause, exccode); + + if (1 <= exccode && exccode <= 5) + printf("BadVA : %0*lx\n", field, regs->cp0_badvaddr); + + printf("PrId : %08x\n", read_c0_prid()); +} + +void do_reserved(const struct pt_regs *regs) +{ + puts("\nOoops:\n"); + show_regs(regs); + hang(); +} + +void do_ejtag_debug(const struct pt_regs *regs) +{ + const int field = 2 * sizeof(unsigned long); + unsigned long depc; + unsigned int debug; + + depc = read_c0_depc(); + debug = read_c0_debug(); + + printf("SDBBP EJTAG debug exception: c0_depc = %0*lx, DEBUG = %08x\n", + field, depc, debug); +} + +static void set_handler(unsigned long offset, void *addr, unsigned long size) +{ + unsigned long ebase = gd->irq_sp; + + memcpy((void *)(ebase + offset), addr, size); + flush_cache(ebase + offset, size); +} + +void trap_init(ulong reloc_addr) +{ + unsigned long ebase = gd->irq_sp; + + set_handler(0x180, &except_vec3_generic, 0x80); + set_handler(0x280, &except_vec_ejtag_debug, 0x80); + + write_c0_ebase(ebase); + clear_c0_status(ST0_BEV); + execution_hazard_barrier(); +}