2017-11-01 15:08:43 +01:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
2012-12-14 22:37:13 +00:00
|
|
|
#ifndef _UAPI__SVM_H
|
|
|
|
#define _UAPI__SVM_H
|
|
|
|
|
|
|
|
#define SVM_EXIT_READ_CR0 0x000
|
2016-05-23 08:43:31 +02:00
|
|
|
#define SVM_EXIT_READ_CR2 0x002
|
2012-12-14 22:37:13 +00:00
|
|
|
#define SVM_EXIT_READ_CR3 0x003
|
|
|
|
#define SVM_EXIT_READ_CR4 0x004
|
|
|
|
#define SVM_EXIT_READ_CR8 0x008
|
|
|
|
#define SVM_EXIT_WRITE_CR0 0x010
|
2016-05-23 08:43:31 +02:00
|
|
|
#define SVM_EXIT_WRITE_CR2 0x012
|
2012-12-14 22:37:13 +00:00
|
|
|
#define SVM_EXIT_WRITE_CR3 0x013
|
|
|
|
#define SVM_EXIT_WRITE_CR4 0x014
|
|
|
|
#define SVM_EXIT_WRITE_CR8 0x018
|
|
|
|
#define SVM_EXIT_READ_DR0 0x020
|
|
|
|
#define SVM_EXIT_READ_DR1 0x021
|
|
|
|
#define SVM_EXIT_READ_DR2 0x022
|
|
|
|
#define SVM_EXIT_READ_DR3 0x023
|
|
|
|
#define SVM_EXIT_READ_DR4 0x024
|
|
|
|
#define SVM_EXIT_READ_DR5 0x025
|
|
|
|
#define SVM_EXIT_READ_DR6 0x026
|
|
|
|
#define SVM_EXIT_READ_DR7 0x027
|
|
|
|
#define SVM_EXIT_WRITE_DR0 0x030
|
|
|
|
#define SVM_EXIT_WRITE_DR1 0x031
|
|
|
|
#define SVM_EXIT_WRITE_DR2 0x032
|
|
|
|
#define SVM_EXIT_WRITE_DR3 0x033
|
|
|
|
#define SVM_EXIT_WRITE_DR4 0x034
|
|
|
|
#define SVM_EXIT_WRITE_DR5 0x035
|
|
|
|
#define SVM_EXIT_WRITE_DR6 0x036
|
|
|
|
#define SVM_EXIT_WRITE_DR7 0x037
|
|
|
|
#define SVM_EXIT_EXCP_BASE 0x040
|
2020-09-07 15:15:24 +02:00
|
|
|
#define SVM_EXIT_LAST_EXCP 0x05f
|
2012-12-14 22:37:13 +00:00
|
|
|
#define SVM_EXIT_INTR 0x060
|
|
|
|
#define SVM_EXIT_NMI 0x061
|
|
|
|
#define SVM_EXIT_SMI 0x062
|
|
|
|
#define SVM_EXIT_INIT 0x063
|
|
|
|
#define SVM_EXIT_VINTR 0x064
|
|
|
|
#define SVM_EXIT_CR0_SEL_WRITE 0x065
|
|
|
|
#define SVM_EXIT_IDTR_READ 0x066
|
|
|
|
#define SVM_EXIT_GDTR_READ 0x067
|
|
|
|
#define SVM_EXIT_LDTR_READ 0x068
|
|
|
|
#define SVM_EXIT_TR_READ 0x069
|
|
|
|
#define SVM_EXIT_IDTR_WRITE 0x06a
|
|
|
|
#define SVM_EXIT_GDTR_WRITE 0x06b
|
|
|
|
#define SVM_EXIT_LDTR_WRITE 0x06c
|
|
|
|
#define SVM_EXIT_TR_WRITE 0x06d
|
|
|
|
#define SVM_EXIT_RDTSC 0x06e
|
|
|
|
#define SVM_EXIT_RDPMC 0x06f
|
|
|
|
#define SVM_EXIT_PUSHF 0x070
|
|
|
|
#define SVM_EXIT_POPF 0x071
|
|
|
|
#define SVM_EXIT_CPUID 0x072
|
|
|
|
#define SVM_EXIT_RSM 0x073
|
|
|
|
#define SVM_EXIT_IRET 0x074
|
|
|
|
#define SVM_EXIT_SWINT 0x075
|
|
|
|
#define SVM_EXIT_INVD 0x076
|
|
|
|
#define SVM_EXIT_PAUSE 0x077
|
|
|
|
#define SVM_EXIT_HLT 0x078
|
|
|
|
#define SVM_EXIT_INVLPG 0x079
|
|
|
|
#define SVM_EXIT_INVLPGA 0x07a
|
|
|
|
#define SVM_EXIT_IOIO 0x07b
|
|
|
|
#define SVM_EXIT_MSR 0x07c
|
|
|
|
#define SVM_EXIT_TASK_SWITCH 0x07d
|
|
|
|
#define SVM_EXIT_FERR_FREEZE 0x07e
|
|
|
|
#define SVM_EXIT_SHUTDOWN 0x07f
|
|
|
|
#define SVM_EXIT_VMRUN 0x080
|
|
|
|
#define SVM_EXIT_VMMCALL 0x081
|
|
|
|
#define SVM_EXIT_VMLOAD 0x082
|
|
|
|
#define SVM_EXIT_VMSAVE 0x083
|
|
|
|
#define SVM_EXIT_STGI 0x084
|
|
|
|
#define SVM_EXIT_CLGI 0x085
|
|
|
|
#define SVM_EXIT_SKINIT 0x086
|
|
|
|
#define SVM_EXIT_RDTSCP 0x087
|
|
|
|
#define SVM_EXIT_ICEBP 0x088
|
|
|
|
#define SVM_EXIT_WBINVD 0x089
|
|
|
|
#define SVM_EXIT_MONITOR 0x08a
|
|
|
|
#define SVM_EXIT_MWAIT 0x08b
|
|
|
|
#define SVM_EXIT_MWAIT_COND 0x08c
|
|
|
|
#define SVM_EXIT_XSETBV 0x08d
|
2019-09-19 15:59:17 -07:00
|
|
|
#define SVM_EXIT_RDPRU 0x08e
|
2020-12-10 11:09:55 -06:00
|
|
|
#define SVM_EXIT_EFER_WRITE_TRAP 0x08f
|
2020-12-10 11:09:56 -06:00
|
|
|
#define SVM_EXIT_CR0_WRITE_TRAP 0x090
|
|
|
|
#define SVM_EXIT_CR1_WRITE_TRAP 0x091
|
|
|
|
#define SVM_EXIT_CR2_WRITE_TRAP 0x092
|
|
|
|
#define SVM_EXIT_CR3_WRITE_TRAP 0x093
|
|
|
|
#define SVM_EXIT_CR4_WRITE_TRAP 0x094
|
|
|
|
#define SVM_EXIT_CR5_WRITE_TRAP 0x095
|
|
|
|
#define SVM_EXIT_CR6_WRITE_TRAP 0x096
|
|
|
|
#define SVM_EXIT_CR7_WRITE_TRAP 0x097
|
|
|
|
#define SVM_EXIT_CR8_WRITE_TRAP 0x098
|
|
|
|
#define SVM_EXIT_CR9_WRITE_TRAP 0x099
|
|
|
|
#define SVM_EXIT_CR10_WRITE_TRAP 0x09a
|
|
|
|
#define SVM_EXIT_CR11_WRITE_TRAP 0x09b
|
|
|
|
#define SVM_EXIT_CR12_WRITE_TRAP 0x09c
|
|
|
|
#define SVM_EXIT_CR13_WRITE_TRAP 0x09d
|
|
|
|
#define SVM_EXIT_CR14_WRITE_TRAP 0x09e
|
|
|
|
#define SVM_EXIT_CR15_WRITE_TRAP 0x09f
|
2020-09-11 14:29:19 -05:00
|
|
|
#define SVM_EXIT_INVPCID 0x0a2
|
2025-05-02 05:03:44 +00:00
|
|
|
#define SVM_EXIT_BUS_LOCK 0x0a5
|
KVM: SVM: Add Idle HLT intercept support
Add support for "Idle HLT" interception on AMD CPUs, and enable Idle HLT
interception instead of "normal" HLT interception for all VMs for which
HLT-exiting is enabled. Idle HLT provides a mild performance boost for
all VM types, by avoiding a VM-Exit in the scenario where KVM would
immediately "wake" and resume the vCPU.
Idle HLT makes HLT-exiting conditional on the vCPU not having a valid,
unmasked interrupt. Specifically, a VM-Exit occurs on execution of HLT
if and only if there are no pending V_IRQ or V_NMI events. Note, Idle
is a replacement for full HLT interception, i.e. enabling HLT interception
would result in all HLT instructions causing unconditional VM-Exits. Per
the APM:
When both HLT and Idle HLT intercepts are active at the same time, the
HLT intercept takes priority. This intercept occurs only if a virtual
interrupt is not pending (V_INTR or V_NMI).
For KVM's use of V_IRQ (also called V_INTR in the APM) to detect interrupt
windows, the net effect of enabling Idle HLT is that, if a virtual
interupt is pending and unmasked at the time of HLT, the vCPU will take
a V_IRQ intercept instead of a HLT intercept.
When AVIC is enabled, Idle HLT works as intended: the vCPU continues
unimpeded and services the pending virtual interrupt.
Note, the APM's description of V_IRQ interaction with AVIC is quite
confusing, and requires piecing together implied behavior. Per the APM,
when AVIC is enabled, V_IRQ *from the VMCB* is ignored:
When AVIC mode is enabled for a virtual processor, the V_IRQ, V_INTR_PRIO,
V_INTR_VECTOR, and V_IGN_TPR fields in the VMCB are ignored.
Which seems to contradict the behavior of Idle HLT:
This intercept occurs only if a virtual interrupt is not pending (V_INTR
or V_NMI).
What's not explicitly stated is that hardware's internal copy of V_IRQ
(and related fields) *are* still active, i.e. are presumably used to cache
information from the virtual APIC.
Handle Idle HLT exits as if they were normal HLT exits, e.g. don't try to
optimize the handling under the assumption that there isn't a pending IRQ.
Irrespective of AVIC, Idle HLT is inherently racy with respect to the vIRR,
as KVM can set vIRR bits asychronously.
No changes are required to support KVM's use Idle HLT while running
L2. In fact, supporting Idle HLT is actually a bug fix to some extent.
If L1 wants to intercept HLT, recalc_intercepts() will enable HLT
interception in vmcb02 and forward the intercept to L1 as normal.
But if L1 does not want to intercept HLT, then KVM will run L2 with Idle
HLT enabled and HLT interception disabled. If a V_IRQ or V_NMI for L2
becomes pending and L2 executes HLT, then use of Idle HLT will do the
right thing, i.e. not #VMEXIT and instead deliver the virtual event. KVM
currently doesn't handle this scenario correctly, e.g. doesn't check V_IRQ
or V_NMI in vmcs02 as part of kvm_vcpu_has_events().
Do not expose Idle HLT to L1 at this time, as supporting nested Idle HLT is
more complex than just enumerating the feature, e.g. requires KVM to handle
the aforementioned scenarios of V_IRQ and V_NMI at the time of exit.
Signed-off-by: Manali Shukla <Manali.Shukla@amd.com>
Reviewed-by: Nikunj A Dadhania <nikunj@amd.com>
Link: https://bugzilla.kernel.org/attachment.cgi?id=306250
Link: https://lore.kernel.org/r/20250128124812.7324-3-manali.shukla@amd.com
[sean: rewrite changelog, drop nested "support"]
Signed-off-by: Sean Christopherson <seanjc@google.com>
2025-01-28 12:48:11 +00:00
|
|
|
#define SVM_EXIT_IDLE_HLT 0x0a6
|
2012-12-14 22:37:13 +00:00
|
|
|
#define SVM_EXIT_NPF 0x400
|
2016-05-04 14:09:48 -05:00
|
|
|
#define SVM_EXIT_AVIC_INCOMPLETE_IPI 0x401
|
|
|
|
#define SVM_EXIT_AVIC_UNACCELERATED_ACCESS 0x402
|
2020-12-10 11:09:47 -06:00
|
|
|
#define SVM_EXIT_VMGEXIT 0x403
|
2012-12-14 22:37:13 +00:00
|
|
|
|
2020-09-07 15:15:50 +02:00
|
|
|
/* SEV-ES software-defined VMGEXIT events */
|
|
|
|
#define SVM_VMGEXIT_MMIO_READ 0x80000001
|
|
|
|
#define SVM_VMGEXIT_MMIO_WRITE 0x80000002
|
2020-09-07 15:16:11 +02:00
|
|
|
#define SVM_VMGEXIT_NMI_COMPLETE 0x80000003
|
2020-09-07 15:16:10 +02:00
|
|
|
#define SVM_VMGEXIT_AP_HLT_LOOP 0x80000004
|
2020-09-07 15:16:07 +02:00
|
|
|
#define SVM_VMGEXIT_AP_JUMP_TABLE 0x80000005
|
|
|
|
#define SVM_VMGEXIT_SET_AP_JUMP_TABLE 0
|
|
|
|
#define SVM_VMGEXIT_GET_AP_JUMP_TABLE 1
|
2022-02-24 10:56:01 -06:00
|
|
|
#define SVM_VMGEXIT_PSC 0x80000010
|
2022-03-07 15:33:51 -06:00
|
|
|
#define SVM_VMGEXIT_GUEST_REQUEST 0x80000011
|
|
|
|
#define SVM_VMGEXIT_EXT_GUEST_REQUEST 0x80000012
|
2022-03-07 15:33:32 -06:00
|
|
|
#define SVM_VMGEXIT_AP_CREATION 0x80000013
|
|
|
|
#define SVM_VMGEXIT_AP_CREATE_ON_INIT 0
|
|
|
|
#define SVM_VMGEXIT_AP_CREATE 1
|
|
|
|
#define SVM_VMGEXIT_AP_DESTROY 2
|
2024-06-05 10:18:46 -05:00
|
|
|
#define SVM_VMGEXIT_SNP_RUN_VMPL 0x80000018
|
2022-02-09 12:10:06 -06:00
|
|
|
#define SVM_VMGEXIT_HV_FEATURES 0x8000fffd
|
2023-01-18 11:49:43 +05:30
|
|
|
#define SVM_VMGEXIT_TERM_REQUEST 0x8000fffe
|
|
|
|
#define SVM_VMGEXIT_TERM_REASON(reason_set, reason_code) \
|
|
|
|
/* SW_EXITINFO1[3:0] */ \
|
|
|
|
(((((u64)reason_set) & 0xf)) | \
|
|
|
|
/* SW_EXITINFO1[11:4] */ \
|
|
|
|
((((u64)reason_code) & 0xff) << 4))
|
2020-09-07 15:15:50 +02:00
|
|
|
#define SVM_VMGEXIT_UNSUPPORTED_EVENT 0x8000ffff
|
|
|
|
|
2021-06-03 15:14:37 +00:00
|
|
|
/* Exit code reserved for hypervisor/software use */
|
|
|
|
#define SVM_EXIT_SW 0xf0000000
|
|
|
|
|
2012-12-14 22:37:13 +00:00
|
|
|
#define SVM_EXIT_ERR -1
|
|
|
|
|
|
|
|
#define SVM_EXIT_REASONS \
|
|
|
|
{ SVM_EXIT_READ_CR0, "read_cr0" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_READ_CR2, "read_cr2" }, \
|
2012-12-14 22:37:13 +00:00
|
|
|
{ SVM_EXIT_READ_CR3, "read_cr3" }, \
|
|
|
|
{ SVM_EXIT_READ_CR4, "read_cr4" }, \
|
|
|
|
{ SVM_EXIT_READ_CR8, "read_cr8" }, \
|
|
|
|
{ SVM_EXIT_WRITE_CR0, "write_cr0" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_WRITE_CR2, "write_cr2" }, \
|
2012-12-14 22:37:13 +00:00
|
|
|
{ SVM_EXIT_WRITE_CR3, "write_cr3" }, \
|
|
|
|
{ SVM_EXIT_WRITE_CR4, "write_cr4" }, \
|
|
|
|
{ SVM_EXIT_WRITE_CR8, "write_cr8" }, \
|
|
|
|
{ SVM_EXIT_READ_DR0, "read_dr0" }, \
|
|
|
|
{ SVM_EXIT_READ_DR1, "read_dr1" }, \
|
|
|
|
{ SVM_EXIT_READ_DR2, "read_dr2" }, \
|
|
|
|
{ SVM_EXIT_READ_DR3, "read_dr3" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_READ_DR4, "read_dr4" }, \
|
|
|
|
{ SVM_EXIT_READ_DR5, "read_dr5" }, \
|
|
|
|
{ SVM_EXIT_READ_DR6, "read_dr6" }, \
|
|
|
|
{ SVM_EXIT_READ_DR7, "read_dr7" }, \
|
2012-12-14 22:37:13 +00:00
|
|
|
{ SVM_EXIT_WRITE_DR0, "write_dr0" }, \
|
|
|
|
{ SVM_EXIT_WRITE_DR1, "write_dr1" }, \
|
|
|
|
{ SVM_EXIT_WRITE_DR2, "write_dr2" }, \
|
|
|
|
{ SVM_EXIT_WRITE_DR3, "write_dr3" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_WRITE_DR4, "write_dr4" }, \
|
2012-12-14 22:37:13 +00:00
|
|
|
{ SVM_EXIT_WRITE_DR5, "write_dr5" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_WRITE_DR6, "write_dr6" }, \
|
2012-12-14 22:37:13 +00:00
|
|
|
{ SVM_EXIT_WRITE_DR7, "write_dr7" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_EXCP_BASE + DE_VECTOR, "DE excp" }, \
|
2012-12-14 22:37:13 +00:00
|
|
|
{ SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \
|
|
|
|
{ SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_EXCP_BASE + OF_VECTOR, "OF excp" }, \
|
|
|
|
{ SVM_EXIT_EXCP_BASE + BR_VECTOR, "BR excp" }, \
|
2012-12-14 22:37:13 +00:00
|
|
|
{ SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
|
|
|
|
{ SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_EXCP_BASE + DF_VECTOR, "DF excp" }, \
|
|
|
|
{ SVM_EXIT_EXCP_BASE + TS_VECTOR, "TS excp" }, \
|
|
|
|
{ SVM_EXIT_EXCP_BASE + NP_VECTOR, "NP excp" }, \
|
|
|
|
{ SVM_EXIT_EXCP_BASE + SS_VECTOR, "SS excp" }, \
|
|
|
|
{ SVM_EXIT_EXCP_BASE + GP_VECTOR, "GP excp" }, \
|
|
|
|
{ SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
|
|
|
|
{ SVM_EXIT_EXCP_BASE + MF_VECTOR, "MF excp" }, \
|
2015-11-03 18:03:53 +01:00
|
|
|
{ SVM_EXIT_EXCP_BASE + AC_VECTOR, "AC excp" }, \
|
2012-12-14 22:37:13 +00:00
|
|
|
{ SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_EXCP_BASE + XM_VECTOR, "XF excp" }, \
|
2012-12-14 22:37:13 +00:00
|
|
|
{ SVM_EXIT_INTR, "interrupt" }, \
|
|
|
|
{ SVM_EXIT_NMI, "nmi" }, \
|
|
|
|
{ SVM_EXIT_SMI, "smi" }, \
|
|
|
|
{ SVM_EXIT_INIT, "init" }, \
|
|
|
|
{ SVM_EXIT_VINTR, "vintr" }, \
|
2016-05-04 14:09:48 -05:00
|
|
|
{ SVM_EXIT_CR0_SEL_WRITE, "cr0_sel_write" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_IDTR_READ, "read_idtr" }, \
|
|
|
|
{ SVM_EXIT_GDTR_READ, "read_gdtr" }, \
|
|
|
|
{ SVM_EXIT_LDTR_READ, "read_ldtr" }, \
|
|
|
|
{ SVM_EXIT_TR_READ, "read_rt" }, \
|
|
|
|
{ SVM_EXIT_IDTR_WRITE, "write_idtr" }, \
|
|
|
|
{ SVM_EXIT_GDTR_WRITE, "write_gdtr" }, \
|
|
|
|
{ SVM_EXIT_LDTR_WRITE, "write_ldtr" }, \
|
|
|
|
{ SVM_EXIT_TR_WRITE, "write_rt" }, \
|
|
|
|
{ SVM_EXIT_RDTSC, "rdtsc" }, \
|
|
|
|
{ SVM_EXIT_RDPMC, "rdpmc" }, \
|
|
|
|
{ SVM_EXIT_PUSHF, "pushf" }, \
|
|
|
|
{ SVM_EXIT_POPF, "popf" }, \
|
2012-12-14 22:37:13 +00:00
|
|
|
{ SVM_EXIT_CPUID, "cpuid" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_RSM, "rsm" }, \
|
|
|
|
{ SVM_EXIT_IRET, "iret" }, \
|
|
|
|
{ SVM_EXIT_SWINT, "swint" }, \
|
2012-12-14 22:37:13 +00:00
|
|
|
{ SVM_EXIT_INVD, "invd" }, \
|
2016-05-04 14:09:48 -05:00
|
|
|
{ SVM_EXIT_PAUSE, "pause" }, \
|
2012-12-14 22:37:13 +00:00
|
|
|
{ SVM_EXIT_HLT, "hlt" }, \
|
|
|
|
{ SVM_EXIT_INVLPG, "invlpg" }, \
|
|
|
|
{ SVM_EXIT_INVLPGA, "invlpga" }, \
|
|
|
|
{ SVM_EXIT_IOIO, "io" }, \
|
|
|
|
{ SVM_EXIT_MSR, "msr" }, \
|
|
|
|
{ SVM_EXIT_TASK_SWITCH, "task_switch" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_FERR_FREEZE, "ferr_freeze" }, \
|
2012-12-14 22:37:13 +00:00
|
|
|
{ SVM_EXIT_SHUTDOWN, "shutdown" }, \
|
|
|
|
{ SVM_EXIT_VMRUN, "vmrun" }, \
|
|
|
|
{ SVM_EXIT_VMMCALL, "hypercall" }, \
|
|
|
|
{ SVM_EXIT_VMLOAD, "vmload" }, \
|
|
|
|
{ SVM_EXIT_VMSAVE, "vmsave" }, \
|
|
|
|
{ SVM_EXIT_STGI, "stgi" }, \
|
|
|
|
{ SVM_EXIT_CLGI, "clgi" }, \
|
|
|
|
{ SVM_EXIT_SKINIT, "skinit" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_RDTSCP, "rdtscp" }, \
|
|
|
|
{ SVM_EXIT_ICEBP, "icebp" }, \
|
2012-12-14 22:37:13 +00:00
|
|
|
{ SVM_EXIT_WBINVD, "wbinvd" }, \
|
|
|
|
{ SVM_EXIT_MONITOR, "monitor" }, \
|
|
|
|
{ SVM_EXIT_MWAIT, "mwait" }, \
|
|
|
|
{ SVM_EXIT_XSETBV, "xsetbv" }, \
|
2020-12-10 11:09:55 -06:00
|
|
|
{ SVM_EXIT_EFER_WRITE_TRAP, "write_efer_trap" }, \
|
2020-12-10 11:09:56 -06:00
|
|
|
{ SVM_EXIT_CR0_WRITE_TRAP, "write_cr0_trap" }, \
|
2020-12-10 11:09:57 -06:00
|
|
|
{ SVM_EXIT_CR4_WRITE_TRAP, "write_cr4_trap" }, \
|
2020-12-10 11:09:58 -06:00
|
|
|
{ SVM_EXIT_CR8_WRITE_TRAP, "write_cr8_trap" }, \
|
2020-09-11 14:29:19 -05:00
|
|
|
{ SVM_EXIT_INVPCID, "invpcid" }, \
|
2025-05-02 05:03:44 +00:00
|
|
|
{ SVM_EXIT_BUS_LOCK, "buslock" }, \
|
KVM: SVM: Add Idle HLT intercept support
Add support for "Idle HLT" interception on AMD CPUs, and enable Idle HLT
interception instead of "normal" HLT interception for all VMs for which
HLT-exiting is enabled. Idle HLT provides a mild performance boost for
all VM types, by avoiding a VM-Exit in the scenario where KVM would
immediately "wake" and resume the vCPU.
Idle HLT makes HLT-exiting conditional on the vCPU not having a valid,
unmasked interrupt. Specifically, a VM-Exit occurs on execution of HLT
if and only if there are no pending V_IRQ or V_NMI events. Note, Idle
is a replacement for full HLT interception, i.e. enabling HLT interception
would result in all HLT instructions causing unconditional VM-Exits. Per
the APM:
When both HLT and Idle HLT intercepts are active at the same time, the
HLT intercept takes priority. This intercept occurs only if a virtual
interrupt is not pending (V_INTR or V_NMI).
For KVM's use of V_IRQ (also called V_INTR in the APM) to detect interrupt
windows, the net effect of enabling Idle HLT is that, if a virtual
interupt is pending and unmasked at the time of HLT, the vCPU will take
a V_IRQ intercept instead of a HLT intercept.
When AVIC is enabled, Idle HLT works as intended: the vCPU continues
unimpeded and services the pending virtual interrupt.
Note, the APM's description of V_IRQ interaction with AVIC is quite
confusing, and requires piecing together implied behavior. Per the APM,
when AVIC is enabled, V_IRQ *from the VMCB* is ignored:
When AVIC mode is enabled for a virtual processor, the V_IRQ, V_INTR_PRIO,
V_INTR_VECTOR, and V_IGN_TPR fields in the VMCB are ignored.
Which seems to contradict the behavior of Idle HLT:
This intercept occurs only if a virtual interrupt is not pending (V_INTR
or V_NMI).
What's not explicitly stated is that hardware's internal copy of V_IRQ
(and related fields) *are* still active, i.e. are presumably used to cache
information from the virtual APIC.
Handle Idle HLT exits as if they were normal HLT exits, e.g. don't try to
optimize the handling under the assumption that there isn't a pending IRQ.
Irrespective of AVIC, Idle HLT is inherently racy with respect to the vIRR,
as KVM can set vIRR bits asychronously.
No changes are required to support KVM's use Idle HLT while running
L2. In fact, supporting Idle HLT is actually a bug fix to some extent.
If L1 wants to intercept HLT, recalc_intercepts() will enable HLT
interception in vmcb02 and forward the intercept to L1 as normal.
But if L1 does not want to intercept HLT, then KVM will run L2 with Idle
HLT enabled and HLT interception disabled. If a V_IRQ or V_NMI for L2
becomes pending and L2 executes HLT, then use of Idle HLT will do the
right thing, i.e. not #VMEXIT and instead deliver the virtual event. KVM
currently doesn't handle this scenario correctly, e.g. doesn't check V_IRQ
or V_NMI in vmcs02 as part of kvm_vcpu_has_events().
Do not expose Idle HLT to L1 at this time, as supporting nested Idle HLT is
more complex than just enumerating the feature, e.g. requires KVM to handle
the aforementioned scenarios of V_IRQ and V_NMI at the time of exit.
Signed-off-by: Manali Shukla <Manali.Shukla@amd.com>
Reviewed-by: Nikunj A Dadhania <nikunj@amd.com>
Link: https://bugzilla.kernel.org/attachment.cgi?id=306250
Link: https://lore.kernel.org/r/20250128124812.7324-3-manali.shukla@amd.com
[sean: rewrite changelog, drop nested "support"]
Signed-off-by: Sean Christopherson <seanjc@google.com>
2025-01-28 12:48:11 +00:00
|
|
|
{ SVM_EXIT_IDLE_HLT, "idle-halt" }, \
|
2016-05-04 14:09:48 -05:00
|
|
|
{ SVM_EXIT_NPF, "npf" }, \
|
|
|
|
{ SVM_EXIT_AVIC_INCOMPLETE_IPI, "avic_incomplete_ipi" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_AVIC_UNACCELERATED_ACCESS, "avic_unaccelerated_access" }, \
|
2020-12-10 11:09:47 -06:00
|
|
|
{ SVM_EXIT_VMGEXIT, "vmgexit" }, \
|
|
|
|
{ SVM_VMGEXIT_MMIO_READ, "vmgexit_mmio_read" }, \
|
|
|
|
{ SVM_VMGEXIT_MMIO_WRITE, "vmgexit_mmio_write" }, \
|
|
|
|
{ SVM_VMGEXIT_NMI_COMPLETE, "vmgexit_nmi_complete" }, \
|
|
|
|
{ SVM_VMGEXIT_AP_HLT_LOOP, "vmgexit_ap_hlt_loop" }, \
|
|
|
|
{ SVM_VMGEXIT_AP_JUMP_TABLE, "vmgexit_ap_jump_table" }, \
|
2022-02-24 10:56:01 -06:00
|
|
|
{ SVM_VMGEXIT_PSC, "vmgexit_page_state_change" }, \
|
2022-03-07 15:33:51 -06:00
|
|
|
{ SVM_VMGEXIT_GUEST_REQUEST, "vmgexit_guest_request" }, \
|
|
|
|
{ SVM_VMGEXIT_EXT_GUEST_REQUEST, "vmgexit_ext_guest_request" }, \
|
2022-03-07 15:33:32 -06:00
|
|
|
{ SVM_VMGEXIT_AP_CREATION, "vmgexit_ap_creation" }, \
|
2022-02-09 12:10:06 -06:00
|
|
|
{ SVM_VMGEXIT_HV_FEATURES, "vmgexit_hypervisor_feature" }, \
|
2016-05-23 08:43:31 +02:00
|
|
|
{ SVM_EXIT_ERR, "invalid_guest_state" }
|
2012-12-14 22:37:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
#endif /* _UAPI__SVM_H */
|