mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-24 06:29:19 +00:00
DM: Enable vsbl boot path.
There are two things here: 1. Enable basic vsbl boot functionality. 2. add long option to DM to specific vsbl file. So DM could choice to boot guest with vsbl. It's hard to find a suitable short option. So only long option is supported for vsbl file name option. If long option "--vsbl='vsbl_file_name'" is given in DM commandline, the "vsbl_file_name" will be loaded by DM first and running. vsbl will be response to lead guest to next boot stage. Signed-off-by: Yin Fengwei <fengwei.yin@intel.com> Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
parent
860c2cab3e
commit
1e13533ec0
@ -83,6 +83,7 @@ SRCS += hw/acpi/acpi.c
|
|||||||
#SRCS += core/bootrom.c
|
#SRCS += core/bootrom.c
|
||||||
SRCS += core/sw_load_common.c
|
SRCS += core/sw_load_common.c
|
||||||
SRCS += core/sw_load_bzimage.c
|
SRCS += core/sw_load_bzimage.c
|
||||||
|
SRCS += core/sw_load_vsbl.c
|
||||||
SRCS += core/smbiostbl.c
|
SRCS += core/smbiostbl.c
|
||||||
SRCS += core/mevent.c
|
SRCS += core/mevent.c
|
||||||
SRCS += core/gc.c
|
SRCS += core/gc.c
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "vmm.h"
|
#include "vmm.h"
|
||||||
#include "vmmapi.h"
|
#include "vmmapi.h"
|
||||||
|
#include "sw_load.h"
|
||||||
#include "cpuset.h"
|
#include "cpuset.h"
|
||||||
#include "dm.h"
|
#include "dm.h"
|
||||||
#include "acpi.h"
|
#include "acpi.h"
|
||||||
@ -72,6 +73,7 @@ char *vmname;
|
|||||||
|
|
||||||
int guest_ncpus;
|
int guest_ncpus;
|
||||||
char *guest_uuid_str;
|
char *guest_uuid_str;
|
||||||
|
char *vsbl_file_name;
|
||||||
bool stdio_in_use;
|
bool stdio_in_use;
|
||||||
|
|
||||||
static int guest_vmexit_on_hlt, guest_vmexit_on_pause;
|
static int guest_vmexit_on_hlt, guest_vmexit_on_pause;
|
||||||
@ -125,7 +127,8 @@ usage(int code)
|
|||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Usage: %s [-abehuwxACHPSWY] [-c vcpus] [-g <gdb port>] [-l <lpc>]\n"
|
"Usage: %s [-abehuwxACHPSWY] [-c vcpus] [-g <gdb port>] [-l <lpc>]\n"
|
||||||
" %*s [-m mem] [-p vcpu:hostcpu] [-s <pci>] [-U uuid] <vm>\n"
|
" %*s [-m mem] [-p vcpu:hostcpu] [-s <pci>] [-U uuid] \n"
|
||||||
|
" %*s [--vsbl vsbl_file_name] <vm>\n"
|
||||||
" -a: local apic is in xAPIC mode (deprecated)\n"
|
" -a: local apic is in xAPIC mode (deprecated)\n"
|
||||||
" -A: create ACPI tables\n"
|
" -A: create ACPI tables\n"
|
||||||
" -c: # cpus (default 1)\n"
|
" -c: # cpus (default 1)\n"
|
||||||
@ -150,8 +153,9 @@ usage(int code)
|
|||||||
" -k: kernel image path\n"
|
" -k: kernel image path\n"
|
||||||
" -r: ramdisk image path\n"
|
" -r: ramdisk image path\n"
|
||||||
" -B: bootargs for kernel\n"
|
" -B: bootargs for kernel\n"
|
||||||
" -v: version\n",
|
" -v: version\n"
|
||||||
progname, (int)strlen(progname), "");
|
" --vsbl: vsbl file path\n",
|
||||||
|
progname, (int)strlen(progname), "", (int)strlen(progname), "");
|
||||||
|
|
||||||
exit(code);
|
exit(code);
|
||||||
}
|
}
|
||||||
@ -545,6 +549,10 @@ sig_handler_term(int signo)
|
|||||||
mevent_notify();
|
mevent_notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CMD_OPT_VSBL = 1000,
|
||||||
|
};
|
||||||
|
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{"no_x2apic_mode", no_argument, 0, 'a' },
|
{"no_x2apic_mode", no_argument, 0, 'a' },
|
||||||
{"acpi", no_argument, 0, 'A' },
|
{"acpi", no_argument, 0, 'A' },
|
||||||
@ -573,6 +581,9 @@ static struct option long_options[] = {
|
|||||||
{"version", no_argument, 0, 'v' },
|
{"version", no_argument, 0, 'v' },
|
||||||
{"gvtargs", required_argument, 0, 'G' },
|
{"gvtargs", required_argument, 0, 'G' },
|
||||||
{"help", no_argument, 0, 'h' },
|
{"help", no_argument, 0, 'h' },
|
||||||
|
|
||||||
|
/* Following cmd option only has long option */
|
||||||
|
{"vsbl", required_argument, 0, CMD_OPT_VSBL},
|
||||||
{0, 0, 0, 0 },
|
{0, 0, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -707,6 +718,12 @@ main(int argc, char *argv[])
|
|||||||
case 'v':
|
case 'v':
|
||||||
print_version();
|
print_version();
|
||||||
break;
|
break;
|
||||||
|
case CMD_OPT_VSBL:
|
||||||
|
if (acrn_parse_vsbl(optarg) != 0) {
|
||||||
|
errx(EX_USAGE, "invalid vsbl param %s", optarg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(0);
|
usage(0);
|
||||||
default:
|
default:
|
||||||
|
@ -153,5 +153,8 @@ acrn_create_e820_table(struct vmctx *ctx, struct e820_entry *e820)
|
|||||||
int
|
int
|
||||||
acrn_sw_load(struct vmctx *ctx)
|
acrn_sw_load(struct vmctx *ctx)
|
||||||
{
|
{
|
||||||
return acrn_sw_load_bzimage(ctx);
|
if (vsbl_file_name)
|
||||||
|
return acrn_sw_load_vsbl(ctx);
|
||||||
|
else
|
||||||
|
return acrn_sw_load_bzimage(ctx);
|
||||||
}
|
}
|
||||||
|
287
devicemodel/core/sw_load_vsbl.c
Normal file
287
devicemodel/core/sw_load_vsbl.c
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2018 Intel Corporation
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "dm.h"
|
||||||
|
#include "acrn_common.h"
|
||||||
|
#include "vmmapi.h"
|
||||||
|
#include "sw_load.h"
|
||||||
|
#include "acpi.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* If the vsbl is loaded by DM, the UOS memory layout will be like:
|
||||||
|
*
|
||||||
|
* | ... |
|
||||||
|
* +--------------------------------------------------+
|
||||||
|
* | offset: 0xf2400 (ACPI table) |
|
||||||
|
* +--------------------------------------------------+
|
||||||
|
* | ... |
|
||||||
|
* +--------------------------------------------------+
|
||||||
|
* | offset: 16MB (vsbl image) |
|
||||||
|
* +--------------------------------------------------+
|
||||||
|
* | ... |
|
||||||
|
* +--------------------------------------------------+
|
||||||
|
* | offset: lowmem - 16K (partition blob) |
|
||||||
|
* +--------------------------------------------------+
|
||||||
|
* | offset: lowmem - 12K (e820 table) |
|
||||||
|
* +--------------------------------------------------+
|
||||||
|
* | offset: lowmem - 8K (boot_args_address) |
|
||||||
|
* +--------------------------------------------------+
|
||||||
|
* | offset: lowmem - 6K (vsbl entry address) |
|
||||||
|
* +--------------------------------------------------+
|
||||||
|
* | offset: lowmem - 4K (config_page with e820 table)|
|
||||||
|
* +--------------------------------------------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Check default e820 table in sw_load_common.c for info about ctx->lowmem */
|
||||||
|
#define CONFIGPAGE_OFF(ctx) ((ctx)->lowmem - 4*KB)
|
||||||
|
#define VSBL_ENTRY_OFF(ctx) ((ctx)->lowmem - 6*KB)
|
||||||
|
#define BOOTARGS_OFF(ctx) ((ctx)->lowmem - 8*KB)
|
||||||
|
#define E820_TABLE_OFF(ctx) ((ctx)->lowmem - 12*KB)
|
||||||
|
#define GUEST_PART_INFO_OFF(ctx) ((ctx)->lowmem - 16*KB)
|
||||||
|
/* vsbl real entry is saved in the first 4 bytes of vsbl image */
|
||||||
|
#define VSBL_OFF(ctx) (16*MB)
|
||||||
|
|
||||||
|
struct vsbl_para {
|
||||||
|
uint64_t e820_table_address;
|
||||||
|
uint64_t e820_entries;
|
||||||
|
uint64_t acpi_table_address;
|
||||||
|
uint64_t acpi_table_size;
|
||||||
|
uint64_t guest_part_info_address;
|
||||||
|
uint64_t guest_part_info_size;
|
||||||
|
uint64_t vsbl_address;
|
||||||
|
uint64_t vsbl_size;
|
||||||
|
uint64_t bootargs_address;
|
||||||
|
uint32_t trusty_enabled;
|
||||||
|
uint32_t key_info_lock;
|
||||||
|
uint32_t watchdog_reset;
|
||||||
|
uint32_t boot_device_address;
|
||||||
|
};
|
||||||
|
|
||||||
|
static char guest_part_info_path[STR_LEN];
|
||||||
|
static int guest_part_info_size;
|
||||||
|
static bool with_guest_part_info;
|
||||||
|
|
||||||
|
static char vsbl_path[STR_LEN];
|
||||||
|
static int vsbl_size;
|
||||||
|
|
||||||
|
static int boot_blk_bdf;
|
||||||
|
|
||||||
|
#define LOW_8BIT(x) ((x) & 0xFF)
|
||||||
|
void
|
||||||
|
vsbl_set_bdf(int bnum, int snum, int fnum)
|
||||||
|
{
|
||||||
|
boot_blk_bdf = (LOW_8BIT(bnum) << 16) | (LOW_8BIT(snum) << 8) |
|
||||||
|
LOW_8BIT(fnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
acrn_parse_guest_part_info(char *arg)
|
||||||
|
{
|
||||||
|
int len = strlen(arg);
|
||||||
|
|
||||||
|
if (len < STR_LEN) {
|
||||||
|
strncpy(guest_part_info_path, arg, len);
|
||||||
|
guest_part_info_path[len] = '\0';
|
||||||
|
assert(check_image(guest_part_info_path) == 0);
|
||||||
|
|
||||||
|
with_guest_part_info = true;
|
||||||
|
|
||||||
|
printf("SW_LOAD: get partition blob path %s\n",
|
||||||
|
guest_part_info_path);
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
acrn_prepare_guest_part_info(struct vmctx *ctx)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
int len, read;
|
||||||
|
|
||||||
|
fp = fopen(guest_part_info_path, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"SW_LOAD ERR: could not open partition blob %s\n",
|
||||||
|
guest_part_info_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
len = ftell(fp);
|
||||||
|
if ((len + GUEST_PART_INFO_OFF(ctx)) > BOOTARGS_OFF(ctx)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"SW_LOAD ERR: too large partition blob\n");
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
guest_part_info_size = len;
|
||||||
|
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
read = fread(ctx->baseaddr + GUEST_PART_INFO_OFF(ctx),
|
||||||
|
sizeof(char), len, fp);
|
||||||
|
if (read < len) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"SW_LOAD ERR: could not read whole partition blob\n");
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
printf("SW_LOAD: partition blob %s size %d copy to guest 0x%lx\n",
|
||||||
|
guest_part_info_path, guest_part_info_size,
|
||||||
|
GUEST_PART_INFO_OFF(ctx));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
acrn_parse_vsbl(char *arg)
|
||||||
|
{
|
||||||
|
int len = strlen(arg);
|
||||||
|
|
||||||
|
if (len < STR_LEN) {
|
||||||
|
strncpy(vsbl_path, arg, len);
|
||||||
|
vsbl_path[len] = '\0';
|
||||||
|
assert(check_image(vsbl_path) == 0);
|
||||||
|
|
||||||
|
vsbl_file_name = vsbl_path;
|
||||||
|
|
||||||
|
printf("SW_LOAD: get vsbl path %s\n",
|
||||||
|
vsbl_path);
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
acrn_prepare_vsbl(struct vmctx *ctx)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
int len, read;
|
||||||
|
|
||||||
|
fp = fopen(vsbl_path, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"SW_LOAD ERR: could not open vsbl file: %s\n",
|
||||||
|
vsbl_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
len = ftell(fp);
|
||||||
|
if ((len + VSBL_OFF(ctx)) > GUEST_PART_INFO_OFF(ctx)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"SW_LOAD ERR: too large vsbl file\n");
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vsbl_size = len;
|
||||||
|
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
read = fread(ctx->baseaddr + VSBL_OFF(ctx),
|
||||||
|
sizeof(char), len, fp);
|
||||||
|
if (read < len) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"SW_LOAD ERR: could not read whole partition blob\n");
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
printf("SW_LOAD: partition blob %s size %d copy to guest 0x%lx\n",
|
||||||
|
vsbl_path, vsbl_size, VSBL_OFF(ctx));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
acrn_sw_load_vsbl(struct vmctx *ctx)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct e820_entry *e820;
|
||||||
|
struct vsbl_para *vsbl_para;
|
||||||
|
uint64_t vsbl_start_addr =
|
||||||
|
(uint64_t)ctx->baseaddr + VSBL_OFF(ctx);
|
||||||
|
uint64_t *vsbl_entry =
|
||||||
|
(uint64_t *)(ctx->baseaddr + VSBL_ENTRY_OFF(ctx));
|
||||||
|
uint64_t *cfg_offset =
|
||||||
|
(uint64_t *)(ctx->baseaddr + GUEST_CFG_OFFSET);
|
||||||
|
|
||||||
|
*cfg_offset = ctx->lowmem;
|
||||||
|
|
||||||
|
vsbl_para = (struct vsbl_para *)
|
||||||
|
(ctx->baseaddr + CONFIGPAGE_OFF(ctx));
|
||||||
|
|
||||||
|
memset(vsbl_para, 0x0, sizeof(struct vsbl_para));
|
||||||
|
|
||||||
|
e820 = (struct e820_entry *)
|
||||||
|
(ctx->baseaddr + E820_TABLE_OFF(ctx));
|
||||||
|
|
||||||
|
vsbl_para->e820_entries = acrn_create_e820_table(ctx, e820);
|
||||||
|
vsbl_para->e820_table_address = E820_TABLE_OFF(ctx);
|
||||||
|
|
||||||
|
vsbl_para->acpi_table_address = get_acpi_base();
|
||||||
|
vsbl_para->acpi_table_size = get_acpi_table_length();
|
||||||
|
|
||||||
|
if (with_bootargs) {
|
||||||
|
strcpy(ctx->baseaddr + BOOTARGS_OFF(ctx), get_bootargs());
|
||||||
|
vsbl_para->bootargs_address = BOOTARGS_OFF(ctx);
|
||||||
|
} else {
|
||||||
|
vsbl_para->bootargs_address = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (with_guest_part_info) {
|
||||||
|
ret = acrn_prepare_guest_part_info(ctx);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
vsbl_para->guest_part_info_address = GUEST_PART_INFO_OFF(ctx);
|
||||||
|
vsbl_para->guest_part_info_size = guest_part_info_size;
|
||||||
|
} else {
|
||||||
|
vsbl_para->guest_part_info_address = 0;
|
||||||
|
vsbl_para->guest_part_info_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = acrn_prepare_vsbl(ctx);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
vsbl_para->vsbl_address = VSBL_OFF(ctx);
|
||||||
|
vsbl_para->vsbl_size = vsbl_size;
|
||||||
|
*vsbl_entry = *((uint32_t *) vsbl_start_addr);
|
||||||
|
|
||||||
|
vsbl_para->boot_device_address = boot_blk_bdf;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -38,6 +38,7 @@
|
|||||||
struct vmctx;
|
struct vmctx;
|
||||||
extern int guest_ncpus;
|
extern int guest_ncpus;
|
||||||
extern char *guest_uuid_str;
|
extern char *guest_uuid_str;
|
||||||
|
extern char *vsbl_file_name;
|
||||||
extern char *vmname;
|
extern char *vmname;
|
||||||
extern bool stdio_in_use;
|
extern bool stdio_in_use;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user