diff options
-rw-r--r-- | arch/s390/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/s390/include/asm/sclp.h | 1 | ||||
-rw-r--r-- | arch/s390/include/uapi/asm/kvm.h | 1 | ||||
-rw-r--r-- | arch/s390/kvm/intercept.c | 3 | ||||
-rw-r--r-- | arch/s390/kvm/interrupt.c | 2 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 8 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.h | 1 | ||||
-rw-r--r-- | arch/s390/kvm/priv.c | 19 | ||||
-rw-r--r-- | arch/s390/kvm/vsie.c | 8 | ||||
-rw-r--r-- | drivers/s390/char/sclp_early.c | 4 |
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 | ||
122 | struct kvm_s390_vm_cpu_feat { | 123 | struct 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); | |||
254 | int kvm_s390_handle_stctl(struct kvm_vcpu *vcpu); | 254 | int kvm_s390_handle_stctl(struct kvm_vcpu *vcpu); |
255 | int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu); | 255 | int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu); |
256 | int kvm_s390_handle_eb(struct kvm_vcpu *vcpu); | 256 | int kvm_s390_handle_eb(struct kvm_vcpu *vcpu); |
257 | int kvm_s390_skey_check_enable(struct kvm_vcpu *vcpu); | ||
257 | 258 | ||
258 | /* implemented in vsie.c */ | 259 | /* implemented in vsie.c */ |
259 | int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu); | 260 | int 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 | ||
201 | static int __skey_check_enable(struct kvm_vcpu *vcpu) | 201 | int 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; |
633 | unpin: | 637 | unpin: |
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; |