ahci-test.c 50.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 * AHCI test cases
 *
 * Copyright (c) 2014 John Snow <jsnow@redhat.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <stdint.h>
#include <string.h>
#include <stdio.h>
28
#include <getopt.h>
29 30 31
#include <glib.h>

#include "libqtest.h"
J
John Snow 已提交
32
#include "libqos/libqos-pc.h"
J
John Snow 已提交
33
#include "libqos/ahci.h"
34 35 36 37 38 39 40 41
#include "libqos/pci-pc.h"

#include "qemu-common.h"
#include "qemu/host-utils.h"

#include "hw/pci/pci_ids.h"
#include "hw/pci/pci_regs.h"

42 43 44
/* Test images sizes in MB */
#define TEST_IMAGE_SIZE_MB_LARGE (200 * 1024)
#define TEST_IMAGE_SIZE_MB_SMALL 64
45 46 47

/*** Globals ***/
static char tmp_path[] = "/tmp/qtest.XXXXXX";
J
John Snow 已提交
48
static char debug_path[] = "/tmp/qtest-blkdebug.XXXXXX";
49
static char mig_socket[] = "/tmp/qtest-migration.XXXXXX";
50
static bool ahci_pedantic;
51
static const char *imgfmt;
52
static unsigned test_image_size_mb;
53

54
/*** Function Declarations ***/
55
static void ahci_test_port_spec(AHCIQState *ahci, uint8_t port);
56 57
static void ahci_test_pci_spec(AHCIQState *ahci);
static void ahci_test_pci_caps(AHCIQState *ahci, uint16_t header,
58
                               uint8_t offset);
59 60 61
static void ahci_test_satacap(AHCIQState *ahci, uint8_t offset);
static void ahci_test_msicap(AHCIQState *ahci, uint8_t offset);
static void ahci_test_pmcap(AHCIQState *ahci, uint8_t offset);
62 63 64

/*** Utilities ***/

65 66 67 68 69
static uint64_t mb_to_sectors(uint64_t image_size_mb)
{
    return (image_size_mb * 1024 * 1024) / AHCI_SECTOR_SIZE;
}

70 71 72 73 74 75 76 77 78 79 80
static void string_bswap16(uint16_t *s, size_t bytes)
{
    g_assert_cmphex((bytes & 1), ==, 0);
    bytes /= 2;

    while (bytes--) {
        *s = bswap16(*s);
        s++;
    }
}

J
John Snow 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
/**
 * Verify that the transfer did not corrupt our state at all.
 */
static void verify_state(AHCIQState *ahci)
{
    int i, j;
    uint32_t ahci_fingerprint;
    uint64_t hba_base;
    uint64_t hba_stored;
    AHCICommandHeader cmd;

    ahci_fingerprint = qpci_config_readl(ahci->dev, PCI_VENDOR_ID);
    g_assert_cmphex(ahci_fingerprint, ==, ahci->fingerprint);

    /* If we haven't initialized, this is as much as can be validated. */
    if (!ahci->hba_base) {
        return;
    }

    hba_base = (uint64_t)qpci_config_readl(ahci->dev, PCI_BASE_ADDRESS_5);
    hba_stored = (uint64_t)(uintptr_t)ahci->hba_base;
    g_assert_cmphex(hba_base, ==, hba_stored);

    g_assert_cmphex(ahci_rreg(ahci, AHCI_CAP), ==, ahci->cap);
    g_assert_cmphex(ahci_rreg(ahci, AHCI_CAP2), ==, ahci->cap2);

    for (i = 0; i < 32; i++) {
        g_assert_cmphex(ahci_px_rreg(ahci, i, AHCI_PX_FB), ==,
                        ahci->port[i].fb);
        g_assert_cmphex(ahci_px_rreg(ahci, i, AHCI_PX_CLB), ==,
                        ahci->port[i].clb);
        for (j = 0; j < 32; j++) {
            ahci_get_command_header(ahci, i, j, &cmd);
            g_assert_cmphex(cmd.prdtl, ==, ahci->port[i].prdtl[j]);
            g_assert_cmphex(cmd.ctba, ==, ahci->port[i].ctba[j]);
        }
    }
}

static void ahci_migrate(AHCIQState *from, AHCIQState *to, const char *uri)
{
    QOSState *tmp = to->parent;
    QPCIDevice *dev = to->dev;
124 125
    char *uri_local = NULL;

J
John Snow 已提交
126
    if (uri == NULL) {
127 128
        uri_local = g_strdup_printf("%s%s", "unix:", mig_socket);
        uri = uri_local;
J
John Snow 已提交
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
    }

    /* context will be 'to' after completion. */
    migrate(from->parent, to->parent, uri);

    /* We'd like for the AHCIState objects to still point
     * to information specific to its specific parent
     * instance, but otherwise just inherit the new data. */
    memcpy(to, from, sizeof(AHCIQState));
    to->parent = tmp;
    to->dev = dev;

    tmp = from->parent;
    dev = from->dev;
    memset(from, 0x00, sizeof(AHCIQState));
    from->parent = tmp;
    from->dev = dev;

    verify_state(to);
148
    g_free(uri_local);
J
John Snow 已提交
149 150
}

151 152 153
/*** Test Setup & Teardown ***/

/**
J
John Snow 已提交
154
 * Start a Q35 machine and bookmark a handle to the AHCI device.
155
 */
156
static AHCIQState *ahci_vboot(const char *cli, va_list ap)
157
{
J
John Snow 已提交
158
    AHCIQState *s;
159

J
John Snow 已提交
160
    s = g_malloc0(sizeof(AHCIQState));
161
    s->parent = qtest_pc_vboot(cli, ap);
J
John Snow 已提交
162
    alloc_set_flags(s->parent->alloc, ALLOC_LEAK_ASSERT);
163

J
John Snow 已提交
164
    /* Verify that we have an AHCI device present. */
165
    s->dev = get_ahci_device(&s->fingerprint);
166

J
John Snow 已提交
167
    return s;
168 169
}

170 171 172 173 174 175 176 177 178 179 180 181 182 183
/**
 * Start a Q35 machine and bookmark a handle to the AHCI device.
 */
static AHCIQState *ahci_boot(const char *cli, ...)
{
    AHCIQState *s;
    va_list ap;

    if (cli) {
        va_start(ap, cli);
        s = ahci_vboot(cli, ap);
        va_end(ap);
    } else {
        cli = "-drive if=none,id=drive0,file=%s,cache=writeback,serial=%s"
184
            ",format=%s"
185 186 187
            " -M q35 "
            "-device ide-hd,drive=drive0 "
            "-global ide-hd.ver=%s";
188
        s = ahci_boot(cli, tmp_path, "testdisk", imgfmt, "version");
189 190 191 192 193
    }

    return s;
}

194 195 196
/**
 * Clean up the PCI device, then terminate the QEMU instance.
 */
J
John Snow 已提交
197
static void ahci_shutdown(AHCIQState *ahci)
198
{
J
John Snow 已提交
199
    QOSState *qs = ahci->parent;
J
John Snow 已提交
200 201

    set_context(qs);
J
John Snow 已提交
202
    ahci_clean_mem(ahci);
J
John Snow 已提交
203 204 205
    free_ahci_device(ahci->dev);
    g_free(ahci);
    qtest_shutdown(qs);
206 207
}

208 209 210 211
/**
 * Boot and fully enable the HBA device.
 * @see ahci_boot, ahci_pci_enable and ahci_hba_enable.
 */
212
static AHCIQState *ahci_boot_and_enable(const char *cli, ...)
213 214
{
    AHCIQState *ahci;
215
    va_list ap;
216 217
    uint16_t buff[256];
    uint8_t port;
218 219 220 221 222 223 224 225

    if (cli) {
        va_start(ap, cli);
        ahci = ahci_vboot(cli, ap);
        va_end(ap);
    } else {
        ahci = ahci_boot(NULL);
    }
226 227 228

    ahci_pci_enable(ahci);
    ahci_hba_enable(ahci);
229 230 231 232
    /* Initialize test device */
    port = ahci_port_select(ahci);
    ahci_port_clear(ahci, port);
    ahci_io(ahci, port, CMD_IDENTIFY, &buff, sizeof(buff), 0);
233 234 235 236

    return ahci;
}

237 238 239 240 241
/*** Specification Adherence Tests ***/

/**
 * Implementation for test_pci_spec. Ensures PCI configuration space is sane.
 */
