Message ID | 20231024192648.25527-1-bjorn@kernel.org |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:ce89:0:b0:403:3b70:6f57 with SMTP id p9csp2159287vqx; Tue, 24 Oct 2023 12:27:17 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHLTfGcUDpvXPZpx+p23noT/R6c2AhGdADy8G20oatFEosU3JpiyMOjjge+RaszlJZHf0m0 X-Received: by 2002:a17:90b:374b:b0:27d:e1c:5347 with SMTP id ne11-20020a17090b374b00b0027d0e1c5347mr12949265pjb.11.1698175637316; Tue, 24 Oct 2023 12:27:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1698175637; cv=none; d=google.com; s=arc-20160816; b=mBa4a7TeMpUunOYjvo6ggFa0mEdY+0YhB8ixGZaF34CoqCGB1yODXfZUj7GhjnoVb2 WwNQAZ/69WAzQF3hGER6XMaoDJjUQaWuF0K168Sh1Pftd5tPXb3pILoZXTn/UDU7cOU+ quOiBZ1ofF0OmEKwzUJtqTCTuFEPj1yOsiy+b1i58pOsLTVg/ofdmHrcOvFHSH6yhI6z boKa0kC83H0HfjF39xSeyzn4gneh2rMxrqRvw/4XdYT9huUTJGEpYvNahbbuEmMqT1IO 5oBrzpziOC3m2HXZei5p0VvWc664k2LIThtJ5zBsQUhxLtf9tHTGOXMPeBnSTf+Zc7Om /svg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=yQW4VbFynynaHkom/Z17QvTxTqtw+Oss9bf3O5EJsKw=; fh=bT96g6aTNXlXwYW0egZMl07NlkDuOwvGFvBYvvt31mg=; b=aTzpTr3c2sHrdqCOl76eIt4lpCAHuWcHWyKFPO6A7mcFqwLTniqLVFT2wbfyLxwTPM OzNbiyGoAsufH/j356wmHoyrX29DDUC/7AhMQJn0m9paqAKl5/1XksZXTuBZ0nc1e9mI oNaieVYQ90UiQtLmNNDxd1rcOtzCCUQ5aWRsRnagBcH08YVVhnSN98nQZmAMYKEG2Nmn ZwQf/o9xnG6dO0qQr+AacRY60z1xKzoFp7lgYAdIy0r8bkZcU9AXv5h486GbjAe9F2VC J4AmUjblQ0S9+qi0PtweR6yTTefWGpFCHiaQkVzQpajNfB0a2Gi3Hycy/HDxoEzhA+yp hT9w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=pu5np2xi; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:1 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from morse.vger.email (morse.vger.email. [2620:137:e000::3:1]) by mx.google.com with ESMTPS id lk7-20020a17090b33c700b0026b4d5844ccsi8973039pjb.27.2023.10.24.12.27.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Oct 2023 12:27:17 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:1 as permitted sender) client-ip=2620:137:e000::3:1; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=pu5np2xi; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:1 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by morse.vger.email (Postfix) with ESMTP id 46B5B80227C2; Tue, 24 Oct 2023 12:27:14 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at morse.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344161AbjJXT1B (ORCPT <rfc822;aposhian.dev@gmail.com> + 27 others); Tue, 24 Oct 2023 15:27:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43048 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343612AbjJXT1A (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Tue, 24 Oct 2023 15:27:00 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 75BEE10C3 for <linux-kernel@vger.kernel.org>; Tue, 24 Oct 2023 12:26:57 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 73354C433C7; Tue, 24 Oct 2023 19:26:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1698175617; bh=+anck+iVi4/9AxBaPBVSONihMc3/xRqjTE3i12vRea4=; h=From:To:Cc:Subject:Date:From; b=pu5np2xifqVw00cZ9Z6nwP8ziNGZoZtGj7PA+aR0d4yzvZy/BMB0PUuBb632APfEa 1ZDWDFJBamzVFMHuii8b0pviocPYN4pumq8L7lE1N3btV7b4N5vQs+v0gZYW7rWUNI 0DNFbZput21S/Ccoh+53Z5hatA9Xp5zw+ORQRPUve9tdxmQXUvycyAkkgGU1IP9QcW 91/e5KgIkF8hDog4o8/Zw/FtyugJzHGQqMFQImtfF8frOLiHo0i3jNUbrfrJaL/DDS UfUtgR1vmE9jypMyNpN77f1zO7GT6nVKK/ziBA+69Lpb/n3kpzlTjJQd3+5wLIa1+A lZgiUIuyaqyQA== From: =?utf-8?b?QmrDtnJuIFTDtnBlbA==?= <bjorn@kernel.org> To: Albert Ou <aou@eecs.berkeley.edu>, Anup Patel <anup@brainfault.org>, Atish Patra <atishp@atishpatra.org>, Atish Patra <atishp@rivosinc.com>, Palmer Dabbelt <palmer@dabbelt.com>, Paul Walmsley <paul.walmsley@sifive.com> Cc: =?utf-8?b?QmrDtnJuIFTDtnBlbA==?= <bjorn@rivosinc.com>, Ard Biesheuvel <ardb@kernel.org>, Sunil V L <sunilvl@ventanamicro.com>, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org Subject: [PATCH] riscv: CONFIG_EFI should not depend on CONFIG_RISCV_ISA_C Date: Tue, 24 Oct 2023 21:26:48 +0200 Message-Id: <20231024192648.25527-1-bjorn@kernel.org> X-Mailer: git-send-email 2.40.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on morse.vger.email Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (morse.vger.email [0.0.0.0]); Tue, 24 Oct 2023 12:27:14 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1780666216822940197 X-GMAIL-MSGID: 1780666216822940197 |
Series |
riscv: CONFIG_EFI should not depend on CONFIG_RISCV_ISA_C
|
|
Commit Message
Björn Töpel
Oct. 24, 2023, 7:26 p.m. UTC
From: Björn Töpel <bjorn@rivosinc.com> UEFI/PE mandates that the kernel Image starts with "MZ" ASCII (0x5A4D). Convenient enough, "MZ" is a valid compressed RISC-V instruction. This means that a non-UEFI loader can simply jump to "code0" in the Image header [1] and start executing. The Image specification [1] says the following about "code0": | This header is also reused to support EFI stub for RISC-V. EFI | specification needs PE/COFF image header in the beginning of the | kernel image in order to load it as an EFI application. In order | to support EFI stub, code0 is replaced with "MZ" magic string | and res3(at offset 0x3c) points to the rest of the PE/COFF | header. "MZ" is not a valid instruction for implementations without the C extension. A non-UEFI loader, loading a non-C UEFI image have the following options: 1. Trap and emulate "code0" 2. Avoid "code0" if it is "MZ", and have the kernel entry at "code1". Replace the compressed instruction with a hex code variant, that works for CONFIG_RISCV_ISA_C=n builds. Further, this change also make sure that the "code0" instruction is 32b aligned. [1] Documentation/riscv/boot-image-header.rst Signed-off-by: Björn Töpel <bjorn@rivosinc.com> --- arch/riscv/Kconfig | 1 - arch/riscv/kernel/head.S | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) base-commit: d88520ad73b79e71e3ddf08de335b8520ae41c5c
Comments
On Tue, 24 Oct 2023 12:26:48 PDT (-0700), bjorn@kernel.org wrote: > From: Björn Töpel <bjorn@rivosinc.com> > > UEFI/PE mandates that the kernel Image starts with "MZ" ASCII > (0x5A4D). Convenient enough, "MZ" is a valid compressed RISC-V > instruction. This means that a non-UEFI loader can simply jump to > "code0" in the Image header [1] and start executing. > > The Image specification [1] says the following about "code0": > | This header is also reused to support EFI stub for RISC-V. EFI > | specification needs PE/COFF image header in the beginning of the > | kernel image in order to load it as an EFI application. In order > | to support EFI stub, code0 is replaced with "MZ" magic string > | and res3(at offset 0x3c) points to the rest of the PE/COFF > | header. > > "MZ" is not a valid instruction for implementations without the C > extension. > > A non-UEFI loader, loading a non-C UEFI image have the following > options: > 1. Trap and emulate "code0" > 2. Avoid "code0" if it is "MZ", and have the kernel entry at > "code1". > > Replace the compressed instruction with a hex code variant, that works > for CONFIG_RISCV_ISA_C=n builds. Further, this change also make sure > that the "code0" instruction is 32b aligned. IMO this breaks the Image format on non-C systems: they'll jump straight to the start (as there's no symbols left or anything) and then just fail to execute the C instructions. We could amend the Image format to require bootloaders to handle this (ie, look at the first instructions and emulate them if there's no C), that would require some bootloader updates but given this doesn't work maybe that's fine. We could also just stop producing Image+PE binaries on non-C systems (ie, just produce PE). > [1] Documentation/riscv/boot-image-header.rst > > Signed-off-by: Björn Töpel <bjorn@rivosinc.com> > --- > arch/riscv/Kconfig | 1 - > arch/riscv/kernel/head.S | 8 ++++++-- > 2 files changed, 6 insertions(+), 3 deletions(-) > > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig > index d607ab0f7c6d..9c5bbbc93951 100644 > --- a/arch/riscv/Kconfig > +++ b/arch/riscv/Kconfig > @@ -799,7 +799,6 @@ config EFI > select EFI_RUNTIME_WRAPPERS > select EFI_STUB > select LIBFDT > - select RISCV_ISA_C > select UCS2_STRING > help > This option provides support for runtime services provided > diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S > index 3710ea5d160f..33d69b569843 100644 > --- a/arch/riscv/kernel/head.S > +++ b/arch/riscv/kernel/head.S > @@ -27,9 +27,13 @@ ENTRY(_start) > */ > #ifdef CONFIG_EFI > /* > - * This instruction decodes to "MZ" ASCII required by UEFI. > + * The compressed (C extension) "c.li s4,-13" instruction > + * decodes to 0x5a4d/"MZ" (ASCII), which is required by UEFI. > + * > + * In order to support non-compressed EFI kernels, the > + * instruction is written in hex. > */ > - c.li s4,-13 > + .word 0x5a4d5a4d > j _start_kernel > #else > /* jump to start kernel */ > > base-commit: d88520ad73b79e71e3ddf08de335b8520ae41c5c
Palmer Dabbelt <palmer@dabbelt.com> writes: > On Tue, 24 Oct 2023 12:26:48 PDT (-0700), bjorn@kernel.org wrote: >> From: Björn Töpel <bjorn@rivosinc.com> >> >> UEFI/PE mandates that the kernel Image starts with "MZ" ASCII >> (0x5A4D). Convenient enough, "MZ" is a valid compressed RISC-V >> instruction. This means that a non-UEFI loader can simply jump to >> "code0" in the Image header [1] and start executing. >> >> The Image specification [1] says the following about "code0": >> | This header is also reused to support EFI stub for RISC-V. EFI >> | specification needs PE/COFF image header in the beginning of the >> | kernel image in order to load it as an EFI application. In order >> | to support EFI stub, code0 is replaced with "MZ" magic string >> | and res3(at offset 0x3c) points to the rest of the PE/COFF >> | header. >> >> "MZ" is not a valid instruction for implementations without the C >> extension. >> >> A non-UEFI loader, loading a non-C UEFI image have the following >> options: >> 1. Trap and emulate "code0" >> 2. Avoid "code0" if it is "MZ", and have the kernel entry at >> "code1". >> >> Replace the compressed instruction with a hex code variant, that works >> for CONFIG_RISCV_ISA_C=n builds. Further, this change also make sure >> that the "code0" instruction is 32b aligned. > > IMO this breaks the Image format on non-C systems: they'll jump straight > to the start (as there's no symbols left or anything) and then just fail > to execute the C instructions. That's right! My idea, which was probably really poor articulated, was to add trap/emulate in OpenSBI/non-C for the MZ instructions. > We could amend the Image format to require bootloaders to handle this > (ie, look at the first instructions and emulate them if there's no C), > that would require some bootloader updates but given this doesn't work > maybe that's fine. > > We could also just stop producing Image+PE binaries on non-C systems > (ie, just produce PE). Yes, or make the Image loader in Qemu et al more robust, by e.g. checking code0/code1. The Image spec does say that code0 is 'MZ' for PE+Image builds, and for non-C capable systems one could argue that it should be checked/skipped by the loader. Does the arguments above make sense for you? I.e.: 1. Merge this patch 2a. Add the trap/emu to OpenSBI (2b. Improve the image loader in Qemu?) Björn
Björn Töpel <bjorn@kernel.org> writes: > Palmer Dabbelt <palmer@dabbelt.com> writes: > >> On Tue, 24 Oct 2023 12:26:48 PDT (-0700), bjorn@kernel.org wrote: >>> From: Björn Töpel <bjorn@rivosinc.com> >>> >>> UEFI/PE mandates that the kernel Image starts with "MZ" ASCII >>> (0x5A4D). Convenient enough, "MZ" is a valid compressed RISC-V >>> instruction. This means that a non-UEFI loader can simply jump to >>> "code0" in the Image header [1] and start executing. >>> >>> The Image specification [1] says the following about "code0": >>> | This header is also reused to support EFI stub for RISC-V. EFI >>> | specification needs PE/COFF image header in the beginning of the >>> | kernel image in order to load it as an EFI application. In order >>> | to support EFI stub, code0 is replaced with "MZ" magic string >>> | and res3(at offset 0x3c) points to the rest of the PE/COFF >>> | header. >>> >>> "MZ" is not a valid instruction for implementations without the C >>> extension. >>> >>> A non-UEFI loader, loading a non-C UEFI image have the following >>> options: >>> 1. Trap and emulate "code0" >>> 2. Avoid "code0" if it is "MZ", and have the kernel entry at >>> "code1". >>> >>> Replace the compressed instruction with a hex code variant, that works >>> for CONFIG_RISCV_ISA_C=n builds. Further, this change also make sure >>> that the "code0" instruction is 32b aligned. >> >> IMO this breaks the Image format on non-C systems: they'll jump straight >> to the start (as there's no symbols left or anything) and then just fail >> to execute the C instructions. > > That's right! My idea, which was probably really poor articulated, was > to add trap/emulate in OpenSBI/non-C for the MZ instructions. > >> We could amend the Image format to require bootloaders to handle this >> (ie, look at the first instructions and emulate them if there's no C), >> that would require some bootloader updates but given this doesn't work >> maybe that's fine. >> >> We could also just stop producing Image+PE binaries on non-C systems >> (ie, just produce PE). > > Yes, or make the Image loader in Qemu et al more robust, by e.g. > checking code0/code1. The Image spec does say that code0 is 'MZ' for > PE+Image builds, and for non-C capable systems one could argue that it > should be checked/skipped by the loader. > > Does the arguments above make sense for you? I.e.: > 1. Merge this patch > 2a. Add the trap/emu to OpenSBI > (2b. Improve the image loader in Qemu?) FWIW, the OpenSBI patch would be something like: From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= <bjorn@rivosinc.com> Date: Wed, 8 Nov 2023 06:29:06 +0100 Subject: [PATCH] lib: sbi_illegal_insn: Emulate 'MZ'/c.li s4,-13 instruction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Linux kernel RISC-V image format allows that UEFI Images, can also be booted by non-UEFI firmware. However for that to work, the PE/Image combo requires that 'MZ' is a valid instruction. On RISC-V, 'MZ' is only a valid instruction if the hardware is C capable. Emulate "c.li s4,-13" for non-C capable hardware. Signed-off-by: Björn Töpel <bjorn@rivosinc.com> --- lib/sbi/sbi_illegal_insn.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/sbi/sbi_illegal_insn.c b/lib/sbi/sbi_illegal_insn.c index 2be47575a365..c9588e364264 100644 --- a/lib/sbi/sbi_illegal_insn.c +++ b/lib/sbi/sbi_illegal_insn.c @@ -102,6 +102,19 @@ static int system_opcode_insn(ulong insn, struct sbi_trap_regs *regs) return 0; } +static int compressed_insn(ulong insn, struct sbi_trap_regs *regs) +{ + /* Only handle 'MZ'/c.li s4,-13/0x5a3d */ + if (!misa_extension('C') && (insn & 0xffff) == 0x5a4d) { + regs->s4 = -13; + regs->mepc += 4; + + return 0; + } + + return truly_illegal_insn(insn, regs); +} + static const illegal_insn_func illegal_insn_table[32] = { truly_illegal_insn, /* 0 */ truly_illegal_insn, /* 1 */ @@ -140,6 +153,7 @@ static const illegal_insn_func illegal_insn_table[32] = { int sbi_illegal_insn_handler(ulong insn, struct sbi_trap_regs *regs) { struct sbi_trap_info uptrap; + ulong tmp; /* * We only deal with 32-bit (or longer) illegal instructions. If we @@ -159,7 +173,10 @@ int sbi_illegal_insn_handler(ulong insn, struct sbi_trap_regs *regs) uptrap.epc = regs->mepc; return sbi_trap_redirect(regs, &uptrap); } - if ((insn & 3) != 3) + tmp = insn & 3; + if (tmp == 1) + return compressed_insn(insn, regs); + else if (tmp != 3) return truly_illegal_insn(insn, regs); } base-commit: cbdd86973901b6be2a1a2d3d6b54f3184fdf9a44
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index d607ab0f7c6d..9c5bbbc93951 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -799,7 +799,6 @@ config EFI select EFI_RUNTIME_WRAPPERS select EFI_STUB select LIBFDT - select RISCV_ISA_C select UCS2_STRING help This option provides support for runtime services provided diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S index 3710ea5d160f..33d69b569843 100644 --- a/arch/riscv/kernel/head.S +++ b/arch/riscv/kernel/head.S @@ -27,9 +27,13 @@ ENTRY(_start) */ #ifdef CONFIG_EFI /* - * This instruction decodes to "MZ" ASCII required by UEFI. + * The compressed (C extension) "c.li s4,-13" instruction + * decodes to 0x5a4d/"MZ" (ASCII), which is required by UEFI. + * + * In order to support non-compressed EFI kernels, the + * instruction is written in hex. */ - c.li s4,-13 + .word 0x5a4d5a4d j _start_kernel #else /* jump to start kernel */