@@ -28,7 +28,8 @@ struct vsie_page {
28
28
struct kvm_s390_sie_block * scb_o ; /* 0x0200 */
29
29
/* the shadow gmap in use by the vsie_page */
30
30
struct gmap * gmap ; /* 0x0208 */
31
- __u8 reserved [0x0800 - 0x0210 ]; /* 0x0210 */
31
+ __u8 reserved [0x0700 - 0x0210 ]; /* 0x0210 */
32
+ struct kvm_s390_crypto_cb crycb ; /* 0x0700 */
32
33
__u8 fac [S390_ARCH_FAC_LIST_SIZE_BYTE ]; /* 0x0800 */
33
34
} __packed ;
34
35
@@ -111,6 +112,58 @@ static int prepare_cpuflags(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
111
112
return 0 ;
112
113
}
113
114
115
+ /*
116
+ * Create a shadow copy of the crycb block and setup key wrapping, if
117
+ * requested for guest 3 and enabled for guest 2.
118
+ *
119
+ * We only accept format-1 (no AP in g2), but convert it into format-2
120
+ * There is nothing to do for format-0.
121
+ *
122
+ * Returns: - 0 if shadowed or nothing to do
123
+ * - > 0 if control has to be given to guest 2
124
+ */
125
+ static int shadow_crycb (struct kvm_vcpu * vcpu , struct vsie_page * vsie_page )
126
+ {
127
+ struct kvm_s390_sie_block * scb_s = & vsie_page -> scb_s ;
128
+ struct kvm_s390_sie_block * scb_o = vsie_page -> scb_o ;
129
+ u32 crycb_addr = scb_o -> crycbd & 0x7ffffff8U ;
130
+ unsigned long * b1 , * b2 ;
131
+ u8 ecb3_flags ;
132
+
133
+ scb_s -> crycbd = 0 ;
134
+ if (!(scb_o -> crycbd & vcpu -> arch .sie_block -> crycbd & CRYCB_FORMAT1 ))
135
+ return 0 ;
136
+ /* format-1 is supported with message-security-assist extension 3 */
137
+ if (!test_kvm_facility (vcpu -> kvm , 76 ))
138
+ return 0 ;
139
+ /* we may only allow it if enabled for guest 2 */
140
+ ecb3_flags = scb_o -> ecb3 & vcpu -> arch .sie_block -> ecb3 &
141
+ (ECB3_AES | ECB3_DEA );
142
+ if (!ecb3_flags )
143
+ return 0 ;
144
+
145
+ if ((crycb_addr & PAGE_MASK ) != ((crycb_addr + 128 ) & PAGE_MASK ))
146
+ return set_validity_icpt (scb_s , 0x003CU );
147
+ else if (!crycb_addr )
148
+ return set_validity_icpt (scb_s , 0x0039U );
149
+
150
+ /* copy only the wrapping keys */
151
+ if (read_guest_real (vcpu , crycb_addr + 72 , & vsie_page -> crycb , 56 ))
152
+ return set_validity_icpt (scb_s , 0x0035U );
153
+
154
+ scb_s -> ecb3 |= ecb3_flags ;
155
+ scb_s -> crycbd = ((__u32 )(__u64 ) & vsie_page -> crycb ) | CRYCB_FORMAT1 |
156
+ CRYCB_FORMAT2 ;
157
+
158
+ /* xor both blocks in one run */
159
+ b1 = (unsigned long * ) vsie_page -> crycb .dea_wrapping_key_mask ;
160
+ b2 = (unsigned long * )
161
+ vcpu -> kvm -> arch .crypto .crycb -> dea_wrapping_key_mask ;
162
+ /* as 56%8 == 0, bitmap_xor won't overwrite any data */
163
+ bitmap_xor (b1 , b1 , b2 , BITS_PER_BYTE * 56 );
164
+ return 0 ;
165
+ }
166
+
114
167
/* shadow (round up/down) the ibc to avoid validity icpt */
115
168
static void prepare_ibc (struct kvm_vcpu * vcpu , struct vsie_page * vsie_page )
116
169
{
@@ -248,6 +301,7 @@ static int shadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
248
301
scb_s -> ecb |= scb_o -> ecb & 0x02U ;
249
302
250
303
prepare_ibc (vcpu , vsie_page );
304
+ rc = shadow_crycb (vcpu , vsie_page );
251
305
out :
252
306
if (rc )
253
307
unshadow_scb (vcpu , vsie_page );
0 commit comments