242
static void ahci_test_pci_spec(AHCIQState *ahci)
243 244 245 246 247 248
{
    uint8_t datab;
    uint16_t data;
    uint32_t datal;

    /* Most of these bits should start cleared until we turn them on. */
249
    data = qpci_config_readw(ahci->dev, PCI_COMMAND);
250 251 252 253 254 255 256 257 258 259 260
    ASSERT_BIT_CLEAR(data, PCI_COMMAND_MEMORY);
    ASSERT_BIT_CLEAR(data, PCI_COMMAND_MASTER);
    ASSERT_BIT_CLEAR(data, PCI_COMMAND_SPECIAL);     /* Reserved */
    ASSERT_BIT_CLEAR(data, PCI_COMMAND_VGA_PALETTE); /* Reserved */
    ASSERT_BIT_CLEAR(data, PCI_COMMAND_PARITY);
    ASSERT_BIT_CLEAR(data, PCI_COMMAND_WAIT);        /* Reserved */
    ASSERT_BIT_CLEAR(data, PCI_COMMAND_SERR);
    ASSERT_BIT_CLEAR(data, PCI_COMMAND_FAST_BACK);
    ASSERT_BIT_CLEAR(data, PCI_COMMAND_INTX_DISABLE);
    ASSERT_BIT_CLEAR(data, 0xF800);                  /* Reserved */

261
    data = qpci_config_readw(ahci->dev, PCI_STATUS);
262 263 264 265 266 267 268 269 270 271 272 273
    ASSERT_BIT_CLEAR(data, 0x01 | 0x02 | 0x04);     /* Reserved */
    ASSERT_BIT_CLEAR(data, PCI_STATUS_INTERRUPT);
    ASSERT_BIT_SET(data, PCI_STATUS_CAP_LIST);      /* must be set */
    ASSERT_BIT_CLEAR(data, PCI_STATUS_UDF);         /* Reserved */
    ASSERT_BIT_CLEAR(data, PCI_STATUS_PARITY);
    ASSERT_BIT_CLEAR(data, PCI_STATUS_SIG_TARGET_ABORT);
    ASSERT_BIT_CLEAR(data, PCI_STATUS_REC_TARGET_ABORT);
    ASSERT_BIT_CLEAR(data, PCI_STATUS_REC_MASTER_ABORT);
    ASSERT_BIT_CLEAR(data, PCI_STATUS_SIG_SYSTEM_ERROR);
    ASSERT_BIT_CLEAR(data, PCI_STATUS_DETECTED_PARITY);

    /* RID occupies the low byte, CCs occupy the high three. */
274
    datal = qpci_config_readl(ahci->dev, PCI_CLASS_REVISION);
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
    if (ahci_pedantic) {
        /* AHCI 1.3 specifies that at-boot, the RID should reset to 0x00,
         * Though in practice this is likely seldom true. */
        ASSERT_BIT_CLEAR(datal, 0xFF);
    }

    /* BCC *must* equal 0x01. */
    g_assert_cmphex(PCI_BCC(datal), ==, 0x01);
    if (PCI_SCC(datal) == 0x01) {
        /* IDE */
        ASSERT_BIT_SET(0x80000000, datal);
        ASSERT_BIT_CLEAR(0x60000000, datal);
    } else if (PCI_SCC(datal) == 0x04) {
        /* RAID */
        g_assert_cmphex(PCI_PI(datal), ==, 0);
    } else if (PCI_SCC(datal) == 0x06) {
        /* AHCI */
        g_assert_cmphex(PCI_PI(datal), ==, 0x01);
    } else {
        g_assert_not_reached();
    }

297
    datab = qpci_config_readb(ahci->dev, PCI_CACHE_LINE_SIZE);
298 299
    g_assert_cmphex(datab, ==, 0);

300
    datab = qpci_config_readb(ahci->dev, PCI_LATENCY_TIMER);
301 302 303
    g_assert_cmphex(datab, ==, 0);

    /* Only the bottom 7 bits must be off. */
304
    datab = qpci_config_readb(ahci->dev, PCI_HEADER_TYPE);
305 306 307
    ASSERT_BIT_CLEAR(datab, 0x7F);

    /* BIST is optional, but the low 7 bits must always start off regardless. */
308
    datab = qpci_config_readb(ahci->dev, PCI_BIST);
309 310 311
    ASSERT_BIT_CLEAR(datab, 0x7F);

    /* BARS 0-4 do not have a boot spec, but ABAR/BAR5 must be clean. */
312
    datal = qpci_config_readl(ahci->dev, PCI_BASE_ADDRESS_5);
313 314
    g_assert_cmphex(datal, ==, 0);

315 316
    qpci_config_writel(ahci->dev, PCI_BASE_ADDRESS_5, 0xFFFFFFFF);
    datal = qpci_config_readl(ahci->dev, PCI_BASE_ADDRESS_5);
317 318 319 320 321
    /* ABAR must be 32-bit, memory mapped, non-prefetchable and
     * must be >= 512 bytes. To that end, bits 0-8 must be off. */
    ASSERT_BIT_CLEAR(datal, 0xFF);

    /* Capability list MUST be present, */
322
    datal = qpci_config_readl(ahci->dev, PCI_CAPABILITY_LIST);
323 324 325 326 327
    /* But these bits are reserved. */
    ASSERT_BIT_CLEAR(datal, ~0xFF);
    g_assert_cmphex(datal, !=, 0);

    /* Check specification adherence for capability extenstions. */
328
    data = qpci_config_readw(ahci->dev, datal);
329

330
    switch (ahci->fingerprint) {
331 332 333 334 335 336 337 338 339 340 341 342
    case AHCI_INTEL_ICH9:
        /* Intel ICH9 Family Datasheet 14.1.19 p.550 */
        g_assert_cmphex((data & 0xFF), ==, PCI_CAP_ID_MSI);
        break;
    default:
        /* AHCI 1.3, Section 2.1.14 -- CAP must point to PMCAP. */
        g_assert_cmphex((data & 0xFF), ==, PCI_CAP_ID_PM);
    }

    ahci_test_pci_caps(ahci, data, (uint8_t)datal);

    /* Reserved. */
343
    datal = qpci_config_readl(ahci->dev, PCI_CAPABILITY_LIST + 4);
344 345 346
    g_assert_cmphex(datal, ==, 0);

    /* IPIN might vary, but ILINE must be off. */
347
    datab = qpci_config_readb(ahci->dev, PCI_INTERRUPT_LINE);
348 349 350 351 352 353
    g_assert_cmphex(datab, ==, 0);
}

/**
 * Test PCI capabilities for AHCI specification adherence.
 */
354
static void ahci_test_pci_caps(AHCIQState *ahci, uint16_t header,
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
                               uint8_t offset)
{
    uint8_t cid = header & 0xFF;
    uint8_t next = header >> 8;

    g_test_message("CID: %02x; next: %02x", cid, next);

    switch (cid) {
    case PCI_CAP_ID_PM:
        ahci_test_pmcap(ahci, offset);
        break;
    case PCI_CAP_ID_MSI:
        ahci_test_msicap(ahci, offset);
        break;
    case PCI_CAP_ID_SATA:
        ahci_test_satacap(ahci, offset);
        break;

    default:
        g_test_message("Unknown CAP 0x%02x", cid);
    }

    if (next) {
378
        ahci_test_pci_caps(ahci, qpci_config_readw(ahci->dev, next), next);
379 380 381 382 383 384
    }
}

/**
 * Test SATA PCI capabilitity for AHCI specification adherence.
 */
385
static void ahci_test_satacap(AHCIQState *ahci, uint8_t offset)
386 387 388 389 390 391 392
{
    uint16_t dataw;
    uint32_t datal;

    g_test_message("Verifying SATACAP");

    /* Assert that the SATACAP version is 1.0, And reserved bits are empty. */
393
    dataw = qpci_config_readw(ahci->dev, offset + 2);
394 395 396
    g_assert_cmphex(dataw, ==, 0x10);

    /* Grab the SATACR1 register. */
397
    datal = qpci_config_readw(ahci->dev, offset + 4);
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419

    switch (datal & 0x0F) {
    case 0x04: /* BAR0 */
    case 0x05: /* BAR1 */
    case 0x06:
    case 0x07:
    case 0x08:
    case 0x09: /* BAR5 */
    case 0x0F: /* Immediately following SATACR1 in PCI config space. */
        break;
    default:
        /* Invalid BARLOC for the Index Data Pair. */
        g_assert_not_reached();
    }

    /* Reserved. */
    g_assert_cmphex((datal >> 24), ==, 0x00);
}

/**
 * Test MSI PCI capability for AHCI specification adherence.
 */
420
static void ahci_test_msicap(AHCIQState *ahci, uint8_t offset)
421 422 423 424 425 426
{
    uint16_t dataw;
    uint32_t datal;

    g_test_message("Verifying MSICAP");

427
    dataw = qpci_config_readw(ahci->dev, offset + PCI_MSI_FLAGS);
428 429 430 431
    ASSERT_BIT_CLEAR(dataw, PCI_MSI_FLAGS_ENABLE);
    ASSERT_BIT_CLEAR(dataw, PCI_MSI_FLAGS_QSIZE);
    ASSERT_BIT_CLEAR(dataw, PCI_MSI_FLAGS_RESERVED);

432
    datal = qpci_config_readl(ahci->dev, offset + PCI_MSI_ADDRESS_LO);
433 434 435 436
    g_assert_cmphex(datal, ==, 0);

    if (dataw & PCI_MSI_FLAGS_64BIT) {
        g_test_message("MSICAP is 64bit");
437
        datal = qpci_config_readl(ahci->dev, offset + PCI_MSI_ADDRESS_HI);
438
        g_assert_cmphex(datal, ==, 0);
439
        dataw = qpci_config_readw(ahci->dev, offset + PCI_MSI_DATA_64);
440 441 442
        g_assert_cmphex(dataw, ==, 0);
    } else {
        g_test_message("MSICAP is 32bit");
443
        dataw = qpci_config_readw(ahci->dev, offset + PCI_MSI_DATA_32);
444 445 446 447 448 449 450
        g_assert_cmphex(dataw, ==, 0);
    }
}

