On 18.02.20 09:39, Christian Borntraeger wrote: > From: Janosch Frank <frankja@xxxxxxxxxxxxx> > > This contains 3 main changes: > 1. changes in SIE control block handling for secure guests > 2. helper functions for create/destroy/unpack secure guests > 3. KVM_S390_PV_COMMAND ioctl to allow userspace dealing with secure > machines > > Signed-off-by: Janosch Frank <frankja@xxxxxxxxxxxxx> > [borntraeger@xxxxxxxxxx: patch merging, splitting, fixing] > Signed-off-by: Christian Borntraeger <borntraeger@xxxxxxxxxx> > --- > 2->2.1 - combine CREATE/DESTROY CPU/VM into ENABLE DISABLE > - rework locking and check locks with lockdep > - I still have the PV_COMMAND_CPU in here for later use in > the SET_IPL_PSW ioctl. If wanted I can move > - change CAP number > > arch/s390/include/asm/kvm_host.h | 24 ++- > arch/s390/include/asm/uv.h | 69 ++++++++ > arch/s390/kvm/Makefile | 2 +- > arch/s390/kvm/kvm-s390.c | 231 ++++++++++++++++++++++++++- > arch/s390/kvm/kvm-s390.h | 35 +++++ > arch/s390/kvm/pv.c | 262 +++++++++++++++++++++++++++++++ > include/uapi/linux/kvm.h | 35 +++++ > 7 files changed, 654 insertions(+), 4 deletions(-) > create mode 100644 arch/s390/kvm/pv.c > > diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h > index d058289385a5..1aa2382fe363 100644 > --- a/arch/s390/include/asm/kvm_host.h > +++ b/arch/s390/include/asm/kvm_host.h > @@ -160,7 +160,13 @@ struct kvm_s390_sie_block { > __u8 reserved08[4]; /* 0x0008 */ > #define PROG_IN_SIE (1<<0) > __u32 prog0c; /* 0x000c */ > - __u8 reserved10[16]; /* 0x0010 */ > + union { > + __u8 reserved10[16]; /* 0x0010 */ > + struct { > + __u64 pv_handle_cpu; > + __u64 pv_handle_config; > + }; > + }; > #define PROG_BLOCK_SIE (1<<0) > #define PROG_REQUEST (1<<1) > atomic_t prog20; /* 0x0020 */ > @@ -233,7 +239,7 @@ struct kvm_s390_sie_block { > #define ECB3_RI 0x01 > __u8 ecb3; /* 0x0063 */ > __u32 scaol; /* 0x0064 */ > - __u8 reserved68; /* 0x0068 */ > + __u8 sdf; /* 0x0068 */ > __u8 epdx; /* 0x0069 */ > __u8 reserved6a[2]; /* 0x006a */ > __u32 todpr; /* 0x006c */ > @@ -645,6 +651,11 @@ struct kvm_guestdbg_info_arch { > unsigned long last_bp; > }; > > +struct kvm_s390_pv_vcpu { > + u64 handle; > + unsigned long stor_base; > +}; > + > struct kvm_vcpu_arch { > struct kvm_s390_sie_block *sie_block; > /* if vsie is active, currently executed shadow sie control block */ > @@ -673,6 +684,7 @@ struct kvm_vcpu_arch { > __u64 cputm_start; > bool gs_enabled; > bool skey_enabled; > + struct kvm_s390_pv_vcpu pv; > }; > > struct kvm_vm_stat { > @@ -843,6 +855,13 @@ struct kvm_s390_gisa_interrupt { > DECLARE_BITMAP(kicked_mask, KVM_MAX_VCPUS); > }; > > +struct kvm_s390_pv { > + u64 handle; > + u64 guest_len; > + unsigned long stor_base; > + void *stor_var; > +}; > + > struct kvm_arch{ > void *sca; > int use_esca; > @@ -878,6 +897,7 @@ struct kvm_arch{ > DECLARE_BITMAP(cpu_feat, KVM_S390_VM_CPU_FEAT_NR_BITS); > DECLARE_BITMAP(idle_mask, KVM_MAX_VCPUS); > struct kvm_s390_gisa_interrupt gisa_int; > + struct kvm_s390_pv pv; > }; > > #define KVM_HVA_ERR_BAD (-1UL) > diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h > index bc452a15ac3f..839cb3a89986 100644 > --- a/arch/s390/include/asm/uv.h > +++ b/arch/s390/include/asm/uv.h > @@ -23,11 +23,19 @@ > #define UVC_RC_INV_STATE 0x0003 > #define UVC_RC_INV_LEN 0x0005 > #define UVC_RC_NO_RESUME 0x0007 > +#define UVC_RC_NEED_DESTROY 0x8000 > > #define UVC_CMD_QUI 0x0001 > #define UVC_CMD_INIT_UV 0x000f > +#define UVC_CMD_CREATE_SEC_CONF 0x0100 > +#define UVC_CMD_DESTROY_SEC_CONF 0x0101 > +#define UVC_CMD_CREATE_SEC_CPU 0x0120 > +#define UVC_CMD_DESTROY_SEC_CPU 0x0121 > #define UVC_CMD_CONV_TO_SEC_STOR 0x0200 > #define UVC_CMD_CONV_FROM_SEC_STOR 0x0201 > +#define UVC_CMD_SET_SEC_CONF_PARAMS 0x0300 > +#define UVC_CMD_UNPACK_IMG 0x0301 > +#define UVC_CMD_VERIFY_IMG 0x0302 > #define UVC_CMD_PIN_PAGE_SHARED 0x0341 > #define UVC_CMD_UNPIN_PAGE_SHARED 0x0342 > #define UVC_CMD_SET_SHARED_ACCESS 0x1000 > @@ -37,10 +45,17 @@ > enum uv_cmds_inst { > BIT_UVC_CMD_QUI = 0, > BIT_UVC_CMD_INIT_UV = 1, > + BIT_UVC_CMD_CREATE_SEC_CONF = 2, > + BIT_UVC_CMD_DESTROY_SEC_CONF = 3, > + BIT_UVC_CMD_CREATE_SEC_CPU = 4, > + BIT_UVC_CMD_DESTROY_SEC_CPU = 5, > BIT_UVC_CMD_CONV_TO_SEC_STOR = 6, > BIT_UVC_CMD_CONV_FROM_SEC_STOR = 7, > BIT_UVC_CMD_SET_SHARED_ACCESS = 8, > BIT_UVC_CMD_REMOVE_SHARED_ACCESS = 9, > + BIT_UVC_CMD_SET_SEC_PARMS = 11, > + BIT_UVC_CMD_UNPACK_IMG = 13, > + BIT_UVC_CMD_VERIFY_IMG = 14, > BIT_UVC_CMD_PIN_PAGE_SHARED = 21, > BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22, > }; > @@ -52,6 +67,7 @@ struct uv_cb_header { > u16 rrc; /* Return Reason Code */ > } __packed __aligned(8); > > +/* Query Ultravisor Information */ > struct uv_cb_qui { > struct uv_cb_header header; > u64 reserved08; > @@ -71,6 +87,7 @@ struct uv_cb_qui { > u64 reserveda0; > } __packed __aligned(8); > > +/* Initialize Ultravisor */ > struct uv_cb_init { > struct uv_cb_header header; > u64 reserved08[2]; > @@ -79,6 +96,35 @@ struct uv_cb_init { > u64 reserved28[4]; > } __packed __aligned(8); > > +/* Create Guest Configuration */ > +struct uv_cb_cgc { > + struct uv_cb_header header; > + u64 reserved08[2]; > + u64 guest_handle; > + u64 conf_base_stor_origin; > + u64 conf_virt_stor_origin; > + u64 reserved30; > + u64 guest_stor_origin; > + u64 guest_stor_len; > + u64 guest_sca; > + u64 guest_asce; > + u64 reserved58[5]; > +} __packed __aligned(8); > + > +/* Create Secure CPU */ > +struct uv_cb_csc { > + struct uv_cb_header header; > + u64 reserved08[2]; > + u64 cpu_handle; > + u64 guest_handle; > + u64 stor_origin; > + u8 reserved30[6]; > + u16 num; > + u64 state_origin; > + u64 reserved40[4]; > +} __packed __aligned(8); > + > +/* Convert to Secure */ > struct uv_cb_cts { > struct uv_cb_header header; > u64 reserved08[2]; > @@ -86,12 +132,34 @@ struct uv_cb_cts { > u64 gaddr; > } __packed __aligned(8); > > +/* Convert from Secure / Pin Page Shared */ > struct uv_cb_cfs { > struct uv_cb_header header; > u64 reserved08[2]; > u64 paddr; > } __packed __aligned(8); > > +/* Set Secure Config Parameter */ > +struct uv_cb_ssc { > + struct uv_cb_header header; > + u64 reserved08[2]; > + u64 guest_handle; > + u64 sec_header_origin; > + u32 sec_header_len; > + u32 reserved2c; > + u64 reserved30[4]; > +} __packed __aligned(8); > + > +/* Unpack */ > +struct uv_cb_unp { > + struct uv_cb_header header; > + u64 reserved08[2]; > + u64 guest_handle; > + u64 gaddr; > + u64 tweak[2]; > + u64 reserved38[3]; > +} __packed __aligned(8); > + > /* > * A common UV call struct for calls that take no payload > * Examples: > @@ -105,6 +173,7 @@ struct uv_cb_nodata { > u64 reserved20[4]; > } __packed __aligned(8); > > +/* Set Shared Access */ > struct uv_cb_share { > struct uv_cb_header header; > u64 reserved08[3]; > diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile > index 05ee90a5ea08..12decca22e7c 100644 > --- a/arch/s390/kvm/Makefile > +++ b/arch/s390/kvm/Makefile > @@ -9,6 +9,6 @@ common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o $(KVM)/irqch > ccflags-y := -Ivirt/kvm -Iarch/s390/kvm > > kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o > -kvm-objs += diag.o gaccess.o guestdbg.o vsie.o > +kvm-objs += diag.o gaccess.o guestdbg.o vsie.o pv.o > > obj-$(CONFIG_KVM) += kvm.o > diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c > index cc7793525a69..1a7bb08f5c26 100644 > --- a/arch/s390/kvm/kvm-s390.c > +++ b/arch/s390/kvm/kvm-s390.c > @@ -44,6 +44,7 @@ > #include <asm/cpacf.h> > #include <asm/timex.h> > #include <asm/ap.h> > +#include <asm/uv.h> > #include "kvm-s390.h" > #include "gaccess.h" > > @@ -234,8 +235,10 @@ int kvm_arch_check_processor_compat(void) > return 0; > } > > +/* forward declarations */ > static void kvm_gmap_notifier(struct gmap *gmap, unsigned long start, > unsigned long end); > +static int sca_switch_to_extended(struct kvm *kvm); > > static void kvm_clock_sync_scb(struct kvm_s390_sie_block *scb, u64 delta) > { > @@ -571,6 +574,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) > case KVM_CAP_S390_BPB: > r = test_facility(82); > break; > + case KVM_CAP_S390_PROTECTED: > + r = is_prot_virt_host(); > + break; FWIW, the clean thing to do is to enable the capability only after all features have been implemented, so as the very last patch. -- Thanks, David / dhildenb