Writes to the interrupt registers were not masked, so a guest could set a reserved bit and read it back. The hardware returns 0 for those.
Mask each one to the bits the datasheet marks read/write: UDC_IER 17, 16, 8:6, 4:0 UDC_ISR 8:6, 4:0 UDC_EP_ACK_IER 3:0 UDC_EP_NAK_IER 3:0 UDC_EP_ACK_ISR 3:0 UDC_EP_NAK_ISR 3:0 UDC_ISR bits 17 and 16 summarise the endpoint pool. They are read only, so a write cannot clear them. Signed-off-by: Jamin Lin <[email protected]> --- hw/usb/aspeed-udc.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/hw/usb/aspeed-udc.c b/hw/usb/aspeed-udc.c index 355512822b..95fe823534 100644 --- a/hw/usb/aspeed-udc.c +++ b/hw/usb/aspeed-udc.c @@ -319,14 +319,24 @@ static void aspeed_udc_write(void *opaque, hwaddr offset, uint64_t data, s->regs[R_UDC_FUNC_CTRL] = val; break; case R_UDC_IER: + val &= 0x000301df; + s->regs[reg] = val; + aspeed_udc_update_irq(s); + break; + case R_UDC_ISR: + val &= 0x000001df; + s->regs[reg] &= ~val; + aspeed_udc_update_irq(s); + break; case R_UDC_EP_ACK_IER: case R_UDC_EP_NAK_IER: + val &= 0x0000000f; s->regs[reg] = val; aspeed_udc_update_irq(s); break; - case R_UDC_ISR: case R_UDC_EP_ACK_ISR: case R_UDC_EP_NAK_ISR: + val &= 0x0000000f; s->regs[reg] &= ~val; aspeed_udc_update_irq(s); break; -- 2.53.0
