KVM: s390: vsie: support vectory facility (SIMD)
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>
Wed, 25 Nov 2015 10:08:32 +0000 (11:08 +0100)
committerChristian Borntraeger <borntraeger@de.ibm.com>
Tue, 21 Jun 2016 07:43:38 +0000 (09:43 +0200)
As soon as guest 2 is allowed to use the vector facility (indicated via
STFLE), it can also enable it for guest 3. We have to take care of the
sattellite block that might be used when not relying on lazy vector
copying (not the case for KVM).

Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
arch/s390/include/asm/kvm_host.h
arch/s390/kvm/vsie.c

index 255609c86901139501cb4338dffe9c2a4db73da7..190ad63291fb229e6c0e6b924d94437d3e3ca2d2 100644 (file)
@@ -229,7 +229,7 @@ struct kvm_s390_sie_block {
        __u8    reserved1e6[2];         /* 0x01e6 */
        __u64   itdba;                  /* 0x01e8 */
        __u64   riccbd;                 /* 0x01f0 */
-       __u8    reserved1f8[8];         /* 0x01f8 */
+       __u64   gvrd;                   /* 0x01f8 */
 } __attribute__((packed));
 
 struct kvm_s390_itdb {
index 4e2c71cced4830148214021b05c66c36d35b3822..6d9f4058ce157287fe8383f6d400ada073cf03a4 100644 (file)
@@ -307,6 +307,11 @@ static int shadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
                        prefix_unmapped(vsie_page);
                scb_s->ecb |= scb_o->ecb & 0x10U;
        }
+       /* SIMD */
+       if (test_kvm_facility(vcpu->kvm, 129)) {
+               scb_s->eca |= scb_o->eca & 0x00020000U;
+               scb_s->ecd |= scb_o->ecd & 0x20000000U;
+       }
 
        prepare_ibc(vcpu, vsie_page);
        rc = shadow_crycb(vcpu, vsie_page);
@@ -452,6 +457,13 @@ static void unpin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
                unpin_guest_page(vcpu->kvm, gpa, hpa);
                scb_s->itdba = 0;
        }
+
+       hpa = scb_s->gvrd;
+       if (hpa) {
+               gpa = scb_o->gvrd & ~0x1ffUL;
+               unpin_guest_page(vcpu->kvm, gpa, hpa);
+               scb_s->gvrd = 0;
+       }
 }
 
 /*
@@ -510,6 +522,25 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
                        goto unpin;
                scb_s->itdba = hpa;
        }
+
+       gpa = scb_o->gvrd & ~0x1ffUL;
+       if (gpa && (scb_s->eca & 0x00020000U) &&
+           !(scb_s->ecd & 0x20000000U)) {
+               if (!(gpa & ~0x1fffUL)) {
+                       rc = set_validity_icpt(scb_s, 0x1310U);
+                       goto unpin;
+               }
+               /*
+                * 512 bytes vector registers cannot cross page boundaries
+                * if this block gets bigger, we have to shadow it.
+                */
+               rc = pin_guest_page(vcpu->kvm, gpa, &hpa);
+               if (rc == -EINVAL)
+                       rc = set_validity_icpt(scb_s, 0x1310U);
+               if (rc)
+                       goto unpin;
+               scb_s->gvrd = hpa;
+       }
        return 0;
 unpin:
        unpin_blocks(vcpu, vsie_page);