Add AHCI support to qemu driver

Tested with multiple AHCI controllers and multiple disks attached
to a controller. E.g.,

    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/var/lib/libvirt/images/test/disk0.raw'/>
      <target dev='sda' bus='sata'/>
      <address type='drive' controller='0' bus='0' unit='0'/>
    </disk>
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/var/lib/libvirt/images/test/disk1.raw'/>
      <target dev='sdb' bus='sata'/>
      <address type='drive' controller='0' bus='0' unit='1'/>
    </disk>
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/var/lib/libvirt/images/test/disk2.raw'/>
      <target dev='sdc' bus='sata'/>
      <address type='drive' controller='1' bus='0' unit='0'/>
    </disk>
    <controller type='sata' index='0'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
    </controller>
    <controller type='sata' index='1'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
    </controller>
This commit is contained in:
Jim Fehlig 2011-09-27 21:46:08 -06:00
parent e570d7c4d6
commit c1bc3d892c
9 changed files with 82 additions and 10 deletions

View File

@ -972,11 +972,12 @@
as a device ordering hint. The optional <code>bus</code> as a device ordering hint. The optional <code>bus</code>
attribute specifies the type of disk device to emulate; attribute specifies the type of disk device to emulate;
possible values are driver specific, with typical values being possible values are driver specific, with typical values being
"ide", "scsi", "virtio", "xen" or "usb". If omitted, the bus type is "ide", "scsi", "virtio", "xen", "usb" or "sata". If omitted, the bus
inferred from the style of the device name. eg, a device named 'sda' type is inferred from the style of the device name. eg, a device named
will typically be exported using a SCSI bus. 'sda' will typically be exported using a SCSI bus.
<span class="since">Since 0.0.3; <code>bus</code> attribute since 0.4.3; <span class="since">Since 0.0.3; <code>bus</code> attribute since 0.4.3;
"usb" attribute value since after 0.4.4</span></dd> "usb" attribute value since after 0.4.4; "sata" attribute value since
0.9.7</span></dd>
<dt><code>driver</code></dt> <dt><code>driver</code></dt>
<dd> <dd>
The optional driver element allows specifying further details The optional driver element allows specifying further details

View File

@ -790,6 +790,7 @@
<value>xen</value> <value>xen</value>
<value>usb</value> <value>usb</value>
<value>uml</value> <value>uml</value>
<value>sata</value>
</choice> </choice>
</attribute> </attribute>
</optional> </optional>

View File

@ -2189,6 +2189,15 @@ virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def)
def->info.addr.drive.unit = (idx % 2); def->info.addr.drive.unit = (idx % 2);
break; break;
case VIR_DOMAIN_DISK_BUS_SATA:
/* For SATA we define the default mapping to be 6 units
* per bus, 1 bus per controller, many controllers */
def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
def->info.addr.drive.controller = idx / 6;
def->info.addr.drive.bus = 0;
def->info.addr.drive.unit = idx % 6;
break;
case VIR_DOMAIN_DISK_BUS_FDC: case VIR_DOMAIN_DISK_BUS_FDC:
/* For FDC we define the default mapping to be 2 units /* For FDC we define the default mapping to be 2 units
* per bus, 1 bus per controller, many controllers */ * per bus, 1 bus per controller, many controllers */
@ -8748,6 +8757,11 @@ int virDomainDefAddImplicitControllers(virDomainDefPtr def)
VIR_DOMAIN_DISK_BUS_IDE) < 0) VIR_DOMAIN_DISK_BUS_IDE) < 0)
return -1; return -1;
if (virDomainDefAddDiskControllersForType(def,
VIR_DOMAIN_CONTROLLER_TYPE_SATA,
VIR_DOMAIN_DISK_BUS_SATA) < 0)
return -1;
if (virDomainDefMaybeAddVirtioSerialController(def) < 0) if (virDomainDefMaybeAddVirtioSerialController(def) < 0)
return -1; return -1;

View File

