Unable to update APIC_TPR when x2APIC is enabled and -global kvm-pit.lost_tick_policy=discard parameter provided
Host environment
- Operating system: Gentoo Linux
- OS/kernel version: 6.6.1-gentoo #1 SMP PREEMPT_DYNAMIC Tue Nov 14 13:32:33 CET 2023 x86_64
- Architecture: x86
- QEMU flavor: qemu-system-x86_64 & qemu-system-i386
- QEMU version: QEMU emulator version 8.1.2
- QEMU command line:
qemu-system-x86_64 \
-machine type=pc-q35-7.0,kernel_irqchip=on,accel=kvm,mem-merge=off,vmport=off \
-cpu host,-hypervisor,-amd-stibp,+topoext,invtsc=on,kvm=off,kvm-pv-eoi=on,kvm-hint-dedicated=on,hv_spinlocks=0x1fff,hv_relaxed,hv_vapic,hv_time,hv_crash,hv_reset,hv_vpindex,hv_runtime,hv_synic,hv_stimer,host-cache-info=on,l3-cache=off \
-smp 4,sockets=1,cores=2,threads=2 \
-enable-kvm \
-m 10G \
-mem-prealloc \
-overcommit mem-lock=off \
-rtc clock=host,base=localtime,driftfix=none \
-global kvm-pit.lost_tick_policy=discard \
-global ICH9-LPC.disable_s3=1 \
-global ICH9-LPC.disable_s4=1 \
-drive file=ovmf_code_amd64.fd,if=pflash,format=raw,unit=0,readonly=on \
-drive file=ovmf_vars_amd64.fd,if=pflash,format=raw,unit=1 \
(...)
Emulated/Virtualized environment
- Operating system: OSDEV (custom OS)
- OS/kernel version: Custom OS
- Architecture: x86 (both i686 and amd64)
Description of problem
I am developing a custom OS and I wanted to implement x2APIC support. I was able to enable x2APIC, read and write some registers, like APIC_VER and APIC_SIVR. Everything looks good, except that I cannot update APIC_TPR register. Reading it always returns 0. The code I wrote works properly on bare metal. Below some observations:
Scenario 1:
- Enable x2APIC
- Write to CR8 - success
- Read from CR8 - gives correct value
- Read from APIC_TPR - gives correct value
Scenario 2:
- Enable x2APIC
- Read from APIC_TPR - gives 0
- Write to APIC_TPR
- Read from APIC_TPR - gives 0 again
Scenario 3:
- Initialize APIC (LAPIC or xAPIC)
- Write to APIC_TPR
- Read from APIC_TPR - gives correct value
- Switch to x2APIC
- Read from APIC_TPR - gives correct value stored in pt. 2
- Write to APIC_TPR
- Read from APIC_TPR - gives values stored in pt.2, not in point 6!
Looks like APIC_TPR is stuck at value stored there before switching to x2APIC and it cannot be updated with MSR. Only update CR8 works.
I have checked parameters I passed to qemu. After removing -global kvm-pit.lost_tick_policy=discard problem is gone and APIC_TPR is updated correctly.
Additional information
Please let me know if you need additional information.
Edited by Rafal Kupiec