Skip to content

Commit 75aa87c

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull kvm fix from Paolo Bonzini: - s390: fix support for z16 systems * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM: s390: fix LPSWEY handling
2 parents 661e504 + 8ad209f commit 75aa87c

File tree

4 files changed

+49
-0
lines changed

4 files changed

+49
-0
lines changed

arch/s390/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ struct kvm_vcpu_stat {
427427
u64 instruction_io_other;
428428
u64 instruction_lpsw;
429429
u64 instruction_lpswe;
430+
u64 instruction_lpswey;
430431
u64 instruction_pfmf;
431432
u64 instruction_ptff;
432433
u64 instruction_sck;

arch/s390/kvm/kvm-s390.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
132132
STATS_DESC_COUNTER(VCPU, instruction_io_other),
133133
STATS_DESC_COUNTER(VCPU, instruction_lpsw),
134134
STATS_DESC_COUNTER(VCPU, instruction_lpswe),
135+
STATS_DESC_COUNTER(VCPU, instruction_lpswey),
135136
STATS_DESC_COUNTER(VCPU, instruction_pfmf),
136137
STATS_DESC_COUNTER(VCPU, instruction_ptff),
137138
STATS_DESC_COUNTER(VCPU, instruction_sck),

arch/s390/kvm/kvm-s390.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,21 @@ static inline u64 kvm_s390_get_base_disp_s(struct kvm_vcpu *vcpu, u8 *ar)
138138
return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
139139
}
140140

141+
static inline u64 kvm_s390_get_base_disp_siy(struct kvm_vcpu *vcpu, u8 *ar)
142+
{
143+
u32 base1 = vcpu->arch.sie_block->ipb >> 28;
144+
s64 disp1;
145+
146+
/* The displacement is a 20bit _SIGNED_ value */
147+
disp1 = sign_extend64(((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) +
148+
((vcpu->arch.sie_block->ipb & 0xff00) << 4), 19);
149+
150+
if (ar)
151+
*ar = base1;
152+
153+
return (base1 ? vcpu->run->s.regs.gprs[base1] : 0) + disp1;
154+
}
155+
141156
static inline void kvm_s390_get_base_disp_sse(struct kvm_vcpu *vcpu,
142157
u64 *address1, u64 *address2,
143158
u8 *ar_b1, u8 *ar_b2)

arch/s390/kvm/priv.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,36 @@ static int handle_lpswe(struct kvm_vcpu *vcpu)
797797
return 0;
798798
}
799799

800+
static int handle_lpswey(struct kvm_vcpu *vcpu)
801+
{
802+
psw_t new_psw;
803+
u64 addr;
804+
int rc;
805+
u8 ar;
806+
807+
vcpu->stat.instruction_lpswey++;
808+
809+
if (!test_kvm_facility(vcpu->kvm, 193))
810+
return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
811+
812+
if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
813+
return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
814+
815+
addr = kvm_s390_get_base_disp_siy(vcpu, &ar);
816+
if (addr & 7)
817+
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
818+
819+
rc = read_guest(vcpu, addr, ar, &new_psw, sizeof(new_psw));
820+
if (rc)
821+
return kvm_s390_inject_prog_cond(vcpu, rc);
822+
823+
vcpu->arch.sie_block->gpsw = new_psw;
824+
if (!is_valid_psw(&vcpu->arch.sie_block->gpsw))
825+
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
826+
827+
return 0;
828+
}
829+
800830
static int handle_stidp(struct kvm_vcpu *vcpu)
801831
{
802832
u64 stidp_data = vcpu->kvm->arch.model.cpuid;
@@ -1462,6 +1492,8 @@ int kvm_s390_handle_eb(struct kvm_vcpu *vcpu)
14621492
case 0x61:
14631493
case 0x62:
14641494
return handle_ri(vcpu);
1495+
case 0x71:
1496+
return handle_lpswey(vcpu);
14651497
default:
14661498
return -EOPNOTSUPP;
14671499
}

0 commit comments

Comments
 (0)