summaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/diag.c
diff options
context:
space:
mode:
authorChristian Borntraeger <borntraeger@de.ibm.com>2014-09-03 21:23:13 +0200
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-09-10 12:19:42 +0200
commitf7a960affc6e5a33e8c7fcef065affc4f0461041 (patch)
tree4ffa230638dd30ef0f82201b3c3a6945bc4f35fd /arch/s390/kvm/diag.c
parentKVM: s390: get rid of constant condition in ipte_unlock_simple (diff)
downloadlinux-f7a960affc6e5a33e8c7fcef065affc4f0461041.tar.xz
linux-f7a960affc6e5a33e8c7fcef065affc4f0461041.zip
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/kvm/diag.c')
-rw-r--r--arch/s390/kvm/diag.c26
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)
start = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4];
end = vcpu->run->s.regs.gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096;
- if (start & ~PAGE_MASK || end & ~PAGE_MASK || start > end
+ if (start & ~PAGE_MASK || end & ~PAGE_MASK || start >= end
|| start < 2 * PAGE_SIZE)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
VCPU_EVENT(vcpu, 5, "diag release pages %lX %lX", start, end);
vcpu->stat.diagnose_10++;
- /* we checked for start > end above */
- if (end < prefix || start >= prefix + 2 * PAGE_SIZE) {
+ /*
+ * We checked for start >= end above, so lets check for the
+ * fast path (no prefix swap page involved)
+ */
+ if (end <= prefix || start >= prefix + 2 * PAGE_SIZE) {
gmap_discard(vcpu->arch.gmap, start, end);
} else {
- if (start < prefix)
- gmap_discard(vcpu->arch.gmap, start, prefix);
- if (end >= prefix)
- gmap_discard(vcpu->arch.gmap,
- prefix + 2 * PAGE_SIZE, end);
+ /*
+ * This is slow path. gmap_discard will check for start
+ * so lets split this into before prefix, prefix, after
+ * prefix and let gmap_discard make some of these calls
+ * NOPs.
+ */
+ gmap_discard(vcpu->arch.gmap, start, prefix);
+ if (start <= prefix)
+ gmap_discard(vcpu->arch.gmap, 0, 4096);
+ if (end > prefix + 4096)
+ gmap_discard(vcpu->arch.gmap, 4096, 8192);
+ gmap_discard(vcpu->arch.gmap, prefix + 2 * PAGE_SIZE, end);
}
return 0;
}