From win-pv-devel-bounces@lists.xenproject.org Wed May 13 14:05:16 2026
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 13 May 2026 14:05:16 +0000
Received: from list by lists.xenproject.org with outflank-mailman.1308076.1579617 (Exim 4.92)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1wNAD5-00011Y-Id; Wed, 13 May 2026 14:05:15 +0000
X-Outflank-Mailman: Message body and most headers restored to incoming version
Received: by outflank-mailman (output) from mailman id 1308076.1579617; Wed, 13 May 2026 14:05:15 +0000
Received: from localhost ([127.0.0.1] helo=lists.xenproject.org)
	by lists.xenproject.org with esmtp (Exim 4.92)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1wNAD5-00011O-Fa; Wed, 13 May 2026 14:05:15 +0000
Received: by outflank-mailman (input) for mailman id 1308076;
 Wed, 13 May 2026 14:05:13 +0000
Received: from mx.expurgate.net ([195.190.135.10])
 by lists.xenproject.org with esmtp (Exim 4.92)
 (envelope-from <owen.smith@citrix.com>) id 1wNAD3-00010w-93
 for win-pv-devel@lists.xenproject.org; Wed, 13 May 2026 14:05:13 +0000
Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp
 id 1wNAD2-000luV-Fv
 for win-pv-devel@lists.xenproject.org; Wed, 13 May 2026 16:05:12 +0200
Received: from [10.42.69.8] (helo=localhost)
 by localhost with ESMTP (eXpurgate MTA 0.9.1)
 (envelope-from <owen.smith@citrix.com>)
 id 6a048512-e002-0a2a0a5209dd-0a2a4508ec02-34
 for <win-pv-devel@lists.xenproject.org>; Wed, 13 May 2026 16:05:12 +0200
Received: from [52.101.56.21]
 (helo=BN1PR04CU002.outbound.protection.outlook.com)
 by tlsNG-c1860d.mxtls.expurgate.net with ESMTPS (eXpurgate 4.56.1)
 (envelope-from <owen.smith@citrix.com>)
 id 6a048516-63b5-0a2a45080019-346538152edf-3
 for <win-pv-devel@lists.xenproject.org>; Wed, 13 May 2026 16:05:12 +0200
Received: from SA6PR03MB7760.namprd03.prod.outlook.com (2603:10b6:806:43c::5)
 by SA2PR03MB5723.namprd03.prod.outlook.com (2603:10b6:806:118::6)
 with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9913.11; Wed, 13 May
 2026 14:05:09 +0000
Received: from SA6PR03MB7760.namprd03.prod.outlook.com
 ([fe80::4d5b:a91f:46a3:4b38]) by SA6PR03MB7760.namprd03.prod.outlook.com
 ([fe80::4d5b:a91f:46a3:4b38%7]) with mapi id 15.20.9913.009; Wed, 13 May 2026
 14:05:08 +0000
X-BeenThere: win-pv-devel@lists.xenproject.org
List-Id: Developer list for the Windows PV Drivers subproject
 <win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <https://lists.xenproject.org/mailman/options/win-pv-devel>, 
 <mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <https://lists.xenproject.org/mailman/listinfo/win-pv-devel>, 
 <mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Errors-To: win-pv-devel-bounces@lists.xenproject.org
Precedence: list
Sender: "win-pv-devel" <win-pv-devel-bounces@lists.xenproject.org>
Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=citrix.com header.i="@citrix.com" header.h="From:Date:Subject:Message-ID:Content-Type:MIME-Version:x-ms-exchange-senderadcheck"
ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;
 b=wfIo9lYG8AsN75vT0z3qb7rGNwzYRW4W1LCZpXrbadpVARRDTqEZjoL/6cHJY33ScFmMV+wju7Rexfm3nqmct2VOVml+Kmv75ONZtUX6RrMq9twTPdYOqS+OBGMIli5HcdEkut/EHlvRMHCtkD6yRfnAeSbi83y4529NOYs2fZNNJbsoyd7XKWyahzq49O5UBxLM0EWmq/Ze7U1egD1F3Iz+tTj4IszTy+Z/f1UnIwUt0nmCo4USt+93ikCQARs3gU3Ofx/+/f9O6Z1rV+OghKXKIAQq5NoxhHr9kv0w30rLQqOJ+sL9IrhrOjylih58itIS8uCMFztbj9RVP7NvJA==
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=AywKJuq7cZ17BIUIhFo4V+zRD9jDte/+vdmVxlJzaSk=;
 b=O6jofNli6wIKy/SHHNzQEZxfXaqOBzGIBMsK6OGyzhZr6e5EzVbi2HEGQ2yU4yIEuol+wXLRL9lXGg6dsuoB8cU7cnbO5cG1aZ2MAv4iDypjE1M4AzslfHmr5EX0Vrv+rrDPJgnVFKIgJYAyHC/dEPPs2ITv31aEh5DeeFfyKyIgVJ40dLU4eTAM4W8yPvhFT6vHF//ajMmcLEIUcXwsMGBQsD8pV12BiJZQ4yhN+K7hOrBEcYzvp/oJNGc9Pw6vfBH8ZpitY55QtsM/2uJICmmnbKmlG70ra6l+7i/TDkY1nFf5xBhhnBgvLEQvoTok6s0pu5cmjIZy73SSpUXtLA==
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass
 smtp.mailfrom=citrix.com; dmarc=pass action=none header.from=citrix.com;
 dkim=pass header.d=citrix.com; arc=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com;
 s=selector1;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
 bh=AywKJuq7cZ17BIUIhFo4V+zRD9jDte/+vdmVxlJzaSk=;
 b=vpfxYJMgc/9NDEAEsqbteQ0z7j4TMOVNDU1ghxpJ4D0Eo76So99F+bTll48YSYeltyPlCmm6avMoUhgV25wffUZ9e8Qh4J1k6ySmdWeMZqsULz1l9m6cCvxZ5sCf8Hrn9wy/dV15bkM9R8UIbUJUP69yYtzVKZXZxTADlpxfnX8=
From: Owen Smith <owen.smith@citrix.com>
To: Tu Dinh <ngoc-tu.dinh@vates.tech>, "win-pv-devel@lists.xenproject.org"
	<win-pv-devel@lists.xenproject.org>
Subject: Re: [PATCH 4/5] Implement rundown-based MRSW lock
Thread-Topic: [PATCH 4/5] Implement rundown-based MRSW lock
Thread-Index: AQHczZGVucbfB0LVdUy2gYIuu73oyrYMJkPM
Date: Wed, 13 May 2026 14:05:08 +0000
Message-ID:
 <SA6PR03MB7760EC354D7AF28E5EED13A9FE062@SA6PR03MB7760.namprd03.prod.outlook.com>
References: <20260416110952.355-1-ngoc-tu.dinh@vates.tech>
 <20260416110952.355-5-ngoc-tu.dinh@vates.tech>
In-Reply-To: <20260416110952.355-5-ngoc-tu.dinh@vates.tech>
Accept-Language: en-GB, en-US
Content-Language: en-GB
X-MS-Has-Attach:
X-MS-TNEF-Correlator:
msip_labels:
authentication-results: dkim=none (message not signed)
 header.d=none;dmarc=none action=none header.from=citrix.com;
x-ms-publictraffictype: Email
x-ms-traffictypediagnostic: SA6PR03MB7760:EE_|SA2PR03MB5723:EE_
x-ms-office365-filtering-correlation-id: c0058b20-596f-45d9-a159-08deb0f8a44a
x-ms-exchange-senderadcheck: 1
x-ms-exchange-antispam-relay: 0
x-microsoft-antispam:
 BCL:0;ARA:13230040|1800799024|366016|376014|38070700021|11063799003|56012099003|18002099003|22082099003;
x-microsoft-antispam-message-info:
 G66HA7dlWNcvXJY4uXxYAZ4Nzclnf8DfBgFRFZdWvUszGMMW0CEcu0r0950+faihgRVGP2Aed0WjPeDEkLQYTNYmNEbmVi3cfIrMV65LHF2zJiWMKlZasJDgzVham3FJHWzenOw2nBkj97rSahyE2pCEq1Bpr97sm+iR0ZRSQOnJiODxpQsCcSyCXzFvrAZs736+b7KREDnUf3Q5GtTGYt6EIDeUoJHHGhWYxA0kg5DpDUOa//Kv2HjNaCdrNiIXLjhu1o1F3NQbWfVuf1cbdWyyRPJ7FFF6H1shQtXEZINveYMN6tOz6/LAfd/8HprB5haRvoaZ7Ytbio9T1TExLdyLdi2fhA9aLWD5hBgQH2JXmiBGaNOASwHvHOyHkYgFR6s9ee0YW38QUC6yT2znQOLb6Ke176hSTdmZnEGWzQteK34MIkG6zBhGPhfUoXAplwlKT53HFaVXsEUzX3kXqnfcgDXLPINnYoz3+xENYGi0hGafsXewImAeMyVe4/JaRf8SUvnJc1+OGJBvpdpoGhV4FyTtlD42FrRpLFpCiqZB2pkqECRCHU/ZC9KJxxcDP89ztAD93nqR8eoQeGOAz1aMCJNHb3L/oHvXkhYAC8JyyXs8JOBt8xtnMYqU6R2ZrRJJw2vKB0sXJfssa28zJHXPuHOEQQA6KH9uoPNUZ+R63P0EYZ/+8aIAceCryS3F
x-forefront-antispam-report:
 CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SA6PR03MB7760.namprd03.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(366016)(376014)(38070700021)(11063799003)(56012099003)(18002099003)(22082099003);DIR:OUT;SFP:1101;
x-ms-exchange-antispam-messagedata-chunkcount: 1
x-ms-exchange-antispam-messagedata-0:
 =?us-ascii?Q?ognhfiOVuOrCA0pISYyrFLDOJNmXPUrwbRgK1GPuojtu8B9bNSZ70WXg39FJ?=
 =?us-ascii?Q?wSDSD1CBaMcJ/wWCLysL0nKTfZ0V6WB1b5KkKs/u0TGRXKIR4Da1pN1PzNa0?=
 =?us-ascii?Q?/aE2WglwFalBaMMkBlMTnc19Ce+TdnAl6bVO7DP6iY36dJ1l0/b7WLexG+Ei?=
 =?us-ascii?Q?rzxXzKHqLFh8vL1uPuo4FnPcQyWEXUKrs/ppOIEv5Jma2TTlUUxzAOc/wG4O?=
 =?us-ascii?Q?BumeXI/TUQYPHIERVyWmkA1fbjnG18ur6VA5WopsFT7vJFYGaidHH/mseVgp?=
 =?us-ascii?Q?w6fcGWQFh8vh1vYrjpmGrKem2Su9lL8H/0xP13CkYU6XSMAwjBAx3md5foSB?=
 =?us-ascii?Q?cuv/vIDUsOwm0G2XL4L4k7p2B/u51kg88skBHsU8p/ya3UqKCRIk+tmFBHuX?=
 =?us-ascii?Q?hRRWAlGj+M4GTk0UOLrOO0CRhivPIgpE1RCTSN10S+6nxQm8Lci9zAoaITr0?=
 =?us-ascii?Q?5ksI4DuN5XtqkvLrthusiDQ4gGYA0MawZ3iPuMiKAjMNeabVvIT+PgamDL8R?=
 =?us-ascii?Q?1rPT4x8W//7EGBbhqGOygLkZbWkraWwRUfGCDsf8OyFKrhXQojHwMQyEworf?=
 =?us-ascii?Q?dvgGL5S7cHurncIiL9kmeF2J+TcvQPFQyRgnx5CpxpOk5cMfTmEAM+qJZrpz?=
 =?us-ascii?Q?DXewGadOoK0VekyKK8jGjeycf7WnjPBctgvohZ2OE8kajM+WKr+GZTzTVXBd?=
 =?us-ascii?Q?bMt3peCZIlT2mnhAvPwFz5g+42z1pQQMDqOQkvj7rRXT569jspjRUNmLsIIC?=
 =?us-ascii?Q?yRBHufiaa0Lb9MtdSj64tFmuNpR7esvhOttvyxn7dbDjdLt8C+6n03bM4q1U?=
 =?us-ascii?Q?DRjnxOzDITpqrriUT88pqMuwdXPqy3FgyDIeyCNsndlcD3a+b7Q5EpQlN7KS?=
 =?us-ascii?Q?FFwnQy1kAn9HYpeE0BEXeS21j5tc6jiWwLNtno8beqvief/X2W0e4opK/qhm?=
 =?us-ascii?Q?RNGwZBwZOi2+cK7KN3hiO3s7rFB/i+D4uLMxUVP6fCHAde6hTPNMBEClN/M9?=
 =?us-ascii?Q?xAxdRqE8hKqSGeGReS0TR250TgLr+DO/+BwhgF5bZsg+Uu3wxDLDv6omMY0N?=
 =?us-ascii?Q?NvMRX7v0+5dyxYIF55IwV8uvpPu7WgZPc6WWKZhH+1ca51TeRrPcC81tZGjP?=
 =?us-ascii?Q?Iwu6vLNQCuoy6bjFTh16+3g2M+SfAjpUwVBuiqdYsLrsB9hP5C4hsR1YYigW?=
 =?us-ascii?Q?XAWrDdfwlWzuSkUedsSwIghJNkGip1WlWCD7KiOwreNcYmKG/uYkB2zkd4oS?=
 =?us-ascii?Q?aKMylXLPFoJmAva2KS2TyBknZJuQJigU0IHZIEBeJcnr+HY1c8QiPjSv7bKK?=
 =?us-ascii?Q?pVfvBoLQtYabOj3dWqaqmm/3x3UVE9AtHh7Do1MU3XsuSCfH5brEHIoytvLu?=
 =?us-ascii?Q?wciG0ljKJU6cDlv68R4yhURNJlh75GSIYUkmIdDTlQmf/IjO/KYIrBl9rPRL?=
 =?us-ascii?Q?jeTqVI7bqXNXP+O3ixNvW92TjMWJQXNK5+/ju9p+9d2ciuPt4Uu0a7t9JaFK?=
 =?us-ascii?Q?3/rzpiiQ+qtvu7ojOTbY5aPX/SA2+D88Cqmac/p+HKUFvf/b2693vQJ/shQr?=
 =?us-ascii?Q?hxJjy42QGpJfllK/DsTMOXNnuCfvO2sSfvuQfNzfrUxdksopb2rY1j5v0qu8?=
 =?us-ascii?Q?fD9vnpwkE7t0VfR6xGYQavmQwfpzk9R5OrtEeEl+a2KlfreDmr4Cz/rcQe4/?=
 =?us-ascii?Q?uuwmynTznh+/JA12QnH7lDTUF5EuByA2672LKHkhhdOelG44DMzEKAZLSeH9?=
 =?us-ascii?Q?It0GeJgDeA=3D=3D?=
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
X-OriginatorOrg: citrix.com
X-MS-Exchange-CrossTenant-AuthAs: Internal
X-MS-Exchange-CrossTenant-AuthSource: SA6PR03MB7760.namprd03.prod.outlook.com
X-MS-Exchange-CrossTenant-Network-Message-Id: c0058b20-596f-45d9-a159-08deb0f8a44a
X-MS-Exchange-CrossTenant-originalarrivaltime: 13 May 2026 14:05:08.7798
 (UTC)
X-MS-Exchange-CrossTenant-fromentityheader: Hosted
X-MS-Exchange-CrossTenant-id: 335836de-42ef-43a2-b145-348c2ee9ca5b
X-MS-Exchange-CrossTenant-mailboxtype: HOSTED
X-MS-Exchange-CrossTenant-userprincipalname: d5RFPxkhgnn24jX2cCVdy/rKXOSe2udcAgn0BCRQtegXS27kvF41k1kGguAvbJ3FavssZEikL1GICUZxH2o1fA==
X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA2PR03MB5723
X-purgate-ID: tlsNG-c1860d/1778681112-C4E78DB1-D188237C/0/0
X-purgate-type: clean
X-purgate-size: 33421

Hi Tu,

I'm having an issue with this patch
During a VM start, its possible for a single system thread to acquire the l=
ock exclusively,
and while its locked, a DPC can then attempt to acquire the lock in shared =
mode, resulting
in a deadlock (if AcquireMrswLockShared is called) or spin (if SpinAcquireM=
rswLockShared
is called).

0: kd> k
 # Child-SP          RetAddr               Call Site
