All of lore.kernel.org
 help / color / mirror / Atom feed
* [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support
@ 2021-08-19 11:33 Varad Gautam
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 1/6] x86: Build tests as PE objects for the EFI loader Varad Gautam
                   ` (6 more replies)
  0 siblings, 7 replies; 14+ messages in thread
From: Varad Gautam @ 2021-08-19 11:33 UTC (permalink / raw)
  To: Zixuan Wang, Nadav Amit, Marc Orr, Joerg Roedel, kvm list,
	Linux Virtualization, Paolo Bonzini, Andrew Jones, bp,
	Thomas.Lendacky, brijesh.singh, Hyunwook Baek, Erdem Aktas,
	Tom Roeder
  Cc: Varad Gautam

This series brings EFI support to kvm-unit-tests on x86_64.

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 from Zixuan [1] fixes up some testcases with non-PIC inline
asm stubs which allows building these as PIC.

Changes in v2:
- Add Zixuan's patch to enable more testcases.
- Fix TSS setup in cstart64.S for CONFIG_EFI.

[1]: https://lore.kernel.org/r/20210818000905.1111226-10-zixuanwang@google.com/
git tree: https://github.com/varadgautam/kvm-unit-tests/tree/efi-stub-v2

Varad Gautam (5):
  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

Zixuan Wang (1):
  x86 UEFI: Convert x86 test cases to PIC

 .gitignore          |   2 +
 Makefile            |  16 +-
 configure           |  11 +
 lib/linux/uefi.h    | 518 ++++++++++++++++++++++++++++++++++++++++++++
 lib/x86/usermode.c  |   3 +-
 x86/Makefile.common |  53 +++--
 x86/Makefile.x86_64 |  52 +++--
 x86/access.c        |   6 +-
 x86/cet.c           |   8 +-
 x86/cstart64.S      |  91 ++++++++
 x86/efi.lds         |  67 ++++++
 x86/efi_main.c      | 167 ++++++++++++++
 x86/emulator.c      |   5 +-
 x86/eventinj.c      |   6 +-
 x86/smap.c          |   8 +-
 x86/umip.c          |  10 +-
 16 files changed, 966 insertions(+), 57 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] 14+ messages in thread

* [kvm-unit-tests PATCH v2 1/6] x86: Build tests as PE objects for the EFI loader
  2021-08-19 11:33 [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support Varad Gautam
@ 2021-08-19 11:33 ` Varad Gautam
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 2/6] x86: Call efi_main from _efi_pe_entry Varad Gautam
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Varad Gautam @ 2021-08-19 11:33 UTC (permalink / raw)
  To: Zixuan Wang, Nadav Amit, Marc Orr, Joerg Roedel, kvm list,
	Linux Virtualization, Paolo Bonzini, Andrew Jones, bp,
	Thomas.Lendacky, brijesh.singh, Hyunwook Baek, Erdem Aktas,
	Tom Roeder
  Cc: 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 | 52 +++++++++++++++++++++++------------
 x86/Makefile.x86_64 | 51 +++++++++++++++++++++-------------
 x86/cstart64.S      | 27 +++++++++++++++++-
 x86/efi.lds         | 67 +++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 186 insertions(+), 40 deletions(-)
 create mode 100644 x86/efi.lds

diff --git a/.gitignore b/.gitignore
index b3cf2cb..f83bdf6 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 1d4d855..2d1b1bc 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
@@ -341,6 +351,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..fc9a693 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)
 
@@ -72,14 +88,14 @@ $(TEST_DIR)/realmode.elf: $(TEST_DIR)/realmode.o
 
 $(TEST_DIR)/realmode.o: bits = $(if $(call cc-option,-m16,""),16,32)
 
-$(TEST_DIR)/kvmclock_test.elf: $(TEST_DIR)/kvmclock.o
+$(TEST_DIR)/kvmclock_test.$(bin): $(TEST_DIR)/kvmclock.o
 
-$(TEST_DIR)/hyperv_synic.elf: $(TEST_DIR)/hyperv.o
+$(TEST_DIR)/hyperv_synic.$(bin): $(TEST_DIR)/hyperv.o
 
-$(TEST_DIR)/hyperv_stimer.elf: $(TEST_DIR)/hyperv.o
+$(TEST_DIR)/hyperv_stimer.$(bin): $(TEST_DIR)/hyperv.o
 
-$(TEST_DIR)/hyperv_connections.elf: $(TEST_DIR)/hyperv.o
+$(TEST_DIR)/hyperv_connections.$(bin): $(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..f6c7bd7 100644
--- a/x86/Makefile.x86_64
+++ b/x86/Makefile.x86_64
@@ -5,33 +5,46 @@ 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
+bin = so
+else
+out = flat
+bin = elf
+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
 
-$(TEST_DIR)/hyperv_clock.elf: $(TEST_DIR)/hyperv_clock.o
+$(TEST_DIR)/hyperv_clock.$(bin): $(TEST_DIR)/hyperv_clock.o
 
-$(TEST_DIR)/vmx.elf: $(TEST_DIR)/vmx_tests.o
-$(TEST_DIR)/svm.elf: $(TEST_DIR)/svm_tests.o
+$(TEST_DIR)/vmx.$(bin): $(TEST_DIR)/vmx_tests.o
+$(TEST_DIR)/svm.$(bin): $(TEST_DIR)/svm_tests.o
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] 14+ messages in thread

* [kvm-unit-tests PATCH v2 2/6] x86: Call efi_main from _efi_pe_entry
  2021-08-19 11:33 [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support Varad Gautam
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 1/6] x86: Build tests as PE objects for the EFI loader Varad Gautam
@ 2021-08-19 11:33 ` Varad Gautam
  2021-08-24 22:08   ` Krish Sadhukhan
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 3/6] x86: efi_main: Get EFI memory map and exit boot services Varad Gautam
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Varad Gautam @ 2021-08-19 11:33 UTC (permalink / raw)
  To: Zixuan Wang, Nadav Amit, Marc Orr, Joerg Roedel, kvm list,
	Linux Virtualization, Paolo Bonzini, Andrew Jones, bp,
	Thomas.Lendacky, brijesh.singh, Hyunwook Baek, Erdem Aktas,
	Tom Roeder
  Cc: 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    | 518 ++++++++++++++++++++++++++++++++++++++++++++
 x86/Makefile.common |   2 +-
 x86/cstart64.S      |  10 +-
 x86/efi_main.c      |  11 +
 4 files changed, 539 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..15692eb
