This is version 3 of Xen side patches. RFC tag is dropped because we reach consensus on what to pass on to OVMF, though OVMF side patches are sitll awaiting review. Release wise, I think this patch set should do more good than harm. It only affects OVMF, which we cannot make it worse - it was broken since long. Wei. Changes in V3: * move seabios_info to common code * e820 entry number is 16 again, one can bump it when necessary * reserve low reset vector in E820 map in OVMF Changes in V2: * ovmf_info is now almost the same as seabios_info * bump e820 entry number to 128 * modify build_e820_table to avoid BIOS region reservation if there''s none Wei Liu (4): hvmloader/ovmf: remove hardcoded OVMF loading location hvmloader/ovmf: show OVMF_BEGIN as bios address hvmloader/ovmf: setup BIOS info for OVMF hvmloader/ovmf: setup E820 map tools/firmware/hvmloader/config.h | 20 ++++++++++++++ tools/firmware/hvmloader/hvmloader.c | 4 +-- tools/firmware/hvmloader/ovmf.c | 47 +++++++++++++++++++++++++++----- tools/firmware/hvmloader/seabios.c | 49 +++++++--------------------------- tools/firmware/hvmloader/util.c | 11 ++++++++ tools/firmware/hvmloader/util.h | 2 ++ 6 files changed, 85 insertions(+), 48 deletions(-) -- 1.7.10.4
Wei Liu
2013-Nov-21 16:22 UTC
[PATCH v3 1/4] hvmloader/ovmf: remove hardcoded OVMF loading location
Load OVMF from (100000000ULL - sizeof(ovmf)) to 0xFFFFFFFF, with proper rounding down. Tested with OVMF release build (1 MB) and debug build (2 MB), both worked fine. Signed-off-by: Wei Liu <wei.liu2@citrix.com> --- tools/firmware/hvmloader/ovmf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/firmware/hvmloader/ovmf.c b/tools/firmware/hvmloader/ovmf.c index ee4cbbf..148102a 100644 --- a/tools/firmware/hvmloader/ovmf.c +++ b/tools/firmware/hvmloader/ovmf.c @@ -38,9 +38,9 @@ #define ROM_INCLUDE_OVMF #include "roms.inc" -#define OVMF_BEGIN 0xFFF00000ULL -#define OVMF_SIZE 0x00100000ULL +#define OVMF_SIZE (sizeof(ovmf)) #define OVMF_MAXOFFSET 0x000FFFFFULL +#define OVMF_BEGIN (0x100000000ULL - ((OVMF_SIZE + OVMF_MAXOFFSET) & ~OVMF_MAXOFFSET)) #define OVMF_END (OVMF_BEGIN + OVMF_SIZE) #define LOWCHUNK_BEGIN 0x000F0000 #define LOWCHUNK_SIZE 0x00010000 -- 1.7.10.4
Wei Liu
2013-Nov-21 16:22 UTC
[PATCH v3 2/4] hvmloader/ovmf: show OVMF_BEGIN as bios address
Signed-off-by: Wei Liu <wei.liu2@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/firmware/hvmloader/ovmf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/firmware/hvmloader/ovmf.c b/tools/firmware/hvmloader/ovmf.c index 148102a..a67a2de 100644 --- a/tools/firmware/hvmloader/ovmf.c +++ b/tools/firmware/hvmloader/ovmf.c @@ -99,7 +99,7 @@ struct bios_config ovmf_config = { .image = ovmf, .image_size = sizeof(ovmf), - .bios_address = 0, + .bios_address = OVMF_BEGIN, .bios_load = ovmf_load, .load_roms = 0, -- 1.7.10.4
Move seabios_info to common code and rename it bios_info. BIOS info for OVMF contains E820 map allocated by hvmloader. This info is passed to OVMF to help it do proper initialization. Signed-off-by: Wei Liu <wei.liu2@citrix.com> --- tools/firmware/hvmloader/config.h | 20 ++++++++++++++ tools/firmware/hvmloader/hvmloader.c | 4 +-- tools/firmware/hvmloader/ovmf.c | 28 +++++++++++++++++-- tools/firmware/hvmloader/seabios.c | 49 +++++++--------------------------- tools/firmware/hvmloader/util.c | 11 ++++++++ tools/firmware/hvmloader/util.h | 2 ++ 6 files changed, 70 insertions(+), 44 deletions(-) diff --git a/tools/firmware/hvmloader/config.h b/tools/firmware/hvmloader/config.h index 6641197..7d4da50 100644 --- a/tools/firmware/hvmloader/config.h +++ b/tools/firmware/hvmloader/config.h @@ -39,6 +39,26 @@ extern struct bios_config rombios_config; extern struct bios_config seabios_config; extern struct bios_config ovmf_config; +#define BIOS_INFO_MAX_TABLES 4 +struct bios_info { + char signature[14]; /* Signature */ + uint8_t length; /* Length of this struct */ + uint8_t checksum; /* Set such that the sum over bytes 0..length == 0 */ + /* + * Physical address of an array of tables_nr elements. + * + * Each element is a 32 bit value containing the physical address + * of a BIOS table. + */ + uint32_t tables; + uint32_t tables_nr; + /* + * Physical address of the e820 table, contains e820_nr entries. + */ + uint32_t e820; + uint32_t e820_nr; +} __attribute__ ((packed)); + #define PAGE_SHIFT 12 #define PAGE_SIZE (1ul << PAGE_SHIFT) diff --git a/tools/firmware/hvmloader/hvmloader.c b/tools/firmware/hvmloader/hvmloader.c index 1cc8cf2..9ee6c78 100644 --- a/tools/firmware/hvmloader/hvmloader.c +++ b/tools/firmware/hvmloader/hvmloader.c @@ -202,7 +202,7 @@ static void apic_setup(void) ioapic_write(0x11, SET_APIC_ID(LAPIC_ID(0))); } -struct bios_info { +struct bios { const char *key; const struct bios_config *bios; } bios_configs[] = { @@ -220,7 +220,7 @@ struct bios_info { static const struct bios_config *detect_bios(void) { - const struct bios_info *b; + const struct bios *b; const char *bios; bios = xenstore_read("hvmloader/bios", "rombios"); diff --git a/tools/firmware/hvmloader/ovmf.c b/tools/firmware/hvmloader/ovmf.c index a67a2de..5c0599c 100644 --- a/tools/firmware/hvmloader/ovmf.c +++ b/tools/firmware/hvmloader/ovmf.c @@ -46,10 +46,34 @@ #define LOWCHUNK_SIZE 0x00010000 #define LOWCHUNK_MAXOFFSET 0x0000FFFF #define LOWCHUNK_END (OVMF_BEGIN + OVMF_SIZE) +#define OVMF_INFO_PHYSICAL_ADDRESS 0X00001000 extern unsigned char dsdt_anycpu[]; extern int dsdt_anycpu_len; +static void ovmf_setup_bios_info(void) +{ + struct bios_info *info = (void *)OVMF_INFO_PHYSICAL_ADDRESS; + + memset(info, 0, sizeof(*info)); + + memcpy(info->signature, "XenHVMOVMF", sizeof(info->signature)); + info->length = sizeof(*info); +} + +static void ovmf_finish_bios_info(void) +{ + struct bios_info *info = (void *)OVMF_INFO_PHYSICAL_ADDRESS; + uint32_t i; + uint8_t checksum; + + checksum = 0; + for ( i = 0; i < info->length; i++ ) + checksum += ((uint8_t *)(info))[i]; + + info->checksum = -checksum; +} + static void ovmf_load(const struct bios_config *config) { xen_pfn_t mfn; @@ -104,8 +128,8 @@ struct bios_config ovmf_config = { .load_roms = 0, - .bios_info_setup = NULL, - .bios_info_finish = NULL, + .bios_info_setup = ovmf_setup_bios_info, + .bios_info_finish = ovmf_finish_bios_info, .e820_setup = NULL, diff --git a/tools/firmware/hvmloader/seabios.c b/tools/firmware/hvmloader/seabios.c index dd7dfbe..9bc0a6d 100644 --- a/tools/firmware/hvmloader/seabios.c +++ b/tools/firmware/hvmloader/seabios.c @@ -34,42 +34,22 @@ extern unsigned char dsdt_anycpu_qemu_xen[]; extern int dsdt_anycpu_qemu_xen_len; -struct seabios_info { - char signature[14]; /* XenHVMSeaBIOS\0 */ - uint8_t length; /* Length of this struct */ - uint8_t checksum; /* Set such that the sum over bytes 0..length == 0 */ - /* - * Physical address of an array of tables_nr elements. - * - * Each element is a 32 bit value contianing the physical address - * of a BIOS table. - */ - uint32_t tables; - uint32_t tables_nr; - /* - * Physical address of the e820 table, contains e820_nr entries. - */ - uint32_t e820; - uint32_t e820_nr; -} __attribute__ ((packed)); - -#define MAX_TABLES 4 - static void seabios_setup_bios_info(void) { - struct seabios_info *info = (void *)BIOS_INFO_PHYSICAL_ADDRESS; + struct bios_info *info = (void *)BIOS_INFO_PHYSICAL_ADDRESS; memset(info, 0, sizeof(*info)); memcpy(info->signature, "XenHVMSeaBIOS", sizeof(info->signature)); info->length = sizeof(*info); - info->tables = (uint32_t)scratch_alloc(MAX_TABLES*sizeof(uint32_t), 0); + info->tables + (uint32_t)scratch_alloc(BIOS_INFO_MAX_TABLES*sizeof(uint32_t), 0); } static void seabios_finish_bios_info(void) { - struct seabios_info *info = (void *)BIOS_INFO_PHYSICAL_ADDRESS; + struct bios_info *info = (void *)BIOS_INFO_PHYSICAL_ADDRESS; uint32_t i; uint8_t checksum; @@ -80,17 +60,6 @@ static void seabios_finish_bios_info(void) info->checksum = -checksum; } -static void add_table(uint32_t t) -{ - struct seabios_info *info = (void *)BIOS_INFO_PHYSICAL_ADDRESS; - uint32_t *ts = (uint32_t *)info->tables; - - ASSERT(info->tables_nr < MAX_TABLES); - - ts[info->tables_nr] = t; - info->tables_nr++; -} - static void seabios_acpi_build_tables(void) { uint32_t rsdp = (uint32_t)scratch_alloc(sizeof(struct acpi_20_rsdp), 0); @@ -102,29 +71,29 @@ static void seabios_acpi_build_tables(void) }; acpi_build_tables(&config, rsdp); - add_table(rsdp); + bios_info_add_table(rsdp, BIOS_INFO_PHYSICAL_ADDRESS); } static void seabios_create_mp_tables(void) { - add_table(create_mp_tables(NULL)); + bios_info_add_table(create_mp_tables(NULL), BIOS_INFO_PHYSICAL_ADDRESS); } static void seabios_create_smbios_tables(void) { uint32_t ep = (uint32_t)scratch_alloc(sizeof(struct smbios_entry_point), 0); hvm_write_smbios_tables(ep, 0UL, 0UL); - add_table(ep); + bios_info_add_table(ep, BIOS_INFO_PHYSICAL_ADDRESS); } static void seabios_create_pir_tables(void) { - add_table(create_pir_tables()); + bios_info_add_table(create_pir_tables(), BIOS_INFO_PHYSICAL_ADDRESS); } static void seabios_setup_e820(void) { - struct seabios_info *info = (void *)BIOS_INFO_PHYSICAL_ADDRESS; + struct bios_info *info = (void *)BIOS_INFO_PHYSICAL_ADDRESS; struct e820entry *e820 = scratch_alloc(sizeof(struct e820entry)*16, 0); info->e820 = (uint32_t)e820; diff --git a/tools/firmware/hvmloader/util.c b/tools/firmware/hvmloader/util.c index 80d822f..15c76da 100644 --- a/tools/firmware/hvmloader/util.c +++ b/tools/firmware/hvmloader/util.c @@ -828,6 +828,17 @@ int hpet_exists(unsigned long hpet_base) return ((hpet_id >> 16) == 0x8086); } +void bios_info_add_table(uint32_t t, uint32_t info_phys_addr) +{ + struct bios_info *info = (void *)info_phys_addr; + uint32_t *ts = (uint32_t *)info->tables; + + ASSERT(info->tables_nr < BIOS_INFO_MAX_TABLES); + + ts[info->tables_nr] = t; + info->tables_nr++; +} + /* * Local variables: * mode: C diff --git a/tools/firmware/hvmloader/util.h b/tools/firmware/hvmloader/util.h index 9ccb905..2630dd8 100644 --- a/tools/firmware/hvmloader/util.h +++ b/tools/firmware/hvmloader/util.h @@ -22,6 +22,8 @@ #undef NULL #define NULL ((void*)0) +void bios_info_add_table(uint32_t t, uint32_t info_phys_addr); + void __assert_failed(char *assertion, char *file, int line) __attribute__((noreturn)); #define ASSERT(p) \ -- 1.7.10.4
E820 map will be used by OVMF to create memory map. Signed-off-by: Wei Liu <wei.liu2@citrix.com> --- tools/firmware/hvmloader/ovmf.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/firmware/hvmloader/ovmf.c b/tools/firmware/hvmloader/ovmf.c index 5c0599c..6f34ecf 100644 --- a/tools/firmware/hvmloader/ovmf.c +++ b/tools/firmware/hvmloader/ovmf.c @@ -117,6 +117,17 @@ static void ovmf_create_smbios_tables(void) SMBIOS_PHYSICAL_END); } +static void ovmf_setup_e820(void) +{ + struct bios_info *info = (void *)OVMF_INFO_PHYSICAL_ADDRESS; + struct e820entry *e820 = scratch_alloc(sizeof(struct e820entry)*16, 0); + info->e820 = (uint32_t)e820; + + /* Reserve LOWCHUNK_BEGIN to 0x100000 as well, that''s reset vector. */ + info->e820_nr = build_e820_table(e820, 0, LOWCHUNK_BEGIN); + dump_e820_table(e820, info->e820_nr); +} + struct bios_config ovmf_config = { .name = "OVMF", @@ -131,7 +142,7 @@ struct bios_config ovmf_config = { .bios_info_setup = ovmf_setup_bios_info, .bios_info_finish = ovmf_finish_bios_info, - .e820_setup = NULL, + .e820_setup = ovmf_setup_e820, .acpi_build_tables = ovmf_acpi_build_tables, .create_mp_tables = NULL, -- 1.7.10.4