Hi,
These patches allow users to configure bootable device in guest configration
file.
The shadow memory, which mean memory area loading option ROM, is small.
So if we specified many pass-through device, hvmloader cannot load all of
option ROM.
We want to select a device which we want to load the option ROM.
After applying these patches, we need to specify pci option of bootable device
like below.
pci = [ '01:00.0,boot=1' ]
boot=1 means bootable, boot=0 and no boot option mean non-bootable.
BTW, if we don't specify the boot=1 option, we can boot from emulation disks
and we can boot faster because option ROM is not initialized.
These patches use cmos(0x60) as a place retaining the devfn of bootable device.
Bochs BIOS doesn't seems to use the offset 0x60.
What do you think of using cmos(0x60)?
Do you have some ideas?
Signed-off-by: Akio Takebe <takebe_akio@xxxxxxxxxxxxxx>
Best Regards,
Akio Takebe
diff -r a4274d1e85a3 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c Wed Mar 11 13:11:21 2009 +0000
+++ b/tools/firmware/hvmloader/hvmloader.c Thu Mar 12 18:50:26 2009 +0900
@@ -479,37 +479,38 @@
uint16_t vendor_id, device_id;
uint8_t devfn, class;
- for ( devfn = 0; devfn < 128; devfn++ )
- {
- class = pci_readb(devfn, PCI_CLASS_DEVICE + 1);
- vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
- device_id = pci_readw(devfn, PCI_DEVICE_ID);
+ devfn = cmos_inb(0x60);
+ printf("devfn=%x \n", devfn);
- if ( (vendor_id == 0xffff) && (device_id == 0xffff) )
- continue;
+ class = pci_readb(devfn, PCI_CLASS_DEVICE + 1);
+ vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
+ device_id = pci_readw(devfn, PCI_DEVICE_ID);
- /*
- * Currently only scan options from mass storage devices and serial
- * bus controller (Fibre Channel included).
- */
- if ( (class != 0x1) && (class != 0xc) )
- continue;
+ if ( (vendor_id == 0xffff) && (device_id == 0xffff) )
+ goto out;
- option_rom_addr = pci_readl(devfn, PCI_ROM_ADDRESS);
- if ( !option_rom_addr )
- continue;
+ /*
+ * Currently only scan options from mass storage devices and serial
+ * bus controller (Fibre Channel included).
+ */
+ if ( (class != 0x1) && (class != 0xc) )
+ goto out;
- /* Ensure Expansion Bar is enabled before copying */
- pci_writel(devfn, PCI_ROM_ADDRESS, option_rom_addr | 0x1);
+ option_rom_addr = pci_readl(devfn, PCI_ROM_ADDRESS);
+ if ( !option_rom_addr )
+ goto out;
- rom_phys_addr += scan_option_rom(
- devfn, vendor_id, device_id,
- (void *)(option_rom_addr & ~2047), rom_phys_addr);
+ /* Ensure Expansion Bar is enabled before copying */
+ pci_writel(devfn, PCI_ROM_ADDRESS, option_rom_addr | 0x1);
- /* Restore the default original value of Expansion Bar */
- pci_writel(devfn, PCI_ROM_ADDRESS, option_rom_addr);
- }
+ rom_phys_addr += scan_option_rom(
+ devfn, vendor_id, device_id,
+ (void *)(option_rom_addr & ~2047), rom_phys_addr);
+ /* Restore the default original value of Expansion Bar */
+ pci_writel(devfn, PCI_ROM_ADDRESS, option_rom_addr);
+
+out:
return rom_phys_addr - rom_base_addr;
}
diff -r a4274d1e85a3 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Wed Mar 11 13:11:21 2009 +0000
+++ b/tools/python/xen/xm/create.py Thu Mar 12 18:50:26 2009 +0900
@@ -322,7 +322,7 @@
backend driver domain to use for the disk.
The option may be repeated to add more than one disk.""")
-gopts.var('pci', val='BUS:DEV.FUNC[,msitranslate=0|1][,power_mgmt=0|1]',
+gopts.var('pci',
val='BUS:DEV.FUNC[,msitranslate=0|1][,power_mgmt=0|1][,boot=0|1]',
fn=append_value, default=[],
use="""Add a PCI device to a domain, using given params (in hex).
For example 'pci=c0:02.1'.
@@ -331,7 +331,10 @@
translated from physical MSI, HVM only. Default is 1.
The option may be repeated to add more than one pci device.
If power_mgmt is set, the guest OS will be able to program the power
- states D0-D3hot of the device, HVM only. Default=0.""")
+ states D0-D3hot of the device, HVM only. Default=0.
+ The option can add only one pci device.
+ If boot is set, guest BIOS boot OS from the pass-through devices.
+ The option is used by SAN/SAS boot.""")
gopts.var('vscsi', val='PDEV,VDEV[,DOM]',
fn=append_value, default=[],
@@ -697,7 +700,7 @@
d = comma_sep_kv_to_dict(opts)
def f(k):
- if k not in ['msitranslate', 'power_mgmt']:
+ if k not in ['msitranslate', 'power_mgmt', 'boot']:
err('Invalid pci option: ' + k)
config_pci_opts.append([k, d[k]])
diff --git a/hw/pass-through.c b/hw/pass-through.c
index 4a86309..7a6e8a8 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -3565,6 +3565,7 @@ struct pt_dev * register_real_device(PCIBus *e_bus,
int free_pci_slot = -1;
char *key, *val;
int msi_translate;
+ int pci_boot;
PT_LOG("Assigning real physical device %02x:%02x.%x ...\n",
r_bus, r_dev, r_func);
@@ -3597,6 +3598,7 @@ struct pt_dev * register_real_device(PCIBus *e_bus,
}
msi_translate = direct_pci_msitranslate;
+ pci_boot = 0;
while (opt) {
if (get_next_keyval(&opt, &key, &val)) {
PT_LOG("Error: unrecognized PCI assignment option \"%s\"\n", opt);
@@ -3618,6 +3620,19 @@ struct pt_dev * register_real_device(PCIBus *e_bus,
else
PT_LOG("Error: unrecognized value for msitranslate=\n");
}
+ else if (strcmp(key, "boot") == 0)
+ if (strcmp(val, "0") == 0 || strcmp(val, "no") == 0)
+ {
+ PT_LOG("Disable boot option\n");
+ pci_boot = 0;
+ }
+ else if (strcmp(val, "1") == 0 || strcmp(val, "yes") == 0)
+ {
+ PT_LOG("Enable boot option\n");
+ pci_boot = 1;
+ }
+ else
+ PT_LOG("Error: unrecognized value for boot=\n");
else
PT_LOG("Error: unrecognized PCI assignment option \"%s=%s\"\n",
key, val);
@@ -3710,6 +3725,9 @@ struct pt_dev * register_real_device(PCIBus *e_bus,
*(uint16_t *)(&assigned_device->dev.config[0x04]));
}
+ if (pci_boot)
+ pt_register_bootable_device(e_devfn);
+
out:
PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n"
"IRQ type = %s\n", r_bus, r_dev, r_func,
diff --git a/hw/pass-through.h b/hw/pass-through.h
index e86d311..cb5d3f4 100644
--- a/hw/pass-through.h
+++ b/hw/pass-through.h
@@ -384,5 +384,7 @@ static inline pciaddr_t pt_pci_base_addr(pciaddr_t base)
return base & PCI_ADDR_MEM_MASK;
}
+void pt_register_bootable_device(int e_devfn);
+
#endif /* __PASSTHROUGH_H__ */
diff --git a/hw/pc.c b/hw/pc.c
index f0492c8..ca4995a 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -237,6 +237,14 @@ static int pc_boot_set(void *opaque, const char
*boot_device)
return(0);
}
+#ifdef CONFIG_PASSTHROUGH
+void pt_register_bootable_device(int e_devfn)
+{
+ RTCState *s = rtc_state;
+ rtc_set_memory(s, 0x60, e_devfn);
+}
+#endif
+
/* hd_table must contain 4 block drivers */
static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
const char *boot_device, BlockDriverState **hd_table)
@@ -981,6 +989,8 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
}
}
+ rtc_state = rtc_init(0x70, i8259[8]);
+
#ifdef CONFIG_PASSTHROUGH
/* Pass-through Initialization
* init libpci even direct_pci is null, as can hotplug a dev runtime
@@ -996,8 +1006,6 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
}
#endif
- rtc_state = rtc_init(0x70, i8259[8]);
-
qemu_register_boot_set(pc_boot_set, rtc_state);
register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|