diff options
30 files changed, 415 insertions, 215 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 28cea34..a07086e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1695,6 +1695,7 @@ S: Supported F: docs/system/riscv/sifive_u.rst F: hw/*/*sifive*.c F: include/hw/*/*sifive*.h +F: tests/functional/test_riscv64_sifive_u.py AMD Microblaze-V Generic Board M: Sai Pavan Boddu <sai.pavan.boddu@amd.com> @@ -1 +1 @@ -10.0.91 +10.0.92 diff --git a/docs/devel/submitting-a-patch.rst b/docs/devel/submitting-a-patch.rst index f7917b8..dd1cf32 100644 --- a/docs/devel/submitting-a-patch.rst +++ b/docs/devel/submitting-a-patch.rst @@ -235,6 +235,38 @@ to another list.) ``git send-email`` (`step-by-step setup guide works best for delivering the patch without mangling it, but attachments can be used as a last resort on a first-time submission. +.. _use_b4: + +Use B4 +~~~~~~ + +The `b4`_ tool, used for Linux kernel development, can also be used for QEMU +development. It is packaged in most distros and PyPi. The QEMU source tree +includes a ``b4`` project configuration file at the root: ``.b4-config``. + +Example workflow to prepare a patch series: + +1. Start with a clean checkout of the ``master`` branch. +2. Create a new series with a topical branch name using ``b4 prep -n descriptive-name``. + ``b4`` will create a ``b4/descriptive-name`` branch and switch to it. +3. Commit your changes, following this page's guidelines about proper commit messages etc. +4. Write a descriptive cover letter with ``b4 prep --edit-cover``. +5. Add maintainer and reviewer CCs with ``b4 prep --auto-to-cc``. You can make + changes to Cc: and To: recipients by editing the cover letter. +6. Run patch checks with ``b4 prep --check``. +7. Optionally review the patches with ``b4 send --dry-run`` which will print the + raw patches in standard output. + +To send the patches, you can: + +- Setup ``git-send-email`` and use ``b4 send``, or +- Export the patches to files using ``b4 send -o OUTPUT_DIR`` and send them manually. + +For more details, consult the `b4 documentation`_. + +.. _b4 documentation: https://b4.docs.kernel.org/ +.. _b4: https://github.com/mricon/b4/ + .. _use_git_publish: Use git-publish @@ -418,7 +450,7 @@ Retrieve an existing series --------------------------- If you want to apply an existing series on top of your tree, you can simply use -`b4 <https://github.com/mricon/b4>`__. +`b4`_. :: @@ -533,7 +565,11 @@ summary belongs. The `git-publish <https://github.com/stefanha/git-publish>`__ script can help with tracking a good summary across versions. Also, the `git-backport-diff <https://github.com/codyprime/git-scripts>`__ script can help focus -reviewers on what changed between revisions. +reviewers on what changed between revisions. The ``b4`` tool automatically +generates a version history section in the cover letter, including links to the +previous versions on `Lore`_. + +.. _Lore: https://lore.kernel.org/ .. _tips_and_tricks: diff --git a/hw/display/framebuffer.c b/hw/display/framebuffer.c index 4485aa3..b4296e8 100644 --- a/hw/display/framebuffer.c +++ b/hw/display/framebuffer.c @@ -95,9 +95,9 @@ void framebuffer_update_display( } first = -1; - addr += i * src_width; - src += i * src_width; - dest += i * dest_row_pitch; + addr += (uint64_t)i * src_width; + src += (uint64_t)i * src_width; + dest += (uint64_t)i * dest_row_pitch; snap = memory_region_snapshot_and_clear_dirty(mem, addr, src_width * rows, DIRTY_MEMORY_VGA); diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig index 5139d23..3a0e2b8 100644 --- a/hw/i386/Kconfig +++ b/hw/i386/Kconfig @@ -131,6 +131,7 @@ config MICROVM select I8259 select MC146818RTC select VIRTIO_MMIO + select ACPI_PCI select ACPI_HW_REDUCED select PCI_EXPRESS_GENERIC_BRIDGE select USB_XHCI_SYSBUS diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c index 8ed88e7..6166283 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c @@ -295,7 +295,7 @@ static void kvm_dist_putbmp(GICv3State *s, uint32_t offset, * the 1 bits. */ if (clroffset != 0) { - reg = 0; + reg = ~0; kvm_gicd_access(s, clroffset, ®, true); clroffset += 4; } @@ -387,8 +387,6 @@ static void kvm_arm_gicv3_put(GICv3State *s) reg = c->level; kvm_gic_line_level_access(s, 0, ncpu, ®, true); - reg = ~0; - kvm_gicr_access(s, GICR_ICPENDR0, ncpu, ®, true); reg = c->gicr_ipendr0; kvm_gicr_access(s, GICR_ISPENDR0, ncpu, ®, true); @@ -445,7 +443,7 @@ static void kvm_arm_gicv3_put(GICv3State *s) kvm_gic_put_line_level_bmp(s, s->level); /* s->pending bitmap -> GICD_ISPENDRn */ - kvm_dist_putbmp(s, GICD_ISPENDR, GICD_ICPENDR, s->pending); + kvm_dist_putbmp(s, GICD_ISPENDR, 0, s->pending); /* s->active bitmap -> GICD_ISACTIVERn */ kvm_dist_putbmp(s, GICD_ISACTIVER, GICD_ICACTIVER, s->active); diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c index b31da5c..9d61b37 100644 --- a/hw/sd/allwinner-sdhost.c +++ b/hw/sd/allwinner-sdhost.c @@ -233,7 +233,7 @@ static void allwinner_sdhost_send_command(AwSdHostState *s) { SDRequest request; uint8_t resp[16]; - int rlen; + size_t rlen; /* Auto clear load flag */ s->command &= ~SD_CMDR_LOAD; @@ -246,10 +246,7 @@ static void allwinner_sdhost_send_command(AwSdHostState *s) request.arg = s->command_arg; /* Send request to SD bus */ - rlen = sdbus_do_command(&s->sdbus, &request, resp); - if (rlen < 0) { - goto error; - } + rlen = sdbus_do_command(&s->sdbus, &request, resp, sizeof(resp)); /* If the command has a response, store it in the response registers */ if ((s->command & SD_CMDR_RESPONSE)) { diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c index 29debdf..f7cef7b 100644 --- a/hw/sd/bcm2835_sdhost.c +++ b/hw/sd/bcm2835_sdhost.c @@ -113,15 +113,12 @@ static void bcm2835_sdhost_send_command(BCM2835SDHostState *s) { SDRequest request; uint8_t rsp[16]; - int rlen; + size_t rlen; request.cmd = s->cmd & SDCMD_CMD_MASK; request.arg = s->cmdarg; - rlen = sdbus_do_command(&s->sdbus, &request, rsp); - if (rlen < 0) { - goto error; - } + rlen = sdbus_do_command(&s->sdbus, &request, rsp, sizeof(rsp)); if (!(s->cmd & SDCMD_NO_RESPONSE)) { if (rlen == 0 || (rlen == 4 && (s->cmd & SDCMD_LONG_RESPONSE))) { goto error; diff --git a/hw/sd/core.c b/hw/sd/core.c index 4b30218..d3c9017 100644 --- a/hw/sd/core.c +++ b/hw/sd/core.c @@ -90,7 +90,8 @@ void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts) } } -int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response) +size_t sdbus_do_command(SDBus *sdbus, SDRequest *req, + uint8_t *resp, size_t respsz) { SDState *card = get_card(sdbus); @@ -98,7 +99,7 @@ int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response) if (card) { SDCardClass *sc = SDMMC_COMMON_GET_CLASS(card); - return sc->do_command(card, req, response); + return sc->do_command(card, req, resp, respsz); } return 0; diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c index b7648d4..5a1d25d 100644 --- a/hw/sd/omap_mmc.c +++ b/hw/sd/omap_mmc.c @@ -130,7 +130,8 @@ static void omap_mmc_command(OMAPMMCState *host, int cmd, int dir, sd_rsp_type_t resptype, int init) { uint32_t rspstatus, mask; - int rsplen, timeout; + size_t rsplen; + int timeout; SDRequest request; uint8_t response[16]; @@ -157,7 +158,7 @@ static void omap_mmc_command(OMAPMMCState *host, int cmd, int dir, request.arg = host->arg; request.crc = 0; /* FIXME */ - rsplen = sdbus_do_command(&host->sdbus, &request, response); + rsplen = sdbus_do_command(&host->sdbus, &request, response, sizeof(response)); /* TODO: validate CRCs */ switch (resptype) { diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c index b8fc9f8..5d56ead 100644 --- a/hw/sd/pl181.c +++ b/hw/sd/pl181.c @@ -173,14 +173,12 @@ static void pl181_do_command(PL181State *s) { SDRequest request; uint8_t response[16]; - int rlen; + size_t rlen; request.cmd = s->cmd & PL181_CMD_INDEX; request.arg = s->cmdarg; trace_pl181_command_send(request.cmd, request.arg); - rlen = sdbus_do_command(&s->sdbus, &request, response); - if (rlen < 0) - goto error; + rlen = sdbus_do_command(&s->sdbus, &request, response, sizeof(response)); if (s->cmd & PL181_CMD_RESPONSE) { if (rlen == 0 || (rlen == 4 && (s->cmd & PL181_CMD_LONGRESP))) goto error; @@ -61,6 +61,7 @@ typedef enum { sd_r0 = 0, /* no response */ sd_r1, /* normal response command */ + spi_r2, /* STATUS */ sd_r2_i, /* CID register */ sd_r2_s, /* CSD register */ sd_r3, /* OCR register */ @@ -146,7 +147,6 @@ struct SDState { /* Runtime changeables */ - uint32_t mode; /* current card mode, one of SDCardModes */ int32_t state; /* current card state, one of SDCardStates */ uint32_t vhs; bool wp_switch; @@ -247,6 +247,7 @@ static const char *sd_response_name(sd_rsp_type_t rsp) static const char *response_name[] = { [sd_r0] = "RESP#0 (no response)", [sd_r1] = "RESP#1 (normal cmd)", + [spi_r2] = "RESP#2 (STATUS reg)", [sd_r2_i] = "RESP#2 (CID reg)", [sd_r2_s] = "RESP#2 (CSD reg)", [sd_r3] = "RESP#3 (OCR reg)", @@ -313,27 +314,24 @@ static void sd_set_voltage(SDState *sd, uint16_t millivolts) } } -static void sd_set_mode(SDState *sd) +static enum SDCardModes sd_mode(SDState *sd) { switch (sd->state) { case sd_inactive_state: - sd->mode = sd_inactive; - break; - + return sd_inactive; case sd_idle_state: case sd_ready_state: case sd_identification_state: - sd->mode = sd_card_identification_mode; - break; - + return sd_card_identification_mode; case sd_standby_state: case sd_transfer_state: case sd_sendingdata_state: case sd_receivingdata_state: case sd_programming_state: case sd_disconnect_state: - sd->mode = sd_data_transfer_mode; - break; + return sd_data_transfer_mode; + default: + g_assert_not_reached(); } } @@ -729,16 +727,82 @@ static int sd_req_crc_validate(SDRequest *req) return sd_crc7(buffer, 5) != req->crc; /* TODO */ } +static size_t sd_response_size(SDState *sd, sd_rsp_type_t rtype) +{ + switch (rtype) { + case sd_r1: + case sd_r1b: + return sd_is_spi(sd) ? 1 : 4; + + case spi_r2: + assert(sd_is_spi(sd)); + return 2; + + case sd_r2_i: + case sd_r2_s: + assert(!sd_is_spi(sd)); + return 16; + + case sd_r3: + case sd_r7: + return sd_is_spi(sd) ? 5 : 4; + + case sd_r6: + assert(!sd_is_spi(sd)); + return 4; + + case sd_r0: + case sd_illegal: + return sd_is_spi(sd) ? 1 : 0; + + default: + g_assert_not_reached(); + } +} + static void sd_response_r1_make(SDState *sd, uint8_t *response) { - stl_be_p(response, sd->card_status); + if (sd_is_spi(sd)) { + response[0] = sd->state == sd_idle_state + && !FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP); + response[0] |= FIELD_EX32(sd->card_status, CSR, ERASE_RESET) << 1; + response[0] |= FIELD_EX32(sd->card_status, CSR, ILLEGAL_COMMAND) << 2; + response[0] |= FIELD_EX32(sd->card_status, CSR, COM_CRC_ERROR) << 3; + response[0] |= FIELD_EX32(sd->card_status, CSR, ERASE_SEQ_ERROR) << 4; + response[0] |= FIELD_EX32(sd->card_status, CSR, ADDRESS_ERROR) << 5; + response[0] |= FIELD_EX32(sd->card_status, CSR, BLOCK_LEN_ERROR) << 6; + response[0] |= 0 << 7; + } else { + stl_be_p(response, sd->card_status); + } /* Clear the "clear on read" status bits */ sd->card_status &= ~CARD_STATUS_C; } +static void spi_response_r2_make(SDState *sd, uint8_t *resp) +{ + /* Prepend R1 */ + sd_response_r1_make(sd, resp); + + resp[1] = FIELD_EX32(sd->card_status, CSR, CARD_IS_LOCKED) << 0; + resp[1] |= (FIELD_EX32(sd->card_status, CSR, LOCK_UNLOCK_FAILED) + || FIELD_EX32(sd->card_status, CSR, WP_ERASE_SKIP)) << 1; + resp[1] |= FIELD_EX32(sd->card_status, CSR, ERROR) << 2; + resp[1] |= FIELD_EX32(sd->card_status, CSR, CC_ERROR) << 3; + resp[1] |= FIELD_EX32(sd->card_status, CSR, CARD_ECC_FAILED) << 4; + resp[1] |= FIELD_EX32(sd->card_status, CSR, WP_VIOLATION) << 5; + resp[1] |= FIELD_EX32(sd->card_status, CSR, ERASE_PARAM) << 6; + resp[1] |= FIELD_EX32(sd->card_status, CSR, OUT_OF_RANGE) << 7; +} + static void sd_response_r3_make(SDState *sd, uint8_t *response) { + if (sd_is_spi(sd)) { + /* Prepend R1 */ + sd_response_r1_make(sd, response); + response++; + } stl_be_p(response, sd->ocr & ACMD41_R3_MASK); } @@ -756,6 +820,11 @@ static void sd_response_r6_make(SDState *sd, uint8_t *response) static void sd_response_r7_make(SDState *sd, uint8_t *response) { + if (sd_is_spi(sd)) { + /* Prepend R1 */ + sd_response_r1_make(sd, response); + response++; + } stl_be_p(response, sd->vhs); } @@ -952,7 +1021,7 @@ static const VMStateDescription sd_vmstate = { .minimum_version_id = 2, .pre_load = sd_vmstate_pre_load, .fields = (const VMStateField[]) { - VMSTATE_UINT32(mode, SDState), + VMSTATE_UNUSED(4), VMSTATE_INT32(state, SDState), VMSTATE_UINT8_ARRAY(cid, SDState, 16), VMSTATE_UINT8_ARRAY(csd, SDState, 16), @@ -1252,7 +1321,7 @@ static sd_rsp_type_t sd_invalid_state_for_cmd(SDState *sd, SDRequest req) static sd_rsp_type_t sd_invalid_mode_for_cmd(SDState *sd, SDRequest req) { qemu_log_mask(LOG_GUEST_ERROR, "%s: CMD%i in a wrong mode: %s (spec %s)\n", - sd->proto->name, req.cmd, sd_mode_name(sd->mode), + sd->proto->name, req.cmd, sd_mode_name(sd_mode(sd)), sd_version_str(sd->spec_version)); return sd_illegal; @@ -1305,7 +1374,7 @@ static sd_rsp_type_t sd_cmd_to_sendingdata(SDState *sd, SDRequest req, const void *data, size_t size) { if (sd->state != sd_transfer_state) { - sd_invalid_state_for_cmd(sd, req); + return sd_invalid_state_for_cmd(sd, req); } sd->state = sd_sendingdata_state; @@ -1341,14 +1410,6 @@ static sd_rsp_type_t sd_cmd_GO_IDLE_STATE(SDState *sd, SDRequest req) return sd_is_spi(sd) ? sd_r1 : sd_r0; } -/* CMD1 */ -static sd_rsp_type_t spi_cmd_SEND_OP_COND(SDState *sd, SDRequest req) -{ - sd->state = sd_transfer_state; - - return sd_r1; -} - /* CMD2 */ static sd_rsp_type_t sd_cmd_ALL_SEND_CID(SDState *sd, SDRequest req) { @@ -1420,11 +1481,17 @@ static sd_rsp_type_t emmc_cmd_sleep_awake(SDState *sd, SDRequest req) /* CMD6 */ static sd_rsp_type_t sd_cmd_SWITCH_FUNCTION(SDState *sd, SDRequest req) { - if (sd->mode != sd_data_transfer_mode) { + if (sd_mode(sd) != sd_data_transfer_mode) { return sd_invalid_mode_for_cmd(sd, req); } - if (sd->state != sd_transfer_state) { - return sd_invalid_state_for_cmd(sd, req); + if (sd_is_spi(sd)) { + if (sd->state == sd_idle_state) { + return sd_invalid_state_for_cmd(sd, req); + } + } else { + if (sd->state != sd_transfer_state) { + return sd_invalid_state_for_cmd(sd, req); + } } sd_function_switch(sd, req.arg); @@ -1517,14 +1584,30 @@ static sd_rsp_type_t emmc_cmd_SEND_EXT_CSD(SDState *sd, SDRequest req) sd->ext_csd, sizeof(sd->ext_csd)); } -/* CMD9 */ -static sd_rsp_type_t spi_cmd_SEND_CSD(SDState *sd, SDRequest req) +static sd_rsp_type_t spi_cmd_SEND_CxD(SDState *sd, SDRequest req, + const void *data, size_t size) { + /* + * XXX as of v10.1.0-rc1 command is reached in sd_idle_state, + * so disable this check. if (sd->state != sd_standby_state) { return sd_invalid_state_for_cmd(sd, req); } - return sd_cmd_to_sendingdata(sd, req, sd_req_get_address(sd, req), - sd->csd, 16); + */ + + /* + * Since SPI returns CSD and CID on the DAT lines, + * switch to sd_transfer_state. + */ + sd->state = sd_transfer_state; + + return sd_cmd_to_sendingdata(sd, req, 0, data, size); +} + +/* CMD9 */ +static sd_rsp_type_t spi_cmd_SEND_CSD(SDState *sd, SDRequest req) +{ + return spi_cmd_SEND_CxD(sd, req, sd->csd, sizeof(sd->csd)); } static sd_rsp_type_t sd_cmd_SEND_CSD(SDState *sd, SDRequest req) @@ -1539,11 +1622,7 @@ static sd_rsp_type_t sd_cmd_SEND_CSD(SDState *sd, SDRequest req) /* CMD10 */ static sd_rsp_type_t spi_cmd_SEND_CID(SDState *sd, SDRequest req) { - if (sd->state != sd_standby_state) { - return sd_invalid_state_for_cmd(sd, req); - } - return sd_cmd_to_sendingdata(sd, req, sd_req_get_address(sd, req), - sd->cid, 16); + return spi_cmd_SEND_CxD(sd, req, sd->cid, sizeof(sd->cid)); } static sd_rsp_type_t sd_cmd_SEND_CID(SDState *sd, SDRequest req) @@ -1575,7 +1654,7 @@ static sd_rsp_type_t sd_cmd_STOP_TRANSMISSION(SDState *sd, SDRequest req) /* CMD13 */ static sd_rsp_type_t sd_cmd_SEND_STATUS(SDState *sd, SDRequest req) { - if (sd->mode != sd_data_transfer_mode) { + if (sd_mode(sd) != sd_data_transfer_mode) { return sd_invalid_mode_for_cmd(sd, req); } @@ -1592,7 +1671,7 @@ static sd_rsp_type_t sd_cmd_SEND_STATUS(SDState *sd, SDRequest req) } if (sd_is_spi(sd)) { - return sd_r2_s; + return spi_r2; } return sd_req_rca_same(sd, req) ? sd_r1 : sd_r0; @@ -1601,7 +1680,7 @@ static sd_rsp_type_t sd_cmd_SEND_STATUS(SDState *sd, SDRequest req) /* CMD15 */ static sd_rsp_type_t sd_cmd_GO_INACTIVE_STATE(SDState *sd, SDRequest req) { - if (sd->mode != sd_data_transfer_mode) { + if (sd_mode(sd) != sd_data_transfer_mode) { return sd_invalid_mode_for_cmd(sd, req); } switch (sd->state) { @@ -1906,8 +1985,14 @@ static sd_rsp_type_t sd_acmd_SET_BUS_WIDTH(SDState *sd, SDRequest req) /* ACMD13 */ static sd_rsp_type_t sd_acmd_SD_STATUS(SDState *sd, SDRequest req) { - return sd_cmd_to_sendingdata(sd, req, 0, - sd->sd_status, sizeof(sd->sd_status)); + sd_rsp_type_t rsp; + + rsp = sd_cmd_to_sendingdata(sd, req, 0, + sd->sd_status, sizeof(sd->sd_status)); + if (sd_is_spi(sd) && rsp != sd_illegal) { + return spi_r2; + } + return rsp; } /* ACMD22 */ @@ -1967,6 +2052,9 @@ static sd_rsp_type_t sd_cmd_SEND_OP_COND(SDState *sd, SDRequest req) sd->state = sd_ready_state; } + if (sd_is_spi(sd)) { + return sd_r1; + } return sd_r3; } @@ -1998,7 +2086,9 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) if (req.cmd != 55 || sd->expecting_acmd) { trace_sdcard_normal_command(sd->proto->name, sd->last_cmd_name, req.cmd, - req.arg, sd_state_name(sd->state)); + req.arg, + sd_mode_name(sd_mode(sd)), + sd_state_name(sd->state)); } /* Not interpreting this as an app command */ @@ -2084,7 +2174,9 @@ static sd_rsp_type_t sd_app_command(SDState *sd, { sd->last_cmd_name = sd_acmd_name(sd, req.cmd); trace_sdcard_app_command(sd->proto->name, sd->last_cmd_name, - req.cmd, req.arg, sd_state_name(sd->state)); + req.cmd, req.arg, + sd_mode_name(sd_mode(sd)), + sd_state_name(sd->state)); sd->card_status |= APP_CMD; if (sd->proto->acmd[req.cmd].handler) { @@ -2139,8 +2231,9 @@ static bool cmd_valid_while_locked(SDState *sd, unsigned cmd) return cmd_class == 0 || cmd_class == 7; } -static int sd_do_command(SDState *sd, SDRequest *req, - uint8_t *response) { +static size_t sd_do_command(SDState *sd, SDRequest *req, + uint8_t *response, size_t respsz) +{ int last_state; sd_rsp_type_t rtype; int rsplen; @@ -2183,7 +2276,6 @@ static int sd_do_command(SDState *sd, SDRequest *req, } last_state = sd->state; - sd_set_mode(sd); if (sd->expecting_acmd) { sd->expecting_acmd = false; @@ -2203,36 +2295,37 @@ static int sd_do_command(SDState *sd, SDRequest *req, } send_response: + rsplen = sd_response_size(sd, rtype); + assert(rsplen <= respsz); + switch (rtype) { case sd_r1: case sd_r1b: sd_response_r1_make(sd, response); - rsplen = 4; + break; + + case spi_r2: + spi_response_r2_make(sd, response); break; case sd_r2_i: memcpy(response, sd->cid, sizeof(sd->cid)); - rsplen = 16; break; case sd_r2_s: memcpy(response, sd->csd, sizeof(sd->csd)); - rsplen = 16; break; case sd_r3: sd_response_r3_make(sd, response); - rsplen = 4; break; case sd_r6: sd_response_r6_make(sd, response); - rsplen = 4; break; case sd_r7: sd_response_r7_make(sd, response); - rsplen = 4; break; case sd_r0: @@ -2244,7 +2337,6 @@ send_response: sd->data_offset = 0; /* fall-through */ case sd_illegal: - rsplen = 0; break; default: g_assert_not_reached(); @@ -2510,7 +2602,7 @@ static const SDProto sd_proto_spi = { .name = "SPI", .cmd = { [0] = {0, sd_spi, "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE}, - [1] = {0, sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND}, + [1] = {0, sd_spi, "SEND_OP_COND", sd_cmd_SEND_OP_COND}, [5] = {9, sd_spi, "IO_SEND_OP_COND", sd_cmd_optional}, [6] = {10, sd_spi, "SWITCH_FUNCTION", sd_cmd_SWITCH_FUNCTION}, [8] = {0, sd_spi, "SEND_IF_COND", sd_cmd_SEND_IF_COND}, @@ -2546,7 +2638,7 @@ static const SDProto sd_proto_spi = { [13] = {8, sd_spi, "SD_STATUS", sd_acmd_SD_STATUS}, [22] = {8, sd_spi, "SEND_NUM_WR_BLOCKS", sd_acmd_SEND_NUM_WR_BLOCKS}, [23] = {8, sd_spi, "SET_WR_BLK_ERASE_COUNT", sd_acmd_SET_WR_BLK_ERASE_COUNT}, - [41] = {8, sd_spi, "SEND_OP_COND", spi_cmd_SEND_OP_COND}, + [41] = {8, sd_spi, "SEND_OP_COND", sd_cmd_SEND_OP_COND}, [42] = {8, sd_spi, "SET_CLR_CARD_DETECT", sd_acmd_SET_CLR_CARD_DETECT}, [51] = {8, sd_spi, "SEND_SCR", sd_acmd_SEND_SCR}, }, diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 226ff13..3c897e5 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -337,7 +337,7 @@ static void sdhci_send_command(SDHCIState *s) { SDRequest request; uint8_t response[16]; - int rlen; + size_t rlen; bool timeout = false; s->errintsts = 0; @@ -346,7 +346,7 @@ static void sdhci_send_command(SDHCIState *s) request.arg = s->argument; trace_sdhci_send_command(request.cmd, request.arg); - rlen = sdbus_do_command(&s->sdbus, &request, response); + rlen = sdbus_do_command(&s->sdbus, &request, response, sizeof(response)); if (s->cmdreg & SDHC_CMD_RESPONSE) { if (rlen == 4) { @@ -400,7 +400,7 @@ static void sdhci_end_transfer(SDHCIState *s) request.cmd = 0x0C; request.arg = 0; trace_sdhci_end_transfer(request.cmd, request.arg); - sdbus_do_command(&s->sdbus, &request, response); + sdbus_do_command(&s->sdbus, &request, response, sizeof(response)); /* Auto CMD12 response goes to the upper Response register */ s->rspreg[3] = ldl_be_p(response); } diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c index 6c90a86..594dead 100644 --- a/hw/sd/ssi-sd.c +++ b/hw/sd/ssi-sd.c @@ -70,23 +70,6 @@ struct ssi_sd_state { #define TYPE_SSI_SD "ssi-sd" OBJECT_DECLARE_SIMPLE_TYPE(ssi_sd_state, SSI_SD) -/* State word bits. */ -#define SSI_SDR_LOCKED 0x0001 -#define SSI_SDR_WP_ERASE 0x0002 -#define SSI_SDR_ERROR 0x0004 -#define SSI_SDR_CC_ERROR 0x0008 -#define SSI_SDR_ECC_FAILED 0x0010 -#define SSI_SDR_WP_VIOLATION 0x0020 -#define SSI_SDR_ERASE_PARAM 0x0040 -#define SSI_SDR_OUT_OF_RANGE 0x0080 -#define SSI_SDR_IDLE 0x0100 -#define SSI_SDR_ERASE_RESET 0x0200 -#define SSI_SDR_ILLEGAL_COMMAND 0x0400 -#define SSI_SDR_COM_CRC_ERROR 0x0800 -#define SSI_SDR_ERASE_SEQ_ERROR 0x1000 -#define SSI_SDR_ADDRESS_ERROR 0x2000 -#define SSI_SDR_PARAMETER_ERROR 0x4000 - /* multiple block write */ #define SSI_TOKEN_MULTI_WRITE 0xfc /* terminate multiple block write */ @@ -104,7 +87,7 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val) { ssi_sd_state *s = SSI_SD(dev); SDRequest request; - uint8_t longresp[16]; + uint8_t longresp[5]; /* * Special case: allow CMD12 (STOP TRANSMISSION) while reading data. @@ -146,8 +129,9 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val) /* manually issue cmd12 to stop the transfer */ request.cmd = 12; request.arg = 0; - s->arglen = sdbus_do_command(&s->sdbus, &request, longresp); - if (s->arglen <= 0) { + s->arglen = sdbus_do_command(&s->sdbus, &request, + longresp, sizeof(longresp)); + if (s->arglen == 0) { s->arglen = 1; /* a zero value indicates the card is busy */ s->response[0] = 0; @@ -170,73 +154,15 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val) /* FIXME: Check CRC. */ request.cmd = s->cmd; request.arg = ldl_be_p(s->cmdarg); - DPRINTF("CMD%d arg 0x%08x\n", s->cmd, request.arg); - s->arglen = sdbus_do_command(&s->sdbus, &request, longresp); - if (s->arglen <= 0) { - s->arglen = 1; - s->response[0] = 4; - DPRINTF("SD command failed\n"); - } else if (s->cmd == 8 || s->cmd == 58) { - /* CMD8/CMD58 returns R3/R7 response */ - DPRINTF("Returned R3/R7\n"); - s->arglen = 5; - s->response[0] = 1; - memcpy(&s->response[1], longresp, 4); - } else if (s->arglen != 4) { - BADF("Unexpected response to cmd %d\n", s->cmd); - /* Illegal command is about as near as we can get. */ - s->arglen = 1; - s->response[0] = 4; - } else { - /* All other commands return status. */ - uint32_t cardstatus; - uint16_t status; - /* CMD13 returns a 2-byte statuse work. Other commands - only return the first byte. */ - s->arglen = (s->cmd == 13) ? 2 : 1; - - /* handle R1b */ - if (s->cmd == 28 || s->cmd == 29 || s->cmd == 38) { - s->stopping = 1; - } + s->arglen = sdbus_do_command(&s->sdbus, &request, + longresp, sizeof(longresp)); + DPRINTF("CMD%d arg 0x%08x = %d\n", s->cmd, request.arg, s->arglen); + assert(s->arglen > 0); + memcpy(s->response, longresp, s->arglen); - cardstatus = ldl_be_p(longresp); - status = 0; - if (((cardstatus >> 9) & 0xf) < 4) - status |= SSI_SDR_IDLE; - if (cardstatus & ERASE_RESET) - status |= SSI_SDR_ERASE_RESET; - if (cardstatus & ILLEGAL_COMMAND) - status |= SSI_SDR_ILLEGAL_COMMAND; - if (cardstatus & COM_CRC_ERROR) - status |= SSI_SDR_COM_CRC_ERROR; - if (cardstatus & ERASE_SEQ_ERROR) - status |= SSI_SDR_ERASE_SEQ_ERROR; - if (cardstatus & ADDRESS_ERROR) - status |= SSI_SDR_ADDRESS_ERROR; - if (cardstatus & CARD_IS_LOCKED) - status |= SSI_SDR_LOCKED; - if (cardstatus & (LOCK_UNLOCK_FAILED | WP_ERASE_SKIP)) - status |= SSI_SDR_WP_ERASE; - if (cardstatus & SD_ERROR) - status |= SSI_SDR_ERROR; - if (cardstatus & CC_ERROR) - status |= SSI_SDR_CC_ERROR; - if (cardstatus & CARD_ECC_FAILED) - status |= SSI_SDR_ECC_FAILED; - if (cardstatus & WP_VIOLATION) - status |= SSI_SDR_WP_VIOLATION; - if (cardstatus & ERASE_PARAM) - status |= SSI_SDR_ERASE_PARAM; - if (cardstatus & (OUT_OF_RANGE | CID_CSD_OVERWRITE)) - status |= SSI_SDR_OUT_OF_RANGE; - /* ??? Don't know what Parameter Error really means, so - assume it's set if the second byte is nonzero. */ - if (status & 0xff) - status |= SSI_SDR_PARAMETER_ERROR; - s->response[0] = status >> 8; - s->response[1] = status; - DPRINTF("Card status 0x%02x\n", status); + /* handle R1b (busy signal) */ + if (s->cmd == 28 || s->cmd == 29 || s->cmd == 38) { + s->stopping = 1; } s->mode = SSI_SD_PREP_RESP; s->response_pos = 0; @@ -333,7 +259,7 @@ static int ssi_sd_post_load(void *opaque, int version_id) return -EINVAL; } if (s->mode == SSI_SD_CMDARG && - (s->arglen < 0 || s->arglen >= ARRAY_SIZE(s->cmdarg))) { + (s->arglen >= ARRAY_SIZE(s->cmdarg))) { return -EINVAL; } if (s->mode == SSI_SD_RESPONSE && diff --git a/hw/sd/trace-events b/hw/sd/trace-events index db06442..8d49840 100644 --- a/hw/sd/trace-events +++ b/hw/sd/trace-events @@ -37,8 +37,8 @@ sdhci_write_dataport(uint16_t data_count) "write buffer filled with %u bytes of sdhci_capareg(const char *desc, uint16_t val) "%s: %u" # sd.c -sdcard_normal_command(const char *proto, const char *cmd_desc, uint8_t cmd, uint32_t arg, const char *state) "%s %20s/ CMD%02d arg 0x%08x (state %s)" -sdcard_app_command(const char *proto, const char *acmd_desc, uint8_t acmd, uint32_t arg, const char *state) "%s %23s/ACMD%02d arg 0x%08x (state %s)" +sdcard_normal_command(const char *proto, const char *cmd_desc, uint8_t cmd, uint32_t arg, const char *mode, const char *state) "%s %20s/ CMD%02d arg 0x%08x (mode %s, state %s)" +sdcard_app_command(const char *proto, const char *acmd_desc, uint8_t acmd, uint32_t arg, const char *mode, const char *state) "%s %23s/ACMD%02d arg 0x%08x (mode %s, state %s)" sdcard_response(const char *rspdesc, int rsplen) "%s (sz:%d)" sdcard_powerup(void) "" sdcard_inquiry_cmd41(void) "" diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h index d6bad17..55d363f 100644 --- a/include/hw/sd/sd.h +++ b/include/hw/sd/sd.h @@ -96,7 +96,17 @@ struct SDCardClass { DeviceClass parent_class; /*< public >*/ - int (*do_command)(SDState *sd, SDRequest *req, uint8_t *response); + /** + * Process a SD command request. + * @sd: card + * @req: command request + * @resp: buffer to receive the command response + * @respsz: size of @resp buffer + * + * Return: size of the response + */ + size_t (*do_command)(SDState *sd, SDRequest *req, + uint8_t *resp, size_t respsz); /** * Write a byte to a SD card. * @sd: card @@ -153,7 +163,16 @@ struct SDBusClass { void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts); uint8_t sdbus_get_dat_lines(SDBus *sdbus); bool sdbus_get_cmd_line(SDBus *sdbus); -int sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *response); +/** + * sdbus_do_command: Process a SD command request + * @sd: card + * @req: command request + * @resp: buffer to receive the command response + * @respsz: size of @resp buffer + * + * Return: size of the response + */ +size_t sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *resp, size_t respsz); /** * Write a byte to a SD bus. * @sd: bus diff --git a/qga/commands-linux.c b/qga/commands-linux.c index 9e8a934..9dc0c82 100644 --- a/qga/commands-linux.c +++ b/qga/commands-linux.c @@ -1400,20 +1400,22 @@ static bool linux_sys_state_supports_mode(SuspendMode mode, Error **errp) static void linux_sys_state_suspend(SuspendMode mode, Error **errp) { - g_autoptr(GError) local_gerr = NULL; const char *sysfile_strs[3] = {"disk", "mem", NULL}; const char *sysfile_str = sysfile_strs[mode]; + int fd; if (!sysfile_str) { error_setg(errp, "unknown guest suspend mode"); return; } - if (!g_file_set_contents(LINUX_SYS_STATE_FILE, sysfile_str, - -1, &local_gerr)) { - error_setg(errp, "suspend: cannot write to '%s': %s", - LINUX_SYS_STATE_FILE, local_gerr->message); - return; + fd = open(LINUX_SYS_STATE_FILE, O_WRONLY); + if (fd < 0 || write(fd, sysfile_str, strlen(sysfile_str)) < 0) { + error_setg(errp, "suspend: cannot write to '%s': %m", + LINUX_SYS_STATE_FILE); + } + if (fd >= 0) { + close(fd); } } diff --git a/scripts/make-release b/scripts/make-release index 4509a9f..87f563e 100755 --- a/scripts/make-release +++ b/scripts/make-release @@ -62,17 +62,15 @@ meson subprojects download $SUBPROJECTS (cd roms/skiboot && ./make_version.sh > .version) # Fetch edk2 submodule's submodules, since it won't have access to them via # the tarball later. -# -# A more uniform way to handle this sort of situation would be nice, but we -# don't necessarily have much control over how a submodule handles its -# submodule dependencies, so we continue to handle these on a case-by-case -# basis for now. -(cd roms/edk2 && \ - git submodule update --init --depth 1 -- \ - ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3 \ - BaseTools/Source/C/BrotliCompress/brotli \ - CryptoPkg/Library/OpensslLib/openssl \ - MdeModulePkg/Library/BrotliCustomDecompressLib/brotli) + +# As recommended by the EDK2 readme, we don't use --recursive here. +# EDK2 won't use any code or feature from a submodule of a submodule, +# so we don't need to add them to the tarball. +# Although we don't necessarily need all of the submodules that EDK2 +# has, we clone them all, to avoid running into problems where EDK2 +# adds a new submodule or changes its use of an existing one and +# the sources we ship in the tarball then fail to build. +(cd roms/edk2 && git submodule update --init --depth 1) popd exclude=(--exclude=.git) diff --git a/target/arm/cpregs-pmu.c b/target/arm/cpregs-pmu.c index 0f295b1..9c4431c 100644 --- a/target/arm/cpregs-pmu.c +++ b/target/arm/cpregs-pmu.c @@ -1067,11 +1067,6 @@ static const ARMCPRegInfo v7_pm_reginfo[] = { .fgt = FGT_PMSELR_EL0, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmselr), .writefn = pmselr_write, .raw_writefn = raw_write, }, - { .name = "PMCCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0, - .access = PL0_RW, .resetvalue = 0, .type = ARM_CP_ALIAS | ARM_CP_IO, - .fgt = FGT_PMCCNTR_EL0, - .readfn = pmccntr_read, .writefn = pmccntr_write32, - .accessfn = pmreg_access_ccntr }, { .name = "PMCCNTR_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 13, .opc2 = 0, .access = PL0_RW, .accessfn = pmreg_access_ccntr, @@ -1211,6 +1206,23 @@ void define_pm_cpregs(ARMCPU *cpu) define_one_arm_cp_reg(cpu, &pmcr); define_one_arm_cp_reg(cpu, &pmcr64); define_arm_cp_regs(cpu, v7_pm_reginfo); + /* + * 32-bit AArch32 PMCCNTR. We don't expose this to GDB if the + * new-in-v8 PMUv3 64-bit AArch32 PMCCNTR register is implemented + * (as that will provide the GDB user's view of "PMCCNTR"). + */ + ARMCPRegInfo pmccntr = { + .name = "PMCCNTR", + .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0, + .access = PL0_RW, .accessfn = pmreg_access_ccntr, + .resetvalue = 0, .type = ARM_CP_ALIAS | ARM_CP_IO, + .fgt = FGT_PMCCNTR_EL0, + .readfn = pmccntr_read, .writefn = pmccntr_write32, + }; + if (arm_feature(env, ARM_FEATURE_V8)) { + pmccntr.type |= ARM_CP_NO_GDB; + } + define_one_arm_cp_reg(cpu, &pmccntr); for (unsigned i = 0, pmcrn = pmu_num_counters(env); i < pmcrn; i++) { g_autofree char *pmevcntr_name = g_strdup_printf("PMEVCNTR%d", i); @@ -1276,6 +1288,13 @@ void define_pm_cpregs(ARMCPU *cpu) .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST, .fgt = FGT_PMCEIDN_EL0, .resetvalue = cpu->pmceid1 }, + /* AArch32 64-bit PMCCNTR view: added in PMUv3 with Armv8 */ + { .name = "PMCCNTR", .state = ARM_CP_STATE_AA32, + .cp = 15, .crm = 9, .opc1 = 0, + .access = PL0_RW, .accessfn = pmreg_access_ccntr, .resetvalue = 0, + .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_64BIT, + .fgt = FGT_PMCCNTR_EL0, .readfn = pmccntr_read, + .writefn = pmccntr_write, }, }; define_arm_cp_regs(cpu, v8_pm_reginfo); } diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index aee06d4..579516e 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -940,6 +940,13 @@ static void dbgclaimclr_write(CPUARMState *env, const ARMCPRegInfo *ri, env->cp15.dbgclaim &= ~(value & 0xFF); } +static CPAccessResult access_bogus(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + /* Always UNDEF, as if this cpreg didn't exist */ + return CP_ACCESS_UNDEFINED; +} + static const ARMCPRegInfo debug_cp_reginfo[] = { /* * DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped @@ -1003,6 +1010,28 @@ static const ARMCPRegInfo debug_cp_reginfo[] = { .access = PL0_RW, .accessfn = access_tdcc, .type = ARM_CP_CONST, .resetvalue = 0 }, /* + * This is not a real AArch32 register. We used to incorrectly expose + * this due to a QEMU bug; to avoid breaking migration compatibility we + * need to continue to provide it so that we don't fail the inbound + * migration when it tells us about a sysreg that we don't have. + * We set an always-fails .accessfn, which means that the guest doesn't + * actually see this register (it will always UNDEF, identically to if + * there were no cpreg definition for it other than that we won't print + * a LOG_UNIMP message about it), and we set the ARM_CP_NO_GDB flag so the + * gdbstub won't see it either. + * (We can't just set .access = 0, because add_cpreg_to_hashtable() + * helpfully ignores cpregs which aren't accessible to the highest + * implemented EL.) + * + * TODO: implement a system for being able to describe "this register + * can be ignored if it appears in the inbound stream"; then we can + * remove this temporary hack. + */ + { .name = "BOGUS_DBGDTR_EL0", .state = ARM_CP_STATE_AA32, + .cp = 14, .opc1 = 3, .crn = 0, .crm = 5, .opc2 = 0, + .access = PL0_RW, .accessfn = access_bogus, + .type = ARM_CP_CONST | ARM_CP_NO_GDB, .resetvalue = 0 }, + /* * OSECCR_EL1 provides a mechanism for an operating system * to access the contents of EDECCR. EDECCR is not implemented though, * as is the rest of external device mechanism. diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c index 64ee9b3..08e2858 100644 --- a/target/arm/gdbstub64.c +++ b/target/arm/gdbstub64.c @@ -115,8 +115,22 @@ int aarch64_gdb_set_fpu_reg(CPUState *cs, uint8_t *buf, int reg) /* 128 bit FP register */ { uint64_t *q = aa64_vfp_qreg(env, reg); - q[0] = ldq_le_p(buf); - q[1] = ldq_le_p(buf + 8); + + /* + * On the wire these are target-endian 128 bit values. + * In the CPU state these are host-order uint64_t values + * with the least-significant one first. This means they're + * the other way around for target_big_endian() (which is + * only true for us for aarch64_be-linux-user). + */ + if (target_big_endian()) { + q[1] = ldq_p(buf); + q[0] = ldq_p(buf + 8); + } else{ + q[0] = ldq_p(buf); + q[1] = ldq_p(buf + 8); + } + return 16; } case 32: @@ -192,10 +206,17 @@ int aarch64_gdb_set_sve_reg(CPUState *cs, uint8_t *buf, int reg) case 0 ... 31: { int vq, len = 0; - uint64_t *p = (uint64_t *) buf; for (vq = 0; vq < cpu->sve_max_vq; vq++) { - env->vfp.zregs[reg].d[vq * 2 + 1] = *p++; - env->vfp.zregs[reg].d[vq * 2] = *p++; + if (target_big_endian()) { + env->vfp.zregs[reg].d[vq * 2 + 1] = ldq_p(buf); + buf += 8; + env->vfp.zregs[reg].d[vq * 2] = ldq_p(buf); + } else{ + env->vfp.zregs[reg].d[vq * 2] = ldq_p(buf); + buf += 8; + env->vfp.zregs[reg].d[vq * 2 + 1] = ldq_p(buf); + } + buf += 8; len += 16; } return len; @@ -210,9 +231,9 @@ int aarch64_gdb_set_sve_reg(CPUState *cs, uint8_t *buf, int reg) { int preg = reg - 34; int vq, len = 0; - uint64_t *p = (uint64_t *) buf; for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) { - env->vfp.pregs[preg].p[vq / 4] = *p++; + env->vfp.pregs[preg].p[vq / 4] = ldq_p(buf); + buf += 8; len += 8; } return len; diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 251d576..673f858 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -7885,8 +7885,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, * count, but Intel needs maximum number of addressable IDs for * logical processors per package. */ - if (cpu->vendor_cpuid_only_v2 && - (IS_INTEL_CPU(env) || IS_ZHAOXIN_CPU(env))) { + if ((IS_INTEL_CPU(env) || IS_ZHAOXIN_CPU(env))) { num = 1 << apicid_pkg_offset(topo_info); } else { num = threads_per_pkg; diff --git a/tests/docker/dockerfiles/debian-all-test-cross.docker b/tests/docker/dockerfiles/debian-all-test-cross.docker index ef69bbc..420a4e3 100644 --- a/tests/docker/dockerfiles/debian-all-test-cross.docker +++ b/tests/docker/dockerfiles/debian-all-test-cross.docker @@ -62,9 +62,7 @@ RUN if dpkg-architecture -e amd64; then \ export AVAILABLE_COMPILERS="${AVAILABLE_COMPILERS} gcc-powerpc64-linux-gnu libc6-dev-ppc64-cross"; \ export AVAILABLE_COMPILERS="${AVAILABLE_COMPILERS} gcc-sparc64-linux-gnu libc6-dev-sparc64-cross"; \ fi && \ - echo "compilers: ${AVAILABLE_COMPILERS}" - -RUN DEBIAN_FRONTEND=noninteractive eatmydata \ + DEBIAN_FRONTEND=noninteractive eatmydata \ apt install -y --no-install-recommends \ ${AVAILABLE_COMPILERS} && \ dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt diff --git a/tests/functional/meson.build b/tests/functional/meson.build index ecf965a..311c6f1 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -274,6 +274,7 @@ tests_riscv64_system_quick = [ ] tests_riscv64_system_thorough = [ + 'riscv64_sifive_u', 'riscv64_tuxrun', ] diff --git a/tests/functional/test_riscv64_sifive_u.py b/tests/functional/test_riscv64_sifive_u.py new file mode 100755 index 0000000..dc4cb8a --- /dev/null +++ b/tests/functional/test_riscv64_sifive_u.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on a Sifive U machine +# and checks the console +# +# Copyright (c) Linaro Ltd. +# +# Author: +# Philippe Mathieu-Daudé +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os + +from qemu_test import Asset, LinuxKernelTest +from qemu_test import skipIfMissingCommands + + +class SifiveU(LinuxKernelTest): + + ASSET_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/riscv64/Image', + '2bd8132a3bf21570290042324fff48c987f42f2a00c08de979f43f0662ebadba') + ASSET_ROOTFS = Asset( + ('https://github.com/groeck/linux-build-test/raw/' + '9819da19e6eef291686fdd7b029ea00e764dc62f/rootfs/riscv64/' + 'rootfs.ext2.gz'), + 'b6ed95610310b7956f9bf20c4c9c0c05fea647900df441da9dfe767d24e8b28b') + + def test_riscv64_sifive_u_mmc_spi(self): + self.set_machine('sifive_u') + kernel_path = self.ASSET_KERNEL.fetch() + rootfs_path = self.uncompress(self.ASSET_ROOTFS) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'root=/dev/mmcblk0 rootwait ' + 'earlycon=sbi console=ttySIF0 ' + 'panic=-1 noreboot') + self.vm.add_args('-kernel', kernel_path, + '-drive', f'file={rootfs_path},if=sd,format=raw', + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + os.remove(rootfs_path) + + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/qemu-iotests/tests/mirror-sparse b/tests/qemu-iotests/tests/mirror-sparse index cfcaa60..3b183ee 100755 --- a/tests/qemu-iotests/tests/mirror-sparse +++ b/tests/qemu-iotests/tests/mirror-sparse @@ -40,6 +40,7 @@ cd .. _supported_fmt qcow2 raw # Format of the source. dst is always raw file _supported_proto file _supported_os Linux +_supported_cache_modes none directsync _require_disk_usage echo diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target index 18afd5b..af72903 100644 --- a/tests/tcg/Makefile.target +++ b/tests/tcg/Makefile.target @@ -170,6 +170,10 @@ endif PLUGINS=$(filter-out $(DISABLE_PLUGINS), \ $(patsubst %.c, lib%.so, $(notdir $(wildcard $(PLUGIN_SRC)/*.c)))) +strip-plugin = $(wordlist 1, 1, $(subst -with-, ,$1)) +extract-plugin = $(wordlist 2, 2, $(subst -with-, ,$1)) +extract-test = $(subst run-plugin-,,$(wordlist 1, 1, $(subst -with-, ,$1))) + # We need to ensure expand the run-plugin-TEST-with-PLUGIN # pre-requistes manually here as we can't use stems to handle it. We # only expand MULTIARCH_TESTS which are common on most of our targets @@ -179,6 +183,13 @@ PLUGINS=$(filter-out $(DISABLE_PLUGINS), \ ifneq ($(MULTIARCH_TESTS),) +# Extract extra tests from the extra test+plugin combination. +EXTRA_TESTS_WITH_PLUGIN=$(foreach test, \ + $(EXTRA_RUNS_WITH_PLUGIN),$(call extract-test,$(test))) +# Exclude tests that were specified to run with specific plugins from the tests +# which can run with any plugin combination, so we don't run it twice. +MULTIARCH_TESTS:=$(filter-out $(EXTRA_TESTS_WITH_PLUGIN), $(MULTIARCH_TESTS)) + NUM_PLUGINS := $(words $(PLUGINS)) NUM_TESTS := $(words $(MULTIARCH_TESTS)) @@ -186,19 +197,22 @@ define mod_plus_one $(shell $(PYTHON) -c "print( ($(1) % $(2)) + 1 )") endef +# Rules for running tests with any plugin combination, i.e., no specific plugin. $(foreach _idx, $(shell seq 1 $(NUM_TESTS)), \ $(eval _test := $(word $(_idx), $(MULTIARCH_TESTS))) \ $(eval _plugin := $(word $(call mod_plus_one, $(_idx), $(NUM_PLUGINS)), $(PLUGINS))) \ $(eval run-plugin-$(_test)-with-$(_plugin): $(_test) $(_plugin)) \ $(eval RUN_TESTS+=run-plugin-$(_test)-with-$(_plugin))) +# Rules for running extra tests with specific plugins. +$(foreach f,$(EXTRA_RUNS_WITH_PLUGIN), \ + $(eval $(f): $(call extract-test,$(f)) $(call extract-plugin,$(f)))) + endif # MULTIARCH_TESTS endif # CONFIG_PLUGIN -strip-plugin = $(wordlist 1, 1, $(subst -with-, ,$1)) -extract-plugin = $(wordlist 2, 2, $(subst -with-, ,$1)) - RUN_TESTS+=$(EXTRA_RUNS) +RUN_TESTS+=$(EXTRA_RUNS_WITH_PLUGIN) # Some plugins need additional arguments above the default to fully # exercise things. We can define them on a per-test basis here. diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index 38345ff..8dc65d7 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -201,7 +201,7 @@ run-plugin-test-plugin-mem-access-with-libmem.so: \ $(SRC_PATH)/tests/tcg/multiarch/check-plugin-output.sh \ $(QEMU) $< -EXTRA_RUNS += run-plugin-test-plugin-mem-access-with-libmem.so +EXTRA_RUNS_WITH_PLUGIN += run-plugin-test-plugin-mem-access-with-libmem.so endif # Update TESTS diff --git a/tests/tcg/multiarch/system/Makefile.softmmu-target b/tests/tcg/multiarch/system/Makefile.softmmu-target index 4171b4e..98c4eda 100644 --- a/tests/tcg/multiarch/system/Makefile.softmmu-target +++ b/tests/tcg/multiarch/system/Makefile.softmmu-target @@ -77,5 +77,5 @@ run-plugin-memory-with-libmem.so: memory libmem.so run-plugin-memory-with-libmem.so: PLUGIN_ARGS=$(COMMA)region-summary=true run-plugin-memory-with-libmem.so: CHECK_PLUGIN_OUTPUT_COMMAND=$(MULTIARCH_SYSTEM_SRC)/validate-memory-counts.py $@.out -EXTRA_RUNS += run-plugin-memory-with-libmem.so +EXTRA_RUNS_WITH_PLUGIN += run-plugin-memory-with-libmem.so endif diff --git a/tests/tcg/x86_64/Makefile.softmmu-target b/tests/tcg/x86_64/Makefile.softmmu-target index 3e30ca9..4e65f58 100644 --- a/tests/tcg/x86_64/Makefile.softmmu-target +++ b/tests/tcg/x86_64/Makefile.softmmu-target @@ -40,5 +40,5 @@ run-plugin-patch-target-with-libpatch.so: \ run-plugin-patch-target-with-libpatch.so: \ CHECK_PLUGIN_OUTPUT_COMMAND=$(X64_SYSTEM_SRC)/validate-patch.py $@.out run-plugin-patch-target-with-libpatch.so: patch-target libpatch.so -EXTRA_RUNS+=run-plugin-patch-target-with-libpatch.so +EXTRA_RUNS_WITH_PLUGIN+=run-plugin-patch-target-with-libpatch.so endif |