Short summary for Gleb and Paolo:

- qemu master + kvm_intel (3.10) run both OVMF/master and
  OVMF/master+SeaBIOS/master CSM well, including booting a legacy OS

- qemu master + TCG spirals into an endless loop when trying to boot a
  legacy OS with OVMF+CSM -- I'm not focusing on this right now,

- qemu master + kvm_amd (3.10) throws an emulation failure with pure
  OVMF immediately at startup:

On 09/03/13 11:56, Laszlo Ersek wrote:
> On 09/03/13 01:05, Rod Smith wrote:
>> On 09/02/2013 05:32 PM, Laszlo Ersek wrote:
>
>>> Maybe -enable-kvm would make a difference...
>>
>> It causes it to crash with a new set of error messages:
>>
>> KVM internal error. Suberror: 1
>> emulation failure
>> EAX=c0000033 EBX=fffcc0e4 ECX=c0000080 EDX=00000000
>> ESI=fffcc2c4 EDI=00005042 EBP=fffcc000 ESP=00000000
>> EIP=ffffff26 EFL=00000082 [--S----] CPL=0 II=0 A20=1 SMM=0 HLT=0
>> ES =0008 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
>> CS =0010 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
>> SS =0008 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
>> DS =0008 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
>> FS =0008 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
>> GS =0008 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
>> LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
>> TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS64-busy
>> GDT=     00000000ffffff80 0000001f
>> IDT=     0000000000000000 0000ffff
>> CR0=c0000033 CR2=0000000000000000 CR3=00000000ffffe000 CR4=00000660
>> DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000
>> DR3=0000000000000000
>> DR6=00000000ffff0ff0 DR7=0000000000000400
>> EFER=0000000000000500
>> Code=00 c0 0f 32 0f ba e8 08 0f 30 0f 20 c0 0f ba e8 1f 0f 22 c0 <ea>
>> 2d ff ff ff 18 00 e9 93 00 00 00 fa bb 00 f0 8e db bb 6c ff 2e 66 0f
>> 01 17 66 b8 23 00
>> Connected to RFB server, using protocol version 3.8
>>
>> the kvm and kvm_amd modules are loaded on my system when this
>> happens.

In the qemu monitor:

(qemu) x /20i 0xffffffefd
0x0000000ffffffefd:  mov    $0xffffe000,%eax
0x0000000fffffff02:  mov    %eax,%cr3
0x0000000fffffff05:  mov    %cr4,%eax
0x0000000fffffff08:  bts    $0x5,%eax
0x0000000fffffff0c:  mov    %eax,%cr4
0x0000000fffffff0f:  mov    $0xc0000080,%ecx
0x0000000fffffff14:  rdmsr
0x0000000fffffff16:  bts    $0x8,%eax
0x0000000fffffff1a:  wrmsr
0x0000000fffffff1c:  mov    %cr0,%eax
0x0000000fffffff1f:  bts    $0x1f,%eax
0x0000000fffffff23:  mov    %eax,%cr0
0x0000000fffffff26:  ljmp   $0x18,$0xffffff2d <------ emul. failure here
0x0000000fffffff2d:  jmp    0xffffffc5

This guest disassembly is part of the UEFI reset vector code under
UefiCpuPkg/ResetVector/Vtf0.

Main16                            [Main.asm]
  EarlyInit16                     [Ia16/Init16.asm]
  TransitionFromReal16To32BitFlat [Ia16/Real16ToFlat32.asm]
  Flat32SearchForBfvBase          [Ia32/SearchForBfvBase.asm]
  Flat32SearchForSecEntryPoint    [Ia32/SearchForSecEntry.asm]
  Transition32FlatTo64Flat        [Ia32/Flat32ToFlat64.asm]

The Transition32FlatTo64Flat "function" has the following source,
corresponding to the qemu disassembly:

