Hi All,
I recently met an issue, I can't boot my centos guest in below scenarios.
I disabled kvmvapic by
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index c3829e3..52be2b0 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -440,7 +440,7 @@ static const VMStateDescription vmstate_apic_common = { static Property apic_properties_common[] = { DEFINE_PROP_UINT8("version", APICCommonState, version, 0x14), DEFINE_PROP_BIT("vapic", APICCommonState, vapic_control, VAPIC_ENABLE_BIT, - true), + false), DEFINE_PROP_BOOL("legacy-instance-id", APICCommonState, legacy_instance_id, false), DEFINE_PROP_END_OF_LIST(),
I run Qemu in TCG mode
./x86_64-softmmu/qemu-system-x86_64 -bios /home/root/git/seabios/out/bios.bin -machine q35 -m 1G -drive format=raw,file=/home/root/images/centos7.2.img,if=ide,index=0 -nographic -nodefaults -serial stdio -monitor pty
It can't boot with below message, " Booting from Hard Disk... WARNING - Timeout at ahci_command:154! Boot failed: could not read the boot disk
enter handle_18: NULL Booting from Floppy... Boot failed: could not read the boot disk "
Once I add kvmvapic , it can boot.
I dig into seebios code, and found ahci_process_op is called with A20 off,
The call trace is, process_op_16->process_op_both->call32->call32_smm->process_op_32->ahci_process_op
call32_smm calls call32_prep, but because the method is C16_SMM, A20 is not enabled in call32_prep. ahci_process_op is called with A20 off.
ahci_process_op accesses memory mapped IO to operate ahci, the IO is mapped to 0xfebff000, because a20 is disabled, the bit 20 of 0xfebff000 is set 0 , which is 0xfeaff000, an iotlb entry mapping 0xfebff000 to 0xfeaff000 is added to iotlb cache. So ahci_process_op actually accesses 0xfeaff000, it obviously won't work.
target/i386/helper.c
do_mapping: pte = pte & env->a20_mask;
Why does guest boot with kvmvapic? In above scenario, there is no option roms. After adding kvmvapic, there is one option rom kvmvapic rom, and __callrom is called for kvmvapic rom. __callrom->farcall16big-> call16_override,
once call16_override is called, a20 is enabled and will not be disabled. So ahci_process_op is called with a20 on.
I tried below change, guest can boot without kvmvapic. I'm not familiar with seabios code, I don't consider it as a patch, but it proves my analysis is correct. With the change, __call32 calls call32_prep with method C16_BIG to enable a20 before calling ahci_process_op.
please help fix this issue.
Thanks, Anthony
diff --git a/src/stacks.c b/src/stacks.c index ef6a707..0949652 100644 --- a/src/stacks.c +++ b/src/stacks.c @@ -232,10 +237,11 @@ u32 VISIBLE16 __call32(void *func, u32 eax, u32 errret) { ASSERT16(); - if (CONFIG_CALL32_SMM && GET_GLOBAL(HaveSmmCall32)) - return call32_smm(func, eax); +// if (CONFIG_CALL32_SMM && GET_GLOBAL(HaveSmmCall32)) +// return call32_smm(func, eax); // Jump direclty to 32bit mode - this clobbers the 16bit segment // selector registers.