[PATCH v2 02/20] KVM: s390: vsie: Move SCAO validation into a function
Christoph Schlameuss <[email protected]>
| Newsgroups | org.kernel.vger.linux-s390,org.kernel.vger.kvm |
|---|---|
| Message-ID | <[email protected]> |
Improve readability as well as allow re-use in coming patches. In particular add the logic to be able to check the validity of BSCA and ESCA origin addresses. Signed-off-by: Christoph Schlameuss <[email protected]> --- arch/s390/kvm/vsie.c | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c index 010327a6ebee..6aa44362033c 100644 --- a/arch/s390/kvm/vsie.c +++ b/arch/s390/kvm/vsie.c @@ -71,6 +71,11 @@ static_assert(sizeof(struct vsie_page) == PAGE_SIZE); static_assert(offsetof(struct vsie_page, mcck_info) == offsetof(struct sie_page, mcck_info)); static_assert(IS_ALIGNED(offsetof(struct vsie_page, crycb), 8)); +static inline bool sie_uses_esca(struct kvm_s390_sie_block *scb) +{ + return (scb->ecb2 & ECB2_ESCA); +} + static unsigned long read_scao(struct kvm *kvm, struct kvm_s390_sie_block *scb) { unsigned long vsie_sca = READ_ONCE(scb->scaol) & ~0xfUL; @@ -97,6 +102,25 @@ static int set_validity_icpt(struct kvm_s390_sie_block *scb, return 1; } +/* The sca header must not cross pages etc. */ +static int validate_scao(struct kvm_vcpu *vcpu, struct kvm_s390_sie_block *scb, gpa_t gpa) +{ + int offset; + + if (gpa < 2 * PAGE_SIZE) + return set_validity_icpt(scb, 0x0038U); + if ((gpa & ~0x1fffUL) == kvm_s390_get_prefix(vcpu)) + return set_validity_icpt(scb, 0x0011U); + + if (sie_uses_esca(scb)) + offset = offsetof(struct esca_block, cpu[0]) - 1; + else + offset = offsetof(struct bsca_block, cpu[0]) - 1; + if ((gpa & PAGE_MASK) != ((gpa + offset) & PAGE_MASK)) + return set_validity_icpt(scb, 0x003bU); + return 0; +} + /* mark the prefix as unmapped, this will block the VSIE */ static void prefix_unmapped(struct vsie_page *vsie_page) { @@ -787,20 +811,14 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) gpa = read_scao(vcpu->kvm, scb_o); if (gpa) { - if (gpa < 2 * PAGE_SIZE) - rc = set_validity_icpt(scb_s, 0x0038U); - else if ((gpa & ~0x1fffUL) == kvm_s390_get_prefix(vcpu)) - rc = set_validity_icpt(scb_s, 0x0011U); - else if ((gpa & PAGE_MASK) != - ((gpa + offsetof(struct bsca_block, cpu[0]) - 1) & PAGE_MASK)) - rc = set_validity_icpt(scb_s, 0x003bU); - if (!rc) { - rc = pin_guest_page(vcpu->kvm, gpa, &hpa); - if (rc) - rc = set_validity_icpt(scb_s, 0x0034U); - } + rc = validate_scao(vcpu, scb_s, gpa); if (rc) goto unpin; + rc = pin_guest_page(vcpu->kvm, gpa, &hpa); + if (rc) { + rc = set_validity_icpt(scb_s, 0x0034U); + goto unpin; + } vsie_page->sca_gpa = gpa; write_scao(scb_s, hpa); } -- 2.55.0