* [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
@ 2021-07-02 11:48 ` Varad Gautam via Virtualization
0 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam via Virtualization @ 2021-07-02 11:48 UTC (permalink / raw)
To: kvm, virtualization
Cc: thomas.lendacky, drjones, jroedel, brijesh.singh, pbonzini, bp
This series brings EFI support to a reduced subset of kvm-unit-tests
on x86_64. I'm sending it out for early review since it covers enough
ground to allow adding KVM testcases for EFI-only environments.
EFI support works by changing the test entrypoint to a stub entry
point for the EFI loader to jump to in long mode, where the test binary
exits EFI boot services, performs the remaining CPU bootstrapping,
and then calls the testcase main().
Since the EFI loader only understands PE objects, the first commit
introduces a `configure --efi` mode which builds each test as a shared
lib. This shared lib is repackaged into a PE via objdump.
Commit 2-4 take a trip from the asm entrypoint to C to exit EFI and
relocate ELF .dynamic contents.
Commit 5 adds post-EFI long mode x86_64 setup and calls the testcase.
Commit 6 patches out some broken tests for EFI. Testcases that refuse
to build as shared libs are also left disabled, these need some massaging.
git tree: https://github.com/varadgautam/kvm-unit-tests/commits/efi-stub
Varad Gautam (6):
x86: Build tests as PE objects for the EFI loader
x86: Call efi_main from _efi_pe_entry
x86: efi_main: Get EFI memory map and exit boot services
x86: efi_main: Self-relocate ELF .dynamic addresses
cstart64.S: x86_64 bootstrapping after exiting EFI
x86: Disable some breaking tests for EFI and modify vmexit test
.gitignore | 2 +
Makefile | 16 ++-
configure | 11 ++
lib/linux/uefi.h | 337 ++++++++++++++++++++++++++++++++++++++++++++
x86/Makefile.common | 45 ++++--
x86/Makefile.x86_64 | 43 +++---
x86/cstart64.S | 78 ++++++++++
x86/efi.lds | 67 +++++++++
x86/efi_main.c | 167 ++++++++++++++++++++++
x86/vmexit.c | 7 +
10 files changed, 741 insertions(+), 32 deletions(-)
create mode 100644 lib/linux/uefi.h
create mode 100644 x86/efi.lds
create mode 100644 x86/efi_main.c
--
2.30.2
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply [flat|nested] 32+ messages in thread
* [kvm-unit-tests PATCH 1/6] x86: Build tests as PE objects for the EFI loader
2021-07-02 11:48 ` Varad Gautam via Virtualization
@ 2021-07-02 11:48 ` Varad Gautam via Virtualization
-1 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam @ 2021-07-02 11:48 UTC (permalink / raw)
To: kvm, virtualization
Cc: pbonzini, drjones, jroedel, bp, thomas.lendacky, brijesh.singh,
varad.gautam
kvm-unit-tests produces tests as ELF binaries that can't be directly
loaded with EFI. One way of doing so however, is to build the tests
as shared libs (-pic, -shared), and then objcopy-ing out the relevant
sections into a PE32+.
This adds support to compile the tests as an intermediary .so lib,
which is linked via x86/efi.lds to contain 4K aligned COFF-compatible
sections. The linker script sets up _efi_pe_entry as the image
entrypoint, and the .so sections get repackaged to an EFI binary via
`objcopy --target efi-app-x86_64`.
The 32-bit / long mode transition / multiboot / AP setup code within
cstart64.S being incompatible with EFI builds is now hidden behind
!CONFIG_EFI. It stays enabled without `configure --efi`.
Some tests that don't support building with -fpic / -shared (and need
some cleanups) are also moved to build on non-EFI only for now.
This gets us dud EFI binaries that enter into _efi_pe_entry and die.
No change to non- --efi builds.
Signed-off-by: Varad Gautam <varad.gautam@suse.com>
---
.gitignore | 2 ++
Makefile | 16 +++++++++--
configure | 11 ++++++++
x86/Makefile.common | 44 +++++++++++++++++++----------
x86/Makefile.x86_64 | 43 ++++++++++++++++++-----------
x86/cstart64.S | 27 +++++++++++++++++-
x86/efi.lds | 67 +++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 177 insertions(+), 33 deletions(-)
create mode 100644 x86/efi.lds
diff --git a/.gitignore b/.gitignore
index 8534fb7..81ee499 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,9 @@ tags
*.a
*.d
*.o
+*.so
*.flat
+*.efi
*.elf
.pc
patches
diff --git a/Makefile b/Makefile
index f7b9f28..273b1df 100644
--- a/Makefile
+++ b/Makefile
@@ -50,7 +50,11 @@ fomit_frame_pointer := $(call cc-option, $(frame-pointer-flag), "")
fno_stack_protector := $(call cc-option, -fno-stack-protector, "")
fno_stack_protector_all := $(call cc-option, -fno-stack-protector-all, "")
wno_frame_address := $(call cc-option, -Wno-frame-address, "")
-fno_pic := $(call cc-option, -fno-pic, "")
+ifeq ($(CONFIG_EFI), y)
+opt_pic := -fpic
+else
+opt_pic := $(call cc-option, -fno-pic, "")
+endif
no_pie := $(call cc-option, -no-pie, "")
wclobbered := $(call cc-option, -Wclobbered, "")
wunused_but_set_parameter := $(call cc-option, -Wunused-but-set-parameter, "")
@@ -62,10 +66,15 @@ COMMON_CFLAGS += $(fno_stack_protector)
COMMON_CFLAGS += $(fno_stack_protector_all)
COMMON_CFLAGS += $(wno_frame_address)
COMMON_CFLAGS += $(if $(U32_LONG_FMT),-D__U32_LONG_FMT__,)
-COMMON_CFLAGS += $(fno_pic) $(no_pie)
+COMMON_CFLAGS += $(opt_pic) $(no_pie)
COMMON_CFLAGS += $(wclobbered)
COMMON_CFLAGS += $(wunused_but_set_parameter)
+ifeq ($(CONFIG_EFI),y)
+COMMON_CFLAGS += -mno-red-zone -fshort-wchar -DCONFIG_EFI -ffreestanding \
+ -fno-stack-check
+endif
+
CFLAGS += $(COMMON_CFLAGS)
CFLAGS += $(wmissing_parameter_type)
CFLAGS += $(wold_style_declaration)
@@ -74,6 +83,9 @@ CFLAGS += -Woverride-init -Wmissing-prototypes -Wstrict-prototypes
autodepend-flags = -MMD -MF $(dir $*).$(notdir $*).d
LDFLAGS += $(CFLAGS)
+ifeq ($(CONFIG_EFI),y)
+LDFLAGS += -nostdlib --warn-common --no-undefined --fatal-warnings
+endif
$(libcflat): $(cflatobjs)
$(AR) rcs $@ $^
diff --git a/configure b/configure
index 395c809..e14b9ec 100755
--- a/configure
+++ b/configure
@@ -28,6 +28,7 @@ erratatxt="$srcdir/errata.txt"
host_key_document=
page_size=
earlycon=
+config_efi=
usage() {
cat <<-EOF
@@ -69,6 +70,7 @@ usage() {
pl011,mmio32,ADDR
Specify a PL011 compatible UART at address ADDR. Supported
register stride is 32 bit only.
+ --efi Build with EFI support (x86_64 only).
EOF
exit 1
}
@@ -133,6 +135,9 @@ while [[ "$1" = -* ]]; do
--earlycon)
earlycon="$arg"
;;
+ --efi)
+ config_efi=y
+ ;;
--help)
usage
;;
@@ -192,6 +197,11 @@ elif [ "$processor" = "arm" ]; then
processor="cortex-a15"
fi
+if [ "$config_efi" = y ] && [ "$arch" != "x86_64" ]; then
+ echo "--efi only supported on x86_64"
+ usage
+fi
+
if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then
testdir=x86
elif [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
@@ -337,6 +347,7 @@ U32_LONG_FMT=$u32_long
WA_DIVIDE=$wa_divide
GENPROTIMG=${GENPROTIMG-genprotimg}
HOST_KEY_DOCUMENT=$host_key_document
+CONFIG_EFI=$config_efi
EOF
if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
echo "TARGET=$target" >> config.mak
diff --git a/x86/Makefile.common b/x86/Makefile.common
index 52bb7aa..837a8a5 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -38,7 +38,7 @@ COMMON_CFLAGS += -O1
KEEP_FRAME_POINTER := y
# We want to keep intermediate file: %.elf and %.o
-.PRECIOUS: %.elf %.o
+.PRECIOUS: %.elf %.o %.so
FLATLIBS = lib/libcflat.a
%.elf: %.o $(FLATLIBS) $(SRCDIR)/x86/flat.lds $(cstart.o)
@@ -50,17 +50,33 @@ FLATLIBS = lib/libcflat.a
$(OBJCOPY) -O elf32-i386 $^ $@
@chmod a-x $@
-tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
- $(TEST_DIR)/smptest.flat \
- $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat \
- $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat \
- $(TEST_DIR)/kvmclock_test.flat $(TEST_DIR)/eventinj.flat \
- $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat $(TEST_DIR)/setjmp.flat \
- $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \
- $(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat \
- $(TEST_DIR)/hyperv_synic.flat $(TEST_DIR)/hyperv_stimer.flat \
- $(TEST_DIR)/hyperv_connections.flat \
- $(TEST_DIR)/umip.flat $(TEST_DIR)/tsx-ctrl.flat
+%.so: %.o $(FLATLIBS) $(cstart.o)
+ $(LD) -shared -nostdlib -znocombreloc -Bsymbolic -T $(SRCDIR)/x86/efi.lds $^ \
+ -o $@ $(FLATLIBS)
+ @chmod a-x $@
+
+%.efi: %.so
+ $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \
+ -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* \
+ -j .reloc -j .init --target efi-app-x86_64 $*.so $@
+ @chmod a-x $@
+
+tests-flatonly = $(TEST_DIR)/realmode.$(out) $(TEST_DIR)/eventinj.$(out) \
+ $(TEST_DIR)/smap.$(out) $(TEST_DIR)/umip.$(out)
+
+tests-common = $(TEST_DIR)/vmexit.$(out) $(TEST_DIR)/tsc.$(out) \
+ $(TEST_DIR)/smptest.$(out) $(TEST_DIR)/msr.$(out) \
+ $(TEST_DIR)/hypercall.$(out) $(TEST_DIR)/sieve.$(out) \
+ $(TEST_DIR)/kvmclock_test.$(out) $(TEST_DIR)/s3.$(out) \
+ $(TEST_DIR)/pmu.$(out) $(TEST_DIR)/setjmp.$(out) \
+ $(TEST_DIR)/tsc_adjust.$(out) $(TEST_DIR)/asyncpf.$(out) \
+ $(TEST_DIR)/init.$(out) $(TEST_DIR)/hyperv_synic.$(out) \
+ $(TEST_DIR)/hyperv_stimer.$(out) $(TEST_DIR)/hyperv_connections.$(out) \
+ $(TEST_DIR)/tsx-ctrl.$(out)
+
+ifneq ($(CONFIG_EFI),y)
+tests-common += $(tests-flatonly)
+endif
test_cases: $(tests-common) $(tests)
@@ -81,5 +97,5 @@ $(TEST_DIR)/hyperv_stimer.elf: $(TEST_DIR)/hyperv.o
$(TEST_DIR)/hyperv_connections.elf: $(TEST_DIR)/hyperv.o
arch_clean:
- $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
- $(TEST_DIR)/.*.d lib/x86/.*.d \
+ $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.$(out) $(TEST_DIR)/*.elf \
+ $(TEST_DIR)/.*.d lib/x86/.*.d $(TEST_DIR)/*.so \
diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64
index 8134952..26970ab 100644
--- a/x86/Makefile.x86_64
+++ b/x86/Makefile.x86_64
@@ -5,28 +5,39 @@ ldarch = elf64-x86-64
fcf_protection_full := $(call cc-option, -fcf-protection=full,)
COMMON_CFLAGS += -mno-red-zone -mno-sse -mno-sse2 $(fcf_protection_full)
+ifeq ($(CONFIG_EFI),y)
+out = efi
+else
+out = flat
+endif
+
cflatobjs += lib/x86/setjmp64.o
cflatobjs += lib/x86/intel-iommu.o
cflatobjs += lib/x86/usermode.o
-tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \
- $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \
- $(TEST_DIR)/xsave.flat $(TEST_DIR)/rmap_chain.flat \
- $(TEST_DIR)/pcid.flat $(TEST_DIR)/debug.flat \
- $(TEST_DIR)/ioapic.flat $(TEST_DIR)/memory.flat \
- $(TEST_DIR)/pku.flat $(TEST_DIR)/hyperv_clock.flat
-tests += $(TEST_DIR)/syscall.flat
-tests += $(TEST_DIR)/svm.flat
-tests += $(TEST_DIR)/vmx.flat
-tests += $(TEST_DIR)/tscdeadline_latency.flat
-tests += $(TEST_DIR)/intel-iommu.flat
-tests += $(TEST_DIR)/vmware_backdoors.flat
-tests += $(TEST_DIR)/rdpru.flat
-tests += $(TEST_DIR)/pks.flat
-tests += $(TEST_DIR)/pmu_lbr.flat
+# Tests that have relocation / PIC problems and need more attention for EFI.
+tests_flatonly = $(TEST_DIR)/access.$(out) $(TEST_DIR)/emulator.$(out) \
+ $(TEST_DIR)/svm.$(out) $(TEST_DIR)/vmx.$(out) \
+ $(TEST_DIR)/vmware_backdoors.$(out)
+
+tests = $(TEST_DIR)/apic.$(out) $(TEST_DIR)/idt_test.$(out) \
+ $(TEST_DIR)/xsave.$(out) $(TEST_DIR)/rmap_chain.$(out) \
+ $(TEST_DIR)/pcid.$(out) $(TEST_DIR)/debug.$(out) \
+ $(TEST_DIR)/ioapic.$(out) $(TEST_DIR)/memory.$(out) \
+ $(TEST_DIR)/pku.$(out) $(TEST_DIR)/hyperv_clock.$(out)
+tests += $(TEST_DIR)/syscall.$(out)
+tests += $(TEST_DIR)/tscdeadline_latency.$(out)
+tests += $(TEST_DIR)/intel-iommu.$(out)
+tests += $(TEST_DIR)/rdpru.$(out)
+tests += $(TEST_DIR)/pks.$(out)
+tests += $(TEST_DIR)/pmu_lbr.$(out)
ifneq ($(fcf_protection_full),)
-tests += $(TEST_DIR)/cet.flat
+tests_flatonly += $(TEST_DIR)/cet.$(out)
+endif
+
+ifneq ($(CONFIG_EFI),y)
+tests += $(tests_flatonly)
endif
include $(SRCDIR)/$(TEST_DIR)/Makefile.common
diff --git a/x86/cstart64.S b/x86/cstart64.S
index 5c6ad38..404fcac 100644
--- a/x86/cstart64.S
+++ b/x86/cstart64.S
@@ -101,20 +101,26 @@ i = i + 1
.endr
tss_end:
+#ifndef CONFIG_EFI
mb_boot_info: .quad 0
+#endif
pt_root: .quad ptl4
+#ifndef CONFIG_EFI
.section .init
+#endif
.code32
+#ifndef CONFIG_EFI
mb_magic = 0x1BADB002
mb_flags = 0x0
# multiboot header
.long mb_magic, mb_flags, 0 - (mb_magic + mb_flags)
mb_cmdline = 16
+#endif
MSR_GS_BASE = 0xc0000101
@@ -140,6 +146,7 @@ MSR_GS_BASE = 0xc0000101
wrmsr
.endm
+#ifndef CONFIG_EFI
.globl start
start:
mov %ebx, mb_boot_info
@@ -231,16 +238,20 @@ ap_start32:
setup_percpu_area
call prepare_64
ljmpl $8, $ap_start64
+#endif /* CONFIG_EFI */
.code64
save_id:
+#ifndef CONFIG_EFI
movl $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
movl (%rax), %eax
shrl $24, %eax
lock btsl %eax, online_cpus
+#endif
retq
ap_start64:
+#ifndef CONFIG_EFI
call reset_apic
call load_tss
call enable_apic
@@ -249,11 +260,18 @@ ap_start64:
sti
nop
lock incw cpu_online_count
-
+#endif
1: hlt
jmp 1b
+#ifdef CONFIG_EFI
+.globl _efi_pe_entry
+_efi_pe_entry:
+ ret
+#endif
+
start64:
+#ifndef CONFIG_EFI
call reset_apic
call load_tss
call mask_pic_interrupts
@@ -277,9 +295,11 @@ start64:
call main
mov %eax, %edi
call exit
+#endif
.globl setup_5level_page_table
setup_5level_page_table:
+#ifndef CONFIG_EFI
/* Check if 5-level paging has already enabled */
mov %cr4, %rax
test $0x1000, %eax
@@ -287,6 +307,7 @@ setup_5level_page_table:
pushq $32
pushq $switch_to_5level
+#endif
lretq
lvl5:
retq
@@ -299,6 +320,7 @@ online_cpus:
.fill (max_cpus + 7) / 8, 1, 0
load_tss:
+#ifndef CONFIG_EFI
lidtq idt_descr
mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
mov (%rax), %eax
@@ -317,9 +339,11 @@ load_tss:
mov %eax, tss_descr+8(%rbx)
lea tss_descr-gdt64(%rbx), %rax
ltr %ax
+#endif
ret
ap_init:
+#ifndef CONFIG_EFI
cld
lea sipi_entry, %rsi
xor %rdi, %rdi
@@ -332,6 +356,7 @@ ap_init:
1: pause
cmpw %ax, cpu_online_count
jne 1b
+#endif
ret
cpu_online_count: .word 1
diff --git a/x86/efi.lds b/x86/efi.lds
new file mode 100644
index 0000000..9ed1272
--- /dev/null
+++ b/x86/efi.lds
@@ -0,0 +1,67 @@
+/* Same as gnu-efi's elf_x86_64_fbsd_efi.lds. */
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_efi_pe_entry)
+SECTIONS
+{
+ . = 0;
+ ImageBase = .;
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ . = ALIGN(4096);
+ .text :
+ {
+ _text = .;
+ *(.text)
+ *(.text.*)
+ *(.gnu.linkonce.t.*)
+ . = ALIGN(16);
+ }
+ _etext = .;
+ _text_size = . - _text;
+ . = ALIGN(4096);
+ .reloc :
+ {
+ LONG(_data);
+ LONG(10);
+ SHORT(0);
+ *(.reloc)
+ }
+ . = ALIGN(4096);
+ .data :
+ {
+ _data = .;
+ exception_table_start = .;
+ *(.data.ex)
+ exception_table_end = .;
+ *(.rodata*)
+ *(.got.plt)
+ *(.got)
+ *(.data*)
+ *(.sdata)
+ *(.sbss)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ *(.rel.local)
+ }
+ .note.gnu.build-id : { *(.note.gnu.build-id) }
+ edata = .;
+ _data_size = . - _etext;
+ . = ALIGN(4096);
+ .dynamic : { *(.dynamic) }
+ . = ALIGN(4096);
+ .rela :
+ {
+ *(.rela.data*)
+ *(.rela.got)
+ *(.rela.stab)
+ }
+ . = ALIGN(4096);
+ .dynsym : { *(.dynsym) }
+ . = ALIGN(4096);
+ .dynstr : { *(.dynstr) }
+ . = ALIGN(4096);
+ .comment 0 : { *(.comment) }
+}
--
2.30.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [kvm-unit-tests PATCH 1/6] x86: Build tests as PE objects for the EFI loader
@ 2021-07-02 11:48 ` Varad Gautam via Virtualization
0 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam via Virtualization @ 2021-07-02 11:48 UTC (permalink / raw)
To: kvm, virtualization
Cc: thomas.lendacky, drjones, jroedel, brijesh.singh, pbonzini, bp
kvm-unit-tests produces tests as ELF binaries that can't be directly
loaded with EFI. One way of doing so however, is to build the tests
as shared libs (-pic, -shared), and then objcopy-ing out the relevant
sections into a PE32+.
This adds support to compile the tests as an intermediary .so lib,
which is linked via x86/efi.lds to contain 4K aligned COFF-compatible
sections. The linker script sets up _efi_pe_entry as the image
entrypoint, and the .so sections get repackaged to an EFI binary via
`objcopy --target efi-app-x86_64`.
The 32-bit / long mode transition / multiboot / AP setup code within
cstart64.S being incompatible with EFI builds is now hidden behind
!CONFIG_EFI. It stays enabled without `configure --efi`.
Some tests that don't support building with -fpic / -shared (and need
some cleanups) are also moved to build on non-EFI only for now.
This gets us dud EFI binaries that enter into _efi_pe_entry and die.
No change to non- --efi builds.
Signed-off-by: Varad Gautam <varad.gautam@suse.com>
---
.gitignore | 2 ++
Makefile | 16 +++++++++--
configure | 11 ++++++++
x86/Makefile.common | 44 +++++++++++++++++++----------
x86/Makefile.x86_64 | 43 ++++++++++++++++++-----------
x86/cstart64.S | 27 +++++++++++++++++-
x86/efi.lds | 67 +++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 177 insertions(+), 33 deletions(-)
create mode 100644 x86/efi.lds
diff --git a/.gitignore b/.gitignore
index 8534fb7..81ee499 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,9 @@ tags
*.a
*.d
*.o
+*.so
*.flat
+*.efi
*.elf
.pc
patches
diff --git a/Makefile b/Makefile
index f7b9f28..273b1df 100644
--- a/Makefile
+++ b/Makefile
@@ -50,7 +50,11 @@ fomit_frame_pointer := $(call cc-option, $(frame-pointer-flag), "")
fno_stack_protector := $(call cc-option, -fno-stack-protector, "")
fno_stack_protector_all := $(call cc-option, -fno-stack-protector-all, "")
wno_frame_address := $(call cc-option, -Wno-frame-address, "")
-fno_pic := $(call cc-option, -fno-pic, "")
+ifeq ($(CONFIG_EFI), y)
+opt_pic := -fpic
+else
+opt_pic := $(call cc-option, -fno-pic, "")
+endif
no_pie := $(call cc-option, -no-pie, "")
wclobbered := $(call cc-option, -Wclobbered, "")
wunused_but_set_parameter := $(call cc-option, -Wunused-but-set-parameter, "")
@@ -62,10 +66,15 @@ COMMON_CFLAGS += $(fno_stack_protector)
COMMON_CFLAGS += $(fno_stack_protector_all)
COMMON_CFLAGS += $(wno_frame_address)
COMMON_CFLAGS += $(if $(U32_LONG_FMT),-D__U32_LONG_FMT__,)
-COMMON_CFLAGS += $(fno_pic) $(no_pie)
+COMMON_CFLAGS += $(opt_pic) $(no_pie)
COMMON_CFLAGS += $(wclobbered)
COMMON_CFLAGS += $(wunused_but_set_parameter)
+ifeq ($(CONFIG_EFI),y)
+COMMON_CFLAGS += -mno-red-zone -fshort-wchar -DCONFIG_EFI -ffreestanding \
+ -fno-stack-check
+endif
+
CFLAGS += $(COMMON_CFLAGS)
CFLAGS += $(wmissing_parameter_type)
CFLAGS += $(wold_style_declaration)
@@ -74,6 +83,9 @@ CFLAGS += -Woverride-init -Wmissing-prototypes -Wstrict-prototypes
autodepend-flags = -MMD -MF $(dir $*).$(notdir $*).d
LDFLAGS += $(CFLAGS)
+ifeq ($(CONFIG_EFI),y)
+LDFLAGS += -nostdlib --warn-common --no-undefined --fatal-warnings
+endif
$(libcflat): $(cflatobjs)
$(AR) rcs $@ $^
diff --git a/configure b/configure
index 395c809..e14b9ec 100755
--- a/configure
+++ b/configure
@@ -28,6 +28,7 @@ erratatxt="$srcdir/errata.txt"
host_key_document=
page_size=
earlycon=
+config_efi=
usage() {
cat <<-EOF
@@ -69,6 +70,7 @@ usage() {
pl011,mmio32,ADDR
Specify a PL011 compatible UART at address ADDR. Supported
register stride is 32 bit only.
+ --efi Build with EFI support (x86_64 only).
EOF
exit 1
}
@@ -133,6 +135,9 @@ while [[ "$1" = -* ]]; do
--earlycon)
earlycon="$arg"
;;
+ --efi)
+ config_efi=y
+ ;;
--help)
usage
;;
@@ -192,6 +197,11 @@ elif [ "$processor" = "arm" ]; then
processor="cortex-a15"
fi
+if [ "$config_efi" = y ] && [ "$arch" != "x86_64" ]; then
+ echo "--efi only supported on x86_64"
+ usage
+fi
+
if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then
testdir=x86
elif [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
@@ -337,6 +347,7 @@ U32_LONG_FMT=$u32_long
WA_DIVIDE=$wa_divide
GENPROTIMG=${GENPROTIMG-genprotimg}
HOST_KEY_DOCUMENT=$host_key_document
+CONFIG_EFI=$config_efi
EOF
if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
echo "TARGET=$target" >> config.mak
diff --git a/x86/Makefile.common b/x86/Makefile.common
index 52bb7aa..837a8a5 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -38,7 +38,7 @@ COMMON_CFLAGS += -O1
KEEP_FRAME_POINTER := y
# We want to keep intermediate file: %.elf and %.o
-.PRECIOUS: %.elf %.o
+.PRECIOUS: %.elf %.o %.so
FLATLIBS = lib/libcflat.a
%.elf: %.o $(FLATLIBS) $(SRCDIR)/x86/flat.lds $(cstart.o)
@@ -50,17 +50,33 @@ FLATLIBS = lib/libcflat.a
$(OBJCOPY) -O elf32-i386 $^ $@
@chmod a-x $@
-tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
- $(TEST_DIR)/smptest.flat \
- $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat \
- $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat \
- $(TEST_DIR)/kvmclock_test.flat $(TEST_DIR)/eventinj.flat \
- $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat $(TEST_DIR)/setjmp.flat \
- $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \
- $(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat \
- $(TEST_DIR)/hyperv_synic.flat $(TEST_DIR)/hyperv_stimer.flat \
- $(TEST_DIR)/hyperv_connections.flat \
- $(TEST_DIR)/umip.flat $(TEST_DIR)/tsx-ctrl.flat
+%.so: %.o $(FLATLIBS) $(cstart.o)
+ $(LD) -shared -nostdlib -znocombreloc -Bsymbolic -T $(SRCDIR)/x86/efi.lds $^ \
+ -o $@ $(FLATLIBS)
+ @chmod a-x $@
+
+%.efi: %.so
+ $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \
+ -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* \
+ -j .reloc -j .init --target efi-app-x86_64 $*.so $@
+ @chmod a-x $@
+
+tests-flatonly = $(TEST_DIR)/realmode.$(out) $(TEST_DIR)/eventinj.$(out) \
+ $(TEST_DIR)/smap.$(out) $(TEST_DIR)/umip.$(out)
+
+tests-common = $(TEST_DIR)/vmexit.$(out) $(TEST_DIR)/tsc.$(out) \
+ $(TEST_DIR)/smptest.$(out) $(TEST_DIR)/msr.$(out) \
+ $(TEST_DIR)/hypercall.$(out) $(TEST_DIR)/sieve.$(out) \
+ $(TEST_DIR)/kvmclock_test.$(out) $(TEST_DIR)/s3.$(out) \
+ $(TEST_DIR)/pmu.$(out) $(TEST_DIR)/setjmp.$(out) \
+ $(TEST_DIR)/tsc_adjust.$(out) $(TEST_DIR)/asyncpf.$(out) \
+ $(TEST_DIR)/init.$(out) $(TEST_DIR)/hyperv_synic.$(out) \
+ $(TEST_DIR)/hyperv_stimer.$(out) $(TEST_DIR)/hyperv_connections.$(out) \
+ $(TEST_DIR)/tsx-ctrl.$(out)
+
+ifneq ($(CONFIG_EFI),y)
+tests-common += $(tests-flatonly)
+endif
test_cases: $(tests-common) $(tests)
@@ -81,5 +97,5 @@ $(TEST_DIR)/hyperv_stimer.elf: $(TEST_DIR)/hyperv.o
$(TEST_DIR)/hyperv_connections.elf: $(TEST_DIR)/hyperv.o
arch_clean:
- $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
- $(TEST_DIR)/.*.d lib/x86/.*.d \
+ $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.$(out) $(TEST_DIR)/*.elf \
+ $(TEST_DIR)/.*.d lib/x86/.*.d $(TEST_DIR)/*.so \
diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64
index 8134952..26970ab 100644
--- a/x86/Makefile.x86_64
+++ b/x86/Makefile.x86_64
@@ -5,28 +5,39 @@ ldarch = elf64-x86-64
fcf_protection_full := $(call cc-option, -fcf-protection=full,)
COMMON_CFLAGS += -mno-red-zone -mno-sse -mno-sse2 $(fcf_protection_full)
+ifeq ($(CONFIG_EFI),y)
+out = efi
+else
+out = flat
+endif
+
cflatobjs += lib/x86/setjmp64.o
cflatobjs += lib/x86/intel-iommu.o
cflatobjs += lib/x86/usermode.o
-tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \
- $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \
- $(TEST_DIR)/xsave.flat $(TEST_DIR)/rmap_chain.flat \
- $(TEST_DIR)/pcid.flat $(TEST_DIR)/debug.flat \
- $(TEST_DIR)/ioapic.flat $(TEST_DIR)/memory.flat \
- $(TEST_DIR)/pku.flat $(TEST_DIR)/hyperv_clock.flat
-tests += $(TEST_DIR)/syscall.flat
-tests += $(TEST_DIR)/svm.flat
-tests += $(TEST_DIR)/vmx.flat
-tests += $(TEST_DIR)/tscdeadline_latency.flat
-tests += $(TEST_DIR)/intel-iommu.flat
-tests += $(TEST_DIR)/vmware_backdoors.flat
-tests += $(TEST_DIR)/rdpru.flat
-tests += $(TEST_DIR)/pks.flat
-tests += $(TEST_DIR)/pmu_lbr.flat
+# Tests that have relocation / PIC problems and need more attention for EFI.
+tests_flatonly = $(TEST_DIR)/access.$(out) $(TEST_DIR)/emulator.$(out) \
+ $(TEST_DIR)/svm.$(out) $(TEST_DIR)/vmx.$(out) \
+ $(TEST_DIR)/vmware_backdoors.$(out)
+
+tests = $(TEST_DIR)/apic.$(out) $(TEST_DIR)/idt_test.$(out) \
+ $(TEST_DIR)/xsave.$(out) $(TEST_DIR)/rmap_chain.$(out) \
+ $(TEST_DIR)/pcid.$(out) $(TEST_DIR)/debug.$(out) \
+ $(TEST_DIR)/ioapic.$(out) $(TEST_DIR)/memory.$(out) \
+ $(TEST_DIR)/pku.$(out) $(TEST_DIR)/hyperv_clock.$(out)
+tests += $(TEST_DIR)/syscall.$(out)
+tests += $(TEST_DIR)/tscdeadline_latency.$(out)
+tests += $(TEST_DIR)/intel-iommu.$(out)
+tests += $(TEST_DIR)/rdpru.$(out)
+tests += $(TEST_DIR)/pks.$(out)
+tests += $(TEST_DIR)/pmu_lbr.$(out)
ifneq ($(fcf_protection_full),)
-tests += $(TEST_DIR)/cet.flat
+tests_flatonly += $(TEST_DIR)/cet.$(out)
+endif
+
+ifneq ($(CONFIG_EFI),y)
+tests += $(tests_flatonly)
endif
include $(SRCDIR)/$(TEST_DIR)/Makefile.common
diff --git a/x86/cstart64.S b/x86/cstart64.S
index 5c6ad38..404fcac 100644
--- a/x86/cstart64.S
+++ b/x86/cstart64.S
@@ -101,20 +101,26 @@ i = i + 1
.endr
tss_end:
+#ifndef CONFIG_EFI
mb_boot_info: .quad 0
+#endif
pt_root: .quad ptl4
+#ifndef CONFIG_EFI
.section .init
+#endif
.code32
+#ifndef CONFIG_EFI
mb_magic = 0x1BADB002
mb_flags = 0x0
# multiboot header
.long mb_magic, mb_flags, 0 - (mb_magic + mb_flags)
mb_cmdline = 16
+#endif
MSR_GS_BASE = 0xc0000101
@@ -140,6 +146,7 @@ MSR_GS_BASE = 0xc0000101
wrmsr
.endm
+#ifndef CONFIG_EFI
.globl start
start:
mov %ebx, mb_boot_info
@@ -231,16 +238,20 @@ ap_start32:
setup_percpu_area
call prepare_64
ljmpl $8, $ap_start64
+#endif /* CONFIG_EFI */
.code64
save_id:
+#ifndef CONFIG_EFI
movl $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
movl (%rax), %eax
shrl $24, %eax
lock btsl %eax, online_cpus
+#endif
retq
ap_start64:
+#ifndef CONFIG_EFI
call reset_apic
call load_tss
call enable_apic
@@ -249,11 +260,18 @@ ap_start64:
sti
nop
lock incw cpu_online_count
-
+#endif
1: hlt
jmp 1b
+#ifdef CONFIG_EFI
+.globl _efi_pe_entry
+_efi_pe_entry:
+ ret
+#endif
+
start64:
+#ifndef CONFIG_EFI
call reset_apic
call load_tss
call mask_pic_interrupts
@@ -277,9 +295,11 @@ start64:
call main
mov %eax, %edi
call exit
+#endif
.globl setup_5level_page_table
setup_5level_page_table:
+#ifndef CONFIG_EFI
/* Check if 5-level paging has already enabled */
mov %cr4, %rax
test $0x1000, %eax
@@ -287,6 +307,7 @@ setup_5level_page_table:
pushq $32
pushq $switch_to_5level
+#endif
lretq
lvl5:
retq
@@ -299,6 +320,7 @@ online_cpus:
.fill (max_cpus + 7) / 8, 1, 0
load_tss:
+#ifndef CONFIG_EFI
lidtq idt_descr
mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
mov (%rax), %eax
@@ -317,9 +339,11 @@ load_tss:
mov %eax, tss_descr+8(%rbx)
lea tss_descr-gdt64(%rbx), %rax
ltr %ax
+#endif
ret
ap_init:
+#ifndef CONFIG_EFI
cld
lea sipi_entry, %rsi
xor %rdi, %rdi
@@ -332,6 +356,7 @@ ap_init:
1: pause
cmpw %ax, cpu_online_count
jne 1b
+#endif
ret
cpu_online_count: .word 1
diff --git a/x86/efi.lds b/x86/efi.lds
new file mode 100644
index 0000000..9ed1272
--- /dev/null
+++ b/x86/efi.lds
@@ -0,0 +1,67 @@
+/* Same as gnu-efi's elf_x86_64_fbsd_efi.lds. */
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_efi_pe_entry)
+SECTIONS
+{
+ . = 0;
+ ImageBase = .;
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ . = ALIGN(4096);
+ .text :
+ {
+ _text = .;
+ *(.text)
+ *(.text.*)
+ *(.gnu.linkonce.t.*)
+ . = ALIGN(16);
+ }
+ _etext = .;
+ _text_size = . - _text;
+ . = ALIGN(4096);
+ .reloc :
+ {
+ LONG(_data);
+ LONG(10);
+ SHORT(0);
+ *(.reloc)
+ }
+ . = ALIGN(4096);
+ .data :
+ {
+ _data = .;
+ exception_table_start = .;
+ *(.data.ex)
+ exception_table_end = .;
+ *(.rodata*)
+ *(.got.plt)
+ *(.got)
+ *(.data*)
+ *(.sdata)
+ *(.sbss)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ *(.rel.local)
+ }
+ .note.gnu.build-id : { *(.note.gnu.build-id) }
+ edata = .;
+ _data_size = . - _etext;
+ . = ALIGN(4096);
+ .dynamic : { *(.dynamic) }
+ . = ALIGN(4096);
+ .rela :
+ {
+ *(.rela.data*)
+ *(.rela.got)
+ *(.rela.stab)
+ }
+ . = ALIGN(4096);
+ .dynsym : { *(.dynsym) }
+ . = ALIGN(4096);
+ .dynstr : { *(.dynstr) }
+ . = ALIGN(4096);
+ .comment 0 : { *(.comment) }
+}
--
2.30.2
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [kvm-unit-tests PATCH 2/6] x86: Call efi_main from _efi_pe_entry
2021-07-02 11:48 ` Varad Gautam via Virtualization
@ 2021-07-02 11:48 ` Varad Gautam via Virtualization
-1 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam @ 2021-07-02 11:48 UTC (permalink / raw)
To: kvm, virtualization
Cc: pbonzini, drjones, jroedel, bp, thomas.lendacky, brijesh.singh,
varad.gautam
EFI calls _efi_pe_entry in long mode with the location of EFI
handle/system table. Add an efi_main() C handler to make it easier
to communicate with EFI for initial setup. efi_main will later,
1. Acquire the efi memmap
2. Call ExitBootServices
3. Perform remaining bootstrapping before calling the testcase main()
Signed-off-by: Varad Gautam <varad.gautam@suse.com>
---
lib/linux/uefi.h | 337 ++++++++++++++++++++++++++++++++++++++++++++
x86/Makefile.common | 2 +-
x86/cstart64.S | 10 +-
x86/efi_main.c | 11 ++
4 files changed, 358 insertions(+), 2 deletions(-)
create mode 100644 lib/linux/uefi.h
create mode 100644 x86/efi_main.c
diff --git a/lib/linux/uefi.h b/lib/linux/uefi.h
new file mode 100644
index 0000000..eb142a5
--- /dev/null
+++ b/lib/linux/uefi.h
@@ -0,0 +1,337 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Relevant definitions from linux/efi.h. */
+
+#ifndef __LINUX_UEFI_H
+#define __LINUX_UEFI_H
+
+#include "libcflat.h"
+
+#define BITS_PER_LONG 64
+
+#define EFI_SUCCESS 0
+#define EFI_LOAD_ERROR ( 1 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_INVALID_PARAMETER ( 2 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NOT_READY ( 6 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_DEVICE_ERROR ( 7 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_WRITE_PROTECTED ( 8 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_OUT_OF_RESOURCES ( 9 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_TIMEOUT (18 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_ABORTED (21 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_SECURITY_VIOLATION (26 | (1UL << (BITS_PER_LONG-1)))
+
+typedef unsigned long efi_status_t;
+typedef u8 efi_bool_t;
+typedef u16 efi_char16_t; /* UNICODE character */
+typedef u64 efi_physical_addr_t;
+typedef void *efi_handle_t;
+#define __efiapi __attribute__((ms_abi))
+
+/*
+ * Generic EFI table header
+ */
+typedef struct {
+ u64 signature;
+ u32 revision;
+ u32 headersize;
+ u32 crc32;
+ u32 reserved;
+} efi_table_hdr_t;
+
+typedef struct {
+ u16 scan_code;
+ efi_char16_t unicode_char;
+} efi_input_key_t;
+
+typedef void *efi_event_t;
+/* Note that notifications won't work in mixed mode */
+typedef void (__efiapi *efi_event_notify_t)(efi_event_t, void *);
+
+typedef union efi_simple_text_input_protocol efi_simple_text_input_protocol_t;
+typedef union efi_simple_text_output_protocol efi_simple_text_output_protocol_t;
+
+union efi_simple_text_input_protocol {
+ struct {
+ void *reset;
+ efi_status_t (__efiapi *read_keystroke)(efi_simple_text_input_protocol_t *,
+ efi_input_key_t *);
+ efi_event_t wait_for_key;
+ };
+ struct {
+ u32 reset;
+ u32 read_keystroke;
+ u32 wait_for_key;
+ } mixed_mode;
+};
+
+union efi_simple_text_output_protocol {
+ struct {
+ void *reset;
+ efi_status_t (__efiapi *output_string)(efi_simple_text_output_protocol_t *,
+ efi_char16_t *);
+ void *test_string;
+ };
+ struct {
+ u32 reset;
+ u32 output_string;
+ u32 test_string;
+ } mixed_mode;
+};
+
+typedef enum {
+ EfiTimerCancel,
+ EfiTimerPeriodic,
+ EfiTimerRelative
+} EFI_TIMER_DELAY;
+
+struct efi_generic_dev_path {
+ u8 type;
+ u8 sub_type;
+ u16 length;
+} __packed;
+typedef struct efi_generic_dev_path efi_device_path_protocol_t;
+
+union efi_boot_services {
+ struct {
+ efi_table_hdr_t hdr;
+ void *raise_tpl;
+ void *restore_tpl;
+ efi_status_t (__efiapi *allocate_pages)(int, int, unsigned long,
+ efi_physical_addr_t *);
+ efi_status_t (__efiapi *free_pages)(efi_physical_addr_t,
+ unsigned long);
+ efi_status_t (__efiapi *get_memory_map)(unsigned long *, void *,
+ unsigned long *,
+ unsigned long *, u32 *);
+ efi_status_t (__efiapi *allocate_pool)(int, unsigned long,
+ void **);
+ efi_status_t (__efiapi *free_pool)(void *);
+ efi_status_t (__efiapi *create_event)(u32, unsigned long,
+ efi_event_notify_t, void *,
+ void *);
+ efi_status_t (__efiapi *set_timer)(efi_event_t,
+ EFI_TIMER_DELAY, u64);
+ efi_status_t (__efiapi *wait_for_event)(unsigned long,
+ void *,
+ unsigned long *);
+ void *signal_event;
+ efi_status_t (__efiapi *close_event)(void);
+ void *check_event;
+ void *install_protocol_interface;
+ void *reinstall_protocol_interface;
+ void *uninstall_protocol_interface;
+ efi_status_t (__efiapi *handle_protocol)(efi_handle_t,
+ void *, void **);
+ void *__reserved;
+ void *register_protocol_notify;
+ efi_status_t (__efiapi *locate_handle)(int, void *,
+ void *, unsigned long *,
+ efi_handle_t *);
+ efi_status_t (__efiapi *locate_device_path)(void *,
+ efi_device_path_protocol_t **,
+ efi_handle_t *);
+ efi_status_t (__efiapi *install_configuration_table)(void *,
+ void *);
+ void *load_image;
+ void *start_image;
+ efi_status_t (__efiapi *exit)(efi_handle_t,
+ efi_status_t,
+ unsigned long,
+ efi_char16_t *);
+ void *unload_image;
+ efi_status_t (__efiapi *exit_boot_services)(efi_handle_t,
+ unsigned long);
+ void *get_next_monotonic_count;
+ efi_status_t (__efiapi *stall)(unsigned long);
+ void *set_watchdog_timer;
+ void *connect_controller;
+ efi_status_t (__efiapi *disconnect_controller)(efi_handle_t,
+ efi_handle_t,
+ efi_handle_t);
+ void *open_protocol;
+ void *close_protocol;
+ void *open_protocol_information;
+ void *protocols_per_handle;
+ void *locate_handle_buffer;
+ efi_status_t (__efiapi *locate_protocol)(void *, void *,
+ void **);
+ void *install_multiple_protocol_interfaces;
+ void *uninstall_multiple_protocol_interfaces;
+ void *calculate_crc32;
+ void *copy_mem;
+ void *set_mem;
+ void *create_event_ex;
+ };
+ struct {
+ efi_table_hdr_t hdr;
+ u32 raise_tpl;
+ u32 restore_tpl;
+ u32 allocate_pages;
+ u32 free_pages;
+ u32 get_memory_map;
+ u32 allocate_pool;
+ u32 free_pool;
+ u32 create_event;
+ u32 set_timer;
+ u32 wait_for_event;
+ u32 signal_event;
+ u32 close_event;
+ u32 check_event;
+ u32 install_protocol_interface;
+ u32 reinstall_protocol_interface;
+ u32 uninstall_protocol_interface;
+ u32 handle_protocol;
+ u32 __reserved;
+ u32 register_protocol_notify;
+ u32 locate_handle;
+ u32 locate_device_path;
+ u32 install_configuration_table;
+ u32 load_image;
+ u32 start_image;
+ u32 exit;
+ u32 unload_image;
+ u32 exit_boot_services;
+ u32 get_next_monotonic_count;
+ u32 stall;
+ u32 set_watchdog_timer;
+ u32 connect_controller;
+ u32 disconnect_controller;
+ u32 open_protocol;
+ u32 close_protocol;
+ u32 open_protocol_information;
+ u32 protocols_per_handle;
+ u32 locate_handle_buffer;
+ u32 locate_protocol;
+ u32 install_multiple_protocol_interfaces;
+ u32 uninstall_multiple_protocol_interfaces;
+ u32 calculate_crc32;
+ u32 copy_mem;
+ u32 set_mem;
+ u32 create_event_ex;
+ } mixed_mode;
+};
+
+typedef union efi_boot_services efi_boot_services_t;
+
+typedef struct {
+ efi_table_hdr_t hdr;
+ u64 fw_vendor; /* physical addr of CHAR16 vendor string */
+ u32 fw_revision;
+ u32 __pad1;
+ u64 con_in_handle;
+ u64 con_in;
+ u64 con_out_handle;
+ u64 con_out;
+ u64 stderr_handle;
+ u64 stderr;
+ u64 runtime;
+ u64 boottime;
+ u32 nr_tables;
+ u32 __pad2;
+ u64 tables;
+} efi_system_table_64_t;
+
+typedef struct {
+ efi_table_hdr_t hdr;
+ u32 fw_vendor; /* physical addr of CHAR16 vendor string */
+ u32 fw_revision;
+ u32 con_in_handle;
+ u32 con_in;
+ u32 con_out_handle;
+ u32 con_out;
+ u32 stderr_handle;
+ u32 stderr;
+ u32 runtime;
+ u32 boottime;
+ u32 nr_tables;
+ u32 tables;
+} efi_system_table_32_t;
+
+typedef union {
+ struct {
+ efi_table_hdr_t hdr;
+ unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */
+ u32 fw_revision;
+ unsigned long con_in_handle;
+ efi_simple_text_input_protocol_t *con_in;
+ unsigned long con_out_handle;
+ efi_simple_text_output_protocol_t *con_out;
+ unsigned long stderr_handle;
+ unsigned long stderr;
+ void *runtime;
+ efi_boot_services_t *boottime;
+ unsigned long nr_tables;
+ unsigned long tables;
+ };
+ efi_system_table_32_t mixed_mode;
+} efi_system_table_t;
+
+/*
+ * Memory map descriptor:
+ */
+
+/* Memory types: */
+#define EFI_RESERVED_TYPE 0
+#define EFI_LOADER_CODE 1
+#define EFI_LOADER_DATA 2
+#define EFI_BOOT_SERVICES_CODE 3
+#define EFI_BOOT_SERVICES_DATA 4
+#define EFI_RUNTIME_SERVICES_CODE 5
+#define EFI_RUNTIME_SERVICES_DATA 6
+#define EFI_CONVENTIONAL_MEMORY 7
+#define EFI_UNUSABLE_MEMORY 8
+#define EFI_ACPI_RECLAIM_MEMORY 9
+#define EFI_ACPI_MEMORY_NVS 10
+#define EFI_MEMORY_MAPPED_IO 11
+#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12
+#define EFI_PAL_CODE 13
+#define EFI_PERSISTENT_MEMORY 14
+#define EFI_MAX_MEMORY_TYPE 15
+
+/* Attribute values: */
+#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */
+#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */
+#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */
+#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */
+#define EFI_MEMORY_UCE ((u64)0x0000000000000010ULL) /* uncached, exported */
+#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */
+#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */
+#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */
+#define EFI_MEMORY_NV ((u64)0x0000000000008000ULL) /* non-volatile */
+#define EFI_MEMORY_MORE_RELIABLE \
+ ((u64)0x0000000000010000ULL) /* higher reliability */
+#define EFI_MEMORY_RO ((u64)0x0000000000020000ULL) /* read-only */
+#define EFI_MEMORY_SP ((u64)0x0000000000040000ULL) /* soft reserved */
+#define EFI_MEMORY_CPU_CRYPTO ((u64)0x0000000000080000ULL) /* supports encryption */
+#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */
+#define EFI_MEMORY_DESCRIPTOR_VERSION 1
+
+#define EFI_PAGE_SHIFT 12
+#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT)
+#define EFI_PAGES_MAX (U64_MAX >> EFI_PAGE_SHIFT)
+
+typedef struct {
+ u32 type;
+ u32 pad;
+ u64 phys_addr;
+ u64 virt_addr;
+ u64 num_pages;
+ u64 attribute;
+} efi_memory_desc_t;
+
+struct efi_boot_memmap {
+ efi_memory_desc_t **map;
+ unsigned long *map_size;
+ unsigned long *desc_size;
+ u32 *desc_ver;
+ unsigned long *key_ptr;
+ unsigned long *buff_size;
+};
+
+#define efi_bs_call(func, ...) \
+ efi_system_table->boottime->func(__VA_ARGS__)
+
+#endif /* __LINUX_UEFI_H */
diff --git a/x86/Makefile.common b/x86/Makefile.common
index 837a8a5..98d8de9 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -50,7 +50,7 @@ FLATLIBS = lib/libcflat.a
$(OBJCOPY) -O elf32-i386 $^ $@
@chmod a-x $@
-%.so: %.o $(FLATLIBS) $(cstart.o)
+%.so: %.o $(FLATLIBS) $(TEST_DIR)/efi_main.o $(cstart.o)
$(LD) -shared -nostdlib -znocombreloc -Bsymbolic -T $(SRCDIR)/x86/efi.lds $^ \
-o $@ $(FLATLIBS)
@chmod a-x $@
diff --git a/x86/cstart64.S b/x86/cstart64.S
index 404fcac..98e7848 100644
--- a/x86/cstart64.S
+++ b/x86/cstart64.S
@@ -267,7 +267,15 @@ ap_start64:
#ifdef CONFIG_EFI
.globl _efi_pe_entry
_efi_pe_entry:
- ret
+ # EFI image loader calls this with rcx=efi_handle,
+ # rdx=efi_system_table. Pass these to efi_main.
+ mov %rcx, %rdi
+ mov %rdx, %rsi
+
+ pushq %rdi
+ pushq %rsi
+
+ call efi_main
#endif
start64:
diff --git a/x86/efi_main.c b/x86/efi_main.c
new file mode 100644
index 0000000..00e7086
--- /dev/null
+++ b/x86/efi_main.c
@@ -0,0 +1,11 @@
+#include <linux/uefi.h>
+
+unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab);
+efi_system_table_t *efi_system_table = NULL;
+
+unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab)
+{
+ efi_system_table = sys_tab;
+
+ return 0;
+}
--
2.30.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [kvm-unit-tests PATCH 2/6] x86: Call efi_main from _efi_pe_entry
@ 2021-07-02 11:48 ` Varad Gautam via Virtualization
0 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam via Virtualization @ 2021-07-02 11:48 UTC (permalink / raw)
To: kvm, virtualization
Cc: thomas.lendacky, drjones, jroedel, brijesh.singh, pbonzini, bp
EFI calls _efi_pe_entry in long mode with the location of EFI
handle/system table. Add an efi_main() C handler to make it easier
to communicate with EFI for initial setup. efi_main will later,
1. Acquire the efi memmap
2. Call ExitBootServices
3. Perform remaining bootstrapping before calling the testcase main()
Signed-off-by: Varad Gautam <varad.gautam@suse.com>
---
lib/linux/uefi.h | 337 ++++++++++++++++++++++++++++++++++++++++++++
x86/Makefile.common | 2 +-
x86/cstart64.S | 10 +-
x86/efi_main.c | 11 ++
4 files changed, 358 insertions(+), 2 deletions(-)
create mode 100644 lib/linux/uefi.h
create mode 100644 x86/efi_main.c
diff --git a/lib/linux/uefi.h b/lib/linux/uefi.h
new file mode 100644
index 0000000..eb142a5
--- /dev/null
+++ b/lib/linux/uefi.h
@@ -0,0 +1,337 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Relevant definitions from linux/efi.h. */
+
+#ifndef __LINUX_UEFI_H
+#define __LINUX_UEFI_H
+
+#include "libcflat.h"
+
+#define BITS_PER_LONG 64
+
+#define EFI_SUCCESS 0
+#define EFI_LOAD_ERROR ( 1 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_INVALID_PARAMETER ( 2 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NOT_READY ( 6 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_DEVICE_ERROR ( 7 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_WRITE_PROTECTED ( 8 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_OUT_OF_RESOURCES ( 9 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_TIMEOUT (18 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_ABORTED (21 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_SECURITY_VIOLATION (26 | (1UL << (BITS_PER_LONG-1)))
+
+typedef unsigned long efi_status_t;
+typedef u8 efi_bool_t;
+typedef u16 efi_char16_t; /* UNICODE character */
+typedef u64 efi_physical_addr_t;
+typedef void *efi_handle_t;
+#define __efiapi __attribute__((ms_abi))
+
+/*
+ * Generic EFI table header
+ */
+typedef struct {
+ u64 signature;
+ u32 revision;
+ u32 headersize;
+ u32 crc32;
+ u32 reserved;
+} efi_table_hdr_t;
+
+typedef struct {
+ u16 scan_code;
+ efi_char16_t unicode_char;
+} efi_input_key_t;
+
+typedef void *efi_event_t;
+/* Note that notifications won't work in mixed mode */
+typedef void (__efiapi *efi_event_notify_t)(efi_event_t, void *);
+
+typedef union efi_simple_text_input_protocol efi_simple_text_input_protocol_t;
+typedef union efi_simple_text_output_protocol efi_simple_text_output_protocol_t;
+
+union efi_simple_text_input_protocol {
+ struct {
+ void *reset;
+ efi_status_t (__efiapi *read_keystroke)(efi_simple_text_input_protocol_t *,
+ efi_input_key_t *);
+ efi_event_t wait_for_key;
+ };
+ struct {
+ u32 reset;
+ u32 read_keystroke;
+ u32 wait_for_key;
+ } mixed_mode;
+};
+
+union efi_simple_text_output_protocol {
+ struct {
+ void *reset;
+ efi_status_t (__efiapi *output_string)(efi_simple_text_output_protocol_t *,
+ efi_char16_t *);
+ void *test_string;
+ };
+ struct {
+ u32 reset;
+ u32 output_string;
+ u32 test_string;
+ } mixed_mode;
+};
+
+typedef enum {
+ EfiTimerCancel,
+ EfiTimerPeriodic,
+ EfiTimerRelative
+} EFI_TIMER_DELAY;
+
+struct efi_generic_dev_path {
+ u8 type;
+ u8 sub_type;
+ u16 length;
+} __packed;
+typedef struct efi_generic_dev_path efi_device_path_protocol_t;
+
+union efi_boot_services {
+ struct {
+ efi_table_hdr_t hdr;
+ void *raise_tpl;
+ void *restore_tpl;
+ efi_status_t (__efiapi *allocate_pages)(int, int, unsigned long,
+ efi_physical_addr_t *);
+ efi_status_t (__efiapi *free_pages)(efi_physical_addr_t,
+ unsigned long);
+ efi_status_t (__efiapi *get_memory_map)(unsigned long *, void *,
+ unsigned long *,
+ unsigned long *, u32 *);
+ efi_status_t (__efiapi *allocate_pool)(int, unsigned long,
+ void **);
+ efi_status_t (__efiapi *free_pool)(void *);
+ efi_status_t (__efiapi *create_event)(u32, unsigned long,
+ efi_event_notify_t, void *,
+ void *);
+ efi_status_t (__efiapi *set_timer)(efi_event_t,
+ EFI_TIMER_DELAY, u64);
+ efi_status_t (__efiapi *wait_for_event)(unsigned long,
+ void *,
+ unsigned long *);
+ void *signal_event;
+ efi_status_t (__efiapi *close_event)(void);
+ void *check_event;
+ void *install_protocol_interface;
+ void *reinstall_protocol_interface;
+ void *uninstall_protocol_interface;
+ efi_status_t (__efiapi *handle_protocol)(efi_handle_t,
+ void *, void **);
+ void *__reserved;
+ void *register_protocol_notify;
+ efi_status_t (__efiapi *locate_handle)(int, void *,
+ void *, unsigned long *,
+ efi_handle_t *);
+ efi_status_t (__efiapi *locate_device_path)(void *,
+ efi_device_path_protocol_t **,
+ efi_handle_t *);
+ efi_status_t (__efiapi *install_configuration_table)(void *,
+ void *);
+ void *load_image;
+ void *start_image;
+ efi_status_t (__efiapi *exit)(efi_handle_t,
+ efi_status_t,
+ unsigned long,
+ efi_char16_t *);
+ void *unload_image;
+ efi_status_t (__efiapi *exit_boot_services)(efi_handle_t,
+ unsigned long);
+ void *get_next_monotonic_count;
+ efi_status_t (__efiapi *stall)(unsigned long);
+ void *set_watchdog_timer;
+ void *connect_controller;
+ efi_status_t (__efiapi *disconnect_controller)(efi_handle_t,
+ efi_handle_t,
+ efi_handle_t);
+ void *open_protocol;
+ void *close_protocol;
+ void *open_protocol_information;
+ void *protocols_per_handle;
+ void *locate_handle_buffer;
+ efi_status_t (__efiapi *locate_protocol)(void *, void *,
+ void **);
+ void *install_multiple_protocol_interfaces;
+ void *uninstall_multiple_protocol_interfaces;
+ void *calculate_crc32;
+ void *copy_mem;
+ void *set_mem;
+ void *create_event_ex;
+ };
+ struct {
+ efi_table_hdr_t hdr;
+ u32 raise_tpl;
+ u32 restore_tpl;
+ u32 allocate_pages;
+ u32 free_pages;
+ u32 get_memory_map;
+ u32 allocate_pool;
+ u32 free_pool;
+ u32 create_event;
+ u32 set_timer;
+ u32 wait_for_event;
+ u32 signal_event;
+ u32 close_event;
+ u32 check_event;
+ u32 install_protocol_interface;
+ u32 reinstall_protocol_interface;
+ u32 uninstall_protocol_interface;
+ u32 handle_protocol;
+ u32 __reserved;
+ u32 register_protocol_notify;
+ u32 locate_handle;
+ u32 locate_device_path;
+ u32 install_configuration_table;
+ u32 load_image;
+ u32 start_image;
+ u32 exit;
+ u32 unload_image;
+ u32 exit_boot_services;
+ u32 get_next_monotonic_count;
+ u32 stall;
+ u32 set_watchdog_timer;
+ u32 connect_controller;
+ u32 disconnect_controller;
+ u32 open_protocol;
+ u32 close_protocol;
+ u32 open_protocol_information;
+ u32 protocols_per_handle;
+ u32 locate_handle_buffer;
+ u32 locate_protocol;
+ u32 install_multiple_protocol_interfaces;
+ u32 uninstall_multiple_protocol_interfaces;
+ u32 calculate_crc32;
+ u32 copy_mem;
+ u32 set_mem;
+ u32 create_event_ex;
+ } mixed_mode;
+};
+
+typedef union efi_boot_services efi_boot_services_t;
+
+typedef struct {
+ efi_table_hdr_t hdr;
+ u64 fw_vendor; /* physical addr of CHAR16 vendor string */
+ u32 fw_revision;
+ u32 __pad1;
+ u64 con_in_handle;
+ u64 con_in;
+ u64 con_out_handle;
+ u64 con_out;
+ u64 stderr_handle;
+ u64 stderr;
+ u64 runtime;
+ u64 boottime;
+ u32 nr_tables;
+ u32 __pad2;
+ u64 tables;
+} efi_system_table_64_t;
+
+typedef struct {
+ efi_table_hdr_t hdr;
+ u32 fw_vendor; /* physical addr of CHAR16 vendor string */
+ u32 fw_revision;
+ u32 con_in_handle;
+ u32 con_in;
+ u32 con_out_handle;
+ u32 con_out;
+ u32 stderr_handle;
+ u32 stderr;
+ u32 runtime;
+ u32 boottime;
+ u32 nr_tables;
+ u32 tables;
+} efi_system_table_32_t;
+
+typedef union {
+ struct {
+ efi_table_hdr_t hdr;
+ unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */
+ u32 fw_revision;
+ unsigned long con_in_handle;
+ efi_simple_text_input_protocol_t *con_in;
+ unsigned long con_out_handle;
+ efi_simple_text_output_protocol_t *con_out;
+ unsigned long stderr_handle;
+ unsigned long stderr;
+ void *runtime;
+ efi_boot_services_t *boottime;
+ unsigned long nr_tables;
+ unsigned long tables;
+ };
+ efi_system_table_32_t mixed_mode;
+} efi_system_table_t;
+
+/*
+ * Memory map descriptor:
+ */
+
+/* Memory types: */
+#define EFI_RESERVED_TYPE 0
+#define EFI_LOADER_CODE 1
+#define EFI_LOADER_DATA 2
+#define EFI_BOOT_SERVICES_CODE 3
+#define EFI_BOOT_SERVICES_DATA 4
+#define EFI_RUNTIME_SERVICES_CODE 5
+#define EFI_RUNTIME_SERVICES_DATA 6
+#define EFI_CONVENTIONAL_MEMORY 7
+#define EFI_UNUSABLE_MEMORY 8
+#define EFI_ACPI_RECLAIM_MEMORY 9
+#define EFI_ACPI_MEMORY_NVS 10
+#define EFI_MEMORY_MAPPED_IO 11
+#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12
+#define EFI_PAL_CODE 13
+#define EFI_PERSISTENT_MEMORY 14
+#define EFI_MAX_MEMORY_TYPE 15
+
+/* Attribute values: */
+#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */
+#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */
+#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */
+#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */
+#define EFI_MEMORY_UCE ((u64)0x0000000000000010ULL) /* uncached, exported */
+#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */
+#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */
+#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */
+#define EFI_MEMORY_NV ((u64)0x0000000000008000ULL) /* non-volatile */
+#define EFI_MEMORY_MORE_RELIABLE \
+ ((u64)0x0000000000010000ULL) /* higher reliability */
+#define EFI_MEMORY_RO ((u64)0x0000000000020000ULL) /* read-only */
+#define EFI_MEMORY_SP ((u64)0x0000000000040000ULL) /* soft reserved */
+#define EFI_MEMORY_CPU_CRYPTO ((u64)0x0000000000080000ULL) /* supports encryption */
+#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */
+#define EFI_MEMORY_DESCRIPTOR_VERSION 1
+
+#define EFI_PAGE_SHIFT 12
+#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT)
+#define EFI_PAGES_MAX (U64_MAX >> EFI_PAGE_SHIFT)
+
+typedef struct {
+ u32 type;
+ u32 pad;
+ u64 phys_addr;
+ u64 virt_addr;
+ u64 num_pages;
+ u64 attribute;
+} efi_memory_desc_t;
+
+struct efi_boot_memmap {
+ efi_memory_desc_t **map;
+ unsigned long *map_size;
+ unsigned long *desc_size;
+ u32 *desc_ver;
+ unsigned long *key_ptr;
+ unsigned long *buff_size;
+};
+
+#define efi_bs_call(func, ...) \
+ efi_system_table->boottime->func(__VA_ARGS__)
+
+#endif /* __LINUX_UEFI_H */
diff --git a/x86/Makefile.common b/x86/Makefile.common
index 837a8a5..98d8de9 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -50,7 +50,7 @@ FLATLIBS = lib/libcflat.a
$(OBJCOPY) -O elf32-i386 $^ $@
@chmod a-x $@
-%.so: %.o $(FLATLIBS) $(cstart.o)
+%.so: %.o $(FLATLIBS) $(TEST_DIR)/efi_main.o $(cstart.o)
$(LD) -shared -nostdlib -znocombreloc -Bsymbolic -T $(SRCDIR)/x86/efi.lds $^ \
-o $@ $(FLATLIBS)
@chmod a-x $@
diff --git a/x86/cstart64.S b/x86/cstart64.S
index 404fcac..98e7848 100644
--- a/x86/cstart64.S
+++ b/x86/cstart64.S
@@ -267,7 +267,15 @@ ap_start64:
#ifdef CONFIG_EFI
.globl _efi_pe_entry
_efi_pe_entry:
- ret
+ # EFI image loader calls this with rcx=efi_handle,
+ # rdx=efi_system_table. Pass these to efi_main.
+ mov %rcx, %rdi
+ mov %rdx, %rsi
+
+ pushq %rdi
+ pushq %rsi
+
+ call efi_main
#endif
start64:
diff --git a/x86/efi_main.c b/x86/efi_main.c
new file mode 100644
index 0000000..00e7086
--- /dev/null
+++ b/x86/efi_main.c
@@ -0,0 +1,11 @@
+#include <linux/uefi.h>
+
+unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab);
+efi_system_table_t *efi_system_table = NULL;
+
+unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab)
+{
+ efi_system_table = sys_tab;
+
+ return 0;
+}
--
2.30.2
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [kvm-unit-tests PATCH 3/6] x86: efi_main: Get EFI memory map and exit boot services
2021-07-02 11:48 ` Varad Gautam via Virtualization
@ 2021-07-02 11:48 ` Varad Gautam via Virtualization
-1 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam @ 2021-07-02 11:48 UTC (permalink / raw)
To: kvm, virtualization
Cc: pbonzini, drjones, jroedel, bp, thomas.lendacky, brijesh.singh,
varad.gautam
The largest EFI_CONVENTIONAL_MEMORY chunk is passed over to
alloc_phys for the testcase.
Signed-off-by: Varad Gautam <varad.gautam@suse.com>
---
x86/efi_main.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
diff --git a/x86/efi_main.c b/x86/efi_main.c
index 00e7086..237d4e7 100644
--- a/x86/efi_main.c
+++ b/x86/efi_main.c
@@ -1,11 +1,103 @@
+#include <alloc_phys.h>
#include <linux/uefi.h>
unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab);
efi_system_table_t *efi_system_table = NULL;
+static void efi_free_pool(void *ptr)
+{
+ efi_bs_call(free_pool, ptr);
+}
+
+static efi_status_t efi_get_memory_map(struct efi_boot_memmap *map)
+{
+ efi_memory_desc_t *m = NULL;
+ efi_status_t status;
+ unsigned long key = 0, map_size = 0, desc_size = 0;
+
+ status = efi_bs_call(get_memory_map, &map_size,
+ NULL, &key, &desc_size, NULL);
+ if (status != EFI_BUFFER_TOO_SMALL || map_size == 0)
+ goto out;
+
+ /* Pad map_size with additional descriptors so we don't need to
+ * retry. */
+ map_size += 4 * desc_size;
+ *map->buff_size = map_size;
+ status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
+ map_size, (void **)&m);
+ if (status != EFI_SUCCESS)
+ goto out;
+
+ /* Get the map. */
+ status = efi_bs_call(get_memory_map, &map_size,
+ m, &key, &desc_size, NULL);
+ if (status != EFI_SUCCESS) {
+ efi_free_pool(m);
+ goto out;
+ }
+
+ *map->desc_size = desc_size;
+ *map->map_size = map_size;
+ *map->key_ptr = key;
+out:
+ *map->map = m;
+ return status;
+}
+
+static efi_status_t efi_exit_boot_services(void *handle,
+ struct efi_boot_memmap *map)
+{
+ return efi_bs_call(exit_boot_services, handle, *map->key_ptr);
+}
+
+static efi_status_t exit_efi(void *handle)
+{
+ unsigned long map_size = 0, key = 0, desc_size = 0, buff_size;
+ efi_memory_desc_t *mem_map, *md, *conventional = NULL;
+ efi_status_t status;
+ unsigned num_ents, i;
+ unsigned long pages = 0;
+ struct efi_boot_memmap map;
+
+ map.map = &mem_map;
+ map.map_size = &map_size;
+ map.desc_size = &desc_size;
+ map.desc_ver = NULL;
+ map.key_ptr = &key;
+ map.buff_size = &buff_size;
+
+ status = efi_get_memory_map(&map);
+ if (status != EFI_SUCCESS)
+ return status;
+
+ status = efi_exit_boot_services(handle, &map);
+ if (status != EFI_SUCCESS) {
+ efi_free_pool(mem_map);
+ return status;
+ }
+
+ /* Use the largest EFI_CONVENTIONAL_MEMORY range for phys_alloc_init. */
+ num_ents = map_size / desc_size;
+ for (i = 0; i < num_ents; i++) {
+ md = (efi_memory_desc_t *) (((u8 *) mem_map) + i * (desc_size));
+
+ if (md->type == EFI_CONVENTIONAL_MEMORY && md->num_pages > pages) {
+ conventional = md;
+ pages = md->num_pages;
+ }
+ }
+ phys_alloc_init(conventional->phys_addr,
+ conventional->num_pages << EFI_PAGE_SHIFT);
+
+ return EFI_SUCCESS;
+}
+
unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab)
{
efi_system_table = sys_tab;
+ exit_efi(handle);
+
return 0;
}
--
2.30.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [kvm-unit-tests PATCH 3/6] x86: efi_main: Get EFI memory map and exit boot services
@ 2021-07-02 11:48 ` Varad Gautam via Virtualization
0 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam via Virtualization @ 2021-07-02 11:48 UTC (permalink / raw)
To: kvm, virtualization
Cc: thomas.lendacky, drjones, jroedel, brijesh.singh, pbonzini, bp
The largest EFI_CONVENTIONAL_MEMORY chunk is passed over to
alloc_phys for the testcase.
Signed-off-by: Varad Gautam <varad.gautam@suse.com>
---
x86/efi_main.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
diff --git a/x86/efi_main.c b/x86/efi_main.c
index 00e7086..237d4e7 100644
--- a/x86/efi_main.c
+++ b/x86/efi_main.c
@@ -1,11 +1,103 @@
+#include <alloc_phys.h>
#include <linux/uefi.h>
unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab);
efi_system_table_t *efi_system_table = NULL;
+static void efi_free_pool(void *ptr)
+{
+ efi_bs_call(free_pool, ptr);
+}
+
+static efi_status_t efi_get_memory_map(struct efi_boot_memmap *map)
+{
+ efi_memory_desc_t *m = NULL;
+ efi_status_t status;
+ unsigned long key = 0, map_size = 0, desc_size = 0;
+
+ status = efi_bs_call(get_memory_map, &map_size,
+ NULL, &key, &desc_size, NULL);
+ if (status != EFI_BUFFER_TOO_SMALL || map_size == 0)
+ goto out;
+
+ /* Pad map_size with additional descriptors so we don't need to
+ * retry. */
+ map_size += 4 * desc_size;
+ *map->buff_size = map_size;
+ status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
+ map_size, (void **)&m);
+ if (status != EFI_SUCCESS)
+ goto out;
+
+ /* Get the map. */
+ status = efi_bs_call(get_memory_map, &map_size,
+ m, &key, &desc_size, NULL);
+ if (status != EFI_SUCCESS) {
+ efi_free_pool(m);
+ goto out;
+ }
+
+ *map->desc_size = desc_size;
+ *map->map_size = map_size;
+ *map->key_ptr = key;
+out:
+ *map->map = m;
+ return status;
+}
+
+static efi_status_t efi_exit_boot_services(void *handle,
+ struct efi_boot_memmap *map)
+{
+ return efi_bs_call(exit_boot_services, handle, *map->key_ptr);
+}
+
+static efi_status_t exit_efi(void *handle)
+{
+ unsigned long map_size = 0, key = 0, desc_size = 0, buff_size;
+ efi_memory_desc_t *mem_map, *md, *conventional = NULL;
+ efi_status_t status;
+ unsigned num_ents, i;
+ unsigned long pages = 0;
+ struct efi_boot_memmap map;
+
+ map.map = &mem_map;
+ map.map_size = &map_size;
+ map.desc_size = &desc_size;
+ map.desc_ver = NULL;
+ map.key_ptr = &key;
+ map.buff_size = &buff_size;
+
+ status = efi_get_memory_map(&map);
+ if (status != EFI_SUCCESS)
+ return status;
+
+ status = efi_exit_boot_services(handle, &map);
+ if (status != EFI_SUCCESS) {
+ efi_free_pool(mem_map);
+ return status;
+ }
+
+ /* Use the largest EFI_CONVENTIONAL_MEMORY range for phys_alloc_init. */
+ num_ents = map_size / desc_size;
+ for (i = 0; i < num_ents; i++) {
+ md = (efi_memory_desc_t *) (((u8 *) mem_map) + i * (desc_size));
+
+ if (md->type == EFI_CONVENTIONAL_MEMORY && md->num_pages > pages) {
+ conventional = md;
+ pages = md->num_pages;
+ }
+ }
+ phys_alloc_init(conventional->phys_addr,
+ conventional->num_pages << EFI_PAGE_SHIFT);
+
+ return EFI_SUCCESS;
+}
+
unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab)
{
efi_system_table = sys_tab;
+ exit_efi(handle);
+
return 0;
}
--
2.30.2
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [kvm-unit-tests PATCH 4/6] x86: efi_main: Self-relocate ELF .dynamic addresses
2021-07-02 11:48 ` Varad Gautam via Virtualization
@ 2021-07-02 11:48 ` Varad Gautam via Virtualization
-1 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam @ 2021-07-02 11:48 UTC (permalink / raw)
To: kvm, virtualization
Cc: pbonzini, drjones, jroedel, bp, thomas.lendacky, brijesh.singh,
varad.gautam
EFI expects a relocatable PE, and the loader will patch in the
relocations from the COFF.
Since we are wrapping an ELF into a PE here, the EFI loader will
not handle ELF relocations, and we need to patch the ELF .dynamic
section manually on early boot.
Signed-off-by: Varad Gautam <varad.gautam@suse.com>
---
x86/efi_main.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/x86/efi_main.c b/x86/efi_main.c
index 237d4e7..be3f9ab 100644
--- a/x86/efi_main.c
+++ b/x86/efi_main.c
@@ -1,9 +1,13 @@
#include <alloc_phys.h>
#include <linux/uefi.h>
+#include <elf.h>
unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab);
efi_system_table_t *efi_system_table = NULL;
+extern char ImageBase;
+extern char _DYNAMIC;
+
static void efi_free_pool(void *ptr)
{
efi_bs_call(free_pool, ptr);
@@ -93,11 +97,70 @@ static efi_status_t exit_efi(void *handle)
return EFI_SUCCESS;
}
+static efi_status_t elf_reloc(unsigned long image_base, unsigned long dynamic)
+{
+ long relsz = 0, relent = 0;
+ Elf64_Rel *rel = 0;
+ Elf64_Dyn *dyn = (Elf64_Dyn *) dynamic;
+ unsigned long *addr;
+ int i;
+
+ for (i = 0; dyn[i].d_tag != DT_NULL; i++) {
+ switch (dyn[i].d_tag) {
+ case DT_RELA:
+ rel = (Elf64_Rel *)
+ ((unsigned long) dyn[i].d_un.d_ptr + image_base);
+ 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 (ELF64_R_TYPE (rel->r_info)) {
+ case R_X86_64_NONE:
+ break;
+ case R_X86_64_RELATIVE:
+ addr = (unsigned long *) (image_base + rel->r_offset);
+ *addr += image_base;
+ break;
+ default:
+ break;
+ }
+ rel = (Elf64_Rel *) ((char *) rel + relent);
+ relsz -= relent;
+ }
+ return EFI_SUCCESS;
+}
+
unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab)
{
+ unsigned long image_base, dyn;
efi_system_table = sys_tab;
exit_efi(handle);
+ image_base = (unsigned long) &ImageBase;
+ dyn = image_base + (unsigned long) &_DYNAMIC;
+
+ /* The EFI loader does not handle ELF relocations, so fixup
+ * .dynamic addresses before proceeding any further. */
+ elf_reloc(image_base, dyn);
+
+ start64();
+
return 0;
}
--
2.30.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [kvm-unit-tests PATCH 4/6] x86: efi_main: Self-relocate ELF .dynamic addresses
@ 2021-07-02 11:48 ` Varad Gautam via Virtualization
0 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam via Virtualization @ 2021-07-02 11:48 UTC (permalink / raw)
To: kvm, virtualization
Cc: thomas.lendacky, drjones, jroedel, brijesh.singh, pbonzini, bp
EFI expects a relocatable PE, and the loader will patch in the
relocations from the COFF.
Since we are wrapping an ELF into a PE here, the EFI loader will
not handle ELF relocations, and we need to patch the ELF .dynamic
section manually on early boot.
Signed-off-by: Varad Gautam <varad.gautam@suse.com>
---
x86/efi_main.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/x86/efi_main.c b/x86/efi_main.c
index 237d4e7..be3f9ab 100644
--- a/x86/efi_main.c
+++ b/x86/efi_main.c
@@ -1,9 +1,13 @@
#include <alloc_phys.h>
#include <linux/uefi.h>
+#include <elf.h>
unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab);
efi_system_table_t *efi_system_table = NULL;
+extern char ImageBase;
+extern char _DYNAMIC;
+
static void efi_free_pool(void *ptr)
{
efi_bs_call(free_pool, ptr);
@@ -93,11 +97,70 @@ static efi_status_t exit_efi(void *handle)
return EFI_SUCCESS;
}
+static efi_status_t elf_reloc(unsigned long image_base, unsigned long dynamic)
+{
+ long relsz = 0, relent = 0;
+ Elf64_Rel *rel = 0;
+ Elf64_Dyn *dyn = (Elf64_Dyn *) dynamic;
+ unsigned long *addr;
+ int i;
+
+ for (i = 0; dyn[i].d_tag != DT_NULL; i++) {
+ switch (dyn[i].d_tag) {
+ case DT_RELA:
+ rel = (Elf64_Rel *)
+ ((unsigned long) dyn[i].d_un.d_ptr + image_base);
+ 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 (ELF64_R_TYPE (rel->r_info)) {
+ case R_X86_64_NONE:
+ break;
+ case R_X86_64_RELATIVE:
+ addr = (unsigned long *) (image_base + rel->r_offset);
+ *addr += image_base;
+ break;
+ default:
+ break;
+ }
+ rel = (Elf64_Rel *) ((char *) rel + relent);
+ relsz -= relent;
+ }
+ return EFI_SUCCESS;
+}
+
unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab)
{
+ unsigned long image_base, dyn;
efi_system_table = sys_tab;
exit_efi(handle);
+ image_base = (unsigned long) &ImageBase;
+ dyn = image_base + (unsigned long) &_DYNAMIC;
+
+ /* The EFI loader does not handle ELF relocations, so fixup
+ * .dynamic addresses before proceeding any further. */
+ elf_reloc(image_base, dyn);
+
+ start64();
+
return 0;
}
--
2.30.2
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [kvm-unit-tests PATCH 5/6] cstart64.S: x86_64 bootstrapping after exiting EFI
2021-07-02 11:48 ` Varad Gautam via Virtualization
@ 2021-07-02 11:48 ` Varad Gautam via Virtualization
-1 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam @ 2021-07-02 11:48 UTC (permalink / raw)
To: kvm, virtualization
Cc: pbonzini, drjones, jroedel, bp, thomas.lendacky, brijesh.singh,
varad.gautam
EFI sets up long mode with arbitrary state before calling the
image entrypoint. To run the testcases at hand, it is necessary
to redo some of the bootstrapping to not rely on what EFI
provided.
Adapt start64() for EFI testcases to fixup %rsp/GDT/IDT/TSS and
friends, and jump here after relocation from efi_main. Switch to
RIP-relative addressing where necessary.
Initially leave out:
- AP init - leave EFI to single CPU
- Testcase arg passing
Signed-off-by: Varad Gautam <varad.gautam@suse.com>
---
x86/cstart64.S | 57 ++++++++++++++++++++++++++++++++++++++++++++------
x86/efi_main.c | 1 +
2 files changed, 52 insertions(+), 6 deletions(-)
diff --git a/x86/cstart64.S b/x86/cstart64.S
index 98e7848..d4448c2 100644
--- a/x86/cstart64.S
+++ b/x86/cstart64.S
@@ -242,16 +242,17 @@ ap_start32:
.code64
save_id:
-#ifndef CONFIG_EFI
movl $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
movl (%rax), %eax
shrl $24, %eax
+#ifdef CONFIG_EFI
+ lock btsl %eax, online_cpus(%rip)
+#else
lock btsl %eax, online_cpus
#endif
retq
ap_start64:
-#ifndef CONFIG_EFI
call reset_apic
call load_tss
call enable_apic
@@ -259,12 +260,37 @@ ap_start64:
call enable_x2apic
sti
nop
+#ifdef CONFIG_EFI
+ lock incw cpu_online_count(%rip)
+#else
lock incw cpu_online_count
#endif
+
1: hlt
jmp 1b
#ifdef CONFIG_EFI
+setup_gdt64:
+ lgdt gdt64_desc(%rip)
+
+ setup_segments
+
+ movabsq $flush_cs, %rax
+ pushq $0x8
+ pushq %rax
+ retfq
+flush_cs:
+ ret
+
+setup_idt64:
+ lidtq idt_descr(%rip)
+ ret
+
+setup_cr3:
+ movabsq $ptl4, %rax
+ mov %rax, %cr3
+ ret
+
.globl _efi_pe_entry
_efi_pe_entry:
# EFI image loader calls this with rcx=efi_handle,
@@ -276,15 +302,25 @@ _efi_pe_entry:
pushq %rsi
call efi_main
-#endif
+.globl start64
start64:
-#ifndef CONFIG_EFI
+ cli
+ lea stacktop(%rip), %rsp
+
+ setup_percpu_area
+ call setup_gdt64
+ call setup_idt64
+ call setup_cr3
+#else
+start64:
+#endif
call reset_apic
call load_tss
call mask_pic_interrupts
call enable_apic
call save_id
+#ifndef CONFIG_EFI
mov mb_boot_info(%rip), %rbx
mov %rbx, %rdi
call setup_multiboot
@@ -292,18 +328,24 @@ start64:
mov mb_cmdline(%rbx), %eax
mov %rax, __args(%rip)
call __setup_args
+#endif
call ap_init
call enable_x2apic
call smp_init
+#ifdef CONFIG_EFI
+ mov $0, %edi
+ mov $0, %rsi
+ mov $0, %rdx
+#else
mov __argc(%rip), %edi
lea __argv(%rip), %rsi
lea __environ(%rip), %rdx
+#endif
call main
mov %eax, %edi
call exit
-#endif
.globl setup_5level_page_table
setup_5level_page_table:
@@ -328,7 +370,10 @@ online_cpus:
.fill (max_cpus + 7) / 8, 1, 0
load_tss:
-#ifndef CONFIG_EFI
+#ifdef CONFIG_EFI
+ mov $(tss_descr - gdt64), %rax
+ ltr %ax
+#else
lidtq idt_descr
mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
mov (%rax), %eax
diff --git a/x86/efi_main.c b/x86/efi_main.c
index be3f9ab..c542fb9 100644
--- a/x86/efi_main.c
+++ b/x86/efi_main.c
@@ -7,6 +7,7 @@ efi_system_table_t *efi_system_table = NULL;
extern char ImageBase;
extern char _DYNAMIC;
+extern void start64(void);
static void efi_free_pool(void *ptr)
{
--
2.30.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [kvm-unit-tests PATCH 5/6] cstart64.S: x86_64 bootstrapping after exiting EFI
@ 2021-07-02 11:48 ` Varad Gautam via Virtualization
0 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam via Virtualization @ 2021-07-02 11:48 UTC (permalink / raw)
To: kvm, virtualization
Cc: thomas.lendacky, drjones, jroedel, brijesh.singh, pbonzini, bp
EFI sets up long mode with arbitrary state before calling the
image entrypoint. To run the testcases at hand, it is necessary
to redo some of the bootstrapping to not rely on what EFI
provided.
Adapt start64() for EFI testcases to fixup %rsp/GDT/IDT/TSS and
friends, and jump here after relocation from efi_main. Switch to
RIP-relative addressing where necessary.
Initially leave out:
- AP init - leave EFI to single CPU
- Testcase arg passing
Signed-off-by: Varad Gautam <varad.gautam@suse.com>
---
x86/cstart64.S | 57 ++++++++++++++++++++++++++++++++++++++++++++------
x86/efi_main.c | 1 +
2 files changed, 52 insertions(+), 6 deletions(-)
diff --git a/x86/cstart64.S b/x86/cstart64.S
index 98e7848..d4448c2 100644
--- a/x86/cstart64.S
+++ b/x86/cstart64.S
@@ -242,16 +242,17 @@ ap_start32:
.code64
save_id:
-#ifndef CONFIG_EFI
movl $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
movl (%rax), %eax
shrl $24, %eax
+#ifdef CONFIG_EFI
+ lock btsl %eax, online_cpus(%rip)
+#else
lock btsl %eax, online_cpus
#endif
retq
ap_start64:
-#ifndef CONFIG_EFI
call reset_apic
call load_tss
call enable_apic
@@ -259,12 +260,37 @@ ap_start64:
call enable_x2apic
sti
nop
+#ifdef CONFIG_EFI
+ lock incw cpu_online_count(%rip)
+#else
lock incw cpu_online_count
#endif
+
1: hlt
jmp 1b
#ifdef CONFIG_EFI
+setup_gdt64:
+ lgdt gdt64_desc(%rip)
+
+ setup_segments
+
+ movabsq $flush_cs, %rax
+ pushq $0x8
+ pushq %rax
+ retfq
+flush_cs:
+ ret
+
+setup_idt64:
+ lidtq idt_descr(%rip)
+ ret
+
+setup_cr3:
+ movabsq $ptl4, %rax
+ mov %rax, %cr3
+ ret
+
.globl _efi_pe_entry
_efi_pe_entry:
# EFI image loader calls this with rcx=efi_handle,
@@ -276,15 +302,25 @@ _efi_pe_entry:
pushq %rsi
call efi_main
-#endif
+.globl start64
start64:
-#ifndef CONFIG_EFI
+ cli
+ lea stacktop(%rip), %rsp
+
+ setup_percpu_area
+ call setup_gdt64
+ call setup_idt64
+ call setup_cr3
+#else
+start64:
+#endif
call reset_apic
call load_tss
call mask_pic_interrupts
call enable_apic
call save_id
+#ifndef CONFIG_EFI
mov mb_boot_info(%rip), %rbx
mov %rbx, %rdi
call setup_multiboot
@@ -292,18 +328,24 @@ start64:
mov mb_cmdline(%rbx), %eax
mov %rax, __args(%rip)
call __setup_args
+#endif
call ap_init
call enable_x2apic
call smp_init
+#ifdef CONFIG_EFI
+ mov $0, %edi
+ mov $0, %rsi
+ mov $0, %rdx
+#else
mov __argc(%rip), %edi
lea __argv(%rip), %rsi
lea __environ(%rip), %rdx
+#endif
call main
mov %eax, %edi
call exit
-#endif
.globl setup_5level_page_table
setup_5level_page_table:
@@ -328,7 +370,10 @@ online_cpus:
.fill (max_cpus + 7) / 8, 1, 0
load_tss:
-#ifndef CONFIG_EFI
+#ifdef CONFIG_EFI
+ mov $(tss_descr - gdt64), %rax
+ ltr %ax
+#else
lidtq idt_descr
mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
mov (%rax), %eax
diff --git a/x86/efi_main.c b/x86/efi_main.c
index be3f9ab..c542fb9 100644
--- a/x86/efi_main.c
+++ b/x86/efi_main.c
@@ -7,6 +7,7 @@ efi_system_table_t *efi_system_table = NULL;
extern char ImageBase;
extern char _DYNAMIC;
+extern void start64(void);
static void efi_free_pool(void *ptr)
{
--
2.30.2
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [kvm-unit-tests PATCH 6/6] x86: Disable some breaking tests for EFI and modify vmexit test
2021-07-02 11:48 ` Varad Gautam via Virtualization
@ 2021-07-02 11:48 ` Varad Gautam via Virtualization
-1 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam @ 2021-07-02 11:48 UTC (permalink / raw)
To: kvm, virtualization
Cc: pbonzini, drjones, jroedel, bp, thomas.lendacky, brijesh.singh,
varad.gautam
Disable some tests from building on EFI. These fail early, and need some
adaptation (eg. inline asm changes / AP initialization / memory
reclamation from EFI).
Eg, asyncpf: runs out of memory since the allocator only uses the largest
EFI_CONVENTIONAL_MEMORY block.
hyperv_*: untested with EFI.
vmexit: breaks since test arg passing isn't enabled - enable it except for
pci-* cases since iomem needs more fixups.
Signed-off-by: Varad Gautam <varad.gautam@suse.com>
---
x86/Makefile.common | 21 +++++++++++----------
x86/vmexit.c | 7 +++++++
2 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/x86/Makefile.common b/x86/Makefile.common
index 98d8de9..b995a67 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -62,17 +62,18 @@ FLATLIBS = lib/libcflat.a
@chmod a-x $@
tests-flatonly = $(TEST_DIR)/realmode.$(out) $(TEST_DIR)/eventinj.$(out) \
- $(TEST_DIR)/smap.$(out) $(TEST_DIR)/umip.$(out)
-
-tests-common = $(TEST_DIR)/vmexit.$(out) $(TEST_DIR)/tsc.$(out) \
- $(TEST_DIR)/smptest.$(out) $(TEST_DIR)/msr.$(out) \
- $(TEST_DIR)/hypercall.$(out) $(TEST_DIR)/sieve.$(out) \
- $(TEST_DIR)/kvmclock_test.$(out) $(TEST_DIR)/s3.$(out) \
+ $(TEST_DIR)/smap.$(out) $(TEST_DIR)/umip.$(out) \
+ $(TEST_DIR)/kvmclock_test.$(out) $(TEST_DIR)/hypercall.$(out) \
+ $(TEST_DIR)/init.$(out) \
+ $(TEST_DIR)/asyncpf.$(out) $(TEST_DIR)/hyperv_synic.$(out) \
+ $(TEST_DIR)/hyperv_stimer.$(out) $(TEST_DIR)/hyperv_connections.$(out)
+
+tests-common = $(TEST_DIR)/tsc.$(out) $(TEST_DIR)/smptest.$(out) \
+ $(TEST_DIR)/msr.$(out) $(TEST_DIR)/sieve.$(out) \
+ $(TEST_DIR)/sieve.$(out) $(TEST_DIR)/s3.$(out) \
$(TEST_DIR)/pmu.$(out) $(TEST_DIR)/setjmp.$(out) \
- $(TEST_DIR)/tsc_adjust.$(out) $(TEST_DIR)/asyncpf.$(out) \
- $(TEST_DIR)/init.$(out) $(TEST_DIR)/hyperv_synic.$(out) \
- $(TEST_DIR)/hyperv_stimer.$(out) $(TEST_DIR)/hyperv_connections.$(out) \
- $(TEST_DIR)/tsx-ctrl.$(out)
+ $(TEST_DIR)/tsc_adjust.$(out) $(TEST_DIR)/tsx-ctrl.$(out) \
+ $(TEST_DIR)/vmexit.$(out)
ifneq ($(CONFIG_EFI),y)
tests-common += $(tests-flatonly)
diff --git a/x86/vmexit.c b/x86/vmexit.c
index 999babf..4062f7a 100644
--- a/x86/vmexit.c
+++ b/x86/vmexit.c
@@ -560,6 +560,12 @@ static void enable_nx(void *junk)
static bool test_wanted(struct test *test, char *wanted[], int nwanted)
{
+#ifdef CONFIG_EFI
+ if (strcmp(test->name, "pci-io") == 0 || strcmp(test->name, "pci-mem") == 0 )
+ return false;
+
+ return true;
+#else
int i;
if (!nwanted)
@@ -570,6 +576,7 @@ static bool test_wanted(struct test *test, char *wanted[], int nwanted)
return true;
return false;
+#endif
}
int main(int ac, char **av)
--
2.30.2
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [kvm-unit-tests PATCH 6/6] x86: Disable some breaking tests for EFI and modify vmexit test
@ 2021-07-02 11:48 ` Varad Gautam via Virtualization
0 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam via Virtualization @ 2021-07-02 11:48 UTC (permalink / raw)
To: kvm, virtualization
Cc: thomas.lendacky, drjones, jroedel, brijesh.singh, pbonzini, bp
Disable some tests from building on EFI. These fail early, and need some
adaptation (eg. inline asm changes / AP initialization / memory
reclamation from EFI).
Eg, asyncpf: runs out of memory since the allocator only uses the largest
EFI_CONVENTIONAL_MEMORY block.
hyperv_*: untested with EFI.
vmexit: breaks since test arg passing isn't enabled - enable it except for
pci-* cases since iomem needs more fixups.
Signed-off-by: Varad Gautam <varad.gautam@suse.com>
---
x86/Makefile.common | 21 +++++++++++----------
x86/vmexit.c | 7 +++++++
2 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/x86/Makefile.common b/x86/Makefile.common
index 98d8de9..b995a67 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -62,17 +62,18 @@ FLATLIBS = lib/libcflat.a
@chmod a-x $@
tests-flatonly = $(TEST_DIR)/realmode.$(out) $(TEST_DIR)/eventinj.$(out) \
- $(TEST_DIR)/smap.$(out) $(TEST_DIR)/umip.$(out)
-
-tests-common = $(TEST_DIR)/vmexit.$(out) $(TEST_DIR)/tsc.$(out) \
- $(TEST_DIR)/smptest.$(out) $(TEST_DIR)/msr.$(out) \
- $(TEST_DIR)/hypercall.$(out) $(TEST_DIR)/sieve.$(out) \
- $(TEST_DIR)/kvmclock_test.$(out) $(TEST_DIR)/s3.$(out) \
+ $(TEST_DIR)/smap.$(out) $(TEST_DIR)/umip.$(out) \
+ $(TEST_DIR)/kvmclock_test.$(out) $(TEST_DIR)/hypercall.$(out) \
+ $(TEST_DIR)/init.$(out) \
+ $(TEST_DIR)/asyncpf.$(out) $(TEST_DIR)/hyperv_synic.$(out) \
+ $(TEST_DIR)/hyperv_stimer.$(out) $(TEST_DIR)/hyperv_connections.$(out)
+
+tests-common = $(TEST_DIR)/tsc.$(out) $(TEST_DIR)/smptest.$(out) \
+ $(TEST_DIR)/msr.$(out) $(TEST_DIR)/sieve.$(out) \
+ $(TEST_DIR)/sieve.$(out) $(TEST_DIR)/s3.$(out) \
$(TEST_DIR)/pmu.$(out) $(TEST_DIR)/setjmp.$(out) \
- $(TEST_DIR)/tsc_adjust.$(out) $(TEST_DIR)/asyncpf.$(out) \
- $(TEST_DIR)/init.$(out) $(TEST_DIR)/hyperv_synic.$(out) \
- $(TEST_DIR)/hyperv_stimer.$(out) $(TEST_DIR)/hyperv_connections.$(out) \
- $(TEST_DIR)/tsx-ctrl.$(out)
+ $(TEST_DIR)/tsc_adjust.$(out) $(TEST_DIR)/tsx-ctrl.$(out) \
+ $(TEST_DIR)/vmexit.$(out)
ifneq ($(CONFIG_EFI),y)
tests-common += $(tests-flatonly)
diff --git a/x86/vmexit.c b/x86/vmexit.c
index 999babf..4062f7a 100644
--- a/x86/vmexit.c
+++ b/x86/vmexit.c
@@ -560,6 +560,12 @@ static void enable_nx(void *junk)
static bool test_wanted(struct test *test, char *wanted[], int nwanted)
{
+#ifdef CONFIG_EFI
+ if (strcmp(test->name, "pci-io") == 0 || strcmp(test->name, "pci-mem") == 0 )
+ return false;
+
+ return true;
+#else
int i;
if (!nwanted)
@@ -570,6 +576,7 @@ static bool test_wanted(struct test *test, char *wanted[], int nwanted)
return true;
return false;
+#endif
}
int main(int ac, char **av)
--
2.30.2
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
2021-07-02 11:48 ` Varad Gautam via Virtualization
@ 2021-07-12 16:29 ` Andrew Jones
-1 siblings, 0 replies; 32+ messages in thread
From: Andrew Jones @ 2021-07-12 16:29 UTC (permalink / raw)
To: Varad Gautam
Cc: kvm, virtualization, pbonzini, jroedel, bp, thomas.lendacky,
brijesh.singh
On Fri, Jul 02, 2021 at 01:48:14PM +0200, Varad Gautam wrote:
> This series brings EFI support to a reduced subset of kvm-unit-tests
> on x86_64. I'm sending it out for early review since it covers enough
> ground to allow adding KVM testcases for EFI-only environments.
>
> EFI support works by changing the test entrypoint to a stub entry
> point for the EFI loader to jump to in long mode, where the test binary
> exits EFI boot services, performs the remaining CPU bootstrapping,
> and then calls the testcase main().
>
> Since the EFI loader only understands PE objects, the first commit
> introduces a `configure --efi` mode which builds each test as a shared
> lib. This shared lib is repackaged into a PE via objdump.
>
> Commit 2-4 take a trip from the asm entrypoint to C to exit EFI and
> relocate ELF .dynamic contents.
>
> Commit 5 adds post-EFI long mode x86_64 setup and calls the testcase.
>
> Commit 6 patches out some broken tests for EFI. Testcases that refuse
> to build as shared libs are also left disabled, these need some massaging.
>
> git tree: https://github.com/varadgautam/kvm-unit-tests/commits/efi-stub
Hi Varad,
Thanks for this. I haven't reviewed it in detail yet (I just got back from
vacation), but this looks like the right approach. In fact, I had started
going down the efi stub approach for AArch64 a while back as well, but the
effort got preempted by other work [again]. I'll try to allocate time to
play with this for x86 and to build on it for AArch64 in the coming weeks.
drew
>
> Varad Gautam (6):
> x86: Build tests as PE objects for the EFI loader
> x86: Call efi_main from _efi_pe_entry
> x86: efi_main: Get EFI memory map and exit boot services
> x86: efi_main: Self-relocate ELF .dynamic addresses
> cstart64.S: x86_64 bootstrapping after exiting EFI
> x86: Disable some breaking tests for EFI and modify vmexit test
>
> .gitignore | 2 +
> Makefile | 16 ++-
> configure | 11 ++
> lib/linux/uefi.h | 337 ++++++++++++++++++++++++++++++++++++++++++++
> x86/Makefile.common | 45 ++++--
> x86/Makefile.x86_64 | 43 +++---
> x86/cstart64.S | 78 ++++++++++
> x86/efi.lds | 67 +++++++++
> x86/efi_main.c | 167 ++++++++++++++++++++++
> x86/vmexit.c | 7 +
> 10 files changed, 741 insertions(+), 32 deletions(-)
> create mode 100644 lib/linux/uefi.h
> create mode 100644 x86/efi.lds
> create mode 100644 x86/efi_main.c
>
> --
> 2.30.2
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
@ 2021-07-12 16:29 ` Andrew Jones
0 siblings, 0 replies; 32+ messages in thread
From: Andrew Jones @ 2021-07-12 16:29 UTC (permalink / raw)
To: Varad Gautam
Cc: thomas.lendacky, jroedel, brijesh.singh, kvm, virtualization,
pbonzini, bp
On Fri, Jul 02, 2021 at 01:48:14PM +0200, Varad Gautam wrote:
> This series brings EFI support to a reduced subset of kvm-unit-tests
> on x86_64. I'm sending it out for early review since it covers enough
> ground to allow adding KVM testcases for EFI-only environments.
>
> EFI support works by changing the test entrypoint to a stub entry
> point for the EFI loader to jump to in long mode, where the test binary
> exits EFI boot services, performs the remaining CPU bootstrapping,
> and then calls the testcase main().
>
> Since the EFI loader only understands PE objects, the first commit
> introduces a `configure --efi` mode which builds each test as a shared
> lib. This shared lib is repackaged into a PE via objdump.
>
> Commit 2-4 take a trip from the asm entrypoint to C to exit EFI and
> relocate ELF .dynamic contents.
>
> Commit 5 adds post-EFI long mode x86_64 setup and calls the testcase.
>
> Commit 6 patches out some broken tests for EFI. Testcases that refuse
> to build as shared libs are also left disabled, these need some massaging.
>
> git tree: https://github.com/varadgautam/kvm-unit-tests/commits/efi-stub
Hi Varad,
Thanks for this. I haven't reviewed it in detail yet (I just got back from
vacation), but this looks like the right approach. In fact, I had started
going down the efi stub approach for AArch64 a while back as well, but the
effort got preempted by other work [again]. I'll try to allocate time to
play with this for x86 and to build on it for AArch64 in the coming weeks.
drew
>
> Varad Gautam (6):
> x86: Build tests as PE objects for the EFI loader
> x86: Call efi_main from _efi_pe_entry
> x86: efi_main: Get EFI memory map and exit boot services
> x86: efi_main: Self-relocate ELF .dynamic addresses
> cstart64.S: x86_64 bootstrapping after exiting EFI
> x86: Disable some breaking tests for EFI and modify vmexit test
>
> .gitignore | 2 +
> Makefile | 16 ++-
> configure | 11 ++
> lib/linux/uefi.h | 337 ++++++++++++++++++++++++++++++++++++++++++++
> x86/Makefile.common | 45 ++++--
> x86/Makefile.x86_64 | 43 +++---
> x86/cstart64.S | 78 ++++++++++
> x86/efi.lds | 67 +++++++++
> x86/efi_main.c | 167 ++++++++++++++++++++++
> x86/vmexit.c | 7 +
> 10 files changed, 741 insertions(+), 32 deletions(-)
> create mode 100644 lib/linux/uefi.h
> create mode 100644 x86/efi.lds
> create mode 100644 x86/efi_main.c
>
> --
> 2.30.2
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
2021-07-02 11:48 ` Varad Gautam via Virtualization
` (7 preceding siblings ...)
(?)
@ 2021-08-13 18:44 ` Marc Orr
2021-08-16 7:26 ` Andrew Jones
2021-08-17 10:49 ` Joerg Roedel
-1 siblings, 2 replies; 32+ messages in thread
From: Marc Orr @ 2021-08-13 18:44 UTC (permalink / raw)
To: Varad Gautam
Cc: kvm list, virtualization, Paolo Bonzini, drjones, Joerg Roedel,
bp, Lendacky, Thomas, Singh, Brijesh, Zixuan Wang,
Hyunwook (Wooky) Baek, Erdem Aktas, Tom Roeder
On Fri, Jul 2, 2021 at 4:48 AM Varad Gautam <varad.gautam@suse.com> wrote:
>
> This series brings EFI support to a reduced subset of kvm-unit-tests
> on x86_64. I'm sending it out for early review since it covers enough
> ground to allow adding KVM testcases for EFI-only environments.
>
> EFI support works by changing the test entrypoint to a stub entry
> point for the EFI loader to jump to in long mode, where the test binary
> exits EFI boot services, performs the remaining CPU bootstrapping,
> and then calls the testcase main().
>
> Since the EFI loader only understands PE objects, the first commit
> introduces a `configure --efi` mode which builds each test as a shared
> lib. This shared lib is repackaged into a PE via objdump.
>
> Commit 2-4 take a trip from the asm entrypoint to C to exit EFI and
> relocate ELF .dynamic contents.
>
> Commit 5 adds post-EFI long mode x86_64 setup and calls the testcase.
>
> Commit 6 patches out some broken tests for EFI. Testcases that refuse
> to build as shared libs are also left disabled, these need some massaging.
>
> git tree: https://github.com/varadgautam/kvm-unit-tests/commits/efi-stub
Thanks for this patchset. My colleague, Zixuan Wang
<zixuanwang@google.com>, has also been working to extend
kvm-unit-tests to run under UEFI. Our goal is to enable running
kvm-unit-tests under SEV-ES.
Our approach is a bit different. Rather than pull in bits of the EFI
library and Linux EFI ABI, we've elected to build the entire
kvm-unit-tests binaries as an EFI app (similar to the ARM approach).
To date, we have _most_ x86 test cases (39/44) working under UEFI and
we've also got some of the test cases to boot under SEV-ES, using the
UEFI #VC handler.
We will post our patchset as soon as possible (hopefully by Monday) so
that the community can see our approach. We are very eager to see
kvm-unit-tests running under SEV-ES (and SNP) and are happy to work
with you all on either approach, depending on what the community
thinks is the best approach.
Thanks in advance,
Marc
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
2021-08-13 18:44 ` Marc Orr
@ 2021-08-16 7:26 ` Andrew Jones
2021-08-17 10:49 ` Joerg Roedel
1 sibling, 0 replies; 32+ messages in thread
From: Andrew Jones @ 2021-08-16 7:26 UTC (permalink / raw)
To: Marc Orr
Cc: Varad Gautam, kvm list, virtualization, Paolo Bonzini,
Joerg Roedel, bp, Lendacky, Thomas, Singh, Brijesh, Zixuan Wang,
Hyunwook (Wooky) Baek, Erdem Aktas, Tom Roeder
On Fri, Aug 13, 2021 at 11:44:39AM -0700, Marc Orr wrote:
> On Fri, Jul 2, 2021 at 4:48 AM Varad Gautam <varad.gautam@suse.com> wrote:
> >
> > This series brings EFI support to a reduced subset of kvm-unit-tests
> > on x86_64. I'm sending it out for early review since it covers enough
> > ground to allow adding KVM testcases for EFI-only environments.
> >
> > EFI support works by changing the test entrypoint to a stub entry
> > point for the EFI loader to jump to in long mode, where the test binary
> > exits EFI boot services, performs the remaining CPU bootstrapping,
> > and then calls the testcase main().
> >
> > Since the EFI loader only understands PE objects, the first commit
> > introduces a `configure --efi` mode which builds each test as a shared
> > lib. This shared lib is repackaged into a PE via objdump.
> >
> > Commit 2-4 take a trip from the asm entrypoint to C to exit EFI and
> > relocate ELF .dynamic contents.
> >
> > Commit 5 adds post-EFI long mode x86_64 setup and calls the testcase.
> >
> > Commit 6 patches out some broken tests for EFI. Testcases that refuse
> > to build as shared libs are also left disabled, these need some massaging.
> >
> > git tree: https://github.com/varadgautam/kvm-unit-tests/commits/efi-stub
>
> Thanks for this patchset. My colleague, Zixuan Wang
> <zixuanwang@google.com>, has also been working to extend
> kvm-unit-tests to run under UEFI. Our goal is to enable running
> kvm-unit-tests under SEV-ES.
>
> Our approach is a bit different. Rather than pull in bits of the EFI
> library and Linux EFI ABI, we've elected to build the entire
> kvm-unit-tests binaries as an EFI app (similar to the ARM approach).
>
> To date, we have _most_ x86 test cases (39/44) working under UEFI and
> we've also got some of the test cases to boot under SEV-ES, using the
> UEFI #VC handler.
>
> We will post our patchset as soon as possible (hopefully by Monday) so
> that the community can see our approach. We are very eager to see
> kvm-unit-tests running under SEV-ES (and SNP) and are happy to work
> with you all on either approach, depending on what the community
> thinks is the best approach.
>
> Thanks in advance,
> Marc
>
Hi Marc,
I'm definitely eager to see your approach. I was actually working on
a second version of EFI support for ARM using the stub approach like
this series before getting perpetually sidetracked. I've been wanted
to experiment with Varad's code to continue that, but haven't been
able to find the time. I'm curious if you considered the stub approach
as well, but then opted for the app approach in the end. I was
leaning towards the stub approach to avoid the gnu-efi dependency.
Thanks,
drew
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
@ 2021-08-16 7:26 ` Andrew Jones
0 siblings, 0 replies; 32+ messages in thread
From: Andrew Jones @ 2021-08-16 7:26 UTC (permalink / raw)
To: Marc Orr
Cc: Lendacky, Thomas, Joerg Roedel, Singh, Brijesh, kvm list,
Tom Roeder, Hyunwook (Wooky) Baek, virtualization, Zixuan Wang,
Erdem Aktas, Paolo Bonzini, bp
On Fri, Aug 13, 2021 at 11:44:39AM -0700, Marc Orr wrote:
> On Fri, Jul 2, 2021 at 4:48 AM Varad Gautam <varad.gautam@suse.com> wrote:
> >
> > This series brings EFI support to a reduced subset of kvm-unit-tests
> > on x86_64. I'm sending it out for early review since it covers enough
> > ground to allow adding KVM testcases for EFI-only environments.
> >
> > EFI support works by changing the test entrypoint to a stub entry
> > point for the EFI loader to jump to in long mode, where the test binary
> > exits EFI boot services, performs the remaining CPU bootstrapping,
> > and then calls the testcase main().
> >
> > Since the EFI loader only understands PE objects, the first commit
> > introduces a `configure --efi` mode which builds each test as a shared
> > lib. This shared lib is repackaged into a PE via objdump.
> >
> > Commit 2-4 take a trip from the asm entrypoint to C to exit EFI and
> > relocate ELF .dynamic contents.
> >
> > Commit 5 adds post-EFI long mode x86_64 setup and calls the testcase.
> >
> > Commit 6 patches out some broken tests for EFI. Testcases that refuse
> > to build as shared libs are also left disabled, these need some massaging.
> >
> > git tree: https://github.com/varadgautam/kvm-unit-tests/commits/efi-stub
>
> Thanks for this patchset. My colleague, Zixuan Wang
> <zixuanwang@google.com>, has also been working to extend
> kvm-unit-tests to run under UEFI. Our goal is to enable running
> kvm-unit-tests under SEV-ES.
>
> Our approach is a bit different. Rather than pull in bits of the EFI
> library and Linux EFI ABI, we've elected to build the entire
> kvm-unit-tests binaries as an EFI app (similar to the ARM approach).
>
> To date, we have _most_ x86 test cases (39/44) working under UEFI and
> we've also got some of the test cases to boot under SEV-ES, using the
> UEFI #VC handler.
>
> We will post our patchset as soon as possible (hopefully by Monday) so
> that the community can see our approach. We are very eager to see
> kvm-unit-tests running under SEV-ES (and SNP) and are happy to work
> with you all on either approach, depending on what the community
> thinks is the best approach.
>
> Thanks in advance,
> Marc
>
Hi Marc,
I'm definitely eager to see your approach. I was actually working on
a second version of EFI support for ARM using the stub approach like
this series before getting perpetually sidetracked. I've been wanted
to experiment with Varad's code to continue that, but haven't been
able to find the time. I'm curious if you considered the stub approach
as well, but then opted for the app approach in the end. I was
leaning towards the stub approach to avoid the gnu-efi dependency.
Thanks,
drew
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
2021-08-16 7:26 ` Andrew Jones
(?)
@ 2021-08-17 3:41 ` Marc Orr
-1 siblings, 0 replies; 32+ messages in thread
From: Marc Orr @ 2021-08-17 3:41 UTC (permalink / raw)
To: Andrew Jones
Cc: Varad Gautam, kvm list, virtualization, Paolo Bonzini,
Joerg Roedel, bp, Lendacky, Thomas, Singh, Brijesh, Zixuan Wang,
Hyunwook (Wooky) Baek, Erdem Aktas, Tom Roeder
On Mon, Aug 16, 2021 at 12:26 AM Andrew Jones <drjones@redhat.com> wrote:
>
> On Fri, Aug 13, 2021 at 11:44:39AM -0700, Marc Orr wrote:
> > On Fri, Jul 2, 2021 at 4:48 AM Varad Gautam <varad.gautam@suse.com> wrote:
> > >
> > > This series brings EFI support to a reduced subset of kvm-unit-tests
> > > on x86_64. I'm sending it out for early review since it covers enough
> > > ground to allow adding KVM testcases for EFI-only environments.
> > >
> > > EFI support works by changing the test entrypoint to a stub entry
> > > point for the EFI loader to jump to in long mode, where the test binary
> > > exits EFI boot services, performs the remaining CPU bootstrapping,
> > > and then calls the testcase main().
> > >
> > > Since the EFI loader only understands PE objects, the first commit
> > > introduces a `configure --efi` mode which builds each test as a shared
> > > lib. This shared lib is repackaged into a PE via objdump.
> > >
> > > Commit 2-4 take a trip from the asm entrypoint to C to exit EFI and
> > > relocate ELF .dynamic contents.
> > >
> > > Commit 5 adds post-EFI long mode x86_64 setup and calls the testcase.
> > >
> > > Commit 6 patches out some broken tests for EFI. Testcases that refuse
> > > to build as shared libs are also left disabled, these need some massaging.
> > >
> > > git tree: https://github.com/varadgautam/kvm-unit-tests/commits/efi-stub
> >
> > Thanks for this patchset. My colleague, Zixuan Wang
> > <zixuanwang@google.com>, has also been working to extend
> > kvm-unit-tests to run under UEFI. Our goal is to enable running
> > kvm-unit-tests under SEV-ES.
> >
> > Our approach is a bit different. Rather than pull in bits of the EFI
> > library and Linux EFI ABI, we've elected to build the entire
> > kvm-unit-tests binaries as an EFI app (similar to the ARM approach).
> >
> > To date, we have _most_ x86 test cases (39/44) working under UEFI and
> > we've also got some of the test cases to boot under SEV-ES, using the
> > UEFI #VC handler.
> >
> > We will post our patchset as soon as possible (hopefully by Monday) so
> > that the community can see our approach. We are very eager to see
> > kvm-unit-tests running under SEV-ES (and SNP) and are happy to work
> > with you all on either approach, depending on what the community
> > thinks is the best approach.
> >
> > Thanks in advance,
> > Marc
> >
>
> Hi Marc,
>
> I'm definitely eager to see your approach. I was actually working on
> a second version of EFI support for ARM using the stub approach like
> this series before getting perpetually sidetracked. I've been wanted
> to experiment with Varad's code to continue that, but haven't been
> able to find the time. I'm curious if you considered the stub approach
> as well, but then opted for the app approach in the end. I was
> leaning towards the stub approach to avoid the gnu-efi dependency.
Ack. We never seriously contemplated the stub approach. In hindsight,
I think we were probably biased towards the EFI app approach because
we have some test cases running as UEFI EFI apps internally with great
success (not using the kvm-unit-tests framework though). That being
said, I agree that avoiding the gnu-efi dependency is a win. I also
asked Zixuan, who wrote our patches, if he had an opinion on this. He
said that GNU-EFI provides useful set up code and library functions,
so we do not have to re-implement and debug them in KVM-Unit-Tests.
In any case, we have the patchset ready to post. However, Zixuan ran
into some permission issues when he tried to post the patches because
they are outside of our corporate domain. We'll try to get these
permissions issues fixed up and post the patches tomorrow. If we
cannot get them fixed up, I can always post the patches on his behalf.
Also, we will spend some more time reading Varad's patches this week,
so we can better contrast the stub approach taken by Varad vs. the EFI
app approach that we've taken.
Thanks,
Marc
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
2021-08-13 18:44 ` Marc Orr
@ 2021-08-17 10:49 ` Joerg Roedel
2021-08-17 10:49 ` Joerg Roedel
1 sibling, 0 replies; 32+ messages in thread
From: Joerg Roedel @ 2021-08-17 10:49 UTC (permalink / raw)
To: Marc Orr
Cc: Varad Gautam, kvm list, virtualization, Paolo Bonzini, drjones,
bp, Lendacky, Thomas, Singh, Brijesh, Zixuan Wang,
Hyunwook (Wooky) Baek, Erdem Aktas, Tom Roeder
Hi Marc,
On Fri, Aug 13, 2021 at 11:44:39AM -0700, Marc Orr wrote:
> To date, we have _most_ x86 test cases (39/44) working under UEFI and
> we've also got some of the test cases to boot under SEV-ES, using the
> UEFI #VC handler.
While the EFI APP approach simplifies the implementation a lot, I don't
think it is the best path to SEV and TDX testing for a couple of
reasons:
1) It leaves the details of #VC/#VE handling and the SEV-ES
specific communication channels (GHCB) under control of the
firmware. So we can't reliably test those interfaces from an
EFI APP.
2) Same for the memory validation/acceptance interface needed
for SEV-SNP and TDX. Using an EFI APP leaves those under
firmware control and we are not able to reliably test them.
3) The IDT also stays under control of the firmware in an EFI
APP, otherwise the firmware couldn't provide a #VC handler.
This makes it unreliable to test anything IDT or IRQ related.
4) Relying on the firmware #VC hanlder limits the tests to its
abilities. Implementing a separate #VC handler routine for
kvm-unit-tests is more work, but it makes test development
much more flexible.
So it comes down to the fact that and EFI APP leaves control over
SEV/TDX specific hypervisor interfaces in the firmware, making it hard
and unreliable to test these interfaces from kvm-unit-tests. The stub
approach on the other side gives the tests full control over the VM,
allowing to test all aspects of the guest-host interface.
Regards,
Joerg
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
@ 2021-08-17 10:49 ` Joerg Roedel
0 siblings, 0 replies; 32+ messages in thread
From: Joerg Roedel @ 2021-08-17 10:49 UTC (permalink / raw)
To: Marc Orr
Cc: Lendacky, Thomas, drjones, Singh, Brijesh, kvm list, Tom Roeder,
Hyunwook (Wooky) Baek, virtualization, Zixuan Wang, Erdem Aktas,
Paolo Bonzini, bp
Hi Marc,
On Fri, Aug 13, 2021 at 11:44:39AM -0700, Marc Orr wrote:
> To date, we have _most_ x86 test cases (39/44) working under UEFI and
> we've also got some of the test cases to boot under SEV-ES, using the
> UEFI #VC handler.
While the EFI APP approach simplifies the implementation a lot, I don't
think it is the best path to SEV and TDX testing for a couple of
reasons:
1) It leaves the details of #VC/#VE handling and the SEV-ES
specific communication channels (GHCB) under control of the
firmware. So we can't reliably test those interfaces from an
EFI APP.
2) Same for the memory validation/acceptance interface needed
for SEV-SNP and TDX. Using an EFI APP leaves those under
firmware control and we are not able to reliably test them.
3) The IDT also stays under control of the firmware in an EFI
APP, otherwise the firmware couldn't provide a #VC handler.
This makes it unreliable to test anything IDT or IRQ related.
4) Relying on the firmware #VC hanlder limits the tests to its
abilities. Implementing a separate #VC handler routine for
kvm-unit-tests is more work, but it makes test development
much more flexible.
So it comes down to the fact that and EFI APP leaves control over
SEV/TDX specific hypervisor interfaces in the firmware, making it hard
and unreliable to test these interfaces from kvm-unit-tests. The stub
approach on the other side gives the tests full control over the VM,
allowing to test all aspects of the guest-host interface.
Regards,
Joerg
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
2021-08-17 10:49 ` Joerg Roedel
(?)
@ 2021-08-18 1:52 ` Marc Orr
2021-08-18 8:38 ` Varad Gautam via Virtualization
-1 siblings, 1 reply; 32+ messages in thread
From: Marc Orr @ 2021-08-18 1:52 UTC (permalink / raw)
To: Joerg Roedel
Cc: Varad Gautam, kvm list, virtualization, Paolo Bonzini,
Andrew Jones, bp, Lendacky, Thomas, Singh, Brijesh, Zixuan Wang,
Hyunwook (Wooky) Baek, Erdem Aktas, Tom Roeder
On Tue, Aug 17, 2021 at 3:49 AM Joerg Roedel <jroedel@suse.de> wrote:
>
> Hi Marc,
>
> On Fri, Aug 13, 2021 at 11:44:39AM -0700, Marc Orr wrote:
> > To date, we have _most_ x86 test cases (39/44) working under UEFI and
> > we've also got some of the test cases to boot under SEV-ES, using the
> > UEFI #VC handler.
>
> While the EFI APP approach simplifies the implementation a lot, I don't
> think it is the best path to SEV and TDX testing for a couple of
> reasons:
>
> 1) It leaves the details of #VC/#VE handling and the SEV-ES
> specific communication channels (GHCB) under control of the
> firmware. So we can't reliably test those interfaces from an
> EFI APP.
>
> 2) Same for the memory validation/acceptance interface needed
> for SEV-SNP and TDX. Using an EFI APP leaves those under
> firmware control and we are not able to reliably test them.
>
> 3) The IDT also stays under control of the firmware in an EFI
> APP, otherwise the firmware couldn't provide a #VC handler.
> This makes it unreliable to test anything IDT or IRQ related.
>
> 4) Relying on the firmware #VC hanlder limits the tests to its
> abilities. Implementing a separate #VC handler routine for
> kvm-unit-tests is more work, but it makes test development
> much more flexible.
>
> So it comes down to the fact that and EFI APP leaves control over
> SEV/TDX specific hypervisor interfaces in the firmware, making it hard
> and unreliable to test these interfaces from kvm-unit-tests. The stub
> approach on the other side gives the tests full control over the VM,
> allowing to test all aspects of the guest-host interface.
I think we might be using terminology differently. (Maybe I mis-used
the term “EFI app”?) With our approach, it is true that all
pre-existing x86_64 test cases work out of the box with the UEFI #VC
handler. However, because kvm-unit-tests calls `ExitBootServices` to
take full control of the system it executes as a “UEFI-stubbed
kernel”. Thus, it should be trivial for test cases to update the IDT
to set up a custom #VC handler for the duration of a test. (Some of
the x86_64 test cases already do something similar where they install
a temporary exception handler and then restore the “default”
kvm-unit-tests exception handler.)
In general, our approach is to set up the test cases to run with the
kvm-unit-tests configuration (e.g., IDT, GDT). The one exception is
the #VC handler. However, all of this state can be overridden within a
test as needed.
Zixuan just posted the patches. So hopefully they make things more clear.
Thanks,
Marc
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
2021-08-18 1:52 ` Marc Orr
@ 2021-08-18 8:38 ` Varad Gautam via Virtualization
0 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam @ 2021-08-18 8:38 UTC (permalink / raw)
To: Marc Orr, Joerg Roedel
Cc: kvm list, virtualization, Paolo Bonzini, Andrew Jones, bp,
Lendacky, Thomas, Singh, Brijesh, Zixuan Wang,
Hyunwook (Wooky) Baek, Erdem Aktas, Tom Roeder
Hi Marc, Zixuan,
On 8/18/21 3:52 AM, Marc Orr wrote:
> On Tue, Aug 17, 2021 at 3:49 AM Joerg Roedel <jroedel@suse.de> wrote:
>>
>> Hi Marc,
>>
>> On Fri, Aug 13, 2021 at 11:44:39AM -0700, Marc Orr wrote:
>>> To date, we have _most_ x86 test cases (39/44) working under UEFI and
>>> we've also got some of the test cases to boot under SEV-ES, using the
>>> UEFI #VC handler.
>>
>> While the EFI APP approach simplifies the implementation a lot, I don't
>> think it is the best path to SEV and TDX testing for a couple of
>> reasons:
>>
>> 1) It leaves the details of #VC/#VE handling and the SEV-ES
>> specific communication channels (GHCB) under control of the
>> firmware. So we can't reliably test those interfaces from an
>> EFI APP.
>>
>> 2) Same for the memory validation/acceptance interface needed
>> for SEV-SNP and TDX. Using an EFI APP leaves those under
>> firmware control and we are not able to reliably test them.
>>
>> 3) The IDT also stays under control of the firmware in an EFI
>> APP, otherwise the firmware couldn't provide a #VC handler.
>> This makes it unreliable to test anything IDT or IRQ related.
>>
>> 4) Relying on the firmware #VC hanlder limits the tests to its
>> abilities. Implementing a separate #VC handler routine for
>> kvm-unit-tests is more work, but it makes test development
>> much more flexible.
>>
>> So it comes down to the fact that and EFI APP leaves control over
>> SEV/TDX specific hypervisor interfaces in the firmware, making it hard
>> and unreliable to test these interfaces from kvm-unit-tests. The stub
>> approach on the other side gives the tests full control over the VM,
>> allowing to test all aspects of the guest-host interface.
>
> I think we might be using terminology differently. (Maybe I mis-used
> the term “EFI app”?) With our approach, it is true that all
> pre-existing x86_64 test cases work out of the box with the UEFI #VC
> handler. However, because kvm-unit-tests calls `ExitBootServices` to
> take full control of the system it executes as a “UEFI-stubbed
> kernel”. Thus, it should be trivial for test cases to update the IDT
> to set up a custom #VC handler for the duration of a test. (Some of
> the x86_64 test cases already do something similar where they install
> a temporary exception handler and then restore the “default”
> kvm-unit-tests exception handler.)
>
> In general, our approach is to set up the test cases to run with the
> kvm-unit-tests configuration (e.g., IDT, GDT). The one exception is
> the #VC handler. However, all of this state can be overridden within a
> test as needed.
>
> Zixuan just posted the patches. So hopefully they make things more clear.
>
Nomenclature aside, I believe Zixuan's patchset [1] takes the same approach
as I posted here. In the end, we need to:
- build the testcases as ELF shared objs and link them to look like a PE
- switch away from UEFI GDT/IDT/pagetable states on early boot to what
kvm-unit-tests needs
- modify the testcases that contain non-PIC asm stubs to allow building
them as shared objs
I went with avoiding to bring in gnu-efi objects into kvm-unit-tests
for EFI helpers, and disabling the non-PIC testcases for the RFC's sake.
I'll try out "x86 UEFI: Convert x86 test cases to PIC" [2] from Zixuan's
patchset with my series and see what breaks. I think we can combine
the two patchsets.
[1] https://lore.kernel.org/r/20210818000905.1111226-1-zixuanwang@google.com/
[2] https://lore.kernel.org/r/20210818000905.1111226-10-zixuanwang@google.com/
Thanks,
Varad
> Thanks,
> Marc
>
--
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5
90409 Nürnberg
Germany
HRB 36809, AG Nürnberg
Geschäftsführer: Felix Imendörffer
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
@ 2021-08-18 8:38 ` Varad Gautam via Virtualization
0 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam via Virtualization @ 2021-08-18 8:38 UTC (permalink / raw)
To: Marc Orr, Joerg Roedel
Cc: Lendacky, Thomas, Andrew Jones, Singh, Brijesh, kvm list,
Tom Roeder, Hyunwook (Wooky) Baek, virtualization, Zixuan Wang,
Erdem Aktas, Paolo Bonzini, bp
Hi Marc, Zixuan,
On 8/18/21 3:52 AM, Marc Orr wrote:
> On Tue, Aug 17, 2021 at 3:49 AM Joerg Roedel <jroedel@suse.de> wrote:
>>
>> Hi Marc,
>>
>> On Fri, Aug 13, 2021 at 11:44:39AM -0700, Marc Orr wrote:
>>> To date, we have _most_ x86 test cases (39/44) working under UEFI and
>>> we've also got some of the test cases to boot under SEV-ES, using the
>>> UEFI #VC handler.
>>
>> While the EFI APP approach simplifies the implementation a lot, I don't
>> think it is the best path to SEV and TDX testing for a couple of
>> reasons:
>>
>> 1) It leaves the details of #VC/#VE handling and the SEV-ES
>> specific communication channels (GHCB) under control of the
>> firmware. So we can't reliably test those interfaces from an
>> EFI APP.
>>
>> 2) Same for the memory validation/acceptance interface needed
>> for SEV-SNP and TDX. Using an EFI APP leaves those under
>> firmware control and we are not able to reliably test them.
>>
>> 3) The IDT also stays under control of the firmware in an EFI
>> APP, otherwise the firmware couldn't provide a #VC handler.
>> This makes it unreliable to test anything IDT or IRQ related.
>>
>> 4) Relying on the firmware #VC hanlder limits the tests to its
>> abilities. Implementing a separate #VC handler routine for
>> kvm-unit-tests is more work, but it makes test development
>> much more flexible.
>>
>> So it comes down to the fact that and EFI APP leaves control over
>> SEV/TDX specific hypervisor interfaces in the firmware, making it hard
>> and unreliable to test these interfaces from kvm-unit-tests. The stub
>> approach on the other side gives the tests full control over the VM,
>> allowing to test all aspects of the guest-host interface.
>
> I think we might be using terminology differently. (Maybe I mis-used
> the term “EFI app”?) With our approach, it is true that all
> pre-existing x86_64 test cases work out of the box with the UEFI #VC
> handler. However, because kvm-unit-tests calls `ExitBootServices` to
> take full control of the system it executes as a “UEFI-stubbed
> kernel”. Thus, it should be trivial for test cases to update the IDT
> to set up a custom #VC handler for the duration of a test. (Some of
> the x86_64 test cases already do something similar where they install
> a temporary exception handler and then restore the “default”
> kvm-unit-tests exception handler.)
>
> In general, our approach is to set up the test cases to run with the
> kvm-unit-tests configuration (e.g., IDT, GDT). The one exception is
> the #VC handler. However, all of this state can be overridden within a
> test as needed.
>
> Zixuan just posted the patches. So hopefully they make things more clear.
>
Nomenclature aside, I believe Zixuan's patchset [1] takes the same approach
as I posted here. In the end, we need to:
- build the testcases as ELF shared objs and link them to look like a PE
- switch away from UEFI GDT/IDT/pagetable states on early boot to what
kvm-unit-tests needs
- modify the testcases that contain non-PIC asm stubs to allow building
them as shared objs
I went with avoiding to bring in gnu-efi objects into kvm-unit-tests
for EFI helpers, and disabling the non-PIC testcases for the RFC's sake.
I'll try out "x86 UEFI: Convert x86 test cases to PIC" [2] from Zixuan's
patchset with my series and see what breaks. I think we can combine
the two patchsets.
[1] https://lore.kernel.org/r/20210818000905.1111226-1-zixuanwang@google.com/
[2] https://lore.kernel.org/r/20210818000905.1111226-10-zixuanwang@google.com/
Thanks,
Varad
> Thanks,
> Marc
>
--
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5
90409 Nürnberg
Germany
HRB 36809, AG Nürnberg
Geschäftsführer: Felix Imendörffer
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
2021-08-18 8:38 ` Varad Gautam via Virtualization
(?)
@ 2021-08-19 1:32 ` Marc Orr
2021-08-19 1:42 ` Nadav Amit
2021-08-19 11:36 ` Varad Gautam via Virtualization
-1 siblings, 2 replies; 32+ messages in thread
From: Marc Orr @ 2021-08-19 1:32 UTC (permalink / raw)
To: Varad Gautam
Cc: Joerg Roedel, kvm list, virtualization, Paolo Bonzini,
Andrew Jones, bp, Lendacky, Thomas, Singh, Brijesh, Zixuan Wang,
Hyunwook (Wooky) Baek, Erdem Aktas, Tom Roeder
On Wed, Aug 18, 2021 at 1:38 AM Varad Gautam <varad.gautam@suse.com> wrote:
>
> Hi Marc, Zixuan,
>
> On 8/18/21 3:52 AM, Marc Orr wrote:
> > On Tue, Aug 17, 2021 at 3:49 AM Joerg Roedel <jroedel@suse.de> wrote:
> >>
> >> Hi Marc,
> >>
> >> On Fri, Aug 13, 2021 at 11:44:39AM -0700, Marc Orr wrote:
> >>> To date, we have _most_ x86 test cases (39/44) working under UEFI and
> >>> we've also got some of the test cases to boot under SEV-ES, using the
> >>> UEFI #VC handler.
> >>
> >> While the EFI APP approach simplifies the implementation a lot, I don't
> >> think it is the best path to SEV and TDX testing for a couple of
> >> reasons:
> >>
> >> 1) It leaves the details of #VC/#VE handling and the SEV-ES
> >> specific communication channels (GHCB) under control of the
> >> firmware. So we can't reliably test those interfaces from an
> >> EFI APP.
> >>
> >> 2) Same for the memory validation/acceptance interface needed
> >> for SEV-SNP and TDX. Using an EFI APP leaves those under
> >> firmware control and we are not able to reliably test them.
> >>
> >> 3) The IDT also stays under control of the firmware in an EFI
> >> APP, otherwise the firmware couldn't provide a #VC handler.
> >> This makes it unreliable to test anything IDT or IRQ related.
> >>
> >> 4) Relying on the firmware #VC hanlder limits the tests to its
> >> abilities. Implementing a separate #VC handler routine for
> >> kvm-unit-tests is more work, but it makes test development
> >> much more flexible.
> >>
> >> So it comes down to the fact that and EFI APP leaves control over
> >> SEV/TDX specific hypervisor interfaces in the firmware, making it hard
> >> and unreliable to test these interfaces from kvm-unit-tests. The stub
> >> approach on the other side gives the tests full control over the VM,
> >> allowing to test all aspects of the guest-host interface.
> >
> > I think we might be using terminology differently. (Maybe I mis-used
> > the term “EFI app”?) With our approach, it is true that all
> > pre-existing x86_64 test cases work out of the box with the UEFI #VC
> > handler. However, because kvm-unit-tests calls `ExitBootServices` to
> > take full control of the system it executes as a “UEFI-stubbed
> > kernel”. Thus, it should be trivial for test cases to update the IDT
> > to set up a custom #VC handler for the duration of a test. (Some of
> > the x86_64 test cases already do something similar where they install
> > a temporary exception handler and then restore the “default”
> > kvm-unit-tests exception handler.)
> >
> > In general, our approach is to set up the test cases to run with the
> > kvm-unit-tests configuration (e.g., IDT, GDT). The one exception is
> > the #VC handler. However, all of this state can be overridden within a
> > test as needed.
> >
> > Zixuan just posted the patches. So hopefully they make things more clear.
> >
>
> Nomenclature aside, I believe Zixuan's patchset [1] takes the same approach
> as I posted here. In the end, we need to:
> - build the testcases as ELF shared objs and link them to look like a PE
> - switch away from UEFI GDT/IDT/pagetable states on early boot to what
> kvm-unit-tests needs
> - modify the testcases that contain non-PIC asm stubs to allow building
> them as shared objs
>
> I went with avoiding to bring in gnu-efi objects into kvm-unit-tests
> for EFI helpers, and disabling the non-PIC testcases for the RFC's sake.
>
> I'll try out "x86 UEFI: Convert x86 test cases to PIC" [2] from Zixuan's
> patchset with my series and see what breaks. I think we can combine
> the two patchsets.
>
> [1] https://lore.kernel.org/r/20210818000905.1111226-1-zixuanwang@google.com/
> [2] https://lore.kernel.org/r/20210818000905.1111226-10-zixuanwang@google.com/
This sounds great to us. We will also experiment with combining the
two patchsets and report back when we have some experience with this.
Though, please do also report back if you have an update on this
before we do.
Thanks,
Marc
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
2021-08-19 1:32 ` Marc Orr
@ 2021-08-19 1:42 ` Nadav Amit
2021-08-19 11:36 ` Varad Gautam via Virtualization
1 sibling, 0 replies; 32+ messages in thread
From: Nadav Amit @ 2021-08-19 1:42 UTC (permalink / raw)
To: Marc Orr
Cc: Varad Gautam, Joerg Roedel, kvm list, Linux Virtualization,
Paolo Bonzini, Andrew Jones, bp, Lendacky, Thomas, Singh,
Brijesh, Zixuan Wang, Hyunwook (Wooky) Baek, Erdem Aktas,
Tom Roeder
> On Aug 18, 2021, at 6:32 PM, Marc Orr <marcorr@google.com> wrote:
>
> This sounds great to us. We will also experiment with combining the
> two patchsets and report back when we have some experience with this.
> Though, please do also report back if you have an update on this
> before we do.
Just wondering (aka, my standard question): does it work on
bare-metal (putting aside tests that rely on test-devices)?
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
@ 2021-08-19 1:42 ` Nadav Amit
0 siblings, 0 replies; 32+ messages in thread
From: Nadav Amit @ 2021-08-19 1:42 UTC (permalink / raw)
To: Marc Orr
Cc: Lendacky, Thomas, Andrew Jones, Joerg Roedel, Singh, Brijesh,
kvm list, Tom Roeder, Hyunwook (Wooky) Baek,
Linux Virtualization, Zixuan Wang, Erdem Aktas, Paolo Bonzini,
bp
> On Aug 18, 2021, at 6:32 PM, Marc Orr <marcorr@google.com> wrote:
>
> This sounds great to us. We will also experiment with combining the
> two patchsets and report back when we have some experience with this.
> Though, please do also report back if you have an update on this
> before we do.
Just wondering (aka, my standard question): does it work on
bare-metal (putting aside tests that rely on test-devices)?
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
2021-08-19 1:42 ` Nadav Amit
(?)
@ 2021-08-19 1:54 ` Zixuan Wang
-1 siblings, 0 replies; 32+ messages in thread
From: Zixuan Wang @ 2021-08-19 1:54 UTC (permalink / raw)
To: Nadav Amit
Cc: Marc Orr, Varad Gautam, Joerg Roedel, kvm list,
Linux Virtualization, Paolo Bonzini, Andrew Jones, bp, Lendacky,
Thomas, Singh, Brijesh, Hyunwook (Wooky) Baek, Erdem Aktas,
Tom Roeder
On Wed, Aug 18, 2021 at 6:42 PM Nadav Amit <nadav.amit@gmail.com> wrote:
>
> Just wondering (aka, my standard question): does it work on
> bare-metal (putting aside tests that rely on test-devices)?
>
Hi Nadav,
We tested our patches in VMs, and have not tested on bare-metal machines.
Regards,
Zixuan Wang
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
2021-08-19 1:32 ` Marc Orr
@ 2021-08-19 11:36 ` Varad Gautam via Virtualization
2021-08-19 11:36 ` Varad Gautam via Virtualization
1 sibling, 0 replies; 32+ messages in thread
From: Varad Gautam @ 2021-08-19 11:36 UTC (permalink / raw)
To: Marc Orr
Cc: Joerg Roedel, kvm list, virtualization, Paolo Bonzini,
Andrew Jones, bp, Lendacky, Thomas, Singh, Brijesh, Zixuan Wang,
Hyunwook (Wooky) Baek, Erdem Aktas, Tom Roeder
On 8/19/21 3:32 AM, Marc Orr wrote:
> On Wed, Aug 18, 2021 at 1:38 AM Varad Gautam <varad.gautam@suse.com> wrote:
>>
>> Hi Marc, Zixuan,
>>
>> On 8/18/21 3:52 AM, Marc Orr wrote:
>>> On Tue, Aug 17, 2021 at 3:49 AM Joerg Roedel <jroedel@suse.de> wrote:
>>>>
>>>> Hi Marc,
>>>>
>>>> On Fri, Aug 13, 2021 at 11:44:39AM -0700, Marc Orr wrote:
>>>>> To date, we have _most_ x86 test cases (39/44) working under UEFI and
>>>>> we've also got some of the test cases to boot under SEV-ES, using the
>>>>> UEFI #VC handler.
>>>>
>>>> While the EFI APP approach simplifies the implementation a lot, I don't
>>>> think it is the best path to SEV and TDX testing for a couple of
>>>> reasons:
>>>>
>>>> 1) It leaves the details of #VC/#VE handling and the SEV-ES
>>>> specific communication channels (GHCB) under control of the
>>>> firmware. So we can't reliably test those interfaces from an
>>>> EFI APP.
>>>>
>>>> 2) Same for the memory validation/acceptance interface needed
>>>> for SEV-SNP and TDX. Using an EFI APP leaves those under
>>>> firmware control and we are not able to reliably test them.
>>>>
>>>> 3) The IDT also stays under control of the firmware in an EFI
>>>> APP, otherwise the firmware couldn't provide a #VC handler.
>>>> This makes it unreliable to test anything IDT or IRQ related.
>>>>
>>>> 4) Relying on the firmware #VC hanlder limits the tests to its
>>>> abilities. Implementing a separate #VC handler routine for
>>>> kvm-unit-tests is more work, but it makes test development
>>>> much more flexible.
>>>>
>>>> So it comes down to the fact that and EFI APP leaves control over
>>>> SEV/TDX specific hypervisor interfaces in the firmware, making it hard
>>>> and unreliable to test these interfaces from kvm-unit-tests. The stub
>>>> approach on the other side gives the tests full control over the VM,
>>>> allowing to test all aspects of the guest-host interface.
>>>
>>> I think we might be using terminology differently. (Maybe I mis-used
>>> the term “EFI app”?) With our approach, it is true that all
>>> pre-existing x86_64 test cases work out of the box with the UEFI #VC
>>> handler. However, because kvm-unit-tests calls `ExitBootServices` to
>>> take full control of the system it executes as a “UEFI-stubbed
>>> kernel”. Thus, it should be trivial for test cases to update the IDT
>>> to set up a custom #VC handler for the duration of a test. (Some of
>>> the x86_64 test cases already do something similar where they install
>>> a temporary exception handler and then restore the “default”
>>> kvm-unit-tests exception handler.)
>>>
>>> In general, our approach is to set up the test cases to run with the
>>> kvm-unit-tests configuration (e.g., IDT, GDT). The one exception is
>>> the #VC handler. However, all of this state can be overridden within a
>>> test as needed.
>>>
>>> Zixuan just posted the patches. So hopefully they make things more clear.
>>>
>>
>> Nomenclature aside, I believe Zixuan's patchset [1] takes the same approach
>> as I posted here. In the end, we need to:
>> - build the testcases as ELF shared objs and link them to look like a PE
>> - switch away from UEFI GDT/IDT/pagetable states on early boot to what
>> kvm-unit-tests needs
>> - modify the testcases that contain non-PIC asm stubs to allow building
>> them as shared objs
>>
>> I went with avoiding to bring in gnu-efi objects into kvm-unit-tests
>> for EFI helpers, and disabling the non-PIC testcases for the RFC's sake.
>>
>> I'll try out "x86 UEFI: Convert x86 test cases to PIC" [2] from Zixuan's
>> patchset with my series and see what breaks. I think we can combine
>> the two patchsets.
>>
>> [1] https://lore.kernel.org/r/20210818000905.1111226-1-zixuanwang@google.com/
>> [2] https://lore.kernel.org/r/20210818000905.1111226-10-zixuanwang@google.com/
>
> This sounds great to us. We will also experiment with combining the
> two patchsets and report back when we have some experience with this.
> Though, please do also report back if you have an update on this
> before we do.
>
I sent out a v2 [1] with Zixuan's "x86 UEFI: Convert x86 test cases to PIC" [2]
pulled in, PTAL.
[1] https://lore.kernel.org/r/20210819113400.26516-1-varad.gautam@suse.com/
[2] https://lore.kernel.org/r/20210818000905.1111226-10-zixuanwang@google.com/
Thanks,
Varad
> Thanks,
> Marc
>
--
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5
90409 Nürnberg
Germany
HRB 36809, AG Nürnberg
Geschäftsführer: Felix Imendörffer
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
@ 2021-08-19 11:36 ` Varad Gautam via Virtualization
0 siblings, 0 replies; 32+ messages in thread
From: Varad Gautam via Virtualization @ 2021-08-19 11:36 UTC (permalink / raw)
To: Marc Orr
Cc: Lendacky, Thomas, Andrew Jones, Joerg Roedel, Singh, Brijesh,
kvm list, Tom Roeder, Hyunwook (Wooky) Baek, virtualization,
Zixuan Wang, Erdem Aktas, Paolo Bonzini, bp
On 8/19/21 3:32 AM, Marc Orr wrote:
> On Wed, Aug 18, 2021 at 1:38 AM Varad Gautam <varad.gautam@suse.com> wrote:
>>
>> Hi Marc, Zixuan,
>>
>> On 8/18/21 3:52 AM, Marc Orr wrote:
>>> On Tue, Aug 17, 2021 at 3:49 AM Joerg Roedel <jroedel@suse.de> wrote:
>>>>
>>>> Hi Marc,
>>>>
>>>> On Fri, Aug 13, 2021 at 11:44:39AM -0700, Marc Orr wrote:
>>>>> To date, we have _most_ x86 test cases (39/44) working under UEFI and
>>>>> we've also got some of the test cases to boot under SEV-ES, using the
>>>>> UEFI #VC handler.
>>>>
>>>> While the EFI APP approach simplifies the implementation a lot, I don't
>>>> think it is the best path to SEV and TDX testing for a couple of
>>>> reasons:
>>>>
>>>> 1) It leaves the details of #VC/#VE handling and the SEV-ES
>>>> specific communication channels (GHCB) under control of the
>>>> firmware. So we can't reliably test those interfaces from an
>>>> EFI APP.
>>>>
>>>> 2) Same for the memory validation/acceptance interface needed
>>>> for SEV-SNP and TDX. Using an EFI APP leaves those under
>>>> firmware control and we are not able to reliably test them.
>>>>
>>>> 3) The IDT also stays under control of the firmware in an EFI
>>>> APP, otherwise the firmware couldn't provide a #VC handler.
>>>> This makes it unreliable to test anything IDT or IRQ related.
>>>>
>>>> 4) Relying on the firmware #VC hanlder limits the tests to its
>>>> abilities. Implementing a separate #VC handler routine for
>>>> kvm-unit-tests is more work, but it makes test development
>>>> much more flexible.
>>>>
>>>> So it comes down to the fact that and EFI APP leaves control over
>>>> SEV/TDX specific hypervisor interfaces in the firmware, making it hard
>>>> and unreliable to test these interfaces from kvm-unit-tests. The stub
>>>> approach on the other side gives the tests full control over the VM,
>>>> allowing to test all aspects of the guest-host interface.
>>>
>>> I think we might be using terminology differently. (Maybe I mis-used
>>> the term “EFI app”?) With our approach, it is true that all
>>> pre-existing x86_64 test cases work out of the box with the UEFI #VC
>>> handler. However, because kvm-unit-tests calls `ExitBootServices` to
>>> take full control of the system it executes as a “UEFI-stubbed
>>> kernel”. Thus, it should be trivial for test cases to update the IDT
>>> to set up a custom #VC handler for the duration of a test. (Some of
>>> the x86_64 test cases already do something similar where they install
>>> a temporary exception handler and then restore the “default”
>>> kvm-unit-tests exception handler.)
>>>
>>> In general, our approach is to set up the test cases to run with the
>>> kvm-unit-tests configuration (e.g., IDT, GDT). The one exception is
>>> the #VC handler. However, all of this state can be overridden within a
>>> test as needed.
>>>
>>> Zixuan just posted the patches. So hopefully they make things more clear.
>>>
>>
>> Nomenclature aside, I believe Zixuan's patchset [1] takes the same approach
>> as I posted here. In the end, we need to:
>> - build the testcases as ELF shared objs and link them to look like a PE
>> - switch away from UEFI GDT/IDT/pagetable states on early boot to what
>> kvm-unit-tests needs
>> - modify the testcases that contain non-PIC asm stubs to allow building
>> them as shared objs
>>
>> I went with avoiding to bring in gnu-efi objects into kvm-unit-tests
>> for EFI helpers, and disabling the non-PIC testcases for the RFC's sake.
>>
>> I'll try out "x86 UEFI: Convert x86 test cases to PIC" [2] from Zixuan's
>> patchset with my series and see what breaks. I think we can combine
>> the two patchsets.
>>
>> [1] https://lore.kernel.org/r/20210818000905.1111226-1-zixuanwang@google.com/
>> [2] https://lore.kernel.org/r/20210818000905.1111226-10-zixuanwang@google.com/
>
> This sounds great to us. We will also experiment with combining the
> two patchsets and report back when we have some experience with this.
> Though, please do also report back if you have an update on this
> before we do.
>
I sent out a v2 [1] with Zixuan's "x86 UEFI: Convert x86 test cases to PIC" [2]
pulled in, PTAL.
[1] https://lore.kernel.org/r/20210819113400.26516-1-varad.gautam@suse.com/
[2] https://lore.kernel.org/r/20210818000905.1111226-10-zixuanwang@google.com/
Thanks,
Varad
> Thanks,
> Marc
>
--
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5
90409 Nürnberg
Germany
HRB 36809, AG Nürnberg
Geschäftsführer: Felix Imendörffer
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support
2021-08-19 11:36 ` Varad Gautam via Virtualization
(?)
@ 2021-08-20 17:29 ` Marc Orr
-1 siblings, 0 replies; 32+ messages in thread
From: Marc Orr @ 2021-08-20 17:29 UTC (permalink / raw)
To: Varad Gautam
Cc: Joerg Roedel, kvm list, virtualization, Paolo Bonzini,
Andrew Jones, bp, Lendacky, Thomas, Singh, Brijesh, Zixuan Wang,
Hyunwook (Wooky) Baek, Erdem Aktas, Tom Roeder
On Thu, Aug 19, 2021 at 4:36 AM Varad Gautam <varad.gautam@suse.com> wrote:
>
> On 8/19/21 3:32 AM, Marc Orr wrote:
> > On Wed, Aug 18, 2021 at 1:38 AM Varad Gautam <varad.gautam@suse.com> wrote:
> >>
> >> Hi Marc, Zixuan,
> >>
> >> On 8/18/21 3:52 AM, Marc Orr wrote:
> >>> On Tue, Aug 17, 2021 at 3:49 AM Joerg Roedel <jroedel@suse.de> wrote:
> >>>>
> >>>> Hi Marc,
> >>>>
> >>>> On Fri, Aug 13, 2021 at 11:44:39AM -0700, Marc Orr wrote:
> >>>>> To date, we have _most_ x86 test cases (39/44) working under UEFI and
> >>>>> we've also got some of the test cases to boot under SEV-ES, using the
> >>>>> UEFI #VC handler.
> >>>>
> >>>> While the EFI APP approach simplifies the implementation a lot, I don't
> >>>> think it is the best path to SEV and TDX testing for a couple of
> >>>> reasons:
> >>>>
> >>>> 1) It leaves the details of #VC/#VE handling and the SEV-ES
> >>>> specific communication channels (GHCB) under control of the
> >>>> firmware. So we can't reliably test those interfaces from an
> >>>> EFI APP.
> >>>>
> >>>> 2) Same for the memory validation/acceptance interface needed
> >>>> for SEV-SNP and TDX. Using an EFI APP leaves those under
> >>>> firmware control and we are not able to reliably test them.
> >>>>
> >>>> 3) The IDT also stays under control of the firmware in an EFI
> >>>> APP, otherwise the firmware couldn't provide a #VC handler.
> >>>> This makes it unreliable to test anything IDT or IRQ related.
> >>>>
> >>>> 4) Relying on the firmware #VC hanlder limits the tests to its
> >>>> abilities. Implementing a separate #VC handler routine for
> >>>> kvm-unit-tests is more work, but it makes test development
> >>>> much more flexible.
> >>>>
> >>>> So it comes down to the fact that and EFI APP leaves control over
> >>>> SEV/TDX specific hypervisor interfaces in the firmware, making it hard
> >>>> and unreliable to test these interfaces from kvm-unit-tests. The stub
> >>>> approach on the other side gives the tests full control over the VM,
> >>>> allowing to test all aspects of the guest-host interface.
> >>>
> >>> I think we might be using terminology differently. (Maybe I mis-used
> >>> the term “EFI app”?) With our approach, it is true that all
> >>> pre-existing x86_64 test cases work out of the box with the UEFI #VC
> >>> handler. However, because kvm-unit-tests calls `ExitBootServices` to
> >>> take full control of the system it executes as a “UEFI-stubbed
> >>> kernel”. Thus, it should be trivial for test cases to update the IDT
> >>> to set up a custom #VC handler for the duration of a test. (Some of
> >>> the x86_64 test cases already do something similar where they install
> >>> a temporary exception handler and then restore the “default”
> >>> kvm-unit-tests exception handler.)
> >>>
> >>> In general, our approach is to set up the test cases to run with the
> >>> kvm-unit-tests configuration (e.g., IDT, GDT). The one exception is
> >>> the #VC handler. However, all of this state can be overridden within a
> >>> test as needed.
> >>>
> >>> Zixuan just posted the patches. So hopefully they make things more clear.
> >>>
> >>
> >> Nomenclature aside, I believe Zixuan's patchset [1] takes the same approach
> >> as I posted here. In the end, we need to:
> >> - build the testcases as ELF shared objs and link them to look like a PE
> >> - switch away from UEFI GDT/IDT/pagetable states on early boot to what
> >> kvm-unit-tests needs
> >> - modify the testcases that contain non-PIC asm stubs to allow building
> >> them as shared objs
> >>
> >> I went with avoiding to bring in gnu-efi objects into kvm-unit-tests
> >> for EFI helpers, and disabling the non-PIC testcases for the RFC's sake.
> >>
> >> I'll try out "x86 UEFI: Convert x86 test cases to PIC" [2] from Zixuan's
> >> patchset with my series and see what breaks. I think we can combine
> >> the two patchsets.
> >>
> >> [1] https://lore.kernel.org/r/20210818000905.1111226-1-zixuanwang@google.com/
> >> [2] https://lore.kernel.org/r/20210818000905.1111226-10-zixuanwang@google.com/
> >
> > This sounds great to us. We will also experiment with combining the
> > two patchsets and report back when we have some experience with this.
> > Though, please do also report back if you have an update on this
> > before we do.
> >
>
> I sent out a v2 [1] with Zixuan's "x86 UEFI: Convert x86 test cases to PIC" [2]
> pulled in, PTAL.
>
> [1] https://lore.kernel.org/r/20210819113400.26516-1-varad.gautam@suse.com/
> [2] https://lore.kernel.org/r/20210818000905.1111226-10-zixuanwang@google.com/
Thanks. This is a good step. However, after reviewing this new patch
set I think we should go a step further and completely combine the two
patch sets. This way, we get the benefit of Varad’s patches, which is
that we don’t need to link the gnu-efi library. And we get the
benefits of Zixuan’s patches which are twofold: (1) the vast majority
of the x86_64 test cases work under UEFI (optionally with SEV-ES) and
(2) much of the assembly code is refactored into C, making it more
readable/maintainable.
We’ve started experimenting with using Varad’s patch set as the
foundation for Zixuan's patch set. Initial testing on this
Frankenstein patch set is encouraging. I’d like to see Zixuan finish
this effort. Please give us a few days to further test and organize
the combined patch set. We’ll post it as soon as we can. Likely early
next week.
Thanks,
Marc
^ permalink raw reply [flat|nested] 32+ messages in thread