00 fffff805`49b48aa8 fffff805`b66b2b2c     nt!DbgBreakPointWithStatus
01 fffff805`49b48ab0 fffff805`b66b0ada     nt!KeAccumulateTicks+0x70c
02 fffff805`49b48b20 fffff805`b66b0833     nt!KiUpdateRunTime+0xd6
03 fffff805`49b48c70 fffff805`b66aed45     nt!KiUpdateTime+0x473
04 fffff805`49b48e20 fffff805`b66ae35d     nt!KeClockInterruptNotify+0x195
05 fffff805`49b48f50 fffff805`b6a7520e     nt!KiCallInterruptServiceRoutine=
+0x2ed
06 fffff805`49b48fb0 fffff805`b6a75a1c     nt!KiInterruptSubDispatchNoLockN=
oEtw+0x4e
07 fffff805`49b412b0 fffff805`b66d6616     nt!KiInterruptDispatchNoLockNoEt=
w+0x3c
08 fffff805`49b41448 fffff805`4c1d6689     nt!ExfAcquireRundownProtection+0=
x6
09 (Inline Function) --------`--------     xenvif!__MrswRundownAcquire+0x9 =
[src\xenvif\mrsw.h @ 84]
0a (Inline Function) --------`--------     xenvif!__SpinAcquireMrswLockShar=
ed+0x9 [src\xenvif\mrsw.h @ 283]
0b fffff805`49b41450 fffff805`4c4a5dd0     xenvif!VifReceiverReturnPacket+0=
x29 [src\xenvif\vif.c @ 537]
0c (Inline Function) --------`--------     xennet!__ReceiverReturnNetBuffer=
Lists+0x54 [src\xennet\receiver.c @ 213]
0d (Inline Function) --------`--------     xennet!ReceiverReturnNetBufferLi=
sts+0x54 [src\xennet\receiver.c @ 535]
0e fffff805`49b414a0 fffff805`4ac84661     xennet!MiniportReturnNetBufferLi=
sts+0x70 [src\xennet\miniport.c @ 208]
0f fffff805`49b414d0 fffff805`4b341824     ndis!NdisFReturnNetBufferLists+0=
x411
10 fffff805`49b415a0 fffff805`4b34759a     wfplwfs!LwfLowerReturnNetBufferL=
ists+0x84
11 fffff805`49b415f0 fffff805`4b347afa     wfplwfs!L2NdisReceiveNetBufferLi=
stsComplete+0x4e
12 fffff805`49b41620 fffff805`4ac8b628     wfplwfs!LwfLowerRecvNetBufferLis=
ts+0x20a
13 fffff805`49b416e0 fffff805`4c4a62d4     ndis!NdisMIndicateReceiveNetBuff=
erLists+0xa78
14 (Inline Function) --------`--------     xennet!__IndicateReceiveNetBuffe=
rLists+0x41 [src\xennet\receiver.c @ 353]
15 (Inline Function) --------`--------     xennet!__ReceiverPushPackets+0xa=
a [src\xennet\receiver.c @ 422]
16 fffff805`49b41900 fffff805`4c4a1147     xennet!ReceiverQueuePacket+0x1c4=
 [src\xennet\receiver.c @ 603]
17 fffff805`49b41980 fffff805`4c1c3cea     xennet!AdapterVifCallback+0x77 [=
src\xennet\adapter.c @ 237]
18 (Inline Function) --------`--------     xenvif!VifReceiverQueuePacket+0x=
90 [src\xenvif\vif.c @ 1244]
19 (Inline Function) --------`--------     xenvif!__ReceiverRingSwizzle+0x6=
f1 [src\xenvif\receiver.c @ 1541]
1a fffff805`49b41a00 fffff805`b665993e     xenvif!ReceiverRingQueueDpc+0x71=
a [src\xenvif\receiver.c @ 1637]
1b fffff805`49b41ad0 fffff805`b6604f1b     nt!KiExecuteAllDpcs+0x67e
1c fffff805`49b41d20 fffff805`b6a7ae15     nt!KiRetireDpcList+0x36b
1d fffff805`49b41fb0 fffff805`b6a7adbf     nt!KxSwapStacksAndRetireDpcList+=
0x5
1e ffffdf04`854cf2f0 fffff805`b66ed1d5     nt!KiPlatformSwapStacksAndCallRe=
turn
1f ffffdf04`854cf300 fffff805`b6a7a24f     nt!KiDispatchInterrupt+0x65
20 ffffdf04`854cf330 fffff805`b6608670     nt!KiDpcInterrupt+0x39f
21 ffffdf04`854cf4c0 fffff805`4c1d5991     nt!KeReleaseSpinLock+0x30
22 (Inline Function) --------`--------     xenvif!FrontendSetState+0x1b4 [s=
rc\xenvif\frontend.c @ 2797]
23 ffffdf04`854cf4f0 fffff805`4c4a5c83     xenvif!VifEnable+0x241 [src\xenv=
if\vif.c @ 176]
24 (Inline Function) --------`--------     xennet!AdapterEnable+0x64 [src\x=
ennet\adapter.c @ 1934]
25 ffffdf04`854cf550 fffff805`4adceb91     xennet!MiniportRestart+0x73 [src=
\xennet\miniport.c @ 143]
26 ffffdf04`854cf580 fffff805`4ade13d1     ndis!ndisMInvokeRestart+0x51
27 ffffdf04`854cf5d0 fffff805`4adcea65     ndis!ndisMRestartMiniportInner+0=
x141
28 ffffdf04`854cf660 fffff805`4adbf26c     ndis!ndisMRestartMiniport+0x65
29 ffffdf04`854cf750 fffff805`4adbb4fb     ndis!Ndis::BindEngine::Iterate+0=
x7dc
2a ffffdf04`854cf910 fffff805`4adbac8a     ndis!Ndis::BindEngine::UpdateBin=
dings+0xab
2b ffffdf04`854cf9c0 fffff805`4add1771     ndis!Ndis::BindEngine::UpdateBin=
dingsWorkItem+0x5a
2c ffffdf04`854cfa10 fffff805`b6709e32     ndis!KWorkItemBase<Ndis::BindEng=
ine,KWorkItem<Ndis::BindEngine> >::CallbackThunk+0x11
2d ffffdf04`854cfa40 fffff805`b685904a     nt!ExpWorkerThread+0x1b2
2e ffffdf04`854cfbf0 fffff805`b6a741c4     nt!PspSystemThreadStartup+0x5a
2f ffffdf04`854cfc40 00000000`00000000     nt!KiStartSystemThread+0x34

This seems to be a race condition, which depends on the ReceiverRingQueueDp=
c getting
executed when FrontendSetState drops the spinlock

Owen

________________________________________
From: Tu Dinh <ngoc-tu.dinh@vates.tech>
Sent: 16 April 2026 12:10 PM
To: win-pv-devel@lists.xenproject.org
Cc: Tu Dinh; Owen Smith
Subject: [PATCH 4/5] Implement rundown-based MRSW lock

The current MRSW lock has a few downsides:
* Large size (have to store a 1KB holder list)
* Long fast-path acquire (~1KB of code) due to having to scan the holder
  list every acquire
* Limited to 64 holders
* Multiple IRQL operations per acquire
* Always raises the critical section to DISPATCH_LEVEL

It's currently only used as the cleanup lock for the VIF interface, so
replace it with something simpler.

Implement a read-write lock with the following properties:
* The reader section is protected by an EX_RUNDOWN_REF.
* Writer/cleanup section is implemented by running down the reference
  within a guarded mutex.
* It offers 3 read acquire flavors: try acquire, spin acquire (both of
  which can be used from DISPATCH_LEVEL) and sleeping acquire (using the
  guarded mutex).
* It makes the downgrade call explicit instead of overloading it via
  ReleaseMrswLockExclusive.
* Finally, the lock supports cache-aware mode, where EX_RUNDOWN_REF is
  replaced with EX_RUNDOWN_REF_CACHE_AWARE using the corresponding
  macros.

As the changes are only internal to vif.c, the VIF version doesn't need
to be increased.

Signed-off-by: Tu Dinh <ngoc-tu.dinh@vates.tech>
---
 src/xenvif/mrsw.h | 530 +++++++++++++++++++++++++---------------------
 src/xenvif/vif.c  |  65 +++---
 2 files changed, 327 insertions(+), 268 deletions(-)

diff --git a/src/xenvif/mrsw.h b/src/xenvif/mrsw.h
index e1ff056..8bfa441 100644
--- a/src/xenvif/mrsw.h
+++ b/src/xenvif/mrsw.h
@@ -1,289 +1,347 @@
 /* Copyright (c) Xen Project.
  * Copyright (c) Cloud Software Group, Inc.
+ * Copyright (c) Vates.
  * All rights reserved.
- *
- * Redistribution and use in source and binary forms,
- * with or without modification, are permitted provided
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
  * that the following conditions are met:
- *
- * *   Redistributions of source code must retain the above
- *     copyright notice, this list of conditions and the
+ *
+ * *   Redistributions of source code must retain the above
+ *     copyright notice, this list of conditions and the
  *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the
- *     following disclaimer in the documentation and/or other
+ * *   Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer in the documentation and/or other
  *     materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */

-#ifndef _XENVIF_MRSW_H
-#define _XENVIF_MRSW_H
+#ifndef _MRSW_H
+#define _MRSW_H

-#include <ntddk.h>
+#include <wdm.h>

 #include "assert.h"
 #include "util.h"

