]>
Commit | Line | Data |
---|---|---|
e6832405 SL |
1 | From d570385a431a75e0b8e2c31b8b4feb542a031aaa Mon Sep 17 00:00:00 2001 |
2 | From: Vitaly Kuznetsov <vkuznets@redhat.com> | |
3 | Date: Wed, 20 Mar 2019 18:43:20 +0100 | |
4 | Subject: x86: kvm: hyper-v: deal with buggy TLB flush requests from WS2012 | |
5 | ||
6 | [ Upstream commit da66761c2d93a46270d69001abb5692717495a68 ] | |
7 | ||
8 | It was reported that with some special Multi Processor Group configuration, | |
9 | e.g: | |
10 | bcdedit.exe /set groupsize 1 | |
11 | bcdedit.exe /set maxgroup on | |
12 | bcdedit.exe /set groupaware on | |
13 | for a 16-vCPU guest WS2012 shows BSOD on boot when PV TLB flush mechanism | |
14 | is in use. | |
15 | ||
16 | Tracing kvm_hv_flush_tlb immediately reveals the issue: | |
17 | ||
18 | kvm_hv_flush_tlb: processor_mask 0x0 address_space 0x0 flags 0x2 | |
19 | ||
20 | The only flag set in this request is HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES, | |
21 | however, processor_mask is 0x0 and no HV_FLUSH_ALL_PROCESSORS is specified. | |
22 | We don't flush anything and apparently it's not what Windows expects. | |
23 | ||
24 | TLFS doesn't say anything about such requests and newer Windows versions | |
25 | seem to be unaffected. This all feels like a WS2012 bug, which is, however, | |
26 | easy to workaround in KVM: let's flush everything when we see an empty | |
27 | flush request, over-flushing doesn't hurt. | |
28 | ||
29 | Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> | |
30 | Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> | |
31 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
32 | --- | |
33 | arch/x86/kvm/hyperv.c | 11 ++++++++++- | |
34 | 1 file changed, 10 insertions(+), 1 deletion(-) | |
35 | ||
36 | diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c | |
37 | index 371c669696d70..610c0f1fbdd71 100644 | |
38 | --- a/arch/x86/kvm/hyperv.c | |
39 | +++ b/arch/x86/kvm/hyperv.c | |
40 | @@ -1371,7 +1371,16 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *current_vcpu, u64 ingpa, | |
41 | ||
42 | valid_bank_mask = BIT_ULL(0); | |
43 | sparse_banks[0] = flush.processor_mask; | |
44 | - all_cpus = flush.flags & HV_FLUSH_ALL_PROCESSORS; | |
45 | + | |
46 | + /* | |
47 | + * Work around possible WS2012 bug: it sends hypercalls | |
48 | + * with processor_mask = 0x0 and HV_FLUSH_ALL_PROCESSORS clear, | |
49 | + * while also expecting us to flush something and crashing if | |
50 | + * we don't. Let's treat processor_mask == 0 same as | |
51 | + * HV_FLUSH_ALL_PROCESSORS. | |
52 | + */ | |
53 | + all_cpus = (flush.flags & HV_FLUSH_ALL_PROCESSORS) || | |
54 | + flush.processor_mask == 0; | |
55 | } else { | |
56 | if (unlikely(kvm_read_guest(kvm, ingpa, &flush_ex, | |
57 | sizeof(flush_ex)))) | |
58 | -- | |
59 | 2.20.1 | |
60 |