* [kvm-unit-tests PATCH v2 00/13] Enable EFI support
@ 2024-03-05 17:08 Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 01/13] riscv: Call abort instead of assert on unhandled exceptions Andrew Jones
` (13 more replies)
0 siblings, 14 replies; 16+ messages in thread
From: Andrew Jones @ 2024-03-05 17:08 UTC (permalink / raw)
To: kvm, kvm-riscv; +Cc: pbonzini, thuth
This series starts with some fixes for backtraces for bugs found
when tracing with riscv EFI builds. The series then brings EFI
support to riscv, basing the approach heavily on arm64's support
(including arm64's improvements[1]). It should now be possible
to launch tests from EFI-capable bootloaders.
[1] https://lore.kernel.org/all/20240305164623.379149-20-andrew.jones@linux.dev/
v2:
- Rebase on v3 of arm's efi improvement series
- Just make base_address a weak function rather than duplicate it
- Always preserve .so files (they're useful for debug)
- Build the sieve test for EFI
- Pick up a couple tags
Thanks,
drew
Andrew Jones (13):
riscv: Call abort instead of assert on unhandled exceptions
riscv: show_regs: Prepare for EFI images
treewide: lib/stack: Fix backtrace
treewide: lib/stack: Make base_address arch specific
riscv: Import gnu-efi files
riscv: Tweak the gnu-efi imported code
riscv: Enable building for EFI
riscv: efi: Switch stack in _start
efi: Add support for obtaining the boot hartid
riscv: Refactor setup code
riscv: Enable EFI boot
riscv: efi: Add run script
riscv: efi: Use efi-direct by default
configure | 12 +-
lib/arm/stack.c | 13 +--
lib/arm64/stack.c | 12 +-
lib/efi.c | 33 ++++++
lib/elf.h | 5 +
lib/riscv/asm/setup.h | 5 +
lib/riscv/processor.c | 11 +-
lib/riscv/setup.c | 170 +++++++++++++++++++++-------
lib/riscv/stack.c | 30 +++--
lib/s390x/stack.c | 12 +-
lib/stack.c | 8 +-
lib/stack.h | 24 +++-
lib/x86/stack.c | 12 +-
riscv/Makefile | 27 ++++-
riscv/cstart.S | 4 +
riscv/efi/crt0-efi-riscv64.S | 205 ++++++++++++++++++++++++++++++++++
riscv/efi/elf_riscv64_efi.lds | 142 +++++++++++++++++++++++
riscv/efi/reloc_riscv64.c | 91 +++++++++++++++
riscv/efi/run | 106 ++++++++++++++++++
riscv/flat.lds | 1 +
riscv/run | 2 +-
21 files changed, 828 insertions(+), 97 deletions(-)
create mode 100644 riscv/efi/crt0-efi-riscv64.S
create mode 100644 riscv/efi/elf_riscv64_efi.lds
create mode 100644 riscv/efi/reloc_riscv64.c
create mode 100755 riscv/efi/run
--
2.44.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [kvm-unit-tests PATCH v2 01/13] riscv: Call abort instead of assert on unhandled exceptions
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
@ 2024-03-05 17:09 ` Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 02/13] riscv: show_regs: Prepare for EFI images Andrew Jones
` (12 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2024-03-05 17:09 UTC (permalink / raw)
To: kvm, kvm-riscv; +Cc: pbonzini, thuth
We should call abort() instead of assert() on an unhandled
exception since assert() calls abort() anyway after a useless
"assert failed: 0" message. We can also skip dumping the
exception stack and just unwind from the stack frame where
the exception occurred.
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
lib/riscv/processor.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/riscv/processor.c b/lib/riscv/processor.c
index e0904209c0da..6c868b805cf7 100644
--- a/lib/riscv/processor.c
+++ b/lib/riscv/processor.c
@@ -43,7 +43,8 @@ void do_handle_exception(struct pt_regs *regs)
}
show_regs(regs);
- assert(0);
+ dump_frame_stack((void *)regs->epc, (void *)regs->s0);
+ abort();
}
void install_exception_handler(unsigned long cause, void (*handler)(struct pt_regs *))
--
2.44.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [kvm-unit-tests PATCH v2 02/13] riscv: show_regs: Prepare for EFI images
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 01/13] riscv: Call abort instead of assert on unhandled exceptions Andrew Jones
@ 2024-03-05 17:09 ` Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 03/13] treewide: lib/stack: Fix backtrace Andrew Jones
` (11 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2024-03-05 17:09 UTC (permalink / raw)
To: kvm, kvm-riscv; +Cc: pbonzini, thuth
EFI images start with a header page and then _text, so the load
address should use 'ImageBase' instead of _text. Just add the
ImageBase symbol to the non-efi build too and then change show_regs()
to use it instead. While there, add a couple convenience calculations
for the PC and return address (pre-subtract the load address from
them) in order to make it quicker for looking them up in an objdump.
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
lib/riscv/processor.c | 8 ++++----
riscv/flat.lds | 1 +
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/lib/riscv/processor.c b/lib/riscv/processor.c
index 6c868b805cf7..ece7cbffc6dd 100644
--- a/lib/riscv/processor.c
+++ b/lib/riscv/processor.c
@@ -8,20 +8,20 @@
#include <asm/processor.h>
#include <asm/setup.h>
-extern unsigned long _text;
+extern unsigned long ImageBase;
void show_regs(struct pt_regs *regs)
{
struct thread_info *info = current_thread_info();
- uintptr_t text = (uintptr_t)&_text;
+ uintptr_t loadaddr = (uintptr_t)&ImageBase;
unsigned int w = __riscv_xlen / 4;
- printf("Load address: %" PRIxPTR "\n", text);
+ printf("Load address: %" PRIxPTR "\n", loadaddr);
printf("CPU%3d : hartid=%lx\n", info->cpu, info->hartid);
printf("status : %.*lx\n", w, regs->status);
printf("cause : %.*lx\n", w, regs->cause);
printf("badaddr: %.*lx\n", w, regs->badaddr);
- printf("pc: %.*lx ra: %.*lx\n", w, regs->epc, w, regs->ra);
+ printf("pc: %.*lx (%lx) ra: %.*lx (%lx)\n", w, regs->epc, regs->epc - loadaddr, w, regs->ra, regs->ra - loadaddr);
printf("sp: %.*lx gp: %.*lx tp : %.*lx\n", w, regs->sp, w, regs->gp, w, regs->tp);
printf("a0: %.*lx a1: %.*lx a2 : %.*lx a3 : %.*lx\n", w, regs->a0, w, regs->a1, w, regs->a2, w, regs->a3);
printf("a4: %.*lx a5: %.*lx a6 : %.*lx a7 : %.*lx\n", w, regs->a4, w, regs->a5, w, regs->a6, w, regs->a7);
diff --git a/riscv/flat.lds b/riscv/flat.lds
index d4853f82ba1c..1ca501e6593b 100644
--- a/riscv/flat.lds
+++ b/riscv/flat.lds
@@ -30,6 +30,7 @@ PHDRS
SECTIONS
{
+ PROVIDE(ImageBase = .);
PROVIDE(_text = .);
.text : { *(.init) *(.text) *(.text.*) } :text
. = ALIGN(4K);
--
2.44.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [kvm-unit-tests PATCH v2 03/13] treewide: lib/stack: Fix backtrace
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 01/13] riscv: Call abort instead of assert on unhandled exceptions Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 02/13] riscv: show_regs: Prepare for EFI images Andrew Jones
@ 2024-03-05 17:09 ` Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 04/13] treewide: lib/stack: Make base_address arch specific Andrew Jones
` (10 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2024-03-05 17:09 UTC (permalink / raw)
To: kvm, kvm-riscv
Cc: pbonzini, thuth, Claudio Imbrenda, Nicholas Piggin, kvmarm,
linuxppc-dev, linux-s390, lvivier, frankja, nrb
We should never pass the result of __builtin_frame_address(0) to
another function since the compiler is within its rights to pop the
frame to which it points before making the function call, as may be
done for tail calls. Nobody has complained about backtrace(), so
likely all compilations have been inlining backtrace_frame(), not
dropping the frame on the tail call, or nobody is looking at traces.
However, for riscv, when built for EFI, it does drop the frame on the
tail call, and it was noticed. Preemptively fix backtrace() for all
architectures.
Fixes: 52266791750d ("lib: backtrace printing")
Acked-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
lib/arm/stack.c | 13 +++++--------
lib/arm64/stack.c | 12 +++++-------
lib/riscv/stack.c | 12 +++++-------
lib/s390x/stack.c | 12 +++++-------
lib/stack.h | 24 +++++++++++++++++-------
lib/x86/stack.c | 12 +++++-------
6 files changed, 42 insertions(+), 43 deletions(-)
diff --git a/lib/arm/stack.c b/lib/arm/stack.c
index 7d081be7c6d0..66d18b47ea53 100644
--- a/lib/arm/stack.c
+++ b/lib/arm/stack.c
@@ -8,13 +8,16 @@
#include <libcflat.h>
#include <stack.h>
-int backtrace_frame(const void *frame, const void **return_addrs,
- int max_depth)
+int arch_backtrace_frame(const void *frame, const void **return_addrs,
+ int max_depth, bool current_frame)
{
static int walking;
int depth;
const unsigned long *fp = (unsigned long *)frame;
+ if (current_frame)
+ fp = __builtin_frame_address(0);
+
if (walking) {
printf("RECURSIVE STACK WALK!!!\n");
return 0;
@@ -33,9 +36,3 @@ int backtrace_frame(const void *frame, const void **return_addrs,
walking = 0;
return depth;
}
-
-int backtrace(const void **return_addrs, int max_depth)
-{
- return backtrace_frame(__builtin_frame_address(0),
- return_addrs, max_depth);
-}
diff --git a/lib/arm64/stack.c b/lib/arm64/stack.c
index 82611f4b1815..f5eb57fd8892 100644
--- a/lib/arm64/stack.c
+++ b/lib/arm64/stack.c
@@ -8,7 +8,8 @@
extern char vector_stub_start, vector_stub_end;
-int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
+int arch_backtrace_frame(const void *frame, const void **return_addrs,
+ int max_depth, bool current_frame)
{
const void *fp = frame;
static bool walking;
@@ -17,6 +18,9 @@ int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
bool is_exception = false;
unsigned long addr;
+ if (current_frame)
+ fp = __builtin_frame_address(0);
+
if (walking) {
printf("RECURSIVE STACK WALK!!!\n");
return 0;
@@ -54,9 +58,3 @@ int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
walking = false;
return depth;
}
-
-int backtrace(const void **return_addrs, int max_depth)
-{
- return backtrace_frame(__builtin_frame_address(0),
- return_addrs, max_depth);
-}
diff --git a/lib/riscv/stack.c b/lib/riscv/stack.c
index 712a5478d547..d865594b9671 100644
--- a/lib/riscv/stack.c
+++ b/lib/riscv/stack.c
@@ -2,12 +2,16 @@
#include <libcflat.h>
#include <stack.h>
-int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
+int arch_backtrace_frame(const void *frame, const void **return_addrs,
+ int max_depth, bool current_frame)
{
static bool walking;
const unsigned long *fp = (unsigned long *)frame;
int depth;
+ if (current_frame)
+ fp = __builtin_frame_address(0);
+
if (walking) {
printf("RECURSIVE STACK WALK!!!\n");
return 0;
@@ -24,9 +28,3 @@ int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
walking = false;
return depth;
}
-
-int backtrace(const void **return_addrs, int max_depth)
-{
- return backtrace_frame(__builtin_frame_address(0),
- return_addrs, max_depth);
-}
diff --git a/lib/s390x/stack.c b/lib/s390x/stack.c
index 9f234a12adf6..d194f654e94d 100644
--- a/lib/s390x/stack.c
+++ b/lib/s390x/stack.c
@@ -14,11 +14,15 @@
#include <stack.h>
#include <asm/arch_def.h>
-int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
+int arch_backtrace_frame(const void *frame, const void **return_addrs,
+ int max_depth, bool current_frame)
{
int depth = 0;
struct stack_frame *stack = (struct stack_frame *)frame;
+ if (current_frame)
+ stack = __builtin_frame_address(0);
+
for (depth = 0; stack && depth < max_depth; depth++) {
return_addrs[depth] = (void *)stack->grs[8];
stack = stack->back_chain;
@@ -28,9 +32,3 @@ int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
return depth;
}
-
-int backtrace(const void **return_addrs, int max_depth)
-{
- return backtrace_frame(__builtin_frame_address(0),
- return_addrs, max_depth);
-}
diff --git a/lib/stack.h b/lib/stack.h
index 10fc2f793354..6edc84344b51 100644
--- a/lib/stack.h
+++ b/lib/stack.h
@@ -11,17 +11,27 @@
#include <asm/stack.h>
#ifdef HAVE_ARCH_BACKTRACE_FRAME
-extern int backtrace_frame(const void *frame, const void **return_addrs,
- int max_depth);
+extern int arch_backtrace_frame(const void *frame, const void **return_addrs,
+ int max_depth, bool current_frame);
+
+static inline int backtrace_frame(const void *frame, const void **return_addrs,
+ int max_depth)
+{
+ return arch_backtrace_frame(frame, return_addrs, max_depth, false);
+}
+
+static inline int backtrace(const void **return_addrs, int max_depth)
+{
+ return arch_backtrace_frame(NULL, return_addrs, max_depth, true);
+}
#else
-static inline int
-backtrace_frame(const void *frame __unused, const void **return_addrs __unused,
- int max_depth __unused)
+extern int backtrace(const void **return_addrs, int max_depth);
+
+static inline int backtrace_frame(const void *frame, const void **return_addrs,
+ int max_depth)
{
return 0;
}
#endif
-extern int backtrace(const void **return_addrs, int max_depth);
-
#endif
diff --git a/lib/x86/stack.c b/lib/x86/stack.c
index 5ecd97ce90b9..58ab6c4b293a 100644
--- a/lib/x86/stack.c
+++ b/lib/x86/stack.c
@@ -1,12 +1,16 @@
#include <libcflat.h>
#include <stack.h>
-int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
+int arch_backtrace_frame(const void *frame, const void **return_addrs,
+ int max_depth, bool current_frame)
{
static int walking;
int depth = 0;
const unsigned long *bp = (unsigned long *) frame;
+ if (current_frame)
+ bp = __builtin_frame_address(0);
+
if (walking) {
printf("RECURSIVE STACK WALK!!!\n");
return 0;
@@ -23,9 +27,3 @@ int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
walking = 0;
return depth;
}
-
-int backtrace(const void **return_addrs, int max_depth)
-{
- return backtrace_frame(__builtin_frame_address(0), return_addrs,
- max_depth);
-}
--
2.44.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [kvm-unit-tests PATCH v2 04/13] treewide: lib/stack: Make base_address arch specific
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
` (2 preceding siblings ...)
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 03/13] treewide: lib/stack: Fix backtrace Andrew Jones
@ 2024-03-05 17:09 ` Andrew Jones
2024-03-12 5:45 ` Nicholas Piggin
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 05/13] riscv: Import gnu-efi files Andrew Jones
` (9 subsequent siblings)
13 siblings, 1 reply; 16+ messages in thread
From: Andrew Jones @ 2024-03-05 17:09 UTC (permalink / raw)
To: kvm, kvm-riscv
Cc: pbonzini, thuth, kvmarm, linuxppc-dev, linux-s390, lvivier,
npiggin, frankja, imbrenda, nrb
Calculating the offset of an address is image specific, which is
architecture specific. Until now, all architectures and architecture
configurations which select CONFIG_RELOC were able to subtract
_etext, but the EFI configuration of riscv cannot (it must subtract
ImageBase). Make this function weak, such that an architecture may
override it when necessary, to accommodate the image layout. Then,
immediately supply the riscv override.
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
lib/riscv/stack.c | 18 ++++++++++++++++++
lib/stack.c | 8 ++++----
lib/stack.h | 2 ++
3 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/lib/riscv/stack.c b/lib/riscv/stack.c
index d865594b9671..2cd7f012738b 100644
--- a/lib/riscv/stack.c
+++ b/lib/riscv/stack.c
@@ -2,6 +2,24 @@
#include <libcflat.h>
#include <stack.h>
+#ifdef CONFIG_RELOC
+extern char ImageBase, _text, _etext;
+
+bool arch_base_address(const void *rebased_addr, unsigned long *addr)
+{
+ unsigned long ra = (unsigned long)rebased_addr;
+ unsigned long base = (unsigned long)&ImageBase;
+ unsigned long start = (unsigned long)&_text;
+ unsigned long end = (unsigned long)&_etext;
+
+ if (ra < start || ra >= end)
+ return false;
+
+ *addr = ra - base;
+ return true;
+}
+#endif
+
int arch_backtrace_frame(const void *frame, const void **return_addrs,
int max_depth, bool current_frame)
{
diff --git a/lib/stack.c b/lib/stack.c
index dd6bfa8dac6e..086fec544a81 100644
--- a/lib/stack.c
+++ b/lib/stack.c
@@ -14,7 +14,7 @@
#ifdef CONFIG_RELOC
extern char _text, _etext;
-static bool base_address(const void *rebased_addr, unsigned long *addr)
+bool __attribute__((weak)) arch_base_address(const void *rebased_addr, unsigned long *addr)
{
unsigned long ra = (unsigned long)rebased_addr;
unsigned long start = (unsigned long)&_text;
@@ -27,7 +27,7 @@ static bool base_address(const void *rebased_addr, unsigned long *addr)
return true;
}
#else
-static bool base_address(const void *rebased_addr, unsigned long *addr)
+bool __attribute__((weak)) arch_base_address(const void *rebased_addr, unsigned long *addr)
{
*addr = (unsigned long)rebased_addr;
return true;
@@ -45,13 +45,13 @@ static void print_stack(const void **return_addrs, int depth,
/* @addr indicates a non-return address, as expected by the stack
* pretty printer script. */
if (depth > 0 && !top_is_return_address) {
- if (base_address(return_addrs[0], &addr))
+ if (arch_base_address(return_addrs[0], &addr))
printf(" @%lx", addr);
i++;
}
for (; i < depth; i++) {
- if (base_address(return_addrs[i], &addr))
+ if (arch_base_address(return_addrs[i], &addr))
printf(" %lx", addr);
}
printf("\n");
diff --git a/lib/stack.h b/lib/stack.h
index 6edc84344b51..df076d94bf8f 100644
--- a/lib/stack.h
+++ b/lib/stack.h
@@ -34,4 +34,6 @@ static inline int backtrace_frame(const void *frame, const void **return_addrs,
}
#endif
+bool __attribute__((weak)) arch_base_address(const void *rebased_addr, unsigned long *addr);
+
#endif
--
2.44.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [kvm-unit-tests PATCH v2 05/13] riscv: Import gnu-efi files
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
` (3 preceding siblings ...)
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 04/13] treewide: lib/stack: Make base_address arch specific Andrew Jones
@ 2024-03-05 17:09 ` Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 06/13] riscv: Tweak the gnu-efi imported code Andrew Jones
` (8 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2024-03-05 17:09 UTC (permalink / raw)
To: kvm, kvm-riscv; +Cc: pbonzini, thuth
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
riscv/efi/crt0-efi-riscv64.S | 187 ++++++++++++++++++++++++++++++++++
riscv/efi/elf_riscv64_efi.lds | 142 ++++++++++++++++++++++++++
riscv/efi/reloc_riscv64.c | 90 ++++++++++++++++
3 files changed, 419 insertions(+)
create mode 100644 riscv/efi/crt0-efi-riscv64.S
create mode 100644 riscv/efi/elf_riscv64_efi.lds
create mode 100644 riscv/efi/reloc_riscv64.c
diff --git a/riscv/efi/crt0-efi-riscv64.S b/riscv/efi/crt0-efi-riscv64.S
new file mode 100644
index 000000000000..712ed03fc06e
--- /dev/null
+++ b/riscv/efi/crt0-efi-riscv64.S
@@ -0,0 +1,187 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */
+/*
+ * Copright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ * Copright (C) 2018 Alexander Graf <agraf@suse.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice and this list of conditions, without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef EFI_SUBSYSTEM
+#define EFI_SUBSYSTEM 10
+#endif
+
+ .section .text.head
+
+ /*
+ * Magic "MZ" signature for PE/COFF
+ */
+ .globl ImageBase
+ImageBase:
+ .ascii "MZ"
+ .skip 58 // 'MZ' + pad + offset == 64
+ .4byte pe_header - ImageBase // Offset to the PE header.
+pe_header:
+ .ascii "PE"
+ .2byte 0
+coff_header:
+ .2byte 0x5064 // riscv64
+ .2byte 4 // nr_sections
+ .4byte 0 // TimeDateStamp
+ .4byte 0 // PointerToSymbolTable
+ .4byte 0 // NumberOfSymbols
+ .2byte section_table - optional_header // SizeOfOptionalHeader
+ .2byte 0x206 // Characteristics.
+ // IMAGE_FILE_DEBUG_STRIPPED |
+ // IMAGE_FILE_EXECUTABLE_IMAGE |
+ // IMAGE_FILE_LINE_NUMS_STRIPPED
+optional_header:
+ .2byte 0x20b // PE32+ format
+ .byte 0x02 // MajorLinkerVersion
+ .byte 0x14 // MinorLinkerVersion
+ .4byte _text_size - ImageBase // SizeOfCode
+ .4byte _alldata_size - ImageBase // SizeOfInitializedData
+ .4byte 0 // SizeOfUninitializedData
+ .4byte _start - ImageBase // AddressOfEntryPoint
+ .4byte _text - ImageBase // BaseOfCode
+
+extra_header_fields:
+ .8byte 0 // ImageBase
+ .4byte 0x1000 // SectionAlignment
+ .4byte 0x1000 // FileAlignment
+ .2byte 0 // MajorOperatingSystemVersion
+ .2byte 0 // MinorOperatingSystemVersion
+ .2byte 0 // MajorImageVersion
+ .2byte 0 // MinorImageVersion
+ .2byte 0 // MajorSubsystemVersion
+ .2byte 0 // MinorSubsystemVersion
+ .4byte 0 // Win32VersionValue
+
+ .4byte _image_end - ImageBase // SizeOfImage
+
+ // Everything before the kernel image is considered part of the header
+ .4byte _text - ImageBase // SizeOfHeaders
+ .4byte 0 // CheckSum
+ .2byte EFI_SUBSYSTEM // Subsystem
+ .2byte 0 // DllCharacteristics
+ .8byte 0 // SizeOfStackReserve
+ .8byte 0 // SizeOfStackCommit
+ .8byte 0 // SizeOfHeapReserve
+ .8byte 0 // SizeOfHeapCommit
+ .4byte 0 // LoaderFlags
+ .4byte 0x10 // NumberOfRvaAndSizes
+
+ .8byte 0 // ExportTable
+ .8byte 0 // ImportTable
+ .8byte 0 // ResourceTable
+ .8byte 0 // ExceptionTable
+ .8byte 0 // CertificationTable
+ .4byte _reloc - ImageBase // BaseRelocationTable (VirtualAddress)
+ .4byte _reloc_vsize - ImageBase // BaseRelocationTable (Size)
+ .8byte 0 // Debug
+ .8byte 0 // Architecture
+ .8byte 0 // Global Ptr
+ .8byte 0 // TLS Table
+ .8byte 0 // Load Config Table
+ .8byte 0 // Bound Import
+ .8byte 0 // IAT
+ .8byte 0 // Delay Import Descriptor
+ .8byte 0 // CLR Runtime Header
+ .8byte 0 // Reserved, must be zero
+
+ // Section table
+section_table:
+
+ .ascii ".text\0\0\0"
+ .4byte _text_vsize - ImageBase // VirtualSize
+ .4byte _text - ImageBase // VirtualAddress
+ .4byte _text_size - ImageBase // SizeOfRawData
+ .4byte _text - ImageBase // PointerToRawData
+ .4byte 0 // PointerToRelocations (0 for executables)
+ .4byte 0 // PointerToLineNumbers (0 for executables)
+ .2byte 0 // NumberOfRelocations (0 for executables)
+ .2byte 0 // NumberOfLineNumbers (0 for executables)
+ .4byte 0x60000020 // Characteristics (section flags)
+
+ /*
+ * The EFI application loader requires a relocation section
+ * because EFI applications must be relocatable. This is a
+ * dummy section as far as we are concerned.
+ */
+ .ascii ".reloc\0\0"
+ .4byte _reloc_vsize - ImageBase // VirtualSize
+ .4byte _reloc - ImageBase // VirtualAddress
+ .4byte _reloc_size - ImageBase // SizeOfRawData
+ .4byte _reloc - ImageBase // PointerToRawData
+ .4byte 0 // PointerToRelocations
+ .4byte 0 // PointerToLineNumbers
+ .2byte 0 // NumberOfRelocations
+ .2byte 0 // NumberOfLineNumbers
+ .4byte 0x42000040 // Characteristics (section flags)
+
+ .ascii ".data\0\0\0"
+ .4byte _data_vsize - ImageBase // VirtualSize
+ .4byte _data - ImageBase // VirtualAddress
+ .4byte _data_size - ImageBase // SizeOfRawData
+ .4byte _data - ImageBase // PointerToRawData
+ .4byte 0 // PointerToRelocations
+ .4byte 0 // PointerToLineNumbers
+ .2byte 0 // NumberOfRelocations
+ .2byte 0 // NumberOfLineNumbers
+ .4byte 0xC0000040 // Characteristics (section flags)
+
+ .ascii ".rodata\0"
+ .4byte _rodata_vsize - ImageBase // VirtualSize
+ .4byte _rodata - ImageBase // VirtualAddress
+ .4byte _rodata_size - ImageBase // SizeOfRawData
+ .4byte _rodata - ImageBase // PointerToRawData
+ .4byte 0 // PointerToRelocations
+ .4byte 0 // PointerToLineNumbers
+ .2byte 0 // NumberOfRelocations
+ .2byte 0 // NumberOfLineNumbers
+ .4byte 0x40000040 // Characteristics (section flags)
+
+ .text
+ .globl _start
+ .type _start,%function
+_start:
+ addi sp, sp, -24
+ sd a0, 0(sp)
+ sd a1, 8(sp)
+ sd ra, 16(sp)
+ lla a0, ImageBase
+ lla a1, _DYNAMIC
+ call _relocate
+ bne a0, zero, 0f
+ ld a1, 8(sp)
+ ld a0, 0(sp)
+ call _entry
+ ld ra, 16(sp)
+0: addi sp, sp, 24
+ ret
+
+// hand-craft a dummy .reloc section so EFI knows it's a relocatable executable:
+
+ .data
+dummy: .4byte 0
+
+#define IMAGE_REL_ABSOLUTE 0
+ .section .reloc, "a"
+label1:
+ .4byte dummy-label1 // Page RVA
+ .4byte 12 // Block Size (2*4+2*2), must be aligned by 32 Bits
+ .2byte (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy
+ .2byte (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy
+
+#if defined(__ELF__) && defined(__linux__)
+ .section .note.GNU-stack,"",%progbits
+#endif
diff --git a/riscv/efi/elf_riscv64_efi.lds b/riscv/efi/elf_riscv64_efi.lds
new file mode 100644
index 000000000000..ac7055a5619b
--- /dev/null
+++ b/riscv/efi/elf_riscv64_efi.lds
@@ -0,0 +1,142 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */
+
+OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv")
+OUTPUT_ARCH(riscv)
+ENTRY(_start)
+SECTIONS
+{
+ .text 0 : {
+ *(.text.head)
+ . = ALIGN(4096);
+ _text = .;
+ *(.text)
+ *(.text.*)
+ *(.gnu.linkonce.t.*)
+ *(.plt)
+ . = ALIGN(16);
+ _evtext = .;
+ . = ALIGN(4096);
+ _etext = .;
+ } =0
+ _text_vsize = _evtext - _text;
+ _text_size = _etext - _text;
+ . = ALIGN(4096);
+ _reloc = .;
+ .reloc : {
+ *(.reloc)
+ _evreloc = .;
+ . = ALIGN(4096);
+ _ereloc = .;
+ } =0
+ _reloc_vsize = _evreloc - _reloc;
+ _reloc_size = _ereloc - _reloc;
+ . = ALIGN(4096);
+ _data = .;
+ .dynamic : { *(.dynamic) }
+ . = ALIGN(4096);
+ .data :
+ {
+ *(.sdata)
+ *(.data)
+ *(.data1)
+ *(.data.*)
+ *(.got.plt)
+ *(.got)
+
+ /*
+ * Note that these aren't the using the GNU "CONSTRUCTOR" output section
+ * command, so they don't start with a size. Because of p2align and the
+ * end/END definitions, and the fact that they're mergeable, they can also
+ * have NULLs which aren't guaranteed to be at the end.
+ */
+ . = ALIGN(16);
+ __init_array_start = .;
+ *(SORT(.init_array.*))
+ *(.init_array)
+ __init_array_end = .;
+ . = ALIGN(16);
+ __CTOR_LIST__ = .;
+ *(SORT(.ctors.*))
+ *(.ctors)
+ __CTOR_END__ = .;
+ . = ALIGN(16);
+ __DTOR_LIST__ = .;
+ *(SORT(.dtors.*))
+ *(.dtors)
+ __DTOR_END__ = .;
+ . = ALIGN(16);
+ __fini_array_start = .;
+ *(SORT(.fini_array.*))
+ *(.fini_array)
+ __fini_array_end = .;
+
+ /* the EFI loader doesn't seem to like a .bss section, so we stick
+ it all into .data: */
+ . = ALIGN(16);
+ _bss = .;
+ *(.sbss)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ . = ALIGN(16);
+ _bss_end = .;
+ _evdata = .;
+ . = ALIGN(4096);
+ _edata = .;
+ } =0
+ _data_vsize = _evdata - _data;
+ _data_size = _edata - _data;
+
+ . = ALIGN(4096);
+ _rodata = .;
+ .rela :
+ {
+ *(.rela.text*)
+ *(.rela.data*)
+ *(.rela.got)
+ *(.rela.dyn)
+ *(.rela.stab)
+ *(.rela.init_array*)
+ *(.rela.fini_array*)
+ *(.rela.ctors*)
+ *(.rela.dtors*)
+
+ }
+ . = ALIGN(4096);
+ .rela.plt : { *(.rela.plt) }
+ . = ALIGN(4096);
+ .rodata : {
+ *(.rodata*)
+ _evrodata = .;
+ . = ALIGN(4096);
+ _erodata = .;
+ } =0
+ _rodata_vsize = _evrodata - _rodata;
+ _rodata_size = _erodata - _rodata;
+ _image_end = .;
+ _alldata_size = _image_end - _reloc;
+
+ . = ALIGN(4096);
+ .dynsym : { *(.dynsym) }
+ . = ALIGN(4096);
+ .dynstr : { *(.dynstr) }
+ . = ALIGN(4096);
+ .note.gnu.build-id : { *(.note.gnu.build-id) }
+ . = ALIGN(4096);
+ .hash : { *(.hash) }
+ . = ALIGN(4096);
+ .gnu.hash : { *(.gnu.hash) }
+ . = ALIGN(4096);
+ .eh_frame : { *(.eh_frame) }
+ . = ALIGN(4096);
+ .gcc_except_table : { *(.gcc_except_table*) }
+ /DISCARD/ :
+ {
+ *(.rela.reloc)
+ *(.note.GNU-stack)
+ }
+ .comment 0 : { *(.comment) }
+}
+
diff --git a/riscv/efi/reloc_riscv64.c b/riscv/efi/reloc_riscv64.c
new file mode 100644
index 000000000000..e4296026e2a4
--- /dev/null
+++ b/riscv/efi/reloc_riscv64.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/* reloc_riscv.c - position independent ELF shared object relocator
+ Copyright (C) 2018 Alexander Graf <agraf@suse.de>
+ Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ Copyright (C) 1999 Hewlett-Packard Co.
+ Contributed by David Mosberger <davidm@hpl.hp.com>.
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of Hewlett-Packard Co. nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+*/
+
+#include <efi.h>
+
+#include <elf.h>
+
+#define Elf_Dyn Elf64_Dyn
+#define Elf_Rela Elf64_Rela
+#define ELF_R_TYPE ELF64_R_TYPE
+
+EFI_STATUS EFIAPI _relocate(long ldbase, Elf_Dyn *dyn)
+{
+ long relsz = 0, relent = 0;
+ Elf_Rela *rel = NULL;
+ unsigned long *addr;
+ int i;
+
+ for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
+ switch (dyn[i].d_tag) {
+ case DT_RELA:
+ rel = (Elf_Rela *)((unsigned long)dyn[i].d_un.d_ptr + ldbase);
+ break;
+ case DT_RELASZ:
+ relsz = dyn[i].d_un.d_val;
+ break;
+ case DT_RELAENT:
+ relent = dyn[i].d_un.d_val;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!rel && relent == 0)
+ return EFI_SUCCESS;
+
+ if (!rel || relent == 0)
+ return EFI_LOAD_ERROR;
+
+ while (relsz > 0) {
+ /* apply the relocs */
+ switch (ELF_R_TYPE(rel->r_info)) {
+ case R_RISCV_RELATIVE:
+ addr = (unsigned long *)(ldbase + rel->r_offset);
+ *addr = ldbase + rel->r_addend;
+ break;
+ default:
+ break;
+ }
+ rel = (Elf_Rela *)((char *)rel + relent);
+ relsz -= relent;
+ }
+ return EFI_SUCCESS;
+}
--
2.44.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [kvm-unit-tests PATCH v2 06/13] riscv: Tweak the gnu-efi imported code
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
` (4 preceding siblings ...)
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 05/13] riscv: Import gnu-efi files Andrew Jones
@ 2024-03-05 17:09 ` Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 07/13] riscv: Enable building for EFI Andrew Jones
` (7 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2024-03-05 17:09 UTC (permalink / raw)
To: kvm, kvm-riscv; +Cc: pbonzini, thuth
Change _relocate to match the prototype in efi.h (it doesn't
matter that 'handle' and 'sys_tab' are unused). Also add
R_RISCV_RELATIVE to efi.h and replace '_entry' with 'efi_main'.
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
lib/elf.h | 5 +++++
riscv/efi/crt0-efi-riscv64.S | 2 +-
riscv/efi/reloc_riscv64.c | 3 ++-
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/lib/elf.h b/lib/elf.h
index 7a7db57774cd..fee20289e1fc 100644
--- a/lib/elf.h
+++ b/lib/elf.h
@@ -65,4 +65,9 @@ typedef struct elf64_rela {
/* The following are used with relocations */
#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
+/*
+ * riscv static relocation types.
+ */
+#define R_RISCV_RELATIVE 3
+
#endif /* _ELF_H_ */
diff --git a/riscv/efi/crt0-efi-riscv64.S b/riscv/efi/crt0-efi-riscv64.S
index 712ed03fc06e..cc8551a43c6a 100644
--- a/riscv/efi/crt0-efi-riscv64.S
+++ b/riscv/efi/crt0-efi-riscv64.S
@@ -164,7 +164,7 @@ _start:
bne a0, zero, 0f
ld a1, 8(sp)
ld a0, 0(sp)
- call _entry
+ call efi_main
ld ra, 16(sp)
0: addi sp, sp, 24
ret
diff --git a/riscv/efi/reloc_riscv64.c b/riscv/efi/reloc_riscv64.c
index e4296026e2a4..8504ad595e51 100644
--- a/riscv/efi/reloc_riscv64.c
+++ b/riscv/efi/reloc_riscv64.c
@@ -44,7 +44,8 @@
#define Elf_Rela Elf64_Rela
#define ELF_R_TYPE ELF64_R_TYPE
-EFI_STATUS EFIAPI _relocate(long ldbase, Elf_Dyn *dyn)
+efi_status_t _relocate(long ldbase, Elf64_Dyn *dyn, efi_handle_t handle,
+ efi_system_table_t *sys_tab)
{
long relsz = 0, relent = 0;
Elf_Rela *rel = NULL;
--
2.44.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [kvm-unit-tests PATCH v2 07/13] riscv: Enable building for EFI
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
` (5 preceding siblings ...)
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 06/13] riscv: Tweak the gnu-efi imported code Andrew Jones
@ 2024-03-05 17:09 ` Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 08/13] riscv: efi: Switch stack in _start Andrew Jones
` (6 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2024-03-05 17:09 UTC (permalink / raw)
To: kvm, kvm-riscv; +Cc: pbonzini, thuth
Mimicking arm64 support, add configure and makefile changes to build
for EFI. Since the linker script is replaced also replace the initial
cstart code (also done like arm64). Finally, provide a stub for
setup_efi() in order to allow compiling to complete (even though
tests can't yet run).
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
configure | 3 ++-
lib/riscv/asm/setup.h | 5 +++++
riscv/Makefile | 27 +++++++++++++++++++++++++--
riscv/cstart.S | 4 ++++
4 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/configure b/configure
index 51edee8cd21b..c1d0fe4adbb0 100755
--- a/configure
+++ b/configure
@@ -231,7 +231,8 @@ else
fi
fi
-if [ "$efi" ] && [ "$arch" != "x86_64" ] && [ "$arch" != "arm64" ]; then
+if [ "$efi" ] && [ "$arch" != "x86_64" ] &&
+ [ "$arch" != "arm64" ] && [ "$arch" != "riscv64" ]; then
echo "--[enable|disable]-efi is not supported for $arch"
usage
fi
diff --git a/lib/riscv/asm/setup.h b/lib/riscv/asm/setup.h
index e58dd53071ae..dfc8875fbb3b 100644
--- a/lib/riscv/asm/setup.h
+++ b/lib/riscv/asm/setup.h
@@ -12,4 +12,9 @@ int hartid_to_cpu(unsigned long hartid);
void io_init(void);
void setup(const void *fdt, phys_addr_t freemem_start);
+#ifdef CONFIG_EFI
+#include <efi.h>
+static inline efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo) { return 0; }
+#endif
+
#endif /* _ASMRISCV_SETUP_H_ */
diff --git a/riscv/Makefile b/riscv/Makefile
index 85bbca151739..919a3ebb5211 100644
--- a/riscv/Makefile
+++ b/riscv/Makefile
@@ -17,7 +17,8 @@ tests += $(TEST_DIR)/sieve.$(exe)
all: $(tests)
-$(TEST_DIR)/sieve.elf: AUXFLAGS = 0x1
+# When built for EFI sieve needs extra memory, run with e.g. '-m 256' on QEMU
+$(TEST_DIR)/sieve.$(exe): AUXFLAGS = 0x1
cstart.o = $(TEST_DIR)/cstart.o
@@ -85,7 +86,29 @@ include $(SRCDIR)/scripts/asm-offsets.mak
-DPROGNAME=\"$(notdir $(@:.aux.o=.$(exe)))\" -DAUXFLAGS=$(AUXFLAGS)
ifeq ($(CONFIG_EFI),y)
- # TODO
+# avoid jump tables before all relocations have been processed
+riscv/efi/reloc_riscv64.o: CFLAGS += -fno-jump-tables
+cflatobjs += riscv/efi/reloc_riscv64.o
+cflatobjs += lib/acpi.o
+cflatobjs += lib/efi.o
+
+.PRECIOUS: %.so
+
+%.so: EFI_LDFLAGS += -defsym=EFI_SUBSYSTEM=0xa --no-undefined
+%.so: %.o $(FLATLIBS) $(SRCDIR)/riscv/efi/elf_riscv64_efi.lds $(cstart.o) %.aux.o
+ $(LD) $(EFI_LDFLAGS) -o $@ -T $(SRCDIR)/riscv/efi/elf_riscv64_efi.lds \
+ $(filter %.o, $^) $(FLATLIBS) $(EFI_LIBS)
+
+%.efi: %.so
+ $(call arch_elf_check, $^)
+ $(OBJCOPY) --only-keep-debug $^ $@.debug
+ $(OBJCOPY) --strip-debug $^
+ $(OBJCOPY) --add-gnu-debuglink=$@.debug $^
+ $(OBJCOPY) \
+ -j .text -j .sdata -j .data -j .rodata -j .dynamic -j .dynsym \
+ -j .rel -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* \
+ -j .reloc \
+ -O binary $^ $@
else
%.elf: LDFLAGS += -pie -n -z notext
%.elf: %.o $(FLATLIBS) $(SRCDIR)/riscv/flat.lds $(cstart.o) %.aux.o
diff --git a/riscv/cstart.S b/riscv/cstart.S
index c935467ff6a1..10b5da5779b0 100644
--- a/riscv/cstart.S
+++ b/riscv/cstart.S
@@ -42,6 +42,9 @@
9997:
.endm
+#ifdef CONFIG_EFI
+#include "efi/crt0-efi-riscv64.S"
+#else
.section .init
/*
@@ -109,6 +112,7 @@ start:
call exit
j halt
+#endif /* !CONFIG_EFI */
.text
.balign 4
--
2.44.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [kvm-unit-tests PATCH v2 08/13] riscv: efi: Switch stack in _start
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
` (6 preceding siblings ...)
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 07/13] riscv: Enable building for EFI Andrew Jones
@ 2024-03-05 17:09 ` Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 09/13] efi: Add support for obtaining the boot hartid Andrew Jones
` (5 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2024-03-05 17:09 UTC (permalink / raw)
To: kvm, kvm-riscv; +Cc: pbonzini, thuth
Modify gnu-efi's _start to switch the stack. This allows us to not
map memory regions which have EFI memory type EFI_BOOT_SERVICES_DATA,
as the stack will be in the EFI_LOADER_CODE region instead. We'll
still map the stack as R/W instead of R/X because we'll split the
EFI_LOADER_CODE region on the _etext boundary and map addresses
before _etext as R/X and the rest as R/W.
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
riscv/efi/crt0-efi-riscv64.S | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/riscv/efi/crt0-efi-riscv64.S b/riscv/efi/crt0-efi-riscv64.S
index cc8551a43c6a..4ed82b14a1d6 100644
--- a/riscv/efi/crt0-efi-riscv64.S
+++ b/riscv/efi/crt0-efi-riscv64.S
@@ -164,7 +164,20 @@ _start:
bne a0, zero, 0f
ld a1, 8(sp)
ld a0, 0(sp)
+
+ /* Switch to our own stack */
+ mv a2, sp
+ la sp, stacktop
+ mv fp, zero
+ push_fp zero
+ addi sp, sp, -16
+ sd a2, 0(sp)
+
call efi_main
+
+ /* Restore sp */
+ ld sp, 0(sp)
+
ld ra, 16(sp)
0: addi sp, sp, 24
ret
@@ -172,6 +185,11 @@ _start:
// hand-craft a dummy .reloc section so EFI knows it's a relocatable executable:
.data
+
+.balign 16384
+.space 16384
+stacktop:
+
dummy: .4byte 0
#define IMAGE_REL_ABSOLUTE 0
--
2.44.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [kvm-unit-tests PATCH v2 09/13] efi: Add support for obtaining the boot hartid
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
` (7 preceding siblings ...)
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 08/13] riscv: efi: Switch stack in _start Andrew Jones
@ 2024-03-05 17:09 ` Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 10/13] riscv: Refactor setup code Andrew Jones
` (4 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2024-03-05 17:09 UTC (permalink / raw)
To: kvm, kvm-riscv; +Cc: pbonzini, thuth
riscv needs to use an EFI protocol to get the boot hartid.
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
lib/efi.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/lib/efi.c b/lib/efi.c
index 12c66c6ffd1f..5314eaa81e66 100644
--- a/lib/efi.c
+++ b/lib/efi.c
@@ -29,6 +29,31 @@ extern int main(int argc, char **argv, char **envp);
efi_system_table_t *efi_system_table = NULL;
+#ifdef __riscv
+#define RISCV_EFI_BOOT_PROTOCOL_GUID EFI_GUID(0xccd15fec, 0x6f73, 0x4eec, 0x83, 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf)
+
+unsigned long boot_hartid;
+
+struct riscv_efi_boot_protocol {
+ u64 revision;
+ efi_status_t (*get_boot_hartid)(struct riscv_efi_boot_protocol *,
+ unsigned long *boot_hartid);
+};
+
+static efi_status_t efi_get_boot_hartid(void)
+{
+ efi_guid_t boot_protocol_guid = RISCV_EFI_BOOT_PROTOCOL_GUID;
+ struct riscv_efi_boot_protocol *boot_protocol;
+ efi_status_t status;
+
+ status = efi_bs_call(locate_protocol, &boot_protocol_guid, NULL,
+ (void **)&boot_protocol);
+ if (status != EFI_SUCCESS)
+ return status;
+ return efi_call_proto(boot_protocol, get_boot_hartid, &boot_hartid);
+}
+#endif
+
static void efi_free_pool(void *ptr)
{
efi_bs_call(free_pool, ptr);
@@ -421,6 +446,14 @@ efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab)
goto efi_main_error;
}
+#ifdef __riscv
+ status = efi_get_boot_hartid();
+ if (status != EFI_SUCCESS) {
+ printf("Failed to get boot haritd\n");
+ goto efi_main_error;
+ }
+#endif
+
/*
* Exit EFI boot services, let kvm-unit-tests take full control of the
* guest
--
2.44.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [kvm-unit-tests PATCH v2 10/13] riscv: Refactor setup code
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
` (8 preceding siblings ...)
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 09/13] efi: Add support for obtaining the boot hartid Andrew Jones
@ 2024-03-05 17:09 ` Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 11/13] riscv: Enable EFI boot Andrew Jones
` (3 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2024-03-05 17:09 UTC (permalink / raw)
To: kvm, kvm-riscv; +Cc: pbonzini, thuth
To prepare for EFI setup, move code that will be shared into
functions. This is the same type of code and the exact same function
names which were created when refactoring Arm's EFI setup, so riscv
setup is still following Arm's setup patterns.
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
lib/riscv/setup.c | 109 +++++++++++++++++++++++++++++-----------------
1 file changed, 68 insertions(+), 41 deletions(-)
diff --git a/lib/riscv/setup.c b/lib/riscv/setup.c
index 40ff26a24cfc..f721d81192ac 100644
--- a/lib/riscv/setup.c
+++ b/lib/riscv/setup.c
@@ -31,6 +31,8 @@
#define MAX_DT_MEM_REGIONS 16
#define NR_MEM_REGIONS (MAX_DT_MEM_REGIONS + 16)
+extern unsigned long _etext;
+
char *initrd;
u32 initrd_size;
@@ -81,25 +83,12 @@ static void cpu_init(void)
cpu0_calls_idle = true;
}
-extern unsigned long _etext;
-
-static void mem_init(phys_addr_t freemem_start)
+static void mem_allocator_init(phys_addr_t freemem_start, phys_addr_t freemem_end)
{
- struct mem_region *freemem, *code, *data;
- phys_addr_t freemem_end, base, top;
-
- memregions_init(riscv_mem_regions, NR_MEM_REGIONS);
- memregions_add_dt_regions(MAX_DT_MEM_REGIONS);
+ phys_addr_t base, top;
- /* Split the region with the code into two regions; code and data */
- memregions_split((unsigned long)&_etext, &code, &data);
- assert(code);
- code->flags |= MR_F_CODE;
-
- freemem = memregions_find(freemem_start);
- assert(freemem && !(freemem->flags & (MR_F_IO | MR_F_CODE)));
-
- freemem_end = freemem->end & PAGE_MASK;
+ freemem_start = PAGE_ALIGN(freemem_start);
+ freemem_end &= PAGE_MASK;
/*
* The assert below is mostly checking that the free memory doesn't
@@ -129,6 +118,64 @@ static void mem_init(phys_addr_t freemem_start)
page_alloc_ops_enable();
}
+static void mem_init(phys_addr_t freemem_start)
+{
+ struct mem_region *freemem, *code, *data;
+
+ memregions_init(riscv_mem_regions, NR_MEM_REGIONS);
+ memregions_add_dt_regions(MAX_DT_MEM_REGIONS);
+
+ /* Split the region with the code into two regions; code and data */
+ memregions_split((unsigned long)&_etext, &code, &data);
+ assert(code);
+ code->flags |= MR_F_CODE;
+
+ freemem = memregions_find(freemem_start);
+ assert(freemem && !(freemem->flags & (MR_F_IO | MR_F_CODE)));
+
+ mem_allocator_init(freemem_start, freemem->end);
+}
+
+static void freemem_push_fdt(void **freemem, const void *fdt)
+{
+ u32 fdt_size;
+ int ret;
+
+ fdt_size = fdt_totalsize(fdt);
+ ret = fdt_move(fdt, *freemem, fdt_size);
+ assert(ret == 0);
+ ret = dt_init(*freemem);
+ assert(ret == 0);
+ *freemem += fdt_size;
+}
+
+static void freemem_push_dt_initrd(void **freemem)
+{
+ const char *tmp;
+ int ret;
+
+ ret = dt_get_initrd(&tmp, &initrd_size);
+ assert(ret == 0 || ret == -FDT_ERR_NOTFOUND);
+ if (ret == 0) {
+ initrd = *freemem;
+ memmove(initrd, tmp, initrd_size);
+ *freemem += initrd_size;
+ }
+}
+
+static void initrd_setup(void)
+{
+ char *env;
+
+ if (!initrd)
+ return;
+
+ /* environ is currently the only file in the initrd */
+ env = malloc(initrd_size);
+ memcpy(env, initrd, initrd_size);
+ setup_env(env, initrd_size);
+}
+
static void banner(void)
{
puts("\n");
@@ -141,29 +188,14 @@ static void banner(void)
void setup(const void *fdt, phys_addr_t freemem_start)
{
void *freemem;
- const char *bootargs, *tmp;
- u32 fdt_size;
+ const char *bootargs;
int ret;
assert(sizeof(long) == 8 || freemem_start < VA_BASE);
freemem = __va(freemem_start);
- /* Move the FDT to the base of free memory */
- fdt_size = fdt_totalsize(fdt);
- ret = fdt_move(fdt, freemem, fdt_size);
- assert(ret == 0);
- ret = dt_init(freemem);
- assert(ret == 0);
- freemem += fdt_size;
-
- /* Move the initrd to the top of the FDT */
- ret = dt_get_initrd(&tmp, &initrd_size);
- assert(ret == 0 || ret == -FDT_ERR_NOTFOUND);
- if (ret == 0) {
- initrd = freemem;
- memmove(initrd, tmp, initrd_size);
- freemem += initrd_size;
- }
+ freemem_push_fdt(&freemem, fdt);
+ freemem_push_dt_initrd(&freemem);
mem_init(PAGE_ALIGN(__pa(freemem)));
cpu_init();
@@ -174,12 +206,7 @@ void setup(const void *fdt, phys_addr_t freemem_start)
assert(ret == 0 || ret == -FDT_ERR_NOTFOUND);
setup_args_progname(bootargs);
- if (initrd) {
- /* environ is currently the only file in the initrd */
- char *env = malloc(initrd_size);
- memcpy(env, initrd, initrd_size);
- setup_env(env, initrd_size);
- }
+ initrd_setup();
if (!(auxinfo.flags & AUXINFO_MMU_OFF))
setup_vm();
--
2.44.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [kvm-unit-tests PATCH v2 11/13] riscv: Enable EFI boot
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
` (9 preceding siblings ...)
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 10/13] riscv: Refactor setup code Andrew Jones
@ 2024-03-05 17:09 ` Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 12/13] riscv: efi: Add run script Andrew Jones
` (2 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2024-03-05 17:09 UTC (permalink / raw)
To: kvm, kvm-riscv; +Cc: pbonzini, thuth
Mimicking Arm's setup_efi() and duplicating some code from riscv's
setup(), add the EFI setup code needed to boot unit tests from EFI-
capable bootloaders. The selftest unit test can now be run with
qemu-system-riscv64 \
-nodefaults -nographic -serial mon:stdio \
-accel tcg -cpu max \
-machine virt,pflash0=pflash0 \
-blockdev node-name=pflash0,driver=file,read-only=on,filename=RISCV_VIRT_CODE.fd \
-smp 16 \
-kernel riscv/selftest.efi \
-initrd test-env \
-append 'selftest.efi foo bar baz' \
-machine acpi=off
where test-env has the environment variables
$ cat test-env
FOO=foo
BAR=bar
BAZ=baz
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
lib/riscv/asm/setup.h | 2 +-
lib/riscv/setup.c | 63 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/lib/riscv/asm/setup.h b/lib/riscv/asm/setup.h
index dfc8875fbb3b..7f81a705ca4f 100644
--- a/lib/riscv/asm/setup.h
+++ b/lib/riscv/asm/setup.h
@@ -14,7 +14,7 @@ void setup(const void *fdt, phys_addr_t freemem_start);
#ifdef CONFIG_EFI
#include <efi.h>
-static inline efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo) { return 0; }
+efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo);
#endif
#endif /* _ASMRISCV_SETUP_H_ */
diff --git a/lib/riscv/setup.c b/lib/riscv/setup.c
index f721d81192ac..50ffb0d0751b 100644
--- a/lib/riscv/setup.c
+++ b/lib/riscv/setup.c
@@ -213,3 +213,66 @@ void setup(const void *fdt, phys_addr_t freemem_start)
banner();
}
+
+#ifdef CONFIG_EFI
+#include <efi.h>
+
+extern unsigned long exception_vectors;
+extern unsigned long boot_hartid;
+
+static efi_status_t efi_mem_init(efi_bootinfo_t *efi_bootinfo)
+{
+ struct mem_region *freemem_mr = NULL, *code, *data;
+ void *freemem;
+
+ memregions_init(riscv_mem_regions, NR_MEM_REGIONS);
+
+ memregions_efi_init(&efi_bootinfo->mem_map, &freemem_mr);
+ if (!freemem_mr)
+ return EFI_OUT_OF_RESOURCES;
+
+ memregions_split((unsigned long)&_etext, &code, &data);
+ assert(code && (code->flags & MR_F_CODE));
+ if (data)
+ data->flags &= ~MR_F_CODE;
+
+ for (struct mem_region *m = mem_regions; m->end; ++m)
+ assert(m == code || !(m->flags & MR_F_CODE));
+
+ freemem = (void *)PAGE_ALIGN(freemem_mr->start);
+
+ if (efi_bootinfo->fdt)
+ freemem_push_fdt(&freemem, efi_bootinfo->fdt);
+
+ mmu_disable();
+ mem_allocator_init((unsigned long)freemem, freemem_mr->end);
+
+ return EFI_SUCCESS;
+}
+
+efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo)
+{
+ efi_status_t status;
+
+ csr_write(CSR_STVEC, (unsigned long)&exception_vectors);
+ csr_write(CSR_SSCRATCH, boot_hartid);
+
+ status = efi_mem_init(efi_bootinfo);
+ if (status != EFI_SUCCESS) {
+ printf("Failed to initialize memory\n");
+ return status;
+ }
+
+ cpu_init();
+ thread_info_init();
+ io_init();
+ initrd_setup();
+
+ if (!(auxinfo.flags & AUXINFO_MMU_OFF))
+ setup_vm();
+
+ banner();
+
+ return EFI_SUCCESS;
+}
+#endif /* CONFIG_EFI */
--
2.44.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [kvm-unit-tests PATCH v2 12/13] riscv: efi: Add run script
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
` (10 preceding siblings ...)
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 11/13] riscv: Enable EFI boot Andrew Jones
@ 2024-03-05 17:09 ` Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 13/13] riscv: efi: Use efi-direct by default Andrew Jones
2024-03-18 17:28 ` [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
13 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2024-03-05 17:09 UTC (permalink / raw)
To: kvm, kvm-riscv; +Cc: pbonzini, thuth
Adapt Arm's efi run script to riscv. We can now run efi tests with
run_tests.sh.
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
configure | 2 +-
riscv/efi/run | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++
riscv/run | 2 +-
3 files changed, 108 insertions(+), 2 deletions(-)
create mode 100755 riscv/efi/run
diff --git a/configure b/configure
index c1d0fe4adbb0..14d2569e9e0d 100755
--- a/configure
+++ b/configure
@@ -95,7 +95,7 @@ usage() {
Select whether to run EFI tests directly with QEMU's -kernel
option. When not enabled, tests will be placed in an EFI file
system and run from the UEFI shell. Ignored when efi isn't enabled.
- (arm64 only)
+ (arm64 and riscv64 only)
EOF
exit 1
}
diff --git a/riscv/efi/run b/riscv/efi/run
new file mode 100755
index 000000000000..982b8b9c455a
--- /dev/null
+++ b/riscv/efi/run
@@ -0,0 +1,106 @@
+#!/bin/bash
+
+if [ $# -eq 0 ]; then
+ echo "Usage $0 TEST_CASE [QEMU_ARGS]"
+ exit 2
+fi
+
+if [ ! -f config.mak ]; then
+ echo "run './configure --enable-efi && make' first. See ./configure -h"
+ exit 2
+fi
+source config.mak
+source scripts/arch-run.bash
+
+if [ -f RISCV_VIRT_CODE.fd ]; then
+ DEFAULT_UEFI=RISCV_VIRT_CODE.fd
+fi
+
+KERNEL_NAME=$1
+
+: "${EFI_SRC:=$TEST_DIR}"
+: "${EFI_UEFI:=$DEFAULT_UEFI}"
+: "${EFI_TEST:=efi-tests}"
+: "${EFI_CASE:=$(basename $KERNEL_NAME .efi)}"
+: "${EFI_TESTNAME:=$TESTNAME}"
+: "${EFI_TESTNAME:=$EFI_CASE}"
+: "${EFI_CASE_DIR:="$EFI_TEST/$EFI_TESTNAME"}"
+: "${EFI_VAR_GUID:=97ef3e03-7329-4a6a-b9ba-6c1fdcc5f823}"
+
+if [ ! -f "$EFI_UEFI" ]; then
+ echo "UEFI firmware not found."
+ echo "Please specify the path with the env variable EFI_UEFI"
+ exit 2
+fi
+
+if [ "$EFI_USE_ACPI" = "y" ]; then
+ echo "ACPI not available"
+ exit 2
+fi
+
+# Remove the TEST_CASE from $@
+shift 1
+
+# Fish out the arguments for the test, they should be the next string
+# after the "-append" option
+qemu_args=()
+cmd_args=()
+while (( "$#" )); do
+ if [ "$1" = "-append" ]; then
+ cmd_args=$2
+ shift 2
+ else
+ qemu_args+=("$1")
+ shift 1
+ fi
+done
+
+if [ "$EFI_CASE" = "_NO_FILE_4Uhere_" ]; then
+ EFI_CASE_DIR="$EFI_TEST/dummy"
+ mkdir -p "$EFI_CASE_DIR"
+ $TEST_DIR/run \
+ $EFI_CASE \
+ -machine pflash0=pflash0 \
+ -blockdev node-name=pflash0,driver=file,read-only=on,filename="$EFI_UEFI" \
+ -drive file.dir="$EFI_CASE_DIR/",file.driver=vvfat,file.rw=on,format=raw,if=virtio \
+ "${qemu_args[@]}"
+ exit
+fi
+
+uefi_shell_run()
+{
+ mkdir -p "$EFI_CASE_DIR"
+ cp "$EFI_SRC/$EFI_CASE.efi" "$EFI_CASE_DIR/"
+ echo "@echo -off" > "$EFI_CASE_DIR/startup.nsh"
+ if [ "$EFI_USE_ACPI" != "y" ]; then
+ qemu_args+=(-machine acpi=off)
+ FDT_BASENAME="dtb"
+ UEFI_SHELL_RUN=y $TEST_DIR/run \
+ -machine pflash0=pflash0 \
+ -blockdev node-name=pflash0,driver=file,read-only=on,filename="$EFI_UEFI" \
+ -machine dumpdtb="$EFI_CASE_DIR/$FDT_BASENAME" \
+ "${qemu_args[@]}"
+ echo "setvar fdtfile -guid $EFI_VAR_GUID -rt =L\"$FDT_BASENAME\"" >> "$EFI_CASE_DIR/startup.nsh"
+ fi
+ echo "$EFI_CASE.efi" "${cmd_args[@]}" >> "$EFI_CASE_DIR/startup.nsh"
+
+ UEFI_SHELL_RUN=y $TEST_DIR/run \
+ -machine pflash0=pflash0 \
+ -blockdev node-name=pflash0,driver=file,read-only=on,filename="$EFI_UEFI" \
+ -drive file.dir="$EFI_CASE_DIR/",file.driver=vvfat,file.rw=on,format=raw,if=virtio \
+ "${qemu_args[@]}"
+}
+
+if [ "$EFI_DIRECT" = "y" ]; then
+ if [ "$EFI_USE_ACPI" != "y" ]; then
+ qemu_args+=(-machine acpi=off)
+ fi
+ $TEST_DIR/run \
+ $KERNEL_NAME \
+ -append "$(basename $KERNEL_NAME) ${cmd_args[@]}" \
+ -machine pflash0=pflash0 \
+ -blockdev node-name=pflash0,driver=file,read-only=on,filename="$EFI_UEFI" \
+ "${qemu_args[@]}"
+else
+ uefi_shell_run
+fi
diff --git a/riscv/run b/riscv/run
index cbe5dd792dcd..73f2bf54dc32 100755
--- a/riscv/run
+++ b/riscv/run
@@ -33,7 +33,7 @@ command="$qemu -nodefaults -nographic -serial mon:stdio"
command+=" $mach $acc $firmware -cpu $processor "
command="$(migration_cmd) $(timeout_cmd) $command"
-if [ "$EFI_RUN" = "y" ]; then
+if [ "$UEFI_SHELL_RUN" = "y" ]; then
ENVIRON_DEFAULT=n run_qemu_status $command "$@"
else
# We return the exit code via stdout, not via the QEMU return code
--
2.44.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [kvm-unit-tests PATCH v2 13/13] riscv: efi: Use efi-direct by default
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
` (11 preceding siblings ...)
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 12/13] riscv: efi: Add run script Andrew Jones
@ 2024-03-05 17:09 ` Andrew Jones
2024-03-18 17:28 ` [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
13 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2024-03-05 17:09 UTC (permalink / raw)
To: kvm, kvm-riscv; +Cc: pbonzini, thuth
efi-direct is much faster and riscv makes a lot of use of environment
variables, which can't be as easily used without '-initrd'. When efi
is configured for riscv, assume efi-direct is also desired. Users
can switch to running from the UEFI shell by configuring with
--disable-efi-direct.
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
configure | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/configure b/configure
index 14d2569e9e0d..49f047cb2d7d 100755
--- a/configure
+++ b/configure
@@ -94,7 +94,8 @@ usage() {
--[enable|disable]-efi-direct
Select whether to run EFI tests directly with QEMU's -kernel
option. When not enabled, tests will be placed in an EFI file
- system and run from the UEFI shell. Ignored when efi isn't enabled.
+ system and run from the UEFI shell. Ignored when efi isn't enabled
+ and defaults to enabled when efi is enabled for riscv64.
(arm64 and riscv64 only)
EOF
exit 1
@@ -237,6 +238,10 @@ if [ "$efi" ] && [ "$arch" != "x86_64" ] &&
usage
fi
+if [ "$efi" ] && [ "$arch" = "riscv64" ] && [ -z "$efi_direct" ]; then
+ efi_direct=y
+fi
+
if [ -z "$page_size" ]; then
if [ "$efi" = 'y' ] && [ "$arch" = "arm64" ]; then
page_size="4096"
--
2.44.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [kvm-unit-tests PATCH v2 04/13] treewide: lib/stack: Make base_address arch specific
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 04/13] treewide: lib/stack: Make base_address arch specific Andrew Jones
@ 2024-03-12 5:45 ` Nicholas Piggin
0 siblings, 0 replies; 16+ messages in thread
From: Nicholas Piggin @ 2024-03-12 5:45 UTC (permalink / raw)
To: Andrew Jones, kvm, kvm-riscv
Cc: pbonzini, thuth, kvmarm, linuxppc-dev, linux-s390, lvivier,
frankja, imbrenda, nrb
On Wed Mar 6, 2024 at 3:09 AM AEST, Andrew Jones wrote:
> Calculating the offset of an address is image specific, which is
> architecture specific. Until now, all architectures and architecture
> configurations which select CONFIG_RELOC were able to subtract
> _etext, but the EFI configuration of riscv cannot (it must subtract
> ImageBase). Make this function weak, such that an architecture may
> override it when necessary, to accommodate the image layout. Then,
> immediately supply the riscv override.
>
Thanks for making these changes. Looks good. For the generic parts,
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
Thanks,
Nick
> Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
> ---
> lib/riscv/stack.c | 18 ++++++++++++++++++
> lib/stack.c | 8 ++++----
> lib/stack.h | 2 ++
> 3 files changed, 24 insertions(+), 4 deletions(-)
>
> diff --git a/lib/riscv/stack.c b/lib/riscv/stack.c
> index d865594b9671..2cd7f012738b 100644
> --- a/lib/riscv/stack.c
> +++ b/lib/riscv/stack.c
> @@ -2,6 +2,24 @@
> #include <libcflat.h>
> #include <stack.h>
>
> +#ifdef CONFIG_RELOC
> +extern char ImageBase, _text, _etext;
> +
> +bool arch_base_address(const void *rebased_addr, unsigned long *addr)
> +{
> + unsigned long ra = (unsigned long)rebased_addr;
> + unsigned long base = (unsigned long)&ImageBase;
> + unsigned long start = (unsigned long)&_text;
> + unsigned long end = (unsigned long)&_etext;
> +
> + if (ra < start || ra >= end)
> + return false;
> +
> + *addr = ra - base;
> + return true;
> +}
> +#endif
> +
> int arch_backtrace_frame(const void *frame, const void **return_addrs,
> int max_depth, bool current_frame)
> {
> diff --git a/lib/stack.c b/lib/stack.c
> index dd6bfa8dac6e..086fec544a81 100644
> --- a/lib/stack.c
> +++ b/lib/stack.c
> @@ -14,7 +14,7 @@
> #ifdef CONFIG_RELOC
> extern char _text, _etext;
>
> -static bool base_address(const void *rebased_addr, unsigned long *addr)
> +bool __attribute__((weak)) arch_base_address(const void *rebased_addr, unsigned long *addr)
> {
> unsigned long ra = (unsigned long)rebased_addr;
> unsigned long start = (unsigned long)&_text;
> @@ -27,7 +27,7 @@ static bool base_address(const void *rebased_addr, unsigned long *addr)
> return true;
> }
> #else
> -static bool base_address(const void *rebased_addr, unsigned long *addr)
> +bool __attribute__((weak)) arch_base_address(const void *rebased_addr, unsigned long *addr)
> {
> *addr = (unsigned long)rebased_addr;
> return true;
> @@ -45,13 +45,13 @@ static void print_stack(const void **return_addrs, int depth,
> /* @addr indicates a non-return address, as expected by the stack
> * pretty printer script. */
> if (depth > 0 && !top_is_return_address) {
> - if (base_address(return_addrs[0], &addr))
> + if (arch_base_address(return_addrs[0], &addr))
> printf(" @%lx", addr);
> i++;
> }
>
> for (; i < depth; i++) {
> - if (base_address(return_addrs[i], &addr))
> + if (arch_base_address(return_addrs[i], &addr))
> printf(" %lx", addr);
> }
> printf("\n");
> diff --git a/lib/stack.h b/lib/stack.h
> index 6edc84344b51..df076d94bf8f 100644
> --- a/lib/stack.h
> +++ b/lib/stack.h
> @@ -34,4 +34,6 @@ static inline int backtrace_frame(const void *frame, const void **return_addrs,
> }
> #endif
>
> +bool __attribute__((weak)) arch_base_address(const void *rebased_addr, unsigned long *addr);
> +
> #endif
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [kvm-unit-tests PATCH v2 00/13] Enable EFI support
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
` (12 preceding siblings ...)
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 13/13] riscv: efi: Use efi-direct by default Andrew Jones
@ 2024-03-18 17:28 ` Andrew Jones
13 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2024-03-18 17:28 UTC (permalink / raw)
To: kvm, kvm-riscv; +Cc: pbonzini, thuth
On Tue, Mar 05, 2024 at 06:08:59PM +0100, Andrew Jones wrote:
> This series starts with some fixes for backtraces for bugs found
> when tracing with riscv EFI builds. The series then brings EFI
> support to riscv, basing the approach heavily on arm64's support
> (including arm64's improvements[1]). It should now be possible
> to launch tests from EFI-capable bootloaders.
>
> [1] https://lore.kernel.org/all/20240305164623.379149-20-andrew.jones@linux.dev/
>
> v2:
> - Rebase on v3 of arm's efi improvement series
> - Just make base_address a weak function rather than duplicate it
> - Always preserve .so files (they're useful for debug)
> - Build the sieve test for EFI
> - Pick up a couple tags
>
> Thanks,
> drew
>
> Andrew Jones (13):
> riscv: Call abort instead of assert on unhandled exceptions
> riscv: show_regs: Prepare for EFI images
> treewide: lib/stack: Fix backtrace
> treewide: lib/stack: Make base_address arch specific
> riscv: Import gnu-efi files
> riscv: Tweak the gnu-efi imported code
> riscv: Enable building for EFI
> riscv: efi: Switch stack in _start
> efi: Add support for obtaining the boot hartid
> riscv: Refactor setup code
> riscv: Enable EFI boot
> riscv: efi: Add run script
> riscv: efi: Use efi-direct by default
>
Merged.
Thanks,
drew
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2024-03-18 17:28 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-05 17:08 [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 01/13] riscv: Call abort instead of assert on unhandled exceptions Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 02/13] riscv: show_regs: Prepare for EFI images Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 03/13] treewide: lib/stack: Fix backtrace Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 04/13] treewide: lib/stack: Make base_address arch specific Andrew Jones
2024-03-12 5:45 ` Nicholas Piggin
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 05/13] riscv: Import gnu-efi files Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 06/13] riscv: Tweak the gnu-efi imported code Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 07/13] riscv: Enable building for EFI Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 08/13] riscv: efi: Switch stack in _start Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 09/13] efi: Add support for obtaining the boot hartid Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 10/13] riscv: Refactor setup code Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 11/13] riscv: Enable EFI boot Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 12/13] riscv: efi: Add run script Andrew Jones
2024-03-05 17:09 ` [kvm-unit-tests PATCH v2 13/13] riscv: efi: Use efi-direct by default Andrew Jones
2024-03-18 17:28 ` [kvm-unit-tests PATCH v2 00/13] Enable EFI support Andrew Jones
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox