]> Git Repo - J-linux.git/commitdiff
KVM: s390: fix LPSWEY handling
authorChristian Borntraeger <[email protected]>
Fri, 28 Jun 2024 16:35:47 +0000 (18:35 +0200)
committerChristian Borntraeger <[email protected]>
Mon, 1 Jul 2024 12:31:15 +0000 (14:31 +0200)
in rare cases, e.g. for injecting a machine check we do intercept all
load PSW instructions via ICTL_LPSW. With facility 193 a new variant
LPSWEY was added. KVM needs to handle that as well.

Fixes: a3efa8429266 ("KVM: s390: gen_facilities: allow facilities 165, 193, 194 and 196")
Reported-by: Marc Hartmayer <[email protected]>
Reviewed-by: Sven Schnelle <[email protected]>
Reviewed-by: Claudio Imbrenda <[email protected]>
Signed-off-by: Christian Borntraeger <[email protected]>
Message-ID: <20240628163547[email protected]>

arch/s390/include/asm/kvm_host.h
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/kvm-s390.h
arch/s390/kvm/priv.c

index 95990461888fcaee7759af29874071207797ad74..9281063636a73291b09c8db16c825cd03380379d 100644 (file)
@@ -427,6 +427,7 @@ struct kvm_vcpu_stat {
        u64 instruction_io_other;
        u64 instruction_lpsw;
        u64 instruction_lpswe;
+       u64 instruction_lpswey;
        u64 instruction_pfmf;
        u64 instruction_ptff;
        u64 instruction_sck;
index 82e9631cd9efb86defd13e029f0a737726ba853b..54b5b2565df8d16e4cdcfe981642bdf5f3ef285f 100644 (file)
@@ -132,6 +132,7 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
        STATS_DESC_COUNTER(VCPU, instruction_io_other),
        STATS_DESC_COUNTER(VCPU, instruction_lpsw),
        STATS_DESC_COUNTER(VCPU, instruction_lpswe),
+       STATS_DESC_COUNTER(VCPU, instruction_lpswey),
        STATS_DESC_COUNTER(VCPU, instruction_pfmf),
        STATS_DESC_COUNTER(VCPU, instruction_ptff),
        STATS_DESC_COUNTER(VCPU, instruction_sck),
index 111eb5c7478409c4af5c8c3e8f76c730b1b5406c..bf8534218af3dcdf7be20f58a8e95c904cb2b9c0 100644 (file)
@@ -138,6 +138,21 @@ static inline u64 kvm_s390_get_base_disp_s(struct kvm_vcpu *vcpu, u8 *ar)
        return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
 }
 
+static inline u64 kvm_s390_get_base_disp_siy(struct kvm_vcpu *vcpu, u8 *ar)
+{
+       u32 base1 = vcpu->arch.sie_block->ipb >> 28;
+       s64 disp1;
+
+       /* The displacement is a 20bit _SIGNED_ value */
+       disp1 = sign_extend64(((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) +
+                             ((vcpu->arch.sie_block->ipb & 0xff00) << 4), 19);
+
+       if (ar)
+               *ar = base1;
+
+       return (base1 ? vcpu->run->s.regs.gprs[base1] : 0) + disp1;
+}
+
 static inline void kvm_s390_get_base_disp_sse(struct kvm_vcpu *vcpu,
                                              u64 *address1, u64 *address2,
                                              u8 *ar_b1, u8 *ar_b2)
index 1be19cc9d73c19cf35b3df5dd9f7b430cdf8c3b7..1a49b89706f86e75544d765e2a19ff0b2f11cc11 100644 (file)
@@ -797,6 +797,36 @@ static int handle_lpswe(struct kvm_vcpu *vcpu)
        return 0;
 }
 
+static int handle_lpswey(struct kvm_vcpu *vcpu)
+{
+       psw_t new_psw;
+       u64 addr;
+       int rc;
+       u8 ar;
+
+       vcpu->stat.instruction_lpswey++;
+
+       if (!test_kvm_facility(vcpu->kvm, 193))
+               return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
+
+       if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
+               return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
+
+       addr = kvm_s390_get_base_disp_siy(vcpu, &ar);
+       if (addr & 7)
+               return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
+       rc = read_guest(vcpu, addr, ar, &new_psw, sizeof(new_psw));
+       if (rc)
+               return kvm_s390_inject_prog_cond(vcpu, rc);
+
+       vcpu->arch.sie_block->gpsw = new_psw;
+       if (!is_valid_psw(&vcpu->arch.sie_block->gpsw))
+               return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
+       return 0;
+}
+
 static int handle_stidp(struct kvm_vcpu *vcpu)
 {
        u64 stidp_data = vcpu->kvm->arch.model.cpuid;
@@ -1462,6 +1492,8 @@ int kvm_s390_handle_eb(struct kvm_vcpu *vcpu)
        case 0x61:
        case 0x62:
                return handle_ri(vcpu);
+       case 0x71:
+               return handle_lpswey(vcpu);
        default:
                return -EOPNOTSUPP;
        }
This page took 0.066597 seconds and 4 git commands to generate.