Skip to content

Commit

Permalink
sev: Provide VMSA to kvm via KVM_SEV_SNP_LAUNCH_UPDATE
Browse files Browse the repository at this point in the history
Previously the VMSA could not be set directly. Instead the current CPU
state was automatically populated into a VMSA within kvm as part of
KVM_SEV_SNP_LAUNCH_FINISH. This meant that it was hard to ensure the
VMSA provided by IGVM matched the resulting one in kvm.

KVM has been updated to allow the VMSA to be provided via
KVM_SEV_SNP_LAUNCH_UPDATE. In this case, kvm does not perform any
specific synchronisation during FINISH and the VMSA is guaranteed to
match that provided by QEMU.

Signed-off-by: Roy Hopkins <[email protected]>
  • Loading branch information
roy-hopkins committed Oct 3, 2024
1 parent 33cbd8b commit bcb7121
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 19 deletions.
30 changes: 26 additions & 4 deletions backends/igvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,8 @@ static int qigvm_directive_vp_context(QIgvm *ctx, const uint8_t *header_data,
(const IGVM_VHS_VP_CONTEXT *)header_data;
IgvmHandle data_handle;
uint8_t *data;
uint32_t data_size;
uint8_t *region;
int result;

if (!(vp_context->compatibility_mask & ctx->compatibility_mask)) {
Expand All @@ -437,19 +439,39 @@ static int qigvm_directive_vp_context(QIgvm *ctx, const uint8_t *header_data,
return -1;
}

data_handle = igvm_get_header_data(ctx->file, IGVM_HEADER_SECTION_DIRECTIVE,
ctx->current_header_index);
/*
* Complete any other page processing first to ensure measurements
* are correct.
*/
if (qigvm_process_mem_page(ctx, NULL, errp)) {
return -1;
}

data_handle = igvm_get_header_data(ctx->file,
IGVM_HEADER_SECTION_DIRECTIVE,
ctx->current_header_index);
if (data_handle < 0) {
error_setg(errp, "Invalid VP context in IGVM file. Error code: %X",
data_handle);
return -1;
}

data_size = igvm_get_buffer_size(ctx->file, data_handle);
data = (uint8_t *)igvm_get_buffer(ctx->file, data_handle);

region = qigvm_prepare_memory(ctx, vp_context->gpa, IGVM_PAGE_SIZE_4K,
ctx->current_header_index, errp);
if (!region) {
return -1;
}
memset(region, 0, IGVM_PAGE_SIZE_4K);

memcpy(region, data, data_size);
igvm_free_buffer(ctx->file, data_handle);

result = ctx->cgsc->set_guest_state(
vp_context->gpa, data, igvm_get_buffer_size(ctx->file, data_handle),
vp_context->gpa, region, IGVM_PAGE_SIZE_4K,
CGS_PAGE_TYPE_VMSA, vp_context->vp_index, errp);
igvm_free_buffer(ctx->file, data_handle);
if (result < 0) {
return result;
}
Expand Down
44 changes: 29 additions & 15 deletions target/i386/sev.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ typedef struct SevLaunchUpdateData {
hwaddr gpa;
void *hva;
size_t len;
int vcpu_id;
int type;
} SevLaunchUpdateData;

Expand Down Expand Up @@ -1170,6 +1171,7 @@ snp_page_type_to_str(int type)
{
switch (type) {
case KVM_SEV_SNP_PAGE_TYPE_NORMAL: return "Normal";
case KVM_SEV_SNP_PAGE_TYPE_VMSA: return "VMSA";
case KVM_SEV_SNP_PAGE_TYPE_ZERO: return "Zero";
case KVM_SEV_SNP_PAGE_TYPE_UNMEASURED: return "Unmeasured";
case KVM_SEV_SNP_PAGE_TYPE_SECRETS: return "Secrets";
Expand Down Expand Up @@ -1202,6 +1204,7 @@ sev_snp_launch_update(SevSnpGuestState *sev_snp_guest,
update.gfn_start = data->gpa >> TARGET_PAGE_BITS;
update.len = data->len;
update.type = data->type;
update.vcpu_id = data->vcpu_id;

/*
* KVM_SEV_SNP_LAUNCH_UPDATE requires that GPA ranges have the private
Expand Down Expand Up @@ -1435,7 +1438,7 @@ sev_launch_finish(SevCommonState *sev_common)
}

static int snp_launch_update_data(uint64_t gpa, void *hva, size_t len,
int type, Error **errp)
int type, int vcpu_id, Error **errp)
{
SevLaunchUpdateData *data;

Expand All @@ -1444,6 +1447,7 @@ static int snp_launch_update_data(uint64_t gpa, void *hva, size_t len,
data->hva = hva;
data->len = len;
data->type = type;
data->vcpu_id = vcpu_id;

QTAILQ_INSERT_TAIL(&launch_update, data, next);

Expand All @@ -1454,7 +1458,7 @@ static int sev_snp_launch_update_data(SevCommonState *sev_common, hwaddr gpa,
uint8_t *ptr, size_t len, Error **errp)
{
return snp_launch_update_data(gpa, ptr, len,
KVM_SEV_SNP_PAGE_TYPE_NORMAL, errp);
KVM_SEV_SNP_PAGE_TYPE_NORMAL, 0, errp);
}

static int
Expand Down Expand Up @@ -1537,7 +1541,7 @@ static int snp_launch_update_cpuid(uint32_t cpuid_addr, void *hva,
memcpy(hva, &snp_cpuid_info, sizeof(snp_cpuid_info));

return snp_launch_update_data(cpuid_addr, hva, cpuid_len,
KVM_SEV_SNP_PAGE_TYPE_CPUID, errp);
KVM_SEV_SNP_PAGE_TYPE_CPUID, 0, errp);
}

static int snp_launch_update_kernel_hashes(SevSnpGuestState *sev_snp,
Expand All @@ -1554,7 +1558,7 @@ static int snp_launch_update_kernel_hashes(SevSnpGuestState *sev_snp,
sizeof(*sev_snp->kernel_hashes_data));
type = KVM_SEV_SNP_PAGE_TYPE_NORMAL;
}
return snp_launch_update_data(addr, hva, len, type, errp);
return snp_launch_update_data(addr, hva, len, type, 0, errp);
}

static int
Expand Down Expand Up @@ -1599,7 +1603,7 @@ snp_populate_metadata_pages(SevSnpGuestState *sev_snp,
desc->len, &error_fatal);
} else {
ret = snp_launch_update_data(desc->base, hva, desc->len, type,
&error_fatal);
0, &error_fatal);
}

if (ret) {
Expand Down Expand Up @@ -2544,25 +2548,35 @@ static int cgs_set_guest_state(hwaddr gpa, uint8_t *ptr, uint64_t len,
case CGS_PAGE_TYPE_ZERO:
return klass->launch_update_data(sev_common, gpa, ptr, len, errp);

case CGS_PAGE_TYPE_VMSA:
if (!sev_es_enabled()) {
case CGS_PAGE_TYPE_VMSA: {
if (sev_snp_enabled()) {
const struct sev_es_save_area * sa = (const struct sev_es_save_area *)ptr;
if (check_sev_features(sev_common, sa->sev_features, errp) < 0) {
return -1;
}

return snp_launch_update_data(
gpa, ptr, len, KVM_SEV_SNP_PAGE_TYPE_VMSA, cpu_index, errp);
} else if (sev_es_enabled()) {
if (check_vmsa_supported(sev_common, gpa,
(const struct sev_es_save_area *)ptr,
errp) < 0) {
return -1;
}
return sev_set_cpu_context(cpu_index, ptr, len, gpa, errp);
} else {
error_setg(errp,
"%s: attempt to configure initial VMSA, but SEV-ES "
"is not supported",
__func__);
return -1;
}
if (check_vmsa_supported(sev_common, gpa,
(const struct sev_es_save_area *)ptr,
errp) < 0) {
return -1;
}
return sev_set_cpu_context(cpu_index, ptr, len, gpa, errp);
}

case CGS_PAGE_TYPE_UNMEASURED:
if (sev_snp_enabled()) {
return snp_launch_update_data(
gpa, ptr, len, KVM_SEV_SNP_PAGE_TYPE_UNMEASURED, errp);
gpa, ptr, len, KVM_SEV_SNP_PAGE_TYPE_UNMEASURED, 0, errp);
}
/* No action required if not SEV-SNP */
return 0;
Expand All @@ -2576,7 +2590,7 @@ static int cgs_set_guest_state(hwaddr gpa, uint8_t *ptr, uint64_t len,
return -1;
}
return snp_launch_update_data(gpa, ptr, len,
KVM_SEV_SNP_PAGE_TYPE_SECRETS, errp);
KVM_SEV_SNP_PAGE_TYPE_SECRETS, 0, errp);

case CGS_PAGE_TYPE_REQUIRED_MEMORY:
if (kvm_convert_memory(gpa, len, true) < 0) {
Expand Down

0 comments on commit bcb7121

Please sign in to comment.