> BITS    32
>
> ;
> ; Modified:  EAX
> ;
> Transition32FlatTo64Flat:
>
>     mov     eax, ((ADDR_OF_START_OF_RESET_CODE & ~0xfff) - 0x1000)
>     mov     cr3, eax

0x0000000ffffffefd:  mov    $0xffffe000,%eax
0x0000000fffffff02:  mov    %eax,%cr3

>
>     mov     eax, cr4
>     bts     eax, 5                      ; enable PAE
>     mov     cr4, eax

0x0000000fffffff05:  mov    %cr4,%eax
0x0000000fffffff08:  bts    $0x5,%eax
0x0000000fffffff0c:  mov    %eax,%cr4

>
>     mov     ecx, 0xc0000080
>     rdmsr
>     bts     eax, 8                      ; set LME
>     wrmsr

0x0000000fffffff0f:  mov    $0xc0000080,%ecx
0x0000000fffffff14:  rdmsr
0x0000000fffffff16:  bts    $0x8,%eax
0x0000000fffffff1a:  wrmsr

>
>     mov     eax, cr0
>     bts     eax, 31                     ; set PG
>     mov     cr0, eax                    ; enable paging

0x0000000fffffff1c:  mov    %cr0,%eax
0x0000000fffffff1f:  bts    $0x1f,%eax
0x0000000fffffff23:  mov    %eax,%cr0

>
>     jmp     LINEAR_CODE64_SEL:ADDR_OF(jumpTo64BitAndLandHere)

0x0000000fffffff26:  ljmp   $0x18,$0xffffff2d <------ emul. failure here

> BITS    64
> jumpTo64BitAndLandHere:
>
>     debugShowPostCode POSTCODE_64BIT_MODE
>
>     OneTimeCallRet Transition32FlatTo64Flat

0x0000000fffffff2d:  jmp    0xffffffc5


"LINEAR_CODE64_SEL" is defined in "Ia16/Real16ToFlat32.asm" as:

> ;
> ; The Global Descriptor Table (GDT)
> ;
>
> GDT_BASE:
> ; null descriptor
> [...]
>
> ; linear data segment descriptor
> LINEAR_SEL          equ $-GDT_BASE
> [...]
>
> ; linear code segment descriptor
> LINEAR_CODE_SEL     equ $-GDT_BASE
> [...]
>
> %ifdef ARCH_X64
> ; linear code (64-bit) segment descriptor
> LINEAR_CODE64_SEL   equ $-GDT_BASE
>     DW      0xffff       ; limit 15:0
>     DW      0            ; base 15:0
>     DB      0            ; base 23:16
>     DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE64_TYPE)
>     DB      
> GRANULARITY_FLAG(1)|DEFAULT_SIZE32(0)|CODE64_FLAG(1)|UPPER_LIMIT(0xf)
>     DB      0            ; base 31:24
> %endif
>
> GDT_END:
>

I grepped the 3.10 kernel for KVM_INTERNAL_ERROR_EMULATION:

arch/x86/kvm/svm.c:             svm->vcpu.run->internal.suberror = 
KVM_INTERNAL_ERROR_EMULATION;
arch/x86/kvm/vmx.c:             vcpu->run->internal.suberror = 
KVM_INTERNAL_ERROR_EMULATION;
arch/x86/kvm/vmx.c:                     vcpu->run->internal.suberror = 
KVM_INTERNAL_ERROR_EMULATION;
arch/x86/kvm/x86.c:             vcpu->run->internal.suberror = 
KVM_INTERNAL_ERROR_EMULATION;
include/uapi/linux/kvm.h:#define KVM_INTERNAL_ERROR_EMULATION   1

"x86.c" would be my first guess (after x86_decode_insn() or
x86_emulate_insn() fails), but that's probably not it, considering that
the code runs fine on VMX and fails on SVM, and "x86.c" looks like a
shared file.

This is what trace-cmd has to say:

