From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from GVXPR05CU001.outbound.protection.outlook.com (mail-swedencentralazon11023102.outbound.protection.outlook.com [52.101.83.102]) by lore.virtuozzo.com (Postfix) with ESMTPS id 39947807D5 for ; Tue, 6 Oct 2026 16:28:05 +0000 (UTC) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=vSojxHScCTMzo+yUmKELM/F21ZHJImRrSt8P5CZJlPc9ycVhrp9K2nlbCfJsxer3HRQtKgZEnlQPRgY5CgwRZsJRCOKZfyzvQa6CEknee+4BTW0ejijLCTP4aSOzGg6LncF1OlLxYWP0ADEXFmxutcOyJ0DCuVAy75K5vMvJt3Jb0fdpJD94Y4CJuIANPi6H/dEkf9XHoBih7CJDgCVeNoL17dilotTHuUP8PiVIbcQzDj0SDIaZTajn6SvcBRCT0AmlsRVDhUKlU3DE4VEEr0UDKw2aFlHMYOVFubaUcOcd37xBi8HgpB1/oZTjaRMcvex0lxAr9o/RcZ2xdyoy+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=URb50pBvaZajkNb1i29/toE8wj2hRvPoRWSgQAnombo=; b=wK4kr8UZCvEWjD8AWcS6jA/m7voB4ocrkozeYdT8bt8W9yURwnaLGYspSKcdQZSFXIAN1uikosw+lCxvf+cOpUFJHw754lctra8WjCfe4bs2BV2Ht3VlWM1uPrfQKdaDR3Lup7UoRF9W0UNP6S1UsftAfdBe/MPuoaoDnOFLwheu56apYNzKgoinNKJqi+S/HZK1erRoqpjzADqasEWhiHjKTWIof9Ga0jDFMjNQZry8rYtKisII2RSskOl37NndovcHzBdhqWbFGoppzYAdh+NoO2p4uLAdMw1+04pVn1U2n7uvKExsaZpOEXlI/aNocRAQQniYZ5hSZqXTlbK9zg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=virtuozzo.com; dmarc=pass action=none header.from=virtuozzo.com; dkim=pass header.d=virtuozzo.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=virtuozzo.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=URb50pBvaZajkNb1i29/toE8wj2hRvPoRWSgQAnombo=; b=AczgtkMO06AUKb0in+DfuzkMoDLH1TxHB4dYmSEmGbiAk2aHAI66rVszBBXf9/PM0Gm57gg1GOS/FmzFnZxgQzAdoJLTvxDwS09I6Zm4dpf+oBNXzyJLZYsD8O5v16hpIns9j2dM88rB2scRoUckVImr/M6JCnb9WL2FtCDgyAd2r2ERt3Sc/+aOmIQLugg5bkl/G0F64s7TwBeWz1ilD1z+AbojGLFmgI86OAWcK1izpSOY6340z/m4qbbNZOWtmalzoIbDLFPuV+I+hoiC73W7Gz5sfTI2GunUEnyEFqZD0rhCCp2bWIuW1nx0h9fFQTQSKokdEDKSOPuRw3x1bQ== Authentication-Results: mx.microsoft.com 1; dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=virtuozzo.com; Received: from VI0PR08MB10656.eurprd08.prod.outlook.com (2603:10a6:800:20a::12) by AS8PR08MB8899.eurprd08.prod.outlook.com (2603:10a6:20b:5b6::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.496.14; Tue, 6 Oct 2026 16:28:01 +0000 Received: from VI0PR08MB10656.eurprd08.prod.outlook.com ([fe80::4e37:b189:ddcd:3dd8]) by VI0PR08MB10656.eurprd08.prod.outlook.com ([fe80::4e37:b189:ddcd:3dd8%7]) with mapi id 15.21.0496.010; Tue, 6 Oct 2026 16:28:01 +0000 From: Andrey Drobyshev Date: Tue, 06 Oct 2026 19:28:03 +0300 Subject: [PATCH QEMU HCI-8.0 v8 12/14] usb-host: reconfigure endpoints on CPR incoming #VSTOR-137800 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20261006-usb-host_v3-v8-12-72ae4fb8977b@virtuozzo.com> References: <20261006-usb-host_v3-v8-0-72ae4fb8977b@virtuozzo.com> In-Reply-To: <20261006-usb-host_v3-v8-0-72ae4fb8977b@virtuozzo.com> To: svt-core@virtuozzo.com Cc: andrey.drobyshev@virtuozzo.com, den@openvz.org X-Mailer: b4 0.16.0 X-ClientProxiedBy: VI1PR08CA0230.eurprd08.prod.outlook.com (2603:10a6:802:15::39) To VI0PR08MB10656.eurprd08.prod.outlook.com (2603:10a6:800:20a::12) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: VI0PR08MB10656:EE_|AS8PR08MB8899:EE_ X-MS-Office365-Filtering-Correlation-Id: 05ea429c-926f-4f40-8f2e-08df23c6c8ef X-LD-Processed: 0bc7f26d-0264-416e-a6fc-8352af79c58f,ExtAddr List-Id: svt-core@virtuozzo.com X-MS-Exchange-Transport-Rules-Loop: 1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|52116014|376014|23010399003|5113699003|6133799003|22082099003|18002099003|38350700014|56012099006|10067099003|5023799004; X-Microsoft-Antispam-Message-Info: GmDLJb/NqsF4Xn3Jo8WJjpTWtUY1CIsFJOKzPg9/NNf85dX1Y5+7uXJ+CZFV7YpX7z0evq4NY57ebj+6RLdbBAlqrilSyJSgxdV8cL+b+/72Eb1CAt9P/Pu4LacoEo6jter+Zv/8PmWhMQhTUbJ0+V/tBE2LMUVElRcSU7447GKjlKmedcDJflOhJ8Cx327wOHcj+EaG4wsJWF9CrKJVsKX2SnpJfbFKRNqW4yKfaCPNLLAeqZ9yn5zMC8WwOWoB3ZlNVCMwfmEJkMiSTSjeADa6Uq+17HTtKFiCwxISvRLDLb7EIqwptVIbiDtnlCH0DAgTe4sRlBz4Bf8y39xW/7WkW0mIzuAPQyqIvxXy4AnQ/WMw8JEcdqa7xVUE+X+5pL887ZTgW00zr5PfPHtubLPMRaPlQNnqlMqnbdoqkN4dpCH0twrL80veAYc6VNrxV6oXh94J7B/H1iZ1oi5Eu9HShkP+theykXE+qJIi+kJplSkIhy/nrAwbc7q8AMTHaB4/E9dqjVfANPDZIdMIpmy78ffjzfrPZgRD6xzpv6i7OQmcuiyqDI8BwfdxY2ReA4iQvr2UQajzSt6p1T8fYp4CYGw54Cga7WyRA9uWwrLAwcR8MW56R2TRu8g7teCk8BjBK8ZiTmrFKFX7gBNX1gMg1MpnG7IKojs/vFJIe2rY1VSUsAGWngLlzm7ratZ3Lqo3aacYasQnEZ/r0bk5FbhrM9dB+D+OsBwRIiSTP5o= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:VI0PR08MB10656.eurprd08.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(366016)(52116014)(376014)(23010399003)(5113699003)(6133799003)(22082099003)(18002099003)(38350700014)(56012099006)(10067099003)(5023799004);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?UkdnOXRHVDhWMVM5OFdYaGFhYUVtVUxOU3hueENBN3R4eUxuZU1QSlNkeUNt?= =?utf-8?B?d0JkMmFobVhBTk5GVHd3d1ZkWWtMOWxCRWhib0JaZXVMZVBLUi9IY3pYRENq?= =?utf-8?B?eUtLOGo4RWMzRFlpUWJFWHFVTEg3UkgyNmEvVk43RWJvMmRNT1ZvU2Mxc2Z5?= =?utf-8?B?OGhySHJ1azY0LzREc1RabzhwT1NNMmU1cTMwUm03Lzkxb0prWGRZdXBKU3NR?= =?utf-8?B?MW9VODNnUHljOGttOXlBZ04rN0gvbmhxSE0rek5mYjAvUjFTMmh5QzNRTFFi?= =?utf-8?B?UDZyRWppcjMzNHJWYVFaWUlCREo3amJNRGJINWJmc3MraVlyeFc0ZHhPVm5S?= =?utf-8?B?anFPL2tOcTlha1pEa0prR3hBRUNld3NWeDBIaDRVVmNrYWRHdVlsdVo0S2ts?= =?utf-8?B?TUxEdmt0aTVSbWxnYVFvU3p2YWlDRllhSEZ6cGE5bWsxNGxvRUxoU20vd1dB?= =?utf-8?B?T3BYMjJKS0RKQklXZmIweU83U25yOC9naHduOTZhQlZwZklSNDNIQVExNWRu?= =?utf-8?B?cUpSTkJiQ1J6Mm1TdUJaZGV1YmlRNVdvZzZGM2hjbVNYR1hQYmFkaFRFQjVs?= =?utf-8?B?MzNoRGpmMHF3T2pXcGZITUpCODlUVDIyWFdQMko1eXlPUjVUZ3BIa1JpUWlu?= =?utf-8?B?bVRSOWtWd0g2eEl0ZnBxVklKQk5BYzVkVGxsbTM3ZDNuZVdIWGxycllsdlB3?= =?utf-8?B?QnZ0WklmLzRvMjZVZnpFM2o0VFFIU0pEa3c3azZ2V1hZTUtMUE9la0IvY3VD?= =?utf-8?B?S3RrSDNSSW9wbUF4OTMrWU9sb3hDQjZXV1FQeGU4SUp0WlA5VnlYV24yNGZS?= =?utf-8?B?bnBjdkxsc1dsalJMVkJRekdiVjZSTjZETDQ3dHVxK2U3TFV6VHpFWmZMcndS?= =?utf-8?B?M3d5WXNpblZHRUx4R2FRb2xldzVpWkRtRTJDaHk3WVdHWDFVWm1Kc2c2YTdK?= =?utf-8?B?SVBmbmJ2ZWFoSmU2NFI0cXJVM2ZDcUExOUlQLytjaDZoV1puTXZGWi8yR1kw?= =?utf-8?B?cTNyYVdiNExxdXIrNmd2eHdtUWNDQVpLLzBnYTg4WTQ0T05JQjcyTVhBa015?= =?utf-8?B?a3hYMWhEeXVZWllFcS9mcU5nbitkVXl0Z2FsOFlZNVVlRVZaVjZYU05nQ3p1?= =?utf-8?B?ekdyRWZabzUxbnFNejRHRG1nakQxWDBHSU5MZStoOHVkQU5IUS91VE5rSFV5?= =?utf-8?B?dUNWR0oyVFBMUEtQRkdmQ0s2d1d3YW5ZeXB2cm1ORmlydWJta1ZSR1V2Y0hl?= =?utf-8?B?a3Y2cWdhTjNEekRZMDZGNktFQVhlRlRGNThoVU1seDJyK2FzOWVCV1VZZnRq?= =?utf-8?B?TUFPZmY1dkpqRE45T0V3bEhpeVpmS0hSenVFbnZvclh5TEJqUTNPMnlLMStG?= =?utf-8?B?TGsyZjRJSkhLcW5EOHlrNnZkYlJBbUFsK29LN09rdlVVNVJrbm9xeVRWVW9y?= =?utf-8?B?ZVY1cXJCMTd3NWlCdHJRSDZyd2JnWjlBYndTdi9EOWRFQy9lOWpOeStwM0Yy?= =?utf-8?B?V2RQeHlsOFBYM1NLNUNBRWtuTFA0OS9SaFQyd1lvY1ZEV2dSL2g0UzFIbkNZ?= =?utf-8?B?eHMwZzByck5LWFNGMWxJd1QwU2t2UTVWR2kxbjlaQXEwRkxVMlJpWXBHSWpr?= =?utf-8?B?N1MySE5LYmFEZHgveEtycEVCZWRtcHNyUFdyeUVYN2lFcU1TZ2tLKzRRT2hR?= =?utf-8?B?TzdRU01zUk5VV1dYR3VJUjJsQnBZbEhvQW8vSGlwSnJiOS9YcHF3MnNVUWhs?= =?utf-8?B?bm1vb2hSR1k5VGZLT0xsRnk3NUlWOWRLSjYvL1Q5amhna0E0MDBRZkVhZk9O?= =?utf-8?B?WkRuazBSNU1jYkphdEN3eDJCZ2R5dnFOWDdjLzhic0VYQnBvL2VTRGt1OE0v?= =?utf-8?B?UW1nWXJwS2JmYW9wVWo0Umlyc3FvOTNYY3c2ZDNUQU5QbW0xQVV2L296eTAr?= =?utf-8?B?dDBpUXJZZ0VWR25aZWd3RjQ3OWkrZDl5anY4ZHY0dnBvNUgxQ1NUOGtldlJr?= =?utf-8?B?NmdNdjRmTEFMWUpIeFBHT1ZzRFNvckZXWGNVRTVpSTlNSVE5UGVlSElJQnVF?= =?utf-8?B?dmprVFgvNytlWUljMUN3VHpXTGI4QjVTUjYyV0tZTThsRm9pNkY5bTMwd1du?= =?utf-8?B?YW1CaXM4T3JtYVhTbGpiSXdObHdtZ0VJUjRPcUlqbFl5MXp4c0k5UkdaendF?= =?utf-8?B?ZDNuQkN6aktndTZmOVFFemNjMWhFWDJHVG1VSkR4WTI2U2FsK2xLUHVqZmhK?= =?utf-8?B?TTJHZ3ZGK3d1NEsyQ3FVcXczd3FaQ1hnNnE0d250R1hPTmpFSFFhRzBYMitp?= =?utf-8?B?MWtSQnVBdHNVcjV3R2tENG1LTUlqRy9BeUxBL3I4L01rZVJYY1FLSHpGTkF3?= =?utf-8?Q?B9LTxh8kGiMtmb4w=3D?= X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-Network-Message-Id: 05ea429c-926f-4f40-8f2e-08df23c6c8ef X-MS-Exchange-CrossTenant-AuthSource: VI0PR08MB10656.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Oct 2026 16:27:59.2648 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 0bc7f26d-0264-416e-a6fc-8352af79c58f X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 6B+da+bYkiA0Wpwcs7ivJArvp1ZE6Whg1pFj4JCGRoF9tYV7saxTPb/lU9OCoJnMcJUOrAg9RBNs4N0MGIJEUDPzFo7uev20cqK7C5Pqoew= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR08MB8899 On CPR incoming we skip the usb_host_open() rescan, so libusb only sets up the endpoints from the device's default configuration. If the guest had enabled an endpoint by selecting a non-zero altsetting (e.g. an isochronous streaming endpoint), that endpoint is now missing, and the guest's transfers to it simply stall. The altsetting itself is restored by vmload now, so let's call usb_host_ep_update() on the CPR target to rebuild the endpoints out of it. The kernel claims are still there on the preserved FD, but libusb's own handle knows nothing about them, so a later SET_INTERFACE would fail with LIBUSB_ERROR_NOT_FOUND. Let's re-claim the interfaces on the target as well to bring libusb's view back in sync - on the preserved FD this is a no-op at the usbfs level anyway. Signed-off-by: Andrey Drobyshev --- hw/usb/host-libusb.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index 1412f92c12e..076ba08533b 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -988,7 +988,7 @@ static void usb_host_ep_update(USBHostDevice *s) alt = udev->altsetting[intf->bInterfaceNumber]; if (alt != 0) { - assert(alt < conf->interface[i].num_altsetting); + assert(alt >= 0 && alt < conf->interface[i].num_altsetting); intf = &conf->interface[i].altsetting[alt]; } @@ -2101,6 +2101,75 @@ static void usb_host_post_load_bh(void *opaque) usb_host_auto_check(NULL); } +/* + * Reconfigure the CPR target after vmload: reject a migrated altsetting the + * device can't honour, then re-claim the interfaces so libusb's view matches + * the preserved fd (which already holds the claims). + */ +static int usb_host_cpr_reclaim_interfaces(USBHostDevice *s) +{ + USBDevice *udev = USB_DEVICE(s); + struct libusb_config_descriptor *conf; + int rc; + + if (!s->dh) { + /* e.g. a target whose command line doesn't open the device */ + error_report("usb-host: CPR target has no open host device"); + return -1; + } + + rc = libusb_get_active_config_descriptor(s->dev, &conf); + if (rc == LIBUSB_ERROR_NOT_FOUND) { + /* device is unconfigured (address state), nothing to reclaim */ + return 0; + } + if (rc != 0) { + usb_host_libusb_error("libusb_get_active_config_descriptor", rc); + return -1; + } + + /* + * Validate all migrated interface/altsetting numbers before touching the + * device, so garbage migration data can't leave it half-claimed. + */ + for (int i = 0; i < conf->bNumInterfaces; i++) { + int ifnum = conf->interface[i].altsetting[0].bInterfaceNumber; + int alt; + + if (ifnum >= USB_MAX_INTERFACES) { + error_report("usb-host: interface number %d out of range", ifnum); + libusb_free_config_descriptor(conf); + return -1; + } + alt = udev->altsetting[ifnum]; + if (alt < 0 || alt >= conf->interface[i].num_altsetting) { + error_report("usb-host: migrated altsetting %d out of range for " + "interface %d", alt, ifnum); + libusb_free_config_descriptor(conf); + return -1; + } + } + + /* Data is sane: claim each interface on the fd and record it. */ + for (int i = 0; i < conf->bNumInterfaces; i++) { + int ifnum = conf->interface[i].altsetting[0].bInterfaceNumber; + + rc = libusb_claim_interface(s->dh, ifnum); + if (rc != 0) { + usb_host_libusb_error("libusb_claim_interface", rc); + libusb_free_config_descriptor(conf); + return -1; + } + s->ifs[ifnum].claimed = true; + } + + udev->ninterfaces = conf->bNumInterfaces; + udev->configuration = conf->bConfigurationValue; + libusb_free_config_descriptor(conf); + + return 0; +} + static int usb_host_post_load(void *opaque, int version_id) { USBHostDevice *dev = opaque; @@ -2110,6 +2179,14 @@ static int usb_host_post_load(void *opaque, int version_id) * rescan in usb_host_post_load_bh() -- those are for cross-host migration. */ if (cpr_is_incoming()) { + /* + * The device stayed open, so rebuild libusb's claims and endpoints, + * and start reaping now that the source has handed the fd off. + */ + if (usb_host_cpr_reclaim_interfaces(dev) < 0) { + return -1; + } + usb_host_ep_update(dev); usb_host_start_events(); /* the takeover is complete: from here on this process owns the fd */ dev->cpr_handed_off = false; -- 2.47.1