/**
 * Test Power Management PCI capability for AHCI specification adherence.
 */
451
static void ahci_test_pmcap(AHCIQState *ahci, uint8_t offset)
452 453 454 455 456
{
    uint16_t dataw;

    g_test_message("Verifying PMCAP");

457
    dataw = qpci_config_readw(ahci->dev, offset + PCI_PM_PMC);
458 459 460 461 462
    ASSERT_BIT_CLEAR(dataw, PCI_PM_CAP_PME_CLOCK);
    ASSERT_BIT_CLEAR(dataw, PCI_PM_CAP_RESERVED);
    ASSERT_BIT_CLEAR(dataw, PCI_PM_CAP_D1);
    ASSERT_BIT_CLEAR(dataw, PCI_PM_CAP_D2);

463
    dataw = qpci_config_readw(ahci->dev, offset + PCI_PM_CTRL);
464 465 466 467 468 469
    ASSERT_BIT_CLEAR(dataw, PCI_PM_CTRL_STATE_MASK);
    ASSERT_BIT_CLEAR(dataw, PCI_PM_CTRL_RESERVED);
    ASSERT_BIT_CLEAR(dataw, PCI_PM_CTRL_DATA_SEL_MASK);
    ASSERT_BIT_CLEAR(dataw, PCI_PM_CTRL_DATA_SCALE_MASK);
}

470
static void ahci_test_hba_spec(AHCIQState *ahci)
471 472
{
    unsigned i;
473
    uint32_t reg;
474 475 476 477
    uint32_t ports;
    uint8_t nports_impl;
    uint8_t maxports;

478
    g_assert(ahci != NULL);
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500

    /*
     * Note that the AHCI spec does expect the BIOS to set up a few things:
     * CAP.SSS    - Support for staggered spin-up            (t/f)
     * CAP.SMPS   - Support for mechanical presence switches (t/f)
     * PI         - Ports Implemented                        (1-32)
     * PxCMD.HPCP - Hot Plug Capable Port
     * PxCMD.MPSP - Mechanical Presence Switch Present
     * PxCMD.CPD  - Cold Presence Detection support
     *
     * Additional items are touched if CAP.SSS is on, see AHCI 10.1.1 p.97:
     * Foreach Port Implemented:
     * -PxCMD.ST, PxCMD.CR, PxCMD.FRE, PxCMD.FR, PxSCTL.DET are 0
     * -PxCLB/U and PxFB/U are set to valid regions in memory
     * -PxSUD is set to 1.
     * -PxSSTS.DET is polled for presence; if detected, we continue:
     * -PxSERR is cleared with 1's.
     * -If PxTFD.STS.BSY, PxTFD.STS.DRQ, and PxTFD.STS.ERR are all zero,
     *  the device is ready.
     */

    /* 1 CAP - Capabilities Register */
501
    ahci->cap = ahci_rreg(ahci, AHCI_CAP);
502
    ASSERT_BIT_CLEAR(ahci->cap, AHCI_CAP_RESERVED);
503 504

    /* 2 GHC - Global Host Control */
505
    reg = ahci_rreg(ahci, AHCI_GHC);
506 507 508
    ASSERT_BIT_CLEAR(reg, AHCI_GHC_HR);
    ASSERT_BIT_CLEAR(reg, AHCI_GHC_IE);
    ASSERT_BIT_CLEAR(reg, AHCI_GHC_MRSM);
509
    if (BITSET(ahci->cap, AHCI_CAP_SAM)) {
510 511 512 513 514 515 516 517
        g_test_message("Supports AHCI-Only Mode: GHC_AE is Read-Only.");
        ASSERT_BIT_SET(reg, AHCI_GHC_AE);
    } else {
        g_test_message("Supports AHCI/Legacy mix.");
        ASSERT_BIT_CLEAR(reg, AHCI_GHC_AE);
    }

    /* 3 IS - Interrupt Status */
518
    reg = ahci_rreg(ahci, AHCI_IS);
519 520 521
    g_assert_cmphex(reg, ==, 0);

    /* 4 PI - Ports Implemented */
522
    ports = ahci_rreg(ahci, AHCI_PI);
523 524 525 526
    /* Ports Implemented must be non-zero. */
    g_assert_cmphex(ports, !=, 0);
    /* Ports Implemented must be <= Number of Ports. */
    nports_impl = ctpopl(ports);
527
    g_assert_cmpuint(((AHCI_CAP_NP & ahci->cap) + 1), >=, nports_impl);
528 529 530 531

    /* Ports must be within the proper range. Given a mapping of SIZE,
     * 256 bytes are used for global HBA control, and the rest is used
     * for ports data, at 0x80 bytes each. */
532 533
    g_assert_cmphex(ahci->barsize, >, 0);
    maxports = (ahci->barsize - HBA_DATA_REGION_SIZE) / HBA_PORT_DATA_SIZE;
534 535 536 537
    /* e.g, 30 ports for 4K of memory. (4096 - 256) / 128 = 30 */
    g_assert_cmphex((reg >> maxports), ==, 0);

    /* 5 AHCI Version */
538
    reg = ahci_rreg(ahci, AHCI_VS);
539 540 541 542 543 544 545 546 547 548 549 550
    switch (reg) {
    case AHCI_VERSION_0_95:
    case AHCI_VERSION_1_0:
    case AHCI_VERSION_1_1:
    case AHCI_VERSION_1_2:
    case AHCI_VERSION_1_3:
        break;
    default:
        g_assert_not_reached();
    }

    /* 6 Command Completion Coalescing Control: depends on CAP.CCCS. */
551
    reg = ahci_rreg(ahci, AHCI_CCCCTL);
552
    if (BITSET(ahci->cap, AHCI_CAP_CCCS)) {
553 554 555 556 557 558 559 560 561
        ASSERT_BIT_CLEAR(reg, AHCI_CCCCTL_EN);
        ASSERT_BIT_CLEAR(reg, AHCI_CCCCTL_RESERVED);
        ASSERT_BIT_SET(reg, AHCI_CCCCTL_CC);
        ASSERT_BIT_SET(reg, AHCI_CCCCTL_TV);
    } else {
        g_assert_cmphex(reg, ==, 0);
    }

    /* 7 CCC_PORTS */
562
    reg = ahci_rreg(ahci, AHCI_CCCPORTS);
563 564 565 566
    /* Must be zeroes initially regardless of CAP.CCCS */
    g_assert_cmphex(reg, ==, 0);

    /* 8 EM_LOC */
567
    reg = ahci_rreg(ahci, AHCI_EMLOC);
568
    if (BITCLR(ahci->cap, AHCI_CAP_EMS)) {
569 570 571 572
        g_assert_cmphex(reg, ==, 0);
    }

    /* 9 EM_CTL */
573
    reg = ahci_rreg(ahci, AHCI_EMCTL);
574
    if (BITSET(ahci->cap, AHCI_CAP_EMS)) {
575 576 577 578 579 580 581 582 583
        ASSERT_BIT_CLEAR(reg, AHCI_EMCTL_STSMR);
        ASSERT_BIT_CLEAR(reg, AHCI_EMCTL_CTLTM);
        ASSERT_BIT_CLEAR(reg, AHCI_EMCTL_CTLRST);
        ASSERT_BIT_CLEAR(reg, AHCI_EMCTL_RESERVED);
    } else {
        g_assert_cmphex(reg, ==, 0);
    }

    /* 10 CAP2 -- Capabilities Extended */
584
    ahci->cap2 = ahci_rreg(ahci, AHCI_CAP2);
585
    ASSERT_BIT_CLEAR(ahci->cap2, AHCI_CAP2_RESERVED);
586 587

    /* 11 BOHC -- Bios/OS Handoff Control */
588
    reg = ahci_rreg(ahci, AHCI_BOHC);
589 590 591 592 593
    g_assert_cmphex(reg, ==, 0);

    /* 12 -- 23: Reserved */
    g_test_message("Verifying HBA reserved area is empty.");
    for (i = AHCI_RESERVED; i < AHCI_NVMHCI; ++i) {
594
        reg = ahci_rreg(ahci, i);
595 596 597 598
        g_assert_cmphex(reg, ==, 0);
    }

    /* 24 -- 39: NVMHCI */
599
    if (BITCLR(ahci->cap2, AHCI_CAP2_NVMP)) {
600 601
        g_test_message("Verifying HBA/NVMHCI area is empty.");
        for (i = AHCI_NVMHCI; i < AHCI_VENDOR; ++i) {
602
            reg = ahci_rreg(ahci, i);
603 604 605 606 607 608 609
            g_assert_cmphex(reg, ==, 0);
        }
    }

    /* 40 -- 63: Vendor */
    g_test_message("Verifying HBA/Vendor area is empty.");
    for (i = AHCI_VENDOR; i < AHCI_PORTS; ++i) {
610
        reg = ahci_rreg(ahci, i);
611 612 613 614 615 616 617
        g_assert_cmphex(reg, ==, 0);
    }

    /* 64 -- XX: Port Space */
    for (i = 0; ports || (i < maxports); ports >>= 1, ++i) {
        if (BITSET(ports, 0x1)) {
            g_test_message("Testing port %u for spec", i);
618
            ahci_test_port_spec(ahci, i);
619 620 621 622 623 624 625 626
        } else {
            uint16_t j;
            uint16_t low = AHCI_PORTS + (32 * i);
            uint16_t high = AHCI_PORTS + (32 * (i + 1));
            g_test_message("Asserting unimplemented port %u "
                           "(reg [%u-%u]) is empty.",
                           i, low, high - 1);
            for (j = low; j < high; ++j) {
627
                reg = ahci_rreg(ahci, j);
628 629 630 631 632 633 634 635 636
                g_assert_cmphex(reg, ==, 0);
            }
        }
    }
}

