Message ID | 20220118095210.1651483-7-scgl@linux.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: s390: Do storage key checking | expand |
On 18/01/2022 10.52, Janis Schoetterl-Glausch wrote: > Channel I/O honors storage keys and is performed on absolute memory. > For I/O emulation user space therefore needs to be able to do key > checked accesses. Can't we do the checking in userspace? We already have functions for handling the storage keys there (see hw/s390x/s390-skeys-kvm.c), so why can't we do the checking in QEMU? Thomas
Am 19.01.22 um 12:52 schrieb Thomas Huth: > On 18/01/2022 10.52, Janis Schoetterl-Glausch wrote: >> Channel I/O honors storage keys and is performed on absolute memory. >> For I/O emulation user space therefore needs to be able to do key >> checked accesses. > > Can't we do the checking in userspace? We already have functions for handling the storage keys there (see hw/s390x/s390-skeys-kvm.c), so why can't we do the checking in QEMU? That would separate the key check from the memory operation. Potentially for a long time. Wenn we piggy back on access_guest_abs_with_key we use mvcos in the host and thus do the key check in lockstep with the keycheck which is the preferrable solution. I would also like to avoid reading guest storage keys via the ioctl that was done for migration in the I/O path just to do a single key check. This has peformance concerns.
On 19/01/2022 13.46, Christian Borntraeger wrote: > > > Am 19.01.22 um 12:52 schrieb Thomas Huth: >> On 18/01/2022 10.52, Janis Schoetterl-Glausch wrote: >>> Channel I/O honors storage keys and is performed on absolute memory. >>> For I/O emulation user space therefore needs to be able to do key >>> checked accesses. >> >> Can't we do the checking in userspace? We already have functions for >> handling the storage keys there (see hw/s390x/s390-skeys-kvm.c), so why >> can't we do the checking in QEMU? > > That would separate the key check from the memory operation. Potentially for > a long time. > Wenn we piggy back on access_guest_abs_with_key we use mvcos in the host and > thus do the key check in lockstep with the keycheck which is the preferrable > solution. Ok, makes sense - Janis, could you please add this rationale to the patch description? Thomas
On 1/19/22 13:53, Thomas Huth wrote: > On 19/01/2022 13.46, Christian Borntraeger wrote: >> >> >> Am 19.01.22 um 12:52 schrieb Thomas Huth: >>> On 18/01/2022 10.52, Janis Schoetterl-Glausch wrote: >>>> Channel I/O honors storage keys and is performed on absolute memory. >>>> For I/O emulation user space therefore needs to be able to do key >>>> checked accesses. >>> >>> Can't we do the checking in userspace? We already have functions for handling the storage keys there (see hw/s390x/s390-skeys-kvm.c), so why can't we do the checking in QEMU? >> >> That would separate the key check from the memory operation. Potentially for a long time. >> Wenn we piggy back on access_guest_abs_with_key we use mvcos in the host and thus do the key check in lockstep with the keycheck which is the preferrable solution. > > Ok, makes sense - Janis, could you please add this rationale to the patch description? Will do. > > Thomas >
On 18/01/2022 10.52, Janis Schoetterl-Glausch wrote: > Channel I/O honors storage keys and is performed on absolute memory. > For I/O emulation user space therefore needs to be able to do key > checked accesses. > The vm IOCTL supports read/write accesses, as well as checking > if an access would succeed. ... > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h > index e3f450b2f346..dd04170287fd 100644 > --- a/include/uapi/linux/kvm.h > +++ b/include/uapi/linux/kvm.h > @@ -572,6 +572,8 @@ struct kvm_s390_mem_op { > #define KVM_S390_MEMOP_LOGICAL_WRITE 1 > #define KVM_S390_MEMOP_SIDA_READ 2 > #define KVM_S390_MEMOP_SIDA_WRITE 3 > +#define KVM_S390_MEMOP_ABSOLUTE_READ 4 > +#define KVM_S390_MEMOP_ABSOLUTE_WRITE 5 Not quite sure about this - maybe it is, but at least I'd like to see this discussed: Do we really want to re-use the same ioctl layout for both, the VM and the VCPU file handles? Where the userspace developer has to know that the *_ABSOLUTE_* ops only work with VM handles, and the others only work with the VCPU handles? A CPU can also address absolute memory, so why not adding the *_ABSOLUTE_* ops there, too? And if we'd do that, wouldn't it be sufficient to have the VCPU ioctls only - or do you want to call these ioctls from spots in QEMU where you do not have a VCPU handle available? (I/O instructions are triggered from a CPU, so I'd assume that you should have a VCPU handle around?) Thomas
Am 20.01.22 um 11:38 schrieb Thomas Huth: > On 18/01/2022 10.52, Janis Schoetterl-Glausch wrote: >> Channel I/O honors storage keys and is performed on absolute memory. >> For I/O emulation user space therefore needs to be able to do key >> checked accesses. >> The vm IOCTL supports read/write accesses, as well as checking >> if an access would succeed. > ... >> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h >> index e3f450b2f346..dd04170287fd 100644 >> --- a/include/uapi/linux/kvm.h >> +++ b/include/uapi/linux/kvm.h >> @@ -572,6 +572,8 @@ struct kvm_s390_mem_op { >> #define KVM_S390_MEMOP_LOGICAL_WRITE 1 >> #define KVM_S390_MEMOP_SIDA_READ 2 >> #define KVM_S390_MEMOP_SIDA_WRITE 3 >> +#define KVM_S390_MEMOP_ABSOLUTE_READ 4 >> +#define KVM_S390_MEMOP_ABSOLUTE_WRITE 5 > > Not quite sure about this - maybe it is, but at least I'd like to see this discussed: Do we really want to re-use the same ioctl layout for both, the VM and the VCPU file handles? Where the userspace developer has to know that the *_ABSOLUTE_* ops only work with VM handles, and the others only work with the VCPU handles? A CPU can also address absolute memory, so why not adding the *_ABSOLUTE_* ops there, too? And if we'd do that, wouldn't it be sufficient to have the VCPU ioctls only - or do you want to call these ioctls from spots in QEMU where you do not have a VCPU handle available? (I/O instructions are triggered from a CPU, so I'd assume that you should have a VCPU handle around?) I paritally agree. the ABSOLUTE calls should also work from a VCPU handle. But you also want to be able to call this from a different thread than the vpcu threads as you do not want to kick a CPU out of the kernel just for that. So it makes sense to have this ioctl also for the VM fd. > > Thomas > >
On 1/20/22 11:38, Thomas Huth wrote: > On 18/01/2022 10.52, Janis Schoetterl-Glausch wrote: >> Channel I/O honors storage keys and is performed on absolute memory. >> For I/O emulation user space therefore needs to be able to do key >> checked accesses. >> The vm IOCTL supports read/write accesses, as well as checking >> if an access would succeed. > ... >> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h >> index e3f450b2f346..dd04170287fd 100644 >> --- a/include/uapi/linux/kvm.h >> +++ b/include/uapi/linux/kvm.h >> @@ -572,6 +572,8 @@ struct kvm_s390_mem_op { >> #define KVM_S390_MEMOP_LOGICAL_WRITE 1 >> #define KVM_S390_MEMOP_SIDA_READ 2 >> #define KVM_S390_MEMOP_SIDA_WRITE 3 >> +#define KVM_S390_MEMOP_ABSOLUTE_READ 4 >> +#define KVM_S390_MEMOP_ABSOLUTE_WRITE 5 > > Not quite sure about this - maybe it is, but at least I'd like to see this discussed: Do we really want to re-use the same ioctl layout for both, the VM and the VCPU file handles? Where the userspace developer has to know that the *_ABSOLUTE_* ops only work with VM handles, and the others only work with the VCPU handles? A CPU can also address absolute memory, so why not adding the *_ABSOLUTE_* ops there, too? And if we'd do that, wouldn't it be sufficient to have the VCPU ioctls only - or do you want to call these ioctls from spots in QEMU where you do not have a VCPU handle available? (I/O instructions are triggered from a CPU, so I'd assume that you should have a VCPU handle around?) There are some differences between the vm and the vcpu memops. No storage or fetch protection overrides apply to IO/vm memops, after all there is no control register to enable them. Additionally, quiescing is not required for IO, tho in practice we use the same code path for the vcpu and the vm here. Allowing absolute accesses with a vcpu is doable, but I'm not sure what the use case for it would be, I'm not aware of a precedence in the architecture. Of course the vcpu memop already supports logical=real accesses. > > Thomas > >
On 20/01/2022 13.23, Janis Schoetterl-Glausch wrote: > On 1/20/22 11:38, Thomas Huth wrote: >> On 18/01/2022 10.52, Janis Schoetterl-Glausch wrote: >>> Channel I/O honors storage keys and is performed on absolute memory. >>> For I/O emulation user space therefore needs to be able to do key >>> checked accesses. >>> The vm IOCTL supports read/write accesses, as well as checking >>> if an access would succeed. >> ... >>> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h >>> index e3f450b2f346..dd04170287fd 100644 >>> --- a/include/uapi/linux/kvm.h >>> +++ b/include/uapi/linux/kvm.h >>> @@ -572,6 +572,8 @@ struct kvm_s390_mem_op { >>> #define KVM_S390_MEMOP_LOGICAL_WRITE 1 >>> #define KVM_S390_MEMOP_SIDA_READ 2 >>> #define KVM_S390_MEMOP_SIDA_WRITE 3 >>> +#define KVM_S390_MEMOP_ABSOLUTE_READ 4 >>> +#define KVM_S390_MEMOP_ABSOLUTE_WRITE 5 >> >> Not quite sure about this - maybe it is, but at least I'd like to see this discussed: Do we really want to re-use the same ioctl layout for both, the VM and the VCPU file handles? Where the userspace developer has to know that the *_ABSOLUTE_* ops only work with VM handles, and the others only work with the VCPU handles? A CPU can also address absolute memory, so why not adding the *_ABSOLUTE_* ops there, too? And if we'd do that, wouldn't it be sufficient to have the VCPU ioctls only - or do you want to call these ioctls from spots in QEMU where you do not have a VCPU handle available? (I/O instructions are triggered from a CPU, so I'd assume that you should have a VCPU handle around?) > > There are some differences between the vm and the vcpu memops. > No storage or fetch protection overrides apply to IO/vm memops, after all there is no control register to enable them. > Additionally, quiescing is not required for IO, tho in practice we use the same code path for the vcpu and the vm here. > Allowing absolute accesses with a vcpu is doable, but I'm not sure what the use case for it would be, I'm not aware of > a precedence in the architecture. Of course the vcpu memop already supports logical=real accesses. Ok. Maybe it then would be better to call new ioctl and the new op defines differently, to avoid confusion? E.g. call it "vmmemop" and use: #define KVM_S390_VMMEMOP_ABSOLUTE_READ 1 #define KVM_S390_VMMEMOP_ABSOLUTE_WRITE 2 ? Thomas
On 1/25/22 13:00, Thomas Huth wrote: > On 20/01/2022 13.23, Janis Schoetterl-Glausch wrote: >> On 1/20/22 11:38, Thomas Huth wrote: >>> On 18/01/2022 10.52, Janis Schoetterl-Glausch wrote: >>>> Channel I/O honors storage keys and is performed on absolute memory. >>>> For I/O emulation user space therefore needs to be able to do key >>>> checked accesses. >>>> The vm IOCTL supports read/write accesses, as well as checking >>>> if an access would succeed. >>> ... >>>> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h >>>> index e3f450b2f346..dd04170287fd 100644 >>>> --- a/include/uapi/linux/kvm.h >>>> +++ b/include/uapi/linux/kvm.h >>>> @@ -572,6 +572,8 @@ struct kvm_s390_mem_op { >>>> #define KVM_S390_MEMOP_LOGICAL_WRITE 1 >>>> #define KVM_S390_MEMOP_SIDA_READ 2 >>>> #define KVM_S390_MEMOP_SIDA_WRITE 3 >>>> +#define KVM_S390_MEMOP_ABSOLUTE_READ 4 >>>> +#define KVM_S390_MEMOP_ABSOLUTE_WRITE 5 >>> >>> Not quite sure about this - maybe it is, but at least I'd like to see this discussed: Do we really want to re-use the same ioctl layout for both, the VM and the VCPU file handles? Where the userspace developer has to know that the *_ABSOLUTE_* ops only work with VM handles, and the others only work with the VCPU handles? A CPU can also address absolute memory, so why not adding the *_ABSOLUTE_* ops there, too? And if we'd do that, wouldn't it be sufficient to have the VCPU ioctls only - or do you want to call these ioctls from spots in QEMU where you do not have a VCPU handle available? (I/O instructions are triggered from a CPU, so I'd assume that you should have a VCPU handle around?) >> >> There are some differences between the vm and the vcpu memops. >> No storage or fetch protection overrides apply to IO/vm memops, after all there is no control register to enable them. >> Additionally, quiescing is not required for IO, tho in practice we use the same code path for the vcpu and the vm here. >> Allowing absolute accesses with a vcpu is doable, but I'm not sure what the use case for it would be, I'm not aware of >> a precedence in the architecture. Of course the vcpu memop already supports logical=real accesses. > > Ok. Maybe it then would be better to call new ioctl and the new op defines differently, to avoid confusion? E.g. call it "vmmemop" and use: > > #define KVM_S390_VMMEMOP_ABSOLUTE_READ 1 > #define KVM_S390_VMMEMOP_ABSOLUTE_WRITE 2 > > ? > > Thomas > Thanks for the suggestion, I had to think about it for a while :). Here are my thoughts: The ioctl type (vm/vcpu) and the operations cannot be completely orthogonal (vm + logical cannot work), but with regards to the absolute operations they could be. We don't have a use case for that right now and the semantics are a bit unclear, so I think we should choose a design now that leaves us space for future extension. If we need to, we can add a NON_QUIESCING flag backwards compatibly (tho it seems a rather unlikely requirement to me), that would behave the same for vm/vcpu memops. We could also have a NO_PROT_OVERRIDE flag, which the vm memop would ignore. Whether override is possible is dependent on the vcpu state, so user space leaves the exact behavior to KVM anyway. If you wanted to enforce that protection override occurs, you would have to adjust the vcpu state and therefore there should be no confusion about whether to use a vcpu or vm ioctl. So I'm inclined to have one ioctl code and keep the operations as they are. I moved the key to the union. One question that remains is whether to enforce that reserved bytes must be 0. In general I think that it is a good idea, since it leaves a bigger design space for future extensions. However the vcpu memop has not done that. I think it should be enforced for new functionality (operations, flags), any objections? I'll try to be thorough in documenting the currently supported behavior.
On Thu, 27 Jan 2022 17:29:44 +0100 Janis Schoetterl-Glausch <scgl@linux.ibm.com> wrote: > On 1/25/22 13:00, Thomas Huth wrote: > > On 20/01/2022 13.23, Janis Schoetterl-Glausch wrote: > >> On 1/20/22 11:38, Thomas Huth wrote: > >>> On 18/01/2022 10.52, Janis Schoetterl-Glausch wrote: > >>>> Channel I/O honors storage keys and is performed on absolute memory. > >>>> For I/O emulation user space therefore needs to be able to do key > >>>> checked accesses. > >>>> The vm IOCTL supports read/write accesses, as well as checking > >>>> if an access would succeed. > >>> ... > >>>> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h > >>>> index e3f450b2f346..dd04170287fd 100644 > >>>> --- a/include/uapi/linux/kvm.h > >>>> +++ b/include/uapi/linux/kvm.h > >>>> @@ -572,6 +572,8 @@ struct kvm_s390_mem_op { > >>>> #define KVM_S390_MEMOP_LOGICAL_WRITE 1 > >>>> #define KVM_S390_MEMOP_SIDA_READ 2 > >>>> #define KVM_S390_MEMOP_SIDA_WRITE 3 > >>>> +#define KVM_S390_MEMOP_ABSOLUTE_READ 4 > >>>> +#define KVM_S390_MEMOP_ABSOLUTE_WRITE 5 > >>> > >>> Not quite sure about this - maybe it is, but at least I'd like to see this discussed: Do we really want to re-use the same ioctl layout for both, the VM and the VCPU file handles? Where the userspace developer has to know that the *_ABSOLUTE_* ops only work with VM handles, and the others only work with the VCPU handles? A CPU can also address absolute memory, so why not adding the *_ABSOLUTE_* ops there, too? And if we'd do that, wouldn't it be sufficient to have the VCPU ioctls only - or do you want to call these ioctls from spots in QEMU where you do not have a VCPU handle available? (I/O instructions are triggered from a CPU, so I'd assume that you should have a VCPU handle around?) > >> > >> There are some differences between the vm and the vcpu memops. > >> No storage or fetch protection overrides apply to IO/vm memops, after all there is no control register to enable them. > >> Additionally, quiescing is not required for IO, tho in practice we use the same code path for the vcpu and the vm here. > >> Allowing absolute accesses with a vcpu is doable, but I'm not sure what the use case for it would be, I'm not aware of > >> a precedence in the architecture. Of course the vcpu memop already supports logical=real accesses. > > > > Ok. Maybe it then would be better to call new ioctl and the new op defines differently, to avoid confusion? E.g. call it "vmmemop" and use: > > > > #define KVM_S390_VMMEMOP_ABSOLUTE_READ 1 > > #define KVM_S390_VMMEMOP_ABSOLUTE_WRITE 2 > > > > ? > > > > Thomas > > > > Thanks for the suggestion, I had to think about it for a while :). Here are my thoughts: > The ioctl type (vm/vcpu) and the operations cannot be completely orthogonal (vm + logical cannot work), > but with regards to the absolute operations they could be. We don't have a use case for that > right now and the semantics are a bit unclear, so I think we should choose a design now that > leaves us space for future extension. If we need to, we can add a NON_QUIESCING flag backwards compatibly > (tho it seems a rather unlikely requirement to me), that would behave the same for vm/vcpu memops. > We could also have a NO_PROT_OVERRIDE flag, which the vm memop would ignore. > Whether override is possible is dependent on the vcpu state, so user space leaves the exact behavior to KVM anyway. > If you wanted to enforce that protection override occurs, you would have to adjust > the vcpu state and therefore there should be no confusion about whether to use a vcpu or vm ioctl. > > So I'm inclined to have one ioctl code and keep the operations as they are. > I moved the key to the union. One question that remains is whether to enforce that reserved bytes must be 0. > In general I think that it is a good idea, since it leaves a bigger design space for future extensions. > However the vcpu memop has not done that. I think it should be enforced for new functionality (operations, flags), I agree with enforcing that unused bits should be 0 > any objections? > > I'll try to be thorough in documenting the currently supported behavior. this is also a good idea :)
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index efe33cda38b6..db1d9a494f77 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c @@ -795,6 +795,35 @@ static int low_address_protection_enabled(struct kvm_vcpu *vcpu, return 1; } +static int vm_check_access_key(struct kvm *kvm, char access_key, + enum gacc_mode mode, gpa_t gpa) +{ + unsigned long hva; + unsigned char storage_key, access_control; + bool fetch_protected; + int r; + + if (access_key == 0) + return 0; + + hva = gfn_to_hva(kvm, gpa_to_gfn(gpa)); + if (kvm_is_error_hva(hva)) + return PGM_ADDRESSING; + + mmap_read_lock(current->mm); + r = get_guest_storage_key(current->mm, hva, &storage_key); + mmap_read_unlock(current->mm); + if (r) + return r; + access_control = FIELD_GET(_PAGE_ACC_BITS, storage_key); + if (access_control == access_key) + return 0; + fetch_protected = storage_key & _PAGE_FP_BIT; + if ((mode == GACC_FETCH || mode == GACC_IFETCH) && !fetch_protected) + return 0; + return PGM_PROTECTION; +} + static bool fetch_prot_override_applicable(struct kvm_vcpu *vcpu, enum gacc_mode mode, union asce asce) { @@ -990,6 +1019,26 @@ access_guest_page_with_key(struct kvm *kvm, enum gacc_mode mode, gpa_t gpa, return 0; } +int access_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, void *data, + unsigned long len, enum gacc_mode mode, char key) +{ + int offset = offset_in_page(gpa); + int fragment_len; + int rc; + + while (min(PAGE_SIZE - offset, len) > 0) { + fragment_len = min(PAGE_SIZE - offset, len); + rc = access_guest_page_with_key(kvm, mode, gpa, data, fragment_len, key); + if (rc) + return rc; + offset = 0; + len -= fragment_len; + data += fragment_len; + gpa += fragment_len; + } + return 0; +} + int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data, unsigned long len, enum gacc_mode mode, char access_key) @@ -1131,6 +1180,29 @@ int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, return rc; } +/** + * check_gpa_range - test a range of guest physical addresses for accessibility + * @kvm: virtual machine instance + * @gpa: guest physical address + * @length: length of test range + * @mode: access mode to test, relevant for storage keys + * @access_key: access key to mach the storage keys with + */ +int check_gpa_range(struct kvm *kvm, unsigned long gpa, unsigned long length, + enum gacc_mode mode, char access_key) +{ + unsigned int fragment_len; + int rc = 0; + + while (length && !rc) { + fragment_len = min(PAGE_SIZE - offset_in_page(gpa), length); + rc = vm_check_access_key(kvm, access_key, mode, gpa); + length -= fragment_len; + gpa += fragment_len; + } + return rc; +} + /** * kvm_s390_check_low_addr_prot_real - check for low-address protection * @vcpu: virtual cpu diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h index 0d4416178bb6..d89178b92d51 100644 --- a/arch/s390/kvm/gaccess.h +++ b/arch/s390/kvm/gaccess.h @@ -194,6 +194,12 @@ int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, unsigned long length, enum gacc_mode mode, char access_key); +int check_gpa_range(struct kvm *kvm, unsigned long gpa, unsigned long length, + enum gacc_mode mode, char access_key); + +int access_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, void *data, + unsigned long len, enum gacc_mode mode, char key); + int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data, unsigned long len, enum gacc_mode mode, char access_key); diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index c4acdb025ff1..8dab956f84a6 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -2390,6 +2390,78 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd) return r; } +static int kvm_s390_vm_mem_op(struct kvm *kvm, struct kvm_s390_mem_op *mop) +{ + static const __u8 zeros[sizeof(mop->reserved)] = {0}; + void __user *uaddr = (void __user *)mop->buf; + u64 supported_flags; + void *tmpbuf = NULL; + char access_key; + int r, srcu_idx; + + access_key = FIELD_GET(KVM_S390_MEMOP_F_SKEYS_ACC, mop->flags); + supported_flags = KVM_S390_MEMOP_F_SKEYS_ACC + | KVM_S390_MEMOP_F_CHECK_ONLY; + if (mop->flags & ~supported_flags) + return -EINVAL; + if (mop->size > MEM_OP_MAX_SIZE) + return -E2BIG; + if (kvm_s390_pv_is_protected(kvm)) + return -EINVAL; + if (memcmp(mop->reserved, zeros, sizeof(zeros)) != 0) + return -EINVAL; + + if (!(mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY)) { + tmpbuf = vmalloc(mop->size); + if (!tmpbuf) + return -ENOMEM; + } + + srcu_idx = srcu_read_lock(&kvm->srcu); + + if (kvm_is_error_gpa(kvm, mop->gaddr)) { + r = PGM_ADDRESSING; + goto out_unlock; + } + + switch (mop->op) { + case KVM_S390_MEMOP_ABSOLUTE_READ: { + if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) { + r = check_gpa_range(kvm, mop->gaddr, mop->size, GACC_FETCH, access_key); + } else { + r = access_guest_abs_with_key(kvm, mop->gaddr, tmpbuf, + mop->size, GACC_FETCH, access_key); + if (r == 0) { + if (copy_to_user(uaddr, tmpbuf, mop->size)) + r = -EFAULT; + } + } + break; + } + case KVM_S390_MEMOP_ABSOLUTE_WRITE: { + if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) { + r = check_gpa_range(kvm, mop->gaddr, mop->size, GACC_STORE, access_key); + } else { + if (copy_from_user(tmpbuf, uaddr, mop->size)) { + r = -EFAULT; + break; + } + r = access_guest_abs_with_key(kvm, mop->gaddr, tmpbuf, + mop->size, GACC_STORE, access_key); + } + break; + } + default: + r = -EINVAL; + } + +out_unlock: + srcu_read_unlock(&kvm->srcu, srcu_idx); + + vfree(tmpbuf); + return r; +} + long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { @@ -2514,6 +2586,15 @@ long kvm_arch_vm_ioctl(struct file *filp, } break; } + case KVM_S390_MEM_OP: { + struct kvm_s390_mem_op mem_op; + + if (copy_from_user(&mem_op, argp, sizeof(mem_op)) == 0) + r = kvm_s390_vm_mem_op(kvm, &mem_op); + else + r = -EFAULT; + break; + } default: r = -ENOTTY; } diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index e3f450b2f346..dd04170287fd 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -572,6 +572,8 @@ struct kvm_s390_mem_op { #define KVM_S390_MEMOP_LOGICAL_WRITE 1 #define KVM_S390_MEMOP_SIDA_READ 2 #define KVM_S390_MEMOP_SIDA_WRITE 3 +#define KVM_S390_MEMOP_ABSOLUTE_READ 4 +#define KVM_S390_MEMOP_ABSOLUTE_WRITE 5 /* flags for kvm_s390_mem_op->flags */ #define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0) #define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1)