-#pragma warning(disable:4127)   // conditional expression is constant
-
-typedef struct _XENVIF_MRSW_HOLDER {
-    PKTHREAD    Thread;
-    LONG        Level;
-} XENVIF_MRSW_HOLDER, *PXENVIF_MRSW_HOLDER;
-
-typedef struct _XENVIF_MRSW_LOCK {
-    volatile LONG64 Mask;
-    XENVIF_MRSW_HOLDER     Holder[64];
-    KEVENT          Event;
-} XENVIF_MRSW_LOCK, *PXENVIF_MRSW_LOCK;
-
-C_ASSERT(RTL_FIELD_SIZE(XENVIF_MRSW_LOCK, Holder) =3D=3D RTL_FIELD_SIZE(XE=
NVIF_MRSW_LOCK, Mask) * 8 * sizeof (XENVIF_MRSW_HOLDER));
-
-#define XENVIF_MRSW_EXCLUSIVE_SLOT  0
-
-static FORCEINLINE VOID
-InitializeMrswLock(
-    IN  PXENVIF_MRSW_LOCK   Lock
+#pragma warning(push)
+#pragma warning(disable:4201) // nameless struct/union
+struct _MRSW_LOCK {
+    KGUARDED_MUTEX                  Mutex;
+    union {
+        EX_RUNDOWN_REF              Rundown;
+        PEX_RUNDOWN_REF_CACHE_AWARE RundownCacheAware;
+    };
+};
+#pragma warning(pop)
+
+typedef struct _MRSW_LOCK   MRSW_LOCK, *PMRSW_LOCK;
+typedef struct _MRSW_LOCK   MRSW_CACHE_AWARE_LOCK, *PMRSW_CACHE_AWARE_LOCK=
;
+
+static FORCEINLINE NTSTATUS
+__MrswRundownInitialize(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware,
+    _In_ ULONG                  Tag
     )
 {
-    LONG                    Slot;
-
-    RtlZeroMemory(Lock, sizeof (XENVIF_MRSW_LOCK));
-
-    for (Slot =3D 0; Slot < (LONG) sizeof (Lock->Mask) * 8; Slot++)
-        Lock->Holder[Slot].Level =3D -1;
+    if (CacheAware) {
+        Lock->RundownCacheAware =3D ExAllocateCacheAwareRundownProtection(=
NonPagedPoolNx,
+                                                                        Ta=
g);
+        if (!Lock->RundownCacheAware)
+            return STATUS_NO_MEMORY;
+    } else {
+        ExInitializeRundownProtection(&Lock->Rundown);
+    }

-    KeInitializeEvent(&Lock->Event, NotificationEvent, FALSE);
+    return STATUS_SUCCESS;
 }

 static FORCEINLINE BOOLEAN
-__ClaimExclusive(
-    IN  PXENVIF_MRSW_LOCK   Lock
+__MrswRundownAcquire(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware
     )
 {
-    LONG64                  Old;
-    LONG64                  New;
-
-    Old =3D 0;
-    New =3D 1ll << XENVIF_MRSW_EXCLUSIVE_SLOT;
-
-    return (InterlockedCompareExchange64(&Lock->Mask, New, Old) =3D=3D Old=
) ? TRUE : FALSE;
+    if (CacheAware)
+        return ExAcquireRundownProtectionCacheAware(Lock->RundownCacheAwar=
e);
+    else
+        return ExAcquireRundownProtection(&Lock->Rundown);
 }

-static FORCEINLINE KIRQL
-__drv_maxIRQL(APC_LEVEL)
-__drv_raisesIRQL(DISPATCH_LEVEL)
-__drv_savesIRQL
-__AcquireMrswLockExclusive(
-    IN  PXENVIF_MRSW_LOCK   Lock
+static FORCEINLINE VOID
+__MrswRundownRelease(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware
     )
 {
-    KIRQL                   Irql;
-    LONG                    Slot;
-    PKTHREAD                Self;
-    PXENVIF_MRSW_HOLDER     Holder;
-
-    ASSERT3U(KeGetCurrentIrql(), <, DISPATCH_LEVEL);
-    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
-
-    Self =3D KeGetCurrentThread();
-
-    // Make sure we do not already hold the lock
-    for (Slot =3D 0; Slot < (LONG) sizeof (Lock->Mask) * 8; Slot++)
-        ASSERT(Lock->Holder[Slot].Thread !=3D Self);
-
-    for (;;) {
-        if (__ClaimExclusive(Lock))
-            break;
-
-        KeLowerIrql(Irql);
-
-        (VOID) KeWaitForSingleObject(&Lock->Event,
-                                     Executive,
-                                     KernelMode,
-                                     FALSE,
-                                     NULL);
-        KeClearEvent(&Lock->Event);
-
-        KeRaiseIrql(DISPATCH_LEVEL, &Irql);
-    }
-
-    Holder =3D &Lock->Holder[XENVIF_MRSW_EXCLUSIVE_SLOT];
-
-    ASSERT3P(Holder->Thread, =3D=3D, NULL);
-    Holder->Thread =3D Self;
-    Holder->Level =3D 0;
-
-    return Irql;
+    if (CacheAware)
+        ExReleaseRundownProtectionCacheAware(Lock->RundownCacheAware);
+    else
+        ExReleaseRundownProtection(&Lock->Rundown);
 }

-#define AcquireMrswLockExclusive(_Lock, _Irql)              \
-        do {                                                \
-            *(_Irql) =3D __AcquireMrswLockExclusive(_Lock);   \
-        } while (FALSE)
-
 static FORCEINLINE VOID
-__drv_maxIRQL(DISPATCH_LEVEL)
-__drv_requiresIRQL(DISPATCH_LEVEL)
-ReleaseMrswLockExclusive(
-    IN  PXENVIF_MRSW_LOCK           Lock,
-    IN  __drv_restoresIRQL KIRQL    Irql,
-    IN  BOOLEAN                     Shared
+__MrswRundownWait(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware
     )
 {
-    LONG                            Slot;
-    PKTHREAD                        Self;
-    LONG64                          Old;
-    LONG64                          New;
-    PXENVIF_MRSW_HOLDER             Holder;
-
-    ASSERT3U(KeGetCurrentIrql(), =3D=3D, DISPATCH_LEVEL);
-
-    Slot =3D XENVIF_MRSW_EXCLUSIVE_SLOT + 1; // Choose any slot other than=
 the exclusive slot
-
-    Old =3D 1ll << XENVIF_MRSW_EXCLUSIVE_SLOT;
-    New =3D (Shared) ? (1ll << Slot) : 0;
-
-    Old =3D InterlockedCompareExchange64(&Lock->Mask, New, Old);
-    ASSERT3U(Old, =3D=3D , 1ll << XENVIF_MRSW_EXCLUSIVE_SLOT);
-
-    Self =3D KeGetCurrentThread();
-
-    ASSERT3P(Lock->Holder[XENVIF_MRSW_EXCLUSIVE_SLOT].Thread, =3D=3D, Self=
);
-
-    // If we are leaving the lock held shared then we need to transfer
-    // our identity information into the hew slot.
-    if (Shared)
-        Lock->Holder[Slot] =3D Lock->Holder[XENVIF_MRSW_EXCLUSIVE_SLOT];
-
-    Holder =3D &Lock->Holder[XENVIF_MRSW_EXCLUSIVE_SLOT];
-
-    Holder->Thread =3D NULL;
-    Holder->Level =3D -1;
-
-    KeLowerIrql(Irql);
+    if (CacheAware)
+        ExWaitForRundownProtectionReleaseCacheAware(Lock->RundownCacheAwar=
e);
+    else
+        ExWaitForRundownProtectionRelease(&Lock->Rundown);
 }

-static FORCEINLINE LONG
-__ClaimShared(
-    IN  PXENVIF_MRSW_LOCK   Lock
+static FORCEINLINE VOID
+__MrswRundownCompleted(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware
     )
 {
-    LONG                    Slot;
-    LONG64                  Old;
-    LONG64                  New;
-
-    // Make sure the exclusive bit is set so that we don't find it
-    Old =3D Lock->Mask | (1ll << XENVIF_MRSW_EXCLUSIVE_SLOT);
-
-    Slot =3D __ffu((ULONG64)Old);
-    ASSERT(Slot >=3D 0);
-    ASSERT3U(Slot, !=3D , XENVIF_MRSW_EXCLUSIVE_SLOT);
+    if (CacheAware)
+        ExRundownCompletedCacheAware(Lock->RundownCacheAware);
+    else
+        ExRundownCompleted(&Lock->Rundown);
+}

-    Old &=3D ~(1ll << XENVIF_MRSW_EXCLUSIVE_SLOT);
-    New =3D Old | (1ll << Slot);
+static FORCEINLINE VOID
+__MrswRundownReInitialize(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware
+    )
+{
+    if (CacheAware)
+        ExReInitializeRundownProtectionCacheAware(Lock->RundownCacheAware)=
;
+    else
+        ExReInitializeRundownProtection(&Lock->Rundown);
+}

-    return (InterlockedCompareExchange64(&Lock->Mask, New, Old) =3D=3D Old=
) ? Slot : -1;
+static FORCEINLINE VOID
+__MrswRundownTeardown(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware
+    )
+{
+    if (CacheAware)
+        ExFreeCacheAwareRundownProtection(Lock->RundownCacheAware);
+    else
+        RtlZeroMemory(&Lock->Rundown, sizeof(Lock->Rundown));
 }

+_IRQL_requires_min_(PASSIVE_LEVEL)
+_IRQL_requires_max_(APC_LEVEL)
+static FORCEINLINE NTSTATUS
+__InitializeMrswLock(
+    _Out_ struct _MRSW_LOCK     *Lock,
+    _In_ BOOLEAN                CacheAware,
+    _In_ ULONG                  Tag
+    )
+{
+    KeInitializeGuardedMutex(&Lock->Mutex);
+    return __MrswRundownInitialize(Lock, CacheAware, Tag);
+}
+#define InitializeMrswLock(Lock, Tag) \
+    __InitializeMrswLock(Lock, FALSE, Tag)
+#define InitializeMrswCacheAwareLock(Lock, Tag) \
+    __InitializeMrswLock(Lock, TRUE, Tag)
+
+_Requires_lock_not_held_(*Lock)
+_IRQL_requires_min_(PASSIVE_LEVEL)
+_IRQL_requires_max_(APC_LEVEL)
+static FORCEINLINE VOID
+__TeardownMrswLock(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware
+    )
+{
+#if DBG
+    BUG_ON(!KeTryToAcquireGuardedMutex(&Lock->Mutex));
+    BUG_ON(!__MrswRundownAcquire(Lock, CacheAware));
+    KeReleaseGuardedMutex(&Lock->Mutex);
+    __MrswRundownRelease(Lock, CacheAware);
+#endif
+
+    __MrswRundownTeardown(Lock, CacheAware);
+    RtlZeroMemory(Lock, sizeof(MRSW_LOCK));
+}
+#define TeardownMrswLock(Lock) \
+    __TeardownMrswLock(Lock, FALSE)
+#define TeardownMrswCacheAwareLock(Lock) \
+    __TeardownMrswLock(Lock, TRUE)
+
+_Acquires_lock_(_Global_critical_region_)
+_Requires_lock_not_held_(*Lock)
+_Acquires_exclusive_lock_(*Lock)
+_IRQL_requires_min_(PASSIVE_LEVEL)
+_IRQL_requires_max_(APC_LEVEL)
 static FORCEINLINE VOID
-AcquireMrswLockShared(
-    IN  PXENVIF_MRSW_LOCK   Lock
+__AcquireMrswLockExclusive(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware
     )
 {
-    KIRQL                   Irql;
-    LONG                    Level;
-    LONG                    Slot;
-    PKTHREAD                Self;
-    PXENVIF_MRSW_HOLDER     Holder;
+    ASSERT3U(KeGetCurrentIrql(), <=3D, APC_LEVEL);

+    KeAcquireGuardedMutex(&Lock->Mutex);
+    __MrswRundownWait(Lock, CacheAware);
+    __MrswRundownCompleted(Lock, CacheAware);
+}
+#define AcquireMrswLockExclusive(Lock) \
+    __AcquireMrswLockExclusive(Lock, FALSE)
+#define AcquireMrswCacheAwareLockExclusive(Lock) \
+    __AcquireMrswLockExclusive(Lock, TRUE)
+
+_Releases_lock_(_Global_critical_region_)
+_Requires_exclusive_lock_held_(*Lock)
+_Releases_exclusive_lock_(*Lock)
+_IRQL_requires_min_(PASSIVE_LEVEL)
+_IRQL_requires_max_(APC_LEVEL)
+static FORCEINLINE VOID
+__ReleaseMrswLockExclusive(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware
+    )
+{
+    __MrswRundownReInitialize(Lock, CacheAware);
+    KeReleaseGuardedMutex(&Lock->Mutex);
+}
+#define ReleaseMrswLockExclusive(Lock) \
+    __ReleaseMrswLockExclusive(Lock, FALSE)
+#define ReleaseMrswCacheAwareLockExclusive(Lock) \
+    __ReleaseMrswLockExclusive(Lock, TRUE)
+
+_Releases_lock_(_Global_critical_region_)
+_Requires_exclusive_lock_held_(*Lock)
+_Releases_exclusive_lock_(*Lock)
+_Acquires_shared_lock_(*Lock)
+_IRQL_requires_min_(PASSIVE_LEVEL)
+_IRQL_requires_max_(APC_LEVEL)
+static FORCEINLINE VOID
+__DowngradeMrswLockExclusive(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware
+    )
+{
+    __MrswRundownReInitialize(Lock, CacheAware);
+    BUG_ON(!__MrswRundownAcquire(Lock, CacheAware));
+    KeReleaseGuardedMutex(&Lock->Mutex);
+}
+#define DowngradeMrswLockExclusive(Lock) \
+    __DowngradeMrswLockExclusive(Lock, FALSE)
+#define DowngradeMrswCacheAwareLockExclusive(Lock) \
+    __DowngradeMrswLockExclusive(Lock, TRUE)
+
+_When_(return, _Acquires_shared_lock_(*Lock))
+_IRQL_requires_min_(PASSIVE_LEVEL)
+_IRQL_requires_max_(DISPATCH_LEVEL)
+static FORCEINLINE BOOLEAN
+__TryAcquireMrswLockShared(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware
+    )
+{
+#if DBG
     ASSERT3U(KeGetCurrentIrql(), <=3D, DISPATCH_LEVEL);
-    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
-
-    Self =3D KeGetCurrentThread();
-
-    // Do we already hold the lock? If so, get the nesting level
-    Level =3D -1;
-    for (Slot =3D 0; Slot < (LONG) sizeof (Lock->Mask) * 8; Slot++) {
-        if (Lock->Holder[Slot].Thread =3D=3D Self && Lock->Holder[Slot].Le=
vel > Level)
-            Level =3D Lock->Holder[Slot].Level;
-    }
-    Level++;
+#endif

-    for (;;) {
-        Slot =3D __ClaimShared(Lock);
-        if (Slot >=3D 0)
-            break;
-
-        _mm_pause();
-    }
-
-    Holder =3D &Lock->Holder[Slot];
-
-    Holder->Thread =3D Self;
-    Holder->Level =3D Level;
-
-    KeLowerIrql(Irql);
+    return __MrswRundownAcquire(Lock, CacheAware);
 }
-
+#define TryAcquireMrswLockShared(Lock) \
+    __TryAcquireMrswLockShared(Lock, FALSE)
+#define TryAcquireMrswCacheAwareLockShared(Lock) \
+    __TryAcquireMrswLockShared(Lock, TRUE)
+
+_Acquires_shared_lock_(*Lock)
+_IRQL_requires_min_(PASSIVE_LEVEL)
+_IRQL_requires_max_(DISPATCH_LEVEL)
 static FORCEINLINE VOID
-ReleaseMrswLockShared(
-    IN  PXENVIF_MRSW_LOCK   Lock
+__SpinAcquireMrswLockShared(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware
     )
 {
-    KIRQL                   Irql;
-    PKTHREAD                Self;
-    LONG                    Level;
-    LONG                    Deepest;
-    LONG                    Slot;
-    LONG64                  Old;
-    LONG64                  New;
-    PXENVIF_MRSW_HOLDER     Holder;
-
+#if DBG
     ASSERT3U(KeGetCurrentIrql(), <=3D, DISPATCH_LEVEL);
-    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
-
-    Self =3D KeGetCurrentThread();
-
-    Level =3D -1;
-    Deepest =3D -1;
-    for (Slot =3D 0; Slot < (LONG) sizeof (Lock->Mask) * 8; Slot++) {
-        if (Lock->Holder[Slot].Thread =3D=3D Self && Lock->Holder[Slot].Le=
vel > Level) {
-            Level =3D Lock->Holder[Slot].Level;
-            Deepest =3D Slot;
-        }
-    }
-    ASSERT(Level >=3D 0);
-
-    Slot =3D Deepest;
-    ASSERT3U(Slot, !=3D, XENVIF_MRSW_EXCLUSIVE_SLOT);
-
-    Holder =3D &Lock->Holder[Slot];
+#endif

-    Holder->Thread =3D NULL;
-    Holder->Level =3D -1;
-
-    do {
-        Old =3D Lock->Mask;
-        New =3D Old & ~(1ll << Slot);
-    } while (InterlockedCompareExchange64(&Lock->Mask, New, Old) !=3D Old)=
;
-
-    KeSetEvent(&Lock->Event, IO_NO_INCREMENT, FALSE);
-    KeLowerIrql(Irql);
+    while (!__MrswRundownAcquire(Lock, CacheAware))
+        YieldProcessor();
+}
+#define SpinAcquireMrswLockShared(Lock) \
+    __SpinAcquireMrswLockShared(Lock, FALSE)
+#define SpinAcquireMrswCacheAwareLockShared(Lock) \
+    __SpinAcquireMrswLockShared(Lock, TRUE)
+
+/*
+ * Unlike SpinAcquireMrswLockShared, AcquireMrswLockShared will
+ * sleep when the lock acquisition fails. Thus it cannot be used at
+ * DISPATCH_LEVEL.
+ */
+_Acquires_shared_lock_(*Lock)
+_IRQL_requires_min_(PASSIVE_LEVEL)
+_IRQL_requires_max_(APC_LEVEL)
+static FORCEINLINE VOID
+__AcquireMrswLockShared(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware
+    )
+{
+#if DBG
+    ASSERT3U(KeGetCurrentIrql(), <=3D, APC_LEVEL);
+#endif
+
+    if (__MrswRundownAcquire(Lock, CacheAware))
+        return;
+
+    /*
+     * Don't bother retrying, since it's most likely that another writer s=
ection
+     * is cleaning up and not ending any time soon. Just jump straight int=
o
+     * sleep.
+     */
+    KeAcquireGuardedMutex(&Lock->Mutex);
+    /*
+     * Since we have the write mutex, we know that there are no writers. S=
o this
+     * acquire must succeed.
+     */
+    BUG_ON(!__MrswRundownAcquire(Lock, CacheAware));
+    KeReleaseGuardedMutex(&Lock->Mutex);
+}
+#define AcquireMrswLockShared(Lock) \
+    __AcquireMrswLockShared(Lock, FALSE)
+#define AcquireMrswCacheAwareLockShared(Lock) \
+    __AcquireMrswLockShared(Lock, TRUE)
+
+_Requires_shared_lock_held_(*Lock)
+_Releases_shared_lock_(*Lock)
+_IRQL_requires_min_(PASSIVE_LEVEL)
+_IRQL_requires_max_(DISPATCH_LEVEL)
+static FORCEINLINE VOID
+__ReleaseMrswLockShared(
+    _Inout_ struct _MRSW_LOCK   *Lock,
+    _In_ BOOLEAN                CacheAware
+    )
+{
+    __MrswRundownRelease(Lock, CacheAware);
 }
+#define ReleaseMrswLockShared(Lock) \
+    __ReleaseMrswLockShared(Lock, FALSE)
+#define ReleaseMrswCacheAwareLockShared(Lock) \
+    __ReleaseMrswLockShared(Lock, TRUE)

-#endif  // _XENVIF_MRSW_H
+#endif  // _MRSW_H
diff --git a/src/xenvif/vif.c b/src/xenvif/vif.c
index 6f468ee..cb4cf84 100644
--- a/src/xenvif/vif.c
+++ b/src/xenvif/vif.c
@@ -47,7 +47,7 @@

 struct _XENVIF_VIF_CONTEXT {
     PXENVIF_PDO                 Pdo;
-    XENVIF_MRSW_LOCK            Lock;
+    MRSW_LOCK                   Lock;
     LONG                        References;
     PXENVIF_FRONTEND            Frontend;
     BOOLEAN                     Enabled;
@@ -150,13 +150,12 @@ VifEnable(
     )
 {
     PXENVIF_VIF_CONTEXT     Context =3D Interface->Context;
-    KIRQL                   Irql;
     BOOLEAN                 Exclusive;
     NTSTATUS                status;

     Trace("=3D=3D=3D=3D>\n");

-    AcquireMrswLockExclusive(&Context->Lock, &Irql);
+    AcquireMrswLockExclusive(&Context->Lock);
     Exclusive =3D TRUE;

     if (Context->Enabled)
@@ -188,7 +187,7 @@ VifEnable(

 done:
     ASSERT(Exclusive);
-    ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
+    ReleaseMrswLockExclusive(&Context->Lock);

     Trace("<=3D=3D=3D=3D\n");

@@ -199,7 +198,7 @@ fail3:

     (VOID) FrontendSetState(Context->Frontend, FRONTEND_CONNECTED);

-    ReleaseMrswLockExclusive(&Context->Lock, Irql, TRUE);
+    DowngradeMrswLockExclusive(&Context->Lock);
     Exclusive =3D FALSE;

     ReceiverWaitForPackets(FrontendGetReceiver(Context->Frontend));
@@ -234,7 +233,7 @@ fail1:
     Context->Callback =3D NULL;

     if (Exclusive)
-        ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
+        ReleaseMrswLockExclusive(&Context->Lock);
     else
         ReleaseMrswLockShared(&Context->Lock);

@@ -389,17 +388,16 @@ VifEnableVersion9(
     )
 {
     PXENVIF_VIF_CONTEXT             Context =3D Interface->Context;
-    KIRQL                           Irql;
     NTSTATUS                        status;

     Trace("=3D=3D=3D=3D>\n");

-    AcquireMrswLockExclusive(&Context->Lock, &Irql);
+    AcquireMrswLockExclusive(&Context->Lock);

     Context->CallbackVersion9 =3D Callback;
     Context->ArgumentVersion9 =3D Argument;

-    ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
+    ReleaseMrswLockExclusive(&Context->Lock);

     status =3D VifEnable(Interface, VifCallbackVersion9, Context);

@@ -416,17 +414,16 @@ VifEnableVersion8(
     )
 {
     PXENVIF_VIF_CONTEXT             Context =3D Interface->Context;
-    KIRQL                           Irql;
     NTSTATUS                        status;

     Trace("=3D=3D=3D=3D>\n");

-    AcquireMrswLockExclusive(&Context->Lock, &Irql);
+    AcquireMrswLockExclusive(&Context->Lock);

     Context->CallbackVersion8 =3D Callback;
     Context->ArgumentVersion8 =3D Argument;

-    ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
+    ReleaseMrswLockExclusive(&Context->Lock);

     status =3D VifEnableVersion9(Interface, VifCallbackVersion8, Context);

@@ -441,14 +438,13 @@ VifDisable(
     )
 {
     PXENVIF_VIF_CONTEXT Context =3D Interface->Context;
-    KIRQL               Irql;

     Trace("=3D=3D=3D=3D>\n");

-    AcquireMrswLockExclusive(&Context->Lock, &Irql);
+    AcquireMrswLockExclusive(&Context->Lock);

     if (!Context->Enabled) {
-        ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
+        ReleaseMrswLockExclusive(&Context->Lock);
         goto done;
     }

@@ -463,7 +459,7 @@ VifDisable(

     (VOID) FrontendSetState(Context->Frontend, FRONTEND_CONNECTED);

-    ReleaseMrswLockExclusive(&Context->Lock, Irql, TRUE);
+    DowngradeMrswLockExclusive(&Context->Lock);

     ReceiverWaitForPackets(FrontendGetReceiver(Context->Frontend));
     TransmitterAbortPackets(FrontendGetTransmitter(Context->Frontend));
@@ -511,7 +507,7 @@ VifQueryStatistic(
     status =3D STATUS_INVALID_PARAMETER;
     if (Index >=3D XENVIF_VIF_STATISTIC_COUNT)
         goto done;
-
+
     AcquireMrswLockShared(&Context->Lock);

     FrontendQueryStatistic(Context->Frontend, Index, Value);
@@ -567,7 +563,8 @@ VifReceiverReturnPacket(
 {
     PXENVIF_VIF_CONTEXT Context =3D Interface->Context;

-    AcquireMrswLockShared(&Context->Lock);
+    // Called from MINIPORT_RETURN_NET_BUFFER_LISTS
+    SpinAcquireMrswLockShared(&Context->Lock);

     ReceiverReturnPacket(FrontendGetReceiver(Context->Frontend),
                          Cookie);
@@ -592,9 +589,10 @@ VifTransmitterQueuePacket(
     PXENVIF_VIF_CONTEXT             Context =3D Interface->Context;
     NTSTATUS                        status;

-    AcquireMrswLockShared(&Context->Lock);
-
     status =3D STATUS_UNSUCCESSFUL;
+    if (!TryAcquireMrswLockShared(&Context->Lock))
+        return status;
+
     if (!Context->Enabled)
         goto done;

@@ -948,9 +946,8 @@ VifAcquire(
     )
 {
     PXENVIF_VIF_CONTEXT     Context =3D Interface->Context;
-    KIRQL                   Irql;

-    AcquireMrswLockExclusive(&Context->Lock, &Irql);
+    AcquireMrswLockExclusive(&Context->Lock);

     if (Context->References++ !=3D 0)
         goto done;
@@ -963,7 +960,7 @@ VifAcquire(
     Trace("<=3D=3D=3D=3D\n");

 done:
-    ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
+    ReleaseMrswLockExclusive(&Context->Lock);

     return STATUS_SUCCESS;
 }
@@ -974,9 +971,8 @@ VifRelease(
     )
 {
     PXENVIF_VIF_CONTEXT     Context =3D Interface->Context;
-    KIRQL                   Irql;

-    AcquireMrswLockExclusive(&Context->Lock, &Irql);
+    AcquireMrswLockExclusive(&Context->Lock);

     if (--Context->References > 0)
         goto done;
@@ -991,7 +987,7 @@ VifRelease(
     Trace("<=3D=3D=3D=3D\n");

 done:
-    ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
+    ReleaseMrswLockExclusive(&Context->Lock);
 }

 static struct _XENVIF_VIF_INTERFACE_V8 VifInterfaceVersion8 =3D {
@@ -1100,7 +1096,9 @@ VifInitialize(
     if (*Context =3D=3D NULL)
         goto fail1;

-    InitializeMrswLock(&(*Context)->Lock);
+    status =3D InitializeMrswLock(&(*Context)->Lock, XENVIF_VIF_TAG);
+    if (!NT_SUCCESS(status))
+        goto fail2;

     FdoGetSuspendInterface(PdoGetFdo(Pdo),&(*Context)->SuspendInterface);

@@ -1110,7 +1108,7 @@ VifInitialize(
                           *Context,
                           &(*Context)->MacThread);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;

     (*Context)->Pdo =3D Pdo;

@@ -1118,7 +1116,7 @@ VifInitialize(

     return STATUS_SUCCESS;

-fail2:
+fail3:
     Error("fail3\n");

     RtlZeroMemory(&(*Context)->MacEvent, sizeof (KEVENT));
@@ -1126,7 +1124,10 @@ fail2:
     RtlZeroMemory(&(*Context)->SuspendInterface,
                   sizeof (XENBUS_SUSPEND_INTERFACE));

-    RtlZeroMemory(&(*Context)->Lock, sizeof (XENVIF_MRSW_LOCK));
+    TeardownMrswLock(&(*Context)->Lock);
+
+fail2:
+    Error("fail2\n");

     ASSERT(IsZeroMemory(*Context, sizeof (XENVIF_VIF_CONTEXT)));
     __VifFree(*Context);
@@ -1205,7 +1206,7 @@ VifGetInterface(
     }

     return status;
-}
+}

 VOID
 VifTeardown(
@@ -1228,7 +1229,7 @@ VifTeardown(
     RtlZeroMemory(&Context->SuspendInterface,
                   sizeof (XENBUS_SUSPEND_INTERFACE));

-    RtlZeroMemory(&Context->Lock, sizeof (XENVIF_MRSW_LOCK));
+    TeardownMrswLock(&Context->Lock);

     ASSERT(IsZeroMemory(Context, sizeof (XENVIF_VIF_CONTEXT)));
     __VifFree(Context);
--
2.53.0.windows.2



--
Ngoc Tu Dinh | Vates XCP-ng Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech



From win-pv-devel-bounces@lists.xenproject.org Wed May 13 15:22:55 2026
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 13 May 2026 15:22:55 +0000
Received: from list by lists.xenproject.org with outflank-mailman.1308226.1579756 (Exim 4.92)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1wNBQE-0003dC-Dz; Wed, 13 May 2026 15:22:54 +0000
X-Outflank-Mailman: Message body and most headers restored to incoming version
Received: by outflank-mailman (output) from mailman id 1308226.1579756; Wed, 13 May 2026 15:22:54 +0000
Received: from localhost ([127.0.0.1] helo=lists.xenproject.org)
	by lists.xenproject.org with esmtp (Exim 4.92)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1wNBQE-0003d5-BF; Wed, 13 May 2026 15:22:54 +0000
Received: by outflank-mailman (input) for mailman id 1308226;
 Wed, 13 May 2026 15:22:53 +0000
Received: from mx.expurgate.net ([195.190.135.10])
 by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from
 <prod-mta-13.8631fc262581453bbf619ec5b2062170.19e21eef1e5000f373@swg.vates.tech>)
 id 1wNBQC-0003cz-SR
 for win-pv-devel@lists.xenproject.org; Wed, 13 May 2026 15:22:53 +0000
Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp
 id 1wNBQC-005JCz-93
 for win-pv-devel@lists.xenproject.org; Wed, 13 May 2026 17:22:52 +0200
Received: from [10.42.69.5] (helo=localhost)
 by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from
 <prod-mta-13.8631fc262581453bbf619ec5b2062170.19e21eef1e5000f373@swg.vates.tech>)
 id 6a04973a-bab6-0a2a0a5309dd-0a2a4505bd1c-24
 for <win-pv-devel@lists.xenproject.org>; Wed, 13 May 2026 17:22:52 +0200
Received: from [185.255.28.34] (helo=prod-mta-13.swg-srv.net)
 by tlsNG-c201ff.mxtls.expurgate.net with ESMTPS (eXpurgate 4.56.1)
 (envelope-from
 <prod-mta-13.8631fc262581453bbf619ec5b2062170.19e21eef1e5000f373@swg.vates.tech>)
 id 6a04974b-aaa8-0a2a45050019-b9ff1c22a9fd-3
 for <win-pv-devel@lists.xenproject.org>; Wed, 13 May 2026 17:22:52 +0200
Received: from mail2.vates.fr ([37.26.189.201] mail2.vates.fr)
 (Authenticated sender:
 8631fc262581453bbf619ec5b2062170/smtp/7773de5a-2839-4720-82ee-e06722ae1d3e)
 by prod-mta-13.swg-srv.net (ZoneMTA - prod-mta-13) with ESMTPSA id
 19e21eef1e5000f373.002 for <win-pv-devel@lists.xenproject.org>
 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384);
 Wed, 13 May 2026 15:22:48 +0000
Received: from [37.26.189.201] (mail2.vates.fr [37.26.189.201])
 (Authenticated sender: ngoc-tu.dinh@835de637.internal)
 by mail2.vates.fr (Postfix) with ESMTPSA id 7D9C986424;
 Wed, 13 May 2026 17:22:47 +0200 (CEST)
X-BeenThere: win-pv-devel@lists.xenproject.org
List-Id: Developer list for the Windows PV Drivers subproject
 <win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <https://lists.xenproject.org/mailman/options/win-pv-devel>, 
 <mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <https://lists.xenproject.org/mailman/listinfo/win-pv-devel>, 
 <mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Errors-To: win-pv-devel-bounces@lists.xenproject.org
Precedence: list
Sender: "win-pv-devel" <win-pv-devel-bounces@lists.xenproject.org>
Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=vates.tech header.i="@vates.tech" header.h="From:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:Feedback-ID"
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vates.tech;
 q=dns/txt; s=selector1; bh=v9Wv4ZHpddNx+EKtI0TqGoefHD9yf89+1yR14Ib48cM=;
 h=from:subject:date:message-id:to:cc:mime-version:content-type:feedback-id;
 b=jx3aGg9oc293jbBV80BpQG95OObmBV44Wc7NIXs7nkwDO2uBQBoK7ycxrxvLKDfKxK+unKrJW
 Nl3A1k+gd/ZGOFbOBW2wf3tzIQsxeFBEs5H9lyMPslRWvM1akoGvO2yuB5/LC3P4yxxBM0GtVfw
 TK7iVI6bJ+px/i5parEa8608RA7zj1UO0iHKyjf1gpbUSa7Wpf1w3ES5VcDjop4VcQBjD3ImhvE
 eEok9DOkWaeFP3xUal+6+3OuuzXpqF85QY1OaVvaAONRjtaOCSwJMV9NzUMM2ssCObvjWHCxvTI
 caUVwZcpXWm1kQmjhN2QttkCdC5ccTv30fSRZlrBuNHg==
X-Zone-Loop: 6bdaf70135c2af2ac3c96cb4cc7b0ce0c99058902f43
x-campaign-type: default
x-transaction-id: 079e5128-30e8-4864-aec0-8fcace5ca3c1
x-swg-uid: 01-9d0a74f1-6672-4ffd-a605-f35d6a151e5e
X-Mailer: Sweego
Message-ID:
 <1778685768.8631fc262581453bbf619ec5b2062170.19e21eef1e5000f373@vates.tech>
x-swg-bid: 1778685768.8631fc262581453bbf619ec5b2062170.19e21eef1e5000f373
Feedback-ID: default:8631fc262581453bbf619ec5b2062170:Sweego
x-campaign-id: default
x-client-id: 8631fc262581453bbf619ec5b2062170
X-Originating-IP: [37.26.189.201]
Date: Wed, 13 May 2026 17:22:46 +0200
Subject: Re: [PATCH 4/5] Implement rundown-based MRSW lock
X-Android-Message-ID: <95328a1f-1fe0-4503-9cb4-78be8323f408@email.android.com>
From: Ngoc Tu Dinh <ngoc-tu.dinh@vates.tech>
To: Owen Smith <owen.smith@citrix.com>
Cc: win-pv-devel@lists.xenproject.org
Importance: Normal
X-Priority: 3
X-MSMail-Priority: Normal
MIME-Version: 1.0
X-BM-Disclaimer: Yes
Content-Type: multipart/alternative; boundary="-=Part.bae.fc8657cf149906f8.19e21eeeff1.cc137a118f92ad64=-"
X-Bm-Milter-Handled: 4ffbd6c1-ee69-4e1b-aabd-f977039bd3e2
X-Bm-Transport-Timestamp: 1778685767670
X-purgate-ID: tlsNG-c201ff/1778685772-E00637E3-435BFE07/0/0
X-purgate-type: clean
X-purgate-size: 98187

---=Part.bae.fc8657cf149906f8.19e21eeeff1.cc137a118f92ad64=-
Content-Type: multipart/related;
 boundary="-=Part.baf.bf3f53f3ec167425.19e21eeeff6.b1b31f559e950585=-"

---=Part.baf.bf3f53f3ec167425.19e21eeeff6.b1b31f559e950585=-
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<html>
 <head></head>
 <body>
  <div dir=3D"auto">
   <div dir=3D"auto">
  =
  <div dir=3D"auto">Hi Owen,</div>
    <div dir=3D"auto">
     <br>
    </d=
iv>
    Thanks for the info=2E This must have been caused by the MRSW lock'=
s writer section no longer running at DISPATCH_LEVEL and so caused the writ=
er section to be preempted by a reader DPC=2E&nbsp;
    <div dir=3D"auto">
=
     <br>
    </div>
    <div dir=3D"auto">I'll look for a solution, but I =
wonder if it's possible to make ReceiverReturnPacket fallible/retryable or =
otherwise influence the timing of DPCs=2E</div>
   </div>
   <div>
    <br>=

    <div class=3D"elided-text">
     On May 13, 2026 16:05, Owen Smith &lt=
;owen=2Esmith@citrix=2Ecom&gt; wrote:
     <br type=3D"attribution">
     <=
blockquote style=3D"margin:0 0 0 0=2E8ex;border-left:1px #ccc solid;padding=
-left:1ex">
      <div>
       Hi Tu,
       <br>
       <br>
       I'm ha=
ving an issue with this patch
       <br>
       During a VM start, its pos=
sible for a single system thread to acquire the lock exclusively,
       <b=
r>
       and while its locked, a DPC can then attempt to acquire the lock =
in shared mode, resulting
       <br>
       in a deadlock (if AcquireMrswL=
ockShared is called) or spin (if SpinAcquireMrswLockShared
       <br>
    =
   is called)=2E
       <br>
       <br>
       0: kd&gt; k
       <br>
   =
    # Child-SP RetAddr Call Site
       <br>
       00 fffff805`49b48aa8 ff=
fff805`b66b2b2c nt!DbgBreakPointWithStatus
       <br>
       01 fffff805`4=
9b48ab0 fffff805`b66b0ada nt!KeAccumulateTicks+0x70c
       <br>
       02 =
fffff805`49b48b20 fffff805`b66b0833 nt!KiUpdateRunTime+0xd6
       <br>
   =
    03 fffff805`49b48c70 fffff805`b66aed45 nt!KiUpdateTime+0x473
       <br=
>
       04 fffff805`49b48e20 fffff805`b66ae35d nt!KeClockInterruptNotify+0=
x195
       <br>
       05 fffff805`49b48f50 fffff805`b6a7520e nt!KiCallInt=
erruptServiceRoutine+0x2ed
       <br>
       06 fffff805`49b48fb0 fffff805=
`b6a75a1c nt!KiInterruptSubDispatchNoLockNoEtw+0x4e
       <br>
       07 f=
ffff805`49b412b0 fffff805`b66d6616 nt!KiInterruptDispatchNoLockNoEtw+0x3c
 =
      <br>
       08 fffff805`49b41448 fffff805`4c1d6689 nt!ExfAcquireRundo=
wnProtection+0x6
       <br>
       09 (Inline Function) --------`-------- =
xenvif!__MrswRundownAcquire+0x9 [src\xenvif\mrsw=2Eh @ 84]
       <br>
    =
   0a (Inline Function) --------`-------- xenvif!__SpinAcquireMrswLockShare=
d+0x9 [src\xenvif\mrsw=2Eh @ 283]
       <br>
       0b fffff805`49b41450 f=
ffff805`4c4a5dd0 xenvif!VifReceiverReturnPacket+0x29 [src\xenvif\vif=2Ec @ =
537]
       <br>
       0c (Inline Function) --------`-------- xennet!__Rec=
eiverReturnNetBufferLists+0x54 [src\xennet\receiver=2Ec @ 213]
       <br>
=
       0d (Inline Function) --------`-------- xennet!ReceiverReturnNetBuffe=
rLists+0x54 [src\xennet\receiver=2Ec @ 535]
       <br>
       0e fffff805`=
49b414a0 fffff805`4ac84661 xennet!MiniportReturnNetBufferLists+0x70 [src\xe=
nnet\miniport=2Ec @ 208]
       <br>
       0f fffff805`49b414d0 fffff805`4=
b341824 ndis!NdisFReturnNetBufferLists+0x411
       <br>
       10 fffff805=
`49b415a0 fffff805`4b34759a wfplwfs!LwfLowerReturnNetBufferLists+0x84
     =
  <br>
       11 fffff805`49b415f0 fffff805`4b347afa wfplwfs!L2NdisReceiveN=
etBufferListsComplete+0x4e
       <br>
       12 fffff805`49b41620 fffff805=
`4ac8b628 wfplwfs!LwfLowerRecvNetBufferLists+0x20a
       <br>
       13 ff=
fff805`49b416e0 fffff805`4c4a62d4 ndis!NdisMIndicateReceiveNetBufferLists+0=
xa78
       <br>
       14 (Inline Function) --------`-------- xennet!__Ind=
icateReceiveNetBufferLists+0x41 [src\xennet\receiver=2Ec @ 353]
       <br>=

       15 (Inline Function) --------`-------- xennet!__ReceiverPushPackets=
+0xaa [src\xennet\receiver=2Ec @ 422]
       <br>
       16 fffff805`49b419=
00 fffff805`4c4a1147 xennet!ReceiverQueuePacket+0x1c4 [src\xennet\receiver=
=2Ec @ 603]
       <br>
       17 fffff805`49b41980 fffff805`4c1c3cea xenne=
t!AdapterVifCallback+0x77 [src\xennet\adapter=2Ec @ 237]
       <br>
      =
 18 (Inline Function) --------`-------- xenvif!VifReceiverQueuePacket+0x90 =
[src\xenvif\vif=2Ec @ 1244]
       <br>
       19 (Inline Function) -------=
-`-------- xenvif!__ReceiverRingSwizzle+0x6f1 [src\xenvif\receiver=2Ec @ 15=
41]
       <br>
       1a fffff805`49b41a00 fffff805`b665993e xenvif!Receiv=
erRingQueueDpc+0x71a [src\xenvif\receiver=2Ec @ 1637]
       <br>
       1b=
 fffff805`49b41ad0 fffff805`b6604f1b nt!KiExecuteAllDpcs+0x67e
       <br>
=
       1c fffff805`49b41d20 fffff805`b6a7ae15 nt!KiRetireDpcList+0x36b
    =
   <br>
       1d fffff805`49b41fb0 fffff805`b6a7adbf nt!KxSwapStacksAndRet=
ireDpcList+0x5
       <br>
       1e ffffdf04`854cf2f0 fffff805`b66ed1d5 nt=
!KiPlatformSwapStacksAndCallReturn
       <br>
       1f ffffdf04`854cf300 =
fffff805`b6a7a24f nt!KiDispatchInterrupt+0x65
       <br>
       20 ffffdf0=
4`854cf330 fffff805`b6608670 nt!KiDpcInterrupt+0x39f
       <br>
       21 =
ffffdf04`854cf4c0 fffff805`4c1d5991 nt!KeReleaseSpinLock+0x30
       <br>
 =
      22 (Inline Function) --------`-------- xenvif!FrontendSetState+0x1b4 =
[src\xenvif\frontend=2Ec @ 2797]
       <br>
       23 ffffdf04`854cf4f0 ff=
fff805`4c4a5c83 xenvif!VifEnable+0x241 [src\xenvif\vif=2Ec @ 176]
       <b=
r>
       24 (Inline Function) --------`-------- xennet!AdapterEnable+0x64 =
[src\xennet\adapter=2Ec @ 1934]
       <br>
       25 ffffdf04`854cf550 fff=
ff805`4adceb91 xennet!MiniportRestart+0x73 [src\xennet\miniport=2Ec @ 143]
=
       <br>
       26 ffffdf04`854cf580 fffff805`4ade13d1 ndis!ndisMInvokeR=
estart+0x51
       <br>
       27 ffffdf04`854cf5d0 fffff805`4adcea65 ndis!=
ndisMRestartMiniportInner+0x141
       <br>
       28 ffffdf04`854cf660 fff=
ff805`4adbf26c ndis!ndisMRestartMiniport+0x65
       <br>
       29 ffffdf0=
4`854cf750 fffff805`4adbb4fb ndis!Ndis::BindEngine::Iterate+0x7dc
       <b=
r>
       2a ffffdf04`854cf910 fffff805`4adbac8a ndis!Ndis::BindEngine::Upd=
ateBindings+0xab
       <br>
       2b ffffdf04`854cf9c0 fffff805`4add1771 =
ndis!Ndis::BindEngine::UpdateBindingsWorkItem+0x5a
       <br>
       2c ff=
ffdf04`854cfa10 fffff805`b6709e32 ndis!KWorkItemBase&lt;Ndis::BindEngine,KW=
orkItem&lt;Ndis::BindEngine&gt; &gt;::CallbackThunk+0x11
       <br>
      =
 2d ffffdf04`854cfa40 fffff805`b685904a nt!ExpWorkerThread+0x1b2
       <br=
>
       2e ffffdf04`854cfbf0 fffff805`b6a741c4 nt!PspSystemThreadStartup+0=
x5a
       <br>
       2f ffffdf04`854cfc40 00000000`00000000 nt!KiStartSys=
temThread+0x34
       <br>
       <br>
       This seems to be a race condi=
tion, which depends on the ReceiverRingQueueDpc getting
       <br>
       =
executed when FrontendSetState drops the spinlock
       <br>
       <br>
 =
      Owen
       <br>
       <br>
       _________________________________=
_______
       <br>
       From: Tu Dinh &lt;ngoc-tu=2Edinh@vates=2Etech&gt=
;
       <br>
       Sent: 16 April 2026 12:10 PM
       <br>
       To: wi=
n-pv-devel@lists=2Exenproject=2Eorg
       <br>
       Cc: Tu Dinh; Owen Sm=
ith
       <br>
       Subject: [PATCH 4/5] Implement rundown-based MRSW lo=
ck
       <br>
       <br>
       The current MRSW lock has a few downsides=
:
       <br>
       * Large size (have to store a 1KB holder list)
       =
<br>
       * Long fast-path acquire (~1KB of code) due to having to scan t=
he holder
       <br>
       list every acquire
       <br>
       * Limite=
d to 64 holders
       <br>
       * Multiple IRQL operations per acquire
 =
      <br>
       * Always raises the critical section to DISPATCH_LEVEL
  =
     <br>
       <br>
       It's currently only used as the cleanup lock f=
or the VIF interface, so
       <br>
       replace it with something simpl=
er=2E
       <br>
       <br>
       Implement a read-write lock with the f=
ollowing properties:
       <br>
       * The reader section is protected b=
y an EX_RUNDOWN_REF=2E
       <br>
       * Writer/cleanup section is imple=
mented by running down the reference
       <br>
       within a guarded mu=
tex=2E
       <br>
       * It offers 3 read acquire flavors: try acquire, =
spin acquire (both of
       <br>
       which can be used from DISPATCH_LE=
VEL) and sleeping acquire (using the
       <br>
       guarded mutex)=2E
 =
      <br>
       * It makes the downgrade call explicit instead of overloa=
ding it via
       <br>
       ReleaseMrswLockExclusive=2E
       <br>
    =
   * Finally, the lock supports cache-aware mode, where EX_RUNDOWN_REF is
 =
      <br>
       replaced with EX_RUNDOWN_REF_CACHE_AWARE using the corres=
ponding
       <br>
       macros=2E
       <br>
       <br>
       As the =
changes are only internal to vif=2Ec, the VIF version doesn't need
       <=
br>
       to be increased=2E
       <br>
       <br>
       Signed-off-by:=
 Tu Dinh &lt;ngoc-tu=2Edinh@vates=2Etech&gt;
       <br>
       ---
       =
<br>
       src/xenvif/mrsw=2Eh | 530 +++++++++++++++++++++++++------------=
---------
       <br>
       src/xenvif/vif=2Ec | 65 +++---
       <br>
   =
    2 files changed, 327 insertions(+), 268 deletions(-)
       <br>
      =
 <br>
       diff --git a/src/xenvif/mrsw=2Eh b/src/xenvif/mrsw=2Eh
       =
<br>
       index e1ff056=2E=2E8bfa441 100644
       <br>
       --- a/src/=
xenvif/mrsw=2Eh
       <br>
       +++ b/src/xenvif/mrsw=2Eh
       <br>
  =
     @@ -1,289 +1,347 @@
       <br>
       /* Copyright (c) Xen Project=2E=

       <br>
       * Copyright (c) Cloud Software Group, Inc=2E
       <br=
>
       + * Copyright (c) Vates=2E
       <br>
       * All rights reserve=
d=2E
       <br>
       - *
       <br>
       - * Redistribution and use i=
n source and binary forms,
       <br>
       - * with or without modificat=
ion, are permitted provided
       <br>
       + *
       <br>
       + * R=
edistribution and use in source and binary forms,
       <br>
       + * wi=
th or without modification, are permitted provided
       <br>
       * tha=
t the following conditions are met:
       <br>
       - *
       <br>
    =
   - * * Redistributions of source code must retain the above
       <br>
 =
      - * copyright notice, this list of conditions and the
       <br>
   =
    + *
       <br>
       + * * Redistributions of source code must retain=
 the above
       <br>
       + * copyright notice, this list of conditions=
 and the
       <br>
       * following disclaimer=2E
       <br>
       - =
* * Redistributions in binary form must reproduce the above
       <br>
   =
    - * copyright notice, this list of conditions and the
       <br>
     =
  - * following disclaimer in the documentation and/or other
       <br>
  =
     + * * Redistributions in binary form must reproduce the above
       <=
br>
       + * copyright notice, this list of conditions and the
       <br=
>
       + * following disclaimer in the documentation and/or other
       =
<br>
       * materials provided with the distribution=2E
       <br>
     =
  - *
       <br>
       - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOL=
DERS AND
       <br>
       - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMP=
LIED WARRANTIES,
       <br>
       - * INCLUDING, BUT NOT LIMITED TO, THE =
IMPLIED WARRANTIES OF
       <br>
       - * MERCHANTABILITY AND FITNESS FO=
R A PARTICULAR PURPOSE ARE
       <br>
       - * DISCLAIMED=2E IN NO EVENT=
 SHALL THE COPYRIGHT HOLDER OR
       <br>
       - * CONTRIBUTORS BE LIABL=
E FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       <br>
       - * SPECIAL, EXE=
MPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
       <br>
       - * BUT NOT=
 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
       <br>
       - * SERV=
ICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
       <br>
       - * INT=
ERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
       <br>
     =
  - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
       <br>=

       - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    =
   <br>
       - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
=
       <br>
       + *
       <br>
       + * THIS SOFTWARE IS PROVIDED BY =
THE COPYRIGHT HOLDERS AND
       <br>
       + * CONTRIBUTORS "AS IS" AND A=
NY EXPRESS OR IMPLIED WARRANTIES,
       <br>
       + * INCLUDING, BUT NOT=
 LIMITED TO, THE IMPLIED WARRANTIES OF
       <br>
       + * MERCHANTABILI=
TY AND FITNESS FOR A PARTICULAR PURPOSE ARE
       <br>
       + * DISCLAIM=
ED=2E IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
       <br>
       + * CONT=
RIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       <br>
      =
 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
       <br>
 =
      + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
       <br=
>
       + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
       <b=
r>
       + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
=
       <br>
       + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCL=
UDING
       <br>
       + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OU=
T OF THE USE
       <br>
       + * OF THIS SOFTWARE, EVEN IF ADVISED OF TH=
E POSSIBILITY OF
       <br>
       * SUCH DAMAGE=2E
       <br>
       */
=
       <br>
       <br>
       -#ifndef _XENVIF_MRSW_H
       <br>
       -=
#define _XENVIF_MRSW_H
       <br>
       +#ifndef _MRSW_H
       <br>
    =
   +#define _MRSW_H
       <br>
       <br>
       -#include &lt;ntddk=2Eh&=
gt;
       <br>
       +#include &lt;wdm=2Eh&gt;
       <br>
       <br>
  =
     #include "assert=2Eh"
       <br>
       #include "util=2Eh"
       <b=
r>
       <br>
       -#pragma warning(disable:4127) // conditional express=
ion is constant
       <br>
       -
       <br>
       -typedef struct _XE=
NVIF_MRSW_HOLDER {<!-- -->
       <br>
       - PKTHREAD Thread;
       <br=
>
       - LONG Level;
       <br>
       -} XENVIF_MRSW_HOLDER, *PXENVIF_M=
RSW_HOLDER;
       <br>
       -
       <br>
       -typedef struct _XENVIF=
_MRSW_LOCK {<!-- -->
       <br>
       - volatile LONG64 Mask;
       <br>=

       - XENVIF_MRSW_HOLDER Holder[64];
       <br>
       - KEVENT Event;=

       <br>
       -} XENVIF_MRSW_LOCK, *PXENVIF_MRSW_LOCK;
       <br>
  =
     -
       <br>
       -C_ASSERT(RTL_FIELD_SIZE(XENVIF_MRSW_LOCK, Holder=
) =3D=3D RTL_FIELD_SIZE(XENVIF_MRSW_LOCK, Mask) * 8 * sizeof (XENVIF_MRSW_H=
OLDER));
       <br>
       -
       <br>
       -#define XENVIF_MRSW_EXCLU=
SIVE_SLOT 0
       <br>
       -
       <br>
       -static FORCEINLINE VOI=
D
       <br>
       -InitializeMrswLock(
       <br>
       - IN PXENVIF_M=
RSW_LOCK Lock
       <br>
       +#pragma warning(push)
       <br>
       =
+#pragma warning(disable:4201) // nameless struct/union
       <br>
       =
+struct _MRSW_LOCK {<!-- -->
       <br>
       + KGUARDED_MUTEX Mutex;
   =
    <br>
       + union {<!-- -->
       <br>
       + EX_RUNDOWN_REF Rundo=
wn;
       <br>
       + PEX_RUNDOWN_REF_CACHE_AWARE RundownCacheAware;
   =
    <br>
       + };
       <br>
       +};
       <br>
       +#pragma war=
ning(pop)
       <br>
       +
       <br>
       +typedef struct _MRSW_LOC=
K MRSW_LOCK, *PMRSW_LOCK;
       <br>
       +typedef struct _MRSW_LOCK MRS=
W_CACHE_AWARE_LOCK, *PMRSW_CACHE_AWARE_LOCK;
       <br>
       +
       <b=
r>
       +static FORCEINLINE NTSTATUS
       <br>
       +__MrswRundownIni=
tialize(
       <br>
       + _Inout_ struct _MRSW_LOCK *Lock,
       <br>
=
       + _In_ BOOLEAN CacheAware,
       <br>
       + _In_ ULONG Tag
     =
  <br>
       )
       <br>
       {<!-- -->
       <br>
       - LONG Slot=
;
       <br>
       -
       <br>
       - RtlZeroMemory(Lock, sizeof (XEN=
VIF_MRSW_LOCK));
       <br>
       -
       <br>
       - for (Slot =3D 0;=
 Slot &lt; (LONG) sizeof (Lock-&gt;Mask) * 8; Slot++)
       <br>
       - =
Lock-&gt;Holder[Slot]=2ELevel =3D -1;
       <br>
       + if (CacheAware) =
{<!-- -->
       <br>
       + Lock-&gt;RundownCacheAware =3D ExAllocateCac=
heAwareRundownProtection(NonPagedPoolNx,
       <br>
       + Tag);
       =
<br>
       + if (!Lock-&gt;RundownCacheAware)
       <br>
       + return =
STATUS_NO_MEMORY;
       <br>
       + } else {<!-- -->
       <br>
       =
+ ExInitializeRundownProtection(&amp;Lock-&gt;Rundown);
       <br>
       =
+ }
       <br>
       <br>
       - KeInitializeEvent(&amp;Lock-&gt;Event,=
 NotificationEvent, FALSE);
       <br>
       + return STATUS_SUCCESS;
   =
    <br>
       }
       <br>
       <br>
       static FORCEINLINE BOOLEAN=

       <br>
       -__ClaimExclusive(
       <br>
       - IN PXENVIF_MRSW=
_LOCK Lock
       <br>
       +__MrswRundownAcquire(
       <br>
       + _=
Inout_ struct _MRSW_LOCK *Lock,
       <br>
       + _In_ BOOLEAN CacheAwar=
e
       <br>
       )
       <br>
       {<!-- -->
       <br>
       - LO=
NG64 Old;
       <br>
       - LONG64 New;
       <br>
       -
       <br>=

       - Old =3D 0;
       <br>
       - New =3D 1ll &lt;&lt; XENVIF_MRSW_=
EXCLUSIVE_SLOT;
       <br>
       -
       <br>
       - return (Interlock=
edCompareExchange64(&amp;Lock-&gt;Mask, New, Old) =3D=3D Old) ? TRUE : FALS=
E;
       <br>
       + if (CacheAware)
       <br>
       + return ExAcqui=
reRundownProtectionCacheAware(Lock-&gt;RundownCacheAware);
       <br>
    =
   + else
       <br>
       + return ExAcquireRundownProtection(&amp;Lock-=
&gt;Rundown);
       <br>
       }
       <br>
       <br>
       -static F=
ORCEINLINE KIRQL
       <br>
       -__drv_maxIRQL(APC_LEVEL)
       <br>
 =
      -__drv_raisesIRQL(DISPATCH_LEVEL)
       <br>
       -__drv_savesIRQL=

       <br>
       -__AcquireMrswLockExclusive(
       <br>
       - IN PX=
ENVIF_MRSW_LOCK Lock
       <br>
       +static FORCEINLINE VOID
       <br=
>
       +__MrswRundownRelease(
       <br>
       + _Inout_ struct _MRSW_L=
OCK *Lock,
       <br>
       + _In_ BOOLEAN CacheAware
       <br>
       =
)
       <br>
       {<!-- -->
       <br>
       - KIRQL Irql;
       <br>=

       - LONG Slot;
       <br>
       - PKTHREAD Self;
       <br>
      =
 - PXENVIF_MRSW_HOLDER Holder;
       <br>
       -
       <br>
       - AS=
SERT3U(KeGetCurrentIrql(), &lt;, DISPATCH_LEVEL);
       <br>
       - KeRa=
iseIrql(DISPATCH_LEVEL, &amp;Irql);
       <br>
       -
       <br>
      =
 - Self =3D KeGetCurrentThread();
       <br>
       -
       <br>
       -=
 // Make sure we do not already hold the lock
       <br>
       - for (Slo=
t =3D 0; Slot &lt; (LONG) sizeof (Lock-&gt;Mask) * 8; Slot++)
       <br>
 =
      - ASSERT(Lock-&gt;Holder[Slot]=2EThread !=3D Self);
       <br>
     =
  -
       <br>
       - for (;;) {<!-- -->
       <br>
       - if (__Clai=
mExclusive(Lock))
       <br>
       - break;
       <br>
       -
       <=
br>
       - KeLowerIrql(Irql);
       <br>
       -
       <br>
       - (=
VOID) KeWaitForSingleObject(&amp;Lock-&gt;Event,
       <br>
       - Execu=
tive,
       <br>
       - KernelMode,
       <br>
       - FALSE,
       <=
br>
       - NULL);
       <br>
       - KeClearEvent(&amp;Lock-&gt;Event);=

       <br>
       -
       <br>
       - KeRaiseIrql(DISPATCH_LEVEL, &amp=
;Irql);
       <br>
       - }
       <br>
       -
       <br>
       - Ho=
lder =3D &amp;Lock-&gt;Holder[XENVIF_MRSW_EXCLUSIVE_SLOT];
       <br>
    =
   -
       <br>
       - ASSERT3P(Holder-&gt;Thread, =3D=3D, NULL);
      =
 <br>
       - Holder-&gt;Thread =3D Self;
       <br>
       - Holder-&gt;=
Level =3D 0;
       <br>
       -
       <br>
       - return Irql;
       =
<br>
       + if (CacheAware)
       <br>
       + ExReleaseRundownProtecti=
onCacheAware(Lock-&gt;RundownCacheAware);
       <br>
       + else
       =
<br>
       + ExReleaseRundownProtection(&amp;Lock-&gt;Rundown);
       <br=
>
       }
       <br>
       <br>
       -#define AcquireMrswLockExclusive=
(_Lock, _Irql) \
       <br>
       - do { \
       <br>
       - *(_Irql) =
=3D __AcquireMrswLockExclusive(_Lock); \
       <br>
       - } while (FALS=
E)
       <br>
       -
       <br>
       static FORCEINLINE VOID
       <=
br>
       -__drv_maxIRQL(DISPATCH_LEVEL)
       <br>
       -__drv_require=
sIRQL(DISPATCH_LEVEL)
       <br>
       -ReleaseMrswLockExclusive(
       =
<br>
       - IN PXENVIF_MRSW_LOCK Lock,
       <br>
       - IN __drv_rest=
oresIRQL KIRQL Irql,
       <br>
       - IN BOOLEAN Shared
       <br>
   =
    +__MrswRundownWait(
       <br>
       + _Inout_ struct _MRSW_LOCK *Loc=
k,
       <br>
       + _In_ BOOLEAN CacheAware
       <br>
       )
      =
 <br>
       {<!-- -->
       <br>
       - LONG Slot;
       <br>
       -=
 PKTHREAD Self;
       <br>
       - LONG64 Old;
       <br>
       - LONG6=
4 New;
       <br>
       - PXENVIF_MRSW_HOLDER Holder;
       <br>
       =
-
       <br>
       - ASSERT3U(KeGetCurrentIrql(), =3D=3D, DISPATCH_LEVEL)=
;
       <br>
       -
       <br>
       - Slot =3D XENVIF_MRSW_EXCLUSIVE_=
SLOT + 1; // Choose any slot other than the exclusive slot
       <br>
    =
   -
       <br>
       - Old =3D 1ll &lt;&lt; XENVIF_MRSW_EXCLUSIVE_SLOT;
=
       <br>
       - New =3D (Shared) ? (1ll &lt;&lt; Slot) : 0;
       <br=
>
       -
       <br>
       - Old =3D InterlockedCompareExchange64(&amp;L=
ock-&gt;Mask, New, Old);
       <br>
       - ASSERT3U(Old, =3D=3D , 1ll &l=
t;&lt; XENVIF_MRSW_EXCLUSIVE_SLOT);
       <br>
       -
       <br>
      =
 - Self =3D KeGetCurrentThread();
       <br>
       -
       <br>
       -=
 ASSERT3P(Lock-&gt;Holder[XENVIF_MRSW_EXCLUSIVE_SLOT]=2EThread, =3D=3D, Sel=
f);
       <br>
       -
       <br>
       - // If we are leaving the lock=
 held shared then we need to transfer
       <br>
       - // our identity =
information into the hew slot=2E
       <br>
       - if (Shared)
       <b=
r>
       - Lock-&gt;Holder[Slot] =3D Lock-&gt;Holder[XENVIF_MRSW_EXCLUSIVE=
_SLOT];
       <br>
       -
       <br>
       - Holder =3D &amp;Lock-&gt;=
Holder[XENVIF_MRSW_EXCLUSIVE_SLOT];
       <br>
       -
       <br>
      =
 - Holder-&gt;Thread =3D NULL;
       <br>
       - Holder-&gt;Level =3D -1=
;
       <br>
       -
       <br>
       - KeLowerIrql(Irql);
       <br>
=
       + if (CacheAware)
       <br>
       + ExWaitForRundownProtectionRel=
easeCacheAware(Lock-&gt;RundownCacheAware);
       <br>
       + else
     =
  <br>
       + ExWaitForRundownProtectionRelease(&amp;Lock-&gt;Rundown);
 =
      <br>
       }
       <br>
       <br>
       -static FORCEINLINE LONG=

       <br>
       -__ClaimShared(
       <br>
       - IN PXENVIF_MRSW_LO=
CK Lock
       <br>
       +static FORCEINLINE VOID
       <br>
       +__M=
rswRundownCompleted(
       <br>
       + _Inout_ struct _MRSW_LOCK *Lock,
=
       <br>
       + _In_ BOOLEAN CacheAware
       <br>
       )
       <b=
r>
       {<!-- -->
       <br>
       - LONG Slot;
       <br>
       - LO=
NG64 Old;
       <br>
       - LONG64 New;
       <br>
       -
       <br>=

       - // Make sure the exclusive bit is set so that we don't find it
  =
     <br>
       - Old =3D Lock-&gt;Mask | (1ll &lt;&lt; XENVIF_MRSW_EXCLUS=
IVE_SLOT);
       <br>
       -
       <br>
       - Slot =3D __ffu((ULONG6=
4)Old);
       <br>
       - ASSERT(Slot &gt;=3D 0);
       <br>
       - A=
SSERT3U(Slot, !=3D , XENVIF_MRSW_EXCLUSIVE_SLOT);
       <br>
       + if (=
CacheAware)
       <br>
       + ExRundownCompletedCacheAware(Lock-&gt;Rund=
ownCacheAware);
       <br>
       + else
       <br>
       + ExRundownCom=
pleted(&amp;Lock-&gt;Rundown);
       <br>
       +}
       <br>
       <br=
>
       - Old &amp;=3D ~(1ll &lt;&lt; XENVIF_MRSW_EXCLUSIVE_SLOT);
       =
<br>
       - New =3D Old | (1ll &lt;&lt; Slot);
       <br>
       +static=
 FORCEINLINE VOID
       <br>
       +__MrswRundownReInitialize(
       <br=
>
       + _Inout_ struct _MRSW_LOCK *Lock,
       <br>
       + _In_ BOOLE=
AN CacheAware
       <br>
       + )
       <br>
       +{<!-- -->
       <=
br>
       + if (CacheAware)
       <br>
       + ExReInitializeRundownProt=
ectionCacheAware(Lock-&gt;RundownCacheAware);
       <br>
       + else
   =
    <br>
       + ExReInitializeRundownProtection(&amp;Lock-&gt;Rundown);
 =
      <br>
       +}
       <br>
       <br>
       - return (InterlockedCo=
mpareExchange64(&amp;Lock-&gt;Mask, New, Old) =3D=3D Old) ? Slot : -1;
    =
   <br>
       +static FORCEINLINE VOID
       <br>
       +__MrswRundownTe=
ardown(
       <br>
       + _Inout_ struct _MRSW_LOCK *Lock,
       <br>
 =
      + _In_ BOOLEAN CacheAware
       <br>
       + )
       <br>
       +=
{<!-- -->
       <br>
       + if (CacheAware)
       <br>
       + ExFreeC=
acheAwareRundownProtection(Lock-&gt;RundownCacheAware);
       <br>
       =
+ else
       <br>
       + RtlZeroMemory(&amp;Lock-&gt;Rundown, sizeof(Loc=
k-&gt;Rundown));
       <br>
       }
       <br>
       <br>
       +_IRQL=
_requires_min_(PASSIVE_LEVEL)
       <br>
       +_IRQL_requires_max_(APC_L=
EVEL)
       <br>
       +static FORCEINLINE NTSTATUS
       <br>
       +_=
_InitializeMrswLock(
       <br>
       + _Out_ struct _MRSW_LOCK *Lock,
  =
     <br>
       + _In_ BOOLEAN CacheAware,
       <br>
       + _In_ ULONG=
 Tag
       <br>
       + )
       <br>
       +{<!-- -->
       <br>
     =
  + KeInitializeGuardedMutex(&amp;Lock-&gt;Mutex);
       <br>
       + ret=
urn __MrswRundownInitialize(Lock, CacheAware, Tag);
       <br>
       +}
 =
      <br>
       +#define InitializeMrswLock(Lock, Tag) \
       <br>
    =
   + __InitializeMrswLock(Lock, FALSE, Tag)
       <br>
       +#define Ini=
tializeMrswCacheAwareLock(Lock, Tag) \
       <br>
       + __InitializeMrs=
wLock(Lock, TRUE, Tag)
       <br>
       +
       <br>
       +_Requires_l=
ock_not_held_(*Lock)
       <br>
       +_IRQL_requires_min_(PASSIVE_LEVEL)=

       <br>
       +_IRQL_requires_max_(APC_LEVEL)
       <br>
       +sta=
tic FORCEINLINE VOID
       <br>
       +__TeardownMrswLock(
       <br>
  =
     + _Inout_ struct _MRSW_LOCK *Lock,
       <br>
       + _In_ BOOLEAN C=
acheAware
       <br>
       + )
       <br>
       +{<!-- -->
       <br>
=
       +#if DBG
       <br>
       + BUG_ON(!KeTryToAcquireGuardedMutex(&am=
p;Lock-&gt;Mutex));
       <br>
       + BUG_ON(!__MrswRundownAcquire(Lock,=
 CacheAware));
       <br>
       + KeReleaseGuardedMutex(&amp;Lock-&gt;Mut=
ex);
       <br>
       + __MrswRundownRelease(Lock, CacheAware);
       <b=
r>
       +#endif
       <br>
       +
       <br>
       + __MrswRundownTe=
ardown(Lock, CacheAware);
       <br>
       + RtlZeroMemory(Lock, sizeof(M=
RSW_LOCK));
       <br>
       +}
       <br>
       +#define TeardownMrswL=
ock(Lock) \
       <br>
       + __TeardownMrswLock(Lock, FALSE)
       <br=
>
       +#define TeardownMrswCacheAwareLock(Lock) \
       <br>
       + _=
_TeardownMrswLock(Lock, TRUE)
       <br>
       +
       <br>
       +_Acq=
uires_lock_(_Global_critical_region_)
       <br>
       +_Requires_lock_no=
t_held_(*Lock)
       <br>
       +_Acquires_exclusive_lock_(*Lock)
       =
<br>
       +_IRQL_requires_min_(PASSIVE_LEVEL)
       <br>
       +_IRQL_r=
equires_max_(APC_LEVEL)
       <br>
       static FORCEINLINE VOID
       <=
br>
       -AcquireMrswLockShared(
       <br>
       - IN PXENVIF_MRSW_LOC=
K Lock
       <br>
       +__AcquireMrswLockExclusive(
       <br>
       +=
 _Inout_ struct _MRSW_LOCK *Lock,
       <br>
       + _In_ BOOLEAN CacheAw=
are
       <br>
       )
       <br>
       {<!-- -->
       <br>
       - =
KIRQL Irql;
       <br>
       - LONG Level;
       <br>
       - LONG Slot=
;
       <br>
       - PKTHREAD Self;
       <br>
       - PXENVIF_MRSW_HOL=
DER Holder;
       <br>
       + ASSERT3U(KeGetCurrentIrql(), &lt;=3D, APC_=
LEVEL);
       <br>
       <br>
       + KeAcquireGuardedMutex(&amp;Lock-&g=
t;Mutex);
       <br>
       + __MrswRundownWait(Lock, CacheAware);
       =
<br>
       + __MrswRundownCompleted(Lock, CacheAware);
       <br>
       =
+}
       <br>
       +#define AcquireMrswLockExclusive(Lock) \
       <br>=

       + __AcquireMrswLockExclusive(Lock, FALSE)
       <br>
       +#defi=
ne AcquireMrswCacheAwareLockExclusive(Lock) \
       <br>
       + __Acquir=
eMrswLockExclusive(Lock, TRUE)
       <br>
       +
       <br>
       +_Re=
leases_lock_(_Global_critical_region_)
       <br>
       +_Requires_exclus=
ive_lock_held_(*Lock)
       <br>
       +_Releases_exclusive_lock_(*Lock)
=
       <br>
       +_IRQL_requires_min_(PASSIVE_LEVEL)
       <br>
       +=
_IRQL_requires_max_(APC_LEVEL)
       <br>
       +static FORCEINLINE VOID
=
       <br>
       +__ReleaseMrswLockExclusive(
       <br>
       + _Inout=
_ struct _MRSW_LOCK *Lock,
       <br>
       + _In_ BOOLEAN CacheAware
   =
    <br>
       + )
       <br>
       +{<!-- -->
       <br>
       + __Mr=
swRundownReInitialize(Lock, CacheAware);
       <br>
       + KeReleaseGuar=
dedMutex(&amp;Lock-&gt;Mutex);
       <br>
       +}
       <br>
       +#d=
efine ReleaseMrswLockExclusive(Lock) \
       <br>
       + __ReleaseMrswLo=
ckExclusive(Lock, FALSE)
       <br>
       +#define ReleaseMrswCacheAwareL=
ockExclusive(Lock) \
       <br>
       + __ReleaseMrswLockExclusive(Lock, =
TRUE)
       <br>
       +
       <br>
       +_Releases_lock_(_Global_crit=
ical_region_)
       <br>
       +_Requires_exclusive_lock_held_(*Lock)
   =
    <br>
       +_Releases_exclusive_lock_(*Lock)
       <br>
       +_Acqu=
ires_shared_lock_(*Lock)
       <br>
       +_IRQL_requires_min_(PASSIVE_LE=
VEL)
       <br>
       +_IRQL_requires_max_(APC_LEVEL)
       <br>
       =
+static FORCEINLINE VOID
       <br>
       +__DowngradeMrswLockExclusive(
=
       <br>
       + _Inout_ struct _MRSW_LOCK *Lock,
       <br>
       + =
_In_ BOOLEAN CacheAware
       <br>
       + )
       <br>
       +{<!-- --=
>
       <br>
       + __MrswRundownReInitialize(Lock, CacheAware);
       =
<br>
       + BUG_ON(!__MrswRundownAcquire(Lock, CacheAware));
       <br>
=
       + KeReleaseGuardedMutex(&amp;Lock-&gt;Mutex);
       <br>
       +}
=
       <br>
       +#define DowngradeMrswLockExclusive(Lock) \
       <br>
=
       + __DowngradeMrswLockExclusive(Lock, FALSE)
       <br>
       +#def=
ine DowngradeMrswCacheAwareLockExclusive(Lock) \
       <br>
       + __Dow=
ngradeMrswLockExclusive(Lock, TRUE)
       <br>
       +
       <br>
      =
 +_When_(return, _Acquires_shared_lock_(*Lock))
       <br>
       +_IRQL_r=
equires_min_(PASSIVE_LEVEL)
       <br>
       +_IRQL_requires_max_(DISPATC=
H_LEVEL)
       <br>
       +static FORCEINLINE BOOLEAN
       <br>
       =
+__TryAcquireMrswLockShared(
       <br>
       + _Inout_ struct _MRSW_LOCK=
 *Lock,
       <br>
       + _In_ BOOLEAN CacheAware
       <br>
       + )=

       <br>
       +{<!-- -->
       <br>
       +#if DBG
       <br>
    =
   ASSERT3U(KeGetCurrentIrql(), &lt;=3D, DISPATCH_LEVEL);
       <br>
     =
  - KeRaiseIrql(DISPATCH_LEVEL, &amp;Irql);
       <br>
       -
       <br=
>
       - Self =3D KeGetCurrentThread();
       <br>
       -
       <br>
=
       - // Do we already hold the lock? If so, get the nesting level
     =
  <br>
       - Level =3D -1;
       <br>
       - for (Slot =3D 0; Slot &l=
t; (LONG) sizeof (Lock-&gt;Mask) * 8; Slot++) {<!-- -->
       <br>
       =
- if (Lock-&gt;Holder[Slot]=2EThread =3D=3D Self &amp;&amp; Lock-&gt;Holder=
[Slot]=2ELevel &gt; Level)
       <br>
       - Level =3D Lock-&gt;Holder[S=
lot]=2ELevel;
       <br>
       - }
       <br>
       - Level++;
       <=
br>
       +#endif
       <br>
       <br>
       - for (;;) {<!-- -->
    =
   <br>
       - Slot =3D __ClaimShared(Lock);
       <br>
       - if (Slo=
t &gt;=3D 0)
       <br>
       - break;
       <br>
       -
       <br>
 =
      - _mm_pause();
       <br>
       - }
       <br>
       -
       <br=
>
       - Holder =3D &amp;Lock-&gt;Holder[Slot];
       <br>
       -
    =
   <br>
       - Holder-&gt;Thread =3D Self;
       <br>
       - Holder-&g=
t;Level =3D Level;
       <br>
       -
       <br>
       - KeLowerIrql(Ir=
ql);
       <br>
       + return __MrswRundownAcquire(Lock, CacheAware);
  =
     <br>
       }
       <br>
       -
       <br>
       +#define TryAcqu=
ireMrswLockShared(Lock) \
       <br>
       + __TryAcquireMrswLockShared(L=
ock, FALSE)
       <br>
       +#define TryAcquireMrswCacheAwareLockShared(=
Lock) \
       <br>
       + __TryAcquireMrswLockShared(Lock, TRUE)
       =
<br>
       +
       <br>
       +_Acquires_shared_lock_(*Lock)
       <br>=

       +_IRQL_requires_min_(PASSIVE_LEVEL)
       <br>
       +_IRQL_requi=
res_max_(DISPATCH_LEVEL)
       <br>
       static FORCEINLINE VOID
       =
<br>
       -ReleaseMrswLockShared(
       <br>
       - IN PXENVIF_MRSW_LO=
CK Lock
       <br>
       +__SpinAcquireMrswLockShared(
       <br>
      =
 + _Inout_ struct _MRSW_LOCK *Lock,
       <br>
       + _In_ BOOLEAN Cache=
Aware
       <br>
       )
       <br>
       {<!-- -->
       <br>
       =
- KIRQL Irql;
       <br>
       - PKTHREAD Self;
       <br>
       - LONG=
 Level;
       <br>
       - LONG Deepest;
       <br>
       - LONG Slot;
=
       <br>
       - LONG64 Old;
       <br>
       - LONG64 New;
       <b=
r>
       - PXENVIF_MRSW_HOLDER Holder;
       <br>
       -
       <br>
  =
     +#if DBG
       <br>
       ASSERT3U(KeGetCurrentIrql(), &lt;=3D, DISP=
ATCH_LEVEL);
       <br>
       - KeRaiseIrql(DISPATCH_LEVEL, &amp;Irql);
 =
      <br>
       -
       <br>
       - Self =3D KeGetCurrentThread();
   =
    <br>
       -
       <br>
       - Level =3D -1;
       <br>
       - D=
eepest =3D -1;
       <br>
       - for (Slot =3D 0; Slot &lt; (LONG) sizeo=
f (Lock-&gt;Mask) * 8; Slot++) {<!-- -->
       <br>
       - if (Lock-&gt;=
Holder[Slot]=2EThread =3D=3D Self &amp;&amp; Lock-&gt;Holder[Slot]=2ELevel =
&gt; Level) {<!-- -->
       <br>
       - Level =3D Lock-&gt;Holder[Slot]=
=2ELevel;
       <br>
       - Deepest =3D Slot;
       <br>
       - }
   =
    <br>
       - }
       <br>
       - ASSERT(Level &gt;=3D 0);
       <b=
r>
       -
       <br>
       - Slot =3D Deepest;
       <br>
       - ASS=
ERT3U(Slot, !=3D, XENVIF_MRSW_EXCLUSIVE_SLOT);
       <br>
       -
       =
<br>
       - Holder =3D &amp;Lock-&gt;Holder[Slot];
       <br>
       +#e=
ndif
       <br>
       <br>
       - Holder-&gt;Thread =3D NULL;
       <b=
r>
       - Holder-&gt;Level =3D -1;
       <br>
       -
       <br>
     =
  - do {<!-- -->
       <br>
       - Old =3D Lock-&gt;Mask;
       <br>
  =
     - New =3D Old &amp; ~(1ll &lt;&lt; Slot);
       <br>
       - } while=
 (InterlockedCompareExchange64(&amp;Lock-&gt;Mask, New, Old) !=3D Old);
   =
    <br>
       -
       <br>
       - KeSetEvent(&amp;Lock-&gt;Event, IO_N=
O_INCREMENT, FALSE);
       <br>
       - KeLowerIrql(Irql);
       <br>
  =
     + while (!__MrswRundownAcquire(Lock, CacheAware))
       <br>
       +=
 YieldProcessor();
       <br>
       +}
       <br>
       +#define SpinAc=
quireMrswLockShared(Lock) \
       <br>
       + __SpinAcquireMrswLockShare=
d(Lock, FALSE)
       <br>
       +#define SpinAcquireMrswCacheAwareLockSha=
red(Lock) \
       <br>
       + __SpinAcquireMrswLockShared(Lock, TRUE)
  =
     <br>
       +
       <br>
       +/*
       <br>
       + * Unlike Spi=
nAcquireMrswLockShared, AcquireMrswLockShared will
       <br>
       + * s=
leep when the lock acquisition fails=2E Thus it cannot be used at
       <b=
r>
       + * DISPATCH_LEVEL=2E
       <br>
       + */
       <br>
       =
+_Acquires_shared_lock_(*Lock)
       <br>
       +_IRQL_requires_min_(PASS=
IVE_LEVEL)
       <br>
       +_IRQL_requires_max_(APC_LEVEL)
       <br>
 =
      +static FORCEINLINE VOID
       <br>
       +__AcquireMrswLockShared(=

       <br>
       + _Inout_ struct _MRSW_LOCK *Lock,
       <br>
       +=
 _In_ BOOLEAN CacheAware
       <br>
       + )
       <br>
       +{<!-- -=
->
       <br>
       +#if DBG
       <br>
       + ASSERT3U(KeGetCurrentIr=
ql(), &lt;=3D, APC_LEVEL);
       <br>
       +#endif
       <br>
       +
=
       <br>
       + if (__MrswRundownAcquire(Lock, CacheAware))
       <br=
>
       + return;
       <br>
       +
       <br>
       + /*
       <br>=

       + * Don't bother retrying, since it's most likely that another writ=
er section
       <br>
       + * is cleaning up and not ending any time so=
on=2E Just jump straight into
       <br>
       + * sleep=2E
       <br>
 =
      + */
       <br>
       + KeAcquireGuardedMutex(&amp;Lock-&gt;Mutex);=

       <br>
       + /*
       <br>
       + * Since we have the write mut=
ex, we know that there are no writers=2E So this
       <br>
       + * acq=
uire must succeed=2E
       <br>
       + */
       <br>
       + BUG_ON(!_=
_MrswRundownAcquire(Lock, CacheAware));
       <br>
       + KeReleaseGuard=
edMutex(&amp;Lock-&gt;Mutex);
       <br>
       +}
       <br>
       +#de=
fine AcquireMrswLockShared(Lock) \
       <br>
       + __AcquireMrswLockSh=
ared(Lock, FALSE)
       <br>
       +#define AcquireMrswCacheAwareLockShar=
ed(Lock) \
       <br>
       + __AcquireMrswLockShared(Lock, TRUE)
       =
<br>
       +
       <br>
       +_Requires_shared_lock_held_(*Lock)
      =
 <br>
       +_Releases_shared_lock_(*Lock)
       <br>
       +_IRQL_requi=
res_min_(PASSIVE_LEVEL)
       <br>
       +_IRQL_requires_max_(DISPATCH_LE=
VEL)
       <br>
       +static FORCEINLINE VOID
       <br>
       +__Rele=
aseMrswLockShared(
       <br>
       + _Inout_ struct _MRSW_LOCK *Lock,
  =
     <br>
       + _In_ BOOLEAN CacheAware
       <br>
       + )
       <b=
r>
       +{<!-- -->
       <br>
       + __MrswRundownRelease(Lock, CacheA=
ware);
       <br>
       }
       <br>
       +#define ReleaseMrswLockShar=
ed(Lock) \
       <br>
       + __ReleaseMrswLockShared(Lock, FALSE)
      =
 <br>
       +#define ReleaseMrswCacheAwareLockShared(Lock) \
       <br>
 =
      + __ReleaseMrswLockShared(Lock, TRUE)
       <br>
       <br>
       =
-#endif // _XENVIF_MRSW_H
       <br>
       +#endif // _MRSW_H
       <br>=

       diff --git a/src/xenvif/vif=2Ec b/src/xenvif/vif=2Ec
       <br>
  =
     index 6f468ee=2E=2Ecb4cf84 100644
       <br>
       --- a/src/xenvif/=
vif=2Ec
       <br>
       +++ b/src/xenvif/vif=2Ec
       <br>
       @@ -=
47,7 +47,7 @@
       <br>
       <br>
       struct _XENVIF_VIF_CONTEXT {<!=
-- -->
       <br>
       PXENVIF_PDO Pdo;
       <br>
       - XENVIF_MRSW=
_LOCK Lock;
       <br>
       + MRSW_LOCK Lock;
       <br>
       LONG Re=
ferences;
       <br>
       PXENVIF_FRONTEND Frontend;
       <br>
       =
BOOLEAN Enabled;
       <br>
       @@ -150,13 +150,12 @@ VifEnable(
      =
 <br>
       )
       <br>
       {<!-- -->
       <br>
       PXENVIF_VIF_=
CONTEXT Context =3D Interface-&gt;Context;
       <br>
       - KIRQL Irql;=

       <br>
       BOOLEAN Exclusive;
       <br>
       NTSTATUS status;
=
       <br>
       <br>
       Trace("=3D=3D=3D=3D&gt;\n");
       <br>
   =
    <br>
       - AcquireMrswLockExclusive(&amp;Context-&gt;Lock, &amp;Irql=
);
       <br>
       + AcquireMrswLockExclusive(&amp;Context-&gt;Lock);
  =
     <br>
       Exclusive =3D TRUE;
       <br>
       <br>
       if (Con=
text-&gt;Enabled)
       <br>
       @@ -188,7 +187,7 @@ VifEnable(
       =
<br>
       <br>
       done:
       <br>
       ASSERT(Exclusive);
       =
<br>
       - ReleaseMrswLockExclusive(&amp;Context-&gt;Lock, Irql, FALSE);=

       <br>
       + ReleaseMrswLockExclusive(&amp;Context-&gt;Lock);
    =
   <br>
       <br>
       Trace("&lt;=3D=3D=3D=3D\n");
       <br>
       =
<br>
       @@ -199,7 +198,7 @@ fail3:
       <br>
       <br>
       (VOID=
) FrontendSetState(Context-&gt;Frontend, FRONTEND_CONNECTED);
       <br>
 =
      <br>
       - ReleaseMrswLockExclusive(&amp;Context-&gt;Lock, Irql, T=
RUE);
       <br>
       + DowngradeMrswLockExclusive(&amp;Context-&gt;Lock=
);
       <br>
       Exclusive =3D FALSE;
       <br>
       <br>
       R=
eceiverWaitForPackets(FrontendGetReceiver(Context-&gt;Frontend));
       <b=
r>
       @@ -234,7 +233,7 @@ fail1:
       <br>
       Context-&gt;Callbac=
k =3D NULL;
       <br>
       <br>
       if (Exclusive)
       <br>
     =
  - ReleaseMrswLockExclusive(&amp;Context-&gt;Lock, Irql, FALSE);
       <b=
r>
       + ReleaseMrswLockExclusive(&amp;Context-&gt;Lock);
       <br>
  =
     else
       <br>
       ReleaseMrswLockShared(&amp;Context-&gt;Lock);
=
       <br>
       <br>
       @@ -389,17 +388,16 @@ VifEnableVersion9(
   =
    <br>
       )
       <br>
       {<!-- -->
       <br>
       PXENVIF_V=
IF_CONTEXT Context =3D Interface-&gt;Context;
       <br>
       - KIRQL Ir=
ql;
       <br>
       NTSTATUS status;
       <br>
       <br>
       Trac=
e("=3D=3D=3D=3D&gt;\n");
       <br>
       <br>
       - AcquireMrswLockEx=
clusive(&amp;Context-&gt;Lock, &amp;Irql);
       <br>
       + AcquireMrsw=
LockExclusive(&amp;Context-&gt;Lock);
       <br>
       <br>
       Contex=
t-&gt;CallbackVersion9 =3D Callback;
       <br>
       Context-&gt;Argumen=
tVersion9 =3D Argument;
       <br>
       <br>
       - ReleaseMrswLockExc=
lusive(&amp;Context-&gt;Lock, Irql, FALSE);
       <br>
       + ReleaseMrs=
wLockExclusive(&amp;Context-&gt;Lock);
       <br>
       <br>
       statu=
s =3D VifEnable(Interface, VifCallbackVersion9, Context);
       <br>
     =
  <br>
       @@ -416,17 +414,16 @@ VifEnableVersion8(
       <br>
       )=

       <br>
       {<!-- -->
       <br>
       PXENVIF_VIF_CONTEXT Contex=
t =3D Interface-&gt;Context;
       <br>
       - KIRQL Irql;
       <br>
 =
      NTSTATUS status;
       <br>
       <br>
       Trace("=3D=3D=3D=3D&g=
t;\n");
       <br>
       <br>
       - AcquireMrswLockExclusive(&amp;Cont=
ext-&gt;Lock, &amp;Irql);
       <br>
       + AcquireMrswLockExclusive(&am=
p;Context-&gt;Lock);
       <br>
       <br>
       Context-&gt;CallbackVer=
sion8 =3D Callback;
       <br>
       Context-&gt;ArgumentVersion8 =3D Arg=
ument;
       <br>
       <br>
       - ReleaseMrswLockExclusive(&amp;Conte=
xt-&gt;Lock, Irql, FALSE);
       <br>
       + ReleaseMrswLockExclusive(&a=
mp;Context-&gt;Lock);
       <br>
       <br>
       status =3D VifEnableVe=
rsion9(Interface, VifCallbackVersion8, Context);
       <br>
       <br>
  =
     @@ -441,14 +438,13 @@ VifDisable(
       <br>
       )
       <br>
   =
    {<!-- -->
       <br>
       PXENVIF_VIF_CONTEXT Context =3D Interface-=
&gt;Context;
       <br>
       - KIRQL Irql;
       <br>
       <br>
     =
  Trace("=3D=3D=3D=3D&gt;\n");
       <br>
       <br>
       - AcquireMrsw=
LockExclusive(&amp;Context-&gt;Lock, &amp;Irql);
       <br>
       + Acqui=
reMrswLockExclusive(&amp;Context-&gt;Lock);
       <br>
       <br>
       =
if (!Context-&gt;Enabled) {<!-- -->
       <br>
       - ReleaseMrswLockExc=
lusive(&amp;Context-&gt;Lock, Irql, FALSE);
       <br>
       + ReleaseMrs=
wLockExclusive(&amp;Context-&gt;Lock);
       <br>
       goto done;
      =
 <br>
       }
       <br>
       <br>
       @@ -463,7 +459,7 @@ VifDisabl=
e(
       <br>
       <br>
       (VOID) FrontendSetState(Context-&gt;Front=
end, FRONTEND_CONNECTED);
       <br>
       <br>
       - ReleaseMrswLockE=
xclusive(&amp;Context-&gt;Lock, Irql, TRUE);
       <br>
       + Downgrade=
MrswLockExclusive(&amp;Context-&gt;Lock);
       <br>
       <br>
       Re=
ceiverWaitForPackets(FrontendGetReceiver(Context-&gt;Frontend));
       <br=
>
       TransmitterAbortPackets(FrontendGetTransmitter(Context-&gt;Fronten=
d));
       <br>
       @@ -511,7 +507,7 @@ VifQueryStatistic(
       <br>
=
       status =3D STATUS_INVALID_PARAMETER;
       <br>
       if (Index &g=
t;=3D XENVIF_VIF_STATISTIC_COUNT)
       <br>
       goto done;
       <br>=

       -
       <br>
       +
       <br>
       AcquireMrswLockShared(&am=
p;Context-&gt;Lock);
       <br>
       <br>
       FrontendQueryStatistic(=
Context-&gt;Frontend, Index, Value);
       <br>
       @@ -567,7 +563,8 @@=
 VifReceiverReturnPacket(
       <br>
       {<!-- -->
       <br>
       P=
XENVIF_VIF_CONTEXT Context =3D Interface-&gt;Context;
       <br>
       <b=
r>
       - AcquireMrswLockShared(&amp;Context-&gt;Lock);
       <br>
     =
  + // Called from MINIPORT_RETURN_NET_BUFFER_LISTS
       <br>
       + Sp=
inAcquireMrswLockShared(&amp;Context-&gt;Lock);
       <br>
       <br>
   =
    ReceiverReturnPacket(FrontendGetReceiver(Context-&gt;Frontend),
       =
<br>
       Cookie);
       <br>
       @@ -592,9 +589,10 @@ VifTransmitter=
QueuePacket(
       <br>
       PXENVIF_VIF_CONTEXT Context =3D Interface-&=
gt;Context;
       <br>
       NTSTATUS status;
       <br>
       <br>
   =
    - AcquireMrswLockShared(&amp;Context-&gt;Lock);
       <br>
       -
  =
     <br>
       status =3D STATUS_UNSUCCESSFUL;
       <br>
       + if (!=
TryAcquireMrswLockShared(&amp;Context-&gt;Lock))
       <br>
       + retur=
n status;
       <br>
       +
       <br>
       if (!Context-&gt;Enabled)=

       <br>
       goto done;
       <br>
       <br>
       @@ -948,9 +94=
6,8 @@ VifAcquire(
       <br>
       )
       <br>
       {<!-- -->
      =
 <br>
       PXENVIF_VIF_CONTEXT Context =3D Interface-&gt;Context;
       =
<br>
       - KIRQL Irql;
       <br>
       <br>
       - AcquireMrswLockE=
xclusive(&amp;Context-&gt;Lock, &amp;Irql);
       <br>
       + AcquireMrs=
wLockExclusive(&amp;Context-&gt;Lock);
       <br>
       <br>
       if (C=
ontext-&gt;References++ !=3D 0)
       <br>
       goto done;
       <br>
 =
      @@ -963,7 +960,7 @@ VifAcquire(
       <br>
       Trace("&lt;=3D=3D=
=3D=3D\n");
       <br>
       <br>
       done:
       <br>
       - Relea=
seMrswLockExclusive(&amp;Context-&gt;Lock, Irql, FALSE);
       <br>
      =
 + ReleaseMrswLockExclusive(&amp;Context-&gt;Lock);
       <br>
       <br>=

       return STATUS_SUCCESS;
       <br>
       }
       <br>
       @@ -=
974,9 +971,8 @@ VifRelease(
       <br>
       )
       <br>
       {<!-- -=
->
       <br>
       PXENVIF_VIF_CONTEXT Context =3D Interface-&gt;Context=
;
       <br>
       - KIRQL Irql;
       <br>
       <br>
       - Acquire=
MrswLockExclusive(&amp;Context-&gt;Lock, &amp;Irql);
       <br>
       + A=
cquireMrswLockExclusive(&amp;Context-&gt;Lock);
       <br>
       <br>
   =
    if (--Context-&gt;References &gt; 0)
       <br>
       goto done;
    =
   <br>
       @@ -991,7 +987,7 @@ VifRelease(
       <br>
       Trace("&l=
t;=3D=3D=3D=3D\n");
       <br>
       <br>
       done:
       <br>
      =
 - ReleaseMrswLockExclusive(&amp;Context-&gt;Lock, Irql, FALSE);
       <br=
>
       + ReleaseMrswLockExclusive(&amp;Context-&gt;Lock);
       <br>
   =
    }
       <br>
       <br>
       static struct _XENVIF_VIF_INTERFACE_V8=
 VifInterfaceVersion8 =3D {<!-- -->
       <br>
       @@ -1100,7 +1096,9 @=
@ VifInitialize(
       <br>
       if (*Context =3D=3D NULL)
       <br>
 =
      goto fail1;
       <br>
       <br>
       - InitializeMrswLock(&amp;=
(*Context)-&gt;Lock);
       <br>
       + status =3D InitializeMrswLock(&a=
mp;(*Context)-&gt;Lock, XENVIF_VIF_TAG);
       <br>
       + if (!NT_SUCCE=
SS(status))
       <br>
       + goto fail2;
       <br>
       <br>
      =
 FdoGetSuspendInterface(PdoGetFdo(Pdo),&amp;(*Context)-&gt;SuspendInterface=
);
       <br>
       <br>
       @@ -1110,7 +1108,7 @@ VifInitialize(
    =
   <br>
       *Context,
       <br>
       &amp;(*Context)-&gt;MacThread);=

       <br>
       if (!NT_SUCCESS(status))
       <br>
       - goto fail=
2;
       <br>
       + goto fail3;
       <br>
       <br>
       (*Contex=
t)-&gt;Pdo =3D Pdo;
       <br>
       <br>
       @@ -1118,7 +1116,7 @@ Vi=
fInitialize(
       <br>
       <br>
       return STATUS_SUCCESS;
       <=
br>
       <br>
       -fail2:
       <br>
       +fail3:
       <br>
     =
  Error("fail3\n");
       <br>
       <br>
       RtlZeroMemory(&amp;(*Con=
text)-&gt;MacEvent, sizeof (KEVENT));
       <br>
       @@ -1126,7 +1124,1=
0 @@ fail2:
       <br>
       RtlZeroMemory(&amp;(*Context)-&gt;SuspendInt=
erface,
       <br>
       sizeof (XENBUS_SUSPEND_INTERFACE));
       <br>
=
       <br>
       - RtlZeroMemory(&amp;(*Context)-&gt;Lock, sizeof (XENVIF=
_MRSW_LOCK));
       <br>
       + TeardownMrswLock(&amp;(*Context)-&gt;Loc=
k);
       <br>
       +
       <br>
       +fail2:
       <br>
       + Er=
ror("fail2\n");
       <br>
       <br>
       ASSERT(IsZeroMemory(*Context=
, sizeof (XENVIF_VIF_CONTEXT)));
       <br>
       __VifFree(*Context);
  =
     <br>
       @@ -1205,7 +1206,7 @@ VifGetInterface(
       <br>
       =
}
       <br>
       <br>
       return status;
       <br>
       -}
     =
  <br>
       +}
       <br>
       <br>
       VOID
       <br>
       Vif=
Teardown(
       <br>
       @@ -1228,7 +1229,7 @@ VifTeardown(
       <br>=

       RtlZeroMemory(&amp;Context-&gt;SuspendInterface,
       <br>
      =
 sizeof (XENBUS_SUSPEND_INTERFACE));
       <br>
       <br>
       - RtlZe=
roMemory(&amp;Context-&gt;Lock, sizeof (XENVIF_MRSW_LOCK));
       <br>
   =
    + TeardownMrswLock(&amp;Context-&gt;Lock);
       <br>
       <br>
    =
   ASSERT(IsZeroMemory(Context, sizeof (XENVIF_VIF_CONTEXT)));
       <br>
=
       __VifFree(Context);
       <br>
       --
       <br>
       2=2E53=
=2E0=2Ewindows=2E2
       <br>
       <br>
       <br>
       <br>
       -=
-
       <br>
       Ngoc Tu Dinh | Vates XCP-ng Developer
       <br>
    =
   <br>
       XCP-ng &amp; Xen Orchestra - Vates solutions
       <br>
   =
    <br>
       web: <a href=3D"https://vates=2Etech">https://vates=2Etech<=
/a>
       <br>
       <br>
      </div>
     </blockquote>
    </div>
    =
<br>
   </div>
  </div>
  <div class=3D"x-disclaimer-1126181503">
   <div>&=
nbsp;</div>
   <div>
    --
    <br>
    <table>
     <tbody>
      <tr>
  =
     <td style=3D"font-size: 10pt;">&nbsp;</td>
       <td style=3D"font-si=
ze: 10pt; padding-left: 20px; border-left-color: #b42626; border-left-style=
: solid; border-left-width: 1px;">
        <div>
         <strong> Ngoc Tu =
Dinh | Vates XCP-ng Developer</strong>
        </div>
        <div>
       =
  <strong></strong>
        </div>
        <div>
         <div>
          <=
strong></strong>
         </div>
        </div>
        <div>
         <str=
ong>XCP-ng &amp; Xen Orchestra - </strong>Vates solutions
        </div>
  =
      <div>
         <strong> 
          <br> web: 
         </strong> http=
s://vates=2Etech
        </div>
        <div>
         <img style=3D"float:=
 left;" src=3D"cid:x-disclaimer-1126181503-1778685767667=2Epng@bm-disclaime=
r" alt=3D"" width=3D"174" height=3D"159">
        </div>
       </td>
     =
 </tr>
     </tbody>
    </table>
   </div>
  </div>
 </body>
</html>
---=Part.baf.bf3f53f3ec167425.19e21eeeff6.b1b31f559e950585=-
Content-Type: image/png; charset=utf-8;
 name="x-disclaimer-1126181503-1778685767667.png"
Content-Transfer-Encoding: base64
Content-ID: <x-disclaimer-1126181503-1778685767667.png@bm-disclaimer>
Content-Disposition: inline;
 filename="x-disclaimer-1126181503-1778685767667.png"
Content-Description: x-disclaimer-1126181503-1778685767667.png

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
IhUHC4o4ZKhOFqSKOGoVilAh1AqtOphc+iE0aUhSXBwF14KDH4tVBxdnXR1cBUHwA8TRyUnRRUr8
X1JoEePBcT/e3XvcvQOEeplpVsc4oOm2mU4mxGxuRQy9ogsDiCCEuMwsY1aSUvAdX/cI8PUuxrP8
z/05etW8xYCASDzDDNMmXiee2rQNzvvEEVaSVeJz4jGTLkj8yHXF4zfORZcFnhkxM+k54gixWGxj
pY1ZydSIJ4mjqqZTvpD1WOW8xVkrV1nznvyF4by+vMR1msNIYgGLkCBCQRUbKMNGjFadFAtp2k/4
+Idcv0QuhVwbYOSYRwUaZNcP/ge/u7UKE3EvKZwAOl8c52MECO0CjZrjfB87TuMECD4DV3rLX6kD
05+k11pa9Ajo2wYurluasgdc7gCDT4Zsyq4UpCkUCsD7GX1TDui/BXpWvd6a+zh9ADLUVeoGODgE
RouUvebz7u723v490+zvB3gHcqkloKXxAAAN/WlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94
cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1w
bWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNC40LjAtRXhp
djIiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJk
Zi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6
eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICB4bWxuczpzdEV2dD0i
aHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgeG1s
bnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6R0lNUD0i
aHR0cDovL3d3dy5naW1wLm9yZy94bXAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2Jl
LmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEu
MC8iCiAgIHhtcE1NOkRvY3VtZW50SUQ9ImdpbXA6ZG9jaWQ6Z2ltcDo5NmE3ZjI0MS1lMjNjLTRi
MWEtOTdjZS1kNmU2NjliOTk4ZTIiCiAgIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MGNlZmJj
NjYtNjFiMy00ZDZkLWExYzgtMTg5M2QwNWFjOTg5IgogICB4bXBNTTpPcmlnaW5hbERvY3VtZW50
SUQ9InhtcC5kaWQ6NDIyZDdlNTItOGE2Ny00NmExLWI5MjYtNTJiOGEzMGIxOGIwIgogICBkYzpG
b3JtYXQ9ImltYWdlL3BuZyIKICAgR0lNUDpBUEk9IjIuMCIKICAgR0lNUDpQbGF0Zm9ybT0iTGlu
dXgiCiAgIEdJTVA6VGltZVN0YW1wPSIxNjU2MDE0ODk0NDU0Mjg5IgogICBHSU1QOlZlcnNpb249
IjIuMTAuMzAiCiAgIHRpZmY6T3JpZW50YXRpb249IjEiCiAgIHhtcDpDcmVhdG9yVG9vbD0iR0lN
UCAyLjEwIj4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAg
ICAgIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiCiAgICAgIHN0RXZ0OmNoYW5nZWQ9Ii8iCiAgICAgIHN0
RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6YTY0MGI4MmMtMDg0My00MjYwLTk3NmMtYTg1ZjA3MDc5
ZjcwIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJHaW1wIDIuMTAgKExpbnV4KSIKICAgICAg
c3RFdnQ6d2hlbj0iMjAyMi0wNC0yOVQxMzoyMzo1NCswMjowMCIvPgogICAgIDxyZGY6bGkKICAg
ICAgc3RFdnQ6YWN0aW9uPSJzYXZlZCIKICAgICAgc3RFdnQ6Y2hhbmdlZD0iLyIKICAgICAgc3RF
dnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDozYTUyMDNkNS04NGRiLTQzNDMtOWZhYy03NjFmZDZmZmFh
YjgiCiAgICAgIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkdpbXAgMi4xMCAoTGludXgpIgogICAgICBz
dEV2dDp3aGVuPSIyMDIyLTA2LTIzVDIyOjA4OjE0KzAyOjAwIi8+CiAgICA8L3JkZjpTZXE+CiAg
IDwveG1wTU06SGlzdG9yeT4KICA8L3JkZjpEZXNjcmlwdGlvbj4KIDwvcmRmOlJERj4KPC94Onht
cG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAog
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAg
ICAKPD94cGFja2V0IGVuZD0idyI/PlmiVpAAAAAGYktHRADwAKIAftw2PhcAAAAJcEhZcwAALiMA
AC4jAXilP3YAAAAHdElNRQfmBhcUCA56CWQaAAAgAElEQVR42ux9Z5gkV3X2e+6tqk4Td3d2epN2
tUlhJRSQQEKABpFE/ggm2SAMxmBbtjA2/uwPJ2wwGNs8BBuDbTAyOdnYGIEtECMhhISQYIXianOc
2Z3diR2r7j3fj3sqdO/M7Ehik9TneXq3p7u6uvrWe8894T3nEjrymOWnT79UFdaUledrUoFPBADW
AgzYRoio3rTR2CQfuW/UPuPgdu6M2GMX6gzBI5MvAuqiN7+8N9/f1Uta94C5xzbCZQCWE/MSUqoL
zAFZVrAccWRqNoomOTIj1vIBT6uDNjTTptqYmtkxOnHR5ntqnVHtAPe4yAcA9aprX3O231N6ktJ6
E0AbCLyWmc8gYFApBTADlsHWAswgZsAwYC3YMmAsODKwYVSHtXs4srvYmK22GT1ga817p3cdvOei
n9871hntDnAfs4x95DeWB+XBl0S18MW1feMbibEUhD4AgAXADGYGCVhhOXkNNn7YBMDuISCOH5Fp
IjKH2JgDpt78cWOy+vWoEd1y/o/ujDp3oAPcBcn0z79O/uKlJZ6aXG12bX0bwuYvAeiv7DgYmJka
gWXAmMEWABxQs6CNwcqMFKjt/xsHYjY2AbH73xgY2zC18CFTb36Cm9G3olrz0Dk/vqvZuTsd4M4q
tT3f61G54tNA9FoeP/wqs3NLCcagfmgS9f3jIM4CFSBmB073T6phGQDbDHjbtW1sPlhQon3NUSBG
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

---=Part.baf.bf3f53f3ec167425.19e21eeeff6.b1b31f559e950585=---

---=Part.bae.fc8657cf149906f8.19e21eeeff1.cc137a118f92ad64=---