/**
 * Test the memory space for one port for specification adherence.
 */
637
static void ahci_test_port_spec(AHCIQState *ahci, uint8_t port)
638 639 640 641 642
{
    uint32_t reg;
    unsigned i;

    /* (0) CLB */
643
    reg = ahci_px_rreg(ahci, port, AHCI_PX_CLB);
644 645 646
    ASSERT_BIT_CLEAR(reg, AHCI_PX_CLB_RESERVED);

    /* (1) CLBU */
647
    if (BITCLR(ahci->cap, AHCI_CAP_S64A)) {
648
        reg = ahci_px_rreg(ahci, port, AHCI_PX_CLBU);
649 650 651 652
        g_assert_cmphex(reg, ==, 0);
    }

    /* (2) FB */
653
    reg = ahci_px_rreg(ahci, port, AHCI_PX_FB);
654 655 656
    ASSERT_BIT_CLEAR(reg, AHCI_PX_FB_RESERVED);

    /* (3) FBU */
657
    if (BITCLR(ahci->cap, AHCI_CAP_S64A)) {
658
        reg = ahci_px_rreg(ahci, port, AHCI_PX_FBU);
659 660 661 662
        g_assert_cmphex(reg, ==, 0);
    }

    /* (4) IS */
663
    reg = ahci_px_rreg(ahci, port, AHCI_PX_IS);
664 665 666
    g_assert_cmphex(reg, ==, 0);

    /* (5) IE */
667
    reg = ahci_px_rreg(ahci, port, AHCI_PX_IE);
668 669 670
    g_assert_cmphex(reg, ==, 0);

    /* (6) CMD */
671
    reg = ahci_px_rreg(ahci, port, AHCI_PX_CMD);
672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
    ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_FRE);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_RESERVED);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_CCS);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_FR);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_CR);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_PMA); /* And RW only if CAP.SPM */
    ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_APSTE); /* RW only if CAP2.APST */
    ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_ATAPI);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_DLAE);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_ALPE);  /* RW only if CAP.SALP */
    ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_ASP);   /* RW only if CAP.SALP */
    ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_ICC);
    /* If CPDetect support does not exist, CPState must be off. */
    if (BITCLR(reg, AHCI_PX_CMD_CPD)) {
        ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_CPS);
    }
    /* If MPSPresence is not set, MPSState must be off. */
    if (BITCLR(reg, AHCI_PX_CMD_MPSP)) {
        ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_MPSS);
    }
    /* If we do not support MPS, MPSS and MPSP must be off. */
693
    if (BITCLR(ahci->cap, AHCI_CAP_SMPS)) {
694 695 696 697
        ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_MPSS);
        ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_MPSP);
    }
    /* If, via CPD or MPSP we detect a drive, HPCP must be on. */
698
    if (BITANY(reg, AHCI_PX_CMD_CPD | AHCI_PX_CMD_MPSP)) {
699 700 701 702 703
        ASSERT_BIT_SET(reg, AHCI_PX_CMD_HPCP);
    }
    /* HPCP and ESP cannot both be active. */
    g_assert(!BITSET(reg, AHCI_PX_CMD_HPCP | AHCI_PX_CMD_ESP));
    /* If CAP.FBSS is not set, FBSCP must not be set. */
704
    if (BITCLR(ahci->cap, AHCI_CAP_FBSS)) {
705 706 707 708
        ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_FBSCP);
    }

    /* (7) RESERVED */
709
    reg = ahci_px_rreg(ahci, port, AHCI_PX_RES1);
710 711 712
    g_assert_cmphex(reg, ==, 0);

    /* (8) TFD */
713
    reg = ahci_px_rreg(ahci, port, AHCI_PX_TFD);
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730
    /* At boot, prior to an FIS being received, the TFD register should be 0x7F,
     * which breaks down as follows, as seen in AHCI 1.3 sec 3.3.8, p. 27. */
    ASSERT_BIT_SET(reg, AHCI_PX_TFD_STS_ERR);
    ASSERT_BIT_SET(reg, AHCI_PX_TFD_STS_CS1);
    ASSERT_BIT_SET(reg, AHCI_PX_TFD_STS_DRQ);
    ASSERT_BIT_SET(reg, AHCI_PX_TFD_STS_CS2);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_STS_BSY);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_ERR);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_RESERVED);

    /* (9) SIG */
    /* Though AHCI specifies the boot value should be 0xFFFFFFFF,
     * Even when GHC.ST is zero, the AHCI HBA may receive the initial
     * D2H register FIS and update the signature asynchronously,
     * so we cannot expect a value here. AHCI 1.3, sec 3.3.9, pp 27-28 */

    /* (10) SSTS / SCR0: SStatus */
731
    reg = ahci_px_rreg(ahci, port, AHCI_PX_SSTS);
732 733 734 735 736
    ASSERT_BIT_CLEAR(reg, AHCI_PX_SSTS_RESERVED);
    /* Even though the register should be 0 at boot, it is asynchronous and
     * prone to change, so we cannot test any well known value. */

    /* (11) SCTL / SCR2: SControl */
737
    reg = ahci_px_rreg(ahci, port, AHCI_PX_SCTL);
738 739 740
    g_assert_cmphex(reg, ==, 0);

    /* (12) SERR / SCR1: SError */
741
    reg = ahci_px_rreg(ahci, port, AHCI_PX_SERR);
742 743 744
    g_assert_cmphex(reg, ==, 0);

    /* (13) SACT / SCR3: SActive */
745
    reg = ahci_px_rreg(ahci, port, AHCI_PX_SACT);
746 747 748
    g_assert_cmphex(reg, ==, 0);

    /* (14) CI */
749
    reg = ahci_px_rreg(ahci, port, AHCI_PX_CI);
750 751 752
    g_assert_cmphex(reg, ==, 0);

    /* (15) SNTF */
753
    reg = ahci_px_rreg(ahci, port, AHCI_PX_SNTF);
754 755 756
    g_assert_cmphex(reg, ==, 0);

    /* (16) FBS */
757
    reg = ahci_px_rreg(ahci, port, AHCI_PX_FBS);
758 759 760 761 762 763
    ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_EN);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_DEC);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_SDE);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_DEV);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_DWE);
    ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_RESERVED);
764
    if (BITSET(ahci->cap, AHCI_CAP_FBSS)) {
765 766 767 768 769 770
        /* if Port-Multiplier FIS-based switching avail, ADO must >= 2 */
        g_assert((reg & AHCI_PX_FBS_ADO) >> ctzl(AHCI_PX_FBS_ADO) >= 2);
    }

    /* [17 -- 27] RESERVED */
    for (i = AHCI_PX_RES2; i < AHCI_PX_VS; ++i) {
771
        reg = ahci_px_rreg(ahci, port, i);
772 773 774 775 776
        g_assert_cmphex(reg, ==, 0);
    }

    /* [28 -- 31] Vendor-Specific */
    for (i = AHCI_PX_VS; i < 32; ++i) {
777
        reg = ahci_px_rreg(ahci, port, i);
778 779 780 781 782 783
        if (reg) {
            g_test_message("INFO: Vendor register %u non-empty", i);
        }
    }
}

784 785 786 787
/**
 * Utilizing an initialized AHCI HBA, issue an IDENTIFY command to the first
 * device we see, then read and check the response.
 */
788
static void ahci_test_identify(AHCIQState *ahci)
789 790
{
    uint16_t buff[256];
J
John Snow 已提交
791
    unsigned px;
792
    int rc;
793
    uint16_t sect_size;
J
John Snow 已提交
794
    const size_t buffsize = 512;
795 796 797

    g_assert(ahci != NULL);

J
John Snow 已提交
798 799 800 801 802 803
    /**
     * This serves as a bit of a tutorial on AHCI device programming:
     *
     * (1) Create a data buffer for the IDENTIFY response to be sent to
     * (2) Create a Command Table buffer, where we will store the
     *     command and PRDT (Physical Region Descriptor Table)
804
     * (3) Construct an FIS host-to-device command structure, and write it to
J
John Snow 已提交
805 806 807 808 809 810 811 812 813 814 815 816
     *     the top of the Command Table buffer.
     * (4) Create one or more Physical Region Descriptors (PRDs) that describe
     *     a location in memory where data may be stored/retrieved.
     * (5) Write these PRDTs to the bottom (offset 0x80) of the Command Table.
     * (6) Each AHCI port has up to 32 command slots. Each slot contains a
     *     header that points to a Command Table buffer. Pick an unused slot
     *     and update it to point to the Command Table we have built.
     * (7) Now: Command #n points to our Command Table, and our Command Table
     *     contains the FIS (that describes our command) and the PRDTL, which
     *     describes our buffer.
     * (8) We inform the HBA via PxCI (Command Issue) that the command in slot
     *     #n is ready for processing.
817 818 819
     */

    /* Pick the first implemented and running port */
J
John Snow 已提交
820 821
    px = ahci_port_select(ahci);
    g_test_message("Selected port %u for test", px);
822

823
    /* Clear out the FIS Receive area and any pending interrupts. */
J
John Snow 已提交
824
    ahci_port_clear(ahci, px);
825

J
John Snow 已提交
826
    /* "Read" 512 bytes using CMD_IDENTIFY into the host buffer. */
827
    ahci_io(ahci, px, CMD_IDENTIFY, &buff, buffsize, 0);
828 829 830 831 832 833 834 835 836 837 838 839 840

    /* Check serial number/version in the buffer */
    /* NB: IDENTIFY strings are packed in 16bit little endian chunks.
     * Since we copy byte-for-byte in ahci-test, on both LE and BE, we need to
     * unchunk this data. By contrast, ide-test copies 2 bytes at a time, and
     * as a consequence, only needs to unchunk the data on LE machines. */
    string_bswap16(&buff[10], 20);
    rc = memcmp(&buff[10], "testdisk            ", 20);
    g_assert_cmphex(rc, ==, 0);

    string_bswap16(&buff[23], 8);
    rc = memcmp(&buff[23], "version ", 8);
    g_assert_cmphex(rc, ==, 0);
841 842

    sect_size = le16_to_cpu(*((uint16_t *)(&buff[5])));
843
    g_assert_cmphex(sect_size, ==, AHCI_SECTOR_SIZE);
844 845
}

