On Thu, Feb 10, 2022, Hou Wenlong wrote: > Per Intel's SDM on the "Instruction Set Reference", when > loading segment descriptor for far return, not-present segment > check should be after all type and privilege checks. However, > __load_segment_descriptor() in x86's emulator does not-present > segment check first, so it would trigger #NP instead of #GP > if type or privilege checks fail and the segment is not present. > > And if RPL < CPL, it should trigger #GP, but the check is missing > in emulator. > > So add some tests for far ret instruction, and it will test > those tests on hardware and emulator. Enable > kvm.force_emulation_prefix when try to test them on emulator. > > Signed-off-by: Hou Wenlong <houwenlong.hwl@xxxxxxxxxxxx> > --- With fixup for the -fPIC issue... Reviewed-and-tested-by: Sean Christopherson <seanjc@xxxxxxxxxx> > +#define TEST_FAR_RET_ASM(seg, prefix) \ > +({ \ > + asm volatile("lea 1f(%%rip), %%rax\n\t" \ > + "pushq %[asm_seg]\n\t" \ > + "pushq $2f\n\t" \ > + prefix "lretq\n\t" \ > + "1: addq $16, %%rsp\n\t" \ > + "2:" \ > + : : [asm_seg]"r"((u64)seg) \ > + : "eax", "memory"); \ > +}) The "push $2f" generates an absolute address and fails to build with --target-efi, which requires -fPIC. The easiest thing that comes to mind is to load the address into RAX and then push RAX. The lea to get the exception IRET target into RAX needs to be moved down, but that's ok. --- x86/emulator.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/x86/emulator.c b/x86/emulator.c index c56b32b..c62dced 100644 --- a/x86/emulator.c +++ b/x86/emulator.c @@ -66,9 +66,10 @@ static struct far_xfer_test far_ret_test = { #define TEST_FAR_RET_ASM(seg, prefix) \ ({ \ - asm volatile("lea 1f(%%rip), %%rax\n\t" \ - "pushq %[asm_seg]\n\t" \ - "pushq $2f\n\t" \ + asm volatile("pushq %[asm_seg]\n\t" \ + "lea 2f(%%rip), %%rax\n\t" \ + "pushq %%rax\n\t" \ + "lea 1f(%%rip), %%rax\n\t" \ prefix "lretq\n\t" \ "1: addq $16, %%rsp\n\t" \ "2:" \ base-commit: 41d3306e19784478679910ee0afa55de05279b42 --