@samitouri / QOSamiQemu / commits / fad1e8a98e

whpx: i386: interrupt priority support

Implement APIC IRR interrupt priorities. Even with kernel-irqchip=off, Hyper-V is aware of interrupt priorities and implements CR8/TPR, with the InterruptPriority field being followed. Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr> Link: https://lore.kernel.org/r/20260422214225.2242-14-mohamed@unpredictable.fr Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Mohamed Mediouni committed Apr 22, 2026 at 23:42 UTC fad1e8a98e755b6a8ff5edfcadabed1d5b3dc601
1 file changed +20 -4
target/i386/whpx/whpx-all.c
+20 -4
@@ -1673,6 +1673,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
1673 UINT32 reg_count = 0;
1674 WHV_REGISTER_VALUE reg_values[3];
1675 WHV_REGISTER_NAME reg_names[3];
1676 + int irr = apic_get_highest_priority_irr(x86_cpu->apic_state);
1677
1678 memset(&new_int, 0, sizeof(new_int));
1679 memset(reg_values, 0, sizeof(reg_values));
@@ -1708,10 +1709,20 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
1709 }
1710 }
1711
1712 + if (irr == -1) {
1713 + if (isa_pic != NULL && pic_get_output(isa_pic)) {
1714 + /* In case it's a PIC interrupt */
1715 + irr = 0;
1716 + } else if (cpu_test_interrupt(cpu, CPU_INTERRUPT_HARD)) {
1717 + abort();
1718 + }
1719 + }
1720 +
1721 /* Get pending hard interruption or replay one that was overwritten */
1722 if (!whpx_irqchip_in_kernel()) {
1723 if (!vcpu->interruption_pending &&
1714 - vcpu->interruptable && (env->eflags & IF_MASK)) {
1724 + vcpu->interruptable && (env->eflags & IF_MASK)
1725 + && (vcpu->tpr < irr || irr == 0)) {
1726 assert(!new_int.InterruptionPending);
1727 if (cpu_test_interrupt(cpu, CPU_INTERRUPT_HARD)) {
1728 cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
@@ -1768,13 +1779,17 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
1779 }
1780
1781 /* Update the state of the interrupt delivery notification */
1771 - if (!vcpu->window_registered &&
1782 + if ((!vcpu->window_registered ||
1783 + (vcpu->window_priority < irr && vcpu->window_priority != 0) ||
1784 + (irr == 0 && vcpu->window_priority != 0)) &&
1785 cpu_test_interrupt(cpu, CPU_INTERRUPT_HARD)) {
1786 reg_values[reg_count].DeliverabilityNotifications =
1787 (WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER) {
1775 - .InterruptNotification = 1
1788 + .InterruptNotification = 1,
1789 + .InterruptPriority = irr >> 4
1790 };
1791 vcpu->window_registered = 1;
1792 + vcpu->window_priority = irr;
1793 reg_names[reg_count] = WHvX64RegisterDeliverabilityNotifications;
1794 reg_count += 1;
1795 }
@@ -1788,7 +1803,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
1803 reg_names, reg_count, reg_values);
1804 if (FAILED(hr)) {
1805 error_report("WHPX: Failed to set interrupt state registers,"
1791 - " hr=%08lx", hr);
1806 + " hr=%08lx, InterruptPriority=%i", hr, irr >> 4);
1807 }
1808 }
1809 }
@@ -2004,6 +2019,7 @@ int whpx_vcpu_run(CPUState *cpu)
2019 case WHvRunVpExitReasonX64InterruptWindow:
2020 vcpu->ready_for_pic_interrupt = 1;
2021 vcpu->window_registered = 0;
2022 + vcpu->window_priority = 0;
2023 ret = 0;
2024 break;
2025