J
John Snow 已提交
846
static void ahci_test_io_rw_simple(AHCIQState *ahci, unsigned bufsize,
847 848
                                   uint64_t sector, uint8_t read_cmd,
                                   uint8_t write_cmd)
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
{
    uint64_t ptr;
    uint8_t port;
    unsigned char *tx = g_malloc(bufsize);
    unsigned char *rx = g_malloc0(bufsize);

    g_assert(ahci != NULL);

    /* Pick the first running port and clear it. */
    port = ahci_port_select(ahci);
    ahci_port_clear(ahci, port);

    /*** Create pattern and transfer to guest ***/
    /* Data buffer in the guest */
    ptr = ahci_alloc(ahci, bufsize);
    g_assert(ptr);

J
John Snow 已提交
866
    /* Write some indicative pattern to our buffer. */
867
    generate_pattern(tx, bufsize, AHCI_SECTOR_SIZE);
868
    bufwrite(ptr, tx, bufsize);
869 870

    /* Write this buffer to disk, then read it back to the DMA buffer. */
871
    ahci_guest_io(ahci, port, write_cmd, ptr, bufsize, sector);
872
    qmemset(ptr, 0x00, bufsize);
873
    ahci_guest_io(ahci, port, read_cmd, ptr, bufsize, sector);
874 875

    /*** Read back the Data ***/
876
    bufread(ptr, rx, bufsize);
877 878 879 880 881 882 883
    g_assert_cmphex(memcmp(tx, rx, bufsize), ==, 0);

    ahci_free(ahci, ptr);
    g_free(tx);
    g_free(rx);
}

J
John Snow 已提交
884
static uint8_t ahci_test_nondata(AHCIQState *ahci, uint8_t ide_cmd)
J
John Snow 已提交
885
{
J
John Snow 已提交
886
    uint8_t port;
J
John Snow 已提交
887 888 889
    AHCICommand *cmd;

    /* Sanitize */
J
John Snow 已提交
890 891
    port = ahci_port_select(ahci);
    ahci_port_clear(ahci, port);
J
John Snow 已提交
892 893 894

    /* Issue Command */
    cmd = ahci_command_create(ide_cmd);
J
John Snow 已提交
895
    ahci_command_commit(ahci, cmd, port);
J
John Snow 已提交
896 897 898
    ahci_command_issue(ahci, cmd);
    ahci_command_verify(ahci, cmd);
    ahci_command_free(cmd);
J
John Snow 已提交
899 900

    return port;
J
John Snow 已提交
901 902 903 904 905 906 907
}

static void ahci_test_flush(AHCIQState *ahci)
{
    ahci_test_nondata(ahci, CMD_FLUSH_CACHE);
}

J
John Snow 已提交
908 909 910 911 912 913
static void ahci_test_max(AHCIQState *ahci)
{
    RegD2HFIS *d2h = g_malloc0(0x20);
    uint64_t nsect;
    uint8_t port;
    uint8_t cmd;
914
    uint64_t config_sect = mb_to_sectors(test_image_size_mb) - 1;
J
John Snow 已提交
915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934

    if (config_sect > 0xFFFFFF) {
        cmd = CMD_READ_MAX_EXT;
    } else {
        cmd = CMD_READ_MAX;
    }

    port = ahci_test_nondata(ahci, cmd);
    memread(ahci->port[port].fb + 0x40, d2h, 0x20);
    nsect = (uint64_t)d2h->lba_hi[2] << 40 |
        (uint64_t)d2h->lba_hi[1] << 32 |
        (uint64_t)d2h->lba_hi[0] << 24 |
        (uint64_t)d2h->lba_lo[2] << 16 |
        (uint64_t)d2h->lba_lo[1] << 8 |
        (uint64_t)d2h->lba_lo[0];

    g_assert_cmphex(nsect, ==, config_sect);
    g_free(d2h);
}

J
John Snow 已提交
935

936 937 938 939 940 941 942 943 944
/******************************************************************************/
/* Test Interfaces                                                            */
/******************************************************************************/

/**
 * Basic sanity test to boot a machine, find an AHCI device, and shutdown.
 */
static void test_sanity(void)
{
J
John Snow 已提交
945
    AHCIQState *ahci;
946
    ahci = ahci_boot(NULL);
947 948 949
    ahci_shutdown(ahci);
}

950 951 952 953 954 955
/**
 * Ensure that the PCI configuration space for the AHCI device is in-line with
 * the AHCI 1.3 specification for initial values.
 */
static void test_pci_spec(void)
{
J
John Snow 已提交
956
    AHCIQState *ahci;
957
    ahci = ahci_boot(NULL);
958
    ahci_test_pci_spec(ahci);
959 960 961
    ahci_shutdown(ahci);
}

962 963 964 965 966 967
/**
 * Engage the PCI AHCI device and sanity check the response.
 * Perform additional PCI config space bringup for the HBA.
 */
static void test_pci_enable(void)
{
J
John Snow 已提交
968
    AHCIQState *ahci;
969
    ahci = ahci_boot(NULL);
970
    ahci_pci_enable(ahci);
971 972 973
    ahci_shutdown(ahci);
}

974 975 976 977 978 979
/**
 * Investigate the memory mapped regions of the HBA,
 * and test them for AHCI specification adherence.
 */
static void test_hba_spec(void)
{
J
John Snow 已提交
980
    AHCIQState *ahci;
981

982
    ahci = ahci_boot(NULL);
983 984
    ahci_pci_enable(ahci);
    ahci_test_hba_spec(ahci);
985 986 987
    ahci_shutdown(ahci);
}

988 989 990 991 992 993
/**
 * Engage the HBA functionality of the AHCI PCI device,
 * and bring it into a functional idle state.
 */
static void test_hba_enable(void)
{
J
John Snow 已提交
994
    AHCIQState *ahci;
995

996
    ahci = ahci_boot(NULL);
997 998
    ahci_pci_enable(ahci);
    ahci_hba_enable(ahci);
999 1000 1001
    ahci_shutdown(ahci);
}

1002 1003 1004 1005 1006 1007
/**
 * Bring up the device and issue an IDENTIFY command.
 * Inspect the state of the HBA device and the data returned.
 */
static void test_identify(void)
{
J
John Snow 已提交
1008
    AHCIQState *ahci;
1009

1010
    ahci = ahci_boot_and_enable(NULL);
1011
    ahci_test_identify(ahci);
1012 1013 1014
    ahci_shutdown(ahci);
}

J
John Snow 已提交
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
/**
 * Fragmented DMA test: Perform a standard 4K DMA read/write
 * test, but make sure the physical regions are fragmented to
 * be very small, each just 32 bytes, to see how AHCI performs
 * with chunks defined to be much less than a sector.
 */
static void test_dma_fragmented(void)
{
    AHCIQState *ahci;
    AHCICommand *cmd;
    uint8_t px;
    size_t bufsize = 4096;
    unsigned char *tx = g_malloc(bufsize);
    unsigned char *rx = g_malloc0(bufsize);
    uint64_t ptr;

1031
    ahci = ahci_boot_and_enable(NULL);
J
John Snow 已提交
1032 1033 1034 1035
    px = ahci_port_select(ahci);
    ahci_port_clear(ahci, px);

    /* create pattern */
1036
    generate_pattern(tx, bufsize, AHCI_SECTOR_SIZE);
J
John Snow 已提交
1037 1038 1039 1040

    /* Create a DMA buffer in guest memory, and write our pattern to it. */
    ptr = guest_alloc(ahci->parent->alloc, bufsize);
    g_assert(ptr);
1041
    bufwrite(ptr, tx, bufsize);
J
John Snow 已提交
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057

    cmd = ahci_command_create(CMD_WRITE_DMA);
    ahci_command_adjust(cmd, 0, ptr, bufsize, 32);
    ahci_command_commit(ahci, cmd, px);
    ahci_command_issue(ahci, cmd);
    ahci_command_verify(ahci, cmd);
    g_free(cmd);

    cmd = ahci_command_create(CMD_READ_DMA);
    ahci_command_adjust(cmd, 0, ptr, bufsize, 32);
    ahci_command_commit(ahci, cmd, px);
    ahci_command_issue(ahci, cmd);
    ahci_command_verify(ahci, cmd);
    g_free(cmd);

    /* Read back the guest's receive buffer into local memory */
1058
    bufread(ptr, rx, bufsize);
J
John Snow 已提交
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
    guest_free(ahci->parent->alloc, ptr);

    g_assert_cmphex(memcmp(tx, rx, bufsize), ==, 0);

    ahci_shutdown(ahci);

    g_free(rx);
    g_free(tx);
}

