Skip to content

Commit ae06668

Browse files
xiaoguangwuacrnsi
authored andcommitted
DM USB: xHCI: re-implement the emulation of extented capabilities
There are many quirks in Intel xHCI implementation and it is very hard to debug under Microsoft Windows OS, hence use ACRN xHCI extented capabilities as the default setting. Tracked-On: #3163 Signed-off-by: Xiaoguang Wu <xiaoguang.wu@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
1 parent 5f9cd25 commit ae06668

File tree

2 files changed

+72
-41
lines changed

2 files changed

+72
-41
lines changed

devicemodel/hw/pci/xhci.c

Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106
*/
107107
#define XHCI_PADDR_SZ 4096 /* paddr_guest2host max size */
108108
#define XHCI_ERST_MAX 0 /* max 2^entries event ring seg tbl */
109-
#define XHCI_CAPLEN (4*8) /* offset of op register space */
109+
#define XHCI_CAPLEN (8*8) /* offset of op register space */
110110
#define XHCI_HCCPRAMS2 0x1C /* offset of HCCPARAMS2 register */
111111
#define XHCI_PORTREGS_START 0x400
112112
#define XHCI_DOORBELL_MAX 256
@@ -377,6 +377,7 @@ struct pci_xhci_vdev {
377377
uint32_t hccparams1; /* capability parameters 1 */
378378
uint32_t dboff; /* doorbell offset */
379379
uint32_t rtsoff; /* runtime register space offset */
380+
uint32_t rtsend;
380381
uint32_t hccparams2; /* capability parameters 2 */
381382

382383
uint32_t excapoff; /* ext-capability registers offset */
@@ -3332,7 +3333,7 @@ pci_xhci_write(struct vmctx *ctx,
33323333
pci_xhci_hostop_write(xdev, offset, value);
33333334
else if (offset < xdev->rtsoff)
33343335
pci_xhci_dbregs_write(xdev, offset, value);
3335-
else if (offset < xdev->excapoff)
3336+
else if (offset < xdev->rtsend)
33363337
pci_xhci_rtsregs_write(xdev, offset, value);
33373338
else if (offset < xdev->regsend)
33383339
pci_xhci_excap_write(xdev, offset, value);
@@ -3376,8 +3377,36 @@ pci_xhci_hostcap_read(struct pci_xhci_vdev *xdev, uint64_t offset)
33763377
value = xdev->rtsoff;
33773378
break;
33783379

3379-
case XHCI_HCCPRAMS2: /* 0x1C */
3380-
value = xdev->hccparams2;
3380+
case ACRN_XHCI_EXCAP1:
3381+
value = 0x02000402; /* USB 2.0 */
3382+
break;
3383+
3384+
case ACRN_XHCI_EXCAP1 + 4:
3385+
value = 0x20425355; /* "USB " */
3386+
break;
3387+
3388+
case ACRN_XHCI_EXCAP1 + 8:
3389+
value = (((XHCI_MAX_DEVS/2) << 8) | (XHCI_MAX_DEVS/2+1));
3390+
break;
3391+
3392+
case ACRN_XHCI_EXCAP1 + 12:
3393+
value = 0;
3394+
break;
3395+
3396+
case ACRN_XHCI_EXCAP2:
3397+
value = 0x03000002; /* USB 3.0 */
3398+
break;
3399+
3400+
case ACRN_XHCI_EXCAP2 + 4:
3401+
value = 0x20425355; /* "USB " */
3402+
break;
3403+
3404+
case ACRN_XHCI_EXCAP2 + 8:
3405+
value = (((XHCI_MAX_DEVS/2) << 8) | 1);
3406+
break;
3407+
3408+
case ACRN_XHCI_EXCAP2 + 12:
3409+
value = 0;
33813410
break;
33823411

33833412
default:
@@ -3477,11 +3506,11 @@ pci_xhci_rtsregs_read(struct pci_xhci_vdev *xdev, uint64_t offset)
34773506

34783507
if (value >= 1)
34793508
xdev->rtsregs.mfindex += value;
3480-
} else if (offset >= 0x20) {
3509+
} else if (offset >= XHCI_RT_IR_BASE) {
34813510
int item;
34823511
uint32_t *p;
34833512

3484-
offset -= 0x20;
3513+
offset -= XHCI_RT_IR_BASE;
34853514
item = offset % 32;
34863515

34873516
assert(offset < sizeof(xdev->rtsregs.intrreg));
@@ -3551,7 +3580,7 @@ pci_xhci_read(struct vmctx *ctx,
35513580
value = pci_xhci_hostop_read(xdev, offset);
35523581
else if (offset < xdev->rtsoff)
35533582
value = pci_xhci_dbregs_read(xdev, offset);
3554-
else if (offset < xdev->excapoff)
3583+
else if (offset < xdev->rtsend)
35553584
value = pci_xhci_rtsregs_read(xdev, offset);
35563585
else if (offset < xdev->regsend)
35573586
value = pci_xhci_excap_read(xdev, offset);
@@ -3897,19 +3926,18 @@ pci_xhci_parse_extcap(struct pci_xhci_vdev *xdev, char *opts)
38973926
if (!strncmp(cap, "apl", 3)) {
38983927
xdev->excap_write = pci_xhci_apl_drdregs_write;
38993928
xdev->excap_ptr = excap_group_apl;
3900-
xdev->vid = XHCI_PCI_VENDOR_ID_INTEL;
3901-
xdev->pid = XHCI_PCI_DEVICE_ID_INTEL_APL;
3929+
xdev->vid = PCI_INTEL_APL_XHCI_VID;
3930+
xdev->pid = PCI_INTEL_APL_XHCI_PID;
39023931
} else
39033932
rc = -2;
39043933

39053934
if (((struct pci_xhci_excap *)(xdev->excap_ptr))->start
39063935
== EXCAP_GROUP_END) {
39073936
xdev->excap_write = NULL;
3908-
xdev->excap_ptr = excap_group_dft;
3909-
xdev->vid = XHCI_PCI_VENDOR_ID_DFLT;
3910-
xdev->pid = XHCI_PCI_DEVICE_ID_DFLT;
3911-
UPRINTF(LWRN, "Invalid xhci excap, force set "
3912-
"default excap\r\n");
3937+
xdev->excap_ptr = NULL;
3938+
xdev->vid = PCI_ACRN_XHCI_VID;
3939+
xdev->pid = PCI_ACRN_XHCI_PID;
3940+
UPRINTF(LWRN, "Invalid excap, set to ACRN excap\r\n");
39133941
}
39143942

39153943
errout:
@@ -4034,10 +4062,10 @@ pci_xhci_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
40344062
xdev->usb2_port_start = (XHCI_MAX_DEVS/2) + 1;
40354063
xdev->usb3_port_start = 1;
40364064

4037-
xdev->excap_ptr = excap_group_dft;
4038-
4039-
xdev->vid = XHCI_PCI_VENDOR_ID_DFLT;
4040-
xdev->pid = XHCI_PCI_DEVICE_ID_DFLT;
4065+
xdev->vid = PCI_ACRN_XHCI_VID;
4066+
xdev->pid = PCI_ACRN_XHCI_PID;
4067+
xdev->excapoff = ACRN_XHCI_EXCAP1;
4068+
xdev->excap_ptr = NULL;
40414069

40424070
xdev->rtsregs.mfindex = 0;
40434071
clock_gettime(CLOCK_MONOTONIC, &xdev->mf_prev_time);
@@ -4083,6 +4111,7 @@ pci_xhci_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
40834111
(XHCI_MAX_SLOTS+1) * 32);
40844112
if (xdev->rtsoff & 0x1F)
40854113
xdev->rtsoff = (xdev->rtsoff + 0x1F) & ~0x1F;
4114+
xdev->rtsend = xdev->rtsoff + XHCI_RT_IR_BASE + sizeof(xdev->rtsregs);
40864115

40874116
UPRINTF(LDBG, "dboff: 0x%x, rtsoff: 0x%x\r\n", xdev->dboff,
40884117
xdev->rtsoff);
@@ -4092,28 +4121,24 @@ pci_xhci_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
40924121

40934122
pci_xhci_reset(xdev);
40944123

4095-
/* xdev->excap_ptr should be assigned to global array in which
4096-
* it need include two items at least and field start must be
4097-
* ended by EXCAP_GROUP_END at last item.
4098-
*/
40994124
excap = xdev->excap_ptr;
4100-
if (!excap) {
4101-
error = -1;
4102-
goto done;
4125+
if (excap == NULL) {
4126+
xdev->regsend = xdev->rtsend;
4127+
xdev->excapoff = ACRN_XHCI_EXCAP1;
4128+
} else {
4129+
xdev->excapoff = excap->start;
4130+
while (excap && excap->start != EXCAP_GROUP_END) {
4131+
xdev->regsend = excap->end;
4132+
excap++;
4133+
}
41034134
}
41044135

4105-
xdev->excapoff = excap->start;
4106-
4107-
do {
4108-
xdev->regsend = excap->end;
4109-
excap++;
4110-
} while (excap && excap->start != EXCAP_GROUP_END);
4111-
41124136
/*
41134137
* Set extended capabilities pointer to be after regsend;
41144138
* value of excap field is 32-bit offset.
41154139
*/
4116-
xdev->hccparams1 |= XHCI_SET_HCCP1_XECP(XHCI_EXCAP_PTR);
4140+
xdev->hccparams1 |=
4141+
XHCI_SET_HCCP1_XECP(XHCI_XECP_OFF_SHIFT(xdev->excapoff));
41174142

41184143
pci_set_cfgdata16(dev, PCIR_DEVICE, xdev->pid);
41194144
pci_set_cfgdata16(dev, PCIR_VENDOR, xdev->vid);

devicemodel/include/xhcireg.h

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,13 @@
214214
/* RW - doorbell stream ID */
215215
#define XHCI_DB_SID_SET(x) (((x) & 0xFFFF) << 16)
216216

217+
/* XHCI runtime register IR base */
218+
#define XHCI_RT_IR_BASE 0x20
219+
217220
/* XHCI legacy support */
218221
#define XHCI_XECP_ID(x) ((x) & 0xFF)
219222
#define XHCI_XECP_NEXT(x) (((x) >> 8) & 0xFF)
223+
#define XHCI_XECP_OFF_SHIFT(x) ((x) >> 2)
220224
#define XHCI_XECP_BIOS_SEM 0x0002
221225
#define XHCI_XECP_OS_SEM 0x0003
222226

@@ -229,6 +233,10 @@
229233
#define XHCI_ID_USB_LOCAL_MEM 0x0006
230234
#define XHCI_ID_DRD_INTEL 0x00C0
231235

236+
/* ACRN xHCI excapability offset */
237+
#define ACRN_XHCI_EXCAP1 0x20
238+
#define ACRN_XHCI_EXCAP2 0x30
239+
232240
/*
233241
* xHCI extended capability pointer in HCCPARAMS1.
234242
* The excap offset is calculated by left shift 2
@@ -240,15 +248,13 @@
240248
#define EXCAP_GROUP_END 0xFFFF
241249
#define EXCAP_GROUP_NULL NULL
242250

243-
/* xHCI PCI Vendor IDs */
244-
#define XHCI_PCI_VENDOR_ID_INTEL 0x8086
245-
246-
/* xHCI PCI Device IDs */
247-
#define XHCI_PCI_DEVICE_ID_INTEL_APL 0x5aa8
251+
/* Intel xHCI IDs */
252+
#define PCI_INTEL_APL_XHCI_VID 0x8086
253+
#define PCI_INTEL_APL_XHCI_PID 0x5aa8
248254

249-
/* Default xHCI PCI VID/PID */
250-
#define XHCI_PCI_VENDOR_ID_DFLT XHCI_PCI_VENDOR_ID_INTEL
251-
#define XHCI_PCI_DEVICE_ID_DFLT 0x1e31
255+
/* ACRN xHCI iDs */
256+
#define PCI_ACRN_XHCI_VID 0x1234
257+
#define PCI_ACRN_XHCI_PID 0x1234
252258

253259
/* Intel APL xHCI DRD Configuration registers */
254260
#define XHCI_DRD_MUX_CFG0 0x0000

0 commit comments

Comments
 (0)