qemu-system-x86-29149 [002] 12270.789910: kvm_update_master_clock: masterclock 
0 hostclock tsc offsetmatched 0
qemu-system-x86-29149 [002] 12270.789977: kvm_fpu:              load
qemu-system-x86-29149 [002] 12270.789979: kvm_entry:            vcpu 0
qemu-system-x86-29149 [002] 12270.789987: kvm_exit:             reason EXIT_NPF 
rip 0xfff0 info 100000014 fffffff0
qemu-system-x86-29149 [002] 12270.789992: kvm_page_fault:       address 
fffffff0 error_code 14
qemu-system-x86-29149 [002] 12270.790022: kvm_entry:            vcpu 0
qemu-system-x86-29149 [002] 12270.790025: kvm_exit:             reason 
EXIT_WRITE_CR0 rip 0xff46 info 0 0
qemu-system-x86-29149 [002] 12270.790042: kvm_emulate_insn:     ffff0000:ff46: 
0f 22 c0
qemu-system-x86-29149 [002] 12270.790060: kvm_entry:            vcpu 0
qemu-system-x86-29149 [002] 12270.790063: kvm_exit:             reason 
EXIT_WRITE_CR4 rip 0xffffff56 info 0 0
qemu-system-x86-29149 [002] 12270.790065: kvm_emulate_insn:     0:ffffff56: 0f 
22 e0
qemu-system-x86-29149 [002] 12270.790069: kvm_entry:            vcpu 0
qemu-system-x86-29149 [002] 12270.790076: kvm_exit:             reason 
EXIT_READ_CR4 rip 0xffffff05 info 0 0
qemu-system-x86-29149 [002] 12270.790079: kvm_emulate_insn:     0:ffffff05: 0f 
20 e0
qemu-system-x86-29149 [002] 12270.790082: kvm_entry:            vcpu 0
qemu-system-x86-29149 [002] 12270.790084: kvm_exit:             reason 
EXIT_WRITE_CR4 rip 0xffffff0c info 0 0
qemu-system-x86-29149 [002] 12270.790086: kvm_emulate_insn:     0:ffffff0c: 0f 
22 e0
qemu-system-x86-29149 [002] 12270.790092: kvm_entry:            vcpu 0
qemu-system-x86-29149 [002] 12270.790095: kvm_exit:             reason EXIT_MSR 
rip 0xffffff14 info 0 0
qemu-system-x86-29149 [002] 12270.790097: kvm_msr:              msr_read 
c0000080 = 0x0
qemu-system-x86-29149 [002] 12270.790098: kvm_entry:            vcpu 0
qemu-system-x86-29149 [002] 12270.790100: kvm_exit:             reason EXIT_MSR 
rip 0xffffff1a info 1 0
qemu-system-x86-29149 [002] 12270.790102: kvm_msr:              msr_write 
c0000080 = 0x100
qemu-system-x86-29149 [002] 12270.790103: kvm_entry:            vcpu 0
qemu-system-x86-29149 [002] 12270.790105: kvm_exit:             reason 
EXIT_READ_CR0 rip 0xffffff1c info 0 0
qemu-system-x86-29149 [002] 12270.790108: kvm_emulate_insn:     0:ffffff1c: 0f 
20 c0
qemu-system-x86-29149 [002] 12270.790109: kvm_entry:            vcpu 0
qemu-system-x86-29149 [002] 12270.790112: kvm_exit:             reason 
EXIT_WRITE_CR0 rip 0xffffff23 info 0 0
qemu-system-x86-29149 [002] 12270.790113: kvm_emulate_insn:     0:ffffff23: 0f 
22 c0
qemu-system-x86-29149 [002] 12270.790121: kvm_entry:            vcpu 0
qemu-system-x86-29149 [002] 12270.790124: kvm_exit:             reason EXIT_NPF 
rip 0xffffff26 info 200000007 ffffe000
qemu-system-x86-29149 [002] 12270.790125: kvm_page_fault:       address 
ffffe000 error_code 7
qemu-system-x86-29149 [002] 12270.790129: kvm_emulate_insn:     0:ffffff26: 0f 
22 c0
qemu-system-x86-29149 [002] 12270.790131: kvm_emulate_insn:     0:ffffff26: 0f 
22 c0 FAIL
qemu-system-x86-29149 [002] 12270.790134: kvm_userspace_exit:   reason 
KVM_EXIT_INTERNAL_ERROR (17)
qemu-system-x86-29149 [002] 12270.790137: kvm_fpu:              unload

