diff --git a/devicemodel/core/sw_load_bzimage.c b/devicemodel/core/sw_load_bzimage.c index d242f15da..f9bfe77f5 100644 --- a/devicemodel/core/sw_load_bzimage.c +++ b/devicemodel/core/sw_load_bzimage.c @@ -48,6 +48,8 @@ * +-----------------------------------------------------+ * | ... | * +-----------------------------------------------------+ + * | offset: lowmem - 4MB - 2K (kernel gdt) | + * +-----------------------------------------------------+ * | offset: lowmem - 4MB (ramdisk image) | * +-----------------------------------------------------+ * | offset: lowmem - 8K (bootargs) | @@ -59,6 +61,7 @@ */ /* Check default e820 table in sw_load_common.c for info about ctx->lowmem */ +#define GDT_LOAD_OFF(ctx) (ctx->lowmem - 4*MB - 2* KB) #define RAMDISK_LOAD_OFF(ctx) (ctx->lowmem - 4*MB) #define BOOTARGS_LOAD_OFF(ctx) (ctx->lowmem - 8*KB) #define KERNEL_ENTRY_OFF(ctx) (ctx->lowmem - 6*KB) @@ -280,13 +283,20 @@ acrn_prepare_zeropage(struct vmctx *ctx, int setup_size) return 0; } +static const uint64_t bzimage_init_gdt[] = { + 0x0UL, + 0x0UL, + 0x00CF9B000000FFFFUL, /* Linear Code */ + 0x00CF93000000FFFFUL, /* Linear Data */ +}; + int acrn_sw_load_bzimage(struct vmctx *ctx) { int ret, setup_size; - uint64_t *cfg_offset = (uint64_t *)(ctx->baseaddr + GUEST_CFG_OFFSET); - *cfg_offset = ctx->lowmem; + memset(&ctx->bsp_regs, 0, sizeof(struct acrn_set_vcpu_regs)); + ctx->bsp_regs.vcpu_id = 0; if (with_bootargs) { strcpy(ctx->baseaddr + BOOTARGS_LOAD_OFF(ctx), get_bootargs()); @@ -301,26 +311,43 @@ acrn_sw_load_bzimage(struct vmctx *ctx) } if (with_kernel) { - uint64_t *kernel_entry_addr = - (uint64_t *)(ctx->baseaddr + KERNEL_ENTRY_OFF(ctx)); - ret = acrn_prepare_kernel(ctx); if (ret) return ret; setup_size = acrn_get_bzimage_setup_size(ctx); if (setup_size <= 0) return -1; - *kernel_entry_addr = (uint64_t) + + ctx->bsp_regs.vcpu_regs.rip = (uint64_t) (KERNEL_LOAD_OFF(ctx) + setup_size); + ret = acrn_prepare_zeropage(ctx, setup_size); if (ret) return ret; printf("SW_LOAD: zeropage prepared @ 0x%lx, " "kernel_entry_addr=0x%lx\n", - ZEROPAGE_LOAD_OFF(ctx), *kernel_entry_addr); + ZEROPAGE_LOAD_OFF(ctx), + (KERNEL_LOAD_OFF(ctx) + setup_size)); } + memcpy(ctx->baseaddr + GDT_LOAD_OFF(ctx), &bzimage_init_gdt, + sizeof(bzimage_init_gdt)); + ctx->bsp_regs.vcpu_regs.gdt.limit = sizeof(bzimage_init_gdt) - 1; + ctx->bsp_regs.vcpu_regs.gdt.base = GDT_LOAD_OFF(ctx); + + /* CR0_ET | CR0_NE | CR0_PE */ + ctx->bsp_regs.vcpu_regs.cr0 = 0x31U; + + ctx->bsp_regs.vcpu_regs.cs_sel = 0x10U; + ctx->bsp_regs.vcpu_regs.cs_ar = 0xC09BU; + + ctx->bsp_regs.vcpu_regs.ds_sel = 0x18U; + ctx->bsp_regs.vcpu_regs.ss_sel = 0x18U; + ctx->bsp_regs.vcpu_regs.es_sel = 0x18U; + + ctx->bsp_regs.vcpu_regs.gprs.rsi = ZEROPAGE_LOAD_OFF(ctx); + return 0; }