246 lines
8.3 KiB
Diff
246 lines
8.3 KiB
Diff
|
Direct kernel boot to HVM guests has regression from xen-3.3 to xen-4.0.
|
||
|
Foreport this feature to latest qemu-xen. Make a fake boot sector with given
|
||
|
kernel and initrd, which could be accessed by hvmloader.
|
||
|
|
||
|
Signed-off-by: Chunyan Liu <cyliu@novell.com>
|
||
|
|
||
|
Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/block.c
|
||
|
===================================================================
|
||
|
--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/block.c
|
||
|
+++ xen-4.1.1-testing/tools/ioemu-qemu-xen/block.c
|
||
|
@@ -596,6 +596,16 @@ int bdrv_read(BlockDriverState *bs, int6
|
||
|
|
||
|
if (bdrv_check_request(bs, sector_num, nb_sectors))
|
||
|
return -EIO;
|
||
|
+
|
||
|
+ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
|
||
|
+ memcpy(buf, bs->boot_sector_data, 512);
|
||
|
+ sector_num++;
|
||
|
+ nb_sectors--;
|
||
|
+ buf += 512;
|
||
|
+ if (nb_sectors == 0)
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
if (drv->bdrv_pread) {
|
||
|
int ret, len;
|
||
|
len = nb_sectors * 512;
|
||
|
@@ -631,6 +641,10 @@ int bdrv_write(BlockDriverState *bs, int
|
||
|
if (bdrv_check_request(bs, sector_num, nb_sectors))
|
||
|
return -EIO;
|
||
|
|
||
|
+ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
|
||
|
+ memcpy(bs->boot_sector_data, buf, 512);
|
||
|
+ }
|
||
|
+
|
||
|
if (drv->bdrv_pwrite) {
|
||
|
int ret, len, count = 0;
|
||
|
len = nb_sectors * 512;
|
||
|
@@ -934,6 +948,16 @@ void bdrv_guess_geometry(BlockDriverStat
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+/* force a given boot sector. */
|
||
|
+void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
|
||
|
+{
|
||
|
+ bs->boot_sector_enabled = 1;
|
||
|
+ if (size > 512)
|
||
|
+ size = 512;
|
||
|
+ memcpy(bs->boot_sector_data, data, size);
|
||
|
+ memset(bs->boot_sector_data + size, 0, 512 - size);
|
||
|
+}
|
||
|
+
|
||
|
void bdrv_set_geometry_hint(BlockDriverState *bs,
|
||
|
int cyls, int heads, int secs)
|
||
|
{
|
||
|
@@ -1464,6 +1488,14 @@ BlockDriverAIOCB *bdrv_aio_read(BlockDri
|
||
|
if (bdrv_check_request(bs, sector_num, nb_sectors))
|
||
|
return NULL;
|
||
|
|
||
|
+ /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
|
||
|
+ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
|
||
|
+ memcpy(buf, bs->boot_sector_data, 512);
|
||
|
+ sector_num++;
|
||
|
+ nb_sectors--;
|
||
|
+ buf += 512;
|
||
|
+ }
|
||
|
+
|
||
|
ret = drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
|
||
|
|
||
|
if (ret) {
|
||
|
@@ -1489,6 +1521,10 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDr
|
||
|
if (bdrv_check_request(bs, sector_num, nb_sectors))
|
||
|
return NULL;
|
||
|
|
||
|
+ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
|
||
|
+ memcpy(bs->boot_sector_data, buf, 512);
|
||
|
+ }
|
||
|
+
|
||
|
ret = drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
|
||
|
|
||
|
if (ret) {
|
||
|
Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/block_int.h
|
||
|
===================================================================
|
||
|
--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/block_int.h
|
||
|
+++ xen-4.1.1-testing/tools/ioemu-qemu-xen/block_int.h
|
||
|
@@ -122,6 +122,9 @@ struct BlockDriverState {
|
||
|
BlockDriver *drv; /* NULL means no media */
|
||
|
void *opaque;
|
||
|
|
||
|
+ int boot_sector_enabled;
|
||
|
+ uint8_t boot_sector_data[512];
|
||
|
+
|
||
|
char filename[1024];
|
||
|
char backing_file[1024]; /* if non zero, the image is a diff of
|
||
|
this file image */
|
||
|
Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/pc.c
|
||
|
===================================================================
|
||
|
--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/hw/pc.c
|
||
|
+++ xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/pc.c
|
||
|
@@ -474,45 +474,28 @@ static void bochs_bios_init(void)
|
||
|
|
||
|
/* Generate an initial boot sector which sets state and jump to
|
||
|
a specified vector */
|
||
|
-static void generate_bootsect(uint8_t *option_rom,
|
||
|
- uint32_t gpr[8], uint16_t segs[6], uint16_t ip)
|
||
|
+static void generate_bootsect(uint32_t gpr[8], uint16_t segs[6], uint16_t ip)
|
||
|
{
|
||
|
- uint8_t rom[512], *p, *reloc;
|
||
|
- uint8_t sum;
|
||
|
+ uint8_t bootsect[512], *p;
|
||
|
int i;
|
||
|
+ int hda;
|
||
|
+
|
||
|
+ hda = drive_get_index(IF_IDE, 0, 0);
|
||
|
+ if (hda == -1) {
|
||
|
+ fprintf(stderr, "A disk image must be given for 'hda' when booting "
|
||
|
+ "a Linux kernel\n(if you really don't want it, use /dev/zero)\n");
|
||
|
+ exit(1);
|
||
|
+ }
|
||
|
+ memset(bootsect, 0, sizeof(bootsect));
|
||
|
|
||
|
- memset(rom, 0, sizeof(rom));
|
||
|
-
|
||
|
- p = rom;
|
||
|
- /* Make sure we have an option rom signature */
|
||
|
- *p++ = 0x55;
|
||
|
- *p++ = 0xaa;
|
||
|
-
|
||
|
- /* ROM size in sectors*/
|
||
|
- *p++ = 1;
|
||
|
-
|
||
|
- /* Hook int19 */
|
||
|
-
|
||
|
- *p++ = 0x50; /* push ax */
|
||
|
- *p++ = 0x1e; /* push ds */
|
||
|
- *p++ = 0x31; *p++ = 0xc0; /* xor ax, ax */
|
||
|
- *p++ = 0x8e; *p++ = 0xd8; /* mov ax, ds */
|
||
|
-
|
||
|
- *p++ = 0xc7; *p++ = 0x06; /* movvw _start,0x64 */
|
||
|
- *p++ = 0x64; *p++ = 0x00;
|
||
|
- reloc = p;
|
||
|
- *p++ = 0x00; *p++ = 0x00;
|
||
|
-
|
||
|
- *p++ = 0x8c; *p++ = 0x0e; /* mov cs,0x66 */
|
||
|
- *p++ = 0x66; *p++ = 0x00;
|
||
|
-
|
||
|
- *p++ = 0x1f; /* pop ds */
|
||
|
- *p++ = 0x58; /* pop ax */
|
||
|
- *p++ = 0xcb; /* lret */
|
||
|
-
|
||
|
- /* Actual code */
|
||
|
- *reloc = (p - rom);
|
||
|
+ /* Copy the MSDOS partition table if possible */
|
||
|
+ bdrv_read(drives_table[hda].bdrv, 0, bootsect, 1);
|
||
|
+ /* Make sure we have a partition signature */
|
||
|
+ bootsect[510] = 0x55;
|
||
|
+ bootsect[511] = 0xaa;
|
||
|
|
||
|
+ /* Actual code */
|
||
|
+ p = bootsect;
|
||
|
*p++ = 0xfa; /* CLI */
|
||
|
*p++ = 0xfc; /* CLD */
|
||
|
|
||
|
@@ -542,13 +525,7 @@ static void generate_bootsect(uint8_t *o
|
||
|
*p++ = segs[1]; /* CS */
|
||
|
*p++ = segs[1] >> 8;
|
||
|
|
||
|
- /* sign rom */
|
||
|
- sum = 0;
|
||
|
- for (i = 0; i < (sizeof(rom) - 1); i++)
|
||
|
- sum += rom[i];
|
||
|
- rom[sizeof(rom) - 1] = -sum;
|
||
|
-
|
||
|
- memcpy(option_rom, rom, sizeof(rom));
|
||
|
+ bdrv_set_boot_sector(drives_table[hda].bdrv, bootsect, sizeof(bootsect));
|
||
|
}
|
||
|
|
||
|
static long get_file_size(FILE *f)
|
||
|
@@ -565,8 +542,7 @@ static long get_file_size(FILE *f)
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
-static void load_linux(uint8_t *option_rom,
|
||
|
- const char *kernel_filename,
|
||
|
+static void load_linux(const char *kernel_filename,
|
||
|
const char *initrd_filename,
|
||
|
const char *kernel_cmdline)
|
||
|
{
|
||
|
@@ -632,7 +608,9 @@ static void load_linux(uint8_t *option_r
|
||
|
|
||
|
/* Special pages are placed at end of low RAM: pick an arbitrary one and
|
||
|
* subtract a suitably large amount of padding (64kB) to skip BIOS data. */
|
||
|
- xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &end_low_ram);
|
||
|
+ //xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &end_low_ram);
|
||
|
+ /* BUFIO Page beyond last_pfn, use 0x7ffc instead. Fix ME. */
|
||
|
+ end_low_ram = 0x7ffc;
|
||
|
end_low_ram = (end_low_ram << 12) - (64*1024);
|
||
|
|
||
|
/* highest address for loading the initrd */
|
||
|
@@ -721,7 +699,7 @@ static void load_linux(uint8_t *option_r
|
||
|
memset(gpr, 0, sizeof gpr);
|
||
|
gpr[4] = cmdline_addr-real_addr-16; /* SP (-16 is paranoia) */
|
||
|
|
||
|
- generate_bootsect(option_rom, gpr, seg, 0);
|
||
|
+ generate_bootsect(gpr, seg, 0);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
@@ -932,14 +910,6 @@ vga_bios_error:
|
||
|
int size, offset;
|
||
|
|
||
|
offset = 0;
|
||
|
- if (linux_boot) {
|
||
|
- option_rom_offset = qemu_ram_alloc(TARGET_PAGE_SIZE);
|
||
|
- load_linux(phys_ram_base + option_rom_offset,
|
||
|
- kernel_filename, initrd_filename, kernel_cmdline);
|
||
|
- cpu_register_physical_memory(0xd0000, TARGET_PAGE_SIZE,
|
||
|
- option_rom_offset | IO_MEM_ROM);
|
||
|
- offset = TARGET_PAGE_SIZE;
|
||
|
- }
|
||
|
|
||
|
for (i = 0; i < nb_option_roms; i++) {
|
||
|
size = get_image_size(option_rom[i]);
|
||
|
@@ -973,6 +943,9 @@ vga_bios_error:
|
||
|
|
||
|
bochs_bios_init();
|
||
|
|
||
|
+ if (linux_boot)
|
||
|
+ load_linux(kernel_filename, initrd_filename, kernel_cmdline);
|
||
|
+
|
||
|
cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);
|
||
|
i8259 = i8259_init(cpu_irq[0]);
|
||
|
ferr_irq = i8259[13];
|
||
|
Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/block.h
|
||
|
===================================================================
|
||
|
--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/block.h
|
||
|
+++ xen-4.1.1-testing/tools/ioemu-qemu-xen/block.h
|
||
|
@@ -82,6 +82,7 @@ int64_t bdrv_getlength(BlockDriverState
|
||
|
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
|
||
|
void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs);
|
||
|
int bdrv_commit(BlockDriverState *bs);
|
||
|
+void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size);
|
||
|
/* async block I/O */
|
||
|
typedef struct BlockDriverAIOCB BlockDriverAIOCB;
|
||
|
typedef void BlockDriverCompletionFunc(void *opaque, int ret);
|