]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
s390/kvm: diagnose 0x318 sync and reset
authorCollin Walling <walling@linux.ibm.com>
Tue, 7 Dec 2021 20:38:00 +0000 (21:38 +0100)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Thu, 13 Jan 2022 17:43:09 +0000 (18:43 +0100)
BugLink: https://bugs.launchpad.net/bugs/1953334
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: Collin Walling <walling@linux.ibm.com>
Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: David 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: Christian Borntraeger <borntraeger@de.ibm.com>
(backported from commit 23a60f834406c8e3805328b630d09d5546b460c1)
Signed-off-by: Frank Heimes <frank.heimes@canonical.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
Acked-by: Philip Cox <philip.cox@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
arch/s390/include/asm/kvm_host.h
arch/s390/include/uapi/asm/kvm.h
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/vsie.c
include/uapi/linux/kvm.h

index 03be757cc2a5c945287b8a1f5db2ff5090e35542..5802dab2e8a1e7ebe1f9bb5981d945491a0c15f2 100644 (file)
@@ -260,7 +260,8 @@ struct kvm_s390_sie_block {
        __u32   scaol;                  /* 0x0064 */
        __u8    sdf;                    /* 0x0068 */
        __u8    epdx;                   /* 0x0069 */
-       __u8    reserved6a[2];          /* 0x006a */
+       __u8    cpnc;                   /* 0x006a */
+       __u8    reserved6b;             /* 0x006b */
        __u32   todpr;                  /* 0x006c */
 #define GISA_FORMAT1 0x00000001
        __u32   gd;                     /* 0x0070 */
@@ -742,6 +743,7 @@ struct kvm_vcpu_arch {
        bool gs_enabled;
        bool skey_enabled;
        struct kvm_s390_pv_vcpu pv;
+       union diag318_info diag318_info;
 };
 
 struct kvm_vm_stat {
index 436ec7636927379ff40432478e9f175d886a1e7d..7a6b14874d65c486242982d3bccabc4891b8fbda 100644 (file)
@@ -231,11 +231,13 @@ struct kvm_guest_debug_arch {
 #define KVM_SYNC_GSCB   (1UL << 9)
 #define KVM_SYNC_BPBC   (1UL << 10)
 #define KVM_SYNC_ETOKEN (1UL << 11)
+#define KVM_SYNC_DIAG318 (1UL << 12)
 
 #define KVM_SYNC_S390_VALID_FIELDS \
        (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_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 */
 #define SDNXC 8
@@ -264,7 +266,8 @@ struct kvm_sync_regs {
        __u8 reserved2 : 7;
        __u8 padding1[51];      /* riccb needs to be 64byte aligned */
        __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 {
                __u8 sdnx[SDNXL];  /* state description annex */
                struct {
index 908ce7b1d7567585e080967514845fb1bd4c0815..a8adbe7ffc8965c786c6197e68b249a06f7dc8af 100644 (file)
@@ -539,6 +539,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_S390_AIS:
        case KVM_CAP_S390_AIS_MIGRATION:
        case KVM_CAP_S390_VCPU_RESETS:
+       case KVM_CAP_S390_DIAG318:
                r = 1;
                break;
        case KVM_CAP_S390_HPAGE_1M:
@@ -2961,7 +2962,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
                                    KVM_SYNC_ACRS |
                                    KVM_SYNC_CRS |
                                    KVM_SYNC_ARCH0 |
-                                   KVM_SYNC_PFAULT;
+                                   KVM_SYNC_PFAULT |
+                                   KVM_SYNC_DIAG318;
        kvm_s390_set_prefix(vcpu, 0);
        if (test_kvm_facility(vcpu->kvm, 64))
                vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB;
@@ -3554,6 +3556,7 @@ static void kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
                vcpu->arch.sie_block->pp = 0;
                vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
                vcpu->arch.sie_block->todpr = 0;
+               vcpu->arch.sie_block->cpnc = 0;
        }
 }
 
@@ -3571,6 +3574,7 @@ static void kvm_arch_vcpu_ioctl_clear_reset(struct kvm_vcpu *vcpu)
 
        regs->etoken = 0;
        regs->etoken_extension = 0;
+       regs->diag318 = 0;
 }
 
 int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
@@ -4189,6 +4193,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)
                        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,
         * we should enable RI here instead of doing the lazy enablement.
@@ -4290,6 +4298,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.gbea = vcpu->arch.sie_block->gbea;
        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) {
                preempt_disable();
                __ctl_set_bit(2, 4);
index 4f6c22d72072ade872f638a704dab39aa38d2a42..6528716fbd51f34d156123b10dd004a3fe7f887a 100644 (file)
@@ -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->hpid = HPID_VSIE;
+       scb_s->cpnc = scb_o->cpnc;
 
        prepare_ibc(vcpu, vsie_page);
        rc = shadow_crycb(vcpu, vsie_page);
index 743d34da37dd11cb2945e0438cb65eb902d6ae60..460ad2a34b562eb591c17872b8ab85aa06e4e1c8 100644 (file)
@@ -1010,6 +1010,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 175
 #define KVM_CAP_S390_VCPU_RESETS 179
 #define KVM_CAP_S390_PROTECTED 180
+#define KVM_CAP_S390_DIAG318 186
 
 #ifdef KVM_CAP_IRQ_ROUTING