--- /dev/null
+++ b/lib/linux/uefi.h
@@ -0,0 +1,518 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Relevant definitions from linux/efi.h. */
+
+#ifndef __LINUX_UEFI_H
+#define __LINUX_UEFI_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))
+
+/*
+ * The UEFI spec and EDK2 reference implementation both define EFI_GUID as
+ * struct { u32 a; u16; b; u16 c; u8 d[8]; }; and so the implied alignment
+ * is 32 bits not 8 bits like our guid_t. In some cases (i.e., on 32-bit ARM),
+ * this means that firmware services invoked by the kernel may assume that
+ * efi_guid_t* arguments are 32-bit aligned, and use memory accessors that
+ * do not tolerate misalignment. So let's set the minimum alignment to 32 bits.
+ *
+ * Note that the UEFI spec as well as some comments in the EDK2 code base
+ * suggest that EFI_GUID should be 64-bit aligned, but this appears to be
+ * a mistake, given that no code seems to exist that actually enforces that
+ * or relies on it.
+ */
+typedef struct {
+	u8 b[16];
+} guid_t;
+typedef guid_t efi_guid_t;
+
+#define EFI_GUID(a, b, c, d...) (efi_guid_t){ {					\
+	(a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff,	\
+	(b) & 0xff, ((b) >> 8) & 0xff,						\
+	(c) & 0xff, ((c) >> 8) & 0xff, d } }
+
+/*
+ * Generic EFI table header
+ */
+typedef	struct {
+	u64 signature;
+	u32 revision;
+	u32 headersize;
+	u32 crc32;
+	u32 reserved;
+} efi_table_hdr_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;
+
+typedef struct {
+	efi_guid_t guid;
+	u32 headersize;
+	u32 flags;
+	u32 imagesize;
+} efi_capsule_header_t;
+
+/*
+ * EFI capsule flags
+ */
+#define EFI_CAPSULE_PERSIST_ACROSS_RESET	0x00010000
+#define EFI_CAPSULE_POPULATE_SYSTEM_TABLE	0x00020000
+#define EFI_CAPSULE_INITIATE_RESET		0x00040000
+
+struct capsule_info {
+	efi_capsule_header_t	header;
+	efi_capsule_header_t	*capsule;
+	int			reset_type;
+	long			index;
+	size_t			count;
+	size_t			total_size;
+	struct page		**pages;
+	phys_addr_t		*phys;
+	size_t			page_bytes_remain;
+};
+
+int __efi_capsule_setup_info(struct capsule_info *cap_info);
+
+/*
+ * Types and defines for Time Services
+ */
+#define EFI_TIME_ADJUST_DAYLIGHT 0x1
+#define EFI_TIME_IN_DAYLIGHT     0x2
+#define EFI_UNSPECIFIED_TIMEZONE 0x07ff
+
+typedef struct {
+	u16 year;
+	u8 month;
+	u8 day;
+	u8 hour;
+	u8 minute;
+	u8 second;
+	u8 pad1;
+	u32 nanosecond;
+	s16 timezone;
+	u8 daylight;
+	u8 pad2;
+} efi_time_t;
+
+typedef struct {
+	u32 resolution;
+	u32 accuracy;
+	u8 sets_to_zero;
+} efi_time_cap_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 enum {
+	EfiTimerCancel,
+	EfiTimerPeriodic,
+	EfiTimerRelative
+} EFI_TIMER_DELAY;
+
+/*
+ * EFI Device Path information
+ */
+#define EFI_DEV_HW			0x01
+#define  EFI_DEV_PCI				 1
+#define  EFI_DEV_PCCARD				 2
+#define  EFI_DEV_MEM_MAPPED			 3
+#define  EFI_DEV_VENDOR				 4
+#define  EFI_DEV_CONTROLLER			 5
+#define EFI_DEV_ACPI			0x02
+#define   EFI_DEV_BASIC_ACPI			 1
+#define   EFI_DEV_EXPANDED_ACPI			 2
+#define EFI_DEV_MSG			0x03
+#define   EFI_DEV_MSG_ATAPI			 1
+#define   EFI_DEV_MSG_SCSI			 2
+#define   EFI_DEV_MSG_FC			 3
+#define   EFI_DEV_MSG_1394			 4
+#define   EFI_DEV_MSG_USB			 5
+#define   EFI_DEV_MSG_USB_CLASS			15
+#define   EFI_DEV_MSG_I20			 6
+#define   EFI_DEV_MSG_MAC			11
+#define   EFI_DEV_MSG_IPV4			12
+#define   EFI_DEV_MSG_IPV6			13
+#define   EFI_DEV_MSG_INFINIBAND		 9
+#define   EFI_DEV_MSG_UART			14
+#define   EFI_DEV_MSG_VENDOR			10
+#define EFI_DEV_MEDIA			0x04
+#define   EFI_DEV_MEDIA_HARD_DRIVE		 1
+#define   EFI_DEV_MEDIA_CDROM			 2
+#define   EFI_DEV_MEDIA_VENDOR			 3
+#define   EFI_DEV_MEDIA_FILE			 4
+#define   EFI_DEV_MEDIA_PROTOCOL		 5
+#define EFI_DEV_BIOS_BOOT		0x05
+#define EFI_DEV_END_PATH		0x7F
+#define EFI_DEV_END_PATH2		0xFF
+#define   EFI_DEV_END_INSTANCE			0x01
+#define   EFI_DEV_END_ENTIRE			0xFF
+
+struct efi_generic_dev_path {
+	u8				type;
+	u8				sub_type;
+	u16				length;
+} __packed;
+
+typedef struct efi_generic_dev_path efi_device_path_protocol_t;
+
+/*
+ * EFI Boot Services table
+ */
+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 *,
+						      efi_event_t *);
+		efi_status_t (__efiapi *set_timer)(efi_event_t,
+						  EFI_TIMER_DELAY, u64);
+		efi_status_t (__efiapi *wait_for_event)(unsigned long,
+							efi_event_t *,
+							unsigned long *);
+		void *signal_event;
+		efi_status_t (__efiapi *close_event)(efi_event_t);
+		void *check_event;
+		void *install_protocol_interface;
+		void *reinstall_protocol_interface;
+		void *uninstall_protocol_interface;
+		efi_status_t (__efiapi *handle_protocol)(efi_handle_t,
+							 efi_guid_t *, void **);
+		void *__reserved;
+		void *register_protocol_notify;
+		efi_status_t (__efiapi *locate_handle)(int, efi_guid_t *,
+						       void *, unsigned long *,
+						       efi_handle_t *);
+		efi_status_t (__efiapi *locate_device_path)(efi_guid_t *,
+							    efi_device_path_protocol_t **,
+							    efi_handle_t *);
+		efi_status_t (__efiapi *install_configuration_table)(efi_guid_t *,
+								     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)(efi_guid_t *, 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;
+
+/*
+ * Types and defines for EFI ResetSystem
+ */
+#define EFI_RESET_COLD 0
+#define EFI_RESET_WARM 1
+#define EFI_RESET_SHUTDOWN 2
+
+/*
+ * EFI Runtime Services table
+ */
+#define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL)
+#define EFI_RUNTIME_SERVICES_REVISION  0x00010000
+
+typedef struct {
+	efi_table_hdr_t hdr;
+	u32 get_time;
+	u32 set_time;
+	u32 get_wakeup_time;
+	u32 set_wakeup_time;
+	u32 set_virtual_address_map;
+	u32 convert_pointer;
+	u32 get_variable;
+	u32 get_next_variable;
+	u32 set_variable;
+	u32 get_next_high_mono_count;
+	u32 reset_system;
+	u32 update_capsule;
+	u32 query_capsule_caps;
+	u32 query_variable_info;
+} efi_runtime_services_32_t;
+
+typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc);
+typedef efi_status_t efi_set_time_t (efi_time_t *tm);
+typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending,
+					    efi_time_t *tm);
+typedef efi_status_t efi_set_wakeup_time_t (efi_bool_t enabled, efi_time_t *tm);
+typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
+					 unsigned long *data_size, void *data);
+typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name,
+					      efi_guid_t *vendor);
+typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor, 
+					 u32 attr, unsigned long data_size,
+					 void *data);
+typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count);
+typedef void efi_reset_system_t (int reset_type, efi_status_t status,
+				 unsigned long data_size, efi_char16_t *data);
+typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_size,
+						unsigned long descriptor_size,
+						u32 descriptor_version,
+						efi_memory_desc_t *virtual_map);
+typedef efi_status_t efi_query_variable_info_t(u32 attr,
+					       u64 *storage_space,
+					       u64 *remaining_space,
+					       u64 *max_variable_size);
+typedef efi_status_t efi_update_capsule_t(efi_capsule_header_t **capsules,
+					  unsigned long count,
+					  unsigned long sg_list);
+typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
+					      unsigned long count,
+					      u64 *max_size,
+					      int *reset_type);
+typedef efi_status_t efi_query_variable_store_t(u32 attributes,
+						unsigned long size,
+						bool nonblocking);
+
+typedef union {
+	struct {
+		efi_table_hdr_t				hdr;
+		efi_get_time_t __efiapi			*get_time;
+		efi_set_time_t __efiapi			*set_time;
+		efi_get_wakeup_time_t __efiapi		*get_wakeup_time;
+		efi_set_wakeup_time_t __efiapi		*set_wakeup_time;
+		efi_set_virtual_address_map_t __efiapi	*set_virtual_address_map;
+		void					*convert_pointer;
+		efi_get_variable_t __efiapi		*get_variable;
+		efi_get_next_variable_t __efiapi	*get_next_variable;
+		efi_set_variable_t __efiapi		*set_variable;
+		efi_get_next_high_mono_count_t __efiapi	*get_next_high_mono_count;
+		efi_reset_system_t __efiapi		*reset_system;
+		efi_update_capsule_t __efiapi		*update_capsule;
+		efi_query_capsule_caps_t __efiapi	*query_capsule_caps;
+		efi_query_variable_info_t __efiapi	*query_variable_info;
+	};
+	efi_runtime_services_32_t mixed_mode;
+} efi_runtime_services_t;
+
+#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
+
+#define EFI_2_30_SYSTEM_TABLE_REVISION  ((2 << 16) | (30))
+#define EFI_2_20_SYSTEM_TABLE_REVISION  ((2 << 16) | (20))
+#define EFI_2_10_SYSTEM_TABLE_REVISION  ((2 << 16) | (10))
+#define EFI_2_00_SYSTEM_TABLE_REVISION  ((2 << 16) | (00))
+#define EFI_1_10_SYSTEM_TABLE_REVISION  ((1 << 16) | (10))
+#define EFI_1_02_SYSTEM_TABLE_REVISION  ((1 << 16) | (02))
+
+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 efi_simple_text_input_protocol efi_simple_text_input_protocol_t;
+typedef union efi_simple_text_output_protocol efi_simple_text_output_protocol_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;
+		efi_runtime_services_t *runtime;
+		efi_boot_services_t *boottime;
+		unsigned long nr_tables;
+		unsigned long tables;
+	};
+	efi_system_table_32_t mixed_mode;
+} efi_system_table_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 fc9a693..ca33e8e 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] 14+ messages in thread

* [kvm-unit-tests PATCH v2 3/6] x86: efi_main: Get EFI memory map and exit boot services
  2021-08-19 11:33 [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support Varad Gautam
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 1/6] x86: Build tests as PE objects for the EFI loader Varad Gautam
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 2/6] x86: Call efi_main from _efi_pe_entry Varad Gautam
@ 2021-08-19 11:33 ` Varad Gautam
  2021-08-24 22:10   ` Krish Sadhukhan
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 4/6] x86: efi_main: Self-relocate ELF .dynamic addresses Varad Gautam
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Varad Gautam @ 2021-08-19 11:33 UTC (permalink / raw)
  To: Zixuan Wang, Nadav Amit, Marc Orr, Joerg Roedel, kvm list,
	Linux Virtualization, Paolo Bonzini, Andrew Jones, bp,
	Thomas.Lendacky, brijesh.singh, Hyunwook Baek, Erdem Aktas,
	Tom Roeder
  Cc: 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] 14+ messages in thread

