|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v1 00/28] x86: initial SVM AVIC support
Overview
========
Modern AMD processors provide hardware-assisted LAPIC virtualization
support known as AVIC (Advanced Virtual Interrupt Controller). See
"15.29 Advanced Virtual Interrupt Controller" in [1].
The main objective is to improve interrupt delivery for a given VM
by avoiding expensive LAPIC emulation in hypervisor.
At a high-level, there are several types of interrupts needed to be
managed for a Xen domain:
(a) IPIs
(b) Posted interrupts (Xen-to-domain, such as event channels)
(c) External devices (MSI, needs coordination with IOMMU)
This initial implementation addresses (a) and (b).
Current limitations:
- Only vLAPIC in xAPIC mode with AVIC enabled
- No GALog support
Please see [2] for more details on the scope.
This work is loosely based on previously submitted work [3] and [4],
including AVIC support in Linux KVM.
The feature is experimental and disabled in the default configuration.
Patch Series
============
Basically the entire work is divided into three big series:
(A) Current series: initial SVM AVIC [5]
(B) XTF interrupt latency test [6]
(C) XTF infra in public CI [5]
For this AVIC series:
Patches 1, 5, 6, 9, 11-16 introduce various cleanups and fixups.
Patch 20 changes XEN_DOMCTL_debug_op implementation to allow
more debug operations added (like enabling/disabling AVIC at
run-time - used by the XTF test).
Patches 2, 3, 4, 7, 8, 10, 17, 18-25 represent AVIC implementation
including performance counters and run-time controls via debug
hypercall.
Patches 26-28 cover various documentation updates.
Testing
=======
Mainly, the patch series has been tested through public hardware runners.
Full CI run (including manually scheduled jobs) is available at [10].
Approach: I decided to write my own synthetic XTF [6] which runs as dom0
on a hardware target to capture some fine-grained metrics for IPIs and
posted interrupts (event channel).
System | Test results
----------------------------------------+-------------
Zen2: Family 23 (0x17), Model 96 (0x60) | [7]
Zen3: Family 25 (0x19), Model 68 (0x44) | [8]
Zen5: Family 26 (0x1a), Model 36 (0x24) | [9]
Synthetic test:
vCPU0 vCPU1
executes some workload
+-> t0
| |
| write ICR2 [*]
r write ICR
e |---------------- interrupt -----------> t0' = recv_tsc
p return from APIC emulation [*'] ISR
e | t1' = handler_tsc
a t1
t |
| sync against ISR
| |
+---+
First 1K samples is dropped, total number of samples is 20M.
IRQ delivery latency : t0' - t0
IRQ issue latency : t1 - t0
IRQ handler latency : t1' - t0'
[*] For event channel that is EVTCHNOP_send hypercall.
[*'] For event channel that is return from the EVTCHNOP_send hypercall.
For all tested Zen2/Zen3/Zen5 targets there are overall improvements
w/ AVIC enabled: the test duration decreased, IPI delivery improved,
ISR latency improved.
Basically, AVIC optimizes long tails in the latency distribution leading
to more deterministic workload.
There's some peculiar behavior w.r.t. doorbell MSR which roughly takes 2us on
Zen5 - fallback to vcpu_kick() turned out to be faster. I added a run-time
configuration knob for a fallback, just in case.
There are also some outliers in the latency distributions which I haven't
ruled out yet: like look at max latency w/ and w/o AVIC in [7], [8], [9]: once
it a blue moon I've seen AVIC giving p99.999 values as a maximum (~15us vs
~45us for the entire 20M population).
Results for Zen5 target are more pronouced, so I am duplicating them below.
Zen5: Workload #1: IPI
----------------------
no AVIC | AVIC
---------------------------------------------+------------------------------------
A: noaccel: IPI send latency (VCPU#0) (20000000 samples)
B: accel: IPI send latency (VCPU#0) (20000000 samples)
metric cycles A time A | cycles B
time B
min 12240 6.131 us | 140 70
ns
avg 12955 6.489 us | 155 77
ns
p50 < 13000 6.512 us | < 170 85
ns
p99 < 14000 7.013 us | < 170 85
ns
p99.9 < 34000 17.031 us | < 170 85
ns
p99.99 < 35000 17.532 us | < 190 95
ns
p99.999 < 98000 49.092 us | < 23000 11.521
us
max 99100 49.643 us | 86660 43.411
us
A: noaccel: IPI delivery latency (VCPU#0 -> VCPU#1) (20000000 samples)
B: accel: IPI delivery latency (VCPU#0 -> VCPU#1) (20000000 samples)
metric cycles A time A | cycles B
time B
min 0 0 ns | 620 310
ns
avg 1402 702 ns | 626 313
ns
p50 < 1400 701 ns | < 650 325
ns
p99 < 1500 751 ns | < 700 350
ns
p99.9 < 20000 10.018 us | < 700 350
ns
p99.99 < 20000 10.018 us | < 700 350
ns
p99.999 < 71000 35.566 us | < 23000 11.521
us
max 87740 43.952 us | 87000 43.581
us
A: noaccel: IPI handler latency (VCPU#1) (20000000 samples)
B: accel: IPI handler latency (VCPU#1) (20000000 samples)
metric cycles A time A | cycles B
time B
min 15520 7.774 us | 160 80
ns
avg 16256 8.143 us | 174 87
ns
p50 < 17000 8.515 us | < 190 95
ns
p99 < 17000 8.515 us | < 190 95
ns
p99.9 < 17000 8.515 us | < 190 95
ns
p99.99 < 17000 8.515 us | < 190 95
ns
p99.999 < 23000 11.521 us | < 190 95
ns
max 33880 16.971 us | 200 100
ns
Workload time 182552 ms 9919
ms
(20000000 samples) (~18x
boost)
Zen5: Workload #2: evtchn
-------------------------
no AVIC | AVIC
---------------------------------------------+------------------------------------
A: noaccel: evtchn send latency (VCPU#0) (20000000 samples)
B: accel: evtchn send latency (VCPU#0) (20000000 samples)
metric cycles A time A | cycles B
time B
min 5800 2.905 us | 6020 3.015
us
avg 5988 2.999 us | 6204 3.107
us
p50 < 6000 3.005 us | < 6200 3.105
us
p99 < 6100 3.055 us | < 6200 3.105
us
p99.9 < 27000 13.525 us | < 27000 13.525
us
p99.99 < 28000 14.026 us | < 29000 14.527
us
p99.999 < 28000 14.026 us | < 92000 46.086
us
max 92160 46.166 us | 92680 46.427
us
A: noaccel: evtchn delivery latency (VCPU#0 -> VCPU#1) (20000000 samples)
B: accel: evtchn delivery latency (VCPU#0 -> VCPU#1) (20000000 samples)
metric cycles A time A | cycles B
time B
min 0 0 ns | 5440 2.725
us
avg 1412 707 ns | 5497 2.753
us
p50 < 1400 701 ns | < 5600 2.805
us
p99 < 1500 751 ns | < 5600 2.805
us
p99.9 < 19000 9.517 us | < 6000 3.005
us
p99.99 < 19000 9.517 us | < 6200 3.105
us
p99.999 < 71000 35.566 us | < 28000 14.026
us
max 87600 43.882 us | 91760 45.966
us
A: noaccel: evtchn handler latency (VCPU#1) (20000000 samples)
B: accel: evtchn handler latency (VCPU#1) (20000000 samples)
metric cycles A time A | cycles B
time B
min 15540 7.784 us | 180 90
ns
avg 15803 7.916 us | 184 92
ns
p50 < 16000 8.015 us | < 190 95
ns
p99 < 16000 8.015 us | < 210 105
ns
p99.9 < 16000 8.015 us | < 210 105
ns
p99.99 < 16000 8.015 us | < 210 105
ns
p99.999 < 24000 12.022 us | < 210 105
ns
max 33120 16.591 us | 200 100
ns
metric cycles A time A | cycles B
time B
min 0 0 ns | 5400 2.705
us
avg 1425 713 ns | 5467 2.738
us
p50 < 1500 751 ns | < 5500 2.755
us
p99 < 1500 751 ns | < 5600 2.805
us
p99.9 < 19000 9.517 us | < 6000 3.005
us
p99.99 < 19000 9.517 us | < 6200 3.105
us
p99.999 < 71000 35.566 us | < 28000 14.026
us
max 87800 43.981 us | 91940 46.055
us
Workload time 175951 ms 62951
ms
(20000000 samples) (~2.5x
boost)
Thanks a lot to Marek for hooking Zen5 runner to public CI.
Thanks a lot to Stefano and Andrew with advices and fixing the access to the
fleet of hardware runners.
References
==========
[1] AMD APM Volumes 1-5:
https://docs.amd.com/v/u/en-US/40332_4.11_APM_Vol1-5
[2] Xen Summit 2026 SVM AVIC:
- YouTube: https://www.youtube.com/watch?v=RhaJsOU_PIA&list=PLGe6RWOETgTQ
- Slides:
https://hosted-files.sched.co/xensummit2026/05/dmukhin_2026_x86_SVM_AVIC.pdf?_gl=1*158gk36*_gcl_au*MjU3OTQwMDQ2LjE3ODg0NzE3NDQ.*FPAU*MjU3OTQwMDQ2LjE3ODg0NzE3NDQ
[3] Archive v1:
https://lore.kernel.org/xen-devel/1474264368-4104-1-git-send-email-suravee.suthikulpanit@xxxxxxx/
[4] Archive v2:
https://lore.kernel.org/xen-devel/20180507210753.2280-1-Janakarajan.Natarajan@xxxxxxx/
[5] Current patch series:
https://gitlab.com/xen-project/people/dmukhin/xen/-/commits/svm-avic-v3
[6] XTF interrupt latency test:
https://gitlab.com/xen-project/people/dmukhin/xtf/-/tree/x86_64-ipi-latency?ref_type=heads
[7] Zen2: Family 23 (0x17), Model 96 (0x60): interrupt latency results:
https://gist.github.com/dmkhn/289f1af656cce74c0fbc81642727a2a4
[8] Zen3: Family 25 (0x19), Model 68 (0x44): interrupt latency results:
https://gist.github.com/dmkhn/9192105efc49cfedd15e2820b8ad23fd
[9] Zen5: Family 26 (0x1a), Model 36 (0x24): interrupt latency results:
https://gist.github.com/dmkhn/e9f50b43cbc48b82175ec517d6cfe6f5
[10] CI:
https://gitlab.com/xen-project/people/dmukhin/xen/-/pipelines/3025987819
Denis Mukhin (28):
x86/hvm: move SVM feature printout to a separate function
x86/hvm: report SVM AVIC support
x86/hvm: report SVM x2AVIC support
x86/hvm: avic: add domain state initialization
x86/hvm: cleanup svm_create_vmcb()
x86/hvm: introduce vlapic_reg_read()
x86/hvm: avic: add VMCB state initialization
x86/hvm: avic: add AVIC_INCOMP_IPI VMEXIT handler
x86/hvm: fix hvm_emulate_one_vm_event() definition
x86/hvm: avic: add AVIC_NOACCEL VMEXIT handler
x86/hvm: introduce vcpu_is_vlapic_tpr_emulated()
x86: apic: use APIC_EIO_ACK instead of open-coded 0
x86/time: fix typo s/interruopt/interrupt/
x86/hvm: vlapic: update signatures of both vlapic_{clear,test}_*
x86/hvm: vlapic: add checks before posted interrupt delivery
x86/hvm: move VINTR disable to svm_clear_intr_window()
x86/hvm: avic: route interrupt delivery to vCPU
x86/hvm: add facility to print hardware-assisted vLAPIC info
x86/hvm: avic: enable SVM AVIC statistics reporting
x86/hvm: rework XEN_DOMCTL_debug_op
x86/hvm: enable debug hypercall for posted interrupts
x86/hvm: avic: ensure SVM AVIC supports xAPIC operation only
x86/hvm: avic: enable vLAPIC mode switch hook
x86/hvm: avic: ensure SVM AVIC is disabled with nested guest
x86/hvm: avic: account for AMD erratum 1235
docs: add coverage for svm_avic=
CHANGELOG.md: add note on initial SVM AVIC support
MAINTAINERS: add myself as SVM AVIC reviewer
CHANGELOG.md | 3 +
MAINTAINERS | 11 +
docs/misc/xen-command-line.pandoc | 23 +-
xen/arch/x86/cpu-policy.c | 3 +-
xen/arch/x86/domctl.c | 24 +-
xen/arch/x86/hvm/emulate.c | 5 +
xen/arch/x86/hvm/hvm.c | 74 +-
xen/arch/x86/hvm/svm/Makefile | 1 +
xen/arch/x86/hvm/svm/avic.c | 921 +++++++++++++++++++++++
xen/arch/x86/hvm/svm/avic.h | 41 +
xen/arch/x86/hvm/svm/intr.c | 22 +
xen/arch/x86/hvm/svm/nestedsvm.c | 9 +-
xen/arch/x86/hvm/svm/svm.c | 186 ++++-
xen/arch/x86/hvm/svm/svm.h | 2 +
xen/arch/x86/hvm/svm/vmcb.c | 29 +-
xen/arch/x86/hvm/svm/vmcb.h | 27 +-
xen/arch/x86/hvm/vlapic.c | 25 +-
xen/arch/x86/hvm/vmx/vmx.c | 4 +
xen/arch/x86/include/asm/apic.h | 3 +-
xen/arch/x86/include/asm/apicdef.h | 2 +-
xen/arch/x86/include/asm/hvm/hvm.h | 47 +-
xen/arch/x86/include/asm/hvm/svm-types.h | 31 +
xen/arch/x86/include/asm/hvm/svm.h | 4 +
xen/arch/x86/include/asm/hvm/vlapic.h | 1 +
xen/arch/x86/include/asm/msr-index.h | 1 +
xen/arch/x86/irq.c | 24 +
xen/arch/x86/time.c | 2 +-
xen/include/public/domctl.h | 2 +
28 files changed, 1411 insertions(+), 116 deletions(-)
create mode 100644 xen/arch/x86/hvm/svm/avic.c
create mode 100644 xen/arch/x86/hvm/svm/avic.h
--
2.55.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |