diff options
author | Christian Borntraeger <borntraeger@de.ibm.com> | 2014-09-03 15:23:13 -0400 |
---|---|---|
committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2014-09-10 06:19:42 -0400 |
commit | f7a960affc6e5a33e8c7fcef065affc4f0461041 (patch) | |
tree | 4ffa230638dd30ef0f82201b3c3a6945bc4f35fd /arch/s390 | |
parent | 6b331952f1bc2df61c98954e25578629c439e417 (diff) |
KVM: s390/cmm: Fix prefix handling for diag 10 balloon
The old handling of prefix pages was broken in the diag10 ballooner.
We now rely on gmap_discard to check for start > end and do a
slow path if the prefix swap pages are affected:
1. discard the pages from start to prefix
2. discard the absolute 0 pages
3. discard the pages after prefix swap to end
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/kvm/diag.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index b374b6cb7785..9254afff250c 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c | |||
@@ -28,22 +28,32 @@ static int diag_release_pages(struct kvm_vcpu *vcpu) | |||
28 | start = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4]; | 28 | start = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4]; |
29 | end = vcpu->run->s.regs.gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096; | 29 | end = vcpu->run->s.regs.gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096; |
30 | 30 | ||
31 | if (start & ~PAGE_MASK || end & ~PAGE_MASK || start > end | 31 | if (start & ~PAGE_MASK || end & ~PAGE_MASK || start >= end |
32 | || start < 2 * PAGE_SIZE) | 32 | || start < 2 * PAGE_SIZE) |
33 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 33 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
34 | 34 | ||
35 | VCPU_EVENT(vcpu, 5, "diag release pages %lX %lX", start, end); | 35 | VCPU_EVENT(vcpu, 5, "diag release pages %lX %lX", start, end); |
36 | vcpu->stat.diagnose_10++; | 36 | vcpu->stat.diagnose_10++; |
37 | 37 | ||
38 | /* we checked for start > end above */ | 38 | /* |
39 | if (end < prefix || start >= prefix + 2 * PAGE_SIZE) { | 39 | * We checked for start >= end above, so lets check for the |
40 | * fast path (no prefix swap page involved) | ||
41 | */ | ||
42 | if (end <= prefix || start >= prefix + 2 * PAGE_SIZE) { | ||
40 | gmap_discard(vcpu->arch.gmap, start, end); | 43 | gmap_discard(vcpu->arch.gmap, start, end); |
41 | } else { | 44 | } else { |
42 | if (start < prefix) | 45 | /* |
43 | gmap_discard(vcpu->arch.gmap, start, prefix); | 46 | * This is slow path. gmap_discard will check for start |
44 | if (end >= prefix) | 47 | * so lets split this into before prefix, prefix, after |
45 | gmap_discard(vcpu->arch.gmap, | 48 | * prefix and let gmap_discard make some of these calls |
46 | prefix + 2 * PAGE_SIZE, end); | 49 | * NOPs. |
50 | */ | ||
51 | gmap_discard(vcpu->arch.gmap, start, prefix); | ||
52 | if (start <= prefix) | ||
53 | gmap_discard(vcpu->arch.gmap, 0, 4096); | ||
54 | if (end > prefix + 4096) | ||
55 | gmap_discard(vcpu->arch.gmap, 4096, 8192); | ||
56 | gmap_discard(vcpu->arch.gmap, prefix + 2 * PAGE_SIZE, end); | ||
47 | } | 57 | } |
48 | return 0; | 58 | return 0; |
49 | } | 59 | } |