* [kvm-unit-tests PATCH v2 4/6] x86: efi_main: Self-relocate ELF .dynamic addresses
  2021-08-19 11:33 [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support Varad Gautam
                   ` (2 preceding siblings ...)
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 3/6] x86: efi_main: Get EFI memory map and exit boot services Varad Gautam
@ 2021-08-19 11:33 ` Varad Gautam
  2021-08-24 22:10   ` Krish Sadhukhan
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 5/6] cstart64.S: x86_64 bootstrapping after exiting EFI Varad Gautam
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Varad Gautam @ 2021-08-19 11:33 UTC (permalink / raw)
  To: Zixuan Wang, Nadav Amit, Marc Orr, Joerg Roedel, kvm list,
	Linux Virtualization, Paolo Bonzini, Andrew Jones, bp,
	Thomas.Lendacky, brijesh.singh, Hyunwook Baek, Erdem Aktas,
	Tom Roeder
  Cc: 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] 14+ messages in thread

* [kvm-unit-tests PATCH v2 5/6] cstart64.S: x86_64 bootstrapping after exiting EFI
  2021-08-19 11:33 [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support Varad Gautam
                   ` (3 preceding siblings ...)
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 4/6] x86: efi_main: Self-relocate ELF .dynamic addresses Varad Gautam
@ 2021-08-19 11:33 ` Varad Gautam
  2021-08-24 22:11   ` Krish Sadhukhan
  2021-08-19 11:34 ` [kvm-unit-tests PATCH v2 6/6] x86 UEFI: Convert x86 test cases to PIC Varad Gautam
  2021-08-21  0:01 ` [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support Sean Christopherson
  6 siblings, 1 reply; 14+ messages in thread
From: Varad Gautam @ 2021-08-19 11:33 UTC (permalink / raw)
  To: Zixuan Wang, Nadav Amit, Marc Orr, Joerg Roedel, kvm list,
	Linux Virtualization, Paolo Bonzini, Andrew Jones, bp,
	Thomas.Lendacky, brijesh.singh, Hyunwook Baek, Erdem Aktas,
	Tom Roeder
  Cc: 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>
---
v2: Fix TSS setup in cstart64 on CONFIG_EFI.

 x86/cstart64.S | 70 +++++++++++++++++++++++++++++++++++++++++++++-----
 x86/efi_main.c |  1 +
 2 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/x86/cstart64.S b/x86/cstart64.S
index 98e7848..547f3fb 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,38 @@ 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)
+	call load_tss
+
+	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 +303,27 @@ _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
+#ifndef CONFIG_EFI
 	call load_tss
+#endif
 	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 +331,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:
@@ -330,6 +375,7 @@ online_cpus:
 load_tss:
 #ifndef CONFIG_EFI
 	lidtq idt_descr
+#endif
 	mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
 	mov (%rax), %eax
 	shr $24, %eax
@@ -337,6 +383,18 @@ load_tss:
 	shl $4, %ebx
 	mov $((tss_end - tss) / max_cpus), %edx
 	imul %edx
+#ifdef CONFIG_EFI
+	lea tss(%rip), %rax
+	lea tss_descr(%rip), %rcx
+	add %rbx, %rcx
+	mov %ax, 2(%rcx)
+	shr $16, %rax
+	mov %al, 4(%rcx)
+	shr $8, %rax
+	mov %al, 7(%rcx)
+	shr $8, %rax
+	mov %eax, 8(%rcx)
+#else
 	add $tss, %rax
 	mov %ax, tss_descr+2(%rbx)
 	shr $16, %rax
@@ -345,9 +403,9 @@ load_tss:
 	mov %al, tss_descr+7(%rbx)
 	shr $8, %rax
 	mov %eax, tss_descr+8(%rbx)
+#endif
 	lea tss_descr-gdt64(%rbx), %rax
 	ltr %ax
-#endif
 	ret
 
 ap_init:
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] 14+ messages in thread

