KVM: s390: vsie: store guest addresses of satellite blocks in vsie_page

This way, the values cannot change, even if another VCPU might try to
mess with the nested SCB currently getting executed by another VCPU.

We now always use the same gpa for pinning and unpinning a page (for
unpinning, it is only relevant to mark the guest page dirty for
migration).

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20180116171526.12343-3-david@redhat.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
This commit is contained in:
David Hildenbrand 2018-01-16 18:15:26 +01:00 коммит произвёл Christian Borntraeger
Родитель b3ecd4aa86
Коммит 15e5020e57
1 изменённых файлов: 22 добавлений и 15 удалений

Просмотреть файл

@ -38,7 +38,13 @@ struct vsie_page {
struct gmap *gmap; /* 0x0220 */ struct gmap *gmap; /* 0x0220 */
/* address of the last reported fault to guest2 */ /* address of the last reported fault to guest2 */
unsigned long fault_addr; /* 0x0228 */ unsigned long fault_addr; /* 0x0228 */
__u8 reserved[0x0700 - 0x0230]; /* 0x0230 */ /* calculated guest addresses of satellite control blocks */
gpa_t sca_gpa; /* 0x0230 */
gpa_t itdba_gpa; /* 0x0238 */
gpa_t gvrd_gpa; /* 0x0240 */
gpa_t riccbd_gpa; /* 0x0248 */
gpa_t sdnx_gpa; /* 0x0250 */
__u8 reserved[0x0700 - 0x0258]; /* 0x0258 */
struct kvm_s390_crypto_cb crycb; /* 0x0700 */ struct kvm_s390_crypto_cb crycb; /* 0x0700 */
__u8 fac[S390_ARCH_FAC_LIST_SIZE_BYTE]; /* 0x0800 */ __u8 fac[S390_ARCH_FAC_LIST_SIZE_BYTE]; /* 0x0800 */
}; };
@ -475,46 +481,42 @@ static void unpin_guest_page(struct kvm *kvm, gpa_t gpa, hpa_t hpa)
/* unpin all blocks previously pinned by pin_blocks(), marking them dirty */ /* unpin all blocks previously pinned by pin_blocks(), marking them dirty */
static void unpin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) static void unpin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
{ {
struct kvm_s390_sie_block *scb_o = vsie_page->scb_o;
struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s; struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s;
hpa_t hpa; hpa_t hpa;
gpa_t gpa;
hpa = (u64) scb_s->scaoh << 32 | scb_s->scaol; hpa = (u64) scb_s->scaoh << 32 | scb_s->scaol;
if (hpa) { if (hpa) {
gpa = scb_o->scaol & ~0xfUL; unpin_guest_page(vcpu->kvm, vsie_page->sca_gpa, hpa);
if (test_kvm_cpu_feat(vcpu->kvm, KVM_S390_VM_CPU_FEAT_64BSCAO)) vsie_page->sca_gpa = 0;
gpa |= (u64) scb_o->scaoh << 32;
unpin_guest_page(vcpu->kvm, gpa, hpa);
scb_s->scaol = 0; scb_s->scaol = 0;
scb_s->scaoh = 0; scb_s->scaoh = 0;
} }
hpa = scb_s->itdba; hpa = scb_s->itdba;
if (hpa) { if (hpa) {
gpa = scb_o->itdba & ~0xffUL; unpin_guest_page(vcpu->kvm, vsie_page->itdba_gpa, hpa);
unpin_guest_page(vcpu->kvm, gpa, hpa); vsie_page->itdba_gpa = 0;
scb_s->itdba = 0; scb_s->itdba = 0;
} }
hpa = scb_s->gvrd; hpa = scb_s->gvrd;
if (hpa) { if (hpa) {
gpa = scb_o->gvrd & ~0x1ffUL; unpin_guest_page(vcpu->kvm, vsie_page->gvrd_gpa, hpa);
unpin_guest_page(vcpu->kvm, gpa, hpa); vsie_page->gvrd_gpa = 0;
scb_s->gvrd = 0; scb_s->gvrd = 0;
} }
hpa = scb_s->riccbd; hpa = scb_s->riccbd;
if (hpa) { if (hpa) {
gpa = scb_o->riccbd & ~0x3fUL; unpin_guest_page(vcpu->kvm, vsie_page->riccbd_gpa, hpa);
unpin_guest_page(vcpu->kvm, gpa, hpa); vsie_page->riccbd_gpa = 0;
scb_s->riccbd = 0; scb_s->riccbd = 0;
} }
hpa = scb_s->sdnxo; hpa = scb_s->sdnxo;
if (hpa) { if (hpa) {
gpa = scb_o->sdnxo; unpin_guest_page(vcpu->kvm, vsie_page->sdnx_gpa, hpa);
unpin_guest_page(vcpu->kvm, gpa, hpa); vsie_page->sdnx_gpa = 0;
scb_s->sdnxo = 0; scb_s->sdnxo = 0;
} }
} }
@ -559,6 +561,7 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
} }
if (rc) if (rc)
goto unpin; goto unpin;
vsie_page->sca_gpa = gpa;
scb_s->scaoh = (u32)((u64)hpa >> 32); scb_s->scaoh = (u32)((u64)hpa >> 32);
scb_s->scaol = (u32)(u64)hpa; scb_s->scaol = (u32)(u64)hpa;
} }
@ -575,6 +578,7 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
rc = set_validity_icpt(scb_s, 0x0080U); rc = set_validity_icpt(scb_s, 0x0080U);
goto unpin; goto unpin;
} }
vsie_page->itdba_gpa = gpa;
scb_s->itdba = hpa; scb_s->itdba = hpa;
} }
@ -593,6 +597,7 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
rc = set_validity_icpt(scb_s, 0x1310U); rc = set_validity_icpt(scb_s, 0x1310U);
goto unpin; goto unpin;
} }
vsie_page->gvrd_gpa = gpa;
scb_s->gvrd = hpa; scb_s->gvrd = hpa;
} }
@ -609,6 +614,7 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
goto unpin; goto unpin;
} }
/* Validity 0x0044 will be checked by SIE */ /* Validity 0x0044 will be checked by SIE */
vsie_page->riccbd_gpa = gpa;
scb_s->riccbd = hpa; scb_s->riccbd = hpa;
} }
if ((scb_s->ecb & ECB_GS) && !(scb_s->ecd & ECD_HOSTREGMGMT)) { if ((scb_s->ecb & ECB_GS) && !(scb_s->ecd & ECD_HOSTREGMGMT)) {
@ -636,6 +642,7 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
rc = set_validity_icpt(scb_s, 0x10b0U); rc = set_validity_icpt(scb_s, 0x10b0U);
goto unpin; goto unpin;
} }
vsie_page->sdnx_gpa = gpa;
scb_s->sdnxo = hpa | sdnxc; scb_s->sdnxo = hpa | sdnxc;
} }
return 0; return 0;