return 0;
}
- /*
- * A confidential guest support object must be provided for setting
- * a VP context.
- */
- if (!ctx->cgs) {
- error_setg(
- errp,
- "A VP context is present in the IGVM file but is not supported "
- "by the current system.");
- return -1;
- }
-
data_handle = igvm_get_header_data(ctx->file, IGVM_HEADER_SECTION_DIRECTIVE,
ctx->current_header_index);
if (data_handle < 0) {
}
data = (uint8_t *)igvm_get_buffer(ctx->file, data_handle);
- result = ctx->cgsc->set_guest_state(
- vp_context->gpa, data, igvm_get_buffer_size(ctx->file, data_handle),
- CGS_PAGE_TYPE_VMSA, vp_context->vp_index, errp);
+
+ if (ctx->cgs) {
+ result = ctx->cgsc->set_guest_state(
+ vp_context->gpa, data, igvm_get_buffer_size(ctx->file, data_handle),
+ CGS_PAGE_TYPE_VMSA, vp_context->vp_index, errp);
+ } else if (target_arch() == SYS_EMU_TARGET_X86_64) {
+ result = qigvm_x86_set_vp_context(data, vp_context->vp_index, errp);
+ } else {
+ error_setg(
+ errp,
+ "A VP context is present in the IGVM file but is not supported "
+ "by the current system.");
+ result = -1;
+ }
+
igvm_free_buffer(ctx->file, data_handle);
if (result < 0) {
return result;
#include "qemu/osdep.h"
+#include "cpu.h"
#include "hw/i386/e820_memory_layout.h"
#include "system/igvm.h"
+struct IgvmNativeVpContextX64 {
+ uint64_t rax;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rbx;
+ uint64_t rsp;
+ uint64_t rbp;
+ uint64_t rsi;
+ uint64_t rdi;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ uint64_t rip;
+ uint64_t rflags;
+ uint64_t idtr_base;
+ uint16_t idtr_limit;
+ uint16_t reserved[2];
+ uint16_t gdtr_limit;
+ uint64_t gdtr_base;
+
+ uint16_t code_selector;
+ uint16_t code_attributes;
+ uint32_t code_base;
+ uint32_t code_limit;
+
+ uint16_t data_selector;
+ uint16_t data_attributes;
+ uint32_t data_base;
+ uint32_t data_limit;
+
+ uint64_t gs_base;
+ uint64_t cr0;
+ uint64_t cr3;
+ uint64_t cr4;
+ uint64_t efer;
+};
+
+#define FLAGS_TO_SEGCACHE(flags) \
+ (((unsigned int)flags) << 8)
+
+static void qigvm_x86_load_context(struct IgvmNativeVpContextX64 *context,
+ CPUX86State *env)
+{
+ cpu_load_efer(env, context->efer);
+ cpu_x86_update_cr4(env, context->cr4);
+ cpu_x86_update_cr0(env, context->cr0);
+ cpu_x86_update_cr3(env, context->cr3);
+
+ cpu_x86_load_seg_cache(
+ env, R_CS, context->code_selector,
+ context->code_base, context->code_limit,
+ FLAGS_TO_SEGCACHE(context->code_attributes));
+ cpu_x86_load_seg_cache(
+ env, R_DS, context->data_selector,
+ context->data_base, context->data_limit,
+ FLAGS_TO_SEGCACHE(context->data_attributes));
+ cpu_x86_load_seg_cache(
+ env, R_ES, context->data_selector,
+ context->data_base, context->data_limit,
+ FLAGS_TO_SEGCACHE(context->data_attributes));
+ cpu_x86_load_seg_cache(
+ env, R_FS, context->data_selector,
+ context->data_base, context->data_limit,
+ FLAGS_TO_SEGCACHE(context->data_attributes));
+ cpu_x86_load_seg_cache(
+ env, R_GS, context->data_selector,
+ context->data_base, context->data_limit,
+ FLAGS_TO_SEGCACHE(context->data_attributes));
+ cpu_x86_load_seg_cache(
+ env, R_SS, context->data_selector,
+ context->data_base, context->data_limit,
+ FLAGS_TO_SEGCACHE(context->data_attributes));
+
+ env->gdt.base = context->gdtr_base;
+ env->gdt.limit = context->gdtr_limit;
+ env->idt.base = context->idtr_base;
+ env->idt.limit = context->idtr_limit;
+
+ env->regs[R_EAX] = context->rax;
+ env->regs[R_ECX] = context->rcx;
+ env->regs[R_EDX] = context->rdx;
+ env->regs[R_EBX] = context->rbx;
+ env->regs[R_ESP] = context->rsp;
+ env->regs[R_EBP] = context->rbp;
+ env->regs[R_ESI] = context->rsi;
+ env->regs[R_EDI] = context->rdi;
+#ifdef TARGET_X86_64
+ env->regs[R_R8] = context->r8;
+ env->regs[R_R9] = context->r9;
+ env->regs[R_R10] = context->r10;
+ env->regs[R_R11] = context->r11;
+ env->regs[R_R12] = context->r12;
+ env->regs[R_R13] = context->r13;
+ env->regs[R_R14] = context->r14;
+ env->regs[R_R15] = context->r15;
+#endif
+ env->eip = context->rip;
+ env->eflags = context->rflags;
+}
+
/*
* convert e820 table into igvm memory map
*/
}
return 0;
}
+
+/*
+ * set initial cpu context
+ */
+static struct IgvmNativeVpContextX64 *bsp_context;
+
+int qigvm_x86_set_vp_context(void *data, int index, Error **errp)
+{
+ if (index != 0) {
+ error_setg(errp, "context can be set for BSP only");
+ return -1;
+ }
+
+ if (bsp_context == NULL) {
+ bsp_context = g_new0(struct IgvmNativeVpContextX64, 1);
+ }
+ memcpy(bsp_context, data, sizeof(struct IgvmNativeVpContextX64));
+ return 0;
+}
+
+void qigvm_x86_bsp_reset(CPUX86State *env)
+{
+ if (bsp_context == NULL) {
+ return;
+ }
+
+ qigvm_x86_load_context(bsp_context, env);
+}