* [kvm-unit-tests PATCH v2 6/6] x86 UEFI: Convert x86 test cases to PIC
  2021-08-19 11:33 [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support Varad Gautam
                   ` (4 preceding siblings ...)
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 5/6] cstart64.S: x86_64 bootstrapping after exiting EFI Varad Gautam
@ 2021-08-19 11:34 ` Varad Gautam
  2021-08-24 22:12   ` Krish Sadhukhan
  2021-08-21  0:01 ` [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support Sean Christopherson
  6 siblings, 1 reply; 14+ messages in thread
From: Varad Gautam @ 2021-08-19 11:34 UTC (permalink / raw)
  To: Zixuan Wang, Nadav Amit, Marc Orr, Joerg Roedel, kvm list,
	Linux Virtualization, Paolo Bonzini, Andrew Jones, bp,
	Thomas.Lendacky, brijesh.singh, Hyunwook Baek, Erdem Aktas,
	Tom Roeder

From: Zixuan Wang <zixuanwang@google.com>

UEFI loads EFI applications to dynamic runtime addresses, so it requires
all applications to be compiled as PIC (position independent code). PIC
does not allow the usage of compile time absolute address.

This commit converts multiple x86 test cases to PIC so they can compile
and run in UEFI:

- x86/cet.efi

- x86/emulator.c: x86/emulator.c depends on lib/x86/usermode.c. But
usermode.c contains non-PIC inline assembly code and thus blocks the
compilation with GNU-EFI. This commit converts lib/x86/usermode.c and
x86/emulator.c to PIC, so x86/emulator.c can compile and run in UEFI.

- x86/vmware_backdoors.c: it depends on lib/x86/usermode.c and now works
without modifications

- x86/eventinj.c

- x86/smap.c

- x86/access.c

- x86/umip.c

Signed-off-by: Zixuan Wang <zixuanwang@google.com>
---
 lib/x86/usermode.c  |  3 ++-
 x86/Makefile.common |  7 ++++---
 x86/Makefile.x86_64 |  5 +++--
 x86/access.c        |  6 +++---
 x86/cet.c           |  8 +++++---
 x86/emulator.c      |  5 +++--
 x86/eventinj.c      |  6 ++++--
 x86/smap.c          |  8 ++++----
 x86/umip.c          | 10 +++++++---
 9 files changed, 35 insertions(+), 23 deletions(-)

diff --git a/lib/x86/usermode.c b/lib/x86/usermode.c
index f032523..c550545 100644
--- a/lib/x86/usermode.c
+++ b/lib/x86/usermode.c
@@ -58,7 +58,8 @@ uint64_t run_in_user(usermode_func func, unsigned int fault_vector,
 			"pushq %[user_stack_top]\n\t"
 			"pushfq\n\t"
 			"pushq %[user_cs]\n\t"
-			"pushq $user_mode\n\t"
+			"lea user_mode(%%rip), %%rdx\n\t"
+			"pushq %%rdx\n\t"
 			"iretq\n"
 
 			"user_mode:\n\t"
diff --git a/x86/Makefile.common b/x86/Makefile.common
index ca33e8e..a91fd4c 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -61,8 +61,8 @@ FLATLIBS = lib/libcflat.a
 		    -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-flatonly = $(TEST_DIR)/realmode.$(out)						\
+		$(TEST_DIR)/smap.$(out)
 
 tests-common = $(TEST_DIR)/vmexit.$(out) $(TEST_DIR)/tsc.$(out)				\
 		$(TEST_DIR)/smptest.$(out) $(TEST_DIR)/msr.$(out)			\
@@ -72,7 +72,8 @@ tests-common = $(TEST_DIR)/vmexit.$(out) $(TEST_DIR)/tsc.$(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)/tsx-ctrl.$(out)						\
+		$(TEST_DIR)/eventinj.$(out) $(TEST_DIR)/umip.$(out)
 
 ifneq ($(CONFIG_EFI),y)
 tests-common += $(tests-flatonly)
diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64
index f6c7bd7..e8843aa 100644
--- a/x86/Makefile.x86_64
+++ b/x86/Makefile.x86_64
@@ -18,9 +18,8 @@ cflatobjs += lib/x86/intel-iommu.o
 cflatobjs += lib/x86/usermode.o
 
 # Tests that have relocation / PIC problems and need more attention for EFI.
-tests_flatonly = $(TEST_DIR)/access.$(out) $(TEST_DIR)/emulator.$(out) \
+tests_flatonly = $(TEST_DIR)/access.$(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) \
@@ -33,6 +32,8 @@ tests += $(TEST_DIR)/intel-iommu.$(out)
 tests += $(TEST_DIR)/rdpru.$(out)
 tests += $(TEST_DIR)/pks.$(out)
 tests += $(TEST_DIR)/pmu_lbr.$(out)
+tests += $(TEST_DIR)/emulator.$(out)
+tests += $(TEST_DIR)/vmware_backdoors.$(out)
 
 ifneq ($(fcf_protection_full),)
 tests_flatonly += $(TEST_DIR)/cet.$(out)
diff --git a/x86/access.c b/x86/access.c
index 4725bbd..d0c84ca 100644
--- a/x86/access.c
+++ b/x86/access.c
@@ -700,7 +700,7 @@ static int ac_test_do_access(ac_test_t *at)
 
     if (F(AC_ACCESS_TWICE)) {
 	asm volatile (
-	    "mov $fixed2, %%rsi \n\t"
+	    "lea fixed2(%%rip), %%rsi \n\t"
 	    "mov (%[addr]), %[reg] \n\t"
 	    "fixed2:"
 	    : [reg]"=r"(r), [fault]"=a"(fault), "=b"(e)
@@ -710,7 +710,7 @@ static int ac_test_do_access(ac_test_t *at)
 	fault = 0;
     }
 
-    asm volatile ("mov $fixed1, %%rsi \n\t"
+    asm volatile ("lea fixed1(%%rip), %%rsi \n\t"
 		  "mov %%rsp, %%rdx \n\t"
 		  "cmp $0, %[user] \n\t"
 		  "jz do_access \n\t"
@@ -719,7 +719,7 @@ static int ac_test_do_access(ac_test_t *at)
 		  "pushq %[user_stack_top] \n\t"
 		  "pushfq \n\t"
 		  "pushq %[user_cs] \n\t"
-		  "pushq $do_access \n\t"
+		  "lea do_access(%%rip), %%rsi; pushq %%rsi; lea fixed1(%%rip), %%rsi\n\t"
 		  "iretq \n"
 		  "do_access: \n\t"
 		  "cmp $0, %[fetch] \n\t"
diff --git a/x86/cet.c b/x86/cet.c
index a21577a..a4b79cb 100644
--- a/x86/cet.c
+++ b/x86/cet.c
@@ -52,7 +52,7 @@ static u64 cet_ibt_func(void)
 	printf("No endbr64 instruction at jmp target, this triggers #CP...\n");
 	asm volatile ("movq $2, %rcx\n"
 		      "dec %rcx\n"
-		      "leaq 2f, %rax\n"
+		      "leaq 2f(%rip), %rax\n"
 		      "jmp *%rax \n"
 		      "2:\n"
 		      "dec %rcx\n");
@@ -67,7 +67,8 @@ void test_func(void) {
 			"pushq %[user_stack_top]\n\t"
 			"pushfq\n\t"
 			"pushq %[user_cs]\n\t"
-			"pushq $user_mode\n\t"
+			"lea user_mode(%%rip), %%rax\n\t"
+			"pushq %%rax\n\t"
 			"iretq\n"
 
 			"user_mode:\n\t"
@@ -77,7 +78,8 @@ void test_func(void) {
 			[user_ds]"i"(USER_DS),
 			[user_cs]"i"(USER_CS),
 			[user_stack_top]"r"(user_stack +
-					sizeof(user_stack)));
+					sizeof(user_stack))
+			: "rax");
 }
 
 #define SAVE_REGS() \
diff --git a/x86/emulator.c b/x86/emulator.c
index 9fda1a0..4d2de24 100644
--- a/x86/emulator.c
+++ b/x86/emulator.c
@@ -262,12 +262,13 @@ static void test_pop(void *mem)
 
 	asm volatile("mov %%rsp, %[tmp] \n\t"
 		     "mov %[stack_top], %%rsp \n\t"
-		     "push $1f \n\t"
+		     "lea 1f(%%rip), %%rax \n\t"
+		     "push %%rax \n\t"
 		     "ret \n\t"
 		     "2: jmp 2b \n\t"
 		     "1: mov %[tmp], %%rsp"
 		     : [tmp]"=&r"(tmp) : [stack_top]"r"(stack_top)
-		     : "memory");
+		     : "memory", "rax");
 	report(1, "ret");
 
 	stack_top[-1] = 0x778899;
diff --git a/x86/eventinj.c b/x86/eventinj.c
index 46593c9..0cd68e8 100644
--- a/x86/eventinj.c
+++ b/x86/eventinj.c
@@ -155,9 +155,11 @@ asm("do_iret:"
 	"pushf"W" \n\t"
 	"mov %cs, %ecx \n\t"
 	"push"W" %"R "cx \n\t"
-	"push"W" $2f \n\t"
+	"lea"W" 2f(%"R "ip), %"R "bx \n\t"
+	"push"W" %"R "bx \n\t"
 
-	"cmpb $0, no_test_device\n\t"	// see if need to flush
+	"mov no_test_device(%"R "ip), %bl \n\t"
+	"cmpb $0, %bl\n\t"		// see if need to flush
 	"jnz 1f\n\t"
 	"outl %eax, $0xe4 \n\t"		// flush page
 	"1: \n\t"
diff --git a/x86/smap.c b/x86/smap.c
index ac2c8d5..b3ee16f 100644
--- a/x86/smap.c
+++ b/x86/smap.c
@@ -161,10 +161,10 @@ int main(int ac, char **av)
 		test = -1;
 		asm("or $(" xstr(USER_BASE) "), %"R "sp \n"
 		    "push $44 \n "
-		    "decl test\n"
+		    "decl test(%"R "ip)\n"
 		    "and $~(" xstr(USER_BASE) "), %"R "sp \n"
 		    "pop %"R "ax\n"
-		    "movl %eax, test");
+		    "movl %eax, test(%"R "ip)");
 		report(pf_count == 0 && test == 44,
 		       "write to user stack with AC=1");
 
@@ -173,10 +173,10 @@ int main(int ac, char **av)
 		test = -1;
 		asm("or $(" xstr(USER_BASE) "), %"R "sp \n"
 		    "push $45 \n "
-		    "decl test\n"
+		    "decl test(%"R "ip)\n"
 		    "and $~(" xstr(USER_BASE) "), %"R "sp \n"
 		    "pop %"R "ax\n"
-		    "movl %eax, test");
+		    "movl %eax, test(%"R "ip)");
 		report(pf_count == 1 && test == 45 && save == -1,
 		       "write to user stack with AC=0");
 
diff --git a/x86/umip.c b/x86/umip.c
index c5700b3..8b4e798 100644
--- a/x86/umip.c
+++ b/x86/umip.c
@@ -23,7 +23,10 @@ static void gp_handler(struct ex_regs *regs)
 
 #define GP_ASM(stmt, in, clobber)                  \
     asm volatile (                                 \
-          "mov" W " $1f, %[expected_rip]\n\t"      \
+          "push" W " %%" R "ax\n\t"                \
+	  "lea 1f(%%" R "ip), %%" R "ax\n\t"       \
+          "mov %%" R "ax, %[expected_rip]\n\t"     \
+          "pop" W " %%" R "ax\n\t"                 \
           "movl $2f-1f, %[skip_count]\n\t"         \
           "1: " stmt "\n\t"                        \
           "2: "                                    \
@@ -130,7 +133,8 @@ static int do_ring3(void (*fn)(const char *), const char *arg)
 		  "push" W " %%" R "dx \n\t"
 		  "pushf" W "\n\t"
 		  "push" W " %[user_cs] \n\t"
-		  "push" W " $1f \n\t"
+		  "lea 1f(%%" R "ip), %%" R "dx \n\t"
+		  "push" W " %%" R "dx \n\t"
 		  "iret" W "\n"
 		  "1: \n\t"
 		  "push %%" R "cx\n\t"   /* save kernel SP */
@@ -144,7 +148,7 @@ static int do_ring3(void (*fn)(const char *), const char *arg)
 #endif
 
 		  "pop %%" R "cx\n\t"
-		  "mov $1f, %%" R "dx\n\t"
+		  "lea 1f(%%" R "ip), %%" R "dx\n\t"
 		  "int %[kernel_entry_vector]\n\t"
 		  ".section .text.entry \n\t"
 		  "kernel_entry: \n\t"
-- 
2.30.2


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

* Re: [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support
  2021-08-19 11:33 [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support Varad Gautam
                   ` (5 preceding siblings ...)
  2021-08-19 11:34 ` [kvm-unit-tests PATCH v2 6/6] x86 UEFI: Convert x86 test cases to PIC Varad Gautam
@ 2021-08-21  0:01 ` Sean Christopherson
  2021-08-21  0:42   ` Zixuan Wang
  6 siblings, 1 reply; 14+ messages in thread
From: Sean Christopherson @ 2021-08-21  0:01 UTC (permalink / raw)
  To: Varad Gautam
  Cc: Zixuan Wang, Nadav Amit, Marc Orr, Joerg Roedel, kvm list,
	Linux Virtualization, Paolo Bonzini, Andrew Jones, bp,
	Thomas.Lendacky, brijesh.singh, Hyunwook Baek, Erdem Aktas,
	Tom Roeder, Varad Gautam

On Thu, Aug 19, 2021, Varad Gautam wrote:
> This series brings EFI support to kvm-unit-tests on x86_64.
> 
> 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 from Zixuan [1] fixes up some testcases with non-PIC inline
> asm stubs which allows building these as PIC.
> 
> Changes in v2:
> - Add Zixuan's patch to enable more testcases.
> - Fix TSS setup in cstart64.S for CONFIG_EFI.
> 
> [1]: https://lore.kernel.org/r/20210818000905.1111226-10-zixuanwang@google.com/
> git tree: https://github.com/varadgautam/kvm-unit-tests/tree/efi-stub-v2
> 
> Varad Gautam (5):
>   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

Zixuan and Varad, are your two series complimentary or do they conflict?  E.g.
can Zixuan's series be applied on top with little-to-no change to Varad's patches,
or are both series trying to do the same things in different ways?

And if they conflict, are the conflicts largely superficial, or are there
fundamental differences in how the problems are being solved?

Thanks!

> Zixuan Wang (1):
>   x86 UEFI: Convert x86 test cases to PIC

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

* Re: [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support
  2021-08-21  0:01 ` [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support Sean Christopherson
@ 2021-08-21  0:42   ` Zixuan Wang
  0 siblings, 0 replies; 14+ messages in thread
From: Zixuan Wang @ 2021-08-21  0:42 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Varad Gautam, Nadav Amit, Marc Orr, Joerg Roedel, kvm list,
	Linux Virtualization, Paolo Bonzini, Andrew Jones, bp,
	Thomas.Lendacky, brijesh.singh, Hyunwook Baek, Erdem Aktas,
	Tom Roeder, Varad Gautam

On Fri, Aug 20, 2021 at 5:01 PM Sean Christopherson <seanjc@google.com> wrote:
>
> On Thu, Aug 19, 2021, Varad Gautam wrote:
> > This series brings EFI support to kvm-unit-tests on x86_64.
> >
> > 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 from Zixuan [1] fixes up some testcases with non-PIC inline
> > asm stubs which allows building these as PIC.
> >
> > Changes in v2:
> > - Add Zixuan's patch to enable more testcases.
> > - Fix TSS setup in cstart64.S for CONFIG_EFI.
> >
> > [1]: https://lore.kernel.org/r/20210818000905.1111226-10-zixuanwang@google.com/
> > git tree: https://github.com/varadgautam/kvm-unit-tests/tree/efi-stub-v2
> >
> > Varad Gautam (5):
> >   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
>
> Zixuan and Varad, are your two series complimentary or do they conflict?  E.g.
> can Zixuan's series be applied on top with little-to-no change to Varad's patches,
> or are both series trying to do the same things in different ways?
>
> And if they conflict, are the conflicts largely superficial, or are there
> fundamental differences in how the problems are being solved?
>
> Thanks!

I’m currently building my patches on top of Varad’s. This does not
require too many changes to my patches: I just need to (1) replace the
GNU-EFI function calls with Varad’s approach; (2) copy more
EFI-related definitions from Linux to implement several additional
UEFI service calls, e.g. a reset_system() call to shutdown the guest
VM; and (3) remove some duplicated code from Varad’s patches, e.g. I
remove Varad’s modifications in x86/cstart64.S because I implement
similar setup code in lib/x86/setup.c.

This migration affects only the first part of my patch series, and I’m
currently working on it. Hopefully I can send out the second version
where I take Varad’s patches as the foundation of mine.

Regards,
Zixuan

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

* Re: [kvm-unit-tests PATCH v2 2/6] x86: Call efi_main from _efi_pe_entry
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 2/6] x86: Call efi_main from _efi_pe_entry Varad Gautam
@ 2021-08-24 22:08   ` Krish Sadhukhan
  0 siblings, 0 replies; 14+ messages in thread
From: Krish Sadhukhan @ 2021-08-24 22:08 UTC (permalink / raw)
  To: Varad Gautam, Zixuan Wang, Nadav Amit, Marc Orr, Joerg Roedel,
	kvm list, Linux Virtualization, Paolo Bonzini, Andrew Jones, bp,
	Thomas.Lendacky, brijesh.singh, Hyunwook Baek, Erdem Aktas,
	Tom Roeder
  Cc: Varad Gautam


On 8/19/21 4:33 AM, Varad Gautam wrote:
> 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    | 518 ++++++++++++++++++++++++++++++++++++++++++++
>   x86/Makefile.common |   2 +-
>   x86/cstart64.S      |  10 +-
>   x86/efi_main.c      |  11 +
>   4 files changed, 539 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..15692eb
> --- /dev/null
> +++ b/lib/linux/uefi.h
> @@ -0,0 +1,518 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Relevant definitions from linux/efi.h. */
> +
> +#ifndef __LINUX_UEFI_H
> +#define __LINUX_UEFI_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))
> +
> +/*
> + * The UEFI spec and EDK2 reference implementation both define EFI_GUID as
> + * struct { u32 a; u16; b; u16 c; u8 d[8]; }; and so the implied alignment
> + * is 32 bits not 8 bits like our guid_t. In some cases (i.e., on 32-bit ARM),
> + * this means that firmware services invoked by the kernel may assume that
> + * efi_guid_t* arguments are 32-bit aligned, and use memory accessors that
> + * do not tolerate misalignment. So let's set the minimum alignment to 32 bits.
> + *
> + * Note that the UEFI spec as well as some comments in the EDK2 code base
> + * suggest that EFI_GUID should be 64-bit aligned, but this appears to be
> + * a mistake, given that no code seems to exist that actually enforces that
> + * or relies on it.
> + */
> +typedef struct {
> +	u8 b[16];
> +} guid_t;
> +typedef guid_t efi_guid_t;
> +
> +#define EFI_GUID(a, b, c, d...) (efi_guid_t){ {					\
> +	(a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff,	\
> +	(b) & 0xff, ((b) >> 8) & 0xff,						\
> +	(c) & 0xff, ((c) >> 8) & 0xff, d } }
> +
> +/*
> + * Generic EFI table header
> + */
> +typedef	struct {
> +	u64 signature;
> +	u32 revision;
> +	u32 headersize;
> +	u32 crc32;
> +	u32 reserved;
> +} efi_table_hdr_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;
> +
> +typedef struct {
> +	efi_guid_t guid;
> +	u32 headersize;
> +	u32 flags;
> +	u32 imagesize;
> +} efi_capsule_header_t;
> +
> +/*
> + * EFI capsule flags
> + */
> +#define EFI_CAPSULE_PERSIST_ACROSS_RESET	0x00010000
> +#define EFI_CAPSULE_POPULATE_SYSTEM_TABLE	0x00020000
> +#define EFI_CAPSULE_INITIATE_RESET		0x00040000
> +
> +struct capsule_info {
> +	efi_capsule_header_t	header;
> +	efi_capsule_header_t	*capsule;
> +	int			reset_type;
> +	long			index;
> +	size_t			count;
> +	size_t			total_size;
> +	struct page		**pages;
> +	phys_addr_t		*phys;
> +	size_t			page_bytes_remain;
> +};
> +
> +int __efi_capsule_setup_info(struct capsule_info *cap_info);
> +
> +/*
> + * Types and defines for Time Services
> + */
> +#define EFI_TIME_ADJUST_DAYLIGHT 0x1
> +#define EFI_TIME_IN_DAYLIGHT     0x2
> +#define EFI_UNSPECIFIED_TIMEZONE 0x07ff
> +
> +typedef struct {
> +	u16 year;
> +	u8 month;
> +	u8 day;
> +	u8 hour;
> +	u8 minute;
> +	u8 second;
> +	u8 pad1;
> +	u32 nanosecond;
> +	s16 timezone;
> +	u8 daylight;
> +	u8 pad2;
> +} efi_time_t;
> +
> +typedef struct {
> +	u32 resolution;
> +	u32 accuracy;
> +	u8 sets_to_zero;
> +} efi_time_cap_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 enum {
> +	EfiTimerCancel,
> +	EfiTimerPeriodic,
> +	EfiTimerRelative
> +} EFI_TIMER_DELAY;
> +
> +/*
> + * EFI Device Path information
> + */
> +#define EFI_DEV_HW			0x01
> +#define  EFI_DEV_PCI				 1
> +#define  EFI_DEV_PCCARD				 2
> +#define  EFI_DEV_MEM_MAPPED			 3
> +#define  EFI_DEV_VENDOR				 4
> +#define  EFI_DEV_CONTROLLER			 5
> +#define EFI_DEV_ACPI			0x02
> +#define   EFI_DEV_BASIC_ACPI			 1
> +#define   EFI_DEV_EXPANDED_ACPI			 2
> +#define EFI_DEV_MSG			0x03
> +#define   EFI_DEV_MSG_ATAPI			 1
> +#define   EFI_DEV_MSG_SCSI			 2
> +#define   EFI_DEV_MSG_FC			 3
> +#define   EFI_DEV_MSG_1394			 4
> +#define   EFI_DEV_MSG_USB			 5
> +#define   EFI_DEV_MSG_USB_CLASS			15
> +#define   EFI_DEV_MSG_I20			 6
> +#define   EFI_DEV_MSG_MAC			11
> +#define   EFI_DEV_MSG_IPV4			12
> +#define   EFI_DEV_MSG_IPV6			13
> +#define   EFI_DEV_MSG_INFINIBAND		 9
> +#define   EFI_DEV_MSG_UART			14
> +#define   EFI_DEV_MSG_VENDOR			10
> +#define EFI_DEV_MEDIA			0x04
> +#define   EFI_DEV_MEDIA_HARD_DRIVE		 1
> +#define   EFI_DEV_MEDIA_CDROM			 2
> +#define   EFI_DEV_MEDIA_VENDOR			 3
> +#define   EFI_DEV_MEDIA_FILE			 4
> +#define   EFI_DEV_MEDIA_PROTOCOL		 5
> +#define EFI_DEV_BIOS_BOOT		0x05
> +#define EFI_DEV_END_PATH		0x7F
> +#define EFI_DEV_END_PATH2		0xFF
> +#define   EFI_DEV_END_INSTANCE			0x01
> +#define   EFI_DEV_END_ENTIRE			0xFF
> +
> +struct efi_generic_dev_path {
> +	u8				type;
> +	u8				sub_type;
> +	u16				length;
> +} __packed;
> +
> +typedef struct efi_generic_dev_path efi_device_path_protocol_t;


BTW, the following syntax is also allowed by gcc and you can use it here:

+typedef struct efi_generic_dev_path {
+	u8				type;
+	u8				sub_type;
+	u16				length;
+} __packed, efi_device_path_protocol_t;

> +
> +/*
> + * EFI Boot Services table
> + */
> +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 *,
> +						      efi_event_t *);
> +		efi_status_t (__efiapi *set_timer)(efi_event_t,
> +						  EFI_TIMER_DELAY, u64);
> +		efi_status_t (__efiapi *wait_for_event)(unsigned long,
> +							efi_event_t *,
> +							unsigned long *);
> +		void *signal_event;
> +		efi_status_t (__efiapi *close_event)(efi_event_t);
> +		void *check_event;
> +		void *install_protocol_interface;
> +		void *reinstall_protocol_interface;
> +		void *uninstall_protocol_interface;
> +		efi_status_t (__efiapi *handle_protocol)(efi_handle_t,
> +							 efi_guid_t *, void **);
> +		void *__reserved;
> +		void *register_protocol_notify;
> +		efi_status_t (__efiapi *locate_handle)(int, efi_guid_t *,
> +						       void *, unsigned long *,
> +						       efi_handle_t *);
> +		efi_status_t (__efiapi *locate_device_path)(efi_guid_t *,
> +							    efi_device_path_protocol_t **,
> +							    efi_handle_t *);
> +		efi_status_t (__efiapi *install_configuration_table)(efi_guid_t *,
> +								     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)(efi_guid_t *, 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;


It's probably better to group the function pointers together for 
readability purposes.

> +	};
> +	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;


Just curious why we need mixed mode because we are building the tests as 
64-bit UEFI executable.

> +};
> +
> +typedef union efi_boot_services efi_boot_services_t;
> +
> +/*
> + * Types and defines for EFI ResetSystem
> + */
> +#define EFI_RESET_COLD 0
> +#define EFI_RESET_WARM 1
> +#define EFI_RESET_SHUTDOWN 2
> +
> +/*
> + * EFI Runtime Services table
> + */
> +#define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL)
> +#define EFI_RUNTIME_SERVICES_REVISION  0x00010000
> +
> +typedef struct {
> +	efi_table_hdr_t hdr;
> +	u32 get_time;
> +	u32 set_time;
> +	u32 get_wakeup_time;
> +	u32 set_wakeup_time;
> +	u32 set_virtual_address_map;
> +	u32 convert_pointer;
> +	u32 get_variable;
> +	u32 get_next_variable;
> +	u32 set_variable;
> +	u32 get_next_high_mono_count;
> +	u32 reset_system;
> +	u32 update_capsule;
> +	u32 query_capsule_caps;
> +	u32 query_variable_info;
> +} efi_runtime_services_32_t;
> +
> +typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc);
> +typedef efi_status_t efi_set_time_t (efi_time_t *tm);
> +typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending,
> +					    efi_time_t *tm);
> +typedef efi_status_t efi_set_wakeup_time_t (efi_bool_t enabled, efi_time_t *tm);
> +typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
> +					 unsigned long *data_size, void *data);
> +typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name,
> +					      efi_guid_t *vendor);
> +typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor,
> +					 u32 attr, unsigned long data_size,
> +					 void *data);
> +typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count);
> +typedef void efi_reset_system_t (int reset_type, efi_status_t status,
> +				 unsigned long data_size, efi_char16_t *data);
> +typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_size,
> +						unsigned long descriptor_size,
> +						u32 descriptor_version,
> +						efi_memory_desc_t *virtual_map);
> +typedef efi_status_t efi_query_variable_info_t(u32 attr,
> +					       u64 *storage_space,
> +					       u64 *remaining_space,
> +					       u64 *max_variable_size);
> +typedef efi_status_t efi_update_capsule_t(efi_capsule_header_t **capsules,
> +					  unsigned long count,
> +					  unsigned long sg_list);
> +typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
> +					      unsigned long count,
> +					      u64 *max_size,
> +					      int *reset_type);
> +typedef efi_status_t efi_query_variable_store_t(u32 attributes,
> +						unsigned long size,
> +						bool nonblocking);
> +
> +typedef union {
> +	struct {
> +		efi_table_hdr_t				hdr;
> +		efi_get_time_t __efiapi			*get_time;
> +		efi_set_time_t __efiapi			*set_time;
> +		efi_get_wakeup_time_t __efiapi		*get_wakeup_time;
> +		efi_set_wakeup_time_t __efiapi		*set_wakeup_time;
> +		efi_set_virtual_address_map_t __efiapi	*set_virtual_address_map;
> +		void					*convert_pointer;
> +		efi_get_variable_t __efiapi		*get_variable;
> +		efi_get_next_variable_t __efiapi	*get_next_variable;
> +		efi_set_variable_t __efiapi		*set_variable;
> +		efi_get_next_high_mono_count_t __efiapi	*get_next_high_mono_count;
> +		efi_reset_system_t __efiapi		*reset_system;
> +		efi_update_capsule_t __efiapi		*update_capsule;
> +		efi_query_capsule_caps_t __efiapi	*query_capsule_caps;
> +		efi_query_variable_info_t __efiapi	*query_variable_info;
> +	};
> +	efi_runtime_services_32_t mixed_mode;
> +} efi_runtime_services_t;
> +
> +#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
> +
> +#define EFI_2_30_SYSTEM_TABLE_REVISION  ((2 << 16) | (30))
> +#define EFI_2_20_SYSTEM_TABLE_REVISION  ((2 << 16) | (20))
> +#define EFI_2_10_SYSTEM_TABLE_REVISION  ((2 << 16) | (10))
> +#define EFI_2_00_SYSTEM_TABLE_REVISION  ((2 << 16) | (00))
> +#define EFI_1_10_SYSTEM_TABLE_REVISION  ((1 << 16) | (10))
> +#define EFI_1_02_SYSTEM_TABLE_REVISION  ((1 << 16) | (02))
> +
> +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 efi_simple_text_input_protocol efi_simple_text_input_protocol_t;
> +typedef union efi_simple_text_output_protocol efi_simple_text_output_protocol_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;
> +		efi_runtime_services_t *runtime;
> +		efi_boot_services_t *boottime;
> +		unsigned long nr_tables;
> +		unsigned long tables;
> +	};
> +	efi_system_table_32_t mixed_mode;
> +} efi_system_table_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 fc9a693..ca33e8e 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;
> +}

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

* Re: [kvm-unit-tests PATCH v2 3/6] x86: efi_main: Get EFI memory map and exit boot services
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 3/6] x86: efi_main: Get EFI memory map and exit boot services Varad Gautam
@ 2021-08-24 22:10   ` Krish Sadhukhan
  0 siblings, 0 replies; 14+ messages in thread
From: Krish Sadhukhan @ 2021-08-24 22:10 UTC (permalink / raw)
  To: Varad Gautam, Zixuan Wang, Nadav Amit, Marc Orr, Joerg Roedel,
	kvm list, Linux Virtualization, Paolo Bonzini, Andrew Jones, bp,
	Thomas.Lendacky, brijesh.singh, Hyunwook Baek, Erdem Aktas,
	Tom Roeder
  Cc: Varad Gautam


On 8/19/21 4:33 AM, Varad Gautam wrote:
> 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)


Based on the naming pattern, we should call it 'efi_exit' ?

> +{
> +	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;
> +	}


The kernel calls efi_get_memory_map() inside of 
efi_exit_boot_services(). May be we should stick to the same call-chain 
pattern to minimize deviation ?

May be, we should add a check for EFI table signature like the following 
kernel check ?

     if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
                 efi_exit(handle, EFI_INVALID_PARAMETER);

> +
> +	/* 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;
>   }

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

* Re: [kvm-unit-tests PATCH v2 4/6] x86: efi_main: Self-relocate ELF .dynamic addresses
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 4/6] x86: efi_main: Self-relocate ELF .dynamic addresses Varad Gautam
@ 2021-08-24 22:10   ` Krish Sadhukhan
  0 siblings, 0 replies; 14+ messages in thread
From: Krish Sadhukhan @ 2021-08-24 22:10 UTC (permalink / raw)
  To: Varad Gautam, Zixuan Wang, Nadav Amit, Marc Orr, Joerg Roedel,
	kvm list, Linux Virtualization, Paolo Bonzini, Andrew Jones, bp,
	Thomas.Lendacky, brijesh.singh, Hyunwook Baek, Erdem Aktas,
	Tom Roeder
  Cc: Varad Gautam


On 8/19/21 4:33 AM, Varad Gautam wrote:
> 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)


Since this function is only relocating the dynamic section, we should 
probably name it something like elf_reloc_dyn().

> +{
> +	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();


Should this call to start64() be moved to your next patch because the 
function needs to be fixed and you are fixing it in there ?

> +
>   	return 0;
>   }

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

* Re: [kvm-unit-tests PATCH v2 5/6] cstart64.S: x86_64 bootstrapping after exiting EFI
  2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 5/6] cstart64.S: x86_64 bootstrapping after exiting EFI Varad Gautam
@ 2021-08-24 22:11   ` Krish Sadhukhan
  0 siblings, 0 replies; 14+ messages in thread
From: Krish Sadhukhan @ 2021-08-24 22:11 UTC (permalink / raw)
  To: Varad Gautam, Zixuan Wang, Nadav Amit, Marc Orr, Joerg Roedel,
	kvm list, Linux Virtualization, Paolo Bonzini, Andrew Jones, bp,
	Thomas.Lendacky, brijesh.singh, Hyunwook Baek, Erdem Aktas,
	Tom Roeder
  Cc: Varad Gautam


On 8/19/21 4:33 AM, Varad Gautam wrote:
> 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>
> ---
> v2: Fix TSS setup in cstart64 on CONFIG_EFI.
>
>   x86/cstart64.S | 70 +++++++++++++++++++++++++++++++++++++++++++++-----
>   x86/efi_main.c |  1 +
>   2 files changed, 65 insertions(+), 6 deletions(-)
>
> diff --git a/x86/cstart64.S b/x86/cstart64.S
> index 98e7848..547f3fb 100644
> --- a/x86/cstart64.S
> +++ b/x86/cstart64.S


I am wondering if it's cleaner to create a separate .S file for EFI 
because so many #ifdefs are reducing readability of the code.

> @@ -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,38 @@ 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)
> +	call load_tss
> +
> +	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 +303,27 @@ _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
> +#ifndef CONFIG_EFI
>   	call load_tss
> +#endif
>   	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 +331,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:
> @@ -330,6 +375,7 @@ online_cpus:
>   load_tss:
>   #ifndef CONFIG_EFI
>   	lidtq idt_descr
> +#endif
>   	mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
>   	mov (%rax), %eax
>   	shr $24, %eax
> @@ -337,6 +383,18 @@ load_tss:
>   	shl $4, %ebx
>   	mov $((tss_end - tss) / max_cpus), %edx
>   	imul %edx
> +#ifdef CONFIG_EFI
> +	lea tss(%rip), %rax
> +	lea tss_descr(%rip), %rcx
> +	add %rbx, %rcx
> +	mov %ax, 2(%rcx)
> +	shr $16, %rax
> +	mov %al, 4(%rcx)
> +	shr $8, %rax
> +	mov %al, 7(%rcx)
> +	shr $8, %rax
> +	mov %eax, 8(%rcx)
> +#else
>   	add $tss, %rax
>   	mov %ax, tss_descr+2(%rbx)
>   	shr $16, %rax
> @@ -345,9 +403,9 @@ load_tss:
>   	mov %al, tss_descr+7(%rbx)
>   	shr $8, %rax
>   	mov %eax, tss_descr+8(%rbx)
> +#endif
>   	lea tss_descr-gdt64(%rbx), %rax
>   	ltr %ax
> -#endif
>   	ret
>   
>   ap_init:
> 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)
>   {

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

* Re: [kvm-unit-tests PATCH v2 6/6] x86 UEFI: Convert x86 test cases to PIC
  2021-08-19 11:34 ` [kvm-unit-tests PATCH v2 6/6] x86 UEFI: Convert x86 test cases to PIC Varad Gautam
@ 2021-08-24 22:12   ` Krish Sadhukhan
  0 siblings, 0 replies; 14+ messages in thread
From: Krish Sadhukhan @ 2021-08-24 22:12 UTC (permalink / raw)
  To: Varad Gautam, Zixuan Wang, Nadav Amit, Marc Orr, Joerg Roedel,
	kvm list, Linux Virtualization, Paolo Bonzini, Andrew Jones, bp,
	Thomas.Lendacky, brijesh.singh, Hyunwook Baek, Erdem Aktas,
	Tom Roeder


On 8/19/21 4:34 AM, Varad Gautam wrote:
> From: Zixuan Wang <zixuanwang@google.com>
>
> UEFI loads EFI applications to dynamic runtime addresses, so it requires
> all applications to be compiled as PIC (position independent code). PIC
> does not allow the usage of compile time absolute address.
>
> This commit converts multiple x86 test cases to PIC so they can compile
> and run in UEFI:
>
> - x86/cet.efi
>
> - x86/emulator.c: x86/emulator.c depends on lib/x86/usermode.c. But
> usermode.c contains non-PIC inline assembly code and thus blocks the
> compilation with GNU-EFI. This commit converts lib/x86/usermode.c and
> x86/emulator.c to PIC, so x86/emulator.c can compile and run in UEFI.
>
> - x86/vmware_backdoors.c: it depends on lib/x86/usermode.c and now works
> without modifications
>
> - x86/eventinj.c
>
> - x86/smap.c
>
> - x86/access.c
>
> - x86/umip.c


I am wondering if these changes can be part of patch# 1 instead of being 
a separate patch.

>
> Signed-off-by: Zixuan Wang <zixuanwang@google.com>
> ---
>   lib/x86/usermode.c  |  3 ++-
>   x86/Makefile.common |  7 ++++---
>   x86/Makefile.x86_64 |  5 +++--
>   x86/access.c        |  6 +++---
>   x86/cet.c           |  8 +++++---
>   x86/emulator.c      |  5 +++--
>   x86/eventinj.c      |  6 ++++--
>   x86/smap.c          |  8 ++++----
>   x86/umip.c          | 10 +++++++---
>   9 files changed, 35 insertions(+), 23 deletions(-)
>
> diff --git a/lib/x86/usermode.c b/lib/x86/usermode.c
> index f032523..c550545 100644
> --- a/lib/x86/usermode.c
> +++ b/lib/x86/usermode.c
> @@ -58,7 +58,8 @@ uint64_t run_in_user(usermode_func func, unsigned int fault_vector,
>   			"pushq %[user_stack_top]\n\t"
>   			"pushfq\n\t"
>   			"pushq %[user_cs]\n\t"
> -			"pushq $user_mode\n\t"
> +			"lea user_mode(%%rip), %%rdx\n\t"
> +			"pushq %%rdx\n\t"
>   			"iretq\n"
>   
>   			"user_mode:\n\t"
> diff --git a/x86/Makefile.common b/x86/Makefile.common
> index ca33e8e..a91fd4c 100644
> --- a/x86/Makefile.common
> +++ b/x86/Makefile.common
> @@ -61,8 +61,8 @@ FLATLIBS = lib/libcflat.a
>   		    -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-flatonly = $(TEST_DIR)/realmode.$(out)						\
> +		$(TEST_DIR)/smap.$(out)
>   
>   tests-common = $(TEST_DIR)/vmexit.$(out) $(TEST_DIR)/tsc.$(out)				\
>   		$(TEST_DIR)/smptest.$(out) $(TEST_DIR)/msr.$(out)			\
> @@ -72,7 +72,8 @@ tests-common = $(TEST_DIR)/vmexit.$(out) $(TEST_DIR)/tsc.$(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)/tsx-ctrl.$(out)						\
> +		$(TEST_DIR)/eventinj.$(out) $(TEST_DIR)/umip.$(out)
>   
>   ifneq ($(CONFIG_EFI),y)
>   tests-common += $(tests-flatonly)
> diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64
> index f6c7bd7..e8843aa 100644
> --- a/x86/Makefile.x86_64
> +++ b/x86/Makefile.x86_64
> @@ -18,9 +18,8 @@ cflatobjs += lib/x86/intel-iommu.o
>   cflatobjs += lib/x86/usermode.o
>   
>   # Tests that have relocation / PIC problems and need more attention for EFI.
> -tests_flatonly = $(TEST_DIR)/access.$(out) $(TEST_DIR)/emulator.$(out) \
> +tests_flatonly = $(TEST_DIR)/access.$(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) \
> @@ -33,6 +32,8 @@ tests += $(TEST_DIR)/intel-iommu.$(out)
>   tests += $(TEST_DIR)/rdpru.$(out)
>   tests += $(TEST_DIR)/pks.$(out)
>   tests += $(TEST_DIR)/pmu_lbr.$(out)
> +tests += $(TEST_DIR)/emulator.$(out)
> +tests += $(TEST_DIR)/vmware_backdoors.$(out)
>   
>   ifneq ($(fcf_protection_full),)
>   tests_flatonly += $(TEST_DIR)/cet.$(out)
> diff --git a/x86/access.c b/x86/access.c
> index 4725bbd..d0c84ca 100644
> --- a/x86/access.c
> +++ b/x86/access.c
> @@ -700,7 +700,7 @@ static int ac_test_do_access(ac_test_t *at)
>   
>       if (F(AC_ACCESS_TWICE)) {
>   	asm volatile (
> -	    "mov $fixed2, %%rsi \n\t"
> +	    "lea fixed2(%%rip), %%rsi \n\t"
>   	    "mov (%[addr]), %[reg] \n\t"
>   	    "fixed2:"
>   	    : [reg]"=r"(r), [fault]"=a"(fault), "=b"(e)
> @@ -710,7 +710,7 @@ static int ac_test_do_access(ac_test_t *at)
>   	fault = 0;
>       }
>   
> -    asm volatile ("mov $fixed1, %%rsi \n\t"
> +    asm volatile ("lea fixed1(%%rip), %%rsi \n\t"
>   		  "mov %%rsp, %%rdx \n\t"
>   		  "cmp $0, %[user] \n\t"
>   		  "jz do_access \n\t"
> @@ -719,7 +719,7 @@ static int ac_test_do_access(ac_test_t *at)
>   		  "pushq %[user_stack_top] \n\t"
>   		  "pushfq \n\t"
>   		  "pushq %[user_cs] \n\t"
> -		  "pushq $do_access \n\t"
> +		  "lea do_access(%%rip), %%rsi; pushq %%rsi; lea fixed1(%%rip), %%rsi\n\t"
>   		  "iretq \n"
>   		  "do_access: \n\t"
>   		  "cmp $0, %[fetch] \n\t"
> diff --git a/x86/cet.c b/x86/cet.c
> index a21577a..a4b79cb 100644
> --- a/x86/cet.c
> +++ b/x86/cet.c
> @@ -52,7 +52,7 @@ static u64 cet_ibt_func(void)
>   	printf("No endbr64 instruction at jmp target, this triggers #CP...\n");
>   	asm volatile ("movq $2, %rcx\n"
>   		      "dec %rcx\n"
> -		      "leaq 2f, %rax\n"
> +		      "leaq 2f(%rip), %rax\n"
>   		      "jmp *%rax \n"
>   		      "2:\n"
>   		      "dec %rcx\n");
> @@ -67,7 +67,8 @@ void test_func(void) {
>   			"pushq %[user_stack_top]\n\t"
>   			"pushfq\n\t"
>   			"pushq %[user_cs]\n\t"
> -			"pushq $user_mode\n\t"
> +			"lea user_mode(%%rip), %%rax\n\t"
> +			"pushq %%rax\n\t"
>   			"iretq\n"
>   
>   			"user_mode:\n\t"
> @@ -77,7 +78,8 @@ void test_func(void) {
>   			[user_ds]"i"(USER_DS),
>   			[user_cs]"i"(USER_CS),
>   			[user_stack_top]"r"(user_stack +
> -					sizeof(user_stack)));
> +					sizeof(user_stack))
> +			: "rax");
>   }
>   
>   #define SAVE_REGS() \
> diff --git a/x86/emulator.c b/x86/emulator.c
> index 9fda1a0..4d2de24 100644
> --- a/x86/emulator.c
> +++ b/x86/emulator.c
> @@ -262,12 +262,13 @@ static void test_pop(void *mem)
>   
>   	asm volatile("mov %%rsp, %[tmp] \n\t"
>   		     "mov %[stack_top], %%rsp \n\t"
> -		     "push $1f \n\t"
> +		     "lea 1f(%%rip), %%rax \n\t"
> +		     "push %%rax \n\t"
>   		     "ret \n\t"
>   		     "2: jmp 2b \n\t"
>   		     "1: mov %[tmp], %%rsp"
>   		     : [tmp]"=&r"(tmp) : [stack_top]"r"(stack_top)
> -		     : "memory");
> +		     : "memory", "rax");
>   	report(1, "ret");
>   
>   	stack_top[-1] = 0x778899;
> diff --git a/x86/eventinj.c b/x86/eventinj.c
> index 46593c9..0cd68e8 100644
> --- a/x86/eventinj.c
> +++ b/x86/eventinj.c
> @@ -155,9 +155,11 @@ asm("do_iret:"
>   	"pushf"W" \n\t"
>   	"mov %cs, %ecx \n\t"
>   	"push"W" %"R "cx \n\t"
> -	"push"W" $2f \n\t"
> +	"lea"W" 2f(%"R "ip), %"R "bx \n\t"
> +	"push"W" %"R "bx \n\t"
>   
> -	"cmpb $0, no_test_device\n\t"	// see if need to flush
> +	"mov no_test_device(%"R "ip), %bl \n\t"
> +	"cmpb $0, %bl\n\t"		// see if need to flush
>   	"jnz 1f\n\t"
>   	"outl %eax, $0xe4 \n\t"		// flush page
>   	"1: \n\t"
> diff --git a/x86/smap.c b/x86/smap.c
> index ac2c8d5..b3ee16f 100644
> --- a/x86/smap.c
> +++ b/x86/smap.c
> @@ -161,10 +161,10 @@ int main(int ac, char **av)
>   		test = -1;
>   		asm("or $(" xstr(USER_BASE) "), %"R "sp \n"
>   		    "push $44 \n "
> -		    "decl test\n"
> +		    "decl test(%"R "ip)\n"
>   		    "and $~(" xstr(USER_BASE) "), %"R "sp \n"
>   		    "pop %"R "ax\n"
> -		    "movl %eax, test");
> +		    "movl %eax, test(%"R "ip)");
>   		report(pf_count == 0 && test == 44,
>   		       "write to user stack with AC=1");
>   
> @@ -173,10 +173,10 @@ int main(int ac, char **av)
>   		test = -1;
>   		asm("or $(" xstr(USER_BASE) "), %"R "sp \n"
>   		    "push $45 \n "
> -		    "decl test\n"
> +		    "decl test(%"R "ip)\n"
>   		    "and $~(" xstr(USER_BASE) "), %"R "sp \n"
>   		    "pop %"R "ax\n"
> -		    "movl %eax, test");
> +		    "movl %eax, test(%"R "ip)");
>   		report(pf_count == 1 && test == 45 && save == -1,
>   		       "write to user stack with AC=0");
>   
> diff --git a/x86/umip.c b/x86/umip.c
> index c5700b3..8b4e798 100644
> --- a/x86/umip.c
> +++ b/x86/umip.c
> @@ -23,7 +23,10 @@ static void gp_handler(struct ex_regs *regs)
>   
>   #define GP_ASM(stmt, in, clobber)                  \
>       asm volatile (                                 \
> -          "mov" W " $1f, %[expected_rip]\n\t"      \
> +          "push" W " %%" R "ax\n\t"                \
> +	  "lea 1f(%%" R "ip), %%" R "ax\n\t"       \
> +          "mov %%" R "ax, %[expected_rip]\n\t"     \
> +          "pop" W " %%" R "ax\n\t"                 \
>             "movl $2f-1f, %[skip_count]\n\t"         \
>             "1: " stmt "\n\t"                        \
>             "2: "                                    \
> @@ -130,7 +133,8 @@ static int do_ring3(void (*fn)(const char *), const char *arg)
>   		  "push" W " %%" R "dx \n\t"
>   		  "pushf" W "\n\t"
>   		  "push" W " %[user_cs] \n\t"
> -		  "push" W " $1f \n\t"
> +		  "lea 1f(%%" R "ip), %%" R "dx \n\t"
> +		  "push" W " %%" R "dx \n\t"
>   		  "iret" W "\n"
>   		  "1: \n\t"
>   		  "push %%" R "cx\n\t"   /* save kernel SP */
> @@ -144,7 +148,7 @@ static int do_ring3(void (*fn)(const char *), const char *arg)
>   #endif
>   
>   		  "pop %%" R "cx\n\t"
> -		  "mov $1f, %%" R "dx\n\t"
> +		  "lea 1f(%%" R "ip), %%" R "dx\n\t"
>   		  "int %[kernel_entry_vector]\n\t"
>   		  ".section .text.entry \n\t"
>   		  "kernel_entry: \n\t"

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

end of thread, other threads:[~2021-08-24 22:13 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-19 11:33 [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support Varad Gautam
2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 1/6] x86: Build tests as PE objects for the EFI loader Varad Gautam
2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 2/6] x86: Call efi_main from _efi_pe_entry Varad Gautam
2021-08-24 22:08   ` Krish Sadhukhan
2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 3/6] x86: efi_main: Get EFI memory map and exit boot services Varad Gautam
2021-08-24 22:10   ` Krish Sadhukhan
2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 4/6] x86: efi_main: Self-relocate ELF .dynamic addresses Varad Gautam
2021-08-24 22:10   ` Krish Sadhukhan
2021-08-19 11:33 ` [kvm-unit-tests PATCH v2 5/6] cstart64.S: x86_64 bootstrapping after exiting EFI Varad Gautam
2021-08-24 22:11   ` Krish Sadhukhan
2021-08-19 11:34 ` [kvm-unit-tests PATCH v2 6/6] x86 UEFI: Convert x86 test cases to PIC Varad Gautam
2021-08-24 22:12   ` Krish Sadhukhan
2021-08-21  0:01 ` [kvm-unit-tests PATCH v2 0/6] Initial x86_64 UEFI support Sean Christopherson
2021-08-21  0:42   ` Zixuan Wang

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.