On 24.10.19 13:40, Janosch Frank wrote: > Let's add a KVM interface to create and destroy protected VMs. > > Signed-off-by: Janosch Frank <frankja@xxxxxxxxxxxxx> > --- > arch/s390/include/asm/kvm_host.h | 24 +++- > arch/s390/include/asm/uv.h | 110 ++++++++++++++ > arch/s390/kvm/Makefile | 2 +- > arch/s390/kvm/kvm-s390.c | 173 +++++++++++++++++++++- > arch/s390/kvm/kvm-s390.h | 47 ++++++ > arch/s390/kvm/pv.c | 237 +++++++++++++++++++++++++++++++ > include/uapi/linux/kvm.h | 33 +++++ > 7 files changed, 622 insertions(+), 4 deletions(-) > create mode 100644 arch/s390/kvm/pv.c [...] > + case KVM_PV_VM_UNPACK: { > + struct kvm_s390_pv_unp unp = {}; > + > + r = -EFAULT; > + if (copy_from_user(&unp, argp, sizeof(unp))) > + break; > + > + r = kvm_s390_pv_unpack(kvm, unp.addr, unp.size, unp.tweak); > + break; > + } [....] > +int kvm_s390_pv_unpack(struct kvm *kvm, unsigned long addr, unsigned long size, > + unsigned long tweak) > +{ > + int i, rc = 0; > + struct uv_cb_unp uvcb = { > + .header.cmd = UVC_CMD_UNPACK_IMG, > + .header.len = sizeof(uvcb), > + .guest_handle = kvm_s390_pv_handle(kvm), > + .tweak[0] = tweak > + }; > + > + if (addr & ~PAGE_MASK || size & ~PAGE_MASK) > + return -EINVAL; > + > + > + VM_EVENT(kvm, 3, "PROTVIRT VM UNPACK: start addr %lx size %lx", > + addr, size); Does it make sense to check for addr and addr+size to be within the memory size of the guest? The uv_call or gmap_fault will fail later on, but we could do an early exit if the the site is wrong. > + for (i = 0; i < size / PAGE_SIZE; i++) { > + uvcb.gaddr = addr + i * PAGE_SIZE; > + uvcb.tweak[1] = i * PAGE_SIZE; > +retry: > + rc = uv_call(0, (u64)&uvcb); > + if (!rc) > + continue; > + /* If not yet mapped fault and retry */ > + if (uvcb.header.rc == 0x10a) { > + rc = gmap_fault(kvm->arch.gmap, uvcb.gaddr, > + FAULT_FLAG_WRITE); > + if (rc) > + return rc; > + goto retry; > + } > + VM_EVENT(kvm, 3, "PROTVIRT VM UNPACK: failed addr %llx rc %x rrc %x", > + uvcb.gaddr, uvcb.header.rc, uvcb.header.rrc); > + break; > + } [...]