From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from OSPPR02CU001.outbound.protection.outlook.com (mail-norwayeastazon11023130.outbound.protection.outlook.com [40.107.159.130]) by lore.virtuozzo.com (Postfix) with ESMTPS id A85ED807C7 for ; Tue, 6 Oct 2026 15:36:04 +0000 (UTC) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=vbfoKi089WD5N+gkUJRLSVeFXEqXGz60ORbjo/Seh8f8XlRuct2kcQcnFcXDeDrf3Q++qTqxN6lB494xmozFQ5HBmJmCxJ2TwN0bSHOhEW9EaI6G8beosWCbdOpzDfaIAobz1FCsfR868V+5bIh3NitvSpPRvkcASnJhStP6PQ1bKmntEYtvaBtbBglmTbj6lNmrf3njjv5P9MZqqUbyV80VCsNzq+4vjh2LFvVlA4a8DDUP3ZaBC4V/Ld2Xgh2+huKhVipyZpi9ByUdwgXLtlqpp7z4/eNTTcZ2OZPOB3pcznf+NSN/IT/79tJ5AgQ4NyjhoVyH5axAD1tlcJ0E/g== 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=vgqMladmh8SNi8EkaJM6YvTkMV0Uddfol+gn858E76A=; b=csvcLlxMZGykSpTwqMTufe3+/xmioVqQD3EKIoyy9/rhZdi93wSokuCO04jDcKGTAECDY1UwH3EvVpRUygPYc6TWZt7zKvu6jr3pDk7PzLEBuk/LwR8IRQd4HuAwkP7Yq/AwRNCW9OIW+t6L06aYcSHgh4Oj2wmn6pwMrxTdu/jaHzUHUPZoGYsOtaS/U/oVrG/m1ijqGRxHQrLYfkAXWiM7x8ZxTGlrEFGpOvAZw9VxzEY3g8ISUwbOXlEawpCv0y4TTk8mRMSQvltVM6hgzH81LegVZYkQYqOPy6OXPxOXHJFhEV4dfdqsyOueRYvXCiTp88qmBBpYt+zD7kWQJw== 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=vgqMladmh8SNi8EkaJM6YvTkMV0Uddfol+gn858E76A=; b=BwW8nCKaSPRSMkz1KYYvsDv0TDb/cpiwCt7rxAFzW5LlrB5mLqtqSZYXG/N53/1ym93C2XR4ylOC8/+76slNUvT+/QlKaXRaIgkSKbmm8x9587nwpgJCWlCIjOSFbNQv8iuKv5gLoCNyHCTQ1eCq+qezJ6gU7QyaXbi0+fnHDYzaDxdW0pJNgIpJ17iKxa7RLiu0AxYKOg/RW+7/SlMgUt/EL8FDl2QTo3tL27jfLnuLmhOPoknU/A0xFgwT0IneYgyRWrf9IrwOYL9Z+oyuCwf7tyKASivg4fcOnEIz32ANfDuylAq4cG68hLO8zntN0aHM4CJWEbcBBFKwMmBP+w== 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 DB9PR08MB7699.eurprd08.prod.outlook.com (2603:10a6:10:392::22) 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 15:36:02 +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 15:36:02 +0000 From: Andrey Drobyshev Date: Tue, 06 Oct 2026 18:36:03 +0300 Subject: [PATCH QEMU HCI-8.0 v7 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-v7-12-044f668789a1@virtuozzo.com> References: <20261006-usb-host_v3-v7-0-044f668789a1@virtuozzo.com> In-Reply-To: <20261006-usb-host_v3-v7-0-044f668789a1@virtuozzo.com> To: svt-core@virtuozzo.com Cc: den@openvz.org, andrey.drobyshev@virtuozzo.com X-Mailer: b4 0.16.0 X-ClientProxiedBy: VI5PEPF00000985.AUTP296.PROD.OUTLOOK.COM (2603:10a6:808:1::81a) To VI0PR08MB10656.eurprd08.prod.outlook.com (2603:10a6:800:20a::12) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: VI0PR08MB10656:EE_|DB9PR08MB7699:EE_ X-MS-Office365-Filtering-Correlation-Id: c48388b4-9908-4520-e2b2-08df23bf8605 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|52116014|376014|23010399003|1800799024|366016|6133799003|5113699003|10067099003|22082099003|18002099003|56012099006|5023799004|38350700014; X-Microsoft-Antispam-Message-Info: W1mr48bgP+crJSm4yI3PwBEquONujuNeb4cXxbcWCNBYSszJZiNvBaOEgbD8hcElPv/d5NRGggmeA6qUe/DdVM+4+Wk91IpRHBYYurICPAgTqCgRRoVX4Ilt9zoD6qfC2cK3BG98BFTuf/xJjEuzmNRZ6WynWD50uz7qZA6v4x4BbORhV+NLFGSaEcJqnwANqVU9eMW4fd91xQ58KCQNPkpVBa0JzcEcslZW5yBCvqk6EpfGlbeQ2MIn9F/zAxzSzZw0sQ3w5FWK+nx0W/qHTnElqMHAzlE/i2gshbA8yFw4KxQ4Rq9W58baZN0FlanNewY2VGT2pGgJHv2X85khw+B8yQtzS04nzXxGsu3hNVmBigGAisPuTmctrKIBiatnb6lmnFAn5cCMEPFbxcI/tuoAv01BakSd8TDlkbVTlAo5Mvz5676q6pr47XxYAFW3bcXVX9dVW7eqQkii9lQngR9xCYxCOZbqiUM6z6aEIlbTzuKaErHcjxkKs6epqz3lA6uTecM2etrWOGT2Zc86gS2FesVMkfj14vC0SZQ/0rGFNwvUKVChJRCMoWYKfJg7No8RillhVpfcJT8tm8YWnbpiHcgJLT6exnCjxodz8yJXp8UDkrI4oC4wFOjtJPDifyd181W5zCTMCviFJzyhMRDclj7KsTlVNxFF8P1NIO5g24ujw63cB25X6i7djPAquhAJvd9zz6zmtzG6tw7cKZM2nbj7jI7tzMfT8I+ferw= 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)(52116014)(376014)(23010399003)(1800799024)(366016)(6133799003)(5113699003)(10067099003)(22082099003)(18002099003)(56012099006)(5023799004)(38350700014);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?SVRHVGNKdW9HdGhydm9NaURPL05UZFFvc2xSd2ZDTkEvQXRCZ2FCMXl1Zkhm?= =?utf-8?B?d3B3YkZtMVlYL3FraEtMUVEwcmgyK05FVTc4QnBsUG5MK21xaWlKSDlhUHE0?= =?utf-8?B?alFXcnpsV3dHMjE0OExBMWhSREE3SWZRTjBKeHpDc0s1Uk5ySmIvWERYd2pI?= =?utf-8?B?N0N5QzdSME1YemxKWkFxMGc2Tlg1ckZjUURnbkQ4ejJaY25VZDVBZWtoU2xI?= =?utf-8?B?enFCYnhoVDJDZjlNdVZuSy85QzdQY1phU2l3TXUrRGF4YWtSTGNsa0lBU01C?= =?utf-8?B?ODVCNXBFMkNrdzZjZVB4aUZSblJqTWNrNDNlM29PQnJZQlk5S2tLZUZGNDdP?= =?utf-8?B?VDdBMm44OVhNNGlRUC9xYkJXdU9zQ1FVb0JDVXZENEM5RVFpZ3JhSzlZR1d2?= =?utf-8?B?aUZKWEFzVG9nYnduVGZ6Q3crTVBhVkJmRTBpZ0ZIMnk4STE0aFRCZUt0R0FP?= =?utf-8?B?RjNmZ0hqUEZ1SzVqRlNrY2F6YTNTb0dTallBdDlGMk1UWFVnZld6aUZpWitJ?= =?utf-8?B?aVJrZzNjaDJQUzZka2ZGSmMzVzZqclFoYlZ1Vk4wczN3U3U3WlV4RjM1NzEx?= =?utf-8?B?VUMxMDdnNkpDMGlLdkREV082RTNVa2ZqR25OYnZqSzErN3lWZXJyL1FWRFM2?= =?utf-8?B?Y09Hei9tMGVyZGtqSThnYmRVWFc5UDRQWGFTNVI4eXAydnlmUlVEdnFtS043?= =?utf-8?B?RFVYRm03UFgxdVlPd3drM2xLdkhCak5NVTd5R1RMdzdnZnZYYWVZdjdPT0lz?= =?utf-8?B?SlhZMGZkb0ZnSkVqNlR6eHFVd3kzbkZWRUNuK0Eya2RwRWk2V2Jwa1pKNXJC?= =?utf-8?B?SW03S0pYVDd0d1VLbDAxRDNHSnZQRDB2Tktoeko1WHFqMml5OWZnVW1oUk54?= =?utf-8?B?SGVmcUN6dFpVZG1vMVdUMnpMTjcvbmNhclBRTFVYd1BZTFI0Y0FYU3ZkbjBZ?= =?utf-8?B?ZXFUUzFMQk5wUmZHbyt6bk1pSkFZR21KRmRtWFZoS1gyM1FsRHRFRnJ4SWhx?= =?utf-8?B?VUpSS2xuRHlBYmNKcWhORUphWHEwN0hkTnl4ekdZZG1GVURFZmZQNWtxWG5t?= =?utf-8?B?SitTSVNoclg3L1VNb1hMRXNVL2kyZ0tsUjA2d2txVXl2SXpyQzJQWGtEQlZE?= =?utf-8?B?QjhKbFFiQnVYTG5BdUs3NFJVclJtbW5MUGFHSWlvR04wNzl6bjdjVXhGZExJ?= =?utf-8?B?YkNpSzVwdi90Tm9MZGt3a0x0bURWdmx3VzhwdkpDcSsrbDgvdDJaeWZadjNx?= =?utf-8?B?Qnp5azFPME1SK096K2poSmtGN3FTZWViWnduY2x6T0drY1BHZGR6Q2pEd282?= =?utf-8?B?dVcreldhS2xzU3Q4Y3BGTXovTnJuWE9JcTFCcTFWUmwxVDMrTytzMENPeWdt?= =?utf-8?B?OUxoMW92QTZBdllxd3JiV1pvWEdZeVVrcFVUTVBjc3V4MW5ZMVhwZFFGTy8v?= =?utf-8?B?dnJFbmhwRW5ZdG96cmlRMUp6azRQZlRWNk5nZXVKZ1crRGh2cGRWdmc1dDAy?= =?utf-8?B?cER0RGJ1ekM4aEFuNDI2N2t4Sk5renJnZHZOYWMzT1lNdGNLaFI3QzR0UkI5?= =?utf-8?B?TnhFRFJOY1laQ0VTckVzN2pRdGZPYVNEaG5yRVU4VGxWckhXL25BVHB5N2Vv?= =?utf-8?B?RjI3Q2tqUDBiUXdYM1FxVFVlUFZsU2VPdm1XbG5TQnRIQ0k0UVRWQnBLdUp2?= =?utf-8?B?VU5CRnMxeGh5a1ZrR1p3ZU84dVJNeHVQNnF1S3NTK0hjNThOSU1XeGl6RFgz?= =?utf-8?B?TE1wUStvbFpTYmViLzRkYXV2bm1USVdPeitxVWUyT24yWVlJVlZLTm1tVVNx?= =?utf-8?B?SlJQU0dGa1RXS05ZdElhRkF6bVFzc2lGY1V3K1RmMnRDUncvNFhQU25FcFRJ?= =?utf-8?B?NVIwKytnZTBZTzZTQmxiOWtxN0FSSmdpekl2bHBMOGpjbDc5clVONURlUm9V?= =?utf-8?B?NTcrdE50UndQeFFZcmdWMktwblQ2ampYbG5DeGxIY0IxOTBkaUYrZFhoc2Jh?= =?utf-8?B?UGtsais1Y1ZJUUFqUjFhMXRjZXlZdEtzamwwSDJPRDI0WTF6STE2OHhha2lU?= =?utf-8?B?aGFuemIxQ1dXZDdTZFBRMFVBemZsZGF0Rm0vMkFXa2szSm5uY25DS1l6aDJp?= =?utf-8?B?U29MdCtZUDhpRFIxRlZTOTg4NXBod3JTRzlJaDJOK1BTVFZmeVRTZ01hZCtV?= =?utf-8?B?dERrRHVBeFg3Mk1CRFNEaS8zdGdIMUk3ck5SbHQ0Zmw4NW9hRXRUeEdvMXd5?= =?utf-8?B?a3VUTEVXL2VOVmdJVGNqL0VQSHJINis5Q21xNlpHMmFJM1pIUWdmOXNQTjdC?= =?utf-8?B?MXUyVnl0QnFCVWtuRklkd0VyYVkrR1FKMGNkdzEvQ0psNEdnL3hDMlBpQ2Rv?= =?utf-8?Q?Kb16bjFhmnu7RuK8=3D?= X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-Network-Message-Id: c48388b4-9908-4520-e2b2-08df23bf8605 X-MS-Exchange-CrossTenant-AuthSource: VI0PR08MB10656.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Oct 2026 15:36:00.5171 (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: Z/Ym0eTKTVO/IsbrkxDjpLoT8RMlI7T/p+++UpbryDM3an3+Y8Z4f9iCxMrJq2us+8LesnIZpuQ2/5wnYpWFDViy0vXIX5SJSaBKKbCKUxw= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR08MB7699 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 | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index 387040d6e1a..cbe1b91c46d 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -976,7 +976,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]; } @@ -2079,6 +2079,69 @@ 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; + + 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; @@ -2088,6 +2151,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(); return 0; } -- 2.47.1