J
John Snow 已提交
1069 1070 1071 1072
static void test_flush(void)
{
    AHCIQState *ahci;

1073
    ahci = ahci_boot_and_enable(NULL);
J
John Snow 已提交
1074 1075 1076 1077
    ahci_test_flush(ahci);
    ahci_shutdown(ahci);
}

J
John Snow 已提交
1078 1079 1080 1081 1082 1083 1084 1085 1086
static void test_flush_retry(void)
{
    AHCIQState *ahci;
    AHCICommand *cmd;
    uint8_t port;
    const char *s;

    prepare_blkdebug_script(debug_path, "flush_to_disk");
    ahci = ahci_boot_and_enable("-drive file=blkdebug:%s:%s,if=none,id=drive0,"
1087
                                "format=%s,cache=writeback,"
J
John Snow 已提交
1088 1089 1090 1091
                                "rerror=stop,werror=stop "
                                "-M q35 "
                                "-device ide-hd,drive=drive0 ",
                                debug_path,
1092
                                tmp_path, imgfmt);
J
John Snow 已提交
1093

J
John Snow 已提交
1094
    /* Issue Flush Command and wait for error */
J
John Snow 已提交
1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
    port = ahci_port_select(ahci);
    ahci_port_clear(ahci, port);
    cmd = ahci_command_create(CMD_FLUSH_CACHE);
    ahci_command_commit(ahci, cmd, port);
    ahci_command_issue_async(ahci, cmd);
    qmp_eventwait("STOP");

    /* Complete the command */
    s = "{'execute':'cont' }";
    qmp_async(s);
    qmp_eventwait("RESUME");
    ahci_command_wait(ahci, cmd);
    ahci_command_verify(ahci, cmd);

    ahci_command_free(cmd);
    ahci_shutdown(ahci);
}

J
John Snow 已提交
1113 1114 1115 1116 1117 1118
/**
 * Basic sanity test to boot a machine, find an AHCI device, and shutdown.
 */
static void test_migrate_sanity(void)
{
    AHCIQState *src, *dst;
1119
    char *uri = g_strdup_printf("unix:%s", mig_socket);
J
John Snow 已提交
1120 1121

    src = ahci_boot("-m 1024 -M q35 "
1122
                    "-drive if=ide,file=%s,format=%s ", tmp_path, imgfmt);
J
John Snow 已提交
1123
    dst = ahci_boot("-m 1024 -M q35 "
1124 1125
                    "-drive if=ide,file=%s,format=%s "
                    "-incoming %s", tmp_path, imgfmt, uri);
J
John Snow 已提交
1126 1127 1128 1129 1130

    ahci_migrate(src, dst, uri);

    ahci_shutdown(src);
    ahci_shutdown(dst);
1131
    g_free(uri);
J
John Snow 已提交
1132 1133
}

J
John Snow 已提交
1134
/**
J
John Snow 已提交
1135
 * Simple migration test: Write a pattern, migrate, then read.
J
John Snow 已提交
1136
 */
J
John Snow 已提交
1137
static void ahci_migrate_simple(uint8_t cmd_read, uint8_t cmd_write)
J
John Snow 已提交
1138 1139 1140 1141 1142 1143
{
    AHCIQState *src, *dst;
    uint8_t px;
    size_t bufsize = 4096;
    unsigned char *tx = g_malloc(bufsize);
    unsigned char *rx = g_malloc0(bufsize);
1144
    char *uri = g_strdup_printf("unix:%s", mig_socket);
J
John Snow 已提交
1145 1146

    src = ahci_boot_and_enable("-m 1024 -M q35 "
1147 1148
                               "-drive if=ide,format=%s,file=%s ",
                               imgfmt, tmp_path);
J
John Snow 已提交
1149
    dst = ahci_boot("-m 1024 -M q35 "
1150 1151
                    "-drive if=ide,format=%s,file=%s "
                    "-incoming %s", imgfmt, tmp_path, uri);
J
John Snow 已提交
1152 1153 1154 1155 1156 1157 1158 1159

    set_context(src->parent);

    /* initialize */
    px = ahci_port_select(src);
    ahci_port_clear(src, px);

    /* create pattern */
1160
    generate_pattern(tx, bufsize, AHCI_SECTOR_SIZE);
J
John Snow 已提交
1161 1162

    /* Write, migrate, then read. */
J
John Snow 已提交
1163
    ahci_io(src, px, cmd_write, tx, bufsize, 0);
J
John Snow 已提交
1164
    ahci_migrate(src, dst, uri);
J
John Snow 已提交
1165
    ahci_io(dst, px, cmd_read, rx, bufsize, 0);
J
John Snow 已提交
1166 1167 1168 1169 1170 1171 1172 1173

    /* Verify pattern */
    g_assert_cmphex(memcmp(tx, rx, bufsize), ==, 0);

    ahci_shutdown(src);
    ahci_shutdown(dst);
    g_free(rx);
    g_free(tx);
1174
    g_free(uri);
J
John Snow 已提交
1175 1176
}

J
John Snow 已提交
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186
static void test_migrate_dma(void)
{
    ahci_migrate_simple(CMD_READ_DMA, CMD_WRITE_DMA);
}

static void test_migrate_ncq(void)
{
    ahci_migrate_simple(READ_FPDMA_QUEUED, WRITE_FPDMA_QUEUED);
}

J
John Snow 已提交
1187
/**
J
John Snow 已提交
1188
 * Halted IO Error Test
J
John Snow 已提交
1189 1190 1191 1192 1193
 *
 * Simulate an error on first write, Try to write a pattern,
 * Confirm the VM has stopped, resume the VM, verify command
 * has completed, then read back the data and verify.
 */
J
John Snow 已提交
1194
static void ahci_halted_io_test(uint8_t cmd_read, uint8_t cmd_write)
J
John Snow 已提交
1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
{
    AHCIQState *ahci;
    uint8_t port;
    size_t bufsize = 4096;
    unsigned char *tx = g_malloc(bufsize);
    unsigned char *rx = g_malloc0(bufsize);
    uint64_t ptr;
    AHCICommand *cmd;

    prepare_blkdebug_script(debug_path, "write_aio");

    ahci = ahci_boot_and_enable("-drive file=blkdebug:%s:%s,if=none,id=drive0,"
1207
                                "format=%s,cache=writeback,"
J
John Snow 已提交
1208 1209 1210 1211
                                "rerror=stop,werror=stop "
                                "-M q35 "
                                "-device ide-hd,drive=drive0 ",
                                debug_path,
1212
                                tmp_path, imgfmt);
J
John Snow 已提交
1213 1214 1215 1216 1217 1218

    /* Initialize and prepare */
    port = ahci_port_select(ahci);
    ahci_port_clear(ahci, port);

    /* create DMA source buffer and write pattern */
1219
    generate_pattern(tx, bufsize, AHCI_SECTOR_SIZE);
J
John Snow 已提交
1220 1221 1222 1223 1224
    ptr = ahci_alloc(ahci, bufsize);
    g_assert(ptr);
    memwrite(ptr, tx, bufsize);

    /* Attempt to write (and fail) */
J
John Snow 已提交
1225
    cmd = ahci_guest_io_halt(ahci, port, cmd_write,
J
John Snow 已提交
1226 1227 1228 1229 1230 1231 1232
                             ptr, bufsize, 0);

    /* Attempt to resume the command */
    ahci_guest_io_resume(ahci, cmd);
    ahci_free(ahci, ptr);

    /* Read back and verify */
J
John Snow 已提交
1233
    ahci_io(ahci, port, cmd_read, rx, bufsize, 0);
J
John Snow 已提交
1234 1235 1236 1237 1238 1239 1240 1241
    g_assert_cmphex(memcmp(tx, rx, bufsize), ==, 0);

    /* Cleanup and go home */
    ahci_shutdown(ahci);
    g_free(rx);
    g_free(tx);
}

J
John Snow 已提交
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
static void test_halted_dma(void)
{
    ahci_halted_io_test(CMD_READ_DMA, CMD_WRITE_DMA);
}

static void test_halted_ncq(void)
{
    ahci_halted_io_test(READ_FPDMA_QUEUED, WRITE_FPDMA_QUEUED);
}

1252
/**
1253
 * IO Error Migration Test
1254 1255 1256 1257 1258
 *
 * Simulate an error on first write, Try to write a pattern,
 * Confirm the VM has stopped, migrate, resume the VM,
 * verify command has completed, then read back the data and verify.
 */
