To handle vSIE configurations with an ssca we need to pin and unpin multiple consecutive guest-2 pages in guest-1. As these might not be consecutive in guest-1 it is necessary to iterate over all pages and store guest and host addresses for later use. Since the new methods use the existing {,un}pin_guest_page() helpers, they are moved up unchanged in the file to avoid having to resort to forward declarations later on. Signed-off-by: Christoph Schlameuss --- arch/s390/kvm/vsie.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c index 490c29b369cd..442e7997ee51 100644 --- a/arch/s390/kvm/vsie.c +++ b/arch/s390/kvm/vsie.c @@ -72,6 +72,11 @@ struct vsie_page { static_assert(sizeof(struct vsie_page) == PAGE_SIZE); +struct kvm_address_pair { + gpa_t gpa; + hpa_t hpa; +}; + static inline bool sie_uses_esca(struct kvm_s390_sie_block *scb) { return (scb->ecb2 & ECB2_ESCA); @@ -250,6 +255,46 @@ static void unpin_guest_page(struct kvm *kvm, gpa_t gpa, hpa_t hpa) mark_page_dirty(kvm, gpa_to_gfn(gpa)); } +/* unpin multiple guest pages pinned with pin_guest_pages() */ +static void unpin_guest_pages(struct kvm *kvm, struct kvm_address_pair *addr, unsigned int nr_pages) +{ + int i; + + for (i = 0; i < nr_pages; i++) { + unpin_guest_page(kvm, addr[i].gpa, addr[i].hpa); + addr[i].gpa = 0; + addr[i].hpa = 0; + } +} + +/* + * pin nr_pages consecutive guest pages + * + * Returns number of pages pinned or -EFAULT. + */ +static int pin_guest_pages(struct kvm *kvm, gpa_t gpa, unsigned int nr_pages, + struct kvm_address_pair *addr) +{ + hpa_t hpa; + int i, rc; + + gpa = gpa & PAGE_MASK; + + /* the guest pages may not be mapped continuously, so pin each page */ + for (i = 0; i < nr_pages; i++) { + rc = pin_guest_page(kvm, gpa + PAGE_SIZE * i, &hpa); + if (rc) + goto err; + addr[i].gpa = gpa + PAGE_SIZE * i; + addr[i].hpa = hpa; + } + return i; + +err: + unpin_guest_pages(kvm, addr, i); + return -EFAULT; +} + /* copy the updated intervention request bits into the shadow scb */ static void update_intervention_requests(struct vsie_page *vsie_page) { -- 2.55.0