[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [Patch][RFC] BIOS: configure bootable pass-through device



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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.