1259
static void ahci_migrate_halted_io(uint8_t cmd_read, uint8_t cmd_write)
1260 1261 1262 1263 1264 1265 1266 1267
{
    AHCIQState *src, *dst;
    uint8_t port;
    size_t bufsize = 4096;
    unsigned char *tx = g_malloc(bufsize);
    unsigned char *rx = g_malloc0(bufsize);
    uint64_t ptr;
    AHCICommand *cmd;
1268
    char *uri = g_strdup_printf("unix:%s", mig_socket);
1269 1270 1271 1272

    prepare_blkdebug_script(debug_path, "write_aio");

    src = ahci_boot_and_enable("-drive file=blkdebug:%s:%s,if=none,id=drive0,"
1273
                               "format=%s,cache=writeback,"
1274 1275 1276 1277
                               "rerror=stop,werror=stop "
                               "-M q35 "
                               "-device ide-hd,drive=drive0 ",
                               debug_path,
1278
                               tmp_path, imgfmt);
1279 1280

    dst = ahci_boot("-drive file=%s,if=none,id=drive0,"
1281
                    "format=%s,cache=writeback,"
1282 1283 1284 1285
                    "rerror=stop,werror=stop "
                    "-M q35 "
                    "-device ide-hd,drive=drive0 "
                    "-incoming %s",
1286
                    tmp_path, imgfmt, uri);
1287 1288 1289 1290 1291 1292

    set_context(src->parent);

    /* Initialize and prepare */
    port = ahci_port_select(src);
    ahci_port_clear(src, port);
1293
    generate_pattern(tx, bufsize, AHCI_SECTOR_SIZE);
1294 1295 1296 1297 1298 1299 1300

    /* create DMA source buffer and write pattern */
    ptr = ahci_alloc(src, bufsize);
    g_assert(ptr);
    memwrite(ptr, tx, bufsize);

    /* Write, trigger the VM to stop, migrate, then resume. */
1301
    cmd = ahci_guest_io_halt(src, port, cmd_write,
1302 1303 1304 1305 1306 1307
                             ptr, bufsize, 0);
    ahci_migrate(src, dst, uri);
    ahci_guest_io_resume(dst, cmd);
    ahci_free(dst, ptr);

    /* Read back */
1308
    ahci_io(dst, port, cmd_read, rx, bufsize, 0);
1309 1310 1311 1312 1313 1314 1315 1316 1317

    /* Verify TX and RX are identical */
    g_assert_cmphex(memcmp(tx, rx, bufsize), ==, 0);

    /* Cleanup and go home. */
    ahci_shutdown(src);
    ahci_shutdown(dst);
    g_free(rx);
    g_free(tx);
1318
    g_free(uri);
1319 1320
}

1321 1322 1323 1324 1325 1326 1327 1328 1329 1330
static void test_migrate_halted_dma(void)
{
    ahci_migrate_halted_io(CMD_READ_DMA, CMD_WRITE_DMA);
}

static void test_migrate_halted_ncq(void)
{
    ahci_migrate_halted_io(READ_FPDMA_QUEUED, WRITE_FPDMA_QUEUED);
}

J
John Snow 已提交
1331 1332 1333 1334 1335 1336 1337 1338 1339
/**
 * Migration test: Try to flush, migrate, then resume.
 */
static void test_flush_migrate(void)
{
    AHCIQState *src, *dst;
    AHCICommand *cmd;
    uint8_t px;
    const char *s;
1340
    char *uri = g_strdup_printf("unix:%s", mig_socket);
J
John Snow 已提交
1341 1342 1343 1344

    prepare_blkdebug_script(debug_path, "flush_to_disk");

    src = ahci_boot_and_enable("-drive file=blkdebug:%s:%s,if=none,id=drive0,"
1345 1346
                               "cache=writeback,rerror=stop,werror=stop,"
                               "format=%s "
J
John Snow 已提交
1347 1348
                               "-M q35 "
                               "-device ide-hd,drive=drive0 ",
1349
                               debug_path, tmp_path, imgfmt);
J
John Snow 已提交
1350
    dst = ahci_boot("-drive file=%s,if=none,id=drive0,"
1351 1352
                    "cache=writeback,rerror=stop,werror=stop,"
                    "format=%s "
J
John Snow 已提交
1353 1354
                    "-M q35 "
                    "-device ide-hd,drive=drive0 "
1355
                    "-incoming %s", tmp_path, imgfmt, uri);
J
John Snow 已提交
1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379

    set_context(src->parent);

    /* Issue Flush Command */
    px = ahci_port_select(src);
    ahci_port_clear(src, px);
    cmd = ahci_command_create(CMD_FLUSH_CACHE);
    ahci_command_commit(src, cmd, px);
    ahci_command_issue_async(src, cmd);
    qmp_eventwait("STOP");

    /* Migrate over */
    ahci_migrate(src, dst, uri);

    /* Complete the command */
    s = "{'execute':'cont' }";
    qmp_async(s);
    qmp_eventwait("RESUME");
    ahci_command_wait(dst, cmd);
    ahci_command_verify(dst, cmd);

    ahci_command_free(cmd);
    ahci_shutdown(src);
    ahci_shutdown(dst);
1380
    g_free(uri);
J
John Snow 已提交
1381 1382
}

J
John Snow 已提交
1383 1384 1385 1386 1387 1388 1389 1390 1391
static void test_max(void)
{
    AHCIQState *ahci;

    ahci = ahci_boot_and_enable(NULL);
    ahci_test_max(ahci);
    ahci_shutdown(ahci);
}

J
John Snow 已提交
1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414
static void test_reset(void)
{
    AHCIQState *ahci;
    int i;

    ahci = ahci_boot(NULL);
    ahci_test_pci_spec(ahci);
    ahci_pci_enable(ahci);

    for (i = 0; i < 2; i++) {
        ahci_test_hba_spec(ahci);
        ahci_hba_enable(ahci);
        ahci_test_identify(ahci);
        ahci_test_io_rw_simple(ahci, 4096, 0,
                               CMD_READ_DMA_EXT,
                               CMD_WRITE_DMA_EXT);
        ahci_set(ahci, AHCI_GHC, AHCI_GHC_HR);
        ahci_clean_mem(ahci);
    }

    ahci_shutdown(ahci);
}

J
John Snow 已提交
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425
static void test_ncq_simple(void)
{
    AHCIQState *ahci;

    ahci = ahci_boot_and_enable(NULL);
    ahci_test_io_rw_simple(ahci, 4096, 0,
                           READ_FPDMA_QUEUED,
                           WRITE_FPDMA_QUEUED);
    ahci_shutdown(ahci);
}

J
John Snow 已提交
1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465
/******************************************************************************/
/* AHCI I/O Test Matrix Definitions                                           */

enum BuffLen {
    LEN_BEGIN = 0,
    LEN_SIMPLE = LEN_BEGIN,
    LEN_DOUBLE,
    LEN_LONG,
    LEN_SHORT,
    NUM_LENGTHS
};

static const char *buff_len_str[NUM_LENGTHS] = { "simple", "double",
                                                 "long", "short" };

enum AddrMode {
    ADDR_MODE_BEGIN = 0,
    ADDR_MODE_LBA28 = ADDR_MODE_BEGIN,
    ADDR_MODE_LBA48,
    NUM_ADDR_MODES
};

static const char *addr_mode_str[NUM_ADDR_MODES] = { "lba28", "lba48" };

enum IOMode {
    MODE_BEGIN = 0,
    MODE_PIO = MODE_BEGIN,
    MODE_DMA,
    NUM_MODES
};

static const char *io_mode_str[NUM_MODES] = { "pio", "dma" };

enum IOOps {
    IO_BEGIN = 0,
    IO_READ = IO_BEGIN,
    IO_WRITE,
    NUM_IO_OPS
};

1466 1467 1468 1469 1470 1471 1472 1473 1474 1475
enum OffsetType {
    OFFSET_BEGIN = 0,
    OFFSET_ZERO = OFFSET_BEGIN,
    OFFSET_LOW,
    OFFSET_HIGH,
    NUM_OFFSETS
};

static const char *offset_str[NUM_OFFSETS] = { "zero", "low", "high" };

J
John Snow 已提交
1476 1477 1478 1479
typedef struct AHCIIOTestOptions {
    enum BuffLen length;
    enum AddrMode address_type;
    enum IOMode io_type;
1480
    enum OffsetType offset;
J
John Snow 已提交
1481 1482
} AHCIIOTestOptions;

1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496
static uint64_t offset_sector(enum OffsetType ofst,
                              enum AddrMode addr_type,
                              uint64_t buffsize)
{
    uint64_t ceil;
    uint64_t nsectors;

    switch (ofst) {
    case OFFSET_ZERO:
        return 0;
    case OFFSET_LOW:
        return 1;
    case OFFSET_HIGH:
        ceil = (addr_type == ADDR_MODE_LBA28) ? 0xfffffff : 0xffffffffffff;
1497
        ceil = MIN(ceil, mb_to_sectors(test_image_size_mb) - 1);
1498 1499 1500 1501 1502 1503 1504
        nsectors = buffsize / AHCI_SECTOR_SIZE;
        return ceil - nsectors + 1;
    default:
        g_assert_not_reached();
    }
}

1505
/**
J
John Snow 已提交
1506
 * Table of possible I/O ATA commands given a set of enumerations.
1507
 */
