]> Git Repo - qemu.git/blame - target/i386/sev.c
kvm/i386: Use a per-VM check for SMM capability
[qemu.git] / target / i386 / sev.c
CommitLineData
a9b4942f
BS
1/*
2 * QEMU SEV support
3 *
4 * Copyright Advanced Micro Devices 2016-2018
5 *
6 * Author:
7 * Brijesh Singh <[email protected]>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 *
12 */
13
b7d89466
MA
14#include "qemu/osdep.h"
15
d8575c6c
BS
16#include <linux/kvm.h>
17#include <linux/psp-sev.h>
18
19#include <sys/ioctl.h>
20
a9b4942f
BS
21#include "qapi/error.h"
22#include "qom/object_interfaces.h"
23#include "qemu/base64.h"
0b8fa32f 24#include "qemu/module.h"
b2f73a07 25#include "qemu/uuid.h"
a9b4942f
BS
26#include "sysemu/kvm.h"
27#include "sev_i386.h"
28#include "sysemu/sysemu.h"
54d31236 29#include "sysemu/runstate.h"
d8575c6c 30#include "trace.h"
8fa4466d 31#include "migration/blocker.h"
db1015e9 32#include "qom/object.h"
c7f7e697
TFF
33#include "exec/address-spaces.h"
34#include "monitor/monitor.h"
f91f9f25 35#include "exec/confidential-guest-support.h"
b2f73a07 36#include "hw/i386/pc.h"
a9b4942f 37
d2d8a198 38#define TYPE_SEV_GUEST "sev-guest"
8063396b 39OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST)
a86ab19d 40
a86ab19d
DG
41
42/**
d2d8a198 43 * SevGuestState:
a86ab19d 44 *
d2d8a198
DG
45 * The SevGuestState object is used for creating and managing a SEV
46 * guest.
a86ab19d
DG
47 *
48 * # $QEMU \
49 * -object sev-guest,id=sev0 \
50 * -machine ...,memory-encryption=sev0
51 */
d2d8a198 52struct SevGuestState {
f91f9f25 53 ConfidentialGuestSupport parent_obj;
a86ab19d 54
75a877e3 55 /* configuration parameters */
a86ab19d
DG
56 char *sev_device;
57 uint32_t policy;
a86ab19d
DG
58 char *dh_cert_file;
59 char *session_file;
60 uint32_t cbitpos;
61 uint32_t reduced_phys_bits;
a86ab19d 62
75a877e3 63 /* runtime state */
cf504cd6 64 uint32_t handle;
421522eb
DG
65 uint8_t api_major;
66 uint8_t api_minor;
67 uint8_t build_id;
68 uint64_t me_mask;
69 int sev_fd;
70 SevState state;
71 gchar *measurement;
b2f73a07
PB
72
73 uint32_t reset_cs;
74 uint32_t reset_ip;
75 bool reset_data_valid;
a86ab19d
DG
76};
77
a9b4942f
BS
78#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
79#define DEFAULT_SEV_DEVICE "/dev/sev"
80
b2f73a07
PB
81#define SEV_INFO_BLOCK_GUID "00f771de-1a7e-4fcb-890e-68c77e2fb44e"
82typedef struct __attribute__((__packed__)) SevInfoBlock {
83 /* SEV-ES Reset Vector Address */
84 uint32_t reset_addr;
85} SevInfoBlock;
86
8673dee3 87static SevGuestState *sev_guest;
8fa4466d 88static Error *sev_mig_blocker;
d8575c6c
BS
89
90static const char *const sev_fw_errlist[] = {
91 "",
92 "Platform state is invalid",
93 "Guest state is invalid",
94 "Platform configuration is invalid",
95 "Buffer too small",
96 "Platform is already owned",
97 "Certificate is invalid",
98 "Policy is not allowed",
99 "Guest is not active",
100 "Invalid address",
101 "Bad signature",
102 "Bad measurement",
103 "Asid is already owned",
104 "Invalid ASID",
105 "WBINVD is required",
106 "DF_FLUSH is required",
107 "Guest handle is invalid",
108 "Invalid command",
109 "Guest is active",
110 "Hardware error",
111 "Hardware unsafe",
112 "Feature not supported",
113 "Invalid parameter"
114};
115
116#define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
117
118static int
119sev_ioctl(int fd, int cmd, void *data, int *error)
120{
121 int r;
122 struct kvm_sev_cmd input;
123
124 memset(&input, 0x0, sizeof(input));
125
126 input.id = cmd;
127 input.sev_fd = fd;
128 input.data = (__u64)(unsigned long)data;
129
130 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
131
132 if (error) {
133 *error = input.error;
134 }
135
136 return r;
137}
138
139static int
140sev_platform_ioctl(int fd, int cmd, void *data, int *error)
141{
142 int r;
143 struct sev_issue_cmd arg;
144
145 arg.cmd = cmd;
146 arg.data = (unsigned long)data;
147 r = ioctl(fd, SEV_ISSUE_CMD, &arg);
148 if (error) {
149 *error = arg.error;
150 }
151
152 return r;
153}
154
155static const char *
156fw_error_to_str(int code)
157{
158 if (code < 0 || code >= SEV_FW_MAX_ERROR) {
159 return "unknown error";
160 }
161
162 return sev_fw_errlist[code];
163}
164
b738d630 165static bool
8673dee3 166sev_check_state(const SevGuestState *sev, SevState state)
b738d630 167{
8673dee3 168 assert(sev);
421522eb 169 return sev->state == state ? true : false;
b738d630
BS
170}
171
620fd55c 172static void
8673dee3 173sev_set_guest_state(SevGuestState *sev, SevState new_state)
620fd55c
BS
174{
175 assert(new_state < SEV_STATE__MAX);
8673dee3 176 assert(sev);
620fd55c 177
421522eb 178 trace_kvm_sev_change_state(SevState_str(sev->state),
620fd55c 179 SevState_str(new_state));
421522eb 180 sev->state = new_state;
620fd55c
BS
181}
182
2b308e44
BS
183static void
184sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
185{
186 int r;
187 struct kvm_enc_region range;
cedc0ad5
BS
188 ram_addr_t offset;
189 MemoryRegion *mr;
190
191 /*
192 * The RAM device presents a memory region that should be treated
193 * as IO region and should not be pinned.
194 */
195 mr = memory_region_from_host(host, &offset);
196 if (mr && memory_region_is_ram_device(mr)) {
197 return;
198 }
2b308e44
BS
199
200 range.addr = (__u64)(unsigned long)host;
201 range.size = size;
202
203 trace_kvm_memcrypt_register_region(host, size);
204 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
205 if (r) {
206 error_report("%s: failed to register region (%p+%#zx) error '%s'",
207 __func__, host, size, strerror(errno));
208 exit(1);
209 }
210}
211
212static void
213sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
214{
215 int r;
216 struct kvm_enc_region range;
56e2ec94
AW
217 ram_addr_t offset;
218 MemoryRegion *mr;
219
220 /*
221 * The RAM device presents a memory region that should be treated
222 * as IO region and should not have been pinned.
223 */
224 mr = memory_region_from_host(host, &offset);
225 if (mr && memory_region_is_ram_device(mr)) {
226 return;
227 }
2b308e44
BS
228
229 range.addr = (__u64)(unsigned long)host;
230 range.size = size;
231
232 trace_kvm_memcrypt_unregister_region(host, size);
233 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
234 if (r) {
235 error_report("%s: failed to unregister region (%p+%#zx)",
236 __func__, host, size);
237 }
238}
239
240static struct RAMBlockNotifier sev_ram_notifier = {
241 .ram_block_added = sev_ram_block_added,
242 .ram_block_removed = sev_ram_block_removed,
243};
244
a9b4942f 245static void
d2d8a198 246sev_guest_finalize(Object *obj)
a9b4942f
BS
247{
248}
249
250static char *
d2d8a198 251sev_guest_get_session_file(Object *obj, Error **errp)
a9b4942f 252{
d2d8a198 253 SevGuestState *s = SEV_GUEST(obj);
a9b4942f
BS
254
255 return s->session_file ? g_strdup(s->session_file) : NULL;
256}
257
258static void
d2d8a198 259sev_guest_set_session_file(Object *obj, const char *value, Error **errp)
a9b4942f 260{
d2d8a198 261 SevGuestState *s = SEV_GUEST(obj);
a9b4942f
BS
262
263 s->session_file = g_strdup(value);
264}
265
266static char *
d2d8a198 267sev_guest_get_dh_cert_file(Object *obj, Error **errp)
a9b4942f 268{
d2d8a198 269 SevGuestState *s = SEV_GUEST(obj);
a9b4942f
BS
270
271 return g_strdup(s->dh_cert_file);
272}
273
274static void
d2d8a198 275sev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
a9b4942f 276{
d2d8a198 277 SevGuestState *s = SEV_GUEST(obj);
a9b4942f
BS
278
279 s->dh_cert_file = g_strdup(value);
280}
281
282static char *
d2d8a198 283sev_guest_get_sev_device(Object *obj, Error **errp)
a9b4942f 284{
d2d8a198 285 SevGuestState *sev = SEV_GUEST(obj);
a9b4942f
BS
286
287 return g_strdup(sev->sev_device);
288}
289
290static void
d2d8a198 291sev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
a9b4942f 292{
d2d8a198 293 SevGuestState *sev = SEV_GUEST(obj);
a9b4942f
BS
294
295 sev->sev_device = g_strdup(value);
296}
297
298static void
d2d8a198 299sev_guest_class_init(ObjectClass *oc, void *data)
a9b4942f
BS
300{
301 object_class_property_add_str(oc, "sev-device",
d2d8a198
DG
302 sev_guest_get_sev_device,
303 sev_guest_set_sev_device);
a9b4942f 304 object_class_property_set_description(oc, "sev-device",
7eecec7d 305 "SEV device to use");
a9b4942f 306 object_class_property_add_str(oc, "dh-cert-file",
d2d8a198
DG
307 sev_guest_get_dh_cert_file,
308 sev_guest_set_dh_cert_file);
a9b4942f 309 object_class_property_set_description(oc, "dh-cert-file",
7eecec7d 310 "guest owners DH certificate (encoded with base64)");
a9b4942f 311 object_class_property_add_str(oc, "session-file",
d2d8a198
DG
312 sev_guest_get_session_file,
313 sev_guest_set_session_file);
a9b4942f 314 object_class_property_set_description(oc, "session-file",
7eecec7d 315 "guest owners session parameters (encoded with base64)");
a9b4942f
BS
316}
317
a9b4942f 318static void
d2d8a198 319sev_guest_instance_init(Object *obj)
a9b4942f 320{
d2d8a198 321 SevGuestState *sev = SEV_GUEST(obj);
a9b4942f
BS
322
323 sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
324 sev->policy = DEFAULT_GUEST_POLICY;
64a7b8de 325 object_property_add_uint32_ptr(obj, "policy", &sev->policy,
d2623129 326 OBJ_PROP_FLAG_READWRITE);
64a7b8de 327 object_property_add_uint32_ptr(obj, "handle", &sev->handle,
d2623129 328 OBJ_PROP_FLAG_READWRITE);
64a7b8de 329 object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos,
d2623129 330 OBJ_PROP_FLAG_READWRITE);
64a7b8de
FF
331 object_property_add_uint32_ptr(obj, "reduced-phys-bits",
332 &sev->reduced_phys_bits,
d2623129 333 OBJ_PROP_FLAG_READWRITE);
a9b4942f
BS
334}
335
336/* sev guest info */
d2d8a198 337static const TypeInfo sev_guest_info = {
f91f9f25 338 .parent = TYPE_CONFIDENTIAL_GUEST_SUPPORT,
d2d8a198
DG
339 .name = TYPE_SEV_GUEST,
340 .instance_size = sizeof(SevGuestState),
341 .instance_finalize = sev_guest_finalize,
342 .class_init = sev_guest_class_init,
343 .instance_init = sev_guest_instance_init,
a9b4942f
BS
344 .interfaces = (InterfaceInfo[]) {
345 { TYPE_USER_CREATABLE },
346 { }
347 }
348};
349
d8575c6c
BS
350bool
351sev_enabled(void)
352{
8673dee3 353 return !!sev_guest;
d8575c6c
BS
354}
355
6b98e96f
TL
356bool
357sev_es_enabled(void)
358{
359 return false;
360}
361
d8575c6c
BS
362uint64_t
363sev_get_me_mask(void)
364{
421522eb 365 return sev_guest ? sev_guest->me_mask : ~0;
d8575c6c
BS
366}
367
368uint32_t
369sev_get_cbit_position(void)
370{
a06d2bad 371 return sev_guest ? sev_guest->cbitpos : 0;
d8575c6c
BS
372}
373
374uint32_t
375sev_get_reduced_phys_bits(void)
376{
a06d2bad 377 return sev_guest ? sev_guest->reduced_phys_bits : 0;
d8575c6c
BS
378}
379
380SevInfo *
381sev_get_info(void)
382{
383 SevInfo *info;
384
385 info = g_new0(SevInfo, 1);
8673dee3 386 info->enabled = sev_enabled();
d8575c6c
BS
387
388 if (info->enabled) {
421522eb
DG
389 info->api_major = sev_guest->api_major;
390 info->api_minor = sev_guest->api_minor;
391 info->build_id = sev_guest->build_id;
0bd15277 392 info->policy = sev_guest->policy;
421522eb 393 info->state = sev_guest->state;
cf504cd6 394 info->handle = sev_guest->handle;
d8575c6c
BS
395 }
396
397 return info;
398}
399
9f750794
BS
400static int
401sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
e4f62785 402 size_t *cert_chain_len, Error **errp)
9f750794 403{
bf3175b4
PB
404 guchar *pdh_data = NULL;
405 guchar *cert_chain_data = NULL;
9f750794
BS
406 struct sev_user_data_pdh_cert_export export = {};
407 int err, r;
408
409 /* query the certificate length */
410 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
411 if (r < 0) {
412 if (err != SEV_RET_INVALID_LEN) {
e4f62785
PB
413 error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
414 r, err, fw_error_to_str(err));
9f750794
BS
415 return 1;
416 }
417 }
418
419 pdh_data = g_new(guchar, export.pdh_cert_len);
420 cert_chain_data = g_new(guchar, export.cert_chain_len);
421 export.pdh_cert_address = (unsigned long)pdh_data;
422 export.cert_chain_address = (unsigned long)cert_chain_data;
423
424 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
425 if (r < 0) {
e4f62785
PB
426 error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
427 r, err, fw_error_to_str(err));
9f750794
BS
428 goto e_free;
429 }
430
431 *pdh = pdh_data;
432 *pdh_len = export.pdh_cert_len;
433 *cert_chain = cert_chain_data;
434 *cert_chain_len = export.cert_chain_len;
435 return 0;
436
437e_free:
438 g_free(pdh_data);
439 g_free(cert_chain_data);
440 return 1;
441}
442
443SevCapability *
e4f62785 444sev_get_capabilities(Error **errp)
9f750794 445{
bf3175b4
PB
446 SevCapability *cap = NULL;
447 guchar *pdh_data = NULL;
448 guchar *cert_chain_data = NULL;
9f750794
BS
449 size_t pdh_len = 0, cert_chain_len = 0;
450 uint32_t ebx;
451 int fd;
452
1b38750c
PB
453 if (!kvm_enabled()) {
454 error_setg(errp, "KVM not enabled");
455 return NULL;
456 }
457 if (kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, NULL) < 0) {
458 error_setg(errp, "SEV is not enabled in KVM");
459 return NULL;
460 }
461
9f750794
BS
462 fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
463 if (fd < 0) {
e4f62785
PB
464 error_setg_errno(errp, errno, "Failed to open %s",
465 DEFAULT_SEV_DEVICE);
9f750794
BS
466 return NULL;
467 }
468
469 if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
e4f62785 470 &cert_chain_data, &cert_chain_len, errp)) {
bf3175b4 471 goto out;
9f750794
BS
472 }
473
474 cap = g_new0(SevCapability, 1);
475 cap->pdh = g_base64_encode(pdh_data, pdh_len);
476 cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
477
478 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
479 cap->cbitpos = ebx & 0x3f;
480
481 /*
482 * When SEV feature is enabled, we loose one bit in guest physical
483 * addressing.
484 */
485 cap->reduced_phys_bits = 1;
486
bf3175b4 487out:
9f750794
BS
488 g_free(pdh_data);
489 g_free(cert_chain_data);
9f750794
BS
490 close(fd);
491 return cap;
492}
493
620fd55c
BS
494static int
495sev_read_file_base64(const char *filename, guchar **data, gsize *len)
496{
497 gsize sz;
498 gchar *base64;
499 GError *error = NULL;
500
501 if (!g_file_get_contents(filename, &base64, &sz, &error)) {
502 error_report("failed to read '%s' (%s)", filename, error->message);
efacd5b8 503 g_error_free(error);
620fd55c
BS
504 return -1;
505 }
506
507 *data = g_base64_decode(base64, len);
508 return 0;
509}
510
511static int
75a877e3 512sev_launch_start(SevGuestState *sev)
620fd55c
BS
513{
514 gsize sz;
515 int ret = 1;
bf3175b4 516 int fw_error, rc;
620fd55c
BS
517 struct kvm_sev_launch_start *start;
518 guchar *session = NULL, *dh_cert = NULL;
519
520 start = g_new0(struct kvm_sev_launch_start, 1);
521
cf504cd6 522 start->handle = sev->handle;
0bd15277 523 start->policy = sev->policy;
620fd55c
BS
524 if (sev->session_file) {
525 if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
bf3175b4 526 goto out;
620fd55c
BS
527 }
528 start->session_uaddr = (unsigned long)session;
529 start->session_len = sz;
530 }
531
532 if (sev->dh_cert_file) {
533 if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
bf3175b4 534 goto out;
620fd55c
BS
535 }
536 start->dh_uaddr = (unsigned long)dh_cert;
537 start->dh_len = sz;
538 }
539
540 trace_kvm_sev_launch_start(start->policy, session, dh_cert);
421522eb 541 rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
bf3175b4 542 if (rc < 0) {
620fd55c
BS
543 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
544 __func__, ret, fw_error, fw_error_to_str(fw_error));
bf3175b4 545 goto out;
620fd55c
BS
546 }
547
8673dee3 548 sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE);
cf504cd6 549 sev->handle = start->handle;
bf3175b4 550 ret = 0;
620fd55c 551
bf3175b4 552out:
620fd55c
BS
553 g_free(start);
554 g_free(session);
555 g_free(dh_cert);
bf3175b4 556 return ret;
620fd55c
BS
557}
558
b738d630 559static int
8673dee3 560sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len)
b738d630
BS
561{
562 int ret, fw_error;
563 struct kvm_sev_launch_update_data update;
564
565 if (!addr || !len) {
566 return 1;
567 }
568
569 update.uaddr = (__u64)(unsigned long)addr;
570 update.len = len;
571 trace_kvm_sev_launch_update_data(addr, len);
421522eb 572 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
b738d630
BS
573 &update, &fw_error);
574 if (ret) {
575 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
576 __func__, ret, fw_error, fw_error_to_str(fw_error));
577 }
578
579 return ret;
580}
581
6b98e96f
TL
582static int
583sev_launch_update_vmsa(SevGuestState *sev)
584{
585 int ret, fw_error;
586
587 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_VMSA, NULL, &fw_error);
588 if (ret) {
589 error_report("%s: LAUNCH_UPDATE_VMSA ret=%d fw_error=%d '%s'",
590 __func__, ret, fw_error, fw_error_to_str(fw_error));
591 }
592
593 return ret;
594}
595
c6c89c97
BS
596static void
597sev_launch_get_measure(Notifier *notifier, void *unused)
598{
8673dee3 599 SevGuestState *sev = sev_guest;
c6c89c97
BS
600 int ret, error;
601 guchar *data;
c6c89c97
BS
602 struct kvm_sev_launch_measure *measurement;
603
8673dee3 604 if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
c6c89c97
BS
605 return;
606 }
607
6b98e96f
TL
608 if (sev_es_enabled()) {
609 /* measure all the VM save areas before getting launch_measure */
610 ret = sev_launch_update_vmsa(sev);
611 if (ret) {
612 exit(1);
613 }
614 }
615
c6c89c97
BS
616 measurement = g_new0(struct kvm_sev_launch_measure, 1);
617
618 /* query the measurement blob length */
421522eb 619 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
c6c89c97
BS
620 measurement, &error);
621 if (!measurement->len) {
622 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
623 __func__, ret, error, fw_error_to_str(errno));
624 goto free_measurement;
625 }
626
627 data = g_new0(guchar, measurement->len);
628 measurement->uaddr = (unsigned long)data;
629
630 /* get the measurement blob */
421522eb 631 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
c6c89c97
BS
632 measurement, &error);
633 if (ret) {
634 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
635 __func__, ret, error, fw_error_to_str(errno));
636 goto free_data;
637 }
638
8673dee3 639 sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET);
c6c89c97
BS
640
641 /* encode the measurement value and emit the event */
421522eb
DG
642 sev->measurement = g_base64_encode(data, measurement->len);
643 trace_kvm_sev_launch_measurement(sev->measurement);
c6c89c97
BS
644
645free_data:
646 g_free(data);
647free_measurement:
648 g_free(measurement);
649}
650
651char *
652sev_get_launch_measurement(void)
653{
8673dee3 654 if (sev_guest &&
421522eb
DG
655 sev_guest->state >= SEV_STATE_LAUNCH_SECRET) {
656 return g_strdup(sev_guest->measurement);
c6c89c97
BS
657 }
658
659 return NULL;
660}
661
662static Notifier sev_machine_done_notify = {
663 .notify = sev_launch_get_measure,
664};
665
5dd0df7e 666static void
8673dee3 667sev_launch_finish(SevGuestState *sev)
5dd0df7e
BS
668{
669 int ret, error;
8fa4466d 670 Error *local_err = NULL;
5dd0df7e
BS
671
672 trace_kvm_sev_launch_finish();
421522eb 673 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
5dd0df7e
BS
674 if (ret) {
675 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
676 __func__, ret, error, fw_error_to_str(error));
677 exit(1);
678 }
679
8673dee3 680 sev_set_guest_state(sev, SEV_STATE_RUNNING);
8fa4466d
BS
681
682 /* add migration blocker */
683 error_setg(&sev_mig_blocker,
684 "SEV: Migration is not implemented");
685 ret = migrate_add_blocker(sev_mig_blocker, &local_err);
686 if (local_err) {
687 error_report_err(local_err);
688 error_free(sev_mig_blocker);
689 exit(1);
690 }
5dd0df7e
BS
691}
692
693static void
694sev_vm_state_change(void *opaque, int running, RunState state)
695{
8673dee3 696 SevGuestState *sev = opaque;
5dd0df7e
BS
697
698 if (running) {
8673dee3
DG
699 if (!sev_check_state(sev, SEV_STATE_RUNNING)) {
700 sev_launch_finish(sev);
5dd0df7e
BS
701 }
702 }
703}
704
c9f5aaa6 705int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
d8575c6c 706{
ec78e2cd
DG
707 SevGuestState *sev
708 = (SevGuestState *)object_dynamic_cast(OBJECT(cgs), TYPE_SEV_GUEST);
d8575c6c 709 char *devname;
6b98e96f 710 int ret, fw_error, cmd;
d8575c6c
BS
711 uint32_t ebx;
712 uint32_t host_cbitpos;
713 struct sev_user_data_status status = {};
714
ec78e2cd
DG
715 if (!sev) {
716 return 0;
717 }
718
fee3f3ba
DH
719 ret = ram_block_discard_disable(true);
720 if (ret) {
721 error_report("%s: cannot disable RAM discard", __func__);
aacdb844 722 return -1;
fee3f3ba
DH
723 }
724
8673dee3 725 sev_guest = sev;
421522eb 726 sev->state = SEV_STATE_UNINIT;
d8575c6c
BS
727
728 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
729 host_cbitpos = ebx & 0x3f;
730
a06d2bad 731 if (host_cbitpos != sev->cbitpos) {
c9f5aaa6
DG
732 error_setg(errp, "%s: cbitpos check failed, host '%d' requested '%d'",
733 __func__, host_cbitpos, sev->cbitpos);
d8575c6c
BS
734 goto err;
735 }
736
a06d2bad 737 if (sev->reduced_phys_bits < 1) {
c9f5aaa6
DG
738 error_setg(errp, "%s: reduced_phys_bits check failed, it should be >=1,"
739 " requested '%d'", __func__, sev->reduced_phys_bits);
d8575c6c
BS
740 goto err;
741 }
742
421522eb 743 sev->me_mask = ~(1UL << sev->cbitpos);
d8575c6c 744
75a877e3 745 devname = object_property_get_str(OBJECT(sev), "sev-device", NULL);
421522eb
DG
746 sev->sev_fd = open(devname, O_RDWR);
747 if (sev->sev_fd < 0) {
c9f5aaa6
DG
748 error_setg(errp, "%s: Failed to open %s '%s'", __func__,
749 devname, strerror(errno));
750 g_free(devname);
5d7bc72a
GK
751 goto err;
752 }
c9f5aaa6 753 g_free(devname);
d8575c6c 754
421522eb 755 ret = sev_platform_ioctl(sev->sev_fd, SEV_PLATFORM_STATUS, &status,
d8575c6c
BS
756 &fw_error);
757 if (ret) {
c9f5aaa6
DG
758 error_setg(errp, "%s: failed to get platform status ret=%d "
759 "fw_error='%d: %s'", __func__, ret, fw_error,
760 fw_error_to_str(fw_error));
d8575c6c
BS
761 goto err;
762 }
421522eb
DG
763 sev->build_id = status.build;
764 sev->api_major = status.api_major;
765 sev->api_minor = status.api_minor;
d8575c6c 766
6b98e96f 767 if (sev_es_enabled()) {
9681f867
TL
768 if (!kvm_kernel_irqchip_allowed()) {
769 error_report("%s: SEV-ES guests require in-kernel irqchip support",
770 __func__);
771 goto err;
772 }
773
6b98e96f
TL
774 if (!(status.flags & SEV_STATUS_FLAGS_CONFIG_ES)) {
775 error_report("%s: guest policy requires SEV-ES, but "
776 "host SEV-ES support unavailable",
777 __func__);
778 goto err;
779 }
780 cmd = KVM_SEV_ES_INIT;
781 } else {
782 cmd = KVM_SEV_INIT;
783 }
784
d8575c6c 785 trace_kvm_sev_init();
6b98e96f 786 ret = sev_ioctl(sev->sev_fd, cmd, NULL, &fw_error);
d8575c6c 787 if (ret) {
c9f5aaa6
DG
788 error_setg(errp, "%s: failed to initialize ret=%d fw_error=%d '%s'",
789 __func__, ret, fw_error, fw_error_to_str(fw_error));
d8575c6c
BS
790 goto err;
791 }
792
75a877e3 793 ret = sev_launch_start(sev);
620fd55c 794 if (ret) {
c9f5aaa6 795 error_setg(errp, "%s: failed to create encryption context", __func__);
620fd55c
BS
796 goto err;
797 }
798
2b308e44 799 ram_block_notifier_add(&sev_ram_notifier);
c6c89c97 800 qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
8673dee3 801 qemu_add_vm_change_state_handler(sev_vm_state_change, sev);
2b308e44 802
abc27d42
DG
803 cgs->ready = true;
804
aacdb844 805 return 0;
d8575c6c 806err:
8673dee3 807 sev_guest = NULL;
fee3f3ba 808 ram_block_discard_disable(false);
aacdb844 809 return -1;
d8575c6c
BS
810}
811
b738d630 812int
aacdb844 813sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
b738d630 814{
aacdb844
DG
815 if (!sev_guest) {
816 return 0;
817 }
b738d630
BS
818
819 /* if SEV is in update state then encrypt the data else do nothing */
aacdb844
DG
820 if (sev_check_state(sev_guest, SEV_STATE_LAUNCH_UPDATE)) {
821 int ret = sev_launch_update_data(sev_guest, ptr, len);
822 if (ret < 0) {
823 error_setg(errp, "failed to encrypt pflash rom");
824 return ret;
825 }
b738d630
BS
826 }
827
828 return 0;
829}
830
c7f7e697
TFF
831int sev_inject_launch_secret(const char *packet_hdr, const char *secret,
832 uint64_t gpa, Error **errp)
833{
834 struct kvm_sev_launch_secret input;
835 g_autofree guchar *data = NULL, *hdr = NULL;
836 int error, ret = 1;
837 void *hva;
838 gsize hdr_sz = 0, data_sz = 0;
839 MemoryRegion *mr = NULL;
840
841 if (!sev_guest) {
842 error_setg(errp, "SEV: SEV not enabled.");
843 return 1;
844 }
845
846 /* secret can be injected only in this state */
847 if (!sev_check_state(sev_guest, SEV_STATE_LAUNCH_SECRET)) {
848 error_setg(errp, "SEV: Not in correct state. (LSECRET) %x",
849 sev_guest->state);
850 return 1;
851 }
852
853 hdr = g_base64_decode(packet_hdr, &hdr_sz);
854 if (!hdr || !hdr_sz) {
855 error_setg(errp, "SEV: Failed to decode sequence header");
856 return 1;
857 }
858
859 data = g_base64_decode(secret, &data_sz);
860 if (!data || !data_sz) {
861 error_setg(errp, "SEV: Failed to decode data");
862 return 1;
863 }
864
865 hva = gpa2hva(&mr, gpa, data_sz, errp);
866 if (!hva) {
867 error_prepend(errp, "SEV: Failed to calculate guest address: ");
868 return 1;
869 }
870
871 input.hdr_uaddr = (uint64_t)(unsigned long)hdr;
872 input.hdr_len = hdr_sz;
873
874 input.trans_uaddr = (uint64_t)(unsigned long)data;
875 input.trans_len = data_sz;
876
877 input.guest_uaddr = (uint64_t)(unsigned long)hva;
878 input.guest_len = data_sz;
879
880 trace_kvm_sev_launch_secret(gpa, input.guest_uaddr,
881 input.trans_uaddr, input.trans_len);
882
883 ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_LAUNCH_SECRET,
884 &input, &error);
885 if (ret) {
886 error_setg(errp, "SEV: failed to inject secret ret=%d fw_error=%d '%s'",
887 ret, error, fw_error_to_str(error));
888 return ret;
889 }
890
891 return 0;
892}
893
b2f73a07
PB
894static int
895sev_es_parse_reset_block(SevInfoBlock *info, uint32_t *addr)
896{
897 if (!info->reset_addr) {
898 error_report("SEV-ES reset address is zero");
899 return 1;
900 }
901
902 *addr = info->reset_addr;
903
904 return 0;
905}
906
907static int
908sev_es_find_reset_vector(void *flash_ptr, uint64_t flash_size,
909 uint32_t *addr)
910{
911 QemuUUID info_guid, *guid;
912 SevInfoBlock *info;
913 uint8_t *data;
914 uint16_t *len;
915
916 /*
917 * Initialize the address to zero. An address of zero with a successful
918 * return code indicates that SEV-ES is not active.
919 */
920 *addr = 0;
921
922 /*
923 * Extract the AP reset vector for SEV-ES guests by locating the SEV GUID.
924 * The SEV GUID is located on its own (original implementation) or within
925 * the Firmware GUID Table (new implementation), either of which are
926 * located 32 bytes from the end of the flash.
927 *
928 * Check the Firmware GUID Table first.
929 */
930 if (pc_system_ovmf_table_find(SEV_INFO_BLOCK_GUID, &data, NULL)) {
931 return sev_es_parse_reset_block((SevInfoBlock *)data, addr);
932 }
933
934 /*
935 * SEV info block not found in the Firmware GUID Table (or there isn't
936 * a Firmware GUID Table), fall back to the original implementation.
937 */
938 data = flash_ptr + flash_size - 0x20;
939
940 qemu_uuid_parse(SEV_INFO_BLOCK_GUID, &info_guid);
941 info_guid = qemu_uuid_bswap(info_guid); /* GUIDs are LE */
942
943 guid = (QemuUUID *)(data - sizeof(info_guid));
944 if (!qemu_uuid_is_equal(guid, &info_guid)) {
945 error_report("SEV information block/Firmware GUID Table block not found in pflash rom");
946 return 1;
947 }
948
949 len = (uint16_t *)((uint8_t *)guid - sizeof(*len));
950 info = (SevInfoBlock *)(data - le16_to_cpu(*len));
951
952 return sev_es_parse_reset_block(info, addr);
953}
954
955void sev_es_set_reset_vector(CPUState *cpu)
956{
957 X86CPU *x86;
958 CPUX86State *env;
959
960 /* Only update if we have valid reset information */
961 if (!sev_guest || !sev_guest->reset_data_valid) {
962 return;
963 }
964
965 /* Do not update the BSP reset state */
966 if (cpu->cpu_index == 0) {
967 return;
968 }
969
970 x86 = X86_CPU(cpu);
971 env = &x86->env;
972
973 cpu_x86_load_seg_cache(env, R_CS, 0xf000, sev_guest->reset_cs, 0xffff,
974 DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
975 DESC_R_MASK | DESC_A_MASK);
976
977 env->eip = sev_guest->reset_ip;
978}
979
980int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size)
981{
982 CPUState *cpu;
983 uint32_t addr;
984 int ret;
985
986 if (!sev_es_enabled()) {
987 return 0;
988 }
989
990 addr = 0;
991 ret = sev_es_find_reset_vector(flash_ptr, flash_size,
992 &addr);
993 if (ret) {
994 return ret;
995 }
996
997 if (addr) {
998 sev_guest->reset_cs = addr & 0xffff0000;
999 sev_guest->reset_ip = addr & 0x0000ffff;
1000 sev_guest->reset_data_valid = true;
1001
1002 CPU_FOREACH(cpu) {
1003 sev_es_set_reset_vector(cpu);
1004 }
1005 }
1006
1007 return 0;
1008}
1009
a9b4942f
BS
1010static void
1011sev_register_types(void)
1012{
d2d8a198 1013 type_register_static(&sev_guest_info);
a9b4942f
BS
1014}
1015
1016type_init(sev_register_types);
This page took 0.339993 seconds and 4 git commands to generate.