From cd1c312f93ff3ef7b05cdf11a3954024907a7878 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: May 23 2023 15:21:14 +0000 Subject: KVM: x86: emulator: introduce emulator_recalc_and_set_mode (git-fixes). --- diff --git a/patches.suse/KVM-x86-emulator-introduce-emulator_recalc_and_set_m.patch b/patches.suse/KVM-x86-emulator-introduce-emulator_recalc_and_set_m.patch new file mode 100644 index 0000000..3eff6de --- /dev/null +++ b/patches.suse/KVM-x86-emulator-introduce-emulator_recalc_and_set_m.patch @@ -0,0 +1,166 @@ +Patch-mainline: v6.1-rc4 +Git-commit: d087e0f79fa0dd336a9a6b2f79ec23120f5eff73 +References: git-fixes +From: Maxim Levitsky +Date: Tue, 25 Oct 2022 15:47:29 +0300 +Subject: [PATCH] KVM: x86: emulator: introduce emulator_recalc_and_set_mode + +Some instructions update the cpu execution mode, which needs to update the +emulation mode. + +Extract this code, and make assign_eip_far use it. + +assign_eip_far now reads CS, instead of getting it via a parameter, +which is ok, because callers always assign CS to the same value +before calling this function. + +No functional change is intended. + +Signed-off-by: Maxim Levitsky +Message-Id: <20221025124741.228045-12-mlevitsk@redhat.com> +Cc: stable@vger.kernel.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Juergen Gross +--- + arch/x86/kvm/emulate.c | 85 ++++++++++++++++++++++++++++-------------- + 1 file changed, 57 insertions(+), 28 deletions(-) + +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index 261732957431..e5522a23d985 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -791,8 +791,7 @@ static int linearize(struct x86_emulate_ctxt *ctxt, + ctxt->mode, linear); + } + +-static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst, +- enum x86emul_mode mode) ++static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst) + { + ulong linear; + int rc; +@@ -802,41 +801,71 @@ static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst, + + if (ctxt->op_bytes != sizeof(unsigned long)) + addr.ea = dst & ((1UL << (ctxt->op_bytes << 3)) - 1); +- rc = __linearize(ctxt, addr, &max_size, 1, false, true, mode, &linear); ++ rc = __linearize(ctxt, addr, &max_size, 1, false, true, ctxt->mode, &linear); + if (rc == X86EMUL_CONTINUE) + ctxt->_eip = addr.ea; + return rc; + } + ++static inline int emulator_recalc_and_set_mode(struct x86_emulate_ctxt *ctxt) ++{ ++ u64 efer; ++ struct desc_struct cs; ++ u16 selector; ++ u32 base3; ++ ++ ctxt->ops->get_msr(ctxt, MSR_EFER, &efer); ++ ++ if (!(ctxt->ops->get_cr(ctxt, 0) & X86_CR0_PE)) { ++ /* Real mode. cpu must not have long mode active */ ++ if (efer & EFER_LMA) ++ return X86EMUL_UNHANDLEABLE; ++ ctxt->mode = X86EMUL_MODE_REAL; ++ return X86EMUL_CONTINUE; ++ } ++ ++ if (ctxt->eflags & X86_EFLAGS_VM) { ++ /* Protected/VM86 mode. cpu must not have long mode active */ ++ if (efer & EFER_LMA) ++ return X86EMUL_UNHANDLEABLE; ++ ctxt->mode = X86EMUL_MODE_VM86; ++ return X86EMUL_CONTINUE; ++ } ++ ++ if (!ctxt->ops->get_segment(ctxt, &selector, &cs, &base3, VCPU_SREG_CS)) ++ return X86EMUL_UNHANDLEABLE; ++ ++ if (efer & EFER_LMA) { ++ if (cs.l) { ++ /* Proper long mode */ ++ ctxt->mode = X86EMUL_MODE_PROT64; ++ } else if (cs.d) { ++ /* 32 bit compatibility mode*/ ++ ctxt->mode = X86EMUL_MODE_PROT32; ++ } else { ++ ctxt->mode = X86EMUL_MODE_PROT16; ++ } ++ } else { ++ /* Legacy 32 bit / 16 bit mode */ ++ ctxt->mode = cs.d ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; ++ } ++ ++ return X86EMUL_CONTINUE; ++} ++ + static inline int assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst) + { +- return assign_eip(ctxt, dst, ctxt->mode); ++ return assign_eip(ctxt, dst); + } + +-static int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst, +- const struct desc_struct *cs_desc) ++static int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst) + { +- enum x86emul_mode mode = ctxt->mode; +- int rc; ++ int rc = emulator_recalc_and_set_mode(ctxt); + +-#ifdef CONFIG_X86_64 +- if (ctxt->mode >= X86EMUL_MODE_PROT16) { +- if (cs_desc->l) { +- u64 efer = 0; ++ if (rc != X86EMUL_CONTINUE) ++ return rc; + +- ctxt->ops->get_msr(ctxt, MSR_EFER, &efer); +- if (efer & EFER_LMA) +- mode = X86EMUL_MODE_PROT64; +- } else +- mode = X86EMUL_MODE_PROT32; /* temporary value */ +- } +-#endif +- if (mode == X86EMUL_MODE_PROT16 || mode == X86EMUL_MODE_PROT32) +- mode = cs_desc->d ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; +- rc = assign_eip(ctxt, dst, mode); +- if (rc == X86EMUL_CONTINUE) +- ctxt->mode = mode; +- return rc; ++ return assign_eip(ctxt, dst); + } + + static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel) +@@ -2172,7 +2201,7 @@ static int em_jmp_far(struct x86_emulate_ctxt *ctxt) + if (rc != X86EMUL_CONTINUE) + return rc; + +- rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc); ++ rc = assign_eip_far(ctxt, ctxt->src.val); + /* Error handling is not implemented. */ + if (rc != X86EMUL_CONTINUE) + return X86EMUL_UNHANDLEABLE; +@@ -2250,7 +2279,7 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt) + &new_desc); + if (rc != X86EMUL_CONTINUE) + return rc; +- rc = assign_eip_far(ctxt, eip, &new_desc); ++ rc = assign_eip_far(ctxt, eip); + /* Error handling is not implemented. */ + if (rc != X86EMUL_CONTINUE) + return X86EMUL_UNHANDLEABLE; +@@ -3470,7 +3499,7 @@ static int em_call_far(struct x86_emulate_ctxt *ctxt) + if (rc != X86EMUL_CONTINUE) + return rc; + +- rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc); ++ rc = assign_eip_far(ctxt, ctxt->src.val); + if (rc != X86EMUL_CONTINUE) + goto fail; + +-- +2.35.3 + diff --git a/series.conf b/series.conf index 09faccc..f91f756 100644 --- a/series.conf +++ b/series.conf @@ -63146,6 +63146,7 @@ patches.suse/usb-dwc3-gadget-Stop-processing-more-requests-on-IMI.patch patches.suse/usb-dwc3-gadget-Don-t-set-IMI-for-no_interrupt.patch patches.suse/KVM-x86-emulator-em_sysexit-should-update-ctxt-mode.patch + patches.suse/KVM-x86-emulator-introduce-emulator_recalc_and_set_m.patch patches.suse/NFSv4.1-Handle-RECLAIM_COMPLETE-trunking-errors.patch patches.suse/NFSv4.1-We-must-always-send-RECLAIM_COMPLETE-after-a.patch patches.suse/NFSv4.2-Fixup-CLONE-dest-file-size-for-zero-length-c.patch