From b22023838c7f4da40c2f5e14f9fb0253d990e11e Mon Sep 17 00:00:00 2001 From: Volker Ruppert Date: Sun, 11 Oct 2015 17:07:18 +0000 Subject: [PATCH] Completed save/restore support for the USB xHCI device. TODO: reduce size of saved file (find a way to skip unused slots). --- bochs/iodev/usb/usb_xhci.cc | 130 ++++++++++++++++++++++++++++-------- 1 file changed, 104 insertions(+), 26 deletions(-) diff --git a/bochs/iodev/usb/usb_xhci.cc b/bochs/iodev/usb/usb_xhci.cc index 8702613a9..2ad5cda92 100644 --- a/bochs/iodev/usb/usb_xhci.cc +++ b/bochs/iodev/usb/usb_xhci.cc @@ -574,9 +574,6 @@ void bx_usb_xhci_c::reset_hc() } } - for (i=0; iget_bochs_root(), "usb_xhci", "USB xHCI State"); hub = new bx_list_c(list, "hub"); @@ -832,29 +830,9 @@ void bx_usb_xhci_c::register_state(void) BXRS_HEX_PARAM_FIELD(reg_grp, HcConfig_cie, BX_XHCI_THIS hub.op_regs.HcConfig.cie); #endif - reg_grp = new bx_list_c(hub, "runtime_regs"); - BXRS_HEX_PARAM_FIELD(reg_grp, mfindex, BX_XHCI_THIS hub.runtime_regs.mfindex.index); - for (i = 0; i < INTERRUPTERS; i++) { - sprintf(tmpname, "interrupter%d", i+1); - reg_grp1 = new bx_list_c(reg_grp, tmpname); - reg = new bx_list_c(reg_grp1, "iman"); - BXRS_PARAM_BOOL(reg, ie, BX_XHCI_THIS hub.runtime_regs.interrupter[i].iman.ie); - BXRS_PARAM_BOOL(reg, ip, BX_XHCI_THIS hub.runtime_regs.interrupter[i].iman.ip); - reg = new bx_list_c(reg_grp1, "imod"); - BXRS_HEX_PARAM_FIELD(reg, imodc, BX_XHCI_THIS hub.runtime_regs.interrupter[i].imod.imodc); - BXRS_HEX_PARAM_FIELD(reg, imodi, BX_XHCI_THIS hub.runtime_regs.interrupter[i].imod.imodi); - BXRS_HEX_PARAM_FIELD(reg_grp1, erstabsize, BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstsz.erstabsize); - BXRS_HEX_PARAM_FIELD(reg_grp1, erstabadd, BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.erstabadd); - reg = new bx_list_c(reg_grp1, "erdp"); - BXRS_HEX_PARAM_FIELD(reg, eventadd, BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.eventadd); - BXRS_PARAM_BOOL(reg, ehb, BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.ehb); - BXRS_HEX_PARAM_FIELD(reg, desi, BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.desi); - } - for (i = 0; i < USB_XHCI_PORTS; i++) { sprintf(tmpname, "port%d", i+1); port = new bx_list_c(hub, tmpname); - BXRS_PARAM_BOOL(port, is_usb3, BX_XHCI_THIS hub.usb_port[i].is_usb3); BXRS_PARAM_BOOL(port, has_been_reset, BX_XHCI_THIS hub.usb_port[i].has_been_reset); reg = new bx_list_c(port, "portsc"); BXRS_PARAM_BOOL(reg, wpr, BX_XHCI_THIS hub.usb_port[i].portsc.wpr); @@ -880,10 +858,21 @@ void bx_usb_xhci_c::register_state(void) BXRS_PARAM_BOOL(reg, ped, BX_XHCI_THIS hub.usb_port[i].portsc.ped); BXRS_PARAM_BOOL(reg, ccs, BX_XHCI_THIS hub.usb_port[i].portsc.ccs); - // TODO: handle USB2/USB3 cases reg = new bx_list_c(port, "portpmsc"); + if (BX_XHCI_THIS hub.usb_port[i].is_usb3) { + BXRS_PARAM_BOOL(reg, fla, BX_XHCI_THIS hub.usb_port[i].usb3.portpmsc.fla); + BXRS_HEX_PARAM_FIELD(reg, u2timeout, BX_XHCI_THIS hub.usb_port[i].usb3.portpmsc.u2timeout); + BXRS_HEX_PARAM_FIELD(reg, u1timeout, BX_XHCI_THIS hub.usb_port[i].usb3.portpmsc.u1timeout); + BXRS_HEX_PARAM_FIELD(port, portli_lec, BX_XHCI_THIS hub.usb_port[i].usb3.portli.lec); + } else { + BXRS_HEX_PARAM_FIELD(reg, tmode, BX_XHCI_THIS hub.usb_port[i].usb2.portpmsc.tmode); + BXRS_PARAM_BOOL(reg, hle, BX_XHCI_THIS hub.usb_port[i].usb2.portpmsc.hle); + BXRS_HEX_PARAM_FIELD(reg, l1dslot, BX_XHCI_THIS hub.usb_port[i].usb2.portpmsc.l1dslot); + BXRS_HEX_PARAM_FIELD(reg, hird, BX_XHCI_THIS hub.usb_port[i].usb2.portpmsc.hird); + BXRS_PARAM_BOOL(reg, rwe, BX_XHCI_THIS hub.usb_port[i].usb2.portpmsc.rwe); + BXRS_HEX_PARAM_FIELD(reg, l1s, BX_XHCI_THIS hub.usb_port[i].usb2.portpmsc.l1s); + } - BXRS_HEX_PARAM_FIELD(port, portli_lec, BX_XHCI_THIS hub.usb_port[i].usb3.portli.lec); reg = new bx_list_c(port, "porthlpmc"); BXRS_HEX_PARAM_FIELD(reg, hirdm, BX_XHCI_THIS hub.usb_port[i].porthlpmc.hirdm); BXRS_HEX_PARAM_FIELD(reg, l1timeout, BX_XHCI_THIS hub.usb_port[i].porthlpmc.l1timeout); @@ -891,6 +880,95 @@ void bx_usb_xhci_c::register_state(void) // empty list for USB device state new bx_list_c(port, "device"); } + + new bx_shadow_data_c(hub, "extended_caps", BX_XHCI_THIS hub.extended_caps, EXT_CAPS_SIZE, 1); + + reg_grp = new bx_list_c(hub, "runtime_regs"); + BXRS_HEX_PARAM_FIELD(reg_grp, mfindex, BX_XHCI_THIS hub.runtime_regs.mfindex.index); + for (i = 0; i < INTERRUPTERS; i++) { + sprintf(tmpname, "interrupter%d", i+1); + reg_grp1 = new bx_list_c(reg_grp, tmpname); + reg = new bx_list_c(reg_grp1, "iman"); + BXRS_PARAM_BOOL(reg, ie, BX_XHCI_THIS hub.runtime_regs.interrupter[i].iman.ie); + BXRS_PARAM_BOOL(reg, ip, BX_XHCI_THIS hub.runtime_regs.interrupter[i].iman.ip); + reg = new bx_list_c(reg_grp1, "imod"); + BXRS_HEX_PARAM_FIELD(reg, imodc, BX_XHCI_THIS hub.runtime_regs.interrupter[i].imod.imodc); + BXRS_HEX_PARAM_FIELD(reg, imodi, BX_XHCI_THIS hub.runtime_regs.interrupter[i].imod.imodi); + BXRS_HEX_PARAM_FIELD(reg_grp1, erstabsize, BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstsz.erstabsize); + BXRS_HEX_PARAM_FIELD(reg_grp1, erstabadd, BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.erstabadd); + reg = new bx_list_c(reg_grp1, "erdp"); + BXRS_HEX_PARAM_FIELD(reg, eventadd, BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.eventadd); + BXRS_PARAM_BOOL(reg, ehb, BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.ehb); + BXRS_HEX_PARAM_FIELD(reg, desi, BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.desi); + } + + list1 = new bx_list_c(hub, "slots"); + for (i = 1; i < MAX_SLOTS; i++) { + sprintf(tmpname, "slot%d", i); + item = new bx_list_c(list1, tmpname); + BXRS_PARAM_BOOL(item, enabled, BX_XHCI_THIS hub.slots[i].enabled); + BXRS_PARAM_BOOL(item, sent_address, BX_XHCI_THIS hub.slots[i].sent_address); + list2 = new bx_list_c(item, "slot_context"); + BXRS_DEC_PARAM_FIELD(list2, entries, BX_XHCI_THIS hub.slots[i].slot_context.entries); + BXRS_PARAM_BOOL(list2, hub, BX_XHCI_THIS hub.slots[i].slot_context.hub); + BXRS_PARAM_BOOL(list2, mtt, BX_XHCI_THIS hub.slots[i].slot_context.mtt); + BXRS_DEC_PARAM_FIELD(list2, speed, BX_XHCI_THIS hub.slots[i].slot_context.speed); + BXRS_DEC_PARAM_FIELD(list2, route_string, BX_XHCI_THIS hub.slots[i].slot_context.route_string); + BXRS_DEC_PARAM_FIELD(list2, num_ports, BX_XHCI_THIS hub.slots[i].slot_context.num_ports); + BXRS_DEC_PARAM_FIELD(list2, rh_port_num, BX_XHCI_THIS hub.slots[i].slot_context.rh_port_num); + BXRS_DEC_PARAM_FIELD(list2, max_exit_latency, BX_XHCI_THIS hub.slots[i].slot_context.max_exit_latency); + BXRS_DEC_PARAM_FIELD(list2, int_target, BX_XHCI_THIS hub.slots[i].slot_context.int_target); + BXRS_DEC_PARAM_FIELD(list2, ttt, BX_XHCI_THIS hub.slots[i].slot_context.ttt); + BXRS_DEC_PARAM_FIELD(list2, tt_port_num, BX_XHCI_THIS hub.slots[i].slot_context.tt_port_num); + BXRS_DEC_PARAM_FIELD(list2, tt_hub_slot_id, BX_XHCI_THIS hub.slots[i].slot_context.tt_hub_slot_id); + BXRS_DEC_PARAM_FIELD(list2, slot_state, BX_XHCI_THIS hub.slots[i].slot_context.slot_state); + BXRS_DEC_PARAM_FIELD(list2, device_address, BX_XHCI_THIS hub.slots[i].slot_context.device_address); + entries = new bx_list_c(item, "ep_context"); + for (j = 0; j < 32; j++) { + sprintf(tmpname, "%d", j); + entry = new bx_list_c(entries, tmpname); + list2 = new bx_list_c(entry, "ep_context"); + BXRS_DEC_PARAM_FIELD(list2, interval, BX_XHCI_THIS hub.slots[i].ep_context[j].ep_context.interval); + BXRS_PARAM_BOOL(list2, lsa, BX_XHCI_THIS hub.slots[i].ep_context[j].ep_context.lsa); + BXRS_DEC_PARAM_FIELD(list2, max_pstreams, BX_XHCI_THIS hub.slots[i].ep_context[j].ep_context.max_pstreams); + BXRS_DEC_PARAM_FIELD(list2, mult, BX_XHCI_THIS hub.slots[i].ep_context[j].ep_context.mult); + BXRS_DEC_PARAM_FIELD(list2, ep_state, BX_XHCI_THIS hub.slots[i].ep_context[j].ep_context.ep_state); + BXRS_DEC_PARAM_FIELD(list2, max_packet_size, BX_XHCI_THIS hub.slots[i].ep_context[j].ep_context.max_packet_size); + BXRS_DEC_PARAM_FIELD(list2, max_burst_size, BX_XHCI_THIS hub.slots[i].ep_context[j].ep_context.max_burst_size); + BXRS_PARAM_BOOL(list2, hid, BX_XHCI_THIS hub.slots[i].ep_context[j].ep_context.hid); + BXRS_DEC_PARAM_FIELD(list2, ep_type, BX_XHCI_THIS hub.slots[i].ep_context[j].ep_context.ep_type); + BXRS_DEC_PARAM_FIELD(list2, cerr, BX_XHCI_THIS hub.slots[i].ep_context[j].ep_context.cerr); + BXRS_HEX_PARAM_FIELD(list2, tr_dequeue_pointer, BX_XHCI_THIS hub.slots[i].ep_context[j].ep_context.tr_dequeue_pointer); + BXRS_PARAM_BOOL(list2, dcs, BX_XHCI_THIS hub.slots[i].ep_context[j].ep_context.dcs); + BXRS_DEC_PARAM_FIELD(list2, max_esit_payload, BX_XHCI_THIS hub.slots[i].ep_context[j].ep_context.max_esit_payload); + BXRS_DEC_PARAM_FIELD(list2, average_trb_len, BX_XHCI_THIS hub.slots[i].ep_context[j].ep_context.average_trb_len); + BXRS_HEX_PARAM_FIELD(entry, edtla, BX_XHCI_THIS hub.slots[i].ep_context[j].edtla); + BXRS_HEX_PARAM_FIELD(entry, enqueue_pointer, BX_XHCI_THIS hub.slots[i].ep_context[j].enqueue_pointer); + BXRS_PARAM_BOOL(entry, rcs, BX_XHCI_THIS hub.slots[i].ep_context[j].rcs); + } + } + + list1 = new bx_list_c(hub, "ring_members"); + list2 = new bx_list_c(list1, "command_ring"); + BXRS_HEX_PARAM_FIELD(list2, dq_pointer, BX_XHCI_THIS hub.ring_members.command_ring.dq_pointer); + BXRS_PARAM_BOOL(list2, rcs, BX_XHCI_THIS hub.ring_members.command_ring.rcs); + list2 = new bx_list_c(list1, "event_rings"); + for (i = 0; i < INTERRUPTERS; i++) { + sprintf(tmpname, "ring%d", i); + item = new bx_list_c(list2, tmpname); + BXRS_PARAM_BOOL(item, rcs, BX_XHCI_THIS hub.ring_members.event_rings[i].rcs); + BXRS_HEX_PARAM_FIELD(item, trb_count, BX_XHCI_THIS hub.ring_members.event_rings[i].trb_count); + BXRS_HEX_PARAM_FIELD(item, count, BX_XHCI_THIS hub.ring_members.event_rings[i].count); + BXRS_HEX_PARAM_FIELD(item, cur_trb, BX_XHCI_THIS hub.ring_members.event_rings[i].cur_trb); + entries = new bx_list_c(item, "entries"); + for (j = 0; j < (1<