From patchwork Wed May 5 18:47:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liming Sun X-Patchwork-Id: 1474518 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=Nvidia.com header.i=@Nvidia.com header.a=rsa-sha256 header.s=selector2 header.b=McJDk1QZ; dkim-atps=neutral Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Fb5M32GlHz9sV5; Thu, 6 May 2021 04:48:15 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1leMZA-0001TN-FS; Wed, 05 May 2021 18:48:12 +0000 Received: from mail-bn8nam12on2048.outbound.protection.outlook.com ([40.107.237.48] helo=NAM12-BN8-obe.outbound.protection.outlook.com) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1leMZ5-0001S5-QJ for kernel-team@lists.ubuntu.com; Wed, 05 May 2021 18:48:08 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=h0ks6JkLE2kr71aJKrT86YX3CFj0G4qw1eBXML8HWXPWyoGB8tcRaprAa6EYltmMKuJkupQNIDRiMGgr98KsSq7sTFs7CL3vjZSPNcSyLJxKQt4jkvWuS53RpEc/C4jZRC7ZbOMIUXHeCrlxAb2xOfMgZaFqcdDN5k23KE9lgEzfkOOHfoh4NVl2igpc+rOzEgjcsE+8YX0DJtPefbeE/IGtrcqL6NiZfE+bR2+d2kXvbh1+JzC3mp/VQk4sdvDJMdGIGteaJ6K7Y4VrievVwhjoiVFw6Dk+sKNiU3pe9Ahg75yRB4LSzgz5DcNkJYq0yc2AnBkO/67uzIZE/IdL7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=OdnJNRUjT7vlExFrtENmRl6X1razqWqmtBlm/EoluWI=; b=GgThEvSm8QatlezPuMeZq2YOgn6YEBCMPb9MOz4BhF/zDUEPpQYmXhYmtcisTuzcy/BczG6FgD6fYyrP+UTL+wLXCj2t1vgpeGYujUyjXasTc9xpYmrbsbLhlR7CvB+/ivaDD9IlrrWsIGbwygoFwFnF7nuzydhy0/K6BC9HdG1llcMhglXf+OxgyVmFNVhLMpKwR1cIk40m4DmrwjKoOLbBHY687OlrDlYX9Sf/G7uORhQtEPpounfG0Y+c1v7MU0+BvCDgsEmYyqMVr8+tmktG8vc2gf/NYU5he0TV19UQCIh+ato5VqmYp9L6nl4YsIiFSoO233uZi1bT6ib4TQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.112.35) smtp.rcpttodomain=lists.ubuntu.com smtp.mailfrom=nvidia.com; dmarc=pass (p=none sp=none pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=OdnJNRUjT7vlExFrtENmRl6X1razqWqmtBlm/EoluWI=; b=McJDk1QZF5RxdwHEnOP3lLssrJPDeLNaI8wwWYJoJ6CMBp0pYUOrCNJ0V9cDALdbinCVhnOvHMlOjXgvMVQnufuWKvURc4zLSjBTfPrAL+IJ4TUbEcdcSH1UtSlzI2rHSCgIKAAWtnlogExqgQxI7YjkqG08SSBG3b/LBPiLv/kHhI/L6YfcuyUpNRkhXI+BBvng5FAIWI8bgX+Ew1SBqUABw7/vLxmZlHysSpxL6Gljv4qXZdDlJ+lNefN0UK1FLzV8cR9a8Bn5MxnMmvg40JIicp7QLCqqnaA0hKf0kIGXN6DQPmj2N7g6/F0b0CCQ+ftjC7Ja+4hkgbcwWG5aJg== Received: from BN0PR04CA0043.namprd04.prod.outlook.com (2603:10b6:408:e8::18) by CY4PR12MB1253.namprd12.prod.outlook.com (2603:10b6:903:3c::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4087.41; Wed, 5 May 2021 18:48:05 +0000 Received: from BN8NAM11FT034.eop-nam11.prod.protection.outlook.com (2603:10b6:408:e8:cafe::36) by BN0PR04CA0043.outlook.office365.com (2603:10b6:408:e8::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4108.25 via Frontend Transport; Wed, 5 May 2021 18:48:05 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.112.35) smtp.mailfrom=nvidia.com; lists.ubuntu.com; dkim=none (message not signed) header.d=none;lists.ubuntu.com; dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.112.35 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.112.35; helo=mail.nvidia.com; Received: from mail.nvidia.com (216.228.112.35) by BN8NAM11FT034.mail.protection.outlook.com (10.13.176.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.4108.25 via Frontend Transport; Wed, 5 May 2021 18:48:05 +0000 Received: from HQMAIL111.nvidia.com (172.20.187.18) by HQMAIL111.nvidia.com (172.20.187.18) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 5 May 2021 18:48:04 +0000 Received: from vdi.nvidia.com (172.20.145.6) by mail.nvidia.com (172.20.187.18) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Wed, 5 May 2021 18:48:04 +0000 From: Liming Sun To: Subject: [PATCH v2 1/1] mlx-bootctl: rshim logging display from linux sysfs Date: Wed, 5 May 2021 14:47:59 -0400 Message-ID: <1276a0dd5bf5b9d8dd0d33206b1436cc4ff64fd1.1620239895.git.limings@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: References: <8f4bb75041167893ebd991562d4bfcaa2bbaf8ff.1620234248.git.limings@nvidia.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 7b687fc2-bfee-4940-12a9-08d90ff6517d X-MS-TrafficTypeDiagnostic: CY4PR12MB1253: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:220; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: MOYzFHFnE5ho/VfpkB96fDcKxHhlcgWk0S40oW+0cw9fOm+zHrxK/OlalEyFXbgAV/lm/7WOdAJvzwBeM+gC0e0jLCeVBD7aWS4mWG+J+HUStEbZ00bW0QcLCyT9zNmSw84cQzrWGgby2IXCdkKvnI89/9FKJVZ3nhfyrukccfrGBOGfDlQzyn7CGRx77vV9bHrawDJLh8+yhRxNDJ8EuAwGiswB7eUrRy1XaNsZjH8ADPaugwBJYNiizRuuA+2cJAvDlJUGerpTVXeYTFHS7HOgYRmoEuovH1SLioDolc4Vif1TkJGskcw9AOQrtNyLSDozdUmecIw3KNj9JPn9YAOyRUTnW6suQnD5AS5IPoTB4wNLv9I+xKkEXgV6Kc+uUKO6Xl+50PjDNsZb1iZ1IiEFwot7WaFSL/LRKboGyEegQvupRAFAeIJy6Uhf3nAz+5VP691Ft7nRZQq6VltyiUu+HkElAho/pN07zB9Q0Oe+Zi6gQ9XFJWks9l89WL52rwPhnCyIZiUkbZkoYPMxwcjsW8E0Q4B+55emcDZw4+CCoNcVCcp0vvbwBuhbJtlH7KashaYxFoma7qgN2M5OqD9LJVXMHM+uDgIGre2PuanccUGgtoFZYypaPppJAPyCuw21XsSq6RonUmI0b5zDNbGKUnTHrVu6rvXjhj1q17q2jTR7MSwL2bl8J3kIBM72rovHgS8jfjdazdLN/gv4S0hIWvb1iocwC2gjSb3AJ14= X-Forefront-Antispam-Report: CIP:216.228.112.35; CTRY:US; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:mail.nvidia.com; PTR:schybrid02.nvidia.com; CAT:NONE; SFS:(4636009)(396003)(346002)(136003)(39860400002)(376002)(46966006)(36840700001)(107886003)(186003)(2906002)(8676002)(36906005)(7696005)(5660300002)(316002)(70206006)(356005)(966005)(26005)(86362001)(4326008)(82310400003)(83380400001)(70586007)(36860700001)(2616005)(47076005)(336012)(30864003)(478600001)(8936002)(6666004)(7636003)(6916009)(426003)(82740400003)(36756003); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 May 2021 18:48:05.0629 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 7b687fc2-bfee-4940-12a9-08d90ff6517d X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[216.228.112.35]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: BN8NAM11FT034.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY4PR12MB1253 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Liming Sun Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" BugLink: https://bugs.launchpad.net/bugs/1927263 This commit adds the rshim logging display support from linux sysfs. The display logic is ported from the user-space rshim driver. Module parameter 'rsh_log_clear_on_read' is added to clear the the logging buffer after read when this flag is set. Example: cat /sys/bus/platform/drivers/mlx-bootctl/rsh_log INFO[BL2]: start INFO[BL2]: DDR POST passed INFO[BL2]: UEFI loaded INFO[BL31]: start INFO[BL31]: runtime ... echo 1 > /sys/module/mlx_bootctl/parameters/rsh_log_clear_on_read Signed-off-by: Liming Sun --- drivers/platform/mellanox/mlx-bootctl.c | 402 +++++++++++++++++++++++++++++--- 1 file changed, 373 insertions(+), 29 deletions(-) diff --git a/drivers/platform/mellanox/mlx-bootctl.c b/drivers/platform/mellanox/mlx-bootctl.c index 7ec7c9a..6eff360 100644 --- a/drivers/platform/mellanox/mlx-bootctl.c +++ b/drivers/platform/mellanox/mlx-bootctl.c @@ -64,6 +64,10 @@ struct boot_name { static void __iomem *rsh_scratch_buf_ctl; static void __iomem *rsh_scratch_buf_data; +static int rsh_log_clear_on_read; +module_param(rsh_log_clear_on_read, int, 0644); +MODULE_PARM_DESC(rsh_log_clear_on_read, "Clear rshim logging buffer after read."); + /* * Objects are stored within the MFG partition per type. Type 0 is not * supported. @@ -290,7 +294,7 @@ static ssize_t fw_reset_store(struct device_driver *drv, static ssize_t oob_mac_show(struct device_driver *drv, char *buf) { - char mac_str[MLNX_MFG_OOB_MAC_FORMAT_LEN] = { 0 }; + char mac_str[MLNX_MFG_OOB_MAC_FORMAT_LEN + 1] = { 0 }; struct arm_smccc_res res; u8 *mac_byte_ptr; @@ -315,14 +319,15 @@ static ssize_t oob_mac_store(struct device_driver *drv, const char *buf, struct arm_smccc_res res; u64 mac_addr = 0; u8 *mac_byte_ptr; - int byte_idx; + int byte_idx, len; if ((count - 1) != MLNX_MFG_OOB_MAC_FORMAT_LEN) return -EINVAL; - if (MLNX_MFG_OOB_MAC_LEN != sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", - &byte[0], &byte[1], &byte[2], - &byte[3], &byte[4], &byte[5])) + len = sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", + &byte[0], &byte[1], &byte[2], + &byte[3], &byte[4], &byte[5]); + if (len != MLNX_MFG_OOB_MAC_LEN) return -EINVAL; mac_byte_ptr = (u8 *)&mac_addr; @@ -340,7 +345,7 @@ static ssize_t oob_mac_store(struct device_driver *drv, const char *buf, static u8 get_opn_type(u8 word) { - switch(word) { + switch (word) { case 0: return MLNX_MFG_TYPE_OPN_0; case 1: @@ -452,7 +457,32 @@ static ssize_t mfg_lock_store(struct device_driver *drv, const char *buf, #define RSH_LOG_LEVEL_SHIFT 0 /* Module ID and type used here. */ -#define RSH_LOG_TYPE 0x04ULL /* message */ +#define BF_RSH_LOG_TYPE_UNKNOWN 0x00ULL +#define BF_RSH_LOG_TYPE_PANIC 0x01ULL +#define BF_RSH_LOG_TYPE_EXCEPTION 0x02ULL +#define BF_RSH_LOG_TYPE_UNUSED 0x03ULL +#define BF_RSH_LOG_TYPE_MSG 0x04ULL + +/* Utility macro. */ +#define BF_RSH_LOG_MOD_MASK 0x0FULL +#define BF_RSH_LOG_MOD_SHIFT 60 +#define BF_RSH_LOG_TYPE_MASK 0x0FULL +#define BF_RSH_LOG_TYPE_SHIFT 56 +#define BF_RSH_LOG_LEN_MASK 0x7FULL +#define BF_RSH_LOG_LEN_SHIFT 48 +#define BF_RSH_LOG_ARG_MASK 0xFFFFFFFFULL +#define BF_RSH_LOG_ARG_SHIFT 16 +#define BF_RSH_LOG_HAS_ARG_MASK 0xFFULL +#define BF_RSH_LOG_HAS_ARG_SHIFT 8 +#define BF_RSH_LOG_LEVEL_MASK 0xFFULL +#define BF_RSH_LOG_LEVEL_SHIFT 0 +#define BF_RSH_LOG_PC_MASK 0xFFFFFFFFULL +#define BF_RSH_LOG_PC_SHIFT 0 +#define BF_RSH_LOG_SYNDROME_MASK 0xFFFFFFFFULL +#define BF_RSH_LOG_SYNDROME_SHIFT 0 + +#define BF_RSH_LOG_HEADER_GET(f, h) \ + (((h) >> BF_RSH_LOG_##f##_SHIFT) & BF_RSH_LOG_##f##_MASK) /* Log message level. */ enum { @@ -461,16 +491,159 @@ enum { RSH_LOG_ERR }; -const char *rsh_log_level[] = {"INFO", "WARN", "ERR"}; +/* Log module */ +const char * const rsh_log_mod[] = { + "MISC", "BL1", "BL2", "BL2R", "BL31", "UEFI" +}; + +const char *rsh_log_level[] = {"INFO", "WARN", "ERR", "ASSERT"}; + +#define AARCH64_MRS_REG_SHIFT 5 +#define AARCH64_MRS_REG_MASK 0xffff +#define AARCH64_ESR_ELX_EXCEPTION_CLASS_SHIFT 26 + +struct rsh_log_reg { + char *name; + u32 opcode; +} rsh_log_reg; + +static struct rsh_log_reg rsh_log_regs[] = { + {"actlr_el1", 0b1100000010000001}, + {"actlr_el2", 0b1110000010000001}, + {"actlr_el3", 0b1111000010000001}, + {"afsr0_el1", 0b1100001010001000}, + {"afsr0_el2", 0b1110001010001000}, + {"afsr0_el3", 0b1111001010001000}, + {"afsr1_el1", 0b1100001010001001}, + {"afsr1_el2", 0b1110001010001001}, + {"afsr1_el3", 0b1111001010001001}, + {"amair_el1", 0b1100010100011000}, + {"amair_el2", 0b1110010100011000}, + {"amair_el3", 0b1111010100011000}, + {"ccsidr_el1", 0b1100100000000000}, + {"clidr_el1", 0b1100100000000001}, + {"cntkctl_el1", 0b1100011100001000}, + {"cntp_ctl_el0", 0b1101111100010001}, + {"cntp_cval_el0", 0b1101111100010010}, + {"cntv_ctl_el0", 0b1101111100011001}, + {"cntv_cval_el0", 0b1101111100011010}, + {"contextidr_el1", 0b1100011010000001}, + {"cpacr_el1", 0b1100000010000010}, + {"cptr_el2", 0b1110000010001010}, + {"cptr_el3", 0b1111000010001010}, + {"vtcr_el2", 0b1110000100001010}, + {"ctr_el0", 0b1101100000000001}, + {"currentel", 0b1100001000010010}, + {"dacr32_el2", 0b1110000110000000}, + {"daif", 0b1101101000010001}, + {"dczid_el0", 0b1101100000000111}, + {"dlr_el0", 0b1101101000101001}, + {"dspsr_el0", 0b1101101000101000}, + {"elr_el1", 0b1100001000000001}, + {"elr_el2", 0b1110001000000001}, + {"elr_el3", 0b1111001000000001}, + {"esr_el1", 0b1100001010010000}, + {"esr_el2", 0b1110001010010000}, + {"esr_el3", 0b1111001010010000}, + {"esselr_el1", 0b1101000000000000}, + {"far_el1", 0b1100001100000000}, + {"far_el2", 0b1110001100000000}, + {"far_el3", 0b1111001100000000}, + {"fpcr", 0b1101101000100000}, + {"fpexc32_el2", 0b1110001010011000}, + {"fpsr", 0b1101101000100001}, + {"hacr_el2", 0b1110000010001111}, + {"har_el2", 0b1110000010001000}, + {"hpfar_el2", 0b1110001100000100}, + {"hstr_el2", 0b1110000010001011}, + {"far_el1", 0b1100001100000000}, + {"far_el2", 0b1110001100000000}, + {"far_el3", 0b1111001100000000}, + {"hcr_el2", 0b1110000010001000}, + {"hpfar_el2", 0b1110001100000100}, + {"id_aa64afr0_el1", 0b1100000000101100}, + {"id_aa64afr1_el1", 0b1100000000101101}, + {"id_aa64dfr0_el1", 0b1100000000101100}, + {"id_aa64isar0_el1", 0b1100000000110000}, + {"id_aa64isar1_el1", 0b1100000000110001}, + {"id_aa64mmfr0_el1", 0b1100000000111000}, + {"id_aa64mmfr1_el1", 0b1100000000111001}, + {"id_aa64pfr0_el1", 0b1100000000100000}, + {"id_aa64pfr1_el1", 0b1100000000100001}, + {"ifsr32_el2", 0b1110001010000001}, + {"isr_el1", 0b1100011000001000}, + {"mair_el1", 0b1100010100010000}, + {"mair_el2", 0b1110010100010000}, + {"mair_el3", 0b1111010100010000}, + {"midr_el1", 0b1100000000000000}, + {"mpidr_el1", 0b1100000000000101}, + {"nzcv", 0b1101101000010000}, + {"revidr_el1", 0b1100000000000110}, + {"rmr_el3", 0b1111011000000010}, + {"par_el1", 0b1100001110100000}, + {"rvbar_el3", 0b1111011000000001}, + {"scr_el3", 0b1111000010001000}, + {"sctlr_el1", 0b1100000010000000}, + {"sctlr_el2", 0b1110000010000000}, + {"sctlr_el3", 0b1111000010000000}, + {"sp_el0", 0b1100001000001000}, + {"sp_el1", 0b1110001000001000}, + {"spsel", 0b1100001000010000}, + {"spsr_abt", 0b1110001000011001}, + {"spsr_el1", 0b1100001000000000}, + {"spsr_el2", 0b1110001000000000}, + {"spsr_el3", 0b1111001000000000}, + {"spsr_fiq", 0b1110001000011011}, + {"spsr_irq", 0b1110001000011000}, + {"spsr_und", 0b1110001000011010}, + {"tcr_el1", 0b1100000100000010}, + {"tcr_el2", 0b1110000100000010}, + {"tcr_el3", 0b1111000100000010}, + {"tpidr_el0", 0b1101111010000010}, + {"tpidr_el1", 0b1100011010000100}, + {"tpidr_el2", 0b1110011010000010}, + {"tpidr_el3", 0b1111011010000010}, + {"tpidpro_el0", 0b1101111010000011}, + {"vbar_el1", 0b1100011000000000}, + {"vbar_el2", 0b1110011000000000}, + {"vbar_el3", 0b1111011000000000}, + {"vmpidr_el2", 0b1110000000000101}, + {"vpidr_el2", 0b1110000000000000}, + {"ttbr0_el1", 0b1100000100000000}, + {"ttbr0_el2", 0b1110000100000000}, + {"ttbr0_el3", 0b1111000100000000}, + {"ttbr1_el1", 0b1100000100000001}, + {"vtcr_el2", 0b1110000100001010}, + {"vttbr_el2", 0b1110000100001000}, + {NULL, 0b0000000000000000}, +}; /* Size(8-byte words) of the log buffer. */ -#define RSH_SCRATCH_BUF_CTL_IDX_MAX 0x7f +#define RSH_SCRATCH_BUF_CTL_IDX_MASK 0x7f + +static int rsh_log_sem_lock(void) +{ + unsigned long timeout; + + /* Take the semaphore. */ + timeout = jiffies + msecs_to_jiffies(100); + while (readq(rsh_semaphore)) { + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; + } + + return 0; +} + +static void rsh_log_sem_unlock(void) +{ + writeq(0, rsh_semaphore); +} static ssize_t rsh_log_store(struct device_driver *drv, const char *buf, size_t count) { - int idx, num, len, size = (int)count, level = RSH_LOG_INFO; - unsigned long timeout; + int idx, num, len, size = (int)count, level = RSH_LOG_INFO, rc; u64 data; if (!size) @@ -501,22 +674,20 @@ static ssize_t rsh_log_store(struct device_driver *drv, const char *buf, } /* Take the semaphore. */ - timeout = jiffies + msecs_to_jiffies(100); - while (readq(rsh_semaphore)) { - if (time_after(jiffies, timeout)) - return -ETIMEDOUT; - } + rc = rsh_log_sem_lock(); + if (rc) + return rc; /* Calculate how many words are available. */ num = (size + sizeof(u64) - 1) / sizeof(u64); idx = readq(rsh_scratch_buf_ctl); - if (idx + num + 1 >= RSH_SCRATCH_BUF_CTL_IDX_MAX) - num = RSH_SCRATCH_BUF_CTL_IDX_MAX - idx - 1; + if (idx + num + 1 >= RSH_SCRATCH_BUF_CTL_IDX_MASK) + num = RSH_SCRATCH_BUF_CTL_IDX_MASK - idx - 1; if (num <= 0) goto done; /* Write Header. */ - data = (RSH_LOG_TYPE << RSH_LOG_TYPE_SHIFT) | + data = (BF_RSH_LOG_TYPE_MSG << RSH_LOG_TYPE_SHIFT) | ((u64)num << RSH_LOG_LEN_SHIFT) | ((u64)level << RSH_LOG_LEVEL_SHIFT); writeq(data, rsh_scratch_buf_data); @@ -528,7 +699,7 @@ static ssize_t rsh_log_store(struct device_driver *drv, const char *buf, memcpy(&data, buf, len); len = 0; } else { - memcpy (&data, buf, sizeof(u64)); + memcpy(&data, buf, sizeof(u64)); len -= sizeof(u64); buf += sizeof(u64); } @@ -537,24 +708,197 @@ static ssize_t rsh_log_store(struct device_driver *drv, const char *buf, done: /* Release the semaphore. */ - writeq(0, rsh_semaphore); + rsh_log_sem_unlock(); /* Ignore the rest if no more space. */ return count; } -#define MBC_DRV_ATTR(_name) DRIVER_ATTR_RW(_name) +static char *rsh_log_get_reg_name(u64 opcode) +{ + struct rsh_log_reg *reg = rsh_log_regs; + + while (reg->name) { + if (reg->opcode == opcode) + return reg->name; + reg++; + } + + return "unknown"; +} + +static int rsh_log_show_crash(u64 hdr, char *buf) +{ + int i, module, type, len, n = 0; + u32 pc, syndrome, ec; + u64 opcode, data; + char *p = buf; + + module = BF_RSH_LOG_HEADER_GET(MOD, hdr); + if (module >= ARRAY_SIZE(rsh_log_mod)) + module = 0; + type = BF_RSH_LOG_HEADER_GET(TYPE, hdr); + len = BF_RSH_LOG_HEADER_GET(LEN, hdr); + + if (type == BF_RSH_LOG_TYPE_EXCEPTION) { + syndrome = BF_RSH_LOG_HEADER_GET(SYNDROME, hdr); + ec = syndrome >> AARCH64_ESR_ELX_EXCEPTION_CLASS_SHIFT; + n = sprintf(p, " Exception(%s): syndrome = 0x%x%s\n", + rsh_log_mod[module], syndrome, + (ec == 0x24 || ec == 0x25) ? "(Data Abort)" : + (ec == 0x2f) ? "(SError)" : ""); + } else if (type == BF_RSH_LOG_TYPE_PANIC) { + pc = BF_RSH_LOG_HEADER_GET(PC, hdr); + n = sprintf(p, " PANIC(%s): PC = 0x%x\n", rsh_log_mod[module], + pc); + } + if (n > 0) + p += n; + + /* + * Read the registers in a loop. 'len' is the total number of words in + * 8-bytes. Two words are read in each loop. + */ + for (i = 0; i < len/2; i++) { + opcode = readq(rsh_scratch_buf_data); + data = readq(rsh_scratch_buf_data); + + opcode = (opcode >> AARCH64_MRS_REG_SHIFT) & + AARCH64_MRS_REG_MASK; + n = sprintf(p, " %-16s0x%llx\n", rsh_log_get_reg_name(opcode), + (unsigned long long)data); + if (n > 0) + p += n; + } + + return p - buf; +} + +static int rsh_log_format_msg(char *buf, const char *msg, ...) +{ + va_list args; + int len; + + va_start(args, msg); + len = vsprintf(buf, msg, args); + va_end(args); + + return len; +} + +static int rsh_log_show_msg(u64 hdr, char *buf) +{ + int has_arg = BF_RSH_LOG_HEADER_GET(HAS_ARG, hdr); + int level = BF_RSH_LOG_HEADER_GET(LEVEL, hdr); + int module = BF_RSH_LOG_HEADER_GET(MOD, hdr); + int len = BF_RSH_LOG_HEADER_GET(LEN, hdr); + u32 arg = BF_RSH_LOG_HEADER_GET(ARG, hdr); + char *msg, *p; + u64 data; + + if (len <= 0) + return -EINVAL; + + if (module >= ARRAY_SIZE(rsh_log_mod)) + module = 0; + + if (level >= ARRAY_SIZE(rsh_log_level)) + level = 0; + + msg = kmalloc(len * sizeof(u64) + 1, GFP_KERNEL); + if (!msg) + return 0; + p = msg; + + while (len--) { + data = readq(rsh_scratch_buf_data); + memcpy(p, &data, sizeof(data)); + p += sizeof(data); + } + *p = '\0'; + if (!has_arg) { + len = sprintf(buf, " %s[%s]: %s\n", rsh_log_level[level], + rsh_log_mod[module], msg); + } else { + len = sprintf(buf, " %s[%s]: ", rsh_log_level[level], + rsh_log_mod[module]); + len += rsh_log_format_msg(buf + len, msg, arg); + len += sprintf(buf + len, "\n"); + } + + kfree(msg); + return len; +} + +static ssize_t rsh_log_show(struct device_driver *drv, char *buf) +{ + u64 hdr; + char *p = buf; + int i, n, rc, idx, type, len; + + if (!rsh_semaphore || !rsh_scratch_buf_ctl) + return -EOPNOTSUPP; + + /* Take the semaphore. */ + rc = rsh_log_sem_lock(); + if (rc) + return rc; + + /* Save the current index and read from 0. */ + idx = readq(rsh_scratch_buf_ctl) & RSH_SCRATCH_BUF_CTL_IDX_MASK; + if (!idx) + goto done; + writeq(0, rsh_scratch_buf_ctl); + + i = 0; + while (i < idx) { + hdr = readq(rsh_scratch_buf_data); + type = BF_RSH_LOG_HEADER_GET(TYPE, hdr); + len = BF_RSH_LOG_HEADER_GET(LEN, hdr); + i += 1 + len; + if (i > idx) + break; + + switch (type) { + case BF_RSH_LOG_TYPE_PANIC: + case BF_RSH_LOG_TYPE_EXCEPTION: + n = rsh_log_show_crash(hdr, p); + p += n; + break; + case BF_RSH_LOG_TYPE_MSG: + n = rsh_log_show_msg(hdr, p); + p += n; + break; + default: + /* Drain this message. */ + while (len--) + (void) readq(rsh_scratch_buf_data); + break; + } + } + + if (rsh_log_clear_on_read) + writeq(0, rsh_scratch_buf_ctl); + else + writeq(idx, rsh_scratch_buf_ctl); + +done: + /* Release the semaphore. */ + rsh_log_sem_unlock(); + + return p - buf; +} -static MBC_DRV_ATTR(post_reset_wdog); -static MBC_DRV_ATTR(reset_action); -static MBC_DRV_ATTR(second_reset_action); +static DRIVER_ATTR_RW(post_reset_wdog); +static DRIVER_ATTR_RW(reset_action); +static DRIVER_ATTR_RW(second_reset_action); static DRIVER_ATTR_RO(lifecycle_state); static DRIVER_ATTR_RO(secure_boot_fuse_state); static DRIVER_ATTR_WO(fw_reset); -static MBC_DRV_ATTR(oob_mac); -static MBC_DRV_ATTR(opn_str); +static DRIVER_ATTR_RW(oob_mac); +static DRIVER_ATTR_RW(opn_str); static DRIVER_ATTR_WO(mfg_lock); -static DRIVER_ATTR_WO(rsh_log); +static DRIVER_ATTR_RW(rsh_log); static struct attribute *mbc_dev_attrs[] = { &driver_attr_post_reset_wdog.attr, @@ -626,7 +970,7 @@ static ssize_t mbc_bootfifo_read_raw(struct file *filp, struct kobject *kobj, } static struct bin_attribute mbc_bootfifo_sysfs_attr = { - .attr = { .name = "bootfifo", .mode = S_IRUSR }, + .attr = { .name = "bootfifo", .mode = 0400 }, .read = mbc_bootfifo_read_raw, };