@samitouri / QOSamiQemu / commits / 4fdbad6c49

whpx: i386: use WHvX64RegisterCr8 only when kernel-irqchip=off

When kernel-irqchip=on, manage TPR as part of the APIC state instead entirely. This fixes some failure to set state errors. Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr> Link: https://lore.kernel.org/r/20260422214225.2242-10-mohamed@unpredictable.fr Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Mohamed Mediouni committed Apr 22, 2026 at 23:41 UTC 4fdbad6c4981e8c7ff1b9780f6d392227f249cb3
1 file changed +22 -15
target/i386/whpx/whpx-all.c
+22 -15
@@ -95,7 +95,6 @@ static const WHV_REGISTER_NAME whpx_register_names[] = {
95 WHvX64RegisterCr2,
96 WHvX64RegisterCr3,
97 WHvX64RegisterCr4,
98 - WHvX64RegisterCr8,
98
99 /* X64 Debug Registers */
100 /*
@@ -478,8 +477,11 @@ void whpx_set_registers(CPUState *cpu, WHPXStateLevel level)
477 vcxt.values[idx++].Reg64 = env->cr[3];
478 assert(whpx_register_names[idx] == WHvX64RegisterCr4);
479 vcxt.values[idx++].Reg64 = env->cr[4];
481 - assert(whpx_register_names[idx] == WHvX64RegisterCr8);
482 - vcxt.values[idx++].Reg64 = vcpu->tpr;
480 + /* For kernel-irqchip=on, TPR is managed as part of APIC state */
481 + if (!whpx_irqchip_in_kernel()) {
482 + WHV_REGISTER_VALUE cr8 = {.Reg64 = vcpu->tpr};
483 + whpx_set_reg(cpu, WHvX64RegisterCr8, cr8);
484 + }
485
486 /* 8 Debug Registers - Skipped */
487
@@ -735,11 +737,14 @@ void whpx_get_registers(CPUState *cpu, WHPXStateLevel level)
737 env->cr[3] = vcxt.values[idx++].Reg64;
738 assert(whpx_register_names[idx] == WHvX64RegisterCr4);
739 env->cr[4] = vcxt.values[idx++].Reg64;
738 - assert(whpx_register_names[idx] == WHvX64RegisterCr8);
739 - tpr = vcxt.values[idx++].Reg64;
740 - if (tpr != vcpu->tpr) {
741 - vcpu->tpr = tpr;
742 - cpu_set_apic_tpr(x86_cpu->apic_state, tpr);
740 +
741 + /* For kernel-irqchip=on, TPR is managed as part of APIC state */
742 + if (!whpx_irqchip_in_kernel()) {
743 + tpr = vcpu->exit_ctx.VpContext.Cr8;
744 + if (tpr != vcpu->tpr) {
745 + vcpu->tpr = tpr;
746 + cpu_set_apic_tpr(x86_cpu->apic_state, tpr);
747 + }
748 }
749
750 /* 8 Debug Registers - Skipped */
@@ -1745,7 +1750,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
1750
1751 /* Sync the TPR to the CR8 if was modified during the intercept */
1752 tpr = cpu_get_apic_tpr(x86_cpu->apic_state);
1748 - if (tpr != vcpu->tpr) {
1753 + if (!whpx_irqchip_in_kernel() && tpr != vcpu->tpr) {
1754 vcpu->tpr = tpr;
1755 reg_values[reg_count].Reg64 = tpr;
1756 qatomic_set(&cpu->exit_request, true);
@@ -1787,12 +1792,14 @@ static void whpx_vcpu_post_run(CPUState *cpu)
1792
1793 env->eflags = vcpu->exit_ctx.VpContext.Rflags;
1794
1790 - uint64_t tpr = vcpu->exit_ctx.VpContext.Cr8;
1791 - if (vcpu->tpr != tpr) {
1792 - vcpu->tpr = tpr;
1793 - bql_lock();
1794 - cpu_set_apic_tpr(x86_cpu->apic_state, vcpu->tpr);
1795 - bql_unlock();
1795 + if (!whpx_irqchip_in_kernel()) {
1796 + uint64_t tpr = vcpu->exit_ctx.VpContext.Cr8;
1797 + if (vcpu->tpr != tpr) {
1798 + vcpu->tpr = tpr;
1799 + bql_lock();
1800 + cpu_set_apic_tpr(x86_cpu->apic_state, vcpu->tpr);
1801 + bql_unlock();
1802 + }
1803 }
1804
1805 vcpu->interruption_pending =