1 /*
2 * s390x Ultravisor related definitions
3 *
4 * Copyright IBM Corp. 2020, 2022
5 *
6 * Authors:
7 * Janosch Frank <frankja@linux.ibm.com>
8 *
9 * This code is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2.
11 */
12 #ifndef _ASMS390X_UV_H_
13 #define _ASMS390X_UV_H_
14
15 /* Enables printing of command code and return codes for failed UVCs */
16 #ifndef UVC_ERR_DEBUG
17 #define UVC_ERR_DEBUG 0
18 #endif
19
20 #define UVC_RC_EXECUTED 0x0001
21 #define UVC_RC_INV_CMD 0x0002
22 #define UVC_RC_INV_STATE 0x0003
23 #define UVC_RC_INV_LEN 0x0005
24 #define UVC_RC_NO_RESUME 0x0007
25 #define UVC_RC_INV_GHANDLE 0x0020
26 #define UVC_RC_INV_CHANDLE 0x0021
27 #define UVC_RC_DSTR_NEEDED_FLG 0x8000
28
29 #define UVC_CMD_QUI 0x0001
30 #define UVC_CMD_INIT_UV 0x000f
31 #define UVC_CMD_CREATE_SEC_CONF 0x0100
32 #define UVC_CMD_DESTROY_SEC_CONF 0x0101
33 #define UVC_CMD_CREATE_SEC_CPU 0x0120
34 #define UVC_CMD_DESTROY_SEC_CPU 0x0121
35 #define UVC_CMD_CONV_TO_SEC_STOR 0x0200
36 #define UVC_CMD_CONV_FROM_SEC_STOR 0x0201
37 #define UVC_CMD_DESTR_SEC_STOR 0x0202
38 #define UVC_CMD_SET_SEC_CONF_PARAMS 0x0300
39 #define UVC_CMD_UNPACK_IMG 0x0301
40 #define UVC_CMD_VERIFY_IMG 0x0302
41 #define UVC_CMD_CPU_RESET 0x0310
42 #define UVC_CMD_CPU_RESET_INITIAL 0x0311
43 #define UVC_CMD_PREPARE_RESET 0x0320
44 #define UVC_CMD_CPU_RESET_CLEAR 0x0321
45 #define UVC_CMD_CPU_SET_STATE 0x0330
46 #define UVC_CMD_SET_UNSHARED_ALL 0x0340
47 #define UVC_CMD_PIN_PAGE_SHARED 0x0341
48 #define UVC_CMD_UNPIN_PAGE_SHARED 0x0342
49 #define UVC_CMD_SET_SHARED_ACCESS 0x1000
50 #define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001
51 #define UVC_CMD_ATTESTATION 0x1020
52
53 /* Bits in installed uv calls */
54 enum uv_cmds_inst {
55 BIT_UVC_CMD_QUI = 0,
56 BIT_UVC_CMD_INIT_UV = 1,
57 BIT_UVC_CMD_CREATE_SEC_CONF = 2,
58 BIT_UVC_CMD_DESTROY_SEC_CONF = 3,
59 BIT_UVC_CMD_CREATE_SEC_CPU = 4,
60 BIT_UVC_CMD_DESTROY_SEC_CPU = 5,
61 BIT_UVC_CMD_CONV_TO_SEC_STOR = 6,
62 BIT_UVC_CMD_CONV_FROM_SEC_STOR = 7,
63 BIT_UVC_CMD_SET_SHARED_ACCESS = 8,
64 BIT_UVC_CMD_REMOVE_SHARED_ACCESS = 9,
65 BIT_UVC_CMD_SET_SEC_PARMS = 11,
66 BIT_UVC_CMD_UNPACK_IMG = 13,
67 BIT_UVC_CMD_VERIFY_IMG = 14,
68 BIT_UVC_CMD_CPU_RESET = 15,
69 BIT_UVC_CMD_CPU_RESET_INITIAL = 16,
70 BIT_UVC_CMD_CPU_SET_STATE = 17,
71 BIT_UVC_CMD_PREPARE_RESET = 18,
72 BIT_UVC_CMD_CPU_PERFORM_CLEAR_RESET = 19,
73 BIT_UVC_CMD_UNSHARE_ALL = 20,
74 BIT_UVC_CMD_PIN_PAGE_SHARED = 21,
75 BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22,
76 BIT_UVC_CMD_ATTESTATION = 28,
77 };
78
79 struct uv_cb_header {
80 u16 len;
81 u16 cmd; /* Command Code */
82 u16 rc; /* Response Code */
83 u16 rrc; /* Return Reason Code */
84 } __attribute__((packed)) __attribute__((aligned(8)));
85
86 struct uv_cb_init {
87 struct uv_cb_header header;
88 u64 reserved08[2];
89 u64 stor_origin;
90 u64 stor_len;
91 u64 reserved28[4];
92
93 } __attribute__((packed)) __attribute__((aligned(8)));
94
95 struct uv_cb_qui {
96 struct uv_cb_header header; /* 0x0000 */
97 u64 reserved08; /* 0x0008 */
98 u64 inst_calls_list[4]; /* 0x0010 */
99 u64 reserved30[2]; /* 0x0030 */
100 u64 uv_base_stor_len; /* 0x0040 */
101 u64 reserved48; /* 0x0048 */
102 u64 conf_base_phys_stor_len; /* 0x0050 */
103 u64 conf_base_virt_stor_len; /* 0x0058 */
104 u64 conf_virt_var_stor_len; /* 0x0060 */
105 u64 cpu_stor_len; /* 0x0068 */
106 u32 reserved70[3]; /* 0x0070 */
107 u32 max_num_sec_conf; /* 0x007c */
108 u64 max_guest_stor_addr; /* 0x0080 */
109 u8 reserved88[158 - 136]; /* 0x0088 */
110 uint16_t max_guest_cpus; /* 0x009e */
111 u64 uv_feature_indications; /* 0x00a0 */
112 uint8_t reserveda8[224 - 168]; /* 0x00a8 */
113 uint64_t supp_att_hdr_ver; /* 0x00e0 */
114 uint64_t supp_paf; /* 0x00e8 */
115 uint8_t reservedf0[256 - 240]; /* 0x00f0 */
116 } __attribute__((packed)) __attribute__((aligned(8)));
117
118 struct uv_cb_cgc {
119 struct uv_cb_header header;
120 u64 reserved08[2];
121 u64 guest_handle;
122 u64 conf_base_stor_origin;
123 u64 conf_var_stor_origin;
124 u64 reserved30;
125 u64 guest_stor_origin;
126 u64 guest_stor_len;
127 u64 guest_sca;
128 u64 guest_asce;
129 u64 reserved60[5];
130 } __attribute__((packed)) __attribute__((aligned(8)));
131
132 struct uv_cb_csc {
133 struct uv_cb_header header;
134 u64 reserved08[2];
135 u64 cpu_handle;
136 u64 guest_handle;
137 u64 stor_origin;
138 u8 reserved30[6];
139 u16 num;
140 u64 state_origin;
141 u64 reserved[4];
142 } __attribute__((packed)) __attribute__((aligned(8)));
143
144 struct uv_cb_unp {
145 struct uv_cb_header header;
146 u64 reserved08[2];
147 u64 guest_handle;
148 u64 gaddr;
149 u64 tweak[2];
150 u64 reserved38[3];
151 } __attribute__((packed)) __attribute__((aligned(8)));
152
153 /*
154 * A common UV call struct for the following calls:
155 * Destroy cpu/config
156 * Verify
157 */
158 struct uv_cb_nodata {
159 struct uv_cb_header header;
160 u64 reserved08[2];
161 u64 handle;
162 u64 reserved20[4];
163 } __attribute__((packed)) __attribute__((aligned(8)));
164
165 struct uv_cb_share {
166 struct uv_cb_header header;
167 u64 reserved08[3];
168 u64 paddr;
169 u64 reserved28;
170 } __attribute__((packed)) __attribute__((aligned(8)));
171
172 /* Convert to Secure */
173 struct uv_cb_cts {
174 struct uv_cb_header header;
175 u64 reserved08[2];
176 u64 guest_handle;
177 u64 gaddr;
178 } __attribute__((packed)) __attribute__((aligned(8)));
179
180 /* Convert from Secure / Pin Page Shared */
181 struct uv_cb_cfs {
182 struct uv_cb_header header;
183 u64 reserved08[2];
184 u64 paddr;
185 } __attribute__((packed)) __attribute__((aligned(8)));
186
187 /* Retrieve Attestation Measurement */
188 struct uv_cb_attest {
189 struct uv_cb_header header; /* 0x0000 */
190 uint64_t reserved08[2]; /* 0x0008 */
191 uint64_t arcb_addr; /* 0x0018 */
192 uint64_t continuation_token; /* 0x0020 */
193 uint8_t reserved28[6]; /* 0x0028 */
194 uint16_t user_data_length; /* 0x002e */
195 uint8_t user_data[256]; /* 0x0030 */
196 uint32_t reserved130[3]; /* 0x0130 */
197 uint32_t measurement_length; /* 0x013c */
198 uint64_t measurement_address; /* 0x0140 */
199 uint8_t config_uid[16]; /* 0x0148 */
200 uint32_t reserved158; /* 0x0158 */
201 uint32_t add_data_length; /* 0x015c */
202 uint64_t add_data_address; /* 0x0160 */
203 uint64_t reserved168[4]; /* 0x0168 */
204 } __attribute__((packed)) __attribute__((aligned(8)));
205
206 /* Set Secure Config Parameter */
207 struct uv_cb_ssc {
208 struct uv_cb_header header;
209 u64 reserved08[2];
210 u64 guest_handle;
211 u64 sec_header_origin;
212 u32 sec_header_len;
213 u32 reserved2c;
214 u64 reserved30[4];
215 } __attribute__((packed)) __attribute__((aligned(8)));
216
uv_call_once(unsigned long r1,unsigned long r2)217 static inline int uv_call_once(unsigned long r1, unsigned long r2)
218 {
219 uint64_t bogus_cc = 1;
220 int cc;
221
222 asm volatile(
223 " tmll %[bogus_cc],3\n"
224 "0: .insn rrf,0xB9A40000,%[r1],%[r2],0,0\n"
225 " ipm %[cc]\n"
226 " srl %[cc],28\n"
227 : [cc] "=d" (cc)
228 : [r1] "a" (r1), [r2] "a" (r2), [bogus_cc] "d" (bogus_cc)
229 : "memory", "cc");
230
231 if (UVC_ERR_DEBUG && cc == 1)
232 printf("UV call error: call %x rc %x rrc %x\n",
233 ((struct uv_cb_header *)r2)->cmd,
234 ((struct uv_cb_header *)r2)->rc,
235 ((struct uv_cb_header *)r2)->rrc);
236
237 return cc;
238 }
239
uv_call(unsigned long r1,unsigned long r2)240 static inline int uv_call(unsigned long r1, unsigned long r2)
241 {
242 int cc;
243
244 /*
245 * CC 2 and 3 tell us to re-execute because the instruction
246 * hasn't yet finished.
247 */
248 do {
249 cc = uv_call_once(r1, r2);
250 } while (cc > 1);
251
252 return cc;
253 }
254
share(unsigned long addr,u16 cmd)255 static inline int share(unsigned long addr, u16 cmd)
256 {
257 struct uv_cb_share uvcb = {
258 .header.cmd = cmd,
259 .header.len = sizeof(uvcb),
260 .paddr = addr
261 };
262
263 return uv_call(0, (u64)&uvcb);
264 }
265
266 /*
267 * Guest 2 request to the Ultravisor to make a page shared with the
268 * hypervisor for IO.
269 *
270 * @addr: Real or absolute address of the page to be shared
271 */
uv_set_shared(unsigned long addr)272 static inline int uv_set_shared(unsigned long addr)
273 {
274 return share(addr, UVC_CMD_SET_SHARED_ACCESS);
275 }
276
277 /*
278 * Guest 2 request to the Ultravisor to make a page unshared.
279 *
280 * @addr: Real or absolute address of the page to be unshared
281 */
uv_remove_shared(unsigned long addr)282 static inline int uv_remove_shared(unsigned long addr)
283 {
284 return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS);
285 }
286
uv_cmd_nodata(uint64_t handle,uint16_t cmd,uint16_t * rc,uint16_t * rrc)287 static inline int uv_cmd_nodata(uint64_t handle, uint16_t cmd, uint16_t *rc, uint16_t *rrc)
288 {
289 struct uv_cb_nodata uvcb = {
290 .header.cmd = cmd,
291 .header.len = sizeof(uvcb),
292 .handle = handle,
293 };
294 int cc;
295
296 assert(handle);
297 cc = uv_call(0, (uint64_t)&uvcb);
298 *rc = uvcb.header.rc;
299 *rrc = uvcb.header.rrc;
300 return cc;
301 }
302
uv_import(uint64_t handle,unsigned long gaddr)303 static inline int uv_import(uint64_t handle, unsigned long gaddr)
304 {
305 struct uv_cb_cts uvcb = {
306 .header.cmd = UVC_CMD_CONV_TO_SEC_STOR,
307 .header.len = sizeof(uvcb),
308 .guest_handle = handle,
309 .gaddr = gaddr,
310 };
311
312 return uv_call(0, (uint64_t)&uvcb);
313 }
314
uv_export(unsigned long paddr)315 static inline int uv_export(unsigned long paddr)
316 {
317 struct uv_cb_cfs uvcb = {
318 .header.cmd = UVC_CMD_CONV_FROM_SEC_STOR,
319 .header.len = sizeof(uvcb),
320 .paddr = paddr
321 };
322
323 return uv_call(0, (u64)&uvcb);
324 }
325
326 /*
327 * Requests the Ultravisor to destroy a guest page and make it
328 * accessible to the host. The destroy clears the page instead of
329 * exporting.
330 *
331 * @paddr: Absolute host address of page to be destroyed
332 */
uv_destroy_page(unsigned long paddr)333 static inline int uv_destroy_page(unsigned long paddr)
334 {
335 struct uv_cb_cfs uvcb = {
336 .header.cmd = UVC_CMD_DESTR_SEC_STOR,
337 .header.len = sizeof(uvcb),
338 .paddr = paddr
339 };
340
341 return uv_call(0, (uint64_t)&uvcb);
342 }
343
344 struct uv_cb_cpu_set_state {
345 struct uv_cb_header header;
346 u64 reserved08[2];
347 u64 cpu_handle;
348 u8 reserved20[7];
349 u8 state;
350 u64 reserved28[5];
351 };
352
353 #define PV_CPU_STATE_OPR 1
354 #define PV_CPU_STATE_STP 2
355 #define PV_CPU_STATE_CHKSTP 3
356 #define PV_CPU_STATE_OPR_LOAD 5
357
uv_set_cpu_state(uint64_t handle,uint8_t state)358 static inline int uv_set_cpu_state(uint64_t handle, uint8_t state)
359 {
360 struct uv_cb_cpu_set_state uvcb = {
361 .header.cmd = UVC_CMD_CPU_SET_STATE,
362 .header.len = sizeof(uvcb),
363 .cpu_handle = handle,
364 .state = state,
365 };
366
367 assert(handle);
368 return uv_call(0, (uint64_t)&uvcb);
369 }
370
uv_set_se_hdr(uint64_t handle,void * hdr,size_t len)371 static inline int uv_set_se_hdr(uint64_t handle, void *hdr, size_t len)
372 {
373 struct uv_cb_ssc uvcb = {
374 .header.cmd = UVC_CMD_SET_SEC_CONF_PARAMS,
375 .header.len = sizeof(uvcb),
376 .sec_header_origin = (uint64_t)hdr,
377 .sec_header_len = len,
378 .guest_handle = handle,
379 };
380
381 assert(handle);
382 return uv_call(0, (uint64_t)&uvcb);
383 }
384
uv_unp_page(uint64_t handle,uint64_t gaddr,uint64_t tweak1,uint64_t tweak2)385 static inline int uv_unp_page(uint64_t handle, uint64_t gaddr, uint64_t tweak1, uint64_t tweak2)
386 {
387 struct uv_cb_unp uvcb = {
388 .header.cmd = UVC_CMD_UNPACK_IMG,
389 .header.len = sizeof(uvcb),
390 .guest_handle = handle,
391 .gaddr = gaddr,
392 .tweak[0] = tweak1,
393 .tweak[1] = tweak2,
394 };
395
396 return uv_call(0, (uint64_t)&uvcb);
397 }
398
399 #endif
400