Commit 23a60f83 authored by Collin Walling's avatar Collin Walling Committed by Christian Borntraeger

s390/kvm: diagnose 0x318 sync and reset

DIAGNOSE 0x318 (diag318) sets information regarding the environment
the VM is running in (Linux, z/VM, etc) and is observed via
firmware/service events.

This is a privileged s390x instruction that must be intercepted by
SIE. Userspace handles the instruction as well as migration. Data
is communicated via VCPU register synchronization.

The Control Program Name Code (CPNC) is stored in the SIE block. The
CPNC along with the Control Program Version Code (CPVC) are stored
in the kvm_vcpu_arch struct.

This data is reset on load normal and clear resets.
Signed-off-by: default avatarCollin Walling <walling@linux.ibm.com>
Reviewed-by: default avatarJanosch Frank <frankja@linux.ibm.com>
Acked-by: default avatarCornelia Huck <cohuck@redhat.com>
Reviewed-by: default avatarDavid Hildenbrand <david@redhat.com>
Link: https://lore.kernel.org/r/20200622154636.5499-3-walling@linux.ibm.com
[borntraeger@de.ibm.com: fix sync_reg position]
Signed-off-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
parent a23816f3
...@@ -260,7 +260,8 @@ struct kvm_s390_sie_block { ...@@ -260,7 +260,8 @@ struct kvm_s390_sie_block {
__u32 scaol; /* 0x0064 */ __u32 scaol; /* 0x0064 */
__u8 sdf; /* 0x0068 */ __u8 sdf; /* 0x0068 */
__u8 epdx; /* 0x0069 */ __u8 epdx; /* 0x0069 */
__u8 reserved6a[2]; /* 0x006a */ __u8 cpnc; /* 0x006a */
__u8 reserved6b; /* 0x006b */
__u32 todpr; /* 0x006c */ __u32 todpr; /* 0x006c */
#define GISA_FORMAT1 0x00000001 #define GISA_FORMAT1 0x00000001
__u32 gd; /* 0x0070 */ __u32 gd; /* 0x0070 */
...@@ -745,6 +746,7 @@ struct kvm_vcpu_arch { ...@@ -745,6 +746,7 @@ struct kvm_vcpu_arch {
bool gs_enabled; bool gs_enabled;
bool skey_enabled; bool skey_enabled;
struct kvm_s390_pv_vcpu pv; struct kvm_s390_pv_vcpu pv;
union diag318_info diag318_info;
}; };
struct kvm_vm_stat { struct kvm_vm_stat {
......
...@@ -231,11 +231,13 @@ struct kvm_guest_debug_arch { ...@@ -231,11 +231,13 @@ struct kvm_guest_debug_arch {
#define KVM_SYNC_GSCB (1UL << 9) #define KVM_SYNC_GSCB (1UL << 9)
#define KVM_SYNC_BPBC (1UL << 10) #define KVM_SYNC_BPBC (1UL << 10)
#define KVM_SYNC_ETOKEN (1UL << 11) #define KVM_SYNC_ETOKEN (1UL << 11)
#define KVM_SYNC_DIAG318 (1UL << 12)
#define KVM_SYNC_S390_VALID_FIELDS \ #define KVM_SYNC_S390_VALID_FIELDS \
(KVM_SYNC_PREFIX | KVM_SYNC_GPRS | KVM_SYNC_ACRS | KVM_SYNC_CRS | \ (KVM_SYNC_PREFIX | KVM_SYNC_GPRS | KVM_SYNC_ACRS | KVM_SYNC_CRS | \
KVM_SYNC_ARCH0 | KVM_SYNC_PFAULT | KVM_SYNC_VRS | KVM_SYNC_RICCB | \ KVM_SYNC_ARCH0 | KVM_SYNC_PFAULT | KVM_SYNC_VRS | KVM_SYNC_RICCB | \
KVM_SYNC_FPRS | KVM_SYNC_GSCB | KVM_SYNC_BPBC | KVM_SYNC_ETOKEN) KVM_SYNC_FPRS | KVM_SYNC_GSCB | KVM_SYNC_BPBC | KVM_SYNC_ETOKEN | \
KVM_SYNC_DIAG318)
/* length and alignment of the sdnx as a power of two */ /* length and alignment of the sdnx as a power of two */
#define SDNXC 8 #define SDNXC 8
...@@ -264,7 +266,8 @@ struct kvm_sync_regs { ...@@ -264,7 +266,8 @@ struct kvm_sync_regs {
__u8 reserved2 : 7; __u8 reserved2 : 7;
__u8 padding1[51]; /* riccb needs to be 64byte aligned */ __u8 padding1[51]; /* riccb needs to be 64byte aligned */
__u8 riccb[64]; /* runtime instrumentation controls block */ __u8 riccb[64]; /* runtime instrumentation controls block */
__u8 padding2[192]; /* sdnx needs to be 256byte aligned */ __u64 diag318; /* diagnose 0x318 info */
__u8 padding2[184]; /* sdnx needs to be 256byte aligned */
union { union {
__u8 sdnx[SDNXL]; /* state description annex */ __u8 sdnx[SDNXL]; /* state description annex */
struct { struct {
......
...@@ -545,6 +545,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) ...@@ -545,6 +545,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_S390_AIS_MIGRATION: case KVM_CAP_S390_AIS_MIGRATION:
case KVM_CAP_S390_VCPU_RESETS: case KVM_CAP_S390_VCPU_RESETS:
case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_SET_GUEST_DEBUG:
case KVM_CAP_S390_DIAG318:
r = 1; r = 1;
break; break;
case KVM_CAP_S390_HPAGE_1M: case KVM_CAP_S390_HPAGE_1M:
...@@ -3267,7 +3268,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) ...@@ -3267,7 +3268,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
KVM_SYNC_ACRS | KVM_SYNC_ACRS |
KVM_SYNC_CRS | KVM_SYNC_CRS |
KVM_SYNC_ARCH0 | KVM_SYNC_ARCH0 |
KVM_SYNC_PFAULT; KVM_SYNC_PFAULT |
KVM_SYNC_DIAG318;
kvm_s390_set_prefix(vcpu, 0); kvm_s390_set_prefix(vcpu, 0);
if (test_kvm_facility(vcpu->kvm, 64)) if (test_kvm_facility(vcpu->kvm, 64))
vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB; vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB;
...@@ -3562,6 +3564,7 @@ static void kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu) ...@@ -3562,6 +3564,7 @@ static void kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
vcpu->arch.sie_block->pp = 0; vcpu->arch.sie_block->pp = 0;
vcpu->arch.sie_block->fpf &= ~FPF_BPBC; vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
vcpu->arch.sie_block->todpr = 0; vcpu->arch.sie_block->todpr = 0;
vcpu->arch.sie_block->cpnc = 0;
} }
} }
...@@ -3579,6 +3582,7 @@ static void kvm_arch_vcpu_ioctl_clear_reset(struct kvm_vcpu *vcpu) ...@@ -3579,6 +3582,7 @@ static void kvm_arch_vcpu_ioctl_clear_reset(struct kvm_vcpu *vcpu)
regs->etoken = 0; regs->etoken = 0;
regs->etoken_extension = 0; regs->etoken_extension = 0;
regs->diag318 = 0;
} }
int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
...@@ -4196,6 +4200,10 @@ static void sync_regs_fmt2(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) ...@@ -4196,6 +4200,10 @@ static void sync_regs_fmt2(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID) if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID)
kvm_clear_async_pf_completion_queue(vcpu); kvm_clear_async_pf_completion_queue(vcpu);
} }
if (kvm_run->kvm_dirty_regs & KVM_SYNC_DIAG318) {
vcpu->arch.diag318_info.val = kvm_run->s.regs.diag318;
vcpu->arch.sie_block->cpnc = vcpu->arch.diag318_info.cpnc;
}
/* /*
* If userspace sets the riccb (e.g. after migration) to a valid state, * If userspace sets the riccb (e.g. after migration) to a valid state,
* we should enable RI here instead of doing the lazy enablement. * we should enable RI here instead of doing the lazy enablement.
...@@ -4297,6 +4305,7 @@ static void store_regs_fmt2(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) ...@@ -4297,6 +4305,7 @@ static void store_regs_fmt2(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
kvm_run->s.regs.pp = vcpu->arch.sie_block->pp; kvm_run->s.regs.pp = vcpu->arch.sie_block->pp;
kvm_run->s.regs.gbea = vcpu->arch.sie_block->gbea; kvm_run->s.regs.gbea = vcpu->arch.sie_block->gbea;
kvm_run->s.regs.bpbc = (vcpu->arch.sie_block->fpf & FPF_BPBC) == FPF_BPBC; kvm_run->s.regs.bpbc = (vcpu->arch.sie_block->fpf & FPF_BPBC) == FPF_BPBC;
kvm_run->s.regs.diag318 = vcpu->arch.diag318_info.val;
if (MACHINE_HAS_GS) { if (MACHINE_HAS_GS) {
__ctl_set_bit(2, 4); __ctl_set_bit(2, 4);
if (vcpu->arch.gs_enabled) if (vcpu->arch.gs_enabled)
......
...@@ -548,6 +548,7 @@ static int shadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) ...@@ -548,6 +548,7 @@ static int shadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
scb_s->ecd |= scb_o->ecd & ECD_ETOKENF; scb_s->ecd |= scb_o->ecd & ECD_ETOKENF;
scb_s->hpid = HPID_VSIE; scb_s->hpid = HPID_VSIE;
scb_s->cpnc = scb_o->cpnc;
prepare_ibc(vcpu, vsie_page); prepare_ibc(vcpu, vsie_page);
rc = shadow_crycb(vcpu, vsie_page); rc = shadow_crycb(vcpu, vsie_page);
......
...@@ -1031,6 +1031,7 @@ struct kvm_ppc_resize_hpt { ...@@ -1031,6 +1031,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_PPC_SECURE_GUEST 181 #define KVM_CAP_PPC_SECURE_GUEST 181
#define KVM_CAP_HALT_POLL 182 #define KVM_CAP_HALT_POLL 182
#define KVM_CAP_ASYNC_PF_INT 183 #define KVM_CAP_ASYNC_PF_INT 183
#define KVM_CAP_S390_DIAG318 184
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment