From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail05.groups.io (mail05.groups.io [45.79.224.7]) by spool.mail.gandi.net (Postfix) with ESMTPS id D0E5BD800F0 for ; Wed, 5 Jun 2024 01:08:03 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=isgwjL8K1oDleIswTWsxILgVSSsOuI+c+ViiRdytr7E=; c=relaxed/simple; d=groups.io; h=From:To:CC:Subject:Thread-Topic:Thread-Index:Date:Message-ID:References:In-Reply-To:Accept-Language:msip_labels:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Resent-Date:Resent-From:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Language:Content-Type; s=20240206; t=1717549683; v=1; b=IO+PcfT715/cmxGgtG7ZqDLwlGyqlgn5ebiySuBTmr8K3juLiygrH6byzx1+4/jczeEglERf F/elyorc1lFoXrxfDTgV5+6TNvhnlzVvBbNQ8fbpZg2aUVhoYf8lTnzeWKSH6ISJmobia8nUy1q zLMnJuJpJp2OU57EtYjApqzxASwVAjwWX/zwNioWiekfCcXISUSx7sNfGi/NbwIGVeBkP20R3NB mgUu91M8e4TQyVNfNVuDFCEc+P7YoPP3GQvJgBecdrUyZiGE3jEP0L/U6CR0YYrCyoiufooa/20 Ut4o8TqAMlzHTYFomvy4olF1naGCg063wUkLI24di/FHQ== X-Received: by 127.0.0.2 with SMTP id j1zNYY7687511x6Eh79CpuDA; Tue, 04 Jun 2024 18:08:02 -0700 X-Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) by mx.groups.io with SMTP id smtpd.web11.4115.1717549681370675647 for ; Tue, 04 Jun 2024 18:08:01 -0700 X-CSE-ConnectionGUID: xMT0D0iHRyq+16mR2FL25w== X-CSE-MsgGUID: nQtFN5GLRXSaHXzZF3F0pg== X-IronPort-AV: E=McAfee;i="6600,9927,11093"; a="24787552" X-IronPort-AV: E=Sophos;i="6.08,215,1712646000"; d="png'150?scan'150,208,217,150";a="24787552" X-Received: from fmviesa009.fm.intel.com ([10.60.135.149]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Jun 2024 18:08:01 -0700 X-CSE-ConnectionGUID: Vj8oAX40Q8+UE08VxiZUkA== X-CSE-MsgGUID: Al+msdZNRr2l7a2Kfz7xzA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,215,1712646000"; d="png'150?scan'150,208,217,150";a="37538456" X-Received: from orsmsx601.amr.corp.intel.com ([10.22.229.14]) by fmviesa009.fm.intel.com with ESMTP/TLS/AES256-GCM-SHA384; 04 Jun 2024 18:08:00 -0700 X-Received: from orsmsx602.amr.corp.intel.com (10.22.229.15) by ORSMSX601.amr.corp.intel.com (10.22.229.14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Tue, 4 Jun 2024 18:07:59 -0700 X-Received: from orsedg603.ED.cps.intel.com (10.7.248.4) by orsmsx602.amr.corp.intel.com (10.22.229.15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39 via Frontend Transport; Tue, 4 Jun 2024 18:07:59 -0700 X-Received: from NAM12-MW2-obe.outbound.protection.outlook.com (104.47.66.45) by edgegateway.intel.com (134.134.137.100) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.39; Tue, 4 Jun 2024 18:07:59 -0700 X-Received: from CO1PR11MB4929.namprd11.prod.outlook.com (2603:10b6:303:6d::19) by MN6PR11MB8104.namprd11.prod.outlook.com (2603:10b6:208:46c::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7633.21; Wed, 5 Jun 2024 01:07:56 +0000 X-Received: from CO1PR11MB4929.namprd11.prod.outlook.com ([fe80::a886:6510:729d:f9d0]) by CO1PR11MB4929.namprd11.prod.outlook.com ([fe80::a886:6510:729d:f9d0%5]) with mapi id 15.20.7633.021; Wed, 5 Jun 2024 01:07:55 +0000 From: "Michael D Kinney" To: "Ni, Ray" , "Andrew (EFI) Fish" , edk2-devel-groups-io , Rebecca Cran , "Hernandez Miramontes, Jose Miguel" CC: "Kinney, Michael D" Subject: Re: [edk2-devel] CpuDeadLoop() is optimized by compiler Thread-Topic: [edk2-devel] CpuDeadLoop() is optimized by compiler Thread-Index: AdmJbt4CNBNeb1syQVC5/ttKEmOvqQALzAcwAAKnEIAAAIyYQAAAISeAAABBXbAAAEifgAAHC2hzAAHo/WAABlp2AAAEkI0AABp7bwAAAhiXgCBNc/WAAAGTjHAACkPygAAMHuBwKrfa3mA= Date: Wed, 5 Jun 2024 01:07:55 +0000 Message-ID: References: <7C9FD4BA-328C-4CFE-AF5A-3A795BB147E4@apple.com> <0EECE39F-0B65-4BFE-8668-CB59448C578D@apple.com> <17605136DCF3E084.26337@groups.io> <69A704CE-16A4-4C8D-9A32-9BBD22C00475@apple.com> <24bf3d19-a292-11df-c84b-5d941cf2e19d@bsdio.com> <31286A1F-3497-478E-A938-50EEB1F61774@apple.com> In-Reply-To: Accept-Language: en-US X-MS-Has-Attach: yes X-MS-TNEF-Correlator: msip_labels: x-ms-publictraffictype: Email x-ms-traffictypediagnostic: CO1PR11MB4929:EE_|MN6PR11MB8104:EE_ x-ms-office365-filtering-correlation-id: 0926ea6f-e3c3-4f1b-cb09-08dc84fbee6c x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam-message-info: =?us-ascii?Q?g3gkIGGZvG6qEbuEBgFg08UHo0eOt1qvLx4UAOtjXQ1XgE1NDlYPPPDSrZcP?= =?us-ascii?Q?ui+Eb/Gz77J//Xy6nXj8QsABRiVCLXM1BZm5eEfGYlaYYj8ZjfknR/KDh4uE?= =?us-ascii?Q?o/kx+BcDUyTrWhn8TS0GJrjcFrXfNEqhN0JTbKSKMeaB2za5oTyapvpCI6oP?= =?us-ascii?Q?2SxInoHFi+mAsYNqsJZ/7ZCvh4ooSDTex3yqhasunxfD4FSY9jg1hB9WoFKA?= =?us-ascii?Q?SvQd9iPLSX6JbJY2YbPNDwW4OKL1IqPqfdJ8wJRmR6AW2plgOlFUgTyV46Xo?= =?us-ascii?Q?6aloLFvlco4qy7+L2ews5E3b6kUJEJCUuBNsNf4J0sCtdKDHjyDZUsb3ZM9j?= =?us-ascii?Q?yvTMzi8+b7Q/fn5+0A28whdkJu6pNN2GjRErJT4H/Q6BUMX3sNcVc73Jg/N/?= =?us-ascii?Q?7tXV6XLPNxTHvUsdLYxeDX5PF7fjBZ0cnhNaiGDaEO+UDJvAJEgWcqvHmpZR?= =?us-ascii?Q?VzkPF5ivWgTZ2CrUGdxbgEeLNWHeu5xXzCkq3d3CHnXUItlErlEDueCaMLVY?= =?us-ascii?Q?IzNRMP84vc4WGqoFfkOmzotKyPO+oJsY1eSN8vAogcwlrBKU7qNxDqDb5bnT?= =?us-ascii?Q?dGHQz1lBy7QMX3TD1/+shuhNxtCVTJcc3fho+3XzeLBna+cApoRl6xYtdK6N?= =?us-ascii?Q?r8vB+RjF31VKtg30sZUHxRpHIZ3CQIztGiEfM8yIyVxo6rbF7C5fraFlWwzT?= =?us-ascii?Q?fqCuTzfv71V/FRfYwL62PuTGhyH1/0aZ4x04hLlwvlL+3yglXkArq47kmKOB?= =?us-ascii?Q?iHEBT5+Uo29KtV47CMK6lKxd+eWyfMva+Ak3GqRlvK0qfrql8kkBV5jAHJBt?= =?us-ascii?Q?K/hI0pxguuWvrJdq8negoydO7s+Ow1QJ8cUKANAvsDbC10L7c+B5fJLqnB+k?= =?us-ascii?Q?sWb0er3Pqr18WmVoLyeaI7VzJ0rPWGN0GSbQn0SaAPn4PeSC8icOKMuotBSS?= =?us-ascii?Q?kQ2K+dWO8jm/uX6MQCjY8HaAuIuwB0sriaCuw1WBdqdAwvo+sLEsmnRLe0M+?= =?us-ascii?Q?PDhTFuoOkk7W16fTwAvwL4ImsxaNOdto3g0g1kJ1KNQ/Fd6sD+lXXxxou7Y6?= =?us-ascii?Q?BNm+D0sXBv8GNnnF+75oM4IRwXYKY9DOMMYbE3VPekKuH37QHWFSgwaOa7bO?= =?us-ascii?Q?MyvKnaZFGrMLcV/WLF7HZoPDSsOpFmxoc2nufPEzc8BjKTbiPRG1+2aJkOV7?= =?us-ascii?Q?rlP632NUEVjwYs42e84gyev0OW02dSdEqXAl8qxs68nmmYFXOxMepV1infpH?= =?us-ascii?Q?BNLwIva2CpNLcnWr16zAM0Mx9DO/FHAj9avQCaiR6JKwB60MFHpaRgd/WIB0?= =?us-ascii?Q?YTw=3D?= x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?Sy38Om8UJo5jV8E6pvHV4fkQFGhYIeSGM5imJjZfXhaYEaDaiYjHk2EcXKxD?= =?us-ascii?Q?RjLqFBYw13D7GKxk6t48Ukd7C67Qs6yHdR2PTWWGsR0yi/iZKFpFjWDM17vA?= =?us-ascii?Q?9wh/3kxOeShTkJJH0D6q3EIvBMsGHBiSoosSFa+6CtVxyKWm4VKvZL0CTAwy?= =?us-ascii?Q?lJ5mLdrkHfM5NPE2s0A3iTFmm/H+CopohGlwquI0rRfoltXD4BEkyAYiJr6s?= =?us-ascii?Q?xoODkU6jvwALGt0TLOIRUHR6P+6xwRFGY3r7Uh1wwmnv6DRkiR4+GFQszsVr?= =?us-ascii?Q?X03K/PekJknVUUbubBJgyhdr4ajp37es44WNir8dI0K23/6dmfOvONvrrQ5M?= =?us-ascii?Q?M97/QLsl4OsVakjoi5E4ljfsXMlRe/Mp1jfr04lJIUulQR5hdpNwk4UUNFvf?= =?us-ascii?Q?O2tPQnwO0qagv3hrCNHeCJKZp6VIfj/0NAqBdIu7QNMGqJLPT9WX2RxJQC74?= =?us-ascii?Q?xuMbOnSz4gqw71IywAc8CXbsFyfToQeVU3ezEC/dRrU/KuZ7uxUMKQRYN67S?= =?us-ascii?Q?20TzvtkWYFq3EuJb4iUli4NzkKCVBeBAqvWm413AuFgYOmJSZHGAJqH3tQPm?= =?us-ascii?Q?GQzFEBmm1C4RaEjxmKAC2T+mAjA/Jic3hRn9UR0a/8Be+S1ZqgxZ4BU7rD1c?= =?us-ascii?Q?R9tRKlgjs5Mvl3Gr/4er3ejBxsDS0Hl1PzHdeACjG2fXTVcBE9xnyIbtJZHP?= =?us-ascii?Q?uF4i01pLm7savBX22rNnL05TCluoQaE4JNpNlI1ntZI+cP/CJ5SqWWwcio1o?= =?us-ascii?Q?05E02E7maQb3BBpJ8z3GEcq06RGPXa6T5V2zdDOH+37rPpGV5GBG4mYGhiNX?= =?us-ascii?Q?yAAQEYhb+7nr3Znk7K5H8VgLiK4KfwylW5Xc7lnAg2GCSvWSjiDmwW8kIzZr?= =?us-ascii?Q?si/S2p6mZomPqgsEZAhDQVSSAU3uqcmV/Vvdmp/1PmnaeFPveY1ljow9Xa1p?= =?us-ascii?Q?FnFqRKi1gPtSVxtdRgZ/r+Tbok4+cFNZnwphOkJDyMs8p5opQ8M2ftZptozn?= =?us-ascii?Q?CU8VSfUEp3sAnG4IVdlcnHJ2UiK7GAPTyepaLsNtOOjn4Ht6qjctEo6sEFRd?= =?us-ascii?Q?dX54VnTeP+drafjvdaAUcjU0NYvk9xxpqCWrVakQd/nIsD5am0Y7z4GVtNyB?= =?us-ascii?Q?SZ5r6TbS4MY3SXjKJe+nMViP2RT7EwkylHHYNhDrDrkqjTaTiRUXR4i6SVHJ?= =?us-ascii?Q?65uxWOVft8m2shYiazsPBqkkTrQWepjU8xefllrQKRdak2fUl+vMvmkWeZro?= =?us-ascii?Q?3Xd4WflENVHIFIAe3YWXjgzrgf65L2lo7hiZzAcnnyvphC60dEoJbB3qCvi3?= =?us-ascii?Q?BUmHSfzQgF/41PYVc2PsoWU0+eZAAg1qEogHBz5vX5Fk1H1ZmChfKMeOlycf?= =?us-ascii?Q?HRtdAQvuPFR97GESg/q+cBWQhht1KRDHk7YC66LpgCqfy4ikZIAKzc4ox27h?= =?us-ascii?Q?ObdnuiLL/grSzs8syQNIFwy3rKLZj0ZVAn1oF4fxH8RLlBbK1X0kxE5KLrUq?= =?us-ascii?Q?aZqmS7S2EbMtbOCTcIJHGGkRCbwIGmm2uIt5vl6aW0WdzfAb4NGHpeiOKVF3?= =?us-ascii?Q?77aWOzYljwQ00q5euAZm+S+/6C6hM4ukryh3wAfna2ZMvXSkEGHOdJMoj5HJ?= =?us-ascii?Q?Qw=3D=3D?= MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: CO1PR11MB4929.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 0926ea6f-e3c3-4f1b-cb09-08dc84fbee6c X-MS-Exchange-CrossTenant-originalarrivaltime: 05 Jun 2024 01:07:55.1495 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: arWlcYqHfsGw+csJWcOhnF6a8WqoNr0In37ZhsjFtI98uewxw8Dqc4LyGDVGFLtOSWWfMzl9rgEKWLflS9z0lr3PKRd6mEcAxHw9o1s3snU= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN6PR11MB8104 X-OriginatorOrg: intel.com Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Resent-Date: Tue, 04 Jun 2024 18:08:01 -0700 Resent-From: michael.d.kinney@intel.com Reply-To: devel@edk2.groups.io,michael.d.kinney@intel.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: VEFMxkSfpuJW8DFc1ShLm0Csx7686176AA= Content-Language: en-US Content-Type: multipart/related; boundary="_004_CO1PR11MB49293F6F3656FC613FFAD0DCD2F92CO1PR11MB4929namp_"; type="multipart/alternative" X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20240206 header.b=IO+PcfT7; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 45.79.224.7 as permitted sender) smtp.mailfrom=bounce@groups.io; dmarc=fail reason="SPF not aligned (relaxed), DKIM not aligned (relaxed)" header.from=intel.com (policy=none) --_004_CO1PR11MB49293F6F3656FC613FFAD0DCD2F92CO1PR11MB4929namp_ Content-Type: multipart/alternative; boundary="_000_CO1PR11MB49293F6F3656FC613FFAD0DCD2F92CO1PR11MB4929namp_" --_000_CO1PR11MB49293F6F3656FC613FFAD0DCD2F92CO1PR11MB4929namp_ Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi Ray, I know this is an old topic, but I think I have a new idea that works for X= IP code. We can update loop to compare a volatile global to a volatile loc= al. This forces 2 reads and a comparison on every loop iteration. The loc= al variable can be set to 1 to exit the loop without modifying the global v= ariable. I tried this with VS2019 with max opt enabled and I was able to e= xit loop by setting Index to 1 in a debugger. diff --git a/MdePkg/Library/BaseLib/CpuDeadLoop.c b/MdePkg/Library/BaseLib/= CpuDeadLoop.c index b3b7548fa5..393c4290ed 100644 --- a/MdePkg/Library/BaseLib/CpuDeadLoop.c +++ b/MdePkg/Library/BaseLib/CpuDeadLoop.c @@ -9,6 +9,8 @@ #include #include +static volatile UINTN mDeadLoopComparator =3D 0;^M +^M /** Executes an infinite loop. @@ -26,7 +28,7 @@ CpuDeadLoop ( { volatile UINTN Index; - for (Index =3D 0; Index =3D=3D 0;) { + for (Index =3D mDeadLoopComparator; Index =3D=3D mDeadLoopComparator;) {= ^M CpuPause (); } } Mike From: Kinney, Michael D Sent: Tuesday, October 31, 2023 7:19 AM To: Ni, Ray ; Andrew (EFI) Fish ; edk2-d= evel-groups-io ; Rebecca Cran ; He= rnandez Miramontes, Jose Miguel Cc: Kinney, Michael D Subject: RE: [edk2-devel] CpuDeadLoop() is optimized by compiler Right. But if you break in with debugger, you can still skip over the jmp i= nstruction and continue. I agree XIP does not allow variable value to be updated, but we would never= want to do that or all future dead loops in non XIP code would not loop. Mike From: Ni, Ray > Sent: Tuesday, October 31, 2023 1:31 AM To: Kinney, Michael D >; Andrew (EFI) Fish >; ed= k2-devel-groups-io >; Reb= ecca Cran >; Hernandez Miramont= es, Jose Miguel > Subject: Re: [edk2-devel] CpuDeadLoop() is optimized by compiler Mike, This is not friendly for XIP code. With XIP code, the global variable is no= t able to be updated as it sits in read-only SPI flash. Thanks, Ray ________________________________ From: Kinney, Michael D > Sent: Tuesday, October 31, 2023 11:37 AM To: Ni, Ray >; Andrew (EFI) Fish = >; edk2-devel-groups-io >; Rebecca Cran >; Hernandez Miramontes, Jose Miguel > Cc: Kinney, Michael D > Subject: RE: [edk2-devel] CpuDeadLoop() is optimized by compiler Does using a static volatile global instead of a volatile local work? Mike From: Ni, Ray > Sent: Monday, October 30, 2023 7:52 PM To: Andrew (EFI) Fish >; edk2-devel= -groups-io >; Rebecca Cra= n >; Hernandez Miramontes, Jose= Miguel > Cc: Kinney, Michael D > Subject: Re: [edk2-devel] CpuDeadLoop() is optimized by compiler It's been a while. Is there any better solution? Can we go with assembly solution? Thanks, Ray ________________________________ From: Andrew (EFI) Fish > Sent: Saturday, May 20, 2023 12:31 AM To: edk2-devel-groups-io = >; Rebecca Cran > Cc: Ni, Ray >; Kinney, Michael D = > Subject: Re: [edk2-devel] CpuDeadLoop() is optimized by compiler I don't think the atomic is going to help. The compiler honored the volatil= e by doing a read, but assumed it would never change due to scoping. As you= can see in my example if the compiler thinks DeadLoopCount can be changed = it will put the check back in and assume the function can return. So an ass= embly function that does nothing called IncreaseScope() would fix this issue too. void IncreaseScope(int *ptr); void CpuDeadLoopFix(void) { volatile int DeadLoopCount =3D 0; while(DeadLoopCount =3D=3D 0) { IncreaseScope(&DeadLoopCount); } } void CpuDeadLoop(void) { volatile int DeadLoopCount =3D 0; while(DeadLoopCount =3D=3D 0); } Gives us: voltbl SEGMENT voltbl ENDS voltbl SEGMENT voltbl ENDS DeadLoopCount$ =3D 48 CpuDeadLoopFix PROC ; COMDAT $LN12: sub rsp, 40 ; 00000028H mov DWORD PTR DeadLoopCount$[rsp], 0 jmp SHORT $LN10@CpuDeadLoo $LL2@CpuDeadLoo: lea rcx, QWORD PTR DeadLoopCount$[rsp] call IncreaseScope $LN10@CpuDeadLoo: mov eax, DWORD PTR DeadLoopCount$[rsp] test eax, eax je SHORT $LL2@CpuDeadLoo add rsp, 40 ; 00000028H ret 0 CpuDeadLoopFix ENDP DeadLoopCount$ =3D 8 CpuDeadLoop PROC ; COMDAT mov DWORD PTR DeadLoopCount$[rsp], 0 $LL2@CpuDeadLoo: mov eax, DWORD PTR DeadLoopCount$[rsp] jmp SHORT $LL2@CpuDeadLoo CpuDeadLoop ENDP Compiler Explorer godbolt.org [cid:image001.png@01DAB6AA.1D74CB60] Thanks, Andrew Fish PS I'm still not 100% sure it is a compiler bug. Some times things like thi= s are due to the order the compiler applies the optimizations, and changing= the order can change the behavior. On May 19, 2023, at 8:31 AM, Rebecca Cran > wrote: Just to add more data, I also tried with "volatile sig_atomic_t" as someone= suggested and both "/volatile:iso" and "/volatile:ms" with no change in re= sults. -- Rebecca Cran On 5/18/23 20:53, Ni, Ray wrote: I think all the options we considered are workarounds. These might break ag= ain if compiler is "cleverer" in future. Unless some Cxx spec clearly guara= ntees that. I like Mike's idea to use assembly implementation for CpuDeadLoop. The asse= mbly can simply "jmp $" then "ret". I didn't find a dead-loop intrinsic function in MSVC. Any better idea? Thanks, Ray *From:* Andrew (EFI) Fish > *Sent:* Friday, May 19, 2023 8:42 AM *To:* devel@edk2.groups.io; Kinney, Michael D = > *Cc:* Ni, Ray >; Rebecca Cran > *Subject:* Re: [edk2-devel] CpuDeadLoop() is optimized by compiler Mike, Sorry static was just to scope the name to the file since it is a lib, not = to make it work. That is a cool site. I learned about it complaining about stuff to the comp= iler team on our internal clang Slack channel as they use it to answer my q= uestions. Thanks, Andrew Fish On May 18, 2023, at 2:42 PM, Michael D Kinney > wrote: Using that tool, the following fragment seems to generate the right code. Volatile is required. Static is optional. staticvolatileint mDeadLoopCount =3D0; void CpuDeadLoop( void ) { while(mDeadLoopCount =3D=3D0); } GCC =3D=3D=3D CpuDeadLoop(): .L2: moveax,DWORDPTRmDeadLoopCount[rip] testeax,eax je.L2 ret CLANG =3D=3D=3D=3D=3D CpuDeadLoop():# @CpuDeadLoop() .LBB0_1: # =3D>This Inner Loop Header:Depth=3D1 cmpdwordptr[rip+_ZL14mDeadLoopCount],0 je.LBB0_1 ret Mike *From:*Andrew (EFI) Fish > *Sent:*Thursday, May 18, 2023 1:45 PM *To:*edk2-devel-groups-io >; Andrew Fish > *Cc:*Kinney, Michael D >; Ni, Ray >; Rebecca Cran > *Subject:*Re: [edk2-devel] CpuDeadLoop() is optimized by compiler Whoops wrong compiler. Here is an update. I added the flags so this one reproduces the issue. Compiler Explorer godbolt.org Thanks, Andrew Fish On May 18, 2023, at 11:45 AM, Andrew Fish viagroups.io > wrote: Mike, This is a good way to play around with fixes, and to report bugs. You can see the assembler for different compilers with different flag. Compiler Explorer godbolt.org Sorry I'm traveling and in Cupertino with lots of meetings so I did not have time to adjust the compiler flags.... Thanks, Andrew Fish On May 18, 2023, at 10:24 AM, Andrew (EFI) Fish > wrote: Mike, I guess my other question... If this turns out to be a compiler bug should we scope the change to the broken toolchain. I'm not sure what the right answer is for that, but I want to ask the question? Thanks, Andrew Fish On May 18, 2023, at 10:19 AM, Michael D Kinney > wrote: Andrew, This might work for XIP. Set non const global to initial value that is expected value to stay in dead loop. UINTN mDeadLoopCount =3D 0; VOID CpuDeadLoop( VOID ) { while (mDeadLoopCount =3D=3D 0) { CpuPause(); } } When deadloop is entered, developer can not change value of mDeadLoopCount, but they can use debugger to force exit loop and return from function. Mike *From:*Andrew (EFI) Fish > *Sent:*Thursday, May 18, 2023 10:09 AM *To:*Kinney, Michael D > *Cc:*edk2-devel-groups-io >; Ni, Ray >; Rebecca Cra= n > *Subject:*Re: [edk2-devel] CpuDeadLoop() is optimized by compiler Mike, Good point, that is why we are using the stack .... The only other thing I can think of is to pass the address of Index to some inline assembler, or an asm no op function, to give it a side effect the compiler can't resolve. Thanks, Andrew Fish On May 18, 2023, at 10:05 AM, Kinney, Michael D > wrote: Static global will not work for XIP Mike *From:*Andrew (EFI) Fish > *Sent:*Thursday, May 18, 2023 9:49 AM *To:*edk2-devel-groups-io >; Kinney, Michael D > *Cc:*Ni, Ray >= ; Rebecca Cran > *Subject:*Re: [edk2-devel] CpuDeadLoop() is optimized by compiler Mike, I pinged some compiler experts to see if our code is correct, or if the compiler has an issue. Seems to be trending compiler issue right now, but I've NOT gotten feedback from anyone on the spec committee yet. If we move Index to a static global that would likely work around the compiler issue. Thanks, Andrew Fish On May 18, 2023, at 8:36 AM, Michael D Kinney > wrote: Hi Ray, So the code generated does deadloop, but is just not easy to resume from as we have been able to do in the past. We use CpuDeadloop() for 2 purposes. One is a terminal condition with no reason to ever continue. The 2^nd is a debug aide for developers to halt the system at a specific location and then continue from that point, usually with a debugger, to step through code to an area to evaluate unexpected behavior. We may have to do a NASM implementation of CpuDeadloop() to make sure it meets both use cases. Mike *From:*Ni, Ray > *Sent:*Thursday, May 18, 2023 3:00 AM *To:*devel@edk2.groups.io *Cc:*Kinney, Michael D >; Rebecca Cran >; Ni, R= ay > *Subject:*CpuDeadLoop() is optimized by compiler Hi, Starting from certain version of Visual Studio C compiler (I don't have the exact version. I am using VS2019), CpuDeadLoop is now optimized quite well by compiler. The optimization is so "good" that it becomes harder for developers to break out of the deadloop. I copied the assembly instructions as below for your reference. The compiler does not generate instructions that jump out of the loop when the Index is not zero. So in order to break out of the loop, developers need to: 1. Manually adjust rsp by increasing 40 2. Manually "ret" I am not sure if anyone has interest to re-write this function so that compiler can be "fooled" again. Thanks, Ray =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D ; Function compile flags: /Ogspy ; File e:\work\edk2\MdePkg\Library\BaseLib\CpuDeadLoop.c ; COMDAT CpuDeadLoop _TEXT SEGMENT Index$ =3D 48 CpuDeadLoop PROC ; COMDAT ; 26 : { $LN12: 00000 48 83 ec 28 sub rsp, 40 ; 00000028H ; 27 : volatile UINTN Index; ; 28 : ; 29 : for (Index =3D 0; Index =3D=3D 0;) { 00004 48 c7 44 24 30 00 00 00 00 mov QWORD PTR Index$[rsp], 0 $LN10@CpuDeadLoo: ; 30 : CpuPause (); 0000d 48 8b 44 24 30 mov rax, QWORD PTR Index$[rsp] 00012 e8 00 00 00 00 call CpuPause 00017 eb f4 jmp SHORT $LN10@CpuDeadLoo CpuDeadLoop ENDP _TEXT ENDS END -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#119456): https://edk2.groups.io/g/devel/message/119456 Mute This Topic: https://groups.io/mt/98987896/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- --_000_CO1PR11MB49293F6F3656FC613FFAD0DCD2F92CO1PR11MB4929namp_ Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable

Hi Ray,

 

I know this is an old topic, but I think I have a new idea that works = for XIP code.  We can update loop to compare a volatile global to a vo= latile local.  This forces 2 reads and a comparison on every loop iteration.  The local variable can be set to 1 to exit = the loop without modifying the global variable.  I tried this with VS2= 019 with max opt enabled and I was able to exit loop by setting Index to 1 = in a debugger.

 

diff --git a/MdePkg/Library/BaseLib/CpuDead= Loop.c b/MdePkg/Library/BaseLib/CpuDeadLoop.c

index b3b7548fa5..393c4290ed 100644

--- a/MdePkg/Library/BaseLib/CpuDeadLoop.c<= o:p>

+++ b/MdePkg/Library/BaseLib/CpuDeadLoop.c<= o:p>

@@ -9,6 +9,8 @@

#include <Base.h>

#include <Library/BaseLib.h>

 

+static volatile UINTN  mDeadLoopCompa= rator =3D 0;^M

+^M

/**

   Executes an infinite loop.

 

@@ -26,7 +28,7 @@ CpuDeadLoop (<= /span>

{

   volatile UINTN  Index;

 

-  for (Index =3D 0; Index =3D=3D 0;) = {

+  for (Index =3D mDeadLoopComparator;= Index =3D=3D mDeadLoopComparator;) {^M

     CpuPause ();<= /o:p>

   }

}

 

Mike

 

From: Kinney, Michael D <michael.d.kinney@= intel.com>
Sent: Tuesday, October 31, 2023 7:19 AM
To: Ni, Ray <ray.ni@intel.com>; Andrew (EFI) Fish <afish@ap= ple.com>; edk2-devel-groups-io <devel@edk2.groups.io>; Rebecca Cra= n <rebecca@bsdio.com>; Hernandez Miramontes, Jose Miguel <jose.mig= uel.hernandez.miramontes@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>
Subject: RE: [edk2-devel] CpuDeadLoop() is optimized by compiler

 

Right. But if you break in with debugger, you can st= ill skip over the jmp instruction and continue.

 

I agree XIP does not allow variable value to be upda= ted, but we would never want to do that or all future dead loops in non XIP= code would not loop.

 

Mike

 

 

Mike,

This is not friendly for XIP code. With XIP code, the glob= al variable is not able to be updated as it sits in read-only SPI flash.

 

Thanks,

Ray


From: Kinney, Michael D <michael.d.kinney@intel.com>
Sent: Tuesday, October 31, 2023 11:37 AM
To: Ni, Ray <ray.ni@intel.com= >; Andrew (EFI) Fish <afish@ap= ple.com>; edk2-devel-groups-io <devel@edk2.groups.io>; Rebecca Cran <rebecca@bsdio.com>; Hernandez Miramontes, Jose Miguel <jose.miguel.hernandez.miramontes@intel.com>= ;
Cc: Kinney, Michael D <michael.d.kinney@intel.com>
Subject: RE: [edk2-devel] CpuDeadLoop() is optimized by compiler

 

Does using a static volatile global instead of a vo= latile local work?

 

Mike

 

From: Ni, Ray <ray.ni@intel.com>
Sent: Monday, October 30, 2023 7:52 PM
To: Andrew (EFI) Fish <afish@a= pple.com>; edk2-devel-groups-io <devel@edk2.groups.io>; Rebecca Cran <rebecca@bsdio.com>; Hernandez Miramontes, Jose Miguel <jose.miguel.hernandez.miramontes@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>
Subject: Re: [edk2-devel] CpuDeadLoop() is optimized by compiler

 

It's been a while.

 

Is there any better solution? Can we go with assembly sol= ution?

 

Thanks,

Ray


From: Andrew (EFI) Fish <afish@apple.com>
Sent: Saturday, May 20, 2023 12:31 AM
To: edk2-devel-groups-io <devel@edk2.groups.io>; Rebecca Cran <rebecca@bsdio.com>
Cc: Ni, Ray <ray.ni@intel.com= >; Kinney, Michael D <michael.d.kinney@intel.com>
Subject: Re: [edk2-devel] CpuDeadLoop() is optimized by compiler

 

I don’t think the atomic is going to help. Th= e compiler honored the volatile by doing a read, but assumed it would never= change due to scoping. As you can see in my example if the compiler thinks=  DeadLoopCount can be changed it will put the check back in and assume the function can retur= n. So an assembly function that does nothing called Increase= Scope()

 would fix this issue too. 

 

 

void<= span style=3D"font-size:10.5pt;font-family:Consolas;color:black"> IncreaseS= cope(int *ptr);

 

 

void<= span style=3D"font-size:10.5pt;font-family:Consolas;color:black"> CpuDeadLo= opFix(void) {

 

volatile

int DeadLoopCo= unt =3D = 0;=

 

while= (DeadLoop= Count =3D=3D

0<= span style=3D"font-size:10.5pt;font-family:Consolas;color:black">) {=

 

IncreaseSco= pe(&DeadLoopCount);

 

}

 

}

 

 

void<= span style=3D"font-size:10.5pt;font-family:Consolas;color:black"> CpuDeadLo= op(= void) {

 

volatile

int DeadLoopCo= unt =3D = 0;=

 

while= (DeadLoop= Count =3D=3D

0<= span style=3D"font-size:10.5pt;font-family:Consolas;color:black">);<= o:p>

 

}

 

 

Gives us:

 

 

voltbl

SEGMENT

 

voltbl

ENDS<= o:p>

 

voltbl

SEGMENT

 

voltbl

ENDS<= o:p>

 

 

DeadLoopCoun= t$ =3D

48=

 

CpuDeadLoopF= ix PROC

; COMDAT

 

$LN12:

 

sub

rsp, = 40

; 00000028H=

 

mov

DWORD= PTR=

DeadLoopCoun= t$= [rsp],

0<= o:p>

 

jmp

SHORT= $LN= 10@CpuDeadLoo

 

$LL2@CpuDead= Loo:

 

lea

rcx, QWO= RD

PTR Dea= dLoopCount$[rsp]

 

call<= span style=3D"font-size:10.5pt;font-family:Consolas;color:black">

IncreaseScop= e

 

$LN10@CpuDea= dLoo:

 

mov

eax, DWO= RD

PTR Dea= dLoopCount$[rsp]

 

test<= span style=3D"font-size:10.5pt;font-family:Consolas;color:black">

eax, = eax

 

je

SHORT= $LL= 2@CpuDeadLoo

 

add

rsp, = 40

; 00000028H=

 

ret

0<= o:p>

 

CpuDeadLoopF= ix ENDP

 

 

DeadLoopCoun= t$ =3D

8<= o:p>

 

CpuDeadLoop = PROC

; COMDAT

 

mov

DWORD= PTR=

DeadLoopCoun= t$= [rsp],

0<= o:p>

 

$LL2@CpuDead= Loo:

 

mov

eax, DWO= RD

PTR Dea= dLoopCount$[rsp]

 

jmp

SHORT= $LL= 2@CpuDeadLoo

 

CpuDeadLoop = ENDP

 

 

 

 

Thanks,

 

Andrew Fish

 

PS I’m still not 100% sure it is a compiler b= ug. Some times things like this are due to the order the compiler applies t= he optimizations, and changing the order can change the behavior. 

 

 

On May 19, 2023, at 8:31 AM, Rebecca Cran <rebecca@bsdio.com> wrote:=

 

Just to add more d= ata, I also tried with "volatile sig_atomic_t" as someone suggest= ed and both "/volatile:iso" and "/volatile:ms" with no = change in results.


-- 

Rebecca Cran


On 5/18/23 20:53, Ni, Ray wrote:


I think all the options we considered are workarounds. These might break ag= ain if compiler is “cleverer” in future. Unless some Cxx spec c= learly guarantees that.

I like Mike’s idea to use assembly implementation for CpuDeadLoop. Th= e assembly can simply “jmp $” then “ret”.

I didn’t find a dead-loop intrinsic function in MSVC.

Any better idea?

Thanks,

Ray

*From:* Andrew (EFI) Fish <afish@appl= e.com>
*Sent:* Friday, May 19, 2023 8:42 AM
*To:* devel@edk2.groups.io; Kin= ney, Michael D <michael.d.= kinney@intel.com>
*Cc:* Ni, Ray <ray.ni@intel.com&= gt;; Rebecca Cran <rebecca@bsdio.co= m>
*Subject:* Re: [edk2-devel] CpuDeadLoop() is optimized by compiler

Mike,

Sorry static was just to scope the name to the file since it is a lib, not = to make it work.

That is a cool site. I learned about it complaining about stuff to the comp= iler team on our internal clang Slack channel as they use it to answer my q= uestions.

Thanks,

Andrew Fish



   On May 18, 2023, at 2:42 PM, Michael D Kinney
   <michael= .d.kinney@intel.com> wrote:

   Using that tool, the following fragment seems to generate= the
   right code. Volatile is required.  Static is optiona= l.

   staticvolatileint mDeadLoopCount =3D0;

   void

   CpuDeadLoop(

   void

     )

   {

   while(mDeadLoopCount =3D=3D0);

   }

   GCC

   =3D=3D=3D

   CpuDeadLoop():

   .L2:

   moveax,DWORDPTRmDeadLoopCount[rip]

   testeax,eax

   je.L2

   ret

   CLANG

   =3D=3D=3D=3D=3D

   CpuDeadLoop():# @CpuDeadLoop()

   .LBB0_1:              =            # =3D>This Inner Loop Header:D= epth=3D1

   cmpdwordptr[rip+_ZL14mDeadLoopCount],0

   je.LBB0_1

   ret

   Mike

   *From:*Andrew (EFI) Fish <afish@apple.com>
   *Sent:*Thursday, May 18, 2023 1:45 PM
   *To:*edk2-devel-groups-io <devel@edk2.groups.io>; Andrew Fish
   <afish@apple.com>
   *Cc:*Kinney, Michael D <
michael.d.kinney@intel.com>; Ni, Ray
   <ray.ni@intel.com<= /a>>; Rebecca Cran <rebecca@bsdi= o.com>
   *Subject:*Re: [edk2-devel] CpuDeadLoop() is optimized by = compiler

   Whoops wrong compiler. Here is an update. I added the fla= gs so
   this one reproduces the issue.

   Compiler Explorer
   <https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaP= ECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1DIApACY= AQuYukl9ZATwDKjdAGFUtAK4sGIM6SuADJ4DJgAcj4ARpjEINIADqgKhE4MHt6%2B/qRJKY4CIW= GRLDFx0naYDmlCBEzEBBk%2BfgEVVQI1dQSFEdGx8ba19Y1ZLYNdoT0lfZIAlLaoXsTI7BwA9Ks= A1AAqAJ4JmBs7C8QbaFgbCLGYpBskG7SoTOgbhhuYqqwJ9AB0JhoAgqECBsFABHLx1TAQIEbBg%= 2BGYbEwAdisAI26I2xEwBEWDFhPg2ACp8SwTABmVH/ZEAEQ4c1onAArLw/BwtKRUJw3NZrCDjst= EWYyTxSARNHS5gBrECMjT6TiSFnijmcXgKEBysVsumkOCwJBoFgJOixciUQ3G%2BhxYBcMxcPh0= AixdUQKLKqKhOo7Tgiw1sQQAeQYtG92tIWBYhmA4jD%2BCxVQAbph1WH3pUvE6fbwgZgGWHaHgo= sQvR4sMqCMQ8Cws3MqAZgAoAGp4TAAdwD%2B1ZIv4ghEYnYUhkgkUKnUYd09oMRhQPMs%2BkL6s= gc1QCXyDBTAFoA2SNhvI0sEOTqQpJTsDJLMGrc5U1y4GO5PE09MEJsVSnpcqkBMM/PbP2vujfPp= 7VaNcOiGR8shA682gYcDxiKXo4hAsYfz0BQxkApCJDmBR%2BQHUUsRWHh6SZJUw05DhVAADgANg= 3WjJA2YBkGQDZbW%2BLgNggblLGsG5cEIO5zGFG4PCNE0ThErgZl4LUtDmCADVQCSrTNCALUklA= pxtSQNDlGhaCdYgXTdMMPWYYhQ19FT/QIIMQ2VCMoxjdk4xvPAkxTdk02QDNiOzQRc2VAsixLDA= VnZCsqxrPh6ybFt207LMh2EURxEHHt5CUNRlV0AIdJnPi51CxcIGXVc0k3bdd33ZBDzJY9T3PS9= bBg28IFcND7RfRCpmQnJki/dJIN/Qa8jSLD%2BvQ9rqlQ0aZvsMDMNfbCUM6bqBk6Kb3xk%2BZF= mWPQK0wALSI4ZlSFZdlKJo%2BjGNOHT2Mkb4NBe7jeKsOcNkEogpKFe0NnEy1YkFMkzFk0VxUUp= B8CoKh1KyvsMukLKR1y/MEHVSdMdhqgCD2dg5WITHsmJhRcfx/YNTOi6rt4SjqTwOGNmbNsQduh= imJYtiOK4hMFA2Dn7uQR6pBel65KhqUZTlPNFUu5VKLVbJ5IleUODMcjrtVSHtRmOYkxMtJ4iAA= >

   godbolt.org
   <https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaP= ECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1DIApACY= AQuYukl9ZATwDKjdAGFUtAK4sGIM6SuADJ4DJgAcj4ARpjEINIADqgKhE4MHt6%2B/qRJKY4CIW= GRLDFx0naYDmlCBEzEBBk%2BfgEVVQI1dQSFEdGx8ba19Y1ZLYNdoT0lfZIAlLaoXsTI7BwA9Ks= A1AAqAJ4JmBs7C8QbaFgbCLGYpBskG7SoTOgbhhuYqqwJ9AB0JhoAgqECBsFABHLx1TAQIEbBg%= 2BGYbEwAdisAI26I2xEwBEWDFhPg2ACp8SwTABmVH/ZEAEQ4c1onAArLw/BwtKRUJw3NZrCDjst= EWYyTxSARNHS5gBrECMjT6TiSFnijmcXgKEBysVsumkOCwJBoFgJOixciUQ3G%2BhxYBcMxcPh0= AixdUQKLKqKhOo7Tgiw1sQQAeQYtG92tIWBYhmA4jD%2BCxVQAbph1WH3pUvE6fbwgZgGWHaHgo= sQvR4sMqCMQ8Cws3MqAZgAoAGp4TAAdwD%2B1ZIv4ghEYnYUhkgkUKnUYd09oMRhQPMs%2BkL6s= gc1QCXyDBTAFoA2SNhvI0sEOTqQpJTsDJLMGrc5U1y4GO5PE09MEJsVSnpcqkBMM/PbP2vujfPp= 7VaNcOiGR8shA682gYcDxiKXo4hAsYfz0BQxkApCJDmBR%2BQHUUsRWHh6SZJUw05DhVAADgANg= 3WjJA2YBkGQDZbW%2BLgNggblLGsG5cEIO5zGFG4PCNE0ThErgZl4LUtDmCADVQCSrTNCALUklA= pxtSQNDlGhaCdYgXTdMMPWYYhQ19FT/QIIMQ2VCMoxjdk4xvPAkxTdk02QDNiOzQRc2VAsixLDA= VnZCsqxrPh6ybFt207LMh2EURxEHHt5CUNRlV0AIdJnPi51CxcIGXVc0k3bdd33ZBDzJY9T3PS9= bBg28IFcND7RfRCpmQnJki/dJIN/Qa8jSLD%2BvQ9rqlQ0aZvsMDMNfbCUM6bqBk6Kb3xk%2BZF= mWPQK0wALSI4ZlSFZdlKJo%2BjGNOHT2Mkb4NBe7jeKsOcNkEogpKFe0NnEy1YkFMkzFk0VxUUp= B8CoKh1KyvsMukLKR1y/MEHVSdMdhqgCD2dg5WITHsmJhRcfx/YNTOi6rt4SjqTwOGNmbNsQduh= imJYtiOK4hMFA2Dn7uQR6pBel65KhqUZTlPNFUu5VKLVbJ5IleUODMcjrtVSHtRmOYkxMtJ4iAA= >

   

   <image001.png>
   <https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaP= ECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1DIApACY= AQuYukl9ZATwDKjdAGFUtAK4sGIM6SuADJ4DJgAcj4ARpjEINIADqgKhE4MHt6%2B/qRJKY4CIW= GRLDFx0naYDmlCBEzEBBk%2BfgEVVQI1dQSFEdGx8ba19Y1ZLYNdoT0lfZIAlLaoXsTI7BwA9Ks= A1AAqAJ4JmBs7C8QbaFgbCLGYpBskG7SoTOgbhhuYqqwJ9AB0JhoAgqECBsFABHLx1TAQIEbBg%= 2BGYbEwAdisAI26I2xEwBEWDFhPg2ACp8SwTABmVH/ZEAEQ4c1onAArLw/BwtKRUJw3NZrCDjst= EWYyTxSARNHS5gBrECMjT6TiSFnijmcXgKEBysVsumkOCwJBoFgJOixciUQ3G%2BhxYBcMxcPh0= AixdUQKLKqKhOo7Tgiw1sQQAeQYtG92tIWBYhmA4jD%2BCxVQAbph1WH3pUvE6fbwgZgGWHaHgo= sQvR4sMqCMQ8Cws3MqAZgAoAGp4TAAdwD%2B1ZIv4ghEYnYUhkgkUKnUYd09oMRhQPMs%2BkL6s= gc1QCXyDBTAFoA2SNhvI0sEOTqQpJTsDJLMGrc5U1y4GO5PE09MEJsVSnpcqkBMM/PbP2vujfPp= 7VaNcOiGR8shA682gYcDxiKXo4hAsYfz0BQxkApCJDmBR%2BQHUUsRWHh6SZJUw05DhVAADgANg= 3WjJA2YBkGQDZbW%2BLgNggblLGsG5cEIO5zGFG4PCNE0ThErgZl4LUtDmCADVQCSrTNCALUklA= pxtSQNDlGhaCdYgXTdMMPWYYhQ19FT/QIIMQ2VCMoxjdk4xvPAkxTdk02QDNiOzQRc2VAsixLDA= VnZCsqxrPh6ybFt207LMh2EURxEHHt5CUNRlV0AIdJnPi51CxcIGXVc0k3bdd33ZBDzJY9T3PS9= bBg28IFcND7RfRCpmQnJki/dJIN/Qa8jSLD%2BvQ9rqlQ0aZvsMDMNfbCUM6bqBk6Kb3xk%2BZF= mWPQK0wALSI4ZlSFZdlKJo%2BjGNOHT2Mkb4NBe7jeKsOcNkEogpKFe0NnEy1YkFMkzFk0VxUUp= B8CoKh1KyvsMukLKR1y/MEHVSdMdhqgCD2dg5WITHsmJhRcfx/YNTOi6rt4SjqTwOGNmbNsQduh= imJYtiOK4hMFA2Dn7uQR6pBel65KhqUZTlPNFUu5VKLVbJ5IleUODMcjrtVSHtRmOYkxMtJ4iAA= >

   Thanks,

   Andrew Fish




       On May 18, 2023, at 11:45 AM, And= rew Fish viagroups.io
       <http://groups.io/><afish=3Dapple.com@groups.io> wrote:

       Mike,

       This is a good way to play around= with fixes, and to report
       bugs. You can see the assembler f= or different compilers with
       different flag.

       Compiler Explorer
       <https://godbolt.org/#z:OYLghAFBqd5QC= xAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAA= UAHpwAMvAFYTStJg1DIApACYAQuYukl9ZATwDKjdAGFUtAK4sGIM6SuADJ4DJgAcj4ARpjEINIA= DqgKhE4MHt6%2B/qRJKY4CIWGRLDFx0naYDmlCBEzEBBk%2BfgEVVQI1dQSFEdGx8ba19Y1ZLYN= doT0lfZIAlLaoXsTI7BwA9KsA1AAqAJ4JmBs7C8QbaFgbCLGYpBskG7SoTOgbhhuYqqwJ9AB0Jh= oAgqECBsFABHLx1TAQIEbBg%2BGYbEwAdisAI26I2xEwBEWDFhPg2ACp8SwTABmVH/ZEAEQ4c1o= nAArLw/BwtKRUJw3NZrCDjstEWYyTxSARNHS5gBrECMjT6TiSFnijmcXgKEBysVsumkOCwJBoFg= JOixciUQ3G%2BhxYBcMxcPh0AixdUQKLKqKhOo7Tgiw1sQQAeQYtG92tIWBYhmA4jD%2BCxVQAb= ph1WH3pUvE6fbwgZgGWHaHgosQvR4sMqCMQ8Cws3MqAZgAoAGp4TAAdwD%2B1ZIv4ghEYnYUhkg= kUKnUYd09oMRhQPMs%2BkL6sgc1QCXyDBTAFoA2SNhvI0sEOTqQpJTsDJLMGrc5U1y4GO5PE09M= EJsVSnpcqkBMM/PbP2vujfPp7VaNcOiGR8shA682gYcDxiKXo4hAsYfz0BQxkApCJDmBR%2BQHU= UsRWHh6SZJUw05DhVAADgANg3WjJA2YBkGQDZbW%2BLgNggblLGsG5cEIO5zGFG4PCNE0ThErgZ= l4LUtDmCADVQCSrTNCALUklApxtSQNDlGhaCdYgXTdMMPWYYhQ19FT/QIIMQ2VCMoxjdk4xvPAk= xTdk02QDNiOzQRc2VAsixLDAVnZCsqxrPh6ybFt207LMh2EURxEHHt5CUNRlV0AIdJnPi51CxcI= GXVc0k3bdd33ZBDzJY9T3PS9bBg28IFcND7RfRCpmQnJki/dJIN/Qa8jSLD%2BvQ9rqlQ0aZvsM= DMNfbCUM6bqBk6Kb3xk%2BZFmWPQK0wALSI4ZlSFZdlKJo%2BjGNOHT2Mkb4NBe7jeKsOcNkEog= pKFe0NnEy1YkFMkzFk0VxUUpB8CoKh1KyvsMukLKR1y/MEHVSdMdhqgCD2dg5WITHsmJhRcfx/Y= NTOi6rt4SjqTwOGNmbNsQduhimJYtiOK4hMFA2Dn7uQR6pBel65KhqUZTlPNFUu5VKLVbJ5IleU= ODMcjrtVSHtRmOYkxMtJ4iAA>

       g= odbolt.org
       <https://godbolt.org/#z:OYLghAFBqd5QC= xAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAA= UAHpwAMvAFYTStJg1DIApACYAQuYukl9ZATwDKjdAGFUtAK4sGIM6SuADJ4DJgAcj4ARpjEINIA= DqgKhE4MHt6%2B/qRJKY4CIWGRLDFx0naYDmlCBEzEBBk%2BfgEVVQI1dQSFEdGx8ba19Y1ZLYN= doT0lfZIAlLaoXsTI7BwA9KsA1AAqAJ4JmBs7C8QbaFgbCLGYpBskG7SoTOgbhhuYqqwJ9AB0Jh= oAgqECBsFABHLx1TAQIEbBg%2BGYbEwAdisAI26I2xEwBEWDFhPg2ACp8SwTABmVH/ZEAEQ4c1o= nAArLw/BwtKRUJw3NZrCDjstEWYyTxSARNHS5gBrECMjT6TiSFnijmcXgKEBysVsumkOCwJBoFg= JOixciUQ3G%2BhxYBcMxcPh0AixdUQKLKqKhOo7Tgiw1sQQAeQYtG92tIWBYhmA4jD%2BCxVQAb= ph1WH3pUvE6fbwgZgGWHaHgosQvR4sMqCMQ8Cws3MqAZgAoAGp4TAAdwD%2B1ZIv4ghEYnYUhkg= kUKnUYd09oMRhQPMs%2BkL6sgc1QCXyDBTAFoA2SNhvI0sEOTqQpJTsDJLMGrc5U1y4GO5PE09M= EJsVSnpcqkBMM/PbP2vujfPp7VaNcOiGR8shA682gYcDxiKXo4hAsYfz0BQxkApCJDmBR%2BQHU= UsRWHh6SZJUw05DhVAADgANg3WjJA2YBkGQDZbW%2BLgNggblLGsG5cEIO5zGFG4PCNE0ThErgZ= l4LUtDmCADVQCSrTNCALUklApxtSQNDlGhaCdYgXTdMMPWYYhQ19FT/QIIMQ2VCMoxjdk4xvPAk= xTdk02QDNiOzQRc2VAsixLDAVnZCsqxrPh6ybFt207LMh2EURxEHHt5CUNRlV0AIdJnPi51CxcI= GXVc0k3bdd33ZBDzJY9T3PS9bBg28IFcND7RfRCpmQnJki/dJIN/Qa8jSLD%2BvQ9rqlQ0aZvsM= DMNfbCUM6bqBk6Kb3xk%2BZFmWPQK0wALSI4ZlSFZdlKJo%2BjGNOHT2Mkb4NBe7jeKsOcNkEog= pKFe0NnEy1YkFMkzFk0VxUUpB8CoKh1KyvsMukLKR1y/MEHVSdMdhqgCD2dg5WITHsmJhRcfx/Y= NTOi6rt4SjqTwOGNmbNsQduhimJYtiOK4hMFA2Dn7uQR6pBel65KhqUZTlPNFUu5VKLVbJ5IleU= ODMcjrtVSHtRmOYkxMtJ4iAA>

       =

       <favicon.png>
       <https://godbolt.org/#z:OYLghAFBqd5QC= xAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAA= UAHpwAMvAFYTStJg1DIApACYAQuYukl9ZATwDKjdAGFUtAK4sGIM6SuADJ4DJgAcj4ARpjEINIA= DqgKhE4MHt6%2B/qRJKY4CIWGRLDFx0naYDmlCBEzEBBk%2BfgEVVQI1dQSFEdGx8ba19Y1ZLYN= doT0lfZIAlLaoXsTI7BwA9KsA1AAqAJ4JmBs7C8QbaFgbCLGYpBskG7SoTOgbhhuYqqwJ9AB0Jh= oAgqECBsFABHLx1TAQIEbBg%2BGYbEwAdisAI26I2xEwBEWDFhPg2ACp8SwTABmVH/ZEAEQ4c1o= nAArLw/BwtKRUJw3NZrCDjstEWYyTxSARNHS5gBrECMjT6TiSFnijmcXgKEBysVsumkOCwJBoFg= JOixciUQ3G%2BhxYBcMxcPh0AixdUQKLKqKhOo7Tgiw1sQQAeQYtG92tIWBYhmA4jD%2BCxVQAb= ph1WH3pUvE6fbwgZgGWHaHgosQvR4sMqCMQ8Cws3MqAZgAoAGp4TAAdwD%2B1ZIv4ghEYnYUhkg= kUKnUYd09oMRhQPMs%2BkL6sgc1QCXyDBTAFoA2SNhvI0sEOTqQpJTsDJLMGrc5U1y4GO5PE09M= EJsVSnpcqkBMM/PbP2vujfPp7VaNcOiGR8shA682gYcDxiKXo4hAsYfz0BQxkApCJDmBR%2BQHU= UsRWHh6SZJUw05DhVAADgANg3WjJA2YBkGQDZbW%2BLgNggblLGsG5cEIO5zGFG4PCNE0ThErgZ= l4LUtDmCADVQCSrTNCALUklApxtSQNDlGhaCdYgXTdMMPWYYhQ19FT/QIIMQ2VCMoxjdk4xvPAk= xTdk02QDNiOzQRc2VAsixLDAVnZCsqxrPh6ybFt207LMh2EURxEHHt5CUNRlV0AIdJnPi51CxcI= GXVc0k3bdd33ZBDzJY9T3PS9bBg28IFcND7RfRCpmQnJki/dJIN/Qa8jSLD%2BvQ9rqlQ0aZvsM= DMNfbCUM6bqBk6Kb3xk%2BZFmWPQK0wALSI4ZlSFZdlKJo%2BjGNOHT2Mkb4NBe7jeKsOcNkEog= pKFe0NnEy1YkFMkzFk0VxUUpB8CoKh1KyvsMukLKR1y/MEHVSdMdhqgCD2dg5WITHsmJhRcfx/Y= NTOi6rt4SjqTwOGNmbNsQduhimJYtiOK4hMFA2Dn7uQR6pBel65KhqUZTlPNFUu5VKLVbJ5IleU= ODMcjrtVSHtRmOYkxMtJ4iAA>

       Sorry I’m traveling and in = Cupertino with lots of meetings so
       I did not have time to adjust the= compiler flags….

       Thanks,

       Andrew Fish




           On May 18= , 2023, at 10:24 AM, Andrew (EFI) Fish
           <afish@apple.com> wrote:

           Mike,

           I guess m= y other question… If this turns out to be a
           compiler = bug should we scope the change to the broken
           toolchain= . I’m not sure what the right answer is for that,
           but I wan= t to ask the question?

           Thanks,
           Andrew Fi= sh




            &nb= sp;  On May 18, 2023, at 10:19 AM, Michael D Kinney
            &nb= sp;  <michael.d.= kinney@intel.com> wrote:

            &nb= sp;  Andrew,

            &nb= sp;  This might work for XIP.  Set non const global to
            &nb= sp;  initial value that is expected value to stay in dead loop.
            &nb= sp;  UINTN  mDeadLoopCount =3D 0;

            &nb= sp;  VOID

            &nb= sp;  CpuDeadLoop(

            &nb= sp;  VOID

            &nb= sp;  )

            &nb= sp;  {

            &nb= sp;  while (mDeadLoopCount =3D=3D 0) {

            &nb= sp;      CpuPause();

            &nb= sp;  }

            &nb= sp;  }

            &nb= sp;  When deadloop is entered, developer can not change
            &nb= sp;  value of mDeadLoopCount, but they can use debugger to
            &nb= sp;  force exit loop and return from function.

            &nb= sp;  Mike

            &nb= sp;  *From:*Andrew (EFI) Fish <afish@apple.com>
            &nb= sp;  *Sent:*Thursday, May 18, 2023 10:09 AM
            &nb= sp;  *To:*Kinney, Michael D <michael.d.kinney@intel.com>
            &nb= sp;  *Cc:*edk2-devel-groups-io <devel@edk2.groups.io>; Ni,
            &nb= sp;  Ray <ray.ni@intel.com= >; Rebecca Cran <rebecca@bsd= io.com>
            &nb= sp;  *Subject:*Re: [edk2-devel] CpuDeadLoop() is optimized
            &nb= sp;  by compiler

            &nb= sp;  Mike,

            &nb= sp;  Good point, that is why we are using the stack ….

            &nb= sp;  The only other thing I can think of is to pass the
            &nb= sp;  address of Index to some inline assembler, or an asm
            &nb= sp;  no op function, to give it a side effect the compiler
            &nb= sp;  can’t resolve.

            &nb= sp;  Thanks,

            &nb= sp;  Andrew Fish





            &nb= sp;      On May 18, 2023, at 10:05 AM, Kinney= , Michael D
            &nb= sp;      <michael.d.kinney@intel.com> wrote:

            &nb= sp;      Static global will not work for XIP<= br>
            &nb= sp;      Mike

            &nb= sp;      *From:*Andrew (EFI) Fish <afish@apple.com>
            &nb= sp;      *Sent:*Thursday, May 18, 2023 9:49 A= M
            &nb= sp;      *To:*edk2-devel-groups-io <devel@edk2.groups.io>;
            &nb= sp;      Kinney, Michael D <michael.d.kinney@intel.com>
            &nb= sp;      *Cc:*Ni, Ray <ray.ni@intel.com>; Rebecca Cran
            &nb= sp;      <rebecca@bsdio.com>
            &nb= sp;      *Subject:*Re: [edk2-devel] CpuDeadLo= op() is
            &nb= sp;      optimized by compiler

            &nb= sp;      Mike,

            &nb= sp;      I pinged some compiler experts to se= e if our code
            &nb= sp;      is correct, or if the compiler has a= n issue. Seems
            &nb= sp;      to be trending compiler issue right = now, but I’ve
            &nb= sp;      NOT gotten feedback from anyone on t= he spec
            &nb= sp;      committee yet.

            &nb= sp;      If we move Index to a static global = that would
            &nb= sp;      likely work around the compiler issu= e.

            &nb= sp;      Thanks,

            &nb= sp;      Andrew Fish






            &nb= sp;          On May 18, 2= 023, at 8:36 AM, Michael D Kinney
            &nb= sp;          <michael.d.kinney@intel.com> w= rote:

            &nb= sp;          Hi Ray,

            &nb= sp;          So the code = generated does deadloop, but is
            &nb= sp;          just not eas= y to resume from as we have been
            &nb= sp;          able to do i= n the past.

            &nb= sp;          We use CpuDe= adloop() for 2 purposes.  One is a
            &nb= sp;          terminal con= dition with no reason to ever
            &nb= sp;          continue.
            &nb= sp;          The 2^nd is = a debug aide for developers to
            &nb= sp;          halt the sys= tem at a specific location and
            &nb= sp;          then continu= e from that point, usually with a
            &nb= sp;          debugger, to= step through code to an area to
            &nb= sp;          evaluate une= xpected behavior.

            &nb= sp;          We may have = to do a NASM implementation of
            &nb= sp;          CpuDeadloop(= ) to make sure it meets both use
            &nb= sp;          cases.

            &nb= sp;          Mike

            &nb= sp;          *From:*Ni, R= ay <ray.ni@intel.com>
            &nb= sp;          *Sent:*Thurs= day, May 18, 2023 3:00 AM
            &nb= sp;          *To:*devel@edk2.groups.io
            &nb= sp;          *Cc:*Kinney,= Michael D
            &nb= sp;          <michael.d.kinney@intel.com>; = Rebecca Cran
            &nb= sp;          <rebecca@bsdio.com>; Ni, Ray <ray.ni@intel.com>
            &nb= sp;          *Subject:*Cp= uDeadLoop() is optimized by compiler

            &nb= sp;          Hi,

            &nb= sp;          Starting fro= m certain version of Visual Studio
            &nb= sp;          C compiler (= I don’t have the exact version. I
            &nb= sp;          am using VS2= 019), CpuDeadLoop is now optimized
            &nb= sp;          quite well b= y compiler.

            &nb= sp;          The optimiza= tion is so “good” that it becomes
            &nb= sp;          harder for d= evelopers to break out of the
            &nb= sp;          deadloop.
            &nb= sp;          I copied the= assembly instructions as below
            &nb= sp;          for your ref= erence.

            &nb= sp;          The compiler= does not generate instructions
            &nb= sp;          that jump ou= t of the loop when the Index is
            &nb= sp;          not zero.
            &nb= sp;          So in order = to break out of the loop,
            &nb= sp;          developers n= eed to:

            &nb= sp;           1. Man= ually adjust rsp by increasing 40
            &nb= sp;           2. Man= ually “ret”

            &nb= sp;          I am not sur= e if anyone has interest to
            &nb= sp;          re-write thi= s function so that compiler can be
            &nb= sp;          “foole= d” again.

            &nb= sp;          Thanks,
            &nb= sp;          Ray

            &nb= sp;          =3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

            &nb= sp;          ; Function c= ompile flags: /Ogspy

            &nb= sp;          ; File
            &nb= sp;          e:\work\edk2= \MdePkg\Library\BaseLib\CpuDeadLoop.c

            &nb= sp;          ; COMDAT Cpu= DeadLoop

            &nb= sp;          _TEXT SEGMEN= T

            &nb= sp;          Index$ =3D 4= 8

            &nb= sp;          CpuDeadLoop = PROC ; COMDAT

            &nb= sp;          ; 26 &n= bsp; : {

            &nb= sp;          $LN12:

            &nb= sp;          00000  = 48 83 ec 28 sub rsp, 40 ; 00000028H

            &nb= sp;          ; 27 &n= bsp; : volatile UINTN  Index;

            &nb= sp;          ; 28 &n= bsp; :

            &nb= sp;          ; 29 &n= bsp; :   for (Index =3D 0; Index =3D=3D 0;) {

            &nb= sp;          00004  = 48 c7 44 24 30

            &nb= sp;          00 00 00 00 = mov      QWORD PTR Index$[rsp], 0

            &nb= sp;          $LN10@CpuDea= dLoo:

            &nb= sp;          ; 30 &n= bsp; : CpuPause ();

            &nb= sp;          0000d  = 48 8b 44 24 30 mov      rax, QWORD PTR
            &nb= sp;          Index$[rsp]<= br>
            &nb= sp;          00012  = e8 00 00 00 00 call CpuPause

            &nb= sp;          00017  = eb f4 jmp SHORT $LN10@CpuDeadLoo

            &nb= sp;          CpuDeadLoop = ENDP

            &nb= sp;          _TEXT ENDS
            &nb= sp;          END

   



 

_._,_._,_

Groups.io Links:

=20 You receive all messages sent to this group. =20 =20

View/Reply Online (#119456) | =20 | Mute = This Topic | New Topic
Your Subscriptio= n | Contact Group Owner | Unsubscribe [rebecca@openfw.io]

_._,_._,_
--_000_CO1PR11MB49293F6F3656FC613FFAD0DCD2F92CO1PR11MB4929namp_-- --_004_CO1PR11MB49293F6F3656FC613FFAD0DCD2F92CO1PR11MB4929namp_ Content-Type: image/png; name="image001.png" Content-Description: image001.png Content-Disposition: inline; filename="image001.png"; size=12765; creation-date="Wed, 05 Jun 2024 01:07:54 GMT"; modification-date="Wed, 05 Jun 2024 01:07:54 GMT" Content-ID: Content-Transfer-Encoding: base64 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 --_004_CO1PR11MB49293F6F3656FC613FFAD0DCD2F92CO1PR11MB4929namp_--