|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 1/2] x86/vlapic: Fix handling of writes to APIC_ESR
On Thu, Nov 28, 2024 at 12:47:36AM +0000, Andrew Cooper wrote:
> Xen currently presents APIC_ESR to guests as a simple read/write register.
>
> This is incorrect. The SDM states:
>
> The ESR is a write/read register. Before attempt to read from the ESR,
> software should first write to it. (The value written does not affect the
> values read subsequently; only zero may be written in x2APIC mode.) This
> write clears any previously logged errors and updates the ESR with any
> errors detected since the last write to the ESR. This write also rearms the
> APIC error interrupt triggering mechanism.
>
> Introduce a new pending_esr field in hvm_hw_lapic. Update vlapic_error() to
> accumulate errors here, and extend vlapic_reg_write() to discard the written
> value, and instead transfer pending_esr into APIC_ESR. Reads are still as
> before.
>
> Importantly, this means that guests no longer destroys the ESR value it's
> looking for in the LVTERR handler when following the SDM instructions.
>
> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
> ---
> CC: Jan Beulich <JBeulich@xxxxxxxx>
> CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
>
> Slightly RFC. This collides with Alejandro's patch which adds the apic_id
> field to hvm_hw_lapic too. However, this is a far more obvious backport
> candidate.
>
> lapic_check_hidden() might in principle want to audit this field, but it's not
> clear what to check. While prior Xen will never have produced it in the
> migration stream, Intel APIC-V will set APIC_ESR_ILLREGA above and beyond what
> Xen will currently emulate.
>
> I've checked that this does behave correctly under Intel APIC-V. Writes to
> APIC_ESR drop the written value into the backing page then take a trap-style
> EXIT_REASON_APIC_WRITE which allows us to sample/latch properly.
> ---
> xen/arch/x86/hvm/vlapic.c | 17 +++++++++++++++--
> xen/include/public/arch-x86/hvm/save.h | 1 +
> 2 files changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c
> index 3363926b487b..98394ed26a52 100644
> --- a/xen/arch/x86/hvm/vlapic.c
> +++ b/xen/arch/x86/hvm/vlapic.c
> @@ -108,7 +108,7 @@ static void vlapic_error(struct vlapic *vlapic, unsigned
> int errmask)
> uint32_t esr;
>
> spin_lock_irqsave(&vlapic->esr_lock, flags);
> - esr = vlapic_get_reg(vlapic, APIC_ESR);
> + esr = vlapic->hw.pending_esr;
> if ( (esr & errmask) != errmask )
> {
> uint32_t lvterr = vlapic_get_reg(vlapic, APIC_LVTERR);
> @@ -127,7 +127,7 @@ static void vlapic_error(struct vlapic *vlapic, unsigned
> int errmask)
> errmask |= APIC_ESR_RECVILL;
> }
>
> - vlapic_set_reg(vlapic, APIC_ESR, esr | errmask);
> + vlapic->hw.pending_esr |= errmask;
>
> if ( inj )
> vlapic_set_irq(vlapic, lvterr & APIC_VECTOR_MASK, 0);
The SDM also contains:
"This write also rearms the APIC error interrupt triggering
mechanism."
Where "this write" is a write to the ESR register. My understanding
is that the error vector will only be injected for the first reported
error. I think the logic regarding whether to inject the lvterr vector
needs to additionally be gated on whether vlapic->hw.pending_esr ==
0.
Thanks, Roger.
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |