From 8c1a8a32438b95792bbd8719d1cd4fe36e9eba03 Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Fri, 13 Oct 2017 11:40:11 +0200 Subject: [PATCH 01/11] KVM: arm64: its: Fix missing dynamic allocation check in scan_its_table We currently allocate an entry dynamically, but we never check if the allocation actually succeeded. We actually don't need a dynamic allocation, because we know the maximum size of an ITS table entry, so we can simply use an allocation on the stack. Cc: Signed-off-by: Christoffer Dall --- virt/kvm/arm/vgic/vgic-its.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index f51c1e1b3f70..77652885a7c1 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c @@ -1801,37 +1801,33 @@ typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *entry, static int scan_its_table(struct vgic_its *its, gpa_t base, int size, int esz, int start_id, entry_fn_t fn, void *opaque) { - void *entry = kzalloc(esz, GFP_KERNEL); struct kvm *kvm = its->dev->kvm; unsigned long len = size; int id = start_id; gpa_t gpa = base; + char entry[esz]; int ret; + memset(entry, 0, esz); + while (len > 0) { int next_offset; size_t byte_offset; ret = kvm_read_guest(kvm, gpa, entry, esz); if (ret) - goto out; + return ret; next_offset = fn(its, id, entry, opaque); - if (next_offset <= 0) { - ret = next_offset; - goto out; - } + if (next_offset <= 0) + return next_offset; byte_offset = next_offset * esz; id += next_offset; gpa += byte_offset; len -= byte_offset; } - ret = 1; - -out: - kfree(entry); - return ret; + return 1; } /** From fd6c8c206fc5d0717b0433b191de0715122f33bb Mon Sep 17 00:00:00 2001 From: Dongjiu Geng Date: Tue, 17 Oct 2017 22:23:49 +0800 Subject: [PATCH 02/11] arm/arm64: KVM: set right LR register value for 32 bit guest when inject abort When a exception is trapped to EL2, hardware uses ELR_ELx to hold the current fault instruction address. If KVM wants to inject a abort to 32 bit guest, it needs to set the LR register for the guest to emulate this abort happened in the guest. Because ARM32 architecture is pipelined execution, so the LR value has an offset to the fault instruction address. The offsets applied to Link value for exceptions as shown below, which should be added for the ARM32 link register(LR). Table taken from ARMv8 ARM DDI0487B-B, table G1-10: Exception Offset, for PE state of: A32 T32 Undefined Instruction +4 +2 Prefetch Abort +4 +4 Data Abort +8 +8 IRQ or FIQ +4 +4 [ Removed unused variables in inject_abt to avoid compile warnings. -- Christoffer ] Cc: Signed-off-by: Dongjiu Geng Tested-by: Haibin Zhang Reviewed-by: Marc Zyngier Signed-off-by: Christoffer Dall --- arch/arm/kvm/emulate.c | 6 ++---- arch/arm64/kvm/inject_fault.c | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c index 0064b86a2c87..30a13647c54c 100644 --- a/arch/arm/kvm/emulate.c +++ b/arch/arm/kvm/emulate.c @@ -227,7 +227,7 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu) u32 return_offset = (is_thumb) ? 2 : 4; kvm_update_psr(vcpu, UND_MODE); - *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) - return_offset; + *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) + return_offset; /* Branch to exception vector */ *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset; @@ -239,10 +239,8 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu) */ static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr) { - unsigned long cpsr = *vcpu_cpsr(vcpu); - bool is_thumb = (cpsr & PSR_T_BIT); u32 vect_offset; - u32 return_offset = (is_thumb) ? 4 : 0; + u32 return_offset = (is_pabt) ? 4 : 8; bool is_lpae; kvm_update_psr(vcpu, ABT_MODE); diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c index da6a8cfa54a0..3556715a774e 100644 --- a/arch/arm64/kvm/inject_fault.c +++ b/arch/arm64/kvm/inject_fault.c @@ -33,12 +33,26 @@ #define LOWER_EL_AArch64_VECTOR 0x400 #define LOWER_EL_AArch32_VECTOR 0x600 +/* + * Table taken from ARMv8 ARM DDI0487B-B, table G1-10. + */ +static const u8 return_offsets[8][2] = { + [0] = { 0, 0 }, /* Reset, unused */ + [1] = { 4, 2 }, /* Undefined */ + [2] = { 0, 0 }, /* SVC, unused */ + [3] = { 4, 4 }, /* Prefetch abort */ + [4] = { 8, 8 }, /* Data abort */ + [5] = { 0, 0 }, /* HVC, unused */ + [6] = { 4, 4 }, /* IRQ, unused */ + [7] = { 4, 4 }, /* FIQ, unused */ +}; + static void prepare_fault32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset) { unsigned long cpsr; unsigned long new_spsr_value = *vcpu_cpsr(vcpu); bool is_thumb = (new_spsr_value & COMPAT_PSR_T_BIT); - u32 return_offset = (is_thumb) ? 4 : 0; + u32 return_offset = return_offsets[vect_offset >> 2][is_thumb]; u32 sctlr = vcpu_cp15(vcpu, c1_SCTLR); cpsr = mode | COMPAT_PSR_I_BIT; From fe7d7b03c61f6dab70a973fb32c90f2254784e03 Mon Sep 17 00:00:00 2001 From: Julien Thierry Date: Fri, 20 Oct 2017 12:34:16 +0100 Subject: [PATCH 03/11] arm/arm64: kvm: Move initialization completion message KVM is being a bit too optimistic, Hyp mode is said to be initialized when Hyp segments have only been mapped. Notify KVM's successful initialization only once it is really fully initialized. Signed-off-by: Julien Thierry Acked-by: Marc Zyngier Cc: Christoffer Dall Signed-off-by: Christoffer Dall --- virt/kvm/arm/arm.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index b9f68e4add71..95cba0799828 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -1326,21 +1326,12 @@ static void teardown_hyp_mode(void) { int cpu; - if (is_kernel_in_hyp_mode()) - return; - free_hyp_pgds(); for_each_possible_cpu(cpu) free_page(per_cpu(kvm_arm_hyp_stack_page, cpu)); hyp_cpu_pm_exit(); } -static int init_vhe_mode(void) -{ - kvm_info("VHE mode initialized successfully\n"); - return 0; -} - /** * Inits Hyp-mode on all online CPUs */ @@ -1421,8 +1412,6 @@ static int init_hyp_mode(void) } } - kvm_info("Hyp mode initialized successfully\n"); - return 0; out_err: @@ -1456,6 +1445,7 @@ int kvm_arch_init(void *opaque) { int err; int ret, cpu; + bool in_hyp_mode; if (!is_hyp_mode_available()) { kvm_err("HYP mode not available\n"); @@ -1474,21 +1464,28 @@ int kvm_arch_init(void *opaque) if (err) return err; - if (is_kernel_in_hyp_mode()) - err = init_vhe_mode(); - else + in_hyp_mode = is_kernel_in_hyp_mode(); + + if (!in_hyp_mode) { err = init_hyp_mode(); - if (err) - goto out_err; + if (err) + goto out_err; + } err = init_subsystems(); if (err) goto out_hyp; + if (in_hyp_mode) + kvm_info("VHE mode initialized successfully\n"); + else + kvm_info("Hyp mode initialized successfully\n"); + return 0; out_hyp: - teardown_hyp_mode(); + if (!in_hyp_mode) + teardown_hyp_mode(); out_err: teardown_common_resources(); return err; From f9b269f3098121b5d54aaf822e0898c8ed1d3fec Mon Sep 17 00:00:00 2001 From: Julien Thierry Date: Fri, 20 Oct 2017 12:34:17 +0100 Subject: [PATCH 04/11] arm/arm64: kvm: Disable branch profiling in HYP code When HYP code runs into branch profiling code, it attempts to jump to unmapped memory, causing a HYP Panic. Disable the branch profiling for code designed to run at HYP mode. Signed-off-by: Julien Thierry Acked-by: Marc Zyngier Cc: Christoffer Dall Cc: Catalin Marinas Cc: Will Deacon Cc: Russell King Cc: Signed-off-by: Christoffer Dall --- arch/arm/kvm/hyp/Makefile | 2 +- arch/arm64/kvm/hyp/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/kvm/hyp/Makefile b/arch/arm/kvm/hyp/Makefile index 8679405b0b2b..92eab1d51785 100644 --- a/arch/arm/kvm/hyp/Makefile +++ b/arch/arm/kvm/hyp/Makefile @@ -2,7 +2,7 @@ # Makefile for Kernel-based Virtual Machine module, HYP part # -ccflags-y += -fno-stack-protector +ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING KVM=../../../../virt/kvm diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index 14c4e3b14bcb..48b03547a969 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -2,7 +2,7 @@ # Makefile for Kernel-based Virtual Machine module, HYP part # -ccflags-y += -fno-stack-protector +ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING KVM=../../../../virt/kvm From b92382620e33c9f1bcbcd7c169262b9bf0525871 Mon Sep 17 00:00:00 2001 From: wanghaibin Date: Thu, 26 Oct 2017 17:23:03 +0200 Subject: [PATCH 05/11] KVM: arm/arm64: vgic-its: Fix return value for device table restore If ITT only contains invalid entries, vgic_its_restore_itt returns 1 and this is considered as an an error in vgic_its_restore_dte. Also in case the device table only contains invalid entries, the table restore fails and this is not correct. This patch fixes those 2 issues: - vgic_its_restore_itt now returns <= 0 values. If all ITEs are invalid, this is considered as successful. - vgic_its_restore_device_tables also returns <= 0 values. We also simplify the returned value computation in handle_l1_dte. Signed-off-by: wanghaibin Signed-off-by: Eric Auger Reviewed-by: Christoffer Dall Signed-off-by: Christoffer Dall --- virt/kvm/arm/vgic/vgic-its.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index 77652885a7c1..76685f4c6261 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c @@ -1936,6 +1936,14 @@ static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device) return 0; } +/** + * vgic_its_restore_itt - restore the ITT of a device + * + * @its: its handle + * @dev: device handle + * + * Return 0 on success, < 0 on error + */ static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev) { const struct vgic_its_abi *abi = vgic_its_get_abi(its); @@ -1947,6 +1955,10 @@ static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev) ret = scan_its_table(its, base, max_size, ite_esz, 0, vgic_its_restore_ite, dev); + /* scan_its_table returns +1 if all ITEs are invalid */ + if (ret > 0) + ret = 0; + return ret; } @@ -2103,10 +2115,7 @@ static int handle_l1_dte(struct vgic_its *its, u32 id, void *addr, ret = scan_its_table(its, gpa, SZ_64K, dte_esz, l2_start_id, vgic_its_restore_dte, NULL); - if (ret <= 0) - return ret; - - return 1; + return ret; } /** @@ -2136,8 +2145,9 @@ static int vgic_its_restore_device_tables(struct vgic_its *its) vgic_its_restore_dte, NULL); } + /* scan_its_table returns +1 if all entries are invalid */ if (ret > 0) - ret = -EINVAL; + ret = 0; return ret; } From f31b98b57f72dcd458eb63f795f4efe272acc2e3 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 26 Oct 2017 17:23:04 +0200 Subject: [PATCH 06/11] KVM: arm/arm64: vgic-its: Fix vgic_its_restore_collection_table returned value vgic_its_restore_cte returns +1 if the collection table entry is valid and properly decoded. As a consequence, if the collection table is fully filled with valid data that are decoded without error, vgic_its_restore_collection_table() returns +1. This is wrong. Let's return 0 in that case. Fixes: ea1ad53e1e31a3 (KVM: arm64: vgic-its: Collection table save/restore) Signed-off-by: Eric Auger Signed-off-by: Christoffer Dall --- virt/kvm/arm/vgic/vgic-its.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index 76685f4c6261..6a715a6ec64e 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c @@ -2264,6 +2264,10 @@ static int vgic_its_restore_collection_table(struct vgic_its *its) gpa += cte_esz; read += cte_esz; } + + if (ret > 0) + return 0; + return ret; } From c9b51bb60d944067f36f67750e19c18c3cc2697c Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 26 Oct 2017 17:23:05 +0200 Subject: [PATCH 07/11] KVM: arm/arm64: vgic-its: Check CBASER/BASER validity before enabling the ITS The spec says it is UNPREDICTABLE to enable the ITS if any of the following conditions are true: - GITS_CBASER.Valid == 0. - GITS_BASER.Valid == 0, for any GITS_BASER register where the Type field indicates Device. - GITS_BASER.Valid == 0, for any GITS_BASER register where the Type field indicates Interrupt Collection and GITS_TYPER.HCC == 0. In that case, let's keep the ITS disabled. Signed-off-by: Eric Auger Reported-by: Andre Przywara Reviewed-by: Christoffer Dall Signed-off-by: Christoffer Dall --- virt/kvm/arm/vgic/vgic-its.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index 6a715a6ec64e..e69ef7d27fde 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c @@ -1466,6 +1466,16 @@ static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its, { mutex_lock(&its->cmd_lock); + /* + * It is UNPREDICTABLE to enable the ITS if any of the CBASER or + * device/collection BASER are invalid + */ + if (!its->enabled && (val & GITS_CTLR_ENABLE) && + (!(its->baser_device_table & GITS_BASER_VALID) || + !(its->baser_coll_table & GITS_BASER_VALID) || + !(its->cbaser & GITS_CBASER_VALID))) + goto out; + its->enabled = !!(val & GITS_CTLR_ENABLE); /* @@ -1474,6 +1484,7 @@ static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its, */ vgic_its_process_commands(kvm, its); +out: mutex_unlock(&its->cmd_lock); } From c2385eaa6c5a87cdc4e04ed589ae103ca3297c84 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 26 Oct 2017 17:23:06 +0200 Subject: [PATCH 08/11] KVM: arm/arm64: vgic-its: Check GITS_BASER Valid bit before saving tables At the moment we don't properly check the GITS_BASER.Valid bit before saving the collection and device tables. On vgic_its_save_collection_table() we use the GITS_BASER gpa field whereas the Valid bit should be used. On vgic_its_save_device_tables() there is no check. This can cause various bugs, among which a subsequent fault when accessing the table in guest memory. Let's systematically check the Valid bit before doing anything. We also uniformize the code between save and restore. Signed-off-by: Eric Auger Reviewed-by: Andre Przywara Reviewed-by: Christoffer Dall Reviewed-by: Marc Zyngier Signed-off-by: Christoffer Dall --- virt/kvm/arm/vgic/vgic-its.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index e69ef7d27fde..547f12dc4d54 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c @@ -2067,11 +2067,12 @@ static int vgic_its_device_cmp(void *priv, struct list_head *a, static int vgic_its_save_device_tables(struct vgic_its *its) { const struct vgic_its_abi *abi = vgic_its_get_abi(its); + u64 baser = its->baser_device_table; struct its_device *dev; int dte_esz = abi->dte_esz; - u64 baser; - baser = its->baser_device_table; + if (!(baser & GITS_BASER_VALID)) + return 0; list_sort(NULL, &its->device_list, vgic_its_device_cmp); @@ -2215,17 +2216,17 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz) static int vgic_its_save_collection_table(struct vgic_its *its) { const struct vgic_its_abi *abi = vgic_its_get_abi(its); + u64 baser = its->baser_coll_table; + gpa_t gpa = BASER_ADDRESS(baser); struct its_collection *collection; u64 val; - gpa_t gpa; size_t max_size, filled = 0; int ret, cte_esz = abi->cte_esz; - gpa = BASER_ADDRESS(its->baser_coll_table); - if (!gpa) + if (!(baser & GITS_BASER_VALID)) return 0; - max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K; + max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K; list_for_each_entry(collection, &its->collection_list, coll_list) { ret = vgic_its_save_cte(its, collection, gpa, cte_esz); @@ -2256,17 +2257,18 @@ static int vgic_its_save_collection_table(struct vgic_its *its) static int vgic_its_restore_collection_table(struct vgic_its *its) { const struct vgic_its_abi *abi = vgic_its_get_abi(its); + u64 baser = its->baser_coll_table; int cte_esz = abi->cte_esz; size_t max_size, read = 0; gpa_t gpa; int ret; - if (!(its->baser_coll_table & GITS_BASER_VALID)) + if (!(baser & GITS_BASER_VALID)) return 0; - gpa = BASER_ADDRESS(its->baser_coll_table); + gpa = BASER_ADDRESS(baser); - max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K; + max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K; while (read < max_size) { ret = vgic_its_restore_cte(its, gpa, cte_esz); From 008755209ce1ae86c0f562a44810b57d9ea31a71 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Tue, 31 Oct 2017 14:28:09 -0600 Subject: [PATCH 09/11] kvm: Return -ENODEV from update_persistent_clock kvm does not support setting the RTC, so the correct result is -ENODEV. Returning -1 will cause sync_cmos_clock to keep trying to set the RTC every second. Signed-off-by: Jason Gunthorpe Signed-off-by: Paolo Bonzini --- arch/x86/kernel/kvmclock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index d88967659098..5b609e28ce3f 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c @@ -79,7 +79,7 @@ static void kvm_get_wallclock(struct timespec *now) static int kvm_set_wallclock(const struct timespec *now) { - return -1; + return -ENODEV; } static u64 kvm_clock_read(void) From a4888486c5d755118a3c8a30416d7e0febdfb298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=2E=20Sch=C3=B6nherr?= Date: Wed, 25 Oct 2017 16:43:26 +0200 Subject: [PATCH 10/11] KVM: VMX: Do not fully reset PI descriptor on vCPU reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parts of the posted interrupt descriptor configure host behavior, such as the notification vector and destination. Overwriting them with zero as done during vCPU reset breaks posted interrupts. KVM (re-)writes these fields on certain occasions and belatedly fixes the situation in many cases. However, if you have a guest configured with "idle=poll", for example, the fields might stay zero forever. Do not reset the full descriptor in vmx_vcpu_reset(). Instead, reset only the outstanding notifications and leave everything else untouched. Signed-off-by: Jan H. Schönherr Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 95a01609d7ee..e0b4b64f211a 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -5619,8 +5619,10 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu); - if (kvm_vcpu_apicv_active(vcpu)) - memset(&vmx->pi_desc, 0, sizeof(struct pi_desc)); + if (kvm_vcpu_apicv_active(vcpu)) { + pi_clear_on(&vmx->pi_desc); + memset(vmx->pi_desc.pir, 0, sizeof(vmx->pi_desc.pir)); + } if (vmx->vpid != 0) vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid); From 4191db26b714e077e6faddd82d575ae4a8ae7d63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=2E=20Sch=C3=B6nherr?= Date: Wed, 25 Oct 2017 16:43:27 +0200 Subject: [PATCH 11/11] KVM: x86: Update APICv on APIC reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In kvm_apic_set_state() we update the hardware virtualized APIC after the full APIC state has been overwritten. Do the same, when the full APIC state has been reset in kvm_lapic_reset(). This updates some hardware state that was previously forgotten, as far as I can tell. Also, this allows removing some APIC-related reset code from vmx_vcpu_reset(). Signed-off-by: Jan H. Schönherr Signed-off-by: Paolo Bonzini --- arch/x86/kvm/lapic.c | 5 +++++ arch/x86/kvm/vmx.c | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 69c5612be786..36c90d631096 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1992,6 +1992,11 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event) vcpu->arch.apic_base | MSR_IA32_APICBASE_BSP); vcpu->arch.pv_eoi.msr_val = 0; apic_update_ppr(apic); + if (vcpu->arch.apicv_active) { + kvm_x86_ops->apicv_post_state_restore(vcpu); + kvm_x86_ops->hwapic_irr_update(vcpu, -1); + kvm_x86_ops->hwapic_isr_update(vcpu, -1); + } vcpu->arch.apic_arb_prio = 0; vcpu->arch.apic_attention = 0; diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index e0b4b64f211a..a6f4f095f8f4 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -5619,11 +5619,6 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu); - if (kvm_vcpu_apicv_active(vcpu)) { - pi_clear_on(&vmx->pi_desc); - memset(vmx->pi_desc.pir, 0, sizeof(vmx->pi_desc.pir)); - } - if (vmx->vpid != 0) vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);