diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-10-19 13:43:43 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-10-19 13:43:43 +0100 |
commit | 000f5b8f46f9a9f0a0d5304b605d89808ad92d4e (patch) | |
tree | 403dba5e3d9bcf9da60a75311ec8c87f65dde190 /hw | |
parent | ba2a9a9e6318bfd93a2306dec40137e198205b86 (diff) | |
parent | bea2a9e3e00b275dc40cfa09c760c715b8753e03 (diff) |
Merge remote-tracking branch 'remotes/kraxel/tags/usb-20201019-pull-request' into staging
usb: fixes for dwc2 + ehci.
# gpg: Signature made Mon 19 Oct 2020 13:33:16 BST
# gpg: using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full]
# gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full]
# gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full]
# Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138
* remotes/kraxel/tags/usb-20201019-pull-request:
hw/usb/hcd-dwc2: fix divide-by-zero in dwc2_handle_packet()
usb/hcd-ehci: Fix error handling on missing device for iTD
usb: hcd-dwc2: change assert()s to qemu_log_mask(LOG_GUEST_ERROR...)
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/usb/hcd-dwc2.c | 106 | ||||
-rw-r--r-- | hw/usb/hcd-ehci.c | 35 |
2 files changed, 105 insertions, 36 deletions
diff --git a/hw/usb/hcd-dwc2.c b/hw/usb/hcd-dwc2.c index 97688d21bf..e1d96acf7e 100644 --- a/hw/usb/hcd-dwc2.c +++ b/hw/usb/hcd-dwc2.c @@ -238,13 +238,24 @@ static void dwc2_handle_packet(DWC2State *s, uint32_t devadr, USBDevice *dev, pid = get_field(hctsiz, TSIZ_SC_MC_PID); pcnt = get_field(hctsiz, TSIZ_PKTCNT); len = get_field(hctsiz, TSIZ_XFERSIZE); - assert(len <= DWC2_MAX_XFER_SIZE); + if (len > DWC2_MAX_XFER_SIZE) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: HCTSIZ transfer size too large\n", __func__); + return; + } + chan = index >> 3; p = &s->packet[chan]; trace_usb_dwc2_handle_packet(chan, dev, &p->packet, epnum, types[eptype], dirs[epdir], mps, len, pcnt); + if (mps == 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad HCCHAR_MPS set to zero\n", __func__); + return; + } + if (eptype == USB_ENDPOINT_XFER_CONTROL && pid == TSIZ_SC_MC_PID_SETUP) { pid = USB_TOKEN_SETUP; } else { @@ -663,7 +674,12 @@ static uint64_t dwc2_glbreg_read(void *ptr, hwaddr addr, int index, DWC2State *s = ptr; uint32_t val; - assert(addr <= GINTSTS2); + if (addr > GINTSTS2) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return 0; + } + val = s->glbreg[index]; switch (addr) { @@ -690,7 +706,12 @@ static void dwc2_glbreg_write(void *ptr, hwaddr addr, int index, uint64_t val, uint32_t old; int iflg = 0; - assert(addr <= GINTSTS2); + if (addr > GINTSTS2) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return; + } + mmio = &s->glbreg[index]; old = *mmio; @@ -715,27 +736,34 @@ static void dwc2_glbreg_write(void *ptr, hwaddr addr, int index, uint64_t val, val &= ~GRSTCTL_DMAREQ; if (!(old & GRSTCTL_TXFFLSH) && (val & GRSTCTL_TXFFLSH)) { /* TODO - TX fifo flush */ - qemu_log_mask(LOG_UNIMP, "Tx FIFO flush not implemented\n"); + qemu_log_mask(LOG_UNIMP, "%s: Tx FIFO flush not implemented\n", + __func__); } if (!(old & GRSTCTL_RXFFLSH) && (val & GRSTCTL_RXFFLSH)) { /* TODO - RX fifo flush */ - qemu_log_mask(LOG_UNIMP, "Rx FIFO flush not implemented\n"); + qemu_log_mask(LOG_UNIMP, "%s: Rx FIFO flush not implemented\n", + __func__); } if (!(old & GRSTCTL_IN_TKNQ_FLSH) && (val & GRSTCTL_IN_TKNQ_FLSH)) { /* TODO - device IN token queue flush */ - qemu_log_mask(LOG_UNIMP, "Token queue flush not implemented\n"); + qemu_log_mask(LOG_UNIMP, "%s: Token queue flush not implemented\n", + __func__); } if (!(old & GRSTCTL_FRMCNTRRST) && (val & GRSTCTL_FRMCNTRRST)) { /* TODO - host frame counter reset */ - qemu_log_mask(LOG_UNIMP, "Frame counter reset not implemented\n"); + qemu_log_mask(LOG_UNIMP, + "%s: Frame counter reset not implemented\n", + __func__); } if (!(old & GRSTCTL_HSFTRST) && (val & GRSTCTL_HSFTRST)) { /* TODO - host soft reset */ - qemu_log_mask(LOG_UNIMP, "Host soft reset not implemented\n"); + qemu_log_mask(LOG_UNIMP, "%s: Host soft reset not implemented\n", + __func__); } if (!(old & GRSTCTL_CSFTRST) && (val & GRSTCTL_CSFTRST)) { /* TODO - core soft reset */ - qemu_log_mask(LOG_UNIMP, "Core soft reset not implemented\n"); + qemu_log_mask(LOG_UNIMP, "%s: Core soft reset not implemented\n", + __func__); } /* don't allow clearing of self-clearing bits */ val |= old & (GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH | @@ -774,7 +802,12 @@ static uint64_t dwc2_fszreg_read(void *ptr, hwaddr addr, int index, DWC2State *s = ptr; uint32_t val; - assert(addr == HPTXFSIZ); + if (addr != HPTXFSIZ) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return 0; + } + val = s->fszreg[index]; trace_usb_dwc2_fszreg_read(addr, val); @@ -789,7 +822,12 @@ static void dwc2_fszreg_write(void *ptr, hwaddr addr, int index, uint64_t val, uint32_t *mmio; uint32_t old; - assert(addr == HPTXFSIZ); + if (addr != HPTXFSIZ) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return; + } + mmio = &s->fszreg[index]; old = *mmio; @@ -810,7 +848,12 @@ static uint64_t dwc2_hreg0_read(void *ptr, hwaddr addr, int index, DWC2State *s = ptr; uint32_t val; - assert(addr >= HCFG && addr <= HPRT0); + if (addr < HCFG || addr > HPRT0) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return 0; + } + val = s->hreg0[index]; switch (addr) { @@ -837,7 +880,12 @@ static void dwc2_hreg0_write(void *ptr, hwaddr addr, int index, uint64_t val, int prst = 0; int iflg = 0; - assert(addr >= HCFG && addr <= HPRT0); + if (addr < HCFG || addr > HPRT0) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return; + } + mmio = &s->hreg0[index]; old = *mmio; @@ -923,7 +971,12 @@ static uint64_t dwc2_hreg1_read(void *ptr, hwaddr addr, int index, DWC2State *s = ptr; uint32_t val; - assert(addr >= HCCHAR(0) && addr <= HCDMAB(DWC2_NB_CHAN - 1)); + if (addr < HCCHAR(0) || addr > HCDMAB(DWC2_NB_CHAN - 1)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return 0; + } + val = s->hreg1[index]; trace_usb_dwc2_hreg1_read(addr, hreg1nm[index & 7], addr >> 5, val); @@ -941,7 +994,12 @@ static void dwc2_hreg1_write(void *ptr, hwaddr addr, int index, uint64_t val, int enflg = 0; int disflg = 0; - assert(addr >= HCCHAR(0) && addr <= HCDMAB(DWC2_NB_CHAN - 1)); + if (addr < HCCHAR(0) || addr > HCDMAB(DWC2_NB_CHAN - 1)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return; + } + mmio = &s->hreg1[index]; old = *mmio; @@ -1008,7 +1066,12 @@ static uint64_t dwc2_pcgreg_read(void *ptr, hwaddr addr, int index, DWC2State *s = ptr; uint32_t val; - assert(addr >= PCGCTL && addr <= PCGCCTL1); + if (addr < PCGCTL || addr > PCGCCTL1) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return 0; + } + val = s->pcgreg[index]; trace_usb_dwc2_pcgreg_read(addr, pcgregnm[index], val); @@ -1023,7 +1086,12 @@ static void dwc2_pcgreg_write(void *ptr, hwaddr addr, int index, uint32_t *mmio; uint32_t old; - assert(addr >= PCGCTL && addr <= PCGCCTL1); + if (addr < PCGCTL || addr > PCGCCTL1) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", + __func__, addr); + return; + } + mmio = &s->pcgreg[index]; old = *mmio; @@ -1108,7 +1176,7 @@ static uint64_t dwc2_hreg2_read(void *ptr, hwaddr addr, unsigned size) { /* TODO - implement FIFOs to support slave mode */ trace_usb_dwc2_hreg2_read(addr, addr >> 12, 0); - qemu_log_mask(LOG_UNIMP, "FIFO read not implemented\n"); + qemu_log_mask(LOG_UNIMP, "%s: FIFO read not implemented\n", __func__); return 0; } @@ -1119,7 +1187,7 @@ static void dwc2_hreg2_write(void *ptr, hwaddr addr, uint64_t val, /* TODO - implement FIFOs to support slave mode */ trace_usb_dwc2_hreg2_write(addr, addr >> 12, orig, 0, val); - qemu_log_mask(LOG_UNIMP, "FIFO write not implemented\n"); + qemu_log_mask(LOG_UNIMP, "%s: FIFO write not implemented\n", __func__); } static const MemoryRegionOps dwc2_mmio_hreg2_ops = { diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 2b995443fb..ae7f20c502 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1447,24 +1447,25 @@ static int ehci_process_itd(EHCIState *ehci, dev = ehci_find_device(ehci, devaddr); if (dev == NULL) { ehci_trace_guest_bug(ehci, "no device found"); - qemu_sglist_destroy(&ehci->isgl); - return -1; - } - pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT; - ep = usb_ep_get(dev, pid, endp); - if (ep && ep->type == USB_ENDPOINT_XFER_ISOC) { - usb_packet_setup(&ehci->ipacket, pid, ep, 0, addr, false, - (itd->transact[i] & ITD_XACT_IOC) != 0); - if (usb_packet_map(&ehci->ipacket, &ehci->isgl)) { - qemu_sglist_destroy(&ehci->isgl); - return -1; - } - usb_handle_packet(dev, &ehci->ipacket); - usb_packet_unmap(&ehci->ipacket, &ehci->isgl); - } else { - DPRINTF("ISOCH: attempt to addess non-iso endpoint\n"); - ehci->ipacket.status = USB_RET_NAK; + ehci->ipacket.status = USB_RET_NODEV; ehci->ipacket.actual_length = 0; + } else { + pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT; + ep = usb_ep_get(dev, pid, endp); + if (ep && ep->type == USB_ENDPOINT_XFER_ISOC) { + usb_packet_setup(&ehci->ipacket, pid, ep, 0, addr, false, + (itd->transact[i] & ITD_XACT_IOC) != 0); + if (usb_packet_map(&ehci->ipacket, &ehci->isgl)) { + qemu_sglist_destroy(&ehci->isgl); + return -1; + } + usb_handle_packet(dev, &ehci->ipacket); + usb_packet_unmap(&ehci->ipacket, &ehci->isgl); + } else { + DPRINTF("ISOCH: attempt to addess non-iso endpoint\n"); + ehci->ipacket.status = USB_RET_NAK; + ehci->ipacket.actual_length = 0; + } } qemu_sglist_destroy(&ehci->isgl); |