[PATCH v3 5/8] kvm: x86: Emulate split-lock access as a write

From: Xiaoyao Li
Date: Thu Feb 06 2020 - 02:09:46 EST


If split lock detect is enabled (warn/fatal), #AC handler calls die()
when split lock happens in kernel.

A sane guest should never tigger emulation on a split-lock access, but
it cannot prevent malicous guest from doing this. So just emulating the
access as a write if it's a split-lock access (the same as access spans
page) to avoid malicous guest polluting the kernel log.

More detail analysis can be found:
https://lkml.kernel.org/r/20200131200134.GD18946@xxxxxxxxxxxxxxx

Suggested-by: Sean Christopherson <sean.j.christopherson@xxxxxxxxx>
Signed-off-by: Xiaoyao Li <xiaoyao.li@xxxxxxxxx>
---
v3:
- intergrate cache split case into page split case to reuse the logic;
---
arch/x86/kvm/x86.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 2d3be7f3ad67..fab4d25575bf 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5856,6 +5856,7 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
{
struct kvm_host_map map;
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
+ u64 page_line_mask = PAGE_MASK;
gpa_t gpa;
char *kaddr;
bool exchanged;
@@ -5870,7 +5871,11 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
(gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
goto emul_write;

- if (((gpa + bytes - 1) & PAGE_MASK) != (gpa & PAGE_MASK))
+ if (split_lock_detect_enabled())
+ page_line_mask = ~(cache_line_size() - 1);
+
+ /* when write spans page or spans cache when SLD enabled */
+ if (((gpa + bytes - 1) & page_line_mask) != (gpa & page_line_mask))
goto emul_write;

if (kvm_vcpu_map(vcpu, gpa_to_gfn(gpa), &map))
--
2.23.0