diff --git a/configure b/configure index 6a040821c6..89bd662a6a 100755 --- a/configure +++ b/configure @@ -6439,7 +6439,7 @@ target_name=$(echo $target | cut -d '-' -f 1) target_bigendian="no" case "$target_name" in - armeb|hppa|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or1k|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb) + armeb|aarch64_be|hppa|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or1k|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb) target_bigendian=yes ;; esac @@ -6494,7 +6494,8 @@ case "$target_name" in mttcg="yes" gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml" ;; - aarch64) + aarch64|aarch64_be) + TARGET_ARCH=aarch64 TARGET_BASE_ARCH=arm bflt="yes" mttcg="yes" diff --git a/default-configs/aarch64_be-linux-user.mak b/default-configs/aarch64_be-linux-user.mak new file mode 100644 index 0000000000..a69d9d2e41 --- /dev/null +++ b/default-configs/aarch64_be-linux-user.mak @@ -0,0 +1 @@ +# Default configuration for aarch64_be-linux-user diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c index 59ef33efa9..b0d4088290 100644 --- a/hw/arm/fsl-imx6.c +++ b/hw/arm/fsl-imx6.c @@ -385,6 +385,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) spi_table[i].irq)); } + qdev_set_nic_properties(DEVICE(&s->eth), &nd_table[0]); object_property_set_bool(OBJECT(&s->eth), true, "realized", &err); if (err) { error_propagate(errp, err); diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 3d78ff68e6..f7fa795278 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -453,6 +453,7 @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) AcpiSerialPortConsoleRedirection *spcr; const MemMapEntry *uart_memmap = &vms->memmap[VIRT_UART]; int irq = vms->irqmap[VIRT_UART] + ARM_SPI_BASE; + int spcr_start = table_data->len; spcr = acpi_data_push(table_data, sizeof(*spcr)); @@ -476,8 +477,8 @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) spcr->pci_device_id = 0xffff; /* PCI Device ID: not a PCI device */ spcr->pci_vendor_id = 0xffff; /* PCI Vendor ID: not a PCI device */ - build_header(linker, table_data, (void *)spcr, "SPCR", sizeof(*spcr), 2, - NULL, NULL); + build_header(linker, table_data, (void *)(table_data->data + spcr_start), + "SPCR", table_data->len - spcr_start, 2, NULL, NULL); } static void @@ -512,8 +513,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) mem_base += numa_info[i].node_mem; } - build_header(linker, table_data, (void *)srat, "SRAT", - table_data->len - srat_start, 3, NULL, NULL); + build_header(linker, table_data, (void *)(table_data->data + srat_start), + "SRAT", table_data->len - srat_start, 3, NULL, NULL); } static void @@ -522,6 +523,7 @@ build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) AcpiTableMcfg *mcfg; const MemMapEntry *memmap = vms->memmap; int len = sizeof(*mcfg) + sizeof(mcfg->allocation[0]); + int mcfg_start = table_data->len; mcfg = acpi_data_push(table_data, len); mcfg->allocation[0].address = cpu_to_le64(memmap[VIRT_PCIE_ECAM].base); @@ -532,7 +534,8 @@ build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) mcfg->allocation[0].end_bus_number = (memmap[VIRT_PCIE_ECAM].size / PCIE_MMCFG_SIZE_MIN) - 1; - build_header(linker, table_data, (void *)mcfg, "MCFG", len, 1, NULL, NULL); + build_header(linker, table_data, (void *)(table_data->data + mcfg_start), + "MCFG", table_data->len - mcfg_start, 1, NULL, NULL); } /* GTDT */ @@ -651,6 +654,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) static void build_fadt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms, unsigned dsdt_tbl_offset) { + int fadt_start = table_data->len; AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt)); unsigned xdsdt_entry_offset = (char *)&fadt->x_dsdt - table_data->data; uint16_t bootflags; @@ -681,8 +685,8 @@ static void build_fadt(GArray *table_data, BIOSLinker *linker, ACPI_BUILD_TABLE_FILE, xdsdt_entry_offset, sizeof(fadt->x_dsdt), ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset); - build_header(linker, table_data, - (void *)fadt, "FACP", sizeof(*fadt), 5, NULL, NULL); + build_header(linker, table_data, (void *)(table_data->data + fadt_start), + "FACP", table_data->len - fadt_start, 5, NULL, NULL); } /* DSDT */ diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 5a0e2a3c1a..d701e49ff9 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -1261,7 +1261,8 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset, default: qemu_log_mask(LOG_GUEST_ERROR, "gic_cpu_read: Bad offset %x\n", (int)offset); - return MEMTX_ERROR; + *data = 0; + break; } return MEMTX_OK; } @@ -1329,7 +1330,7 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset, default: qemu_log_mask(LOG_GUEST_ERROR, "gic_cpu_write: Bad offset %x\n", (int)offset); - return MEMTX_ERROR; + return MEMTX_OK; } gic_update(s); return MEMTX_OK; diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c index 3ea3dd0d40..93fe936862 100644 --- a/hw/intc/arm_gicv3_dist.c +++ b/hw/intc/arm_gicv3_dist.c @@ -817,6 +817,13 @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data, "%s: invalid guest read at offset " TARGET_FMT_plx "size %u\n", __func__, offset, size); trace_gicv3_dist_badread(offset, size, attrs.secure); + /* The spec requires that reserved registers are RAZ/WI; + * so use MEMTX_ERROR returns from leaf functions as a way to + * trigger the guest-error logging but don't return it to + * the caller, or we'll cause a spurious guest data abort. + */ + r = MEMTX_OK; + *data = 0; } else { trace_gicv3_dist_read(offset, *data, size, attrs.secure); } @@ -852,6 +859,12 @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data, "%s: invalid guest write at offset " TARGET_FMT_plx "size %u\n", __func__, offset, size); trace_gicv3_dist_badwrite(offset, data, size, attrs.secure); + /* The spec requires that reserved registers are RAZ/WI; + * so use MEMTX_ERROR returns from leaf functions as a way to + * trigger the guest-error logging but don't return it to + * the caller, or we'll cause a spurious guest data abort. + */ + r = MEMTX_OK; } else { trace_gicv3_dist_write(offset, data, size, attrs.secure); } diff --git a/hw/intc/arm_gicv3_its_common.c b/hw/intc/arm_gicv3_its_common.c index 2bd2f0f3c9..284c0a7584 100644 --- a/hw/intc/arm_gicv3_its_common.c +++ b/hw/intc/arm_gicv3_its_common.c @@ -67,7 +67,8 @@ static MemTxResult gicv3_its_trans_read(void *opaque, hwaddr offset, MemTxAttrs attrs) { qemu_log_mask(LOG_GUEST_ERROR, "ITS read at offset 0x%"PRIx64"\n", offset); - return MEMTX_ERROR; + *data = 0; + return MEMTX_OK; } static MemTxResult gicv3_its_trans_write(void *opaque, hwaddr offset, @@ -82,15 +83,12 @@ static MemTxResult gicv3_its_trans_write(void *opaque, hwaddr offset, if (ret <= 0) { qemu_log_mask(LOG_GUEST_ERROR, "ITS: Error sending MSI: %s\n", strerror(-ret)); - return MEMTX_DECODE_ERROR; } - - return MEMTX_OK; } else { qemu_log_mask(LOG_GUEST_ERROR, "ITS write at bad offset 0x%"PRIx64"\n", offset); - return MEMTX_DECODE_ERROR; } + return MEMTX_OK; } static const MemoryRegionOps gicv3_its_trans_ops = { diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c index 77e5cfa327..8a8684d76e 100644 --- a/hw/intc/arm_gicv3_redist.c +++ b/hw/intc/arm_gicv3_redist.c @@ -455,6 +455,13 @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data, "size %u\n", __func__, offset, size); trace_gicv3_redist_badread(gicv3_redist_affid(cs), offset, size, attrs.secure); + /* The spec requires that reserved registers are RAZ/WI; + * so use MEMTX_ERROR returns from leaf functions as a way to + * trigger the guest-error logging but don't return it to + * the caller, or we'll cause a spurious guest data abort. + */ + r = MEMTX_OK; + *data = 0; } else { trace_gicv3_redist_read(gicv3_redist_affid(cs), offset, *data, size, attrs.secure); @@ -505,6 +512,12 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data, "size %u\n", __func__, offset, size); trace_gicv3_redist_badwrite(gicv3_redist_affid(cs), offset, data, size, attrs.secure); + /* The spec requires that reserved registers are RAZ/WI; + * so use MEMTX_ERROR returns from leaf functions as a way to + * trigger the guest-error logging but don't return it to + * the caller, or we'll cause a spurious guest data abort. + */ + r = MEMTX_OK; } else { trace_gicv3_redist_write(gicv3_redist_affid(cs), offset, data, size, attrs.secure); diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c index 90e6ee35ba..4fb48f62ba 100644 --- a/hw/net/imx_fec.c +++ b/hw/net/imx_fec.c @@ -196,6 +196,31 @@ static const char *imx_eth_reg_name(IMXFECState *s, uint32_t index) } } +/* + * Versions of this device with more than one TX descriptor save the + * 2nd and 3rd descriptors in a subsection, to maintain migration + * compatibility with previous versions of the device that only + * supported a single descriptor. + */ +static bool imx_eth_is_multi_tx_ring(void *opaque) +{ + IMXFECState *s = IMX_FEC(opaque); + + return s->tx_ring_num > 1; +} + +static const VMStateDescription vmstate_imx_eth_txdescs = { + .name = "imx.fec/txdescs", + .version_id = 1, + .minimum_version_id = 1, + .needed = imx_eth_is_multi_tx_ring, + .fields = (VMStateField[]) { + VMSTATE_UINT32(tx_descriptor[1], IMXFECState), + VMSTATE_UINT32(tx_descriptor[2], IMXFECState), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_imx_eth = { .name = TYPE_IMX_FEC, .version_id = 2, @@ -203,15 +228,18 @@ static const VMStateDescription vmstate_imx_eth = { .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX), VMSTATE_UINT32(rx_descriptor, IMXFECState), - VMSTATE_UINT32(tx_descriptor, IMXFECState), - + VMSTATE_UINT32(tx_descriptor[0], IMXFECState), VMSTATE_UINT32(phy_status, IMXFECState), VMSTATE_UINT32(phy_control, IMXFECState), VMSTATE_UINT32(phy_advertise, IMXFECState), VMSTATE_UINT32(phy_int, IMXFECState), VMSTATE_UINT32(phy_int_mask, IMXFECState), VMSTATE_END_OF_LIST() - } + }, + .subsections = (const VMStateDescription * []) { + &vmstate_imx_eth_txdescs, + NULL + }, }; #define PHY_INT_ENERGYON (1 << 7) @@ -405,9 +433,8 @@ static void imx_eth_update(IMXFECState *s) static void imx_fec_do_tx(IMXFECState *s) { int frame_size = 0, descnt = 0; - uint8_t frame[ENET_MAX_FRAME_SIZE]; - uint8_t *ptr = frame; - uint32_t addr = s->tx_descriptor; + uint8_t *ptr = s->frame; + uint32_t addr = s->tx_descriptor[0]; while (descnt++ < IMX_MAX_DESC) { IMXFECBufDesc bd; @@ -431,8 +458,8 @@ static void imx_fec_do_tx(IMXFECState *s) frame_size += len; if (bd.flags & ENET_BD_L) { /* Last buffer in frame. */ - qemu_send_packet(qemu_get_queue(s->nic), frame, frame_size); - ptr = frame; + qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size); + ptr = s->frame; frame_size = 0; s->regs[ENET_EIR] |= ENET_INT_TXF; } @@ -448,17 +475,47 @@ static void imx_fec_do_tx(IMXFECState *s) } } - s->tx_descriptor = addr; + s->tx_descriptor[0] = addr; imx_eth_update(s); } -static void imx_enet_do_tx(IMXFECState *s) +static void imx_enet_do_tx(IMXFECState *s, uint32_t index) { int frame_size = 0, descnt = 0; - uint8_t frame[ENET_MAX_FRAME_SIZE]; - uint8_t *ptr = frame; - uint32_t addr = s->tx_descriptor; + + uint8_t *ptr = s->frame; + uint32_t addr, int_txb, int_txf, tdsr; + size_t ring; + + switch (index) { + case ENET_TDAR: + ring = 0; + int_txb = ENET_INT_TXB; + int_txf = ENET_INT_TXF; + tdsr = ENET_TDSR; + break; + case ENET_TDAR1: + ring = 1; + int_txb = ENET_INT_TXB1; + int_txf = ENET_INT_TXF1; + tdsr = ENET_TDSR1; + break; + case ENET_TDAR2: + ring = 2; + int_txb = ENET_INT_TXB2; + int_txf = ENET_INT_TXF2; + tdsr = ENET_TDSR2; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: bogus value for index %x\n", + __func__, index); + abort(); + break; + } + + addr = s->tx_descriptor[ring]; while (descnt++ < IMX_MAX_DESC) { IMXENETBufDesc bd; @@ -482,13 +539,13 @@ static void imx_enet_do_tx(IMXFECState *s) frame_size += len; if (bd.flags & ENET_BD_L) { if (bd.option & ENET_BD_PINS) { - struct ip_header *ip_hd = PKT_GET_IP_HDR(frame); + struct ip_header *ip_hd = PKT_GET_IP_HDR(s->frame); if (IP_HEADER_VERSION(ip_hd) == 4) { - net_checksum_calculate(frame, frame_size); + net_checksum_calculate(s->frame, frame_size); } } if (bd.option & ENET_BD_IINS) { - struct ip_header *ip_hd = PKT_GET_IP_HDR(frame); + struct ip_header *ip_hd = PKT_GET_IP_HDR(s->frame); /* We compute checksum only for IPv4 frames */ if (IP_HEADER_VERSION(ip_hd) == 4) { uint16_t csum; @@ -498,57 +555,59 @@ static void imx_enet_do_tx(IMXFECState *s) } } /* Last buffer in frame. */ - qemu_send_packet(qemu_get_queue(s->nic), frame, len); - ptr = frame; + + qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size); + ptr = s->frame; + frame_size = 0; if (bd.option & ENET_BD_TX_INT) { - s->regs[ENET_EIR] |= ENET_INT_TXF; + s->regs[ENET_EIR] |= int_txf; } } if (bd.option & ENET_BD_TX_INT) { - s->regs[ENET_EIR] |= ENET_INT_TXB; + s->regs[ENET_EIR] |= int_txb; } bd.flags &= ~ENET_BD_R; /* Write back the modified descriptor. */ imx_enet_write_bd(&bd, addr); /* Advance to the next descriptor. */ if ((bd.flags & ENET_BD_W) != 0) { - addr = s->regs[ENET_TDSR]; + addr = s->regs[tdsr]; } else { addr += sizeof(bd); } } - s->tx_descriptor = addr; + s->tx_descriptor[ring] = addr; imx_eth_update(s); } -static void imx_eth_do_tx(IMXFECState *s) +static void imx_eth_do_tx(IMXFECState *s, uint32_t index) { if (!s->is_fec && (s->regs[ENET_ECR] & ENET_ECR_EN1588)) { - imx_enet_do_tx(s); + imx_enet_do_tx(s, index); } else { imx_fec_do_tx(s); } } -static void imx_eth_enable_rx(IMXFECState *s) +static void imx_eth_enable_rx(IMXFECState *s, bool flush) { IMXFECBufDesc bd; - bool tmp; + bool rx_ring_full; imx_fec_read_bd(&bd, s->rx_descriptor); - tmp = ((bd.flags & ENET_BD_E) != 0); + rx_ring_full = !(bd.flags & ENET_BD_E); - if (!tmp) { + if (rx_ring_full) { FEC_PRINTF("RX buffer full\n"); - } else if (!s->regs[ENET_RDAR]) { + } else if (flush) { qemu_flush_queued_packets(qemu_get_queue(s->nic)); } - s->regs[ENET_RDAR] = tmp ? ENET_RDAR_RDAR : 0; + s->regs[ENET_RDAR] = rx_ring_full ? 0 : ENET_RDAR_RDAR; } static void imx_eth_reset(DeviceState *d) @@ -585,7 +644,7 @@ static void imx_eth_reset(DeviceState *d) } s->rx_descriptor = 0; - s->tx_descriptor = 0; + memset(s->tx_descriptor, 0, sizeof(s->tx_descriptor)); /* We also reset the PHY */ phy_reset(s); @@ -791,6 +850,7 @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { IMXFECState *s = IMX_FEC(opaque); + const bool single_tx_ring = !imx_eth_is_multi_tx_ring(s); uint32_t index = offset >> 2; FEC_PRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx_eth_reg_name(s, index), @@ -807,16 +867,24 @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value, if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) { if (!s->regs[index]) { s->regs[index] = ENET_RDAR_RDAR; - imx_eth_enable_rx(s); + imx_eth_enable_rx(s, true); } } else { s->regs[index] = 0; } break; - case ENET_TDAR: + case ENET_TDAR1: /* FALLTHROUGH */ + case ENET_TDAR2: /* FALLTHROUGH */ + if (unlikely(single_tx_ring)) { + qemu_log_mask(LOG_GUEST_ERROR, + "[%s]%s: trying to access TDAR2 or TDAR1\n", + TYPE_IMX_FEC, __func__); + return; + } + case ENET_TDAR: /* FALLTHROUGH */ if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) { s->regs[index] = ENET_TDAR_TDAR; - imx_eth_do_tx(s); + imx_eth_do_tx(s, index); } s->regs[index] = 0; break; @@ -828,8 +896,12 @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value, if ((s->regs[index] & ENET_ECR_ETHEREN) == 0) { s->regs[ENET_RDAR] = 0; s->rx_descriptor = s->regs[ENET_RDSR]; - s->regs[ENET_TDAR] = 0; - s->tx_descriptor = s->regs[ENET_TDSR]; + s->regs[ENET_TDAR] = 0; + s->regs[ENET_TDAR1] = 0; + s->regs[ENET_TDAR2] = 0; + s->tx_descriptor[0] = s->regs[ENET_TDSR]; + s->tx_descriptor[1] = s->regs[ENET_TDSR1]; + s->tx_descriptor[2] = s->regs[ENET_TDSR2]; } break; case ENET_MMFR: @@ -907,7 +979,29 @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value, } else { s->regs[index] = value & ~7; } - s->tx_descriptor = s->regs[index]; + s->tx_descriptor[0] = s->regs[index]; + break; + case ENET_TDSR1: + if (unlikely(single_tx_ring)) { + qemu_log_mask(LOG_GUEST_ERROR, + "[%s]%s: trying to access TDSR1\n", + TYPE_IMX_FEC, __func__); + return; + } + + s->regs[index] = value & ~7; + s->tx_descriptor[1] = s->regs[index]; + break; + case ENET_TDSR2: + if (unlikely(single_tx_ring)) { + qemu_log_mask(LOG_GUEST_ERROR, + "[%s]%s: trying to access TDSR2\n", + TYPE_IMX_FEC, __func__); + return; + } + + s->regs[index] = value & ~7; + s->tx_descriptor[2] = s->regs[index]; break; case ENET_MRBR: s->regs[index] = value & 0x00003ff0; @@ -930,7 +1024,7 @@ static int imx_eth_can_receive(NetClientState *nc) FEC_PRINTF("\n"); - return s->regs[ENET_RDAR] ? 1 : 0; + return !!s->regs[ENET_RDAR]; } static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf, @@ -1020,7 +1114,7 @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf, } } s->rx_descriptor = addr; - imx_eth_enable_rx(s); + imx_eth_enable_rx(s, false); imx_eth_update(s); return len; } @@ -1037,6 +1131,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf, uint8_t *crc_ptr; unsigned int buf_len; size_t size = len; + bool shift16 = s->regs[ENET_RACC] & ENET_RACC_SHIFT16; FEC_PRINTF("len %d\n", (int)size); @@ -1051,9 +1146,13 @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf, crc = cpu_to_be32(crc32(~0, buf, size)); crc_ptr = (uint8_t *) &crc; - /* Huge frames are truncted. */ - if (size > ENET_MAX_FRAME_SIZE) { - size = ENET_MAX_FRAME_SIZE; + if (shift16) { + size += 2; + } + + /* Huge frames are truncated. */ + if (size > s->regs[ENET_FTRL]) { + size = s->regs[ENET_FTRL]; flags |= ENET_BD_TR | ENET_BD_LG; } @@ -1076,7 +1175,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf, TYPE_IMX_FEC, __func__); break; } - buf_len = (size <= s->regs[ENET_MRBR]) ? size : s->regs[ENET_MRBR]; + buf_len = MIN(size, s->regs[ENET_MRBR]); bd.length = buf_len; size -= buf_len; @@ -1087,6 +1186,24 @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf, buf_len += size - 4; } buf_addr = bd.data; + + if (shift16) { + /* + * If SHIFT16 bit of ENETx_RACC register is set we need to + * align the payload to 4-byte boundary. + */ + const uint8_t zeros[2] = { 0 }; + + dma_memory_write(&address_space_memory, buf_addr, + zeros, sizeof(zeros)); + + buf_addr += sizeof(zeros); + buf_len -= sizeof(zeros); + + /* We only do this once per Ethernet frame */ + shift16 = false; + } + dma_memory_write(&address_space_memory, buf_addr, buf, buf_len); buf += buf_len; if (size < 4) { @@ -1116,7 +1233,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf, } } s->rx_descriptor = addr; - imx_eth_enable_rx(s); + imx_eth_enable_rx(s, false); imx_eth_update(s); return len; } @@ -1164,15 +1281,13 @@ static void imx_eth_realize(DeviceState *dev, Error **errp) SysBusDevice *sbd = SYS_BUS_DEVICE(dev); memory_region_init_io(&s->iomem, OBJECT(dev), &imx_eth_ops, s, - TYPE_IMX_FEC, 0x400); + TYPE_IMX_FEC, FSL_IMX25_FEC_SIZE); sysbus_init_mmio(sbd, &s->iomem); sysbus_init_irq(sbd, &s->irq[0]); sysbus_init_irq(sbd, &s->irq[1]); qemu_macaddr_default_if_unset(&s->conf.macaddr); - s->conf.peers.ncs[0] = nd_table[0].netdev; - s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf, object_get_typename(OBJECT(dev)), DEVICE(dev)->id, s); @@ -1182,6 +1297,7 @@ static void imx_eth_realize(DeviceState *dev, Error **errp) static Property imx_eth_properties[] = { DEFINE_NIC_PROPERTIES(IMXFECState, conf), + DEFINE_PROP_UINT32("tx-ring-num", IMXFECState, tx_ring_num, 1), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c index 3deccf02c9..82f8ec0d50 100644 --- a/hw/sd/pxa2xx_mmci.c +++ b/hw/sd/pxa2xx_mmci.c @@ -19,6 +19,8 @@ #include "hw/qdev.h" #include "hw/qdev-properties.h" #include "qemu/error-report.h" +#include "qemu/log.h" +#include "trace.h" #define TYPE_PXA2XX_MMCI "pxa2xx-mmci" #define PXA2XX_MMCI(obj) OBJECT_CHECK(PXA2xxMMCIState, (obj), TYPE_PXA2XX_MMCI) @@ -278,45 +280,56 @@ static void pxa2xx_mmci_wakequeues(PXA2xxMMCIState *s) static uint64_t pxa2xx_mmci_read(void *opaque, hwaddr offset, unsigned size) { PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque; - uint32_t ret; + uint32_t ret = 0; switch (offset) { case MMC_STRPCL: - return 0; + break; case MMC_STAT: - return s->status; + ret = s->status; + break; case MMC_CLKRT: - return s->clkrt; + ret = s->clkrt; + break; case MMC_SPI: - return s->spi; + ret = s->spi; + break; case MMC_CMDAT: - return s->cmdat; + ret = s->cmdat; + break; case MMC_RESTO: - return s->resp_tout; + ret = s->resp_tout; + break; case MMC_RDTO: - return s->read_tout; + ret = s->read_tout; + break; case MMC_BLKLEN: - return s->blklen; + ret = s->blklen; + break; case MMC_NUMBLK: - return s->numblk; + ret = s->numblk; + break; case MMC_PRTBUF: - return 0; + break; case MMC_I_MASK: - return s->intmask; + ret = s->intmask; + break; case MMC_I_REG: - return s->intreq; + ret = s->intreq; + break; case MMC_CMD: - return s->cmd | 0x40; + ret = s->cmd | 0x40; + break; case MMC_ARGH: - return s->arg >> 16; + ret = s->arg >> 16; + break; case MMC_ARGL: - return s->arg & 0xffff; + ret = s->arg & 0xffff; + break; case MMC_RES: - if (s->resp_len < 9) - return s->resp_fifo[s->resp_len ++]; - return 0; + ret = (s->resp_len < 9) ? s->resp_fifo[s->resp_len++] : 0; + break; case MMC_RXFIFO: - ret = 0; while (size-- && s->rx_len) { ret |= s->rx_fifo[s->rx_start++] << (size << 3); s->rx_start &= 0x1f; @@ -324,16 +337,20 @@ static uint64_t pxa2xx_mmci_read(void *opaque, hwaddr offset, unsigned size) } s->intreq &= ~INT_RXFIFO_REQ; pxa2xx_mmci_fifo_update(s); - return ret; + break; case MMC_RDWAIT: - return 0; + break; case MMC_BLKS_REM: - return s->numblk; + ret = s->numblk; + break; default: - hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: incorrect register 0x%02" HWADDR_PRIx "\n", + __func__, offset); } + trace_pxa2xx_mmci_read(size, offset, ret); - return 0; + return ret; } static void pxa2xx_mmci_write(void *opaque, @@ -341,6 +358,7 @@ static void pxa2xx_mmci_write(void *opaque, { PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque; + trace_pxa2xx_mmci_write(size, offset, value); switch (offset) { case MMC_STRPCL: if (value & STRPCL_STRT_CLK) { @@ -368,8 +386,10 @@ static void pxa2xx_mmci_write(void *opaque, case MMC_SPI: s->spi = value & 0xf; - if (value & SPI_SPI_MODE) - printf("%s: attempted to use card in SPI mode\n", __FUNCTION__); + if (value & SPI_SPI_MODE) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: attempted to use card in SPI mode\n", __func__); + } break; case MMC_CMDAT: @@ -442,7 +462,9 @@ static void pxa2xx_mmci_write(void *opaque, break; default: - hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: incorrect reg 0x%02" HWADDR_PRIx " " + "(value 0x%08" PRIx64 ")\n", __func__, offset, value); } } diff --git a/hw/sd/trace-events b/hw/sd/trace-events index 1fc0bcf44b..6eca3470e2 100644 --- a/hw/sd/trace-events +++ b/hw/sd/trace-events @@ -3,3 +3,7 @@ # hw/sd/milkymist-memcard.c milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" + +# hw/sd/pxa2xx_mmci.c +pxa2xx_mmci_read(uint8_t size, uint32_t addr, uint32_t value) "size %d addr 0x%02x value 0x%08x" +pxa2xx_mmci_write(uint8_t size, uint32_t addr, uint32_t value) "size %d addr 0x%02x value 0x%08x" diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c index 68ba5a70b3..a489bf5159 100644 --- a/hw/timer/pxa2xx_timer.c +++ b/hw/timer/pxa2xx_timer.c @@ -13,6 +13,7 @@ #include "sysemu/sysemu.h" #include "hw/arm/pxa.h" #include "hw/sysbus.h" +#include "qemu/log.h" #define OSMR0 0x00 #define OSMR1 0x04 @@ -252,8 +253,14 @@ static uint64_t pxa2xx_timer_read(void *opaque, hwaddr offset, case OSNR: return s->snapshot; default: + qemu_log_mask(LOG_UNIMP, + "%s: unknown register 0x%02" HWADDR_PRIx "\n", + __func__, offset); + break; badreg: - hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: incorrect register 0x%02" HWADDR_PRIx "\n", + __func__, offset); } return 0; @@ -377,8 +384,14 @@ static void pxa2xx_timer_write(void *opaque, hwaddr offset, } break; default: + qemu_log_mask(LOG_UNIMP, + "%s: unknown register 0x%02" HWADDR_PRIx " " + "(value 0x%08" PRIx64 ")\n", __func__, offset, value); + break; badreg: - hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: incorrect register 0x%02" HWADDR_PRIx " " + "(value 0x%08" PRIx64 ")\n", __func__, offset, value); } } diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h index d0e8e9d956..65a73714ef 100644 --- a/include/hw/arm/fsl-imx25.h +++ b/include/hw/arm/fsl-imx25.h @@ -192,7 +192,6 @@ typedef struct FslIMX25State { #define FSL_IMX25_UART5_ADDR 0x5002C000 #define FSL_IMX25_UART5_SIZE 0x4000 #define FSL_IMX25_FEC_ADDR 0x50038000 -#define FSL_IMX25_FEC_SIZE 0x4000 #define FSL_IMX25_CCM_ADDR 0x53F80000 #define FSL_IMX25_CCM_SIZE 0x4000 #define FSL_IMX25_GPT4_ADDR 0x53F84000 diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h index 62ad473b05..7b3faa4019 100644 --- a/include/hw/net/imx_fec.h +++ b/include/hw/net/imx_fec.h @@ -52,6 +52,8 @@ #define ENET_TFWR 81 #define ENET_FRBR 83 #define ENET_FRSR 84 +#define ENET_TDSR1 89 +#define ENET_TDSR2 92 #define ENET_RDSR 96 #define ENET_TDSR 97 #define ENET_MRBR 98 @@ -66,6 +68,8 @@ #define ENET_FTRL 108 #define ENET_TACC 112 #define ENET_RACC 113 +#define ENET_TDAR1 121 +#define ENET_TDAR2 123 #define ENET_MIIGSK_CFGR 192 #define ENET_MIIGSK_ENR 194 #define ENET_ATCR 256 @@ -86,7 +90,6 @@ #define ENET_TCCR3 393 #define ENET_MAX 400 -#define ENET_MAX_FRAME_SIZE 2032 /* EIR and EIMR */ #define ENET_INT_HB (1 << 31) @@ -106,13 +109,18 @@ #define ENET_INT_WAKEUP (1 << 17) #define ENET_INT_TS_AVAIL (1 << 16) #define ENET_INT_TS_TIMER (1 << 15) +#define ENET_INT_TXF2 (1 << 7) +#define ENET_INT_TXB2 (1 << 6) +#define ENET_INT_TXF1 (1 << 3) +#define ENET_INT_TXB1 (1 << 2) #define ENET_INT_MAC (ENET_INT_HB | ENET_INT_BABR | ENET_INT_BABT | \ ENET_INT_GRA | ENET_INT_TXF | ENET_INT_TXB | \ ENET_INT_RXF | ENET_INT_RXB | ENET_INT_MII | \ ENET_INT_EBERR | ENET_INT_LC | ENET_INT_RL | \ ENET_INT_UN | ENET_INT_PLR | ENET_INT_WAKEUP | \ - ENET_INT_TS_AVAIL) + ENET_INT_TS_AVAIL | ENET_INT_TXF1 | \ + ENET_INT_TXB1 | ENET_INT_TXF2 | ENET_INT_TXB2) /* RDAR */ #define ENET_RDAR_RDAR (1 << 24) @@ -155,6 +163,8 @@ #define ENET_RCR_NLC (1 << 30) #define ENET_RCR_GRS (1 << 31) +#define ENET_MAX_FRAME_SIZE (1 << ENET_RCR_MAX_FL_LENGTH) + /* TCR */ #define ENET_TCR_GTS (1 << 0) #define ENET_TCR_FDEN (1 << 2) @@ -169,6 +179,8 @@ #define ENET_TWFR_TFWR_LENGTH (6) #define ENET_TWFR_STRFWD (1 << 8) +#define ENET_RACC_SHIFT16 BIT(7) + /* Buffer Descriptor. */ typedef struct { uint16_t length; @@ -231,6 +243,10 @@ typedef struct { #define ENET_BD_BDU (1 << 31) +#define ENET_TX_RING_NUM 3 + +#define FSL_IMX25_FEC_SIZE 0x4000 + typedef struct IMXFECState { /*< private >*/ SysBusDevice parent_obj; @@ -243,7 +259,9 @@ typedef struct IMXFECState { uint32_t regs[ENET_MAX]; uint32_t rx_descriptor; - uint32_t tx_descriptor; + + uint32_t tx_descriptor[ENET_TX_RING_NUM]; + uint32_t tx_ring_num; uint32_t phy_status; uint32_t phy_control; @@ -252,6 +270,9 @@ typedef struct IMXFECState { uint32_t phy_int_mask; bool is_fec; + + /* Buffer used to assemble a Tx frame */ + uint8_t frame[ENET_MAX_FRAME_SIZE]; } IMXFECState; #endif diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h index 1b62953eeb..604ab99b14 100644 --- a/linux-user/aarch64/target_syscall.h +++ b/linux-user/aarch64/target_syscall.h @@ -8,7 +8,11 @@ struct target_pt_regs { uint64_t pstate; }; +#if defined(TARGET_WORDS_BIGENDIAN) +#define UNAME_MACHINE "aarch64_be" +#else #define UNAME_MACHINE "aarch64" +#endif #define UNAME_MINIMUM_RELEASE "3.8.0" #define TARGET_CLONE_BACKWARDS #define TARGET_MINSIGSTKSZ 2048 diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c index 441e3b1cf6..f6f8163eab 100644 --- a/linux-user/arm/nwfpe/fpa11.c +++ b/linux-user/arm/nwfpe/fpa11.c @@ -137,8 +137,17 @@ unsigned int EmulateAll(unsigned int opcode, FPA11* qfpa, CPUARMState* qregs) unsigned int nRc = 0; // unsigned long flags; FPA11 *fpa11; + unsigned int cp; // save_flags(flags); sti(); + /* Check that this is really an FPA11 instruction: the coprocessor + * field in bits [11:8] must be 1 or 2. + */ + cp = (opcode >> 8) & 0xf; + if (cp != 1 && cp != 2) { + return 0; + } + qemufpa=qfpa; user_registers=qregs; diff --git a/linux-user/main.c b/linux-user/main.c index 99a551b04f..450eb3ce65 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -4629,6 +4629,12 @@ int main(int argc, char **argv, char **envp) } env->pc = regs->pc; env->xregs[31] = regs->sp; +#ifdef TARGET_WORDS_BIGENDIAN + env->cp15.sctlr_el[1] |= SCTLR_E0E; + for (i = 1; i < 4; ++i) { + env->cp15.sctlr_el[i] |= SCTLR_EE; + } +#endif } #elif defined(TARGET_ARM) { diff --git a/linux-user/signal.c b/linux-user/signal.c index 74fa03f96d..f85f0dd780 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -1599,9 +1599,13 @@ static void target_setup_frame(int usig, struct target_sigaction *ka, if (ka->sa_flags & TARGET_SA_RESTORER) { return_addr = ka->sa_restorer; } else { - /* mov x8,#__NR_rt_sigreturn; svc #0 */ - __put_user(0xd2801168, &frame->tramp[0]); - __put_user(0xd4000001, &frame->tramp[1]); + /* + * mov x8,#__NR_rt_sigreturn; svc #0 + * Since these are instructions they need to be put as little-endian + * regardless of target default or current CPU endianness. + */ + __put_user_e(0xd2801168, &frame->tramp[0], le); + __put_user_e(0xd4000001, &frame->tramp[1], le); return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp); } env->xregs[0] = usig; diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh index 8afc3eb5bb..ea5a748745 100755 --- a/scripts/qemu-binfmt-conf.sh +++ b/scripts/qemu-binfmt-conf.sh @@ -2,9 +2,9 @@ # enable automatic i386/ARM/M68K/MIPS/SPARC/PPC/s390/HPPA # program execution by the kernel -qemu_target_list="i386 i486 alpha arm sparc32plus ppc ppc64 ppc64le m68k \ +qemu_target_list="i386 i486 alpha arm armeb sparc32plus ppc ppc64 ppc64le m68k \ mips mipsel mipsn32 mipsn32el mips64 mips64el \ -sh4 sh4eb s390x aarch64 hppa" +sh4 sh4eb s390x aarch64 aarch64_be hppa" i386_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00' i386_mask='\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff' @@ -24,7 +24,7 @@ arm_family=arm armeb_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28' armeb_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' -armeb_family=arm +armeb_family=armeb sparc_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02' sparc_mask='\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' @@ -92,6 +92,10 @@ aarch64_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x aarch64_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff' aarch64_family=arm +aarch64_be_magic='\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7' +aarch64_be_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' +aarch64_be_family=armeb + hppa_magic='\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x0f' hppa_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' hppa_family=hppa @@ -111,9 +115,12 @@ qemu_get_family() { ppc64el|ppc64le) echo "ppcle" ;; - arm|armel|armhf|arm64|armv[4-9]*) + arm|armel|armhf|arm64|armv[4-9]*l|aarch64) echo "arm" ;; + armeb|armv[4-9]*b|aarch64_be) + echo "armeb" + ;; sparc*) echo "sparc" ;; diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c index b84ebcae6e..3e00a9ead1 100644 --- a/target/arm/helper-a64.c +++ b/target/arm/helper-a64.c @@ -506,8 +506,11 @@ static uint64_t do_paired_cmpxchg64_be(CPUARMState *env, uint64_t addr, Int128 oldv, cmpv, newv; bool success; - cmpv = int128_make128(env->exclusive_val, env->exclusive_high); - newv = int128_make128(new_lo, new_hi); + /* high and low need to be switched here because this is not actually a + * 128bit store but two doublewords stored consecutively + */ + cmpv = int128_make128(env->exclusive_high, env->exclusive_val); + newv = int128_make128(new_hi, new_lo); if (parallel) { #ifndef CONFIG_ATOMIC128 diff --git a/target/arm/translate.c b/target/arm/translate.c index c690658493..781be1e219 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -9775,9 +9775,8 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, return 0; } -/* Translate a 32-bit thumb instruction. Returns nonzero if the instruction - is not legal. */ -static int disas_thumb2_insn(DisasContext *s, uint32_t insn) +/* Translate a 32-bit thumb instruction. */ +static void disas_thumb2_insn(DisasContext *s, uint32_t insn) { uint32_t imm, shift, offset; uint32_t rd, rn, rm, rs; @@ -11016,16 +11015,16 @@ static int disas_thumb2_insn(DisasContext *s, uint32_t insn) /* UNPREDICTABLE, unallocated hint or * PLD/PLDW/PLI (literal) */ - return 0; + return; } if (op1 & 1) { - return 0; /* PLD/PLDW/PLI or unallocated hint */ + return; /* PLD/PLDW/PLI or unallocated hint */ } if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) { - return 0; /* PLD/PLDW/PLI or unallocated hint */ + return; /* PLD/PLDW/PLI or unallocated hint */ } /* UNDEF space, or an UNPREDICTABLE */ - return 1; + goto illegal_op; } } memidx = get_mem_index(s); @@ -11151,9 +11150,10 @@ static int disas_thumb2_insn(DisasContext *s, uint32_t insn) default: goto illegal_op; } - return 0; + return; illegal_op: - return 1; + gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), + default_exception_el(s)); } static void disas_thumb_insn(DisasContext *s, uint32_t insn) @@ -12275,10 +12275,7 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) if (is_16bit) { disas_thumb_insn(dc, insn); } else { - if (disas_thumb2_insn(dc, insn)) { - gen_exception_insn(dc, 4, EXCP_UDEF, syn_uncategorized(), - default_exception_el(dc)); - } + disas_thumb2_insn(dc, insn); } /* Advance the Thumb condexec condition. */