From nobody Sun Apr 12 04:21:18 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=unpredictable.fr ARC-Seal: i=1; a=rsa-sha256; t=1772029574; cv=none; d=zohomail.com; s=zohoarc; b=SvRAJ3uZw5DBmt9ik0lqvLO+L5xRJuph/sKs871dTiRH51YCMj/IN9Gc9nBogO0NEgHsRLZpkGF2QMhvoOOGegc9582prLo2xtvWdw9/QLgX5Dg9FxwiELIpXI396k5s8SXlDwN9otOFdNBE9Lg8eeA9XZiumlYy/U8m+TBpPxQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772029574; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Ch5IRT2Vcu7OGpHja7L/D+jNMc6Vs/OVDRML8OqTxWQ=; b=VDRwtItKzGkzN1WZ8bPDfYQZ6FJeWmydUjknyW28jsceQo9JkH+8lE4XFMsNel2+2Xbi1mv9XdvzJhvKBsrbZIi9Zwtn1jGDHQZAZgfaDGnDdEKd6l9ssE+LH14jkJD3/n5otFAiVfpQdKpNtE4NUoeGIF3tVH9SpaDdooSw6uw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17720295743181023.7052329869153; Wed, 25 Feb 2026 06:26:14 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vvFpn-0002p7-Kf; Wed, 25 Feb 2026 09:25:51 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vvFpf-0002m3-Ib for qemu-devel@nongnu.org; Wed, 25 Feb 2026 09:25:45 -0500 Received: from qs-2005i-snip4-8.eps.apple.com ([57.103.86.219] helo=outbound.qs.icloud.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vvFpc-0003di-I8 for qemu-devel@nongnu.org; Wed, 25 Feb 2026 09:25:43 -0500 Received: from outbound.qs.icloud.com (unknown [127.0.0.2]) by p00-icloudmta-asmtp-us-east-2d-100-percent-15 (Postfix) with ESMTPS id 840E31800142; Wed, 25 Feb 2026 14:25:38 +0000 (UTC) Received: from localhost.localdomain (unknown [17.57.155.37]) by p00-icloudmta-asmtp-us-east-2d-100-percent-15 (Postfix) with ESMTPSA id 3296618000A8; Wed, 25 Feb 2026 14:25:37 +0000 (UTC) Dkim-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=unpredictable.fr; s=sig1; t=1772029539; x=1774621539; bh=Ch5IRT2Vcu7OGpHja7L/D+jNMc6Vs/OVDRML8OqTxWQ=; h=From:To:Subject:Date:Message-ID:MIME-Version:x-icloud-hme; b=FagX1Fx49JrxErXJjn1DyL1JuMHGY+BQNTRO4/N65IwzEFgF8CvJv+o74O7Qsvd5PmBZ+SAAou0xPN5XG9TfM93gIE3QmqBtlBnAQzne2KbHk9+ggXXO90tjddBcb+zDRSDtfIdFH71waXlJR3t0825DR37N/KvmOHWTzSw3PiMoJgHlIe5YUYqc1NxCSVWX8FHRt1aPhAHxHw678yz1GBihq9F7cT4C+EP+nJIOyGsn9sZ9kh9K/xH3CQAesbDjhPaAIpQCE5JQYDcsL92o74vwjg9X877B/fquVmSJ0Mrluu5PA+hBviC4aDDj71R0Vmu+HMNAP03ihk3Enu+3pA== mail-alias-created-date: 1752046281608 From: Mohamed Mediouni To: qemu-devel@nongnu.org Cc: Pedro Barbuda , Mohamed Mediouni , Paolo Bonzini , "Michael S. Tsirkin" , Zhao Liu Subject: [PATCH] whpx: i386: apic: bring closer to MSHV code path Date: Wed, 25 Feb 2026 15:25:34 +0100 Message-ID: <20260225142534.5471-1-mohamed@unpredictable.fr> X-Mailer: git-send-email 2.50.1 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjI1MDEzOCBTYWx0ZWRfX4jti65wC7v1Y NSFEGbU6FheclOoE8ARcJ9xabUiFHHBri5Z3o3p4aE55oJUwxXFFzDY/V358tv03qkzPodC77Py tPakkCmUPWTo4owpORuBfJi5GgxUl6wNvKvyDZ8NxwDHiboylqyIYJX7dTbQhDb7IiYChoGPgqb DVGawJBkEiDoBwrP++iI7ZBWqEasFXmBO0JG6uM1p6dpeuCfUM0wBCCl8gAeCX/AyLuuKkW3K15 EsPi7wMq8EPouUtB10x0DmTVgTQaTN/GP5ZSb0rUbhqHjIGWbnqRIDT9jE8i+t6aa3BX6190hYz 4k8ZNZblcWLa3bf2TRrJylqqmdQwl6/4UJjeDEa6RgFpEfkTxpuNpuQz9ENgtQ= X-Authority-Info-Out: v=2.4 cv=KtpAGGWN c=1 sm=1 tr=0 ts=699f0662 cx=c_apl:c_apl_out:c_pps a=bsP7O+dXZ5uKcj+dsLqiMw==:117 a=bsP7O+dXZ5uKcj+dsLqiMw==:17 a=HzLeVaNsDn8A:10 a=VkNPw1HP01LnGYTKEx00:22 a=Mpw57Om8IfrbqaoTuvik:22 a=GgsMoib0sEa3-_RKJdDe:22 a=a_U1oVfrAAAA:8 a=yMhMjlubAAAA:8 a=nfi25ZJz4WSbdH3KjXAA:9 X-Proofpoint-ORIG-GUID: lL7wkx2_5zKj-9ik8JLH1-zjtmvR3djB X-Proofpoint-GUID: lL7wkx2_5zKj-9ik8JLH1-zjtmvR3djB X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-02-25_01,2026-02-25_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 bulkscore=0 mlxlogscore=999 mlxscore=0 clxscore=1030 lowpriorityscore=0 suspectscore=0 adultscore=0 malwarescore=0 spamscore=0 phishscore=0 classifier=spam authscore=0 adjust=0 reason=mlx scancount=1 engine=8.22.0-2601150000 definitions=main-2602250138 X-JNJ: AAAAAAABKqhqzX51pMCthWQFFZvyxzQjehvTfYJUV+CkuCoFXSWba42HYBHbecq3kmLsHRVxAskvZhOwUSqDE4rqNr1JsDrhPVyXFxsnQE40QPQOUPsHWTSMPaMNtgIyCryi0g2daheqLayooHf//YHyz9yRYeS0VKNmxAnEjxNv6FSG2eHwwj5uadwWS5Cx6tWX1STVUpt+9jmFTPnXW4CxuuFku36zZd+mEogabUyD/Ei0lHYlnKXslepT4/H90c5XA1oB1s/m2yFUDGgGUc8WRdXvTgAeuX6AL9UFBZZHG5TVQeHvX75LcLksI1hgHRL/0rK8D5gU/YRwFC+dZlOV/K7HkEILzKzoLnDI3tAEjhk8w0FqmD9cIwIi130HbPs44MJXBz3JfeDNG81AoM+g0Wust0sgRbPGA7cBVvJFNaSgBmepJH+JZ87dTEUvdS7Xzmwk+YBpcqAXJG/HLBffVmyQEq0gNINWb4+2UKKknmNQDrtgPIDOCeJlLMy4mjaA08NaU0GjkrNy59Gl4Y4NAmM0/Ibuc/tF2VKvspUCxLVG9IyN4CibNt1ZpyEhhSC1OXWIirYlMXQqD94vKthwKxQBJrH5mKeTkuV9jhY+k2HyUq+EBrsEkoIL/1l26iHxQpkCu17sCm2GiQ== Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=57.103.86.219; envelope-from=mohamed@unpredictable.fr; helo=outbound.qs.icloud.com X-Spam_score_int: -5 X-Spam_score: -0.6 X-Spam_bar: / X-Spam_report: (-0.6 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.734, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.78, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @unpredictable.fr) X-ZM-MESSAGEID: 1772029578754158500 Content-Type: text/plain; charset="utf-8" MSHV doesn't have a dedicated apic_type and uses the common class. Make WHP= X do the same thing. As VM save/restore isn't currently supported anyway, this doesn't break fun= ctionality. Signed-off-by: Mohamed Mediouni --- hw/intc/apic.c | 9 ++ include/system/whpx-internal.h | 2 - target/i386/cpu-apic.c | 3 - target/i386/whpx/irq.c | 76 +++++++++ target/i386/whpx/irq.h | 8 + target/i386/whpx/meson.build | 2 +- target/i386/whpx/whpx-all.c | 15 -- target/i386/whpx/whpx-apic.c | 286 --------------------------------- 8 files changed, 94 insertions(+), 307 deletions(-) create mode 100644 target/i386/whpx/irq.c create mode 100644 target/i386/whpx/irq.h delete mode 100644 target/i386/whpx/whpx-apic.c diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 8766ed00b9..4920043063 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -28,6 +28,8 @@ #include "qemu/host-utils.h" #include "system/kvm.h" #include "system/mshv.h" +#include "system/whpx.h" +#include "whpx/irq.h" #include "trace.h" #include "hw/i386/apic-msidef.h" #include "exec/cpu-common.h" @@ -915,6 +917,13 @@ static void apic_send_msi(MSIMessage *msi) dest_mode, trigger_mode); return; } +#endif +#ifdef CONFIG_WHPX + if (whpx_enabled() && whpx_irqchip_in_kernel()) { + whpx_request_interrupt(delivery, vector, dest, + dest_mode, trigger_mode); + return; + } #endif apic_deliver_irq(dest, dest_mode, delivery, vector, trigger_mode); } diff --git a/include/system/whpx-internal.h b/include/system/whpx-internal.h index 7a1c9871f1..a1f8502155 100644 --- a/include/system/whpx-internal.h +++ b/include/system/whpx-internal.h @@ -4,7 +4,6 @@ =20 #include #include -#include "hw/i386/apic.h" #include "exec/vaddr.h" =20 typedef enum WhpxBreakpointState { @@ -45,7 +44,6 @@ struct whpx_state { }; =20 extern struct whpx_state whpx_global; -void whpx_apic_get(APICCommonState *s); =20 #define WHV_E_UNKNOWN_CAPABILITY 0x80370300L =20 diff --git a/target/i386/cpu-apic.c b/target/i386/cpu-apic.c index eaa10ad2a3..77073ad455 100644 --- a/target/i386/cpu-apic.c +++ b/target/i386/cpu-apic.c @@ -33,10 +33,7 @@ APICCommonClass *apic_get_class(Error **errp) apic_type =3D "kvm-apic"; } else if (xen_enabled()) { apic_type =3D "xen-apic"; - } else if (whpx_irqchip_in_kernel()) { - apic_type =3D "whpx-apic"; } - return APIC_COMMON_CLASS(object_class_by_name(apic_type)); } =20 diff --git a/target/i386/whpx/irq.c b/target/i386/whpx/irq.c new file mode 100644 index 0000000000..b33876a1db --- /dev/null +++ b/target/i386/whpx/irq.c @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "cpu.h" +#include "hw/i386/apic_internal.h" +#include "hw/i386/apic-msidef.h" +#include "hw/pci/msi.h" +#include "system/hw_accel.h" +#include "system/whpx.h" +#include "system/whpx-internal.h" +#include "irq.h" +#include "system/whpx-accel-ops.h" +#include "system/whpx-all.h" +#include "system/whpx-common.h" + +/* Structure definition from Hyper-V, to keep unaltered */ +typedef struct _HV_X64_INTERRUPT_CONTROLLER_STATE +{ + UINT32 ApicId; + UINT32 ApicVersion; + UINT32 ApicLdr; + UINT32 ApicDfr; + UINT32 ApicSpurious; + UINT32 ApicIsr[8]; + UINT32 ApicTmr[8]; + UINT32 ApicIrr[8]; + UINT32 ApicEsr; + UINT32 ApicIcrHigh; + UINT32 ApicIcrLow; + UINT32 ApicLvtTimer; + UINT32 ApicLvtThermal; + UINT32 ApicLvtPerfmon; + UINT32 ApicLvtLint0; + UINT32 ApicLvtLint1; + UINT32 ApicLvtError; + UINT32 ApicLvtCmci; + UINT32 ApicErrorStatus; + UINT32 ApicInitialCount; + UINT32 ApicCounterValue; + UINT32 ApicDivideConfiguration; + UINT32 ApicRemoteRead; + +} HV_X64_INTERRUPT_CONTROLLER_STATE, *PHV_X64_INTERRUPT_CONTROLLER_STATE; + +int whpx_request_interrupt(uint32_t interrupt_type, uint32_t vector, + uint32_t vp_index, bool logical_dest_mode, + bool level_triggered) +{ + HRESULT hr; + + if (vector =3D=3D 0) { + warn_report("Ignoring request for interrupt vector 0"); + return 0; + } + + WHV_INTERRUPT_CONTROL interrupt =3D { + .Type =3D interrupt_type, + .DestinationMode =3D logical_dest_mode ? + WHvX64InterruptDestinationModeLogical : + WHvX64InterruptDestinationModePhysical, + + .TriggerMode =3D level_triggered ? + WHvX64InterruptTriggerModeLevel : WHvX64InterruptTriggerModeEd= ge, + .Reserved =3D 0, + .Vector =3D vector, + .Destination =3D vp_index, + }; + + hr =3D whp_dispatch.WHvRequestInterrupt(whpx_global.partition, + &interrupt, sizeof(interrupt)); + if (FAILED(hr)) { + error_report("Failed to request interrupt"); + return -errno; + } + return 0; +} diff --git a/target/i386/whpx/irq.h b/target/i386/whpx/irq.h new file mode 100644 index 0000000000..1ffaab69eb --- /dev/null +++ b/target/i386/whpx/irq.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef QEMU_X86_WHPX_H +#define QEMU_X86_WHPX_H + +int whpx_request_interrupt(uint32_t interrupt_type, uint32_t vector, + uint32_t vp_index, bool logical_dest_mode, + bool level_triggered); +#endif /* QEMU_X86_WHPX_H */ diff --git a/target/i386/whpx/meson.build b/target/i386/whpx/meson.build index c3aaaff9fd..5c13274b77 100644 --- a/target/i386/whpx/meson.build +++ b/target/i386/whpx/meson.build @@ -1,4 +1,4 @@ i386_system_ss.add(when: 'CONFIG_WHPX', if_true: files( 'whpx-all.c', - 'whpx-apic.c', + 'irq.c' )) diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c index d98619face..ce3019bf4f 100644 --- a/target/i386/whpx/whpx-all.c +++ b/target/i386/whpx/whpx-all.c @@ -619,17 +619,6 @@ void whpx_get_registers(CPUState *cpu, WHPXStateLevel = level) hr); } =20 - if (level > WHPX_LEVEL_FAST_RUNTIME_STATE && whpx_irqchip_in_kernel())= { - /* - * Fetch the TPR value from the emulated APIC. It may get overwrit= ten - * below with the value from CR8 returned by - * WHvGetVirtualProcessorRegisters(). - */ - whpx_apic_get(x86_cpu->apic_state); - vcpu->tpr =3D whpx_apic_tpr_to_cr8( - cpu_get_apic_tpr(x86_cpu->apic_state)); - } - idx =3D 0; =20 /* Indexes for first 16 registers match between HV and QEMU definition= s */ @@ -762,10 +751,6 @@ void whpx_get_registers(CPUState *cpu, WHPXStateLevel = level) =20 assert(idx =3D=3D RTL_NUMBER_OF(whpx_register_names)); =20 - if (level > WHPX_LEVEL_FAST_RUNTIME_STATE && whpx_irqchip_in_kernel())= { - whpx_apic_get(x86_cpu->apic_state); - } - x86_update_hflags(env); } =20 diff --git a/target/i386/whpx/whpx-apic.c b/target/i386/whpx/whpx-apic.c deleted file mode 100644 index f26ecaf6e8..0000000000 --- a/target/i386/whpx/whpx-apic.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * WHPX platform APIC support - * - * Copyright (c) 2011 Siemens AG - * - * Authors: - * Jan Kiszka - * John Starks - * - * This work is licensed under the terms of the GNU GPL version 2. - * See the COPYING file in the top-level directory. - */ -#include "qemu/osdep.h" -#include "qemu/error-report.h" -#include "cpu.h" -#include "hw/i386/apic_internal.h" -#include "hw/i386/apic-msidef.h" -#include "hw/pci/msi.h" -#include "system/hw_accel.h" -#include "system/whpx.h" -#include "system/whpx-internal.h" - -struct whpx_lapic_state { - struct { - uint32_t data; - uint32_t padding[3]; - } fields[256]; -}; - -static void whpx_put_apic_state(APICCommonState *s, - struct whpx_lapic_state *kapic) -{ - int i; - - memset(kapic, 0, sizeof(*kapic)); - kapic->fields[0x2].data =3D s->id << 24; - kapic->fields[0x3].data =3D s->version | ((APIC_LVT_NB - 1) << 16); - kapic->fields[0x8].data =3D s->tpr; - kapic->fields[0xd].data =3D s->log_dest << 24; - kapic->fields[0xe].data =3D s->dest_mode << 28 | 0x0fffffff; - kapic->fields[0xf].data =3D s->spurious_vec; - for (i =3D 0; i < 8; i++) { - kapic->fields[0x10 + i].data =3D s->isr[i]; - kapic->fields[0x18 + i].data =3D s->tmr[i]; - kapic->fields[0x20 + i].data =3D s->irr[i]; - } - - kapic->fields[0x28].data =3D s->esr; - kapic->fields[0x30].data =3D s->icr[0]; - kapic->fields[0x31].data =3D s->icr[1]; - for (i =3D 0; i < APIC_LVT_NB; i++) { - kapic->fields[0x32 + i].data =3D s->lvt[i]; - } - - kapic->fields[0x38].data =3D s->initial_count; - kapic->fields[0x3e].data =3D s->divide_conf; -} - -static void whpx_get_apic_state(APICCommonState *s, - struct whpx_lapic_state *kapic) -{ - int i, v; - - s->id =3D kapic->fields[0x2].data >> 24; - s->tpr =3D kapic->fields[0x8].data; - s->arb_id =3D kapic->fields[0x9].data; - s->log_dest =3D kapic->fields[0xd].data >> 24; - s->dest_mode =3D kapic->fields[0xe].data >> 28; - s->spurious_vec =3D kapic->fields[0xf].data; - for (i =3D 0; i < 8; i++) { - s->isr[i] =3D kapic->fields[0x10 + i].data; - s->tmr[i] =3D kapic->fields[0x18 + i].data; - s->irr[i] =3D kapic->fields[0x20 + i].data; - } - - s->esr =3D kapic->fields[0x28].data; - s->icr[0] =3D kapic->fields[0x30].data; - s->icr[1] =3D kapic->fields[0x31].data; - for (i =3D 0; i < APIC_LVT_NB; i++) { - s->lvt[i] =3D kapic->fields[0x32 + i].data; - } - - s->initial_count =3D kapic->fields[0x38].data; - s->divide_conf =3D kapic->fields[0x3e].data; - - v =3D (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4); - s->count_shift =3D (v + 1) & 7; - - s->initial_count_load_time =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - apic_next_timer(s, s->initial_count_load_time); -} - -static int whpx_apic_set_base(APICCommonState *s, uint64_t val) -{ - s->apicbase =3D val; - return 0; -} - -static void whpx_put_apic_base(CPUState *cpu, uint64_t val) -{ - HRESULT hr; - WHV_REGISTER_VALUE reg_value =3D {.Reg64 =3D val}; - WHV_REGISTER_NAME reg_name =3D WHvX64RegisterApicBase; - - hr =3D whp_dispatch.WHvSetVirtualProcessorRegisters( - whpx_global.partition, - cpu->cpu_index, - ®_name, 1, - ®_value); - - if (FAILED(hr)) { - error_report("WHPX: Failed to set MSR APIC base, hr=3D%08lx", hr); - } -} - -static void whpx_apic_set_tpr(APICCommonState *s, uint8_t val) -{ - s->tpr =3D val; -} - -static uint8_t whpx_apic_get_tpr(APICCommonState *s) -{ - return s->tpr; -} - -static void whpx_apic_vapic_base_update(APICCommonState *s) -{ - /* not implemented yet */ -} - -static void whpx_apic_put(CPUState *cs, run_on_cpu_data data) -{ - APICCommonState *s =3D data.host_ptr; - struct whpx_lapic_state kapic; - HRESULT hr; - - whpx_put_apic_base(CPU(s->cpu), s->apicbase); - whpx_put_apic_state(s, &kapic); - - hr =3D whp_dispatch.WHvSetVirtualProcessorInterruptControllerState2( - whpx_global.partition, - cs->cpu_index, - &kapic, - sizeof(kapic)); - if (FAILED(hr)) { - fprintf(stderr, - "WHvSetVirtualProcessorInterruptControllerState failed: %08lx\= n", - hr); - - abort(); - } -} - -void whpx_apic_get(APICCommonState *s) -{ - CPUState *cpu =3D CPU(s->cpu); - struct whpx_lapic_state kapic; - - HRESULT hr =3D whp_dispatch.WHvGetVirtualProcessorInterruptControllerS= tate2( - whpx_global.partition, - cpu->cpu_index, - &kapic, - sizeof(kapic), - NULL); - if (FAILED(hr)) { - fprintf(stderr, - "WHvSetVirtualProcessorInterruptControllerState failed: %08lx\= n", - hr); - - abort(); - } - - whpx_get_apic_state(s, &kapic); -} - -static void whpx_apic_post_load(APICCommonState *s) -{ - run_on_cpu(CPU(s->cpu), whpx_apic_put, RUN_ON_CPU_HOST_PTR(s)); -} - -static void whpx_apic_external_nmi(APICCommonState *s) -{ -} - -static void whpx_send_msi(MSIMessage *msg) -{ - uint64_t addr =3D msg->address; - uint32_t data =3D msg->data; - uint8_t dest =3D (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SH= IFT; - uint8_t vector =3D (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SH= IFT; - uint8_t dest_mode =3D (addr >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1; - uint8_t trigger_mode =3D (data >> MSI_DATA_TRIGGER_SHIFT) & 0x1; - uint8_t delivery =3D (data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x7; - - if (vector =3D=3D 0) { - warn_report("Ignoring request for interrupt vector 0"); - return; - } - - WHV_INTERRUPT_CONTROL interrupt =3D { - /* Values correspond to delivery modes */ - .Type =3D delivery, - .DestinationMode =3D dest_mode ? - WHvX64InterruptDestinationModeLogical : - WHvX64InterruptDestinationModePhysical, - - .TriggerMode =3D trigger_mode ? - WHvX64InterruptTriggerModeLevel : WHvX64InterruptTriggerModeEd= ge, - .Reserved =3D 0, - .Vector =3D vector, - .Destination =3D dest, - }; - HRESULT hr =3D whp_dispatch.WHvRequestInterrupt(whpx_global.partition, - &interrupt, sizeof(interrupt)); - if (FAILED(hr)) { - fprintf(stderr, "whpx: injection failed, MSI (%llx, %x) delivery: = %d, " - "dest_mode: %d, trigger mode: %d, vector: %d, lost (%08lx)= \n", - addr, data, delivery, dest_mode, trigger_mode, vector, hr); - } -} - -static uint64_t whpx_apic_mem_read(void *opaque, hwaddr addr, - unsigned size) -{ - return ~(uint64_t)0; -} - -static void whpx_apic_mem_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) -{ - MSIMessage msg =3D { .address =3D addr, .data =3D data }; - whpx_send_msi(&msg); -} - -static const MemoryRegionOps whpx_apic_io_ops =3D { - .read =3D whpx_apic_mem_read, - .write =3D whpx_apic_mem_write, - .endianness =3D DEVICE_LITTLE_ENDIAN, -}; - -static void whpx_apic_reset(APICCommonState *s) -{ - /* Not used by WHPX. */ - s->wait_for_sipi =3D 0; - - run_on_cpu(CPU(s->cpu), whpx_apic_put, RUN_ON_CPU_HOST_PTR(s)); -} - -static void whpx_apic_realize(DeviceState *dev, Error **errp) -{ - APICCommonState *s =3D APIC_COMMON(dev); - - memory_region_init_io(&s->io_memory, OBJECT(s), &whpx_apic_io_ops, s, - "whpx-apic-msi", APIC_SPACE_SIZE); - - msi_nonbroken =3D true; -} - -static void whpx_apic_class_init(ObjectClass *klass, const void *data) -{ - APICCommonClass *k =3D APIC_COMMON_CLASS(klass); - - k->realize =3D whpx_apic_realize; - k->reset =3D whpx_apic_reset; - k->set_base =3D whpx_apic_set_base; - k->set_tpr =3D whpx_apic_set_tpr; - k->get_tpr =3D whpx_apic_get_tpr; - k->post_load =3D whpx_apic_post_load; - k->vapic_base_update =3D whpx_apic_vapic_base_update; - k->external_nmi =3D whpx_apic_external_nmi; - k->send_msi =3D whpx_send_msi; -} - -static const TypeInfo whpx_apic_info =3D { - .name =3D "whpx-apic", - .parent =3D TYPE_APIC_COMMON, - .instance_size =3D sizeof(APICCommonState), - .class_init =3D whpx_apic_class_init, -}; - -static void whpx_apic_register_types(void) -{ - type_register_static(&whpx_apic_info); -} - -type_init(whpx_apic_register_types) --=20 2.50.1 (Apple Git-155)