After all this does implicate x86_decode_insn():

x86_emulate_instruction()             [arch/x86/kvm/x86.c]
  x86_decode_insn()                   [arch/x86/kvm/emulate.c]
  trace_kvm_emulate_insn_start()
  handle_emulation_failure()          [arch/x86/kvm/x86.c]
    trace_kvm_emulate_insn_failed
    sets KVM_INTERNAL_ERROR_EMULATION

Interestingly, the trace lists "0f 22 c0", which corresponds to

  mov    %eax,%cr0

(see near "enable paging" above). So I'm not sure if the "ljmp" fails,
or the mov-to-cr0.

Volume 2 of the Intel SDM says under "MOV -- Move to/from Control
Registers" (we're in 32-bit mode, executing Transition32FlatTo64Flat):

Opcode   Instruction  Op/En 64-Bit Mode Compat/Leg Mode Description
-------- ------------ ----- ----------- --------------- -----------
0F 22 /r MOV CR0-CR7, A     Not         Valid           Move r32 to
         r32                Encodable                   control register

A reference is made to Volume 3, Chapter 22.4, "CHANGES TO INSTRUCTION
BEHAVIOR IN VMX NON-ROOT OPERATION"... which reads:

  MOV to CR0. An execution of MOV to CR0 that does not cause a VM exit
  (see Section 22.1.3) leaves unmodified any bit in CR0 corresponding to
  a bit set in the CR0 guest/host mask. Treatment of attempts to modify
  other bits in CR0 depends on the setting of the unrestricted guest
  VM-execution control: ^1

  - If the control is 0, MOV to CR0 causes a general-protection
    exception if it attempts to set any bit in CR0 to a value not
    supported in VMX operation (see Section 20.8).

  - If the control is 1, MOV to CR0 causes a general-protection
    exception if it attempts to set any bit in CR0 other than bit 0 (PE)
    or bit 31 (PG) to a value not supported in VMX operation. It remains
    the case, however, that MOV to CR0 causes a general-protection
    exception if it would result in CR0.PE = 0 and CR0.PG = 1 or if it
    would result in CR0.PG = 1, CR4.PAE = 0, and IA32_EFER.LME = 1.

Ugh, thanks anyway...

So, what's going on here? Perhaps, does this mov-to-cr0 *not* exit on
Intel, but unexpectedly exits on AMD, and the instruction emulator is
not prepared to handle it?

In x86_decode_insn():

        /* Opcode byte(s). */
        opcode = opcode_table[ctxt->b];
        /* Two-byte opcode? */
        if (ctxt->b == 0x0f) {
                ctxt->twobyte = 1;
                ctxt->b = insn_fetch(u8, ctxt);
                opcode = twobyte_table[ctxt->b];
        }
        ctxt->d = opcode.flags;

twobyte_table[0x22] is

        IIP(ModRM | SrcMem | Priv | Op3264, em_cr_write, cr_write, 
check_cr_write),

which at least appears to match mov-to-cr0.


I guess Rod is the first user who tried OVMF on SVM...

Thanks
Laszlo

------------------------------------------------------------------------------
Learn the latest--Visual Studio 2012, SharePoint 2013, SQL 2012, more!
Discover the easy way to master current and previous Microsoft technologies
and advance your career. Get an incredible 1,500+ hours of step-by-step
tutorial videos with LearnDevNow. Subscribe today and save!
http://pubads.g.doubleclick.net/gampad/clk?id=58040911&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to