aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/kvm_host.h2
-rw-r--r--arch/s390/include/asm/sclp.h1
-rw-r--r--arch/s390/include/uapi/asm/kvm.h1
-rw-r--r--arch/s390/kvm/intercept.c3
-rw-r--r--arch/s390/kvm/interrupt.c2
-rw-r--r--arch/s390/kvm/kvm-s390.c8
-rw-r--r--arch/s390/kvm/kvm-s390.h1
-rw-r--r--arch/s390/kvm/priv.c19
-rw-r--r--arch/s390/kvm/vsie.c8
-rw-r--r--drivers/s390/char/sclp_early.c4
10 files changed, 39 insertions, 10 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 552c319483c6..426614a882a9 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -122,6 +122,7 @@ struct esca_block {
122#define CPUSTAT_SLSR 0x00002000 122#define CPUSTAT_SLSR 0x00002000
123#define CPUSTAT_ZARCH 0x00000800 123#define CPUSTAT_ZARCH 0x00000800
124#define CPUSTAT_MCDS 0x00000100 124#define CPUSTAT_MCDS 0x00000100
125#define CPUSTAT_KSS 0x00000200
125#define CPUSTAT_SM 0x00000080 126#define CPUSTAT_SM 0x00000080
126#define CPUSTAT_IBS 0x00000040 127#define CPUSTAT_IBS 0x00000040
127#define CPUSTAT_GED2 0x00000010 128#define CPUSTAT_GED2 0x00000010
@@ -185,6 +186,7 @@ struct kvm_s390_sie_block {
185#define ICPT_OPEREXC 0x2C 186#define ICPT_OPEREXC 0x2C
186#define ICPT_PARTEXEC 0x38 187#define ICPT_PARTEXEC 0x38
187#define ICPT_IOINST 0x40 188#define ICPT_IOINST 0x40
189#define ICPT_KSS 0x5c
188 __u8 icptcode; /* 0x0050 */ 190 __u8 icptcode; /* 0x0050 */
189 __u8 icptstatus; /* 0x0051 */ 191 __u8 icptstatus; /* 0x0051 */
190 __u16 ihcpu; /* 0x0052 */ 192 __u16 ihcpu; /* 0x0052 */
diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h
index ace3bd315438..6f5167bc1928 100644
--- a/arch/s390/include/asm/sclp.h
+++ b/arch/s390/include/asm/sclp.h
@@ -75,6 +75,7 @@ struct sclp_info {
75 unsigned char has_pfmfi : 1; 75 unsigned char has_pfmfi : 1;
76 unsigned char has_ibs : 1; 76 unsigned char has_ibs : 1;
77 unsigned char has_skey : 1; 77 unsigned char has_skey : 1;
78 unsigned char has_kss : 1;
78 unsigned int ibc; 79 unsigned int ibc;
79 unsigned int mtid; 80 unsigned int mtid;
80 unsigned int mtid_cp; 81 unsigned int mtid_cp;
diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h
index 2c9ad251fa33..bf9267930939 100644
--- a/arch/s390/include/uapi/asm/kvm.h
+++ b/arch/s390/include/uapi/asm/kvm.h
@@ -119,6 +119,7 @@ struct kvm_s390_vm_cpu_machine {
119#define KVM_S390_VM_CPU_FEAT_CMMA 10 119#define KVM_S390_VM_CPU_FEAT_CMMA 10
120#define KVM_S390_VM_CPU_FEAT_PFMFI 11 120#define KVM_S390_VM_CPU_FEAT_PFMFI 11
121#define KVM_S390_VM_CPU_FEAT_SIGPIF 12 121#define KVM_S390_VM_CPU_FEAT_SIGPIF 12
122#define KVM_S390_VM_CPU_FEAT_KSS 13
122struct kvm_s390_vm_cpu_feat { 123struct kvm_s390_vm_cpu_feat {
123 __u64 feat[16]; 124 __u64 feat[16];
124}; 125};
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index f5378f336127..a4752bf6b526 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -426,6 +426,9 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
426 case ICPT_PARTEXEC: 426 case ICPT_PARTEXEC:
427 rc = handle_partial_execution(vcpu); 427 rc = handle_partial_execution(vcpu);
428 break; 428 break;
429 case ICPT_KSS:
430 rc = kvm_s390_skey_check_enable(vcpu);
431 break;
429 default: 432 default:
430 return -EOPNOTSUPP; 433 return -EOPNOTSUPP;
431 } 434 }
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 482673e3436d..caf15c8a8948 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -419,6 +419,8 @@ static int __write_machine_check(struct kvm_vcpu *vcpu,
419 /* take care of lazy register loading */ 419 /* take care of lazy register loading */
420 save_fpu_regs(); 420 save_fpu_regs();
421 save_access_regs(vcpu->run->s.regs.acrs); 421 save_access_regs(vcpu->run->s.regs.acrs);
422 if (MACHINE_HAS_GS && vcpu->arch.gs_enabled)
423 save_gs_cb(current->thread.gs_cb);
422 424
423 /* Extended save area */ 425 /* Extended save area */
424 rc = read_guest_lc(vcpu, __LC_MCESAD, &ext_sa_addr, 426 rc = read_guest_lc(vcpu, __LC_MCESAD, &ext_sa_addr,
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 11b7d6638991..8771fef112a1 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -300,6 +300,8 @@ static void kvm_s390_cpu_feat_init(void)
300 allow_cpu_feat(KVM_S390_VM_CPU_FEAT_CEI); 300 allow_cpu_feat(KVM_S390_VM_CPU_FEAT_CEI);
301 if (sclp.has_ibs) 301 if (sclp.has_ibs)
302 allow_cpu_feat(KVM_S390_VM_CPU_FEAT_IBS); 302 allow_cpu_feat(KVM_S390_VM_CPU_FEAT_IBS);
303 if (sclp.has_kss)
304 allow_cpu_feat(KVM_S390_VM_CPU_FEAT_KSS);
303 /* 305 /*
304 * KVM_S390_VM_CPU_FEAT_SKEY: Wrong shadow of PTE.I bits will make 306 * KVM_S390_VM_CPU_FEAT_SKEY: Wrong shadow of PTE.I bits will make
305 * all skey handling functions read/set the skey from the PGSTE 307 * all skey handling functions read/set the skey from the PGSTE
@@ -2034,7 +2036,11 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
2034 vcpu->arch.sie_block->sdnxo = ((unsigned long) &vcpu->run->s.regs.sdnx) 2036 vcpu->arch.sie_block->sdnxo = ((unsigned long) &vcpu->run->s.regs.sdnx)
2035 | SDNXC; 2037 | SDNXC;
2036 vcpu->arch.sie_block->riccbd = (unsigned long) &vcpu->run->s.regs.riccb; 2038 vcpu->arch.sie_block->riccbd = (unsigned long) &vcpu->run->s.regs.riccb;
2037 vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE; 2039
2040 if (sclp.has_kss)
2041 atomic_or(CPUSTAT_KSS, &vcpu->arch.sie_block->cpuflags);
2042 else
2043 vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE;
2038 2044
2039 if (vcpu->kvm->arch.use_cmma) { 2045 if (vcpu->kvm->arch.use_cmma) {
2040 rc = kvm_s390_vcpu_setup_cmma(vcpu); 2046 rc = kvm_s390_vcpu_setup_cmma(vcpu);
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 455124fe0647..55f5c8457d6d 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -254,6 +254,7 @@ int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu);
254int kvm_s390_handle_stctl(struct kvm_vcpu *vcpu); 254int kvm_s390_handle_stctl(struct kvm_vcpu *vcpu);
255int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu); 255int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu);
256int kvm_s390_handle_eb(struct kvm_vcpu *vcpu); 256int kvm_s390_handle_eb(struct kvm_vcpu *vcpu);
257int kvm_s390_skey_check_enable(struct kvm_vcpu *vcpu);
257 258
258/* implemented in vsie.c */ 259/* implemented in vsie.c */
259int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu); 260int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu);
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 0ffe973535fa..c03106c428cf 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -198,18 +198,25 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
198 return 0; 198 return 0;
199} 199}
200 200
201static int __skey_check_enable(struct kvm_vcpu *vcpu) 201int kvm_s390_skey_check_enable(struct kvm_vcpu *vcpu)
202{ 202{
203 int rc = 0; 203 int rc = 0;
204 struct kvm_s390_sie_block *sie_block = vcpu->arch.sie_block;
204 205
205 trace_kvm_s390_skey_related_inst(vcpu); 206 trace_kvm_s390_skey_related_inst(vcpu);
206 if (!(vcpu->arch.sie_block->ictl & (ICTL_ISKE | ICTL_SSKE | ICTL_RRBE))) 207 if (!(sie_block->ictl & (ICTL_ISKE | ICTL_SSKE | ICTL_RRBE)) &&
208 !(atomic_read(&sie_block->cpuflags) & CPUSTAT_KSS))
207 return rc; 209 return rc;
208 210
209 rc = s390_enable_skey(); 211 rc = s390_enable_skey();
210 VCPU_EVENT(vcpu, 3, "enabling storage keys for guest: %d", rc); 212 VCPU_EVENT(vcpu, 3, "enabling storage keys for guest: %d", rc);
211 if (!rc) 213 if (!rc) {
212 vcpu->arch.sie_block->ictl &= ~(ICTL_ISKE | ICTL_SSKE | ICTL_RRBE); 214 if (atomic_read(&sie_block->cpuflags) & CPUSTAT_KSS)
215 atomic_andnot(CPUSTAT_KSS, &sie_block->cpuflags);
216 else
217 sie_block->ictl &= ~(ICTL_ISKE | ICTL_SSKE |
218 ICTL_RRBE);
219 }
213 return rc; 220 return rc;
214} 221}
215 222
@@ -218,7 +225,7 @@ static int try_handle_skey(struct kvm_vcpu *vcpu)
218 int rc; 225 int rc;
219 226
220 vcpu->stat.instruction_storage_key++; 227 vcpu->stat.instruction_storage_key++;
221 rc = __skey_check_enable(vcpu); 228 rc = kvm_s390_skey_check_enable(vcpu);
222 if (rc) 229 if (rc)
223 return rc; 230 return rc;
224 if (sclp.has_skey) { 231 if (sclp.has_skey) {
@@ -916,7 +923,7 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
916 } 923 }
917 924
918 if (vcpu->run->s.regs.gprs[reg1] & PFMF_SK) { 925 if (vcpu->run->s.regs.gprs[reg1] & PFMF_SK) {
919 int rc = __skey_check_enable(vcpu); 926 int rc = kvm_s390_skey_check_enable(vcpu);
920 927
921 if (rc) 928 if (rc)
922 return rc; 929 return rc;
diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c
index 2fafc2be777f..4719ecb9ab42 100644
--- a/arch/s390/kvm/vsie.c
+++ b/arch/s390/kvm/vsie.c
@@ -117,6 +117,8 @@ static int prepare_cpuflags(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
117 newflags |= cpuflags & CPUSTAT_SM; 117 newflags |= cpuflags & CPUSTAT_SM;
118 if (test_kvm_cpu_feat(vcpu->kvm, KVM_S390_VM_CPU_FEAT_IBS)) 118 if (test_kvm_cpu_feat(vcpu->kvm, KVM_S390_VM_CPU_FEAT_IBS))
119 newflags |= cpuflags & CPUSTAT_IBS; 119 newflags |= cpuflags & CPUSTAT_IBS;
120 if (test_kvm_cpu_feat(vcpu->kvm, KVM_S390_VM_CPU_FEAT_KSS))
121 newflags |= cpuflags & CPUSTAT_KSS;
120 122
121 atomic_set(&scb_s->cpuflags, newflags); 123 atomic_set(&scb_s->cpuflags, newflags);
122 return 0; 124 return 0;
@@ -289,7 +291,9 @@ static int shadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
289 * bits. Therefore we cannot provide interpretation and would later 291 * bits. Therefore we cannot provide interpretation and would later
290 * have to provide own emulation handlers. 292 * have to provide own emulation handlers.
291 */ 293 */
292 scb_s->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE; 294 if (!(atomic_read(&scb_s->cpuflags) & CPUSTAT_KSS))
295 scb_s->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE;
296
293 scb_s->icpua = scb_o->icpua; 297 scb_s->icpua = scb_o->icpua;
294 298
295 if (!(atomic_read(&scb_s->cpuflags) & CPUSTAT_SM)) 299 if (!(atomic_read(&scb_s->cpuflags) & CPUSTAT_SM))
@@ -627,7 +631,7 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
627 rc = set_validity_icpt(scb_s, 0x10b0U); 631 rc = set_validity_icpt(scb_s, 0x10b0U);
628 if (rc) 632 if (rc)
629 goto unpin; 633 goto unpin;
630 scb_s->sdnxo = hpa; 634 scb_s->sdnxo = hpa | sdnxc;
631 } 635 }
632 return 0; 636 return 0;
633unpin: 637unpin:
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c
index 519ec1787117..efd84d1d178b 100644
--- a/drivers/s390/char/sclp_early.c
+++ b/drivers/s390/char/sclp_early.c
@@ -40,7 +40,8 @@ struct read_info_sccb {
40 u8 fac85; /* 85 */ 40 u8 fac85; /* 85 */
41 u8 _pad_86[91 - 86]; /* 86-90 */ 41 u8 _pad_86[91 - 86]; /* 86-90 */
42 u8 flags; /* 91 */ 42 u8 flags; /* 91 */
43 u8 _pad_92[99 - 92]; /* 92-98 */ 43 u8 _pad_92[98 - 92]; /* 92-97 */
44 u8 fac98; /* 98 */
44 u8 hamaxpow; /* 99 */ 45 u8 hamaxpow; /* 99 */
45 u32 rnsize2; /* 100-103 */ 46 u32 rnsize2; /* 100-103 */
46 u64 rnmax2; /* 104-111 */ 47 u64 rnmax2; /* 104-111 */
@@ -99,6 +100,7 @@ static void __init sclp_early_facilities_detect(struct read_info_sccb *sccb)
99 sclp.has_pfmfi = !!(sccb->fac117 & 0x40); 100 sclp.has_pfmfi = !!(sccb->fac117 & 0x40);
100 sclp.has_ibs = !!(sccb->fac117 & 0x20); 101 sclp.has_ibs = !!(sccb->fac117 & 0x20);
101 sclp.has_hvs = !!(sccb->fac119 & 0x80); 102 sclp.has_hvs = !!(sccb->fac119 & 0x80);
103 sclp.has_kss = !!(sccb->fac98 & 0x01);
102 if (sccb->fac85 & 0x02) 104 if (sccb->fac85 & 0x02)
103 S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; 105 S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP;
104 sclp.rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; 106 sclp.rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;