@ -140,6 +140,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
"cache-unsafe", /* 75 */ "cache-unsafe", /* 75 */
"rombar", "rombar",
"ich9-ahci",
); );
struct qemu_feature_flags { struct qemu_feature_flags {
@ -1255,6 +1256,8 @@ qemuCapsParseDeviceStr(const char *str, virBitmapPtr flags)
qemuCapsSet(flags, QEMU_CAPS_USB_REDIR); qemuCapsSet(flags, QEMU_CAPS_USB_REDIR);
if (strstr(str, "name \"usb-hub\"")) if (strstr(str, "name \"usb-hub\""))
qemuCapsSet(flags, QEMU_CAPS_USB_HUB); qemuCapsSet(flags, QEMU_CAPS_USB_HUB);
if (strstr(str, "name \"ich9-ahci\""))
qemuCapsSet(flags, QEMU_CAPS_ICH9_AHCI);
/* Prefer -chardev spicevmc (detected earlier) over -device spicevmc */ /* Prefer -chardev spicevmc (detected earlier) over -device spicevmc */
if (!qemuCapsGet(flags, QEMU_CAPS_CHARDEV_SPICEVMC) && if (!qemuCapsGet(flags, QEMU_CAPS_CHARDEV_SPICEVMC) &&

View File

@ -114,6 +114,7 @@ enum qemuCapsFlags {
QEMU_CAPS_DRIVE_CACHE_UNSAFE = 75, /* Is cache=unsafe supported? */ QEMU_CAPS_DRIVE_CACHE_UNSAFE = 75, /* Is cache=unsafe supported? */
QEMU_CAPS_PCI_ROMBAR = 76, /* -device rombar=0|1 */ QEMU_CAPS_PCI_ROMBAR = 76, /* -device rombar=0|1 */
QEMU_CAPS_ICH9_AHCI = 77, /* -device ich9-ahci */
QEMU_CAPS_LAST, /* this must always be the last item */ QEMU_CAPS_LAST, /* this must always be the last item */
}; };

View File

@ -1776,6 +1776,12 @@ qemuBuildDriveDevStr(virDomainDiskDefPtr disk,
disk->info.addr.drive.bus, disk->info.addr.drive.bus,
disk->info.addr.drive.unit); disk->info.addr.drive.unit);
break; break;
case VIR_DOMAIN_DISK_BUS_SATA:
virBufferAddLit(&opt, "ide-drive");
virBufferAsprintf(&opt, ",bus=ahci%d.%d",
disk->info.addr.drive.controller,
disk->info.addr.drive.unit);
break;
case VIR_DOMAIN_DISK_BUS_VIRTIO: case VIR_DOMAIN_DISK_BUS_VIRTIO:
virBufferAddLit(&opt, "virtio-blk-pci"); virBufferAddLit(&opt, "virtio-blk-pci");
qemuBuildIoEventFdStr(&opt, disk->ioeventfd, qemuCaps); qemuBuildIoEventFdStr(&opt, disk->ioeventfd, qemuCaps);
@ -1983,6 +1989,10 @@ qemuBuildControllerDevStr(virDomainControllerDefPtr def,
virBufferAsprintf(&buf, "usb-ccid,id=ccid%d", def->idx); virBufferAsprintf(&buf, "usb-ccid,id=ccid%d", def->idx);
break; break;
case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
virBufferAsprintf(&buf, "ahci,id=ahci%d", def->idx);
break;
case VIR_DOMAIN_CONTROLLER_TYPE_USB: case VIR_DOMAIN_CONTROLLER_TYPE_USB:
if (qemuBuildUSBControllerDevStr(def, qemuCaps, &buf) == -1) if (qemuBuildUSBControllerDevStr(def, qemuCaps, &buf) == -1)
goto error; goto error;
@ -3783,14 +3793,22 @@ qemuBuildCommandLine(virConnectPtr conn,
cont->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC) cont->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC)
continue; continue;
/* QEMU doesn't implement a SATA driver */ /* Only recent QEMU implements a SATA (AHCI) controller */
if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_SATA) { if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_SATA) {
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, if (!qemuCapsGet(qemuCaps, QEMU_CAPS_ICH9_AHCI)) {
"%s", _("SATA is not supported with this QEMU binary")); qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
goto error; "%s", _("SATA is not supported with this QEMU binary"));
} goto error;
} else {
char *devstr;
if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB && virCommandAddArg(cmd, "-device");
if (!(devstr = qemuBuildControllerDevStr(cont, qemuCaps, NULL)))
goto error;
virCommandAddArg(cmd, devstr);
}
} else if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
def->controllers[i]->model == -1 && def->controllers[i]->model == -1 &&
!qemuCapsGet(qemuCaps, QEMU_CAPS_PIIX3_USB_UHCI)) { !qemuCapsGet(qemuCaps, QEMU_CAPS_PIIX3_USB_UHCI)) {
if (usblegacy) { if (usblegacy) {

View File

@ -0,0 +1,6 @@
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \
unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device ahci,id=ahci0,\
bus=pci.0,addr=0x3 -drive file=/dev/HostVG/QEMUGuest1,if=none,\
id=drive-sata0-0-0 -device ide-drive,bus=ahci0.0,drive=drive-sata0-0-0,\
id=sata0-0-0 -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4

View File

@ -0,0 +1,25 @@
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory>219136</memory>
<currentMemory>219136</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu</emulator>
<disk type='block' device='disk'>
<source dev='/dev/HostVG/QEMUGuest1'/>
<target dev='sda' bus='sata'/>
<address type='drive' controller='0' bus='0' unit='0'/>
</disk>
<controller type='sata' index='0'/>
<memballoon model='virtio'/>
</devices>
</domain>

View File

@ -363,6 +363,9 @@ mymain(void)
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
DO_TEST("disk-scsi-device-auto", false, DO_TEST("disk-scsi-device-auto", false,
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
DO_TEST("disk-sata-device", false,
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE,
QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_ICH9_AHCI);
DO_TEST("disk-aio", false, DO_TEST("disk-aio", false,
QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_AIO, QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_AIO,
QEMU_CAPS_DRIVE_CACHE_V2, QEMU_CAPS_DRIVE_FORMAT); QEMU_CAPS_DRIVE_CACHE_V2, QEMU_CAPS_DRIVE_FORMAT);