Skip to content

Commit 0ee4ddc

Browse files
author
Claudio Imbrenda
committed
KVM: s390: Storage key manipulation IOCTL
Add a new IOCTL to allow userspace to manipulate storage keys directly. This will make it easier to write selftests related to storage keys. Acked-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
1 parent 0fdd5c1 commit 0ee4ddc

3 files changed

Lines changed: 111 additions & 0 deletions

File tree

Documentation/virt/kvm/api.rst

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6517,6 +6517,40 @@ the capability to be present.
65176517

65186518
`flags` must currently be zero.
65196519

6520+
4.144 KVM_S390_KEYOP
6521+
--------------------
6522+
6523+
:Capability: KVM_CAP_S390_KEYOP
6524+
:Architectures: s390
6525+
:Type: vm ioctl
6526+
:Parameters: struct kvm_s390_keyop (in/out)
6527+
:Returns: 0 in case of success, < 0 on error
6528+
6529+
The specified key operation is performed on the given guest address. The
6530+
previous storage key (or the relevant part thereof) will be returned in
6531+
`key`.
6532+
6533+
::
6534+
6535+
struct kvm_s390_keyop {
6536+
__u64 guest_addr;
6537+
__u8 key;
6538+
__u8 operation;
6539+
};
6540+
6541+
Currently supported values for ``operation``:
6542+
6543+
KVM_S390_KEYOP_ISKE
6544+
Returns the storage key for the guest address ``guest_addr`` in ``key``.
6545+
6546+
KVM_S390_KEYOP_RRBE
6547+
Resets the reference bit for the guest address ``guest_addr``, returning the
6548+
R and C bits of the old storage key in ``key``; the remaining fields of
6549+
the storage key will be set to 0.
6550+
6551+
KVM_S390_KEYOP_SSKE
6552+
Sets the storage key for the guest address ``guest_addr`` to the key
6553+
specified in ``key``, returning the previous value in ``key``.
65206554

65216555
.. _kvm_run:
65226556

@@ -9287,6 +9321,14 @@ The presence of this capability indicates that KVM_RUN will update the
92879321
KVM_RUN_X86_GUEST_MODE bit in kvm_run.flags to indicate whether the
92889322
vCPU was executing nested guest code when it exited.
92899323

9324+
8.46 KVM_CAP_S390_KEYOP
9325+
-----------------------
9326+
9327+
:Architectures: s390
9328+
9329+
The presence of this capability indicates that the KVM_S390_KEYOP ioctl is
9330+
available.
9331+
92909332
KVM exits with the register state of either the L1 or L2 guest
92919333
depending on which executed at the time of an exit. Userspace must
92929334
take care to differentiate between these cases.

arch/s390/kvm/kvm-s390.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,37 @@ static void __kvm_s390_exit(void)
554554
debug_unregister(kvm_s390_dbf_uv);
555555
}
556556

557+
static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op,
558+
unsigned long addr, union skey skey)
559+
{
560+
union asce asce = kvm->arch.gmap->asce;
561+
gfn_t gfn = gpa_to_gfn(addr);
562+
int r;
563+
564+
guard(read_lock)(&kvm->mmu_lock);
565+
566+
switch (op) {
567+
case KVM_S390_KEYOP_SSKE:
568+
r = dat_cond_set_storage_key(mc, asce, gfn, skey, &skey, 0, 0, 0);
569+
if (r >= 0)
570+
return skey.skey;
571+
break;
572+
case KVM_S390_KEYOP_ISKE:
573+
r = dat_get_storage_key(asce, gfn, &skey);
574+
if (!r)
575+
return skey.skey;
576+
break;
577+
case KVM_S390_KEYOP_RRBE:
578+
r = dat_reset_reference_bit(asce, gfn);
579+
if (r > 0)
580+
return r << 1;
581+
break;
582+
default:
583+
return -EINVAL;
584+
}
585+
return r;
586+
}
587+
557588
/* Section: device related */
558589
long kvm_arch_dev_ioctl(struct file *filp,
559590
unsigned int ioctl, unsigned long arg)
@@ -598,6 +629,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
598629
case KVM_CAP_S390_DIAG318:
599630
case KVM_CAP_IRQFD_RESAMPLE:
600631
case KVM_CAP_S390_USER_OPEREXEC:
632+
case KVM_CAP_S390_KEYOP:
601633
r = 1;
602634
break;
603635
case KVM_CAP_SET_GUEST_DEBUG2:
@@ -2931,6 +2963,32 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
29312963
r = -EFAULT;
29322964
break;
29332965
}
2966+
case KVM_S390_KEYOP: {
2967+
struct kvm_s390_mmu_cache *mc;
2968+
struct kvm_s390_keyop kop;
2969+
union skey skey;
2970+
2971+
if (copy_from_user(&kop, argp, sizeof(kop))) {
2972+
r = -EFAULT;
2973+
break;
2974+
}
2975+
skey.skey = kop.key;
2976+
2977+
mc = kvm_s390_new_mmu_cache();
2978+
if (!mc)
2979+
return -ENOMEM;
2980+
2981+
r = kvm_s390_keyop(mc, kvm, kop.operation, kop.guest_addr, skey);
2982+
kvm_s390_free_mmu_cache(mc);
2983+
if (r < 0)
2984+
break;
2985+
2986+
kop.key = r;
2987+
r = 0;
2988+
if (copy_to_user(argp, &kop, sizeof(kop)))
2989+
r = -EFAULT;
2990+
break;
2991+
}
29342992
case KVM_S390_ZPCI_OP: {
29352993
struct kvm_s390_zpci_op args;
29362994

include/uapi/linux/kvm.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,7 @@ struct kvm_enable_cap {
974974
#define KVM_CAP_GUEST_MEMFD_FLAGS 244
975975
#define KVM_CAP_ARM_SEA_TO_USER 245
976976
#define KVM_CAP_S390_USER_OPEREXEC 246
977+
#define KVM_CAP_S390_KEYOP 247
977978

978979
struct kvm_irq_routing_irqchip {
979980
__u32 irqchip;
@@ -1219,6 +1220,15 @@ struct kvm_vfio_spapr_tce {
12191220
__s32 tablefd;
12201221
};
12211222

1223+
#define KVM_S390_KEYOP_ISKE 0x01
1224+
#define KVM_S390_KEYOP_RRBE 0x02
1225+
#define KVM_S390_KEYOP_SSKE 0x03
1226+
struct kvm_s390_keyop {
1227+
__u64 guest_addr;
1228+
__u8 key;
1229+
__u8 operation;
1230+
};
1231+
12221232
/*
12231233
* KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns
12241234
* a vcpu fd.
@@ -1238,6 +1248,7 @@ struct kvm_vfio_spapr_tce {
12381248
#define KVM_S390_UCAS_MAP _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping)
12391249
#define KVM_S390_UCAS_UNMAP _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping)
12401250
#define KVM_S390_VCPU_FAULT _IOW(KVMIO, 0x52, unsigned long)
1251+
#define KVM_S390_KEYOP _IOWR(KVMIO, 0x53, struct kvm_s390_keyop)
12411252

12421253
/* Device model IOC */
12431254
#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)

0 commit comments

Comments
 (0)