All of lore.kernel.org
 help / color / mirror / Atom feed
* [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 @ 2021-07-02 11:48 UTC (permalink / raw)
  To: kvm, virtualization
  Cc: pbonzini, drjones, jroedel, bp, thomas.lendacky, brijesh.singh,
	varad.gautam

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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [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

end of thread, other threads:[~2021-08-20 17:30 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-02 11:48 [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support Varad Gautam
2021-07-02 11:48 ` Varad Gautam via Virtualization
2021-07-02 11:48 ` [kvm-unit-tests PATCH 1/6] x86: Build tests as PE objects for the EFI loader Varad Gautam
2021-07-02 11:48   ` Varad Gautam via Virtualization
2021-07-02 11:48 ` [kvm-unit-tests PATCH 2/6] x86: Call efi_main from _efi_pe_entry Varad Gautam
2021-07-02 11:48   ` Varad Gautam via Virtualization
2021-07-02 11:48 ` [kvm-unit-tests PATCH 3/6] x86: efi_main: Get EFI memory map and exit boot services Varad Gautam
2021-07-02 11:48   ` Varad Gautam via Virtualization
2021-07-02 11:48 ` [kvm-unit-tests PATCH 4/6] x86: efi_main: Self-relocate ELF .dynamic addresses Varad Gautam
2021-07-02 11:48   ` Varad Gautam via Virtualization
2021-07-02 11:48 ` [kvm-unit-tests PATCH 5/6] cstart64.S: x86_64 bootstrapping after exiting EFI Varad Gautam
2021-07-02 11:48   ` Varad Gautam via Virtualization
2021-07-02 11:48 ` [kvm-unit-tests PATCH 6/6] x86: Disable some breaking tests for EFI and modify vmexit test Varad Gautam
2021-07-02 11:48   ` Varad Gautam via Virtualization
2021-07-12 16:29 ` [kvm-unit-tests PATCH 0/6] Initial x86_64 UEFI support Andrew Jones
2021-07-12 16:29   ` Andrew Jones
2021-08-13 18:44 ` Marc Orr
2021-08-16  7:26   ` Andrew Jones
2021-08-16  7:26     ` Andrew Jones
2021-08-17  3:41     ` Marc Orr
2021-08-17 10:49   ` Joerg Roedel
2021-08-17 10:49     ` Joerg Roedel
2021-08-18  1:52     ` Marc Orr
2021-08-18  8:38       ` Varad Gautam
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  1:42             ` Nadav Amit
2021-08-19  1:54             ` Zixuan Wang
2021-08-19 11:36           ` Varad Gautam
2021-08-19 11:36             ` Varad Gautam via Virtualization
2021-08-20 17:29             ` Marc Orr

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.