J
John Snow 已提交
1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531
static const uint8_t io_cmds[NUM_MODES][NUM_ADDR_MODES][NUM_IO_OPS] = {
    [MODE_PIO] = {
        [ADDR_MODE_LBA28] = {
            [IO_READ] = CMD_READ_PIO,
            [IO_WRITE] = CMD_WRITE_PIO },
        [ADDR_MODE_LBA48] = {
            [IO_READ] = CMD_READ_PIO_EXT,
            [IO_WRITE] = CMD_WRITE_PIO_EXT }
    },
    [MODE_DMA] = {
        [ADDR_MODE_LBA28] = {
            [IO_READ] = CMD_READ_DMA,
            [IO_WRITE] = CMD_WRITE_DMA },
        [ADDR_MODE_LBA48] = {
            [IO_READ] = CMD_READ_DMA_EXT,
            [IO_WRITE] = CMD_WRITE_DMA_EXT }
    }
};

/**
 * Test a Read/Write pattern using various commands, addressing modes,
 * transfer modes, and buffer sizes.
 */
static void test_io_rw_interface(enum AddrMode lba48, enum IOMode dma,
1532
                                 unsigned bufsize, uint64_t sector)
1533 1534 1535
{
    AHCIQState *ahci;

1536
    ahci = ahci_boot_and_enable(NULL);
1537
    ahci_test_io_rw_simple(ahci, bufsize, sector,
J
John Snow 已提交
1538 1539
                           io_cmds[dma][lba48][IO_READ],
                           io_cmds[dma][lba48][IO_WRITE]);
1540 1541 1542
    ahci_shutdown(ahci);
}

J
John Snow 已提交
1543 1544 1545 1546
/**
 * Demultiplex the test data and invoke the actual test routine.
 */
static void test_io_interface(gconstpointer opaque)
J
John Snow 已提交
1547
{
J
John Snow 已提交
1548 1549
    AHCIIOTestOptions *opts = (AHCIIOTestOptions *)opaque;
    unsigned bufsize;
1550
    uint64_t sector;
J
John Snow 已提交
1551

J
John Snow 已提交
1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567
    switch (opts->length) {
    case LEN_SIMPLE:
        bufsize = 4096;
        break;
    case LEN_DOUBLE:
        bufsize = 8192;
        break;
    case LEN_LONG:
        bufsize = 4096 * 64;
        break;
    case LEN_SHORT:
        bufsize = 512;
        break;
    default:
        g_assert_not_reached();
    }
J
John Snow 已提交
1568

1569 1570
    sector = offset_sector(opts->offset, opts->address_type, bufsize);
    test_io_rw_interface(opts->address_type, opts->io_type, bufsize, sector);
J
John Snow 已提交
1571 1572
    g_free(opts);
    return;
J
John Snow 已提交
1573 1574
}

J
John Snow 已提交
1575
static void create_ahci_io_test(enum IOMode type, enum AddrMode addr,
1576
                                enum BuffLen len, enum OffsetType offset)
J
John Snow 已提交
1577
{
J
John Snow 已提交
1578
    char *name;
1579
    AHCIIOTestOptions *opts;
J
John Snow 已提交
1580

1581
    opts = g_malloc(sizeof(AHCIIOTestOptions));
J
John Snow 已提交
1582 1583 1584
    opts->length = len;
    opts->address_type = addr;
    opts->io_type = type;
1585
    opts->offset = offset;
J
John Snow 已提交
1586

1587
    name = g_strdup_printf("ahci/io/%s/%s/%s/%s",
J
John Snow 已提交
1588 1589
                           io_mode_str[type],
                           addr_mode_str[addr],
1590 1591
                           buff_len_str[len],
                           offset_str[offset]);
J
John Snow 已提交
1592

1593 1594 1595 1596 1597 1598 1599
    if ((addr == ADDR_MODE_LBA48) && (offset == OFFSET_HIGH) &&
        (mb_to_sectors(test_image_size_mb) <= 0xFFFFFFF)) {
        g_test_message("%s: skipped; test image too small", name);
        g_free(name);
        return;
    }

1600
    qtest_add_data_func(name, opts, test_io_interface);
J
John Snow 已提交
1601
    g_free(name);
J
John Snow 已提交
1602 1603
}

1604 1605 1606 1607 1608 1609
/******************************************************************************/

int main(int argc, char **argv)
{
    const char *arch;
    int ret;
J
John Snow 已提交
1610
    int fd;
1611
    int c;
1612
    int i, j, k, m;
1613 1614 1615 1616 1617

    static struct option long_options[] = {
        {"pedantic", no_argument, 0, 'p' },
        {0, 0, 0, 0},
    };
1618 1619 1620 1621

    /* Should be first to utilize g_test functionality, So we can see errors. */
    g_test_init(&argc, &argv, NULL);

1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638
    while (1) {
        c = getopt_long(argc, argv, "", long_options, NULL);
        if (c == -1) {
            break;
        }
        switch (c) {
        case -1:
            break;
        case 'p':
            ahci_pedantic = 1;
            break;
        default:
            fprintf(stderr, "Unrecognized ahci_test option.\n");
            g_assert_not_reached();
        }
    }

1639 1640 1641 1642 1643 1644 1645
    /* Check architecture */
    arch = qtest_get_arch();
    if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) {
        g_test_message("Skipping test for non-x86");
        return 0;
    }

1646 1647 1648
    /* Create a temporary image */
    fd = mkstemp(tmp_path);
    g_assert(fd >= 0);
1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660
    if (have_qemu_img()) {
        imgfmt = "qcow2";
        test_image_size_mb = TEST_IMAGE_SIZE_MB_LARGE;
        mkqcow2(tmp_path, TEST_IMAGE_SIZE_MB_LARGE);
    } else {
        g_test_message("QTEST_QEMU_IMG not set or qemu-img missing; "
                       "skipping LBA48 high-sector tests");
        imgfmt = "raw";
        test_image_size_mb = TEST_IMAGE_SIZE_MB_SMALL;
        ret = ftruncate(fd, test_image_size_mb * 1024 * 1024);
        g_assert(ret == 0);
    }
1661
    close(fd);
1662

J
John Snow 已提交
1663 1664 1665 1666 1667
    /* Create temporary blkdebug instructions */
    fd = mkstemp(debug_path);
    g_assert(fd >= 0);
    close(fd);

1668 1669 1670 1671 1672
    /* Reserve a hollow file to use as a socket for migration tests */
    fd = mkstemp(mig_socket);
    g_assert(fd >= 0);
    close(fd);

1673 1674
    /* Run the tests */
    qtest_add_func("/ahci/sanity",     test_sanity);
1675
    qtest_add_func("/ahci/pci_spec",   test_pci_spec);
1676
    qtest_add_func("/ahci/pci_enable", test_pci_enable);
1677
    qtest_add_func("/ahci/hba_spec",   test_hba_spec);
1678
    qtest_add_func("/ahci/hba_enable", test_hba_enable);
1679
    qtest_add_func("/ahci/identify",   test_identify);
J
John Snow 已提交
1680 1681 1682 1683

    for (i = MODE_BEGIN; i < NUM_MODES; i++) {
        for (j = ADDR_MODE_BEGIN; j < NUM_ADDR_MODES; j++) {
            for (k = LEN_BEGIN; k < NUM_LENGTHS; k++) {
1684 1685 1686
                for (m = OFFSET_BEGIN; m < NUM_OFFSETS; m++) {
                    create_ahci_io_test(i, j, k, m);
                }
J
John Snow 已提交
1687 1688 1689
            }
        }
    }
1690

J
John Snow 已提交
1691 1692
    qtest_add_func("/ahci/io/dma/lba28/fragmented", test_dma_fragmented);

J
John Snow 已提交
1693
    qtest_add_func("/ahci/flush/simple", test_flush);
J
John Snow 已提交
1694
    qtest_add_func("/ahci/flush/retry", test_flush_retry);
J
John Snow 已提交
1695
    qtest_add_func("/ahci/flush/migrate", test_flush_migrate);
J
John Snow 已提交
1696

J
John Snow 已提交
1697
    qtest_add_func("/ahci/migrate/sanity", test_migrate_sanity);
1698
    qtest_add_func("/ahci/migrate/dma/simple", test_migrate_dma);
J
John Snow 已提交
1699
    qtest_add_func("/ahci/io/dma/lba28/retry", test_halted_dma);
1700
    qtest_add_func("/ahci/migrate/dma/halted", test_migrate_halted_dma);
J
John Snow 已提交
1701

J
John Snow 已提交
1702
    qtest_add_func("/ahci/max", test_max);
J
John Snow 已提交
1703
    qtest_add_func("/ahci/reset", test_reset);
J
John Snow 已提交
1704

J
John Snow 已提交
1705
    qtest_add_func("/ahci/io/ncq/simple", test_ncq_simple);
J
John Snow 已提交
1706
    qtest_add_func("/ahci/migrate/ncq/simple", test_migrate_ncq);
J
John Snow 已提交
1707
    qtest_add_func("/ahci/io/ncq/retry", test_halted_ncq);
1708
    qtest_add_func("/ahci/migrate/ncq/halted", test_migrate_halted_ncq);
J
John Snow 已提交
1709

1710 1711 1712 1713
    ret = g_test_run();

    /* Cleanup */
    unlink(tmp_path);
J
John Snow 已提交
1714
    unlink(debug_path);
1715
    unlink(mig_socket);
1716 1717 1718

    return ret;
}