diff --git a/NuGet.config b/NuGet.config
index 0dff023e179ae1..961d774f91d772 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -10,6 +10,16 @@
     <!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
     <!--  Begin: Package sources from dotnet-emsdk -->
     <add key="darc-pub-dotnet-emsdk-2674f58" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-2674f580/nuget/v3/index.json" />
+    <add key="darc-pub-dotnet-emsdk-e92f92e" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-e92f92ef/nuget/v3/index.json" />
+    <add key="darc-pub-dotnet-emsdk-e92f92e-9" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-e92f92ef-9/nuget/v3/index.json" />
+    <add key="darc-pub-dotnet-emsdk-e92f92e-8" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-e92f92ef-8/nuget/v3/index.json" />
+    <add key="darc-pub-dotnet-emsdk-e92f92e-7" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-e92f92ef-7/nuget/v3/index.json" />
+    <add key="darc-pub-dotnet-emsdk-e92f92e-6" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-e92f92ef-6/nuget/v3/index.json" />
+    <add key="darc-pub-dotnet-emsdk-e92f92e-5" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-e92f92ef-5/nuget/v3/index.json" />
+    <add key="darc-pub-dotnet-emsdk-e92f92e-4" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-e92f92ef-4/nuget/v3/index.json" />
+    <add key="darc-pub-dotnet-emsdk-e92f92e-3" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-e92f92ef-3/nuget/v3/index.json" />
+    <add key="darc-pub-dotnet-emsdk-e92f92e-2" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-e92f92ef-2/nuget/v3/index.json" />
+    <add key="darc-pub-dotnet-emsdk-e92f92e-1" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-e92f92ef-1/nuget/v3/index.json" />
     <!--  End: Package sources from dotnet-emsdk -->
     <!--  Begin: Package sources from dotnet-sdk -->
     <!--  End: Package sources from dotnet-sdk -->
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index b02016197ce7b9..8c6dbdb2bf4f9a 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -99,14 +99,14 @@
       <Sha>2674f580a4b1d27322914df8488498065e71a3f2</Sha>
       <SourceBuild RepoName="emsdk" ManagedOnly="true" />
     </Dependency>
-    <Dependency Name="Microsoft.SourceBuild.Intermediate.source-build-reference-packages" Version="8.0.0-alpha.1.24257.2">
+    <Dependency Name="Microsoft.SourceBuild.Intermediate.source-build-reference-packages" Version="8.0.0-alpha.1.24372.3">
       <Uri>https://github.com/dotnet/source-build-reference-packages</Uri>
-      <Sha>6ed73280a6d70f7e7ac39c86f2abe8c10983f0bb</Sha>
+      <Sha>30ed464acd37779c64e9dc652d4460543ebf9966</Sha>
       <SourceBuild RepoName="source-build-reference-packages" ManagedOnly="true" />
     </Dependency>
-    <Dependency Name="Microsoft.SourceBuild.Intermediate.source-build-externals" Version="8.0.0-alpha.1.24269.1">
+    <Dependency Name="Microsoft.SourceBuild.Intermediate.source-build-externals" Version="8.0.0-alpha.1.24379.1">
       <Uri>https://github.com/dotnet/source-build-externals</Uri>
-      <Sha>4f2151df120194f0268944f1b723c14820738fc8</Sha>
+      <Sha>fb970eccb0a9cae3092464e29cbabda0d4115049</Sha>
       <SourceBuild RepoName="source-build-externals" ManagedOnly="true" />
     </Dependency>
   </ProductDependencies>
@@ -185,57 +185,57 @@
       <Uri>https://github.com/dotnet/arcade</Uri>
       <Sha>c9efa535175049eb9cba06cae1f8c3d5dbe768a9</Sha>
     </Dependency>
-    <Dependency Name="System.ComponentModel.TypeConverter.TestData" Version="8.0.0-beta.24270.1">
+    <Dependency Name="System.ComponentModel.TypeConverter.TestData" Version="8.0.0-beta.24362.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>20ef600733c107d19f57de4955dfb025d39b99e3</Sha>
+      <Sha>50994571d2f8b4b689c7a0b96c96356fc444b406</Sha>
     </Dependency>
-    <Dependency Name="System.Data.Common.TestData" Version="8.0.0-beta.24270.1">
+    <Dependency Name="System.Data.Common.TestData" Version="8.0.0-beta.24362.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>20ef600733c107d19f57de4955dfb025d39b99e3</Sha>
+      <Sha>50994571d2f8b4b689c7a0b96c96356fc444b406</Sha>
     </Dependency>
-    <Dependency Name="System.Drawing.Common.TestData" Version="8.0.0-beta.24270.1">
+    <Dependency Name="System.Drawing.Common.TestData" Version="8.0.0-beta.24362.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>20ef600733c107d19f57de4955dfb025d39b99e3</Sha>
+      <Sha>50994571d2f8b4b689c7a0b96c96356fc444b406</Sha>
     </Dependency>
-    <Dependency Name="System.Formats.Tar.TestData" Version="8.0.0-beta.24270.1">
+    <Dependency Name="System.Formats.Tar.TestData" Version="8.0.0-beta.24362.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>20ef600733c107d19f57de4955dfb025d39b99e3</Sha>
+      <Sha>50994571d2f8b4b689c7a0b96c96356fc444b406</Sha>
     </Dependency>
-    <Dependency Name="System.IO.Compression.TestData" Version="8.0.0-beta.24270.1">
+    <Dependency Name="System.IO.Compression.TestData" Version="8.0.0-beta.24362.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>20ef600733c107d19f57de4955dfb025d39b99e3</Sha>
+      <Sha>50994571d2f8b4b689c7a0b96c96356fc444b406</Sha>
     </Dependency>
-    <Dependency Name="System.IO.Packaging.TestData" Version="8.0.0-beta.24270.1">
+    <Dependency Name="System.IO.Packaging.TestData" Version="8.0.0-beta.24362.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>20ef600733c107d19f57de4955dfb025d39b99e3</Sha>
+      <Sha>50994571d2f8b4b689c7a0b96c96356fc444b406</Sha>
     </Dependency>
-    <Dependency Name="System.Net.TestData" Version="8.0.0-beta.24270.1">
+    <Dependency Name="System.Net.TestData" Version="8.0.0-beta.24362.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>20ef600733c107d19f57de4955dfb025d39b99e3</Sha>
+      <Sha>50994571d2f8b4b689c7a0b96c96356fc444b406</Sha>
     </Dependency>
-    <Dependency Name="System.Private.Runtime.UnicodeData" Version="8.0.0-beta.24270.1">
+    <Dependency Name="System.Private.Runtime.UnicodeData" Version="8.0.0-beta.24362.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>20ef600733c107d19f57de4955dfb025d39b99e3</Sha>
+      <Sha>50994571d2f8b4b689c7a0b96c96356fc444b406</Sha>
     </Dependency>
-    <Dependency Name="System.Runtime.TimeZoneData" Version="8.0.0-beta.24270.1">
+    <Dependency Name="System.Runtime.TimeZoneData" Version="8.0.0-beta.24362.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>20ef600733c107d19f57de4955dfb025d39b99e3</Sha>
+      <Sha>50994571d2f8b4b689c7a0b96c96356fc444b406</Sha>
     </Dependency>
-    <Dependency Name="System.Security.Cryptography.X509Certificates.TestData" Version="8.0.0-beta.24270.1">
+    <Dependency Name="System.Security.Cryptography.X509Certificates.TestData" Version="8.0.0-beta.24362.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>20ef600733c107d19f57de4955dfb025d39b99e3</Sha>
+      <Sha>50994571d2f8b4b689c7a0b96c96356fc444b406</Sha>
     </Dependency>
-    <Dependency Name="System.Text.RegularExpressions.TestData" Version="8.0.0-beta.24270.1">
+    <Dependency Name="System.Text.RegularExpressions.TestData" Version="8.0.0-beta.24362.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>20ef600733c107d19f57de4955dfb025d39b99e3</Sha>
+      <Sha>50994571d2f8b4b689c7a0b96c96356fc444b406</Sha>
     </Dependency>
-    <Dependency Name="System.Windows.Extensions.TestData" Version="8.0.0-beta.24270.1">
+    <Dependency Name="System.Windows.Extensions.TestData" Version="8.0.0-beta.24362.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>20ef600733c107d19f57de4955dfb025d39b99e3</Sha>
+      <Sha>50994571d2f8b4b689c7a0b96c96356fc444b406</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.DotNet.CilStrip.Sources" Version="8.0.0-beta.24270.1">
+    <Dependency Name="Microsoft.DotNet.CilStrip.Sources" Version="8.0.0-beta.24362.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>20ef600733c107d19f57de4955dfb025d39b99e3</Sha>
+      <Sha>50994571d2f8b4b689c7a0b96c96356fc444b406</Sha>
     </Dependency>
     <Dependency Name="runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk" Version="16.0.5-alpha.1.23566.1" CoherentParentDependency="Microsoft.NET.Workload.Emscripten.Current.Manifest-8.0.100">
       <Uri>https://github.com/dotnet/llvm-project</Uri>
@@ -354,13 +354,13 @@
       <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-optimization</Uri>
       <Sha>67613417f5e1af250e6ddfba79f8f2885d8e90fb</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.DotNet.HotReload.Utils.Generator.BuildTool" Version="8.0.0-alpha.0.24365.1">
+    <Dependency Name="Microsoft.DotNet.HotReload.Utils.Generator.BuildTool" Version="8.0.0-alpha.0.24402.1">
       <Uri>https://github.com/dotnet/hotreload-utils</Uri>
-      <Sha>9fd9805b21b21e16d1c81f0ffabd6ee81fe3e8a2</Sha>
+      <Sha>907017dae648b642c122f9a34573bd88ea0d9730</Sha>
     </Dependency>
-    <Dependency Name="System.Runtime.Numerics.TestData" Version="8.0.0-beta.24270.1">
+    <Dependency Name="System.Runtime.Numerics.TestData" Version="8.0.0-beta.24362.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>20ef600733c107d19f57de4955dfb025d39b99e3</Sha>
+      <Sha>50994571d2f8b4b689c7a0b96c96356fc444b406</Sha>
     </Dependency>
     <Dependency Name="Microsoft.Net.Compilers.Toolset" Version="4.8.0-7.23566.2">
       <Uri>https://github.com/dotnet/roslyn</Uri>
diff --git a/eng/Versions.props b/eng/Versions.props
index c8639af14c99a7..195b4176144e2d 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -145,20 +145,20 @@
     <SystemValueTupleVersion>4.5.0</SystemValueTupleVersion>
     <runtimenativeSystemIOPortsVersion>8.0.0-rc.1.23406.6</runtimenativeSystemIOPortsVersion>
     <!-- Runtime-Assets dependencies -->
-    <SystemRuntimeNumericsTestDataVersion>8.0.0-beta.24270.1</SystemRuntimeNumericsTestDataVersion>
-    <SystemComponentModelTypeConverterTestDataVersion>8.0.0-beta.24270.1</SystemComponentModelTypeConverterTestDataVersion>
-    <SystemDataCommonTestDataVersion>8.0.0-beta.24270.1</SystemDataCommonTestDataVersion>
-    <SystemDrawingCommonTestDataVersion>8.0.0-beta.24270.1</SystemDrawingCommonTestDataVersion>
-    <SystemFormatsTarTestDataVersion>8.0.0-beta.24270.1</SystemFormatsTarTestDataVersion>
-    <SystemIOCompressionTestDataVersion>8.0.0-beta.24270.1</SystemIOCompressionTestDataVersion>
-    <SystemIOPackagingTestDataVersion>8.0.0-beta.24270.1</SystemIOPackagingTestDataVersion>
-    <SystemNetTestDataVersion>8.0.0-beta.24270.1</SystemNetTestDataVersion>
-    <SystemPrivateRuntimeUnicodeDataVersion>8.0.0-beta.24270.1</SystemPrivateRuntimeUnicodeDataVersion>
-    <SystemRuntimeTimeZoneDataVersion>8.0.0-beta.24270.1</SystemRuntimeTimeZoneDataVersion>
-    <SystemSecurityCryptographyX509CertificatesTestDataVersion>8.0.0-beta.24270.1</SystemSecurityCryptographyX509CertificatesTestDataVersion>
-    <SystemTextRegularExpressionsTestDataVersion>8.0.0-beta.24270.1</SystemTextRegularExpressionsTestDataVersion>
-    <SystemWindowsExtensionsTestDataVersion>8.0.0-beta.24270.1</SystemWindowsExtensionsTestDataVersion>
-    <MicrosoftDotNetCilStripSourcesVersion>8.0.0-beta.24270.1</MicrosoftDotNetCilStripSourcesVersion>
+    <SystemRuntimeNumericsTestDataVersion>8.0.0-beta.24362.2</SystemRuntimeNumericsTestDataVersion>
+    <SystemComponentModelTypeConverterTestDataVersion>8.0.0-beta.24362.2</SystemComponentModelTypeConverterTestDataVersion>
+    <SystemDataCommonTestDataVersion>8.0.0-beta.24362.2</SystemDataCommonTestDataVersion>
+    <SystemDrawingCommonTestDataVersion>8.0.0-beta.24362.2</SystemDrawingCommonTestDataVersion>
+    <SystemFormatsTarTestDataVersion>8.0.0-beta.24362.2</SystemFormatsTarTestDataVersion>
+    <SystemIOCompressionTestDataVersion>8.0.0-beta.24362.2</SystemIOCompressionTestDataVersion>
+    <SystemIOPackagingTestDataVersion>8.0.0-beta.24362.2</SystemIOPackagingTestDataVersion>
+    <SystemNetTestDataVersion>8.0.0-beta.24362.2</SystemNetTestDataVersion>
+    <SystemPrivateRuntimeUnicodeDataVersion>8.0.0-beta.24362.2</SystemPrivateRuntimeUnicodeDataVersion>
+    <SystemRuntimeTimeZoneDataVersion>8.0.0-beta.24362.2</SystemRuntimeTimeZoneDataVersion>
+    <SystemSecurityCryptographyX509CertificatesTestDataVersion>8.0.0-beta.24362.2</SystemSecurityCryptographyX509CertificatesTestDataVersion>
+    <SystemTextRegularExpressionsTestDataVersion>8.0.0-beta.24362.2</SystemTextRegularExpressionsTestDataVersion>
+    <SystemWindowsExtensionsTestDataVersion>8.0.0-beta.24362.2</SystemWindowsExtensionsTestDataVersion>
+    <MicrosoftDotNetCilStripSourcesVersion>8.0.0-beta.24362.2</MicrosoftDotNetCilStripSourcesVersion>
     <!-- dotnet-optimization dependencies -->
     <optimizationwindows_ntx64MIBCRuntimeVersion>1.0.0-prerelease.23566.3</optimizationwindows_ntx64MIBCRuntimeVersion>
     <optimizationwindows_ntx86MIBCRuntimeVersion>1.0.0-prerelease.23566.3</optimizationwindows_ntx86MIBCRuntimeVersion>
@@ -188,7 +188,7 @@
     <MicrosoftDotNetXHarnessTestRunnersCommonVersion>8.0.0-prerelease.24229.2</MicrosoftDotNetXHarnessTestRunnersCommonVersion>
     <MicrosoftDotNetXHarnessTestRunnersXunitVersion>8.0.0-prerelease.24229.2</MicrosoftDotNetXHarnessTestRunnersXunitVersion>
     <MicrosoftDotNetXHarnessCLIVersion>8.0.0-prerelease.24229.2</MicrosoftDotNetXHarnessCLIVersion>
-    <MicrosoftDotNetHotReloadUtilsGeneratorBuildToolVersion>8.0.0-alpha.0.24365.1</MicrosoftDotNetHotReloadUtilsGeneratorBuildToolVersion>
+    <MicrosoftDotNetHotReloadUtilsGeneratorBuildToolVersion>8.0.0-alpha.0.24402.1</MicrosoftDotNetHotReloadUtilsGeneratorBuildToolVersion>
     <XUnitVersion>2.4.2</XUnitVersion>
     <XUnitAnalyzersVersion>1.0.0</XUnitAnalyzersVersion>
     <XUnitRunnerVisualStudioVersion>2.4.5</XUnitRunnerVisualStudioVersion>
diff --git a/eng/pipelines/coreclr/templates/helix-queues-setup.yml b/eng/pipelines/coreclr/templates/helix-queues-setup.yml
index 378396bc323a37..8f1d99396b4633 100644
--- a/eng/pipelines/coreclr/templates/helix-queues-setup.yml
+++ b/eng/pipelines/coreclr/templates/helix-queues-setup.yml
@@ -48,7 +48,7 @@ jobs:
 
     # Android x64
     - ${{ if in(parameters.platform, 'android_x64') }}:
-      - Ubuntu.1804.Amd64.Android.29.Open
+      - Ubuntu.2004.Amd64.Android.29.Open
 
     # Browser wasm
     - ${{ if eq(parameters.platform, 'browser_wasm') }}:
@@ -74,28 +74,28 @@ jobs:
       - ${{ if eq(variables['System.TeamProject'], 'public') }}:
         - (Ubuntu.2204.Arm64.Open)Ubuntu.2204.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-arm64v8
       - ${{ if eq(variables['System.TeamProject'], 'internal') }}:
-        - (Ubuntu.1804.Arm64)Ubuntu.2204.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8
+        - (Ubuntu.2204.Arm64)Ubuntu.2204.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-arm64v8
 
     # Linux musl x64
     - ${{ if eq(parameters.platform, 'linux_musl_x64') }}:
       - ${{ if eq(variables['System.TeamProject'], 'public') }}:
-        - (Alpine.317.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.17-helix-amd64
+        - (Alpine.318.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.18-helix-amd64
       - ${{ if eq(variables['System.TeamProject'], 'internal') }}:
-        - (Alpine.319.Amd64)Ubuntu.2204.Amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.19-helix-amd64
+        - (Alpine.318.Amd64)Ubuntu.2204.Amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.18-helix-amd64
 
     # Linux musl arm32
     - ${{ if eq(parameters.platform, 'linux_musl_arm') }}:
       - ${{ if eq(variables['System.TeamProject'], 'public') }}:
-        - (Alpine.317.Arm32.Open)Ubuntu.2204.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.17-helix-arm32v7
+        - (Alpine.318.Arm32.Open)Ubuntu.2204.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.18-helix-arm32v7
       - ${{ if eq(variables['System.TeamProject'], 'internal') }}:
-        - (Alpine.319.Arm32)Ubuntu.2204.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.19-helix-arm32v7
+        - (Alpine.318.Arm32)Ubuntu.2204.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.18-helix-arm32v7
 
     # Linux musl arm64
     - ${{ if eq(parameters.platform, 'linux_musl_arm64') }}:
       - ${{ if eq(variables['System.TeamProject'], 'public') }}:
-        - (Alpine.317.Arm64.Open)Ubuntu.2204.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.17-helix-arm64v8
+        - (Alpine.318.Arm64.Open)Ubuntu.2204.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.18-helix-arm64v8
       - ${{ if eq(variables['System.TeamProject'], 'internal') }}:
-        - (Alpine.319.Arm64)Ubuntu.2204.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.19-helix-arm64v8
+        - (Alpine.318.Arm64)Ubuntu.2204.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.18-helix-arm64v8
 
     # Linux x64
     - ${{ if eq(parameters.platform, 'linux_x64') }}:
diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-other.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-other.yml
index e2e95c6bac5739..d394fc82871076 100644
--- a/eng/pipelines/extra-platforms/runtime-extra-platforms-other.yml
+++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-other.yml
@@ -93,7 +93,7 @@ jobs:
       testGroup: innerloop
       isSingleFile: true
       nameSuffix: NativeAOT_Libs
-      buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) /p:TestNativeAot=true /p:ArchiveTests=true
+      buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) /p:TestNativeAot=true /p:ArchiveTests=true /p:IlcUseServerGc=false
       timeoutInMinutes: 300 # doesn't normally take this long, but I've seen Helix queues backed up for 160 minutes
       # extra steps, run tests
       extraStepsTemplate: /eng/pipelines/libraries/helix.yml
@@ -122,7 +122,7 @@ jobs:
       testGroup: innerloop
       isSingleFile: true
       nameSuffix: NativeAOT_Checked_Libs
-      buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true
+      buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:IlcUseServerGc=false
       timeoutInMinutes: 360
       # extra steps, run tests
       extraStepsTemplate: /eng/pipelines/libraries/helix.yml
@@ -151,7 +151,7 @@ jobs:
       testGroup: innerloop
       isSingleFile: true
       nameSuffix: NativeAOT_Checked_Libs_SizeOpt
-      buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:OptimizationPreference=Size
+      buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:OptimizationPreference=Size /p:IlcUseServerGc=false
       timeoutInMinutes: 240
       # extra steps, run tests
       extraStepsTemplate: /eng/pipelines/libraries/helix.yml
@@ -180,7 +180,7 @@ jobs:
       testGroup: innerloop
       isSingleFile: true
       nameSuffix: NativeAOT_Checked_Libs_SpeedOpt
-      buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:OptimizationPreference=Speed
+      buildArgs: -s clr.aot+host.native+libs+libs.tests -c $(_BuildConfig) -rc Checked /p:TestNativeAot=true /p:ArchiveTests=true /p:OptimizationPreference=Speed /p:IlcUseServerGc=false
       timeoutInMinutes: 240
       # extra steps, run tests
       extraStepsTemplate: /eng/pipelines/libraries/helix.yml
diff --git a/eng/pipelines/libraries/enterprise/linux.yml b/eng/pipelines/libraries/enterprise/linux.yml
index ccfda9fcaebe40..40552c1a0e18f8 100644
--- a/eng/pipelines/libraries/enterprise/linux.yml
+++ b/eng/pipelines/libraries/enterprise/linux.yml
@@ -39,7 +39,7 @@ extends:
         timeoutInMinutes: 120
         pool:
           name: $(DncEngPublicBuildPool)
-          demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open
+          demands: ImageOverride -equals Build.Ubuntu.2204.Amd64.Open
         steps:
         - bash: |
             cd $(enterpriseTestsSetup)
diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml
index d3d7e7b2e64f8e..dcfa5a119db388 100644
--- a/eng/pipelines/libraries/helix-queues-setup.yml
+++ b/eng/pipelines/libraries/helix-queues-setup.yml
@@ -28,7 +28,7 @@ jobs:
     # Linux arm
     - ${{ if eq(parameters.platform, 'linux_arm') }}:
       - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
-        - (Debian.11.Arm32.Open)Ubuntu.2204.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7
+        - (Debian.12.Arm32.Open)Ubuntu.2204.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7
 
     # Linux armv6
     - ${{ if eq(parameters.platform, 'linux_armv6') }}:
@@ -42,18 +42,18 @@ jobs:
       - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
         - (Ubuntu.1804.Arm64.Open)Ubuntu.2204.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8
       - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
-        - (Debian.11.Arm64.Open)Ubuntu.2204.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm64v8
+        - (Debian.12.Arm64.Open)Ubuntu.2204.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm64v8
 
     # Linux musl x64
     - ${{ if eq(parameters.platform, 'linux_musl_x64') }}:
       - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
-        - (Alpine.317.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.17-helix-amd64
+        - (Alpine.318.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.18-helix-amd64
       - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
-        - (Alpine.319.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.19-helix-amd64
+        - (Alpine.318.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.18-helix-amd64
 
     # Linux musl arm64
     - ${{ if and(eq(parameters.platform, 'linux_musl_arm64'), or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true))) }}:
-      - (Alpine.317.Arm64.Open)ubuntu.2204.armarch.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.17-helix-arm64v8
+      - (Alpine.318.Arm64.Open)ubuntu.2204.armarch.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.18-helix-arm64v8
       - (Alpine.319.Arm64.Open)ubuntu.2204.armarch.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.19-helix-arm64v8
 
     # Linux x64
@@ -64,22 +64,22 @@ jobs:
           - (Centos.9.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream9-helix
           - (Fedora.39.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-39-helix
           - (Ubuntu.2204.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-amd64
-          - (Debian.11.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64
+          - (Debian.12.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-amd64
         - ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}:
           - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
             - SLES.15.Amd64.Open
             - (Fedora.39.Amd64.Open)Ubuntu.2204.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-39-helix
             - Ubuntu.2204.Amd64.Open
-            - (Debian.11.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64
+            - (Debian.12.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-amd64
             - (Mariner.2.0.Amd64.Open)Ubuntu.2204.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-helix-amd64
             - (openSUSE.15.2.Amd64.Open)Ubuntu.2204.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:opensuse-15.2-helix-amd64
           - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
             - (Centos.9.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream9-helix
-            - (Debian.11.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64
-            - Ubuntu.1804.Amd64.Open
+            - (Debian.12.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-amd64
+            - Ubuntu.2004.Amd64.Open
       - ${{ if or(eq(parameters.jobParameters.interpreter, 'true'), eq(parameters.jobParameters.isSingleFile, true)) }}:
         # Limiting interp runs as we don't need as much coverage.
-        - (Debian.11.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64
+        - (Debian.12.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-amd64
 
     # Linux s390x
     - ${{ if eq(parameters.platform, 'linux_s390x') }}:
@@ -99,7 +99,7 @@ jobs:
 
     # Android
     - ${{ if in(parameters.platform, 'android_x86', 'android_x64', 'linux_bionic_x64') }}:
-      - Ubuntu.1804.Amd64.Android.29.Open
+      - Ubuntu.2004.Amd64.Android.29.Open
     - ${{ if in(parameters.platform, 'android_arm', 'android_arm64', 'linux_bionic_arm64') }}:
       - Windows.11.Amd64.Android.Open
 
@@ -175,11 +175,11 @@ jobs:
 
     # Browser WebAssembly
     - ${{ if eq(parameters.platform, 'browser_wasm') }}:
-      - (Ubuntu.1804.Amd64)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-webassembly
+      - (Ubuntu.2204.Amd64)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-webassembly
 
     # Browser WebAssembly Firefox
     - ${{ if eq(parameters.platform, 'browser_wasm_firefox') }}:
-      - (Ubuntu.1804.Amd64)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-webassembly
+      - (Ubuntu.2204.Amd64)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-webassembly
 
     # Browser WebAssembly windows
     - ${{ if in(parameters.platform, 'browser_wasm_win', 'wasi_wasm_win') }}:
diff --git a/eng/pipelines/libraries/stress/http.yml b/eng/pipelines/libraries/stress/http.yml
index 68bfcef6c50812..f29a41fcd0a7e9 100644
--- a/eng/pipelines/libraries/stress/http.yml
+++ b/eng/pipelines/libraries/stress/http.yml
@@ -38,7 +38,7 @@ extends:
           DUMPS_SHARE_MOUNT_ROOT: "/dumps-share"
         pool:
           name: $(DncEngPublicBuildPool)
-          demands: ImageOverride -equals 1es-ubuntu-1804-open
+          demands: ImageOverride -equals 1es-ubuntu-2204-open
 
         steps:
         - checkout: self
diff --git a/eng/pipelines/libraries/stress/ssl.yml b/eng/pipelines/libraries/stress/ssl.yml
index a70a18e828f04d..1e8cddf228bcb1 100644
--- a/eng/pipelines/libraries/stress/ssl.yml
+++ b/eng/pipelines/libraries/stress/ssl.yml
@@ -37,7 +37,7 @@ extends:
         timeoutInMinutes: 120
         pool:
           name: $(DncEngPublicBuildPool)
-          demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open
+          demands: ImageOverride -equals Build.Ubuntu.2204.Amd64.Open
 
         steps:
         - checkout: self
diff --git a/eng/pipelines/runtime-official.yml b/eng/pipelines/runtime-official.yml
index 7cadf6a800f675..eb3d2c79eb7e60 100644
--- a/eng/pipelines/runtime-official.yml
+++ b/eng/pipelines/runtime-official.yml
@@ -442,9 +442,9 @@ extends:
           buildConfig: release
           platforms:
           - linux_x64
-          - linux_musl_x64
+          # - linux_musl_x64
           - linux_arm64
-          - linux_musl_arm64
+          # - linux_musl_arm64
           jobParameters:
             templatePath: 'templates-official'
             buildArgs: -s mono+packs -c $(_BuildConfig)
diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt
index e16c74fe4f0750..9bb06b872bb6c9 100644
--- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt
+++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt
@@ -43,3 +43,5 @@ Wasm.Build.Tests.WasmTemplateTests
 Wasm.Build.Tests.WorkloadTests
 Wasm.Build.Tests.TestAppScenarios.ModuleConfigTests
 Wasm.Build.Tests.MT.Blazor.SimpleMultiThreadedTests
+Wasm.Build.Tests.TestAppScenarios.WasmSdkDebugLevelTests
+Wasm.Build.Tests.TestAppScenarios.WasmAppBuilderDebugLevelTests
diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets
index 4dc6b71005449b..9e0fdaf3289e6f 100644
--- a/eng/testing/tests.wasm.targets
+++ b/eng/testing/tests.wasm.targets
@@ -15,10 +15,7 @@
         But we do want to set it for Configuration=Debug .
     -->
     <WasmDebugLevel Condition="'$(Configuration)' == 'Debug' and '$(WasmDebugLevel)' == ''">-1</WasmDebugLevel>
-    <!-- We want to have WasmDebugLevel=0, but if DebuggerSupport=true then WasmApp.targets
-         *will* override it. So, set this to "reset-to-zero" here, and reset the value later
-         in targets. -->
-    <WasmDebugLevel Condition="'$(DebuggerSupport)' == 'true' and '$(ContinuousIntegrationBuild)' == 'true' and '$(WasmDebugLevel)' == ''">reset-to-zero</WasmDebugLevel>
+    <WasmDebugLevel Condition="'$(WasmDebugLevel)' == ''">0</WasmDebugLevel>
 
     <TrimMode Condition="'$(TrimMode)' == ''">full</TrimMode>
     <JsonSerializerIsReflectionEnabledByDefault Condition="'$(JsonSerializerIsReflectionEnabledByDefault)' == ''">true</JsonSerializerIsReflectionEnabledByDefault>
diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs
index dc8d8ccb4c7cca..55e42274817245 100644
--- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs
+++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs
@@ -49,7 +49,7 @@ private static unsafe void LoadInMemoryAssemblyInContextWhenSupported(IntPtr mod
         /// </summary>
         /// <param name="moduleHandle">The native module handle for the assembly.</param>
         /// <param name="assemblyPath">The path to the assembly (as a pointer to a UTF-16 C string).</param>
-        /// <param name="loadContext">Load context (currently must be IntPtr.Zero)</param>
+        /// <param name="loadContext">Load context (currently must be either IntPtr.Zero for default ALC or -1 for isolated ALC)</param>
         [UnmanagedCallersOnly]
         [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
             Justification = "The same C++/CLI feature switch applies to LoadInMemoryAssembly and this function. We rely on the warning from LoadInMemoryAssembly.")]
@@ -58,9 +58,12 @@ public static unsafe void LoadInMemoryAssemblyInContext(IntPtr moduleHandle, Int
             if (!IsSupported)
                 throw new NotSupportedException(SR.NotSupported_CppCli);
 
-            ArgumentOutOfRangeException.ThrowIfNotEqual(loadContext, IntPtr.Zero);
+            if ((loadContext != IntPtr.Zero) && (loadContext != -1))
+            {
+                throw new ArgumentOutOfRangeException(nameof(loadContext));
+            }
 
-            LoadInMemoryAssemblyInContextImpl(moduleHandle, assemblyPath, AssemblyLoadContext.Default);
+            LoadInMemoryAssemblyInContextImpl(moduleHandle, assemblyPath, (loadContext == IntPtr.Zero) ? AssemblyLoadContext.Default : null);
         }
 
         [RequiresUnreferencedCode("C++/CLI is not trim-compatible", Url = "https://aka.ms/dotnet-illink/nativehost")]
diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp
index 1cf604da8a87bc..81229e9cdab86c 100644
--- a/src/coreclr/gc/gc.cpp
+++ b/src/coreclr/gc/gc.cpp
@@ -21595,10 +21595,13 @@ int gc_heap::generation_to_condemn (int n_initial,
     }
 
 #ifdef USE_REGIONS
-    if (!try_get_new_free_region())
+    if (!check_only_p)
     {
-        dprintf (GTC_LOG, ("can't get an empty region -> full compacting"));
-        last_gc_before_oom = TRUE;
+        if (!try_get_new_free_region())
+        {
+            dprintf (GTC_LOG, ("can't get an empty region -> full compacting"));
+            last_gc_before_oom = TRUE;
+        }
     }
 #endif //USE_REGIONS
 
diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp
index 4e506b95c9746b..858f72297f6bd5 100644
--- a/src/coreclr/hosts/corerun/corerun.cpp
+++ b/src/coreclr/hosts/corerun/corerun.cpp
@@ -472,6 +472,7 @@ static void display_usage()
         W("  -p, --property - Property to pass to runtime during initialization.\n")
         W("                   If a property value contains spaces, quote the entire argument.\n")
         W("                   May be supplied multiple times. Format: <key>=<value>.\n")
+        W("  -l, --preload - path to shared library to load before loading the CLR.\n")
         W("  -d, --debug - causes corerun to wait for a debugger to attach before executing.\n")
         W("  -e, --env - path to a .env file with environment variables that corerun should set.\n")
         W("  -?, -h, --help - show this help.\n")
@@ -569,6 +570,22 @@ static bool parse_args(
             config.user_defined_keys.push_back(std::move(key));
             config.user_defined_values.push_back(std::move(value));
         }
+        else if (pal::strcmp(option, W("l")) == 0 || (pal::strcmp(option, W("preload")) == 0))
+        {
+            i++;
+            if (i >= argc)
+            {
+                pal::fprintf(stderr, W("Option %s: missing shared library path\n"), arg);
+                break;
+            }
+
+            string_t library = argv[i];
+            pal::mod_t hMod;
+            if (!pal::try_load_library(library, hMod))
+            {
+                break;
+            }
+        }
         else if (pal::strcmp(option, W("d")) == 0 || (pal::strcmp(option, W("debug")) == 0))
         {
             config.wait_to_debug = true;
diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp
index f0e51a668fe228..567d7b9dc5062f 100644
--- a/src/coreclr/hosts/corerun/corerun.hpp
+++ b/src/coreclr/hosts/corerun/corerun.hpp
@@ -224,6 +224,17 @@ namespace pal
         return hMod != nullptr;
     }
 
+    inline bool try_load_library(const pal::string_t& path, pal::mod_t& hMod)
+    {
+        hMod = (pal::mod_t)::LoadLibraryExW(path.c_str(), nullptr, 0);
+        if (hMod == nullptr)
+        {
+            pal::fprintf(stderr, W("Failed to load: '%s'. Error: 0x%08x\n"), path.c_str(), ::GetLastError());
+            return false;
+        }
+        return true;
+    }
+
     inline bool try_load_coreclr(const pal::string_t& core_root, pal::mod_t& hMod)
     {
         pal::string_t coreclr_path = core_root;
@@ -602,6 +613,18 @@ namespace pal
         return hMod != nullptr;
     }
 
+    inline bool try_load_library(const pal::string_t& path, pal::mod_t& hMod)
+    {
+        hMod = (pal::mod_t)dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
+        if (hMod == nullptr)
+        {
+            pal::fprintf(stderr, W("Failed to load: '%s'. Error: %s\n"), path.c_str(), dlerror());
+            return false;
+        }
+        return true;
+    }
+
+
     inline bool try_load_coreclr(const pal::string_t& core_root, pal::mod_t& hMod)
     {
         pal::string_t coreclr_path = core_root;
diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h
index 7b356b07443999..13962a20609056 100644
--- a/src/coreclr/inc/clrconfigvalues.h
+++ b/src/coreclr/inc/clrconfigvalues.h
@@ -342,6 +342,8 @@ CONFIG_STRING_INFO(INTERNAL_TailCallMax, W("TailCallMax"), "")
 RETAIL_CONFIG_STRING_INFO(EXTERNAL_TailCallOpt, W("TailCallOpt"), "")
 RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TailCallLoopOpt, W("TailCallLoopOpt"), 1, "Convert recursive tail calls to loops")
 RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Jit_NetFx40PInvokeStackResilience, W("NetFx40_PInvokeStackResilience"), (DWORD)-1, "Makes P/Invoke resilient against mismatched signature and calling convention (significant perf penalty).")
+RETAIL_CONFIG_DWORD_INFO(EXTERNAL_DisableOptimizedThreadStaticAccess, W("DisableOptimizedThreadStaticAccess"), (DWORD)0, "Disable the OptimizedThreadStaticAccess feature.")
+CONFIG_DWORD_INFO(EXTERNAL_AssertNotStaticTlsResolver, W("AssertNotStaticTlsResolver"), (DWORD)0, "Assert if we attempt to use the static tls resolver path.")
 
 // AltJitAssertOnNYI should be 0 on targets where JIT is under development or bring up stage, so as to facilitate fallback to main JIT on hitting a NYI.
 #if defined(TARGET_X86)
diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp
index dad1df9ffcfb76..8f3150e7e7b18e 100644
--- a/src/coreclr/jit/lowerxarch.cpp
+++ b/src/coreclr/jit/lowerxarch.cpp
@@ -8292,7 +8292,7 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* parentNode, GenTre
                 return false;
             }
 
-            return parentNode->OperIsEmbBroadcastCompatible();
+            return parentNode->OperIsEmbBroadcastCompatible() && comp->canUseEvexEncoding();
         }
 
         default:
diff --git a/src/coreclr/vm/arm64/asmhelpers.S b/src/coreclr/vm/arm64/asmhelpers.S
index 89dab80461c356..f766b9691278e0 100644
--- a/src/coreclr/vm/arm64/asmhelpers.S
+++ b/src/coreclr/vm/arm64/asmhelpers.S
@@ -1035,4 +1035,18 @@ LEAF_ENTRY GetThreadStaticsVariableOffset, _TEXT
         EPILOG_RETURN
 LEAF_END GetThreadStaticsVariableOffset, _TEXT
 // ------------------------------------------------------------------
+
+// ------------------------------------------------------------------
+// size_t GetTLSResolverAddress()
+
+// Helper to get the TLS resolver address. This will be then used to determine if we have a static or dynamic resolver.
+LEAF_ENTRY GetTLSResolverAddress, _TEXT
+        PROLOG_SAVE_REG_PAIR_INDEXED   fp, lr, -32
+        adrp    x0,     :tlsdesc:t_ThreadStatics
+        ldr     x1,     [x0, #:tlsdesc_lo12:t_ThreadStatics]
+        mov     x0, x1
+        EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 32
+        EPILOG_RETURN
+LEAF_END GetTLSResolverAddress, _TEXT
+// ------------------------------------------------------------------
 #endif // !TARGET_OSX
diff --git a/src/coreclr/vm/dllimport.cpp b/src/coreclr/vm/dllimport.cpp
index 31c4467b7982a6..a8f23fcb2ac493 100644
--- a/src/coreclr/vm/dllimport.cpp
+++ b/src/coreclr/vm/dllimport.cpp
@@ -2268,15 +2268,7 @@ DWORD NDirectStubLinker::EmitProfilerBeginTransitionCallback(ILCodeStream* pcsEm
         EmitLoadStubContext(pcsEmit, dwStubFlags);
     }
 
-    if (SF_IsForwardStub(dwStubFlags))
-    {
-        pcsEmit->EmitLDLOC(GetThreadLocalNum());
-    }
-    else
-    {
-        // we use a null pThread to indicate reverse interop
-        pcsEmit->EmitLoadNullPtr();
-    }
+    pcsEmit->EmitLDLOC(GetThreadLocalNum());
 
     // In the unmanaged delegate case, we need the "this" object to retrieve the MD
     // in StubHelpers::ProfilerEnterCallback().
diff --git a/src/coreclr/vm/eeconfig.cpp b/src/coreclr/vm/eeconfig.cpp
index 0f1de4d4fe788a..37a89224617cec 100644
--- a/src/coreclr/vm/eeconfig.cpp
+++ b/src/coreclr/vm/eeconfig.cpp
@@ -112,6 +112,7 @@ HRESULT EEConfig::Init()
     fJitFramed = false;
     fJitMinOpts = false;
     fJitEnableOptionalRelocs = false;
+    fDisableOptimizedThreadStaticAccess = false;
     fPInvokeRestoreEsp = (DWORD)-1;
 
     fNgenBindOptimizeNonGac = false;
@@ -548,6 +549,8 @@ HRESULT EEConfig::sync()
     iJitOptimizeType      =  CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_JitOptimizeType);
     if (iJitOptimizeType > OPT_RANDOM)     iJitOptimizeType = OPT_DEFAULT;
 
+    fDisableOptimizedThreadStaticAccess = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_DisableOptimizedThreadStaticAccess) != 0;
+
 #ifdef TARGET_X86
     fPInvokeRestoreEsp = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_Jit_NetFx40PInvokeStackResilience);
 #endif
diff --git a/src/coreclr/vm/eeconfig.h b/src/coreclr/vm/eeconfig.h
index 6394f1b998c0f6..3614e54320295d 100644
--- a/src/coreclr/vm/eeconfig.h
+++ b/src/coreclr/vm/eeconfig.h
@@ -77,6 +77,7 @@ class EEConfig
     bool          JitFramed(void)                           const {LIMITED_METHOD_CONTRACT;  return fJitFramed; }
     bool          JitMinOpts(void)                          const {LIMITED_METHOD_CONTRACT;  return fJitMinOpts; }
     bool          JitEnableOptionalRelocs(void)             const {LIMITED_METHOD_CONTRACT;  return fJitEnableOptionalRelocs; }
+    bool          DisableOptimizedThreadStaticAccess(void)  const {LIMITED_METHOD_CONTRACT;  return fDisableOptimizedThreadStaticAccess; }
 
     // Tiered Compilation config
 #if defined(FEATURE_TIERED_COMPILATION)
@@ -480,6 +481,7 @@ class EEConfig
     bool fJitFramed;                   // Enable/Disable EBP based frames
     bool fJitMinOpts;                  // Enable MinOpts for all jitted methods
     bool fJitEnableOptionalRelocs;     // Allow optional relocs
+    bool fDisableOptimizedThreadStaticAccess; // Disable OptimizedThreadStatic access
 
     unsigned iJitOptimizeType; // 0=Blended,1=SmallCode,2=FastCode,              default is 0=Blended
 
diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp
index 9fe9376fd58efa..6d8e3a426bbaab 100644
--- a/src/coreclr/vm/excep.cpp
+++ b/src/coreclr/vm/excep.cpp
@@ -5336,6 +5336,10 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers,
     FlushLogging();     // Flush any logging output
     GCPROTECT_END();
 
+#ifdef HOST_WINDOWS
+    CreateCrashDumpIfEnabled();
+#endif
+
 #ifdef _DEBUG
     // Do not care about lock check for unhandled exception.
     while (unbreakableLockCount)
diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp
index 67e127bf91ea62..01ab9aae94463a 100644
--- a/src/coreclr/vm/jitinterface.cpp
+++ b/src/coreclr/vm/jitinterface.cpp
@@ -1463,6 +1463,10 @@ void CEEInfo::getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO*
     EE_TO_JIT_TRANSITION_LEAF();
 }
 
+#if !defined(TARGET_OSX) && defined(TARGET_UNIX) && defined(TARGET_ARM64)
+extern "C" size_t GetTLSResolverAddress();
+#endif // !TARGET_OSX && TARGET_UNIX && TARGET_ARM64
+
 /*********************************************************************/
 void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
                             CORINFO_METHOD_HANDLE  callerHandle,
@@ -1567,14 +1571,46 @@ void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
                 fieldAccessor = CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER;
 
                 pResult->helper = getSharedStaticsHelper(pField, pFieldMT);
+
+                bool optimizeThreadStaticAccess = false;
 #if defined(TARGET_ARM)
                 // Optimization is disabled for linux/windows arm
 #elif !defined(TARGET_WINDOWS) && defined(TARGET_X86)
                 // Optimization is disabled for linux/x86
 #elif defined(TARGET_LINUX_MUSL) && defined(TARGET_ARM64)
                 // Optimization is disabled for linux musl arm64
+#elif !defined(TARGET_OSX) && defined(TARGET_UNIX) && defined(TARGET_ARM64)
+                // Optimization is enabled for linux/arm64 only for static resolver.
+                // For static resolver, the TP offset is same for all threads.
+                // For dynamic resolver, TP offset returned is for the current thread and
+                // will be different for the other threads.
+                uint32_t* resolverAddress = reinterpret_cast<uint32_t*>(GetTLSResolverAddress());
+                int ip = 0;
+                if ((resolverAddress[ip] == 0xd503201f) || (resolverAddress[ip] == 0xd503241f))
+                {
+                    // nop might not be present in older resolver, so skip it.
+
+                    // nop or hint 32
+                    ip++;
+                }
+
+                if (
+                    // ldr x0, [x0, #8]
+                    (resolverAddress[ip] == 0xf9400400) &&
+                    // ret
+                    (resolverAddress[ip + 1] == 0xd65f03c0)
+                )
+                {
+                    optimizeThreadStaticAccess = true;
+#ifdef _DEBUG
+                    if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_AssertNotStaticTlsResolver) != 0)
+                    {
+                        _ASSERTE(!"Detected static resolver in use when not expected");
+                    }
+#endif
+                }
 #else
-                bool optimizeThreadStaticAccess = true;
+                optimizeThreadStaticAccess = true;
 #if !defined(TARGET_OSX) && defined(TARGET_UNIX) && defined(TARGET_AMD64)
                 // For linux/x64, check if compiled coreclr as .so file and not single file.
                 // For single file, the `tls_index` might not be accurate.
@@ -1582,6 +1618,11 @@ void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
                 optimizeThreadStaticAccess = GetTlsIndexObjectAddress() != nullptr;
 #endif // !TARGET_OSX && TARGET_UNIX && TARGET_AMD64
 
+                if (g_pConfig->DisableOptimizedThreadStaticAccess())
+                {
+                    optimizeThreadStaticAccess = false;
+                }
+
                 if (optimizeThreadStaticAccess)
                 {
                     // For windows x64/x86/arm64, linux x64/arm64/loongarch64/riscv64:
@@ -3898,8 +3939,18 @@ uint32_t CEEInfo::getClassAttribsInternal (CORINFO_CLASS_HANDLE clsHnd)
             if (pMT->IsByRefLike())
                 ret |= CORINFO_FLG_BYREF_LIKE;
 
-            if (pClass->IsUnsafeValueClass())
+            // In Reverse P/Invoke stubs, we are generating the code
+            // and we are not generating the code patterns that the GS checks
+            // are meant to catch.
+            // As a result, we can skip setting this flag.
+            // We do this as the GS checks (emitted when this flag is set)
+            // can break C++/CLI's copy-constructor semantics by missing copies.
+            if (pClass->IsUnsafeValueClass()
+                && !(m_pMethodBeingCompiled->IsILStub()
+                    && dac_cast<PTR_DynamicMethodDesc>(m_pMethodBeingCompiled)->GetILStubType() == DynamicMethodDesc::StubNativeToCLRInterop))
+            {
                 ret |= CORINFO_FLG_UNSAFE_VALUECLASS;
+            }
         }
         if (pClass->HasExplicitFieldOffsetLayout() && pClass->HasOverlaidField())
             ret |= CORINFO_FLG_OVERLAPPING_FIELDS;
diff --git a/src/coreclr/vm/readytoruninfo.cpp b/src/coreclr/vm/readytoruninfo.cpp
index e75373db8855aa..fbf49abe88a8ee 100644
--- a/src/coreclr/vm/readytoruninfo.cpp
+++ b/src/coreclr/vm/readytoruninfo.cpp
@@ -1945,7 +1945,7 @@ bool ReadyToRun_TypeGenericInfoMap::HasVariance(mdTypeDef input, bool *foundResu
 bool ReadyToRun_TypeGenericInfoMap::HasConstraints(mdTypeDef input, bool *foundResult) const
 {
     ReadyToRunTypeGenericInfo typeGenericInfo = GetTypeGenericInfo(input, foundResult);
-    return !!((uint8_t)typeGenericInfo & (uint8_t)ReadyToRunTypeGenericInfo::HasVariance);
+    return !!((uint8_t)typeGenericInfo & (uint8_t)ReadyToRunTypeGenericInfo::HasConstraints);
 }
 
 bool ReadyToRun_MethodIsGenericMap::IsGeneric(mdMethodDef input, bool *foundResult) const
diff --git a/src/coreclr/vm/stubhelpers.cpp b/src/coreclr/vm/stubhelpers.cpp
index 9988a912967cfd..2fa6aecb1c1fef 100644
--- a/src/coreclr/vm/stubhelpers.cpp
+++ b/src/coreclr/vm/stubhelpers.cpp
@@ -552,6 +552,7 @@ FCIMPL3(SIZE_T, StubHelpers::ProfilerBeginTransitionCallback, SIZE_T pSecretPara
     }
 
     {
+        _ASSERTE(pThread != nullptr);
         GCX_PREEMP_THREAD_EXISTS(pThread);
 
         ProfilerManagedToUnmanagedTransitionMD(pRealMD, COR_PRF_TRANSITION_CALL);
@@ -582,6 +583,7 @@ FCIMPL2(void, StubHelpers::ProfilerEndTransitionCallback, MethodDesc* pRealMD, T
     // and the transition requires us to set up a HMF.
     HELPER_METHOD_FRAME_BEGIN_0();
     {
+        _ASSERTE(pThread != nullptr);
         GCX_PREEMP_THREAD_EXISTS(pThread);
 
         ProfilerUnmanagedToManagedTransitionMD(pRealMD, COR_PRF_TRANSITION_RETURN);
diff --git a/src/installer/pkg/sfx/installers/dotnet-runtime-deps/dotnet-runtime-deps-debian.proj b/src/installer/pkg/sfx/installers/dotnet-runtime-deps/dotnet-runtime-deps-debian.proj
index be0713f05f7507..f48ee38a1d78c0 100644
--- a/src/installer/pkg/sfx/installers/dotnet-runtime-deps/dotnet-runtime-deps-debian.proj
+++ b/src/installer/pkg/sfx/installers/dotnet-runtime-deps/dotnet-runtime-deps-debian.proj
@@ -6,9 +6,9 @@
   <ItemGroup>
     <LinuxPackageDependency Include="libc6;libgcc1;libgssapi-krb5-2;libstdc++6;zlib1g"/>
     <LinuxPackageDependency Include="libssl1.0.0 | libssl1.0.2 | libssl1.1 | libssl3" />
-    <KnownLibIcuVersion Include="72;71;70;69;68;67;66;65;63;60;57;55;52" />
+    <KnownLibIcuVersion Include="74;72;71;70;69;68;67;66;65;63;60;57;55;52" />
     <LibIcuPackageDependency Include="libicu" Dependencies="libicu | @(KnownLibIcuVersion -> 'libicu%(Identity)', ' | ')" />
     <LinuxPackageDependency
       Include="@(LibIcuPackageDependency->Metadata('Dependencies'))" />
  </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/src/installer/tests/HostActivation.Tests/NativeHosting/Ijwhost.cs b/src/installer/tests/HostActivation.Tests/NativeHosting/Ijwhost.cs
index e7efe5eaafff84..062e6bcc58130f 100644
--- a/src/installer/tests/HostActivation.Tests/NativeHosting/Ijwhost.cs
+++ b/src/installer/tests/HostActivation.Tests/NativeHosting/Ijwhost.cs
@@ -27,7 +27,7 @@ public void LoadLibrary()
         {
             string [] args = {
                 "ijwhost",
-                sharedState.IjwLibraryPath,
+                sharedState.IjwApp.AppDll,
                 "NativeEntryPoint"
             };
             CommandResult result = sharedState.CreateNativeHostCommand(args, sharedState.RepoDirectories.BuiltDotnet)
@@ -38,6 +38,41 @@ public void LoadLibrary()
                 .And.HaveStdOutContaining("[C++/CLI] ManagedClass: AssemblyLoadContext = \"Default\" System.Runtime.Loader.DefaultAssemblyLoadContext");
         }
 
+        [Theory]
+        [InlineData(true)]
+        [InlineData(false)]
+        public void LoadLibrary_ContextConfig(bool load_isolated)
+        {
+            // make a copy of a portion of the shared state because we will modify it
+            using (var app = sharedState.IjwApp.Copy())
+            {
+                string[] args = {
+                    "ijwhost",
+                    app.AppDll,
+                    "NativeEntryPoint"
+                };
+
+                RuntimeConfig.FromFile(app.RuntimeConfigJson)
+                    .WithProperty("System.Runtime.InteropServices.CppCLI.LoadComponentInIsolatedContext", load_isolated.ToString())
+                    .Save();
+
+                CommandResult result = sharedState.CreateNativeHostCommand(args, sharedState.RepoDirectories.BuiltDotnet)
+                    .Execute();
+
+                result.Should().Pass()
+                    .And.HaveStdOutContaining("[C++/CLI] NativeEntryPoint: calling managed class");
+
+                if (load_isolated)  // Assembly should be loaded in an isolated context
+                {
+                    result.Should().HaveStdOutContaining("[C++/CLI] ManagedClass: AssemblyLoadContext = \"IsolatedComponentLoadContext");
+                }
+                else  // Assembly should be loaded in the default context
+                {
+                    result.Should().HaveStdOutContaining("[C++/CLI] ManagedClass: AssemblyLoadContext = \"Default\" System.Runtime.Loader.DefaultAssemblyLoadContext");
+                }
+            }
+        }
+
         [Theory]
         [InlineData(true)]
         [InlineData(false)]
@@ -45,7 +80,7 @@ public void ManagedHost(bool selfContained)
         {
             string [] args = {
                 "ijwhost",
-                sharedState.IjwLibraryPath,
+                sharedState.IjwApp.AppDll,
                 "NativeEntryPoint"
             };
             TestProjectFixture fixture = selfContained ? sharedState.ManagedHostFixture_SelfContained : sharedState.ManagedHostFixture_FrameworkDependent;
@@ -63,7 +98,7 @@ public void ManagedHost(bool selfContained)
 
         public class SharedTestState : SharedTestStateBase
         {
-            public string IjwLibraryPath { get; }
+            public TestApp IjwApp {get;}
 
             public TestProjectFixture ManagedHostFixture_FrameworkDependent { get; }
             public TestProjectFixture ManagedHostFixture_SelfContained { get; }
@@ -71,7 +106,7 @@ public class SharedTestState : SharedTestStateBase
             public SharedTestState()
             {
                 string folder = Path.Combine(BaseDirectory, "ijw");
-                Directory.CreateDirectory(folder);
+                IjwApp = new TestApp(folder, "ijw");
 
                 // Copy over ijwhost
                 string ijwhostName = "ijwhost.dll";
@@ -79,8 +114,7 @@ public SharedTestState()
 
                 // Copy over the C++/CLI test library
                 string ijwLibraryName = "ijw.dll";
-                IjwLibraryPath = Path.Combine(folder, ijwLibraryName);
-                File.Copy(Path.Combine(RepoDirectories.HostTestArtifacts, ijwLibraryName), IjwLibraryPath);
+                File.Copy(Path.Combine(RepoDirectories.HostTestArtifacts, ijwLibraryName), Path.Combine(folder, ijwLibraryName));
 
                 // Create a runtimeconfig.json for the C++/CLI test library
                 new RuntimeConfig(Path.Combine(folder, "ijw.runtimeconfig.json"))
diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs
index 77b80634bd0ce1..4e8659b5653b78 100644
--- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs
+++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs
@@ -217,7 +217,8 @@ internal static ArraySegment<byte> RentEncodeSubjectPublicKeyInfo(SafeEvpPKeyHan
         [LibraryImport(Libraries.CryptoNative, StringMarshalling = StringMarshalling.Utf8)]
         private static partial SafeEvpPKeyHandle CryptoNative_LoadPrivateKeyFromEngine(
             string engineName,
-            string keyName);
+            string keyName,
+            [MarshalAs(UnmanagedType.Bool)] out bool haveEngine);
 
         internal static SafeEvpPKeyHandle LoadPrivateKeyFromEngine(
             string engineName,
@@ -226,7 +227,13 @@ internal static SafeEvpPKeyHandle LoadPrivateKeyFromEngine(
             Debug.Assert(engineName is not null);
             Debug.Assert(keyName is not null);
 
-            SafeEvpPKeyHandle pkey = CryptoNative_LoadPrivateKeyFromEngine(engineName, keyName);
+            SafeEvpPKeyHandle pkey = CryptoNative_LoadPrivateKeyFromEngine(engineName, keyName, out bool haveEngine);
+
+            if (!haveEngine)
+            {
+                pkey.Dispose();
+                throw new CryptographicException(SR.Cryptography_EnginesNotSupported);
+            }
 
             if (pkey.IsInvalid)
             {
@@ -240,7 +247,8 @@ internal static SafeEvpPKeyHandle LoadPrivateKeyFromEngine(
         [LibraryImport(Libraries.CryptoNative, StringMarshalling = StringMarshalling.Utf8)]
         private static partial SafeEvpPKeyHandle CryptoNative_LoadPublicKeyFromEngine(
             string engineName,
-            string keyName);
+            string keyName,
+            [MarshalAs(UnmanagedType.Bool)] out bool haveEngine);
 
         internal static SafeEvpPKeyHandle LoadPublicKeyFromEngine(
             string engineName,
@@ -249,7 +257,13 @@ internal static SafeEvpPKeyHandle LoadPublicKeyFromEngine(
             Debug.Assert(engineName is not null);
             Debug.Assert(keyName is not null);
 
-            SafeEvpPKeyHandle pkey = CryptoNative_LoadPublicKeyFromEngine(engineName, keyName);
+            SafeEvpPKeyHandle pkey = CryptoNative_LoadPublicKeyFromEngine(engineName, keyName, out bool haveEngine);
+
+            if (!haveEngine)
+            {
+                pkey.Dispose();
+                throw new CryptographicException(SR.Cryptography_EnginesNotSupported);
+            }
 
             if (pkey.IsInvalid)
             {
diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Windows.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Windows.cs
index 1b570872d06d9f..6a166b298cd517 100644
--- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Windows.cs
+++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Windows.cs
@@ -25,6 +25,7 @@ public static partial class PlatformDetection
         public static bool IsWindows8xOrLater => IsWindowsVersionOrLater(6, 2);
         public static bool IsWindows10OrLater => IsWindowsVersionOrLater(10, 0);
         public static bool IsWindowsServer2019 => IsWindows && IsNotWindowsNanoServer && GetWindowsVersion() == 10 && GetWindowsMinorVersion() == 0 && GetWindowsBuildVersion() == 17763;
+        public static bool IsWindowsServer2022 => IsWindows && IsNotWindowsNanoServer && GetWindowsVersion() == 10 && GetWindowsMinorVersion() == 0 && GetWindowsBuildVersion() == 20348;
         public static bool IsWindowsNanoServer => IsWindows && (IsNotWindowsIoTCore && GetWindowsInstallationType().Equals("Nano Server", StringComparison.OrdinalIgnoreCase));
         public static bool IsWindowsServerCore => IsWindows && GetWindowsInstallationType().Equals("Server Core", StringComparison.OrdinalIgnoreCase);
         public static int WindowsVersion => IsWindows ? (int)GetWindowsVersion() : -1;
diff --git a/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj b/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj
index 96deaca0a27ddf..5bf9cee3c8725a 100644
--- a/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj
+++ b/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj
@@ -3,6 +3,8 @@
     <TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetCoreAppPrevious)-windows;$(NetCoreAppPrevious);$(NetCoreAppMinimum)-windows;$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <IsPackable>true</IsPackable>
+    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
+    <ServicingVersion>1</ServicingVersion>
     <PackageDescription>Provides the System.Diagnostics.EventLog class, which allows the applications to use the Windows event log service.
 
 Commonly Used Types:
diff --git a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/NativeWrapper.cs b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/NativeWrapper.cs
index e4cebc7c2e1da2..557ff992004ce0 100644
--- a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/NativeWrapper.cs
+++ b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/NativeWrapper.cs
@@ -482,7 +482,8 @@ internal static EventLogHandle EvtGetPublisherMetadataPropertyHandle(EventLogHan
         public static string EvtFormatMessage(EventLogHandle handle, uint msgId)
         {
             int bufferNeeded;
-            bool status = UnsafeNativeMethods.EvtFormatMessage(handle, EventLogHandle.Zero, msgId, 0, null, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageId, 0, null, out bufferNeeded);
+            Span<char> emptyBuffer = [ '\0' ]; // issue: https://github.com/dotnet/runtime/issues/100198
+            bool status = UnsafeNativeMethods.EvtFormatMessage(handle, EventLogHandle.Zero, msgId, 0, null, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageId, 0, emptyBuffer, out bufferNeeded);
             int error = Marshal.GetLastWin32Error();
 
             // ERROR_EVT_UNRESOLVED_VALUE_INSERT and its cousins are commonly returned for raw message text.
@@ -933,7 +934,8 @@ public static IList<object> EvtRenderBufferWithContextUserOrValues(EventLogHandl
         public static string EvtFormatMessageRenderName(EventLogHandle pmHandle, EventLogHandle eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags flag)
         {
             int bufferNeeded;
-            bool status = UnsafeNativeMethods.EvtFormatMessage(pmHandle, eventHandle, 0, 0, null, flag, 0, null, out bufferNeeded);
+            Span<char> emptyBuffer = [ '\0' ]; // issue: https://github.com/dotnet/runtime/issues/100198
+            bool status = UnsafeNativeMethods.EvtFormatMessage(pmHandle, eventHandle, 0, 0, null, flag, 0, emptyBuffer, out bufferNeeded);
             int error = Marshal.GetLastWin32Error();
 
             if (!status && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT
@@ -985,11 +987,12 @@ public static IEnumerable<string> EvtFormatMessageRenderKeywords(EventLogHandle
         {
             IntPtr buffer = IntPtr.Zero;
             int bufferNeeded;
+            Span<char> emptyBuffer = [ '\0' ]; // issue: https://github.com/dotnet/runtime/issues/100198
 
             try
             {
                 List<string> keywordsList = new List<string>();
-                bool status = UnsafeNativeMethods.EvtFormatMessageBuffer(pmHandle, eventHandle, 0, 0, IntPtr.Zero, flag, 0, IntPtr.Zero, out bufferNeeded);
+                bool status = UnsafeNativeMethods.EvtFormatMessage(pmHandle, eventHandle, 0, 0, null, flag, 0, emptyBuffer, out bufferNeeded);
                 int error = Marshal.GetLastWin32Error();
 
                 if (!status)
@@ -1071,6 +1074,7 @@ public static string EvtRenderBookmark(EventLogHandle eventHandle)
         public static string EvtFormatMessageFormatDescription(EventLogHandle handle, EventLogHandle eventHandle, string[] values)
         {
             int bufferNeeded;
+            Span<char> emptyBuffer = [ '\0' ]; // issue: https://github.com/dotnet/runtime/issues/100198
 
             UnsafeNativeMethods.EvtStringVariant[] stringVariants = new UnsafeNativeMethods.EvtStringVariant[values.Length];
             for (int i = 0; i < values.Length; i++)
@@ -1079,7 +1083,7 @@ public static string EvtFormatMessageFormatDescription(EventLogHandle handle, Ev
                 stringVariants[i].StringVal = values[i];
             }
 
-            bool status = UnsafeNativeMethods.EvtFormatMessage(handle, eventHandle, 0xffffffff, values.Length, stringVariants, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageEvent, 0, null, out bufferNeeded);
+            bool status = UnsafeNativeMethods.EvtFormatMessage(handle, eventHandle, 0xffffffff, values.Length, stringVariants, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageEvent, 0, emptyBuffer, out bufferNeeded);
             int error = Marshal.GetLastWin32Error();
 
             if (!status && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT
diff --git a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs
index 21ce94d0c423f3..ef2d1b8726e360 100644
--- a/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs
+++ b/src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/Reader/UnsafeNativeMethods.cs
@@ -762,7 +762,7 @@ internal static partial bool EvtFormatMessage(
                              EvtStringVariant[] values,
                              EvtFormatMessageFlags flags,
                              int bufferSize,
-                             [Out] char[]? buffer,
+                             Span<char> buffer,
                              out int bufferUsed);
 
         [LibraryImport(Interop.Libraries.Wevtapi, EntryPoint = "EvtFormatMessage", SetLastError = true)]
diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System.Net.Http.WinHttpHandler.csproj b/src/libraries/System.Net.Http.WinHttpHandler/src/System.Net.Http.WinHttpHandler.csproj
index 4e4b50727b7fa8..8959c43540ca16 100644
--- a/src/libraries/System.Net.Http.WinHttpHandler/src/System.Net.Http.WinHttpHandler.csproj
+++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System.Net.Http.WinHttpHandler.csproj
@@ -4,7 +4,7 @@
     <IncludeDllSafeSearchPathAttribute>true</IncludeDllSafeSearchPathAttribute>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <IsPackable>true</IsPackable>
-    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
+    <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
     <ServicingVersion>2</ServicingVersion>
     <PackageDescription>Provides a message handler for HttpClient based on the WinHTTP interface of Windows. While similar to HttpClientHandler, it provides developers more granular control over the application's HTTP communication than the HttpClientHandler.
 
diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/BidirectionStreamingTest.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/BidirectionStreamingTest.cs
index ce79f20ad4efec..540bf4152a9956 100644
--- a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/BidirectionStreamingTest.cs
+++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/BidirectionStreamingTest.cs
@@ -22,9 +22,9 @@ public BidirectionStreamingTest(ITestOutputHelper output) : base(output)
 
         // Build number suggested by the WinHttp team.
         // It can be reduced if bidirectional streaming is backported.
-        public static bool OsSupportsWinHttpBidirectionalStreaming => Environment.OSVersion.Version >= new Version(10, 0, 22357, 0);
+        public static bool OsSupportsWinHttpBidirectionalStreaming => Environment.OSVersion.Version >= new Version(10, 0, 22357, 0) || PlatformDetection.IsWindowsServer2022;
 
-        public static bool TestsEnabled => OsSupportsWinHttpBidirectionalStreaming && PlatformDetection.SupportsAlpn;
+        public static bool TestsEnabled => OsSupportsWinHttpBidirectionalStreaming && PlatformDetection.SupportsAlpn && !PlatformDetection.IsWindowsServer2022;
 
         public static bool TestsBackwardsCompatibilityEnabled => !OsSupportsWinHttpBidirectionalStreaming && PlatformDetection.SupportsAlpn;
 
diff --git a/src/libraries/System.Private.CoreLib/src/System/Int128.cs b/src/libraries/System.Private.CoreLib/src/System/Int128.cs
index fae7c1b441457b..194b2b35f2b451 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Int128.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Int128.cs
@@ -262,17 +262,12 @@ public static explicit operator Half(Int128 value)
         /// <exception cref="OverflowException"><paramref name="value" /> is not representable by <see cref="Int128" />.</exception>
         public static explicit operator checked short(Int128 value)
         {
-            if (~value._upper == 0)
-            {
-                long lower = (long)value._lower;
-                return checked((short)lower);
-            }
-
-            if (value._upper != 0)
+            long lower = (long)value._lower;
+            if ((long)value._upper != lower >> 63)
             {
                 ThrowHelper.ThrowOverflowException();
             }
-            return checked((short)value._lower);
+            return checked((short)lower);
         }
 
         /// <summary>Explicitly converts a 128-bit signed integer to a <see cref="int" /> value.</summary>
@@ -286,17 +281,12 @@ public static explicit operator checked short(Int128 value)
         /// <exception cref="OverflowException"><paramref name="value" /> is not representable by <see cref="Int128" />.</exception>
         public static explicit operator checked int(Int128 value)
         {
-            if (~value._upper == 0)
-            {
-                long lower = (long)value._lower;
-                return checked((int)lower);
-            }
-
-            if (value._upper != 0)
+            long lower = (long)value._lower;
+            if ((long)value._upper != lower >> 63)
             {
                 ThrowHelper.ThrowOverflowException();
             }
-            return checked((int)value._lower);
+            return checked((int)lower);
         }
 
         /// <summary>Explicitly converts a 128-bit signed integer to a <see cref="long" /> value.</summary>
@@ -310,17 +300,12 @@ public static explicit operator checked int(Int128 value)
         /// <exception cref="OverflowException"><paramref name="value" /> is not representable by <see cref="Int128" />.</exception>
         public static explicit operator checked long(Int128 value)
         {
-            if (~value._upper == 0)
-            {
-                long lower = (long)value._lower;
-                return lower;
-            }
-
-            if (value._upper != 0)
+            long lower = (long)value._lower;
+            if ((long)value._upper != lower >> 63)
             {
                 ThrowHelper.ThrowOverflowException();
             }
-            return checked((long)value._lower);
+            return lower;
         }
 
         /// <summary>Explicitly converts a 128-bit signed integer to a <see cref="IntPtr" /> value.</summary>
@@ -334,17 +319,12 @@ public static explicit operator checked long(Int128 value)
         /// <exception cref="OverflowException"><paramref name="value" /> is not representable by <see cref="Int128" />.</exception>
         public static explicit operator checked nint(Int128 value)
         {
-            if (~value._upper == 0)
-            {
-                long lower = (long)value._lower;
-                return checked((nint)lower);
-            }
-
-            if (value._upper != 0)
+            long lower = (long)value._lower;
+            if ((long)value._upper != lower >> 63)
             {
                 ThrowHelper.ThrowOverflowException();
             }
-            return checked((nint)value._lower);
+            return checked((nint)lower);
         }
 
         /// <summary>Explicitly converts a 128-bit signed integer to a <see cref="sbyte" /> value.</summary>
@@ -360,17 +340,12 @@ public static explicit operator checked nint(Int128 value)
         [CLSCompliant(false)]
         public static explicit operator checked sbyte(Int128 value)
         {
-            if (~value._upper == 0)
-            {
-                long lower = (long)value._lower;
-                return checked((sbyte)lower);
-            }
-
-            if (value._upper != 0)
+            long lower = (long)value._lower;
+            if ((long)value._upper != lower >> 63)
             {
                 ThrowHelper.ThrowOverflowException();
             }
-            return checked((sbyte)value._lower);
+            return checked((sbyte)lower);
         }
 
         /// <summary>Explicitly converts a 128-bit signed integer to a <see cref="float" /> value.</summary>
diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs
index 2524b4fd536066..ea0ece02e33b32 100644
--- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs
@@ -220,6 +220,10 @@ public AdjustmentRule[] GetAdjustmentRules()
             return rulesList.ToArray();
         }
 
+        private string NameLookupId =>
+                HasIanaId ? Id :
+                (_equivalentZones is not null && _equivalentZones.Count > 0 ? _equivalentZones[0].Id : (GetAlternativeId(Id, out _) ?? Id));
+
         private string? PopulateDisplayName()
         {
             if (IsUtcAlias(Id))
@@ -231,7 +235,7 @@ public AdjustmentRule[] GetAdjustmentRules()
             if (GlobalizationMode.Invariant)
                 return displayName;
 
-            GetFullValueForDisplayNameField(Id, BaseUtcOffset, ref displayName);
+            GetFullValueForDisplayNameField(NameLookupId, BaseUtcOffset, ref displayName);
 
             return displayName;
         }
@@ -245,7 +249,7 @@ public AdjustmentRule[] GetAdjustmentRules()
             if (GlobalizationMode.Invariant)
                 return standardDisplayName;
 
-            GetStandardDisplayName(Id, ref standardDisplayName);
+            GetStandardDisplayName(NameLookupId, ref standardDisplayName);
 
             return standardDisplayName;
         }
@@ -259,7 +263,7 @@ public AdjustmentRule[] GetAdjustmentRules()
             if (GlobalizationMode.Invariant)
                 return daylightDisplayName;
 
-            GetDaylightDisplayName(Id, ref daylightDisplayName);
+            GetDaylightDisplayName(NameLookupId, ref daylightDisplayName);
 
             return daylightDisplayName;
         }
diff --git a/src/libraries/System.Runtime/tests/System/Int128Tests.cs b/src/libraries/System.Runtime/tests/System/Int128Tests.cs
index 26fba082e64a83..19c8b5d593fdb9 100644
--- a/src/libraries/System.Runtime/tests/System/Int128Tests.cs
+++ b/src/libraries/System.Runtime/tests/System/Int128Tests.cs
@@ -107,6 +107,51 @@ public static void EqualsTest(Int128 i1, object obj, bool expected)
             Assert.Equal(expected, i1.Equals(obj));
         }
 
+        [Fact]
+        public static void CheckedConvertToInt64()
+        {
+            Assert.Equal(123L, checked((long)new Int128(0, 123)));
+            Assert.Equal(-123L, checked((long)(Int128)(-123)));
+            Assert.Throws<OverflowException>(() => checked((long)new Int128(1, 1)));
+            Assert.Throws<OverflowException>(() => checked((long)new Int128(ulong.MaxValue, 42)));
+        }
+
+        [Fact]
+        public static void CheckedConvertToInt32()
+        {
+            Assert.Equal(123, checked((int)new Int128(0, 123)));
+            Assert.Equal(-123, checked((int)(Int128)(-123)));
+            Assert.Throws<OverflowException>(() => checked((int)new Int128(1, 1)));
+            Assert.Throws<OverflowException>(() => checked((int)new Int128(ulong.MaxValue, 42)));
+        }
+
+        [Fact]
+        public static void CheckedConvertToInt16()
+        {
+            Assert.Equal((short)123, checked((short)new Int128(0, 123)));
+            Assert.Equal((short)(-123), checked((short)(Int128)(-123)));
+            Assert.Throws<OverflowException>(() => checked((short)new Int128(1, 1)));
+            Assert.Throws<OverflowException>(() => checked((short)new Int128(ulong.MaxValue, 42)));
+        }
+
+        [Fact]
+        public static void CheckedConvertToSByte()
+        {
+            Assert.Equal((sbyte)123, checked((sbyte)new Int128(0, 123)));
+            Assert.Equal((sbyte)(-123), checked((sbyte)(Int128)(-123)));
+            Assert.Throws<OverflowException>(() => checked((sbyte)new Int128(1, 1)));
+            Assert.Throws<OverflowException>(() => checked((sbyte)new Int128(ulong.MaxValue, 42)));
+        }
+
+        [Fact]
+        public static void CheckedConvertToIntPtr()
+        {
+            Assert.Equal((nint)123, checked((nint)new Int128(0, 123)));
+            Assert.Equal((nint)(-123), checked((nint)(Int128)(-123)));
+            Assert.Throws<OverflowException>(() => checked((nint)new Int128(1, 1)));
+            Assert.Throws<OverflowException>(() => checked((nint)new Int128(ulong.MaxValue, 42)));
+        }
+
         public static IEnumerable<object[]> ToString_TestData()
         {
             foreach (NumberFormatInfo defaultFormat in new[] { null, NumberFormatInfo.CurrentInfo })
diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs
index 286e18ba3410c7..92353c676b64d4 100644
--- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs
+++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs
@@ -3211,6 +3211,32 @@ public static void TestCustomTimeZonesWithNullNames()
             Assert.Equal(string.Empty, custom.DisplayName);
         }
 
+        [InlineData("Eastern Standard Time", "America/New_York")]
+        [InlineData("Central Standard Time", "America/Chicago")]
+        [InlineData("Mountain Standard Time", "America/Denver")]
+        [InlineData("Pacific Standard Time", "America/Los_Angeles")]
+        [ConditionalTheory(nameof(SupportICUAndRemoteExecution))]
+        public static void TestTimeZoneNames(string windowsId, string ianaId)
+        {
+            RemoteExecutor.Invoke(static (wId, iId) =>
+            {
+                TimeZoneInfo info1, info2;
+                if (PlatformDetection.IsWindows)
+                {
+                    info1 = TimeZoneInfo.FindSystemTimeZoneById(iId);
+                    info2 = TimeZoneInfo.FindSystemTimeZoneById(wId);
+                }
+                else
+                {
+                    info1 = TimeZoneInfo.FindSystemTimeZoneById(wId);
+                    info2 = TimeZoneInfo.FindSystemTimeZoneById(iId);
+                }
+                Assert.Equal(info1.StandardName, info2.StandardName);
+                Assert.Equal(info1.DaylightName, info2.DaylightName);
+                Assert.Equal(info1.DisplayName, info2.DisplayName);
+            }, windowsId, ianaId).Dispose();
+        }
+
         private static bool IsEnglishUILanguage => CultureInfo.CurrentUICulture.Name.Length == 0 || CultureInfo.CurrentUICulture.TwoLetterISOLanguageName == "en";
 
         private static bool IsEnglishUILanguageAndRemoteExecutorSupported => IsEnglishUILanguage && RemoteExecutor.IsSupported;
diff --git a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx
index 4bcfdcfd3454fc..5cc5cce830a351 100644
--- a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx
+++ b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx
@@ -327,6 +327,9 @@
   <data name="Cryptography_EncryptedIncorrectLength" xml:space="preserve">
     <value>{0} unexpectedly produced a ciphertext with the incorrect length.</value>
   </data>
+  <data name="Cryptography_EnginesNotSupported" xml:space="preserve">
+    <value>OpenSSL ENGINE is not available on this platform.</value>
+  </data>
   <data name="Cryptography_ExceedKdfExtractLimit" xml:space="preserve">
     <value>The total number of bytes extracted cannot exceed UInt32.MaxValue * hash length.</value>
   </data>
diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj
index a550e9cf9cc827..efcc5c27e4acc9 100644
--- a/src/libraries/tests.proj
+++ b/src/libraries/tests.proj
@@ -418,6 +418,10 @@
     <ProjectExclusions Include="$(MSBuildThisFileDirectory)System.IO.Ports\tests\System.IO.Ports.Tests.csproj"
                       Condition="'$(TargetOS)' != 'windows'" />
 
+    <!-- Getting OOM killed, needs investigation why it uses 10 GB of memory -->
+    <ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Text.Json\tests\System.Text.Json.SourceGeneration.Tests\System.Text.Json.SourceGeneration.Roslyn4.4.Tests.csproj"
+                      Condition="'$(TargetOS)' == 'linux'" />
+
     <!-- Not applicable to NativeAOT -->
     <ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Reflection\tests\InvokeEmit\System.Reflection.InvokeEmit.Tests.csproj" />
     <ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Reflection\tests\InvokeInterpreted\System.Reflection.InvokeInterpreted.Tests.csproj" />
diff --git a/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c b/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c
index 4ab963643d4c32..8f3b104466e24b 100644
--- a/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c
+++ b/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c
@@ -815,7 +815,7 @@ get_module_event_data (
 		module_data->module_flags = MODULE_FLAGS_MANIFEST_MODULE;
 		if (image && image->dynamic)
 			module_data->module_flags |= MODULE_FLAGS_DYNAMIC_MODULE;
-		if (image && image->aot_module)
+		if (image && image->aot_module && (image->aot_module != AOT_MODULE_NOT_FOUND))
 			module_data->module_flags |= MODULE_FLAGS_NATIVE_MODULE;
 
 		module_data->module_il_path = NULL;
@@ -905,7 +905,7 @@ fire_assembly_events (
 	if (assembly->dynamic)
 		assembly_flags |= ASSEMBLY_FLAGS_DYNAMIC_ASSEMBLY;
 
-	if (assembly->image && assembly->image->aot_module) {
+	if (assembly->image && assembly->image->aot_module && (assembly->image->aot_module != AOT_MODULE_NOT_FOUND)) {
 		assembly_flags |= ASSEMBLY_FLAGS_NATIVE_ASSEMBLY;
 	}
 
@@ -2154,7 +2154,7 @@ get_assembly_event_data (
 		if (assembly->dynamic)
 			assembly_data->assembly_flags |= ASSEMBLY_FLAGS_DYNAMIC_ASSEMBLY;
 
-		if (assembly->image && assembly->image->aot_module)
+		if (assembly->image && assembly->image->aot_module && (assembly->image->aot_module != AOT_MODULE_NOT_FOUND))
 			assembly_data->assembly_flags |= ASSEMBLY_FLAGS_NATIVE_ASSEMBLY;
 
 		assembly_data->assembly_name = mono_stringify_assembly_name (&assembly->aname);
diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c
index 86c70dba388621..1a2a4670437ad5 100644
--- a/src/mono/mono/mini/aot-runtime.c
+++ b/src/mono/mono/mini/aot-runtime.c
@@ -1795,7 +1795,7 @@ init_amodule_got (MonoAotModule *amodule, gboolean preinit)
 			if (mono_defaults.corlib) {
 				MonoAotModule *mscorlib_amodule = mono_defaults.corlib->aot_module;
 
-				if (mscorlib_amodule)
+				if (mscorlib_amodule && (mscorlib_amodule != AOT_MODULE_NOT_FOUND))
 					amodule->shared_got [i] = mscorlib_amodule->got;
 			} else {
 				amodule->shared_got [i] = amodule->got;
@@ -2053,6 +2053,7 @@ load_aot_module (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer
 				g_free (aot_name);
 			}
 #endif
+			assembly->image->aot_module = AOT_MODULE_NOT_FOUND;
 			return;
 		}
 	}
@@ -2104,7 +2105,7 @@ load_aot_module (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer
 			mono_dl_close (sofile, close_error);
 			mono_error_cleanup (close_error);
 		}
-		assembly->image->aot_module = NULL;
+		assembly->image->aot_module = AOT_MODULE_NOT_FOUND;
 		return;
 	}
 
@@ -2487,7 +2488,7 @@ load_container_amodule (MonoAssemblyLoadContext *alc)
 
 		load_aot_module(alc, assm, NULL, error);
 		mono_memory_barrier ();
-		g_assert (assm->image->aot_module);
+		g_assert (assm->image->aot_module && (assm->image->aot_module != AOT_MODULE_NOT_FOUND));
 		container_amodule = assm->image->aot_module;
 	}
 
@@ -2561,7 +2562,7 @@ mono_aot_get_method_from_vt_slot (MonoVTable *vtable, int slot, MonoError *error
 
 	error_init (error);
 
-	if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass) || m_class_get_rank (klass) || !amodule)
+	if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass) || m_class_get_rank (klass) || !amodule || (amodule == AOT_MODULE_NOT_FOUND))
 		return NULL;
 
 	info = &amodule->blob [mono_aot_get_offset (amodule->class_info_offsets, mono_metadata_token_index (m_class_get_type_token (klass)) - 1)];
@@ -2597,7 +2598,7 @@ mono_aot_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
 	guint8 *p;
 	gboolean err;
 
-	if (m_class_get_rank (klass) || !m_class_get_type_token (klass) || !amodule)
+	if (m_class_get_rank (klass) || !m_class_get_type_token (klass) || !amodule || (amodule == AOT_MODULE_NOT_FOUND))
 		return FALSE;
 
 	p = (guint8*)&amodule->blob [mono_aot_get_offset (amodule->class_info_offsets, mono_metadata_token_index (m_class_get_type_token (klass)) - 1)];
@@ -2637,7 +2638,7 @@ mono_aot_get_class_from_name (MonoImage *image, const char *name_space, const ch
 	uint32_t debug_hash;
 #endif
 
-	if (!amodule || !amodule->class_name_table)
+	if (!amodule || (amodule == AOT_MODULE_NOT_FOUND) || !amodule->class_name_table)
 		return FALSE;
 
 	amodule_lock (amodule);
@@ -2746,7 +2747,7 @@ mono_aot_get_weak_field_indexes (MonoImage *image)
 {
 	MonoAotModule *amodule = image->aot_module;
 
-	if (!amodule)
+	if (!amodule || (amodule == AOT_MODULE_NOT_FOUND))
 		return NULL;
 
 #if ENABLE_WEAK_ATTR
@@ -3437,7 +3438,7 @@ mono_aot_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
 		amodule = ji->d.aot_info;
 	else
 		amodule = m_class_get_image (jinfo_get_method (ji)->klass)->aot_module;
-	g_assert (amodule);
+	g_assert (amodule && (amodule != AOT_MODULE_NOT_FOUND));
 	g_assert (ji->from_aot);
 
 	if (!amodule_contains_code_addr (amodule, code)) {
@@ -3574,7 +3575,7 @@ mono_aot_find_jit_info (MonoImage *image, gpointer addr)
 	int methods_len;
 	gboolean async;
 
-	if (!amodule)
+	if (!amodule || (amodule == AOT_MODULE_NOT_FOUND))
 		return NULL;
 
 	addr = MINI_FTNPTR_TO_ADDR (addr);
@@ -4468,7 +4469,7 @@ find_aot_method_in_amodule (MonoAotModule *code_amodule, MonoMethod *method, gui
 	// the caching breaking. The solution seems to be to cache using the "metadata" amodule.
 	MonoAotModule *metadata_amodule = m_class_get_image (method->klass)->aot_module;
 
-	if (!metadata_amodule || metadata_amodule->out_of_date || !code_amodule || code_amodule->out_of_date)
+	if (!metadata_amodule || (metadata_amodule == AOT_MODULE_NOT_FOUND) || metadata_amodule->out_of_date || !code_amodule || code_amodule->out_of_date)
 		return 0xffffff;
 
 	table = code_amodule->extra_method_table;
@@ -4638,7 +4639,7 @@ find_aot_method (MonoMethod *method, MonoAotModule **out_amodule)
 
 	/* Try the method's module first */
 	*out_amodule = m_class_get_image (method->klass)->aot_module;
-	index = find_aot_method_in_amodule (m_class_get_image (method->klass)->aot_module, method, hash);
+	index = find_aot_method_in_amodule (*out_amodule, method, hash);
 	if (index != 0xffffff)
 		return index;
 
@@ -4873,14 +4874,37 @@ mono_aot_get_method (MonoMethod *method, MonoError *error)
 	MonoClass *klass = method->klass;
 	MonoMethod *orig_method = method;
 	guint32 method_index;
-	MonoAotModule *amodule = m_class_get_image (klass)->aot_module;
+	MonoImage *image = m_class_get_image (klass);
+	
 	guint8 *code;
 	gboolean cache_result = FALSE;
 	ERROR_DECL (inner_error);
 
 	error_init (error);
 
-	if (!amodule)
+	if (!(image->aot_module)) {
+		// aot_module was uninitialized
+		MonoMethodHeader *header = mono_method_get_header_checked (method, inner_error);
+		mono_error_cleanup (inner_error);
+		if (!header) {
+			return NULL;
+		} else if (header->code_size != 0) {
+			return NULL;
+		} else {
+			// IL code for the method body doesn't exist. Try waiting for aot_module to be loaded probably by another thread
+			int count = 0;
+			while (!(image->aot_module) && (count < 10)) { // The threshold of count should never be removed to prevent deadlock.
+				g_usleep (100);
+				count++;
+			}
+			if (!(image->aot_module))
+				return NULL;
+		}
+	}
+
+	MonoAotModule *amodule = image->aot_module;
+
+	if (amodule == AOT_MODULE_NOT_FOUND)
 		return NULL;
 
 	if (amodule->out_of_date)
@@ -5094,7 +5118,7 @@ mono_aot_get_method_from_token (MonoImage *image, guint32 token, MonoError *erro
 
 	error_init (error);
 
-	if (!aot_module)
+	if (!aot_module || aot_module == AOT_MODULE_NOT_FOUND)
 		return NULL;
 
 	method_index = mono_metadata_token_index (token) - 1;
@@ -5596,7 +5620,7 @@ get_mscorlib_aot_module (void)
 	MonoAotModule *amodule;
 
 	image = mono_defaults.corlib;
-	if (image && image->aot_module)
+	if (image && image->aot_module && (image->aot_module != AOT_MODULE_NOT_FOUND))
 		amodule = image->aot_module;
 	else
 		amodule = mscorlib_aot_module;
@@ -6048,7 +6072,7 @@ ui16_idx_comparer (const void *key, const void *member)
 static gboolean
 aot_is_slim_amodule (MonoAotModule *amodule)
 {
-	if (!amodule)
+	if (!amodule || amodule == AOT_MODULE_NOT_FOUND)
 		return FALSE;
 
 	/* "slim" only applies to mscorlib.dll */
@@ -6086,7 +6110,7 @@ mono_aot_get_unbox_trampoline (MonoMethod *method, gpointer addr)
 	} else
 		amodule = m_class_get_image (method->klass)->aot_module;
 
-	if (amodule == NULL || method_index == 0xffffff || aot_is_slim_amodule (amodule)) {
+	if (!amodule || amodule == AOT_MODULE_NOT_FOUND || method_index == 0xffffff || aot_is_slim_amodule (amodule)) {
 		/* couldn't find unbox trampoline specifically generated for that
 		 * method. this should only happen when an unbox trampoline is needed
 		 * for `fullAOT code -> native-to-interp -> interp` transition if
diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c
index 2942fb23d3f82f..5328d982af6f03 100644
--- a/src/mono/mono/mini/interp/interp.c
+++ b/src/mono/mono/mini/interp/interp.c
@@ -3362,9 +3362,6 @@ interp_create_method_pointer (MonoMethod *method, gboolean compile, MonoError *e
 		return (gpointer)no_llvmonly_interp_method_pointer;
 	}
 
-	if (method->wrapper_type && method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
-		return imethod;
-
 #ifndef MONO_ARCH_HAVE_FTNPTR_ARG_TRAMPOLINE
 	/*
 	 * Interp in wrappers get the argument in the rgctx register. If
diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c
index bdb2b3f45eaf08..da1d0c31e086d8 100644
--- a/src/mono/mono/mini/interp/transform.c
+++ b/src/mono/mono/mini/interp/transform.c
@@ -1231,7 +1231,8 @@ mono_interp_jit_call_supported (MonoMethod *method, MonoMethodSignature *sig)
 	if (!interp_jit_call_can_be_supported (method, sig, mono_llvm_only))
 		return FALSE;
 
-	if (mono_aot_only && m_class_get_image (method->klass)->aot_module && !(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
+	MonoAotModule *amodule = m_class_get_image (method->klass)->aot_module;
+	if (mono_aot_only && amodule && (amodule != AOT_MODULE_NOT_FOUND) && !(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
 		ERROR_DECL (error);
 		mono_class_init_internal (method->klass);
 		gpointer addr = mono_aot_get_method (method, error);
diff --git a/src/mono/mono/mini/mini-amd64.c b/src/mono/mono/mini/mini-amd64.c
index e03b142feef1f3..881f491343af9e 100644
--- a/src/mono/mono/mini/mini-amd64.c
+++ b/src/mono/mono/mini/mini-amd64.c
@@ -3034,7 +3034,8 @@ emit_call (MonoCompile *cfg, MonoCallInst *call, guint8 *code, MonoJitICallId ji
 
 				MonoMethod* const method = call->method;
 
-				if (m_class_get_image (method->klass)->aot_module)
+				MonoAotModule *amodule = m_class_get_image (method->klass)->aot_module;
+				if (amodule && (amodule != AOT_MODULE_NOT_FOUND))
 					/* The callee might be an AOT method */
 					near_call = FALSE;
 				if (method->dynamic)
diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c
index d075623de8cf73..0318c3d1689bcc 100644
--- a/src/mono/mono/mini/mini-runtime.c
+++ b/src/mono/mono/mini/mini-runtime.c
@@ -2558,7 +2558,18 @@ compile_special (MonoMethod *method, MonoError *error)
 		} else {
 			MonoMethod *nm = mono_marshal_get_native_wrapper (method, TRUE, mono_aot_only);
 			compiled_method = mono_jit_compile_method_jit_only (nm, error);
-			return_val_if_nok (error, NULL);
+			if (!compiled_method && mono_aot_only && mono_use_interpreter) {
+				// We failed to find wrapper in aot images, try interpreting it instead
+				mono_error_cleanup (error);
+				error_init_reuse (error);
+				nm = mono_marshal_get_native_wrapper (method, TRUE, FALSE);
+				compiled_method = mono_jit_compile_method (nm, error);
+				return_val_if_nok (error, NULL);
+				code = mono_get_addr_from_ftnptr (compiled_method);
+				return code;
+			} else {
+				return_val_if_nok (error, NULL);
+			}
 		}
 
 		code = mono_get_addr_from_ftnptr (compiled_method);
diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h
index eee8fd39bd5a59..f6a8ded6e7c55d 100644
--- a/src/mono/mono/mini/mini.h
+++ b/src/mono/mono/mini/mini.h
@@ -423,6 +423,8 @@ struct MonoSpillInfo {
 	int offset;
 };
 
+#define AOT_MODULE_NOT_FOUND GINT_TO_POINTER (-1)
+
 /*
  * Information about a call site for the GC map creation code
  */
diff --git a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets
index 324f36cad7957f..b13b13a02bcffc 100644
--- a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets
+++ b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets
@@ -212,9 +212,6 @@ Copyright (c) .NET Foundation. All rights reserved.
       <_BlazorWebAssemblyStartupMemoryCache>$(BlazorWebAssemblyStartupMemoryCache)</_BlazorWebAssemblyStartupMemoryCache>
       <_BlazorWebAssemblyJiterpreter>$(BlazorWebAssemblyJiterpreter)</_BlazorWebAssemblyJiterpreter>
       <_BlazorWebAssemblyRuntimeOptions>$(BlazorWebAssemblyRuntimeOptions)</_BlazorWebAssemblyRuntimeOptions>
-      <_WasmDebugLevel>$(WasmDebugLevel)</_WasmDebugLevel>
-      <_WasmDebugLevel Condition="'$(_WasmDebugLevel)' == ''">0</_WasmDebugLevel>
-      <_WasmDebugLevel Condition="'$(_WasmDebugLevel)' == '0' and ('$(DebuggerSupport)' == 'true' or '$(Configuration)' == 'Debug')">-1</_WasmDebugLevel>
 
       <!-- Workaround for https://github.com/dotnet/sdk/issues/12114-->
       <PublishDir Condition="'$(AppendRuntimeIdentifierToOutputPath)' != 'true' AND '$(PublishDir)' == '$(OutputPath)$(RuntimeIdentifier)\$(PublishDirName)\'">$(OutputPath)$(PublishDirName)\</PublishDir>
@@ -373,7 +370,7 @@ Copyright (c) .NET Foundation. All rights reserved.
       AssemblyPath="@(IntermediateAssembly)"
       Resources="@(_WasmOutputWithHash)"
       DebugBuild="true"
-      DebugLevel="$(_WasmDebugLevel)"
+      DebugLevel="$(WasmDebugLevel)"
       LinkerEnabled="false"
       CacheBootResources="$(BlazorCacheBootResources)"
       OutputPath="$(_WasmBuildBootJsonPath)"
@@ -389,7 +386,8 @@ Copyright (c) .NET Foundation. All rights reserved.
       Extensions="@(WasmBootConfigExtension)"
       TargetFrameworkVersion="$(TargetFrameworkVersion)"
       ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
-      ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
+      ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)"
+      IsPublish="false" />
 
     <ItemGroup>
       <FileWrites Include="$(_WasmBuildBootJsonPath)" />
@@ -566,7 +564,7 @@ Copyright (c) .NET Foundation. All rights reserved.
       AssemblyPath="@(IntermediateAssembly)"
       Resources="@(_WasmPublishBootResourceWithHash)"
       DebugBuild="false"
-      DebugLevel="$(_WasmDebugLevel)"
+      DebugLevel="$(WasmDebugLevel)"
       LinkerEnabled="$(PublishTrimmed)"
       CacheBootResources="$(BlazorCacheBootResources)"
       OutputPath="$(IntermediateOutputPath)blazor.publish.boot.json"
@@ -582,7 +580,8 @@ Copyright (c) .NET Foundation. All rights reserved.
       Extensions="@(WasmBootConfigExtension)"
       TargetFrameworkVersion="$(TargetFrameworkVersion)"
       ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
-      ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
+      ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)"
+      IsPublish="true" />
 
     <ItemGroup>
       <FileWrites Include="$(IntermediateOutputPath)blazor.publish.boot.json" />
diff --git a/src/mono/nuget/mono-packages.proj b/src/mono/nuget/mono-packages.proj
index 438ec97ace3e1a..beebe7690cfada 100644
--- a/src/mono/nuget/mono-packages.proj
+++ b/src/mono/nuget/mono-packages.proj
@@ -28,7 +28,7 @@
     <ProjectReference Include="Microsoft.NET.Runtime.LibraryBuilder.Sdk\Microsoft.NET.Runtime.LibraryBuilder.Sdk.pkgproj" />
   </ItemGroup>
 
-  <ItemGroup Condition="'$(DotNetBuildFromSource)' != 'true'">
+  <ItemGroup Condition="'$(DotNetBuildFromSource)' != 'true' and '$(TargetsMobile)' == 'true'">
     <ProjectReference Include="Microsoft.NET.Runtime.MonoTargets.Sdk\Microsoft.NET.Runtime.MonoTargets.Sdk.pkgproj" />
   </ItemGroup>
 </Project>
diff --git a/src/mono/wasi/build/WasiApp.targets b/src/mono/wasi/build/WasiApp.targets
index 099ba8c3ebea27..c403cd718f55c6 100644
--- a/src/mono/wasi/build/WasiApp.targets
+++ b/src/mono/wasi/build/WasiApp.targets
@@ -368,6 +368,11 @@
 
   <Target Name="_WasiDefaultGenerateAppBundle">
 
+    <PropertyGroup>
+      <_WasmOutputSymbolsToAppBundle Condition="'$(CopyOutputSymbolsToPublishDirectory)' == 'true' and '$(_IsPublishing)' == 'true'">true</_WasmOutputSymbolsToAppBundle>
+      <_WasmOutputSymbolsToAppBundle Condition="'$(_WasmOutputSymbolsToAppBundle)' == ''">false</_WasmOutputSymbolsToAppBundle>
+    </PropertyGroup>
+
     <WasiAppBuilder
       AppDir="$(WasmAppDir)"
       Assemblies="@(_WasmAssembliesInternal)"
@@ -382,7 +387,7 @@
       FilesToIncludeInFileSystem="@(WasmFilesToIncludeInFileSystem)"
       ExtraFilesToDeploy="@(WasmExtraFilesToDeploy)"
       NativeAssets="@(WasmNativeAsset)"
-      DebugLevel="$(WasmDebugLevel)"
+      OutputSymbolsToAppBundle="$(_WasmOutputSymbolsToAppBundle)"
       />
   </Target>
 
diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs
index 1d13051dd7344e..dbf0e848f75135 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs
@@ -75,6 +75,10 @@ public string CreateBlazorWasmTemplateProject(string id)
 
         if (options.ExpectSuccess && options.AssertAppBundle)
         {
+            // Because we do relink in Release publish by default
+            if (options.Config == "Release")
+                options = options with { ExpectedFileType = NativeFilesType.Relinked };
+
             AssertBundle(res.Output, options with { IsPublish = true });
         }
 
diff --git a/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs b/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs
index d72a844abf1e78..19da797813a609 100644
--- a/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs
@@ -41,7 +41,9 @@ public async Task<IPage> RunAsync(
         bool headless = true,
         Action<IConsoleMessage>? onConsoleMessage = null,
         Action<string>? onError = null,
-        Func<string, string>? modifyBrowserUrl = null)
+        Func<string, string>? modifyBrowserUrl = null,
+        int timeout = 10000,
+        int maxRetries = 3)
     {
         TaskCompletionSource<string> urlAvailable = new();
         Action<string?> outputHandler = msg =>
@@ -89,17 +91,33 @@ public async Task<IPage> RunAsync(
         Playwright = await Microsoft.Playwright.Playwright.CreateAsync();
         string[] chromeArgs = new[] { $"--explicitly-allowed-ports={url.Port}" };
         _testOutput.WriteLine($"Launching chrome ('{s_chromePath.Value}') via playwright with args = {string.Join(',', chromeArgs)}");
-        Browser = await Playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions{
-            ExecutablePath = s_chromePath.Value,
-            Headless = headless,
-            Args = chromeArgs
-        });
-
+        int attempt = 0;
+        while (attempt < maxRetries)
+        {
+            try
+            {
+                Browser = await Playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions{
+                    ExecutablePath = s_chromePath.Value,
+                    Headless = headless,
+                    Args = chromeArgs,
+                    Timeout = timeout
+                });
+                break;
+            }
+            catch (System.TimeoutException ex)
+            {
+                attempt++;
+                _testOutput.WriteLine($"Attempt {attempt} failed with TimeoutException: {ex.Message}");
+            }
+        }
+        if (attempt == maxRetries)
+            throw new Exception($"Failed to launch browser after {maxRetries} attempts");
+        
         string browserUrl = urlAvailable.Task.Result;
         if (modifyBrowserUrl != null)
             browserUrl = modifyBrowserUrl(browserUrl);
 
-        IPage page = await Browser.NewPageAsync();
+        IPage page = await Browser!.NewPageAsync();
         if (onConsoleMessage is not null)
             page.Console += (_, msg) => onConsoleMessage(msg);
 
diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppSettingsTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppSettingsTests.cs
index 96f2c4ebd6a1bf..5d028cc238909a 100644
--- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppSettingsTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppSettingsTests.cs
@@ -28,7 +28,7 @@ public async Task LoadAppSettingsBasedOnApplicationEnvironment(string applicatio
         CopyTestAsset("WasmBasicTestApp", "AppSettingsTests");
         PublishProject("Debug");
 
-        var result = await RunSdkStyleApp(new(
+        var result = await RunSdkStyleAppForPublish(new(
             Configuration: "Debug",
             TestScenario: "AppSettingsTest",
             BrowserQueryString: new Dictionary<string, string> { ["applicationEnvironment"] = applicationEnvironment }
diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs
index dc6fb9b490e7f3..3b3baf581c185a 100644
--- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs
@@ -36,15 +36,15 @@ protected void CopyTestAsset(string assetName, string generatedProjectNamePrefix
             _projectDir = Path.Combine(_projectDir!, "App");
     }
 
-    protected void BuildProject(string configuration)
+    protected void BuildProject(string configuration, bool assertAppBundle = true, params string[] extraArgs)
     {
-        (CommandResult result, _) = BlazorBuild(new BlazorBuildOptions(Id, configuration));
+        (CommandResult result, _) = BlazorBuild(new BlazorBuildOptions(Id, configuration, AssertAppBundle: assertAppBundle), extraArgs);
         result.EnsureSuccessful();
     }
 
-    protected void PublishProject(string configuration)
+    protected void PublishProject(string configuration, bool assertAppBundle = true, params string[] extraArgs)
     {
-        (CommandResult result, _) = BlazorPublish(new BlazorBuildOptions(Id, configuration));
+        (CommandResult result, _) = BlazorPublish(new BlazorBuildOptions(Id, configuration, AssertAppBundle: assertAppBundle), extraArgs);
         result.EnsureSuccessful();
     }
 
@@ -52,7 +52,13 @@ protected void PublishProject(string configuration)
         .WithWorkingDirectory(_projectDir!)
         .WithEnvironmentVariable("NUGET_PACKAGES", _nugetPackagesDir);
 
-    protected async Task<RunResult> RunSdkStyleApp(RunOptions options)
+    protected Task<RunResult> RunSdkStyleAppForBuild(RunOptions options)
+        => RunSdkStyleApp(options, BlazorRunHost.DotnetRun);
+    
+    protected Task<RunResult> RunSdkStyleAppForPublish(RunOptions options)
+        => RunSdkStyleApp(options, BlazorRunHost.WebServer);
+
+    private async Task<RunResult> RunSdkStyleApp(RunOptions options, BlazorRunHost host = BlazorRunHost.DotnetRun)
     {
         string queryString = "?test=" + options.TestScenario;
         if (options.BrowserQueryString != null)
@@ -67,9 +73,10 @@ protected async Task<RunResult> RunSdkStyleApp(RunOptions options)
                 CheckCounter: false,
                 Config: options.Configuration,
                 OnConsoleMessage: OnConsoleMessage,
-                QueryString: queryString);
+                QueryString: queryString,
+                Host: host);
 
-        await BlazorRunForBuildWithDotnetRun(blazorRunOptions);
+        await BlazorRunTest(blazorRunOptions);
 
         void OnConsoleMessage(IConsoleMessage msg)
         {
diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DebugLevelTestsBase.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DebugLevelTestsBase.cs
new file mode 100644
index 00000000000000..219b8b2ed6714d
--- /dev/null
+++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DebugLevelTestsBase.cs
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Xunit;
+using Xunit.Abstractions;
+
+#nullable enable
+
+namespace Wasm.Build.Tests.TestAppScenarios;
+
+public abstract class DebugLevelTestsBase : AppTestBase
+{
+    public DebugLevelTestsBase(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
+        : base(output, buildContext)
+    {
+    }
+
+    protected void AssertDebugLevel(RunResult result, int value)
+    {
+        Assert.Collection(
+            result.TestOutput,
+            m => Assert.Equal($"WasmDebugLevel: {value}", m)
+        );
+    }
+
+    protected abstract void SetupProject(string projectId);
+    protected abstract Task<RunResult> RunForBuild(string configuration);
+    protected abstract Task<RunResult> RunForPublish(string configuration);
+
+    [Theory]
+    [InlineData("Debug")]
+    [InlineData("Release")]
+    public async Task BuildWithDefaultLevel(string configuration)
+    {
+        SetupProject($"DebugLevelTests_BuildWithDefaultLevel_{configuration}");
+        BuildProject(configuration, assertAppBundle: false);
+
+        var result = await RunForBuild(configuration);
+        AssertDebugLevel(result, -1);
+    }
+
+    [Theory]
+    [InlineData("Debug", 1)]
+    [InlineData("Release", 1)]
+    [InlineData("Debug", 0)]
+    [InlineData("Release", 0)]
+    public async Task BuildWithExplicitValue(string configuration, int debugLevel)
+    {
+        SetupProject($"DebugLevelTests_BuildWithExplicitValue_{configuration}");
+        BuildProject(configuration, assertAppBundle: false, extraArgs: $"-p:WasmDebugLevel={debugLevel}");
+
+        var result = await RunForBuild(configuration);
+        AssertDebugLevel(result, debugLevel);
+    }
+
+    [Theory]
+    [InlineData("Debug")]
+    [InlineData("Release")]
+    public async Task PublishWithDefaultLevel(string configuration)
+    {
+        SetupProject($"DebugLevelTests_PublishWithDefaultLevel_{configuration}");
+        PublishProject(configuration, assertAppBundle: false);
+
+        var result = await RunForPublish(configuration);
+        AssertDebugLevel(result, 0);
+    }
+
+    [Theory]
+    [InlineData("Debug", 1)]
+    [InlineData("Release", 1)]
+    [InlineData("Debug", -1)]
+    [InlineData("Release", -1)]
+    public async Task PublishWithExplicitValue(string configuration, int debugLevel)
+    {
+        SetupProject($"DebugLevelTests_PublishWithExplicitValue_{configuration}");
+        PublishProject(configuration, assertAppBundle: false, extraArgs: $"-p:WasmDebugLevel={debugLevel}");
+
+        var result = await RunForPublish(configuration);
+        AssertDebugLevel(result, debugLevel);
+    }
+}
\ No newline at end of file
diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs
index 8f37a47e18860a..cf16a0536a38da 100644
--- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs
@@ -26,7 +26,7 @@ public async Task LoadLazyAssemblyBeforeItIsNeeded()
         CopyTestAsset("WasmBasicTestApp", "LazyLoadingTests");
         PublishProject("Debug");
 
-        var result = await RunSdkStyleApp(new(Configuration: "Debug", TestScenario: "LazyLoadingTest"));
+        var result = await RunSdkStyleAppForPublish(new(Configuration: "Debug", TestScenario: "LazyLoadingTest"));
         Assert.True(result.TestOutput.Any(m => m.Contains("FirstName")), "The lazy loading test didn't emit expected message with JSON");
     }
 
@@ -36,7 +36,7 @@ public async Task FailOnMissingLazyAssembly()
         CopyTestAsset("WasmBasicTestApp", "LazyLoadingTests");
         PublishProject("Debug");
 
-        var result = await RunSdkStyleApp(new(
+        var result = await RunSdkStyleAppForPublish(new(
             Configuration: "Debug",
             TestScenario: "LazyLoadingTest",
             BrowserQueryString: new Dictionary<string, string> { ["loadRequiredAssembly"] = "false" },
diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LibraryInitializerTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LibraryInitializerTests.cs
index 6f68a96ad1d61a..e985ad23d89a0b 100644
--- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LibraryInitializerTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LibraryInitializerTests.cs
@@ -29,7 +29,7 @@ public async Task LoadLibraryInitializer()
         CopyTestAsset("WasmBasicTestApp", "LibraryInitializerTests_LoadLibraryInitializer");
         PublishProject("Debug");
 
-        var result = await RunSdkStyleApp(new(Configuration: "Debug", TestScenario: "LibraryInitializerTest"));
+        var result = await RunSdkStyleAppForPublish(new(Configuration: "Debug", TestScenario: "LibraryInitializerTest"));
         Assert.Collection(
             result.TestOutput,
             m => Assert.Equal("LIBRARY_INITIALIZER_TEST = 1", m)
@@ -42,7 +42,7 @@ public async Task AbortStartupOnError()
         CopyTestAsset("WasmBasicTestApp", "LibraryInitializerTests_AbortStartupOnError");
         PublishProject("Debug");
 
-        var result = await RunSdkStyleApp(new(
+        var result = await RunSdkStyleAppForPublish(new(
             Configuration: "Debug",
             TestScenario: "LibraryInitializerTest",
             BrowserQueryString: new Dictionary<string, string> { ["throwError"] = "true" },
diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/ModuleConfigTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/ModuleConfigTests.cs
index 1b8c43ecea77b0..bc2b5631d2373f 100644
--- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/ModuleConfigTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/ModuleConfigTests.cs
@@ -28,7 +28,7 @@ public async Task DownloadProgressFinishes(bool failAssemblyDownload)
         CopyTestAsset("WasmBasicTestApp", $"ModuleConfigTests_DownloadProgressFinishes_{failAssemblyDownload}");
         PublishProject("Debug");
 
-        var result = await RunSdkStyleApp(new(
+        var result = await RunSdkStyleAppForPublish(new(
             Configuration: "Debug",
             TestScenario: "DownloadResourceProgressTest",
             BrowserQueryString: new Dictionary<string, string> { ["failAssemblyDownload"] = failAssemblyDownload.ToString().ToLowerInvariant() }
@@ -54,24 +54,4 @@ public async Task DownloadProgressFinishes(bool failAssemblyDownload)
                 : "The download progress test did emit unexpected message about failing download"
         );
     }
-
-    [Fact]
-    public async Task OutErrOverrideWorks()
-    {
-        CopyTestAsset("WasmBasicTestApp", $"ModuleConfigTests_OutErrOverrideWorks");
-        PublishProject("Debug");
-
-        var result = await RunSdkStyleApp(new(
-            Configuration: "Debug",
-            TestScenario: "OutErrOverrideWorks"
-        ));
-        Assert.True(
-            result.ConsoleOutput.Any(m => m.Contains("Emscripten out override works!")),
-            "Emscripten out override doesn't work"
-        );
-        Assert.True(
-            result.ConsoleOutput.Any(m => m.Contains("Emscripten err override works!")),
-            "Emscripten err override doesn't work"
-        );
-    }
 }
diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SatelliteLoadingTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SatelliteLoadingTests.cs
index 31dcb65582869e..2088e1522ad73b 100644
--- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SatelliteLoadingTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/SatelliteLoadingTests.cs
@@ -29,7 +29,7 @@ public async Task LoadSatelliteAssembly()
         CopyTestAsset("WasmBasicTestApp", "SatelliteLoadingTests");
         BuildProject("Debug");
 
-        var result = await RunSdkStyleApp(new(Configuration: "Debug", TestScenario: "SatelliteAssembliesTest"));
+        var result = await RunSdkStyleAppForBuild(new(Configuration: "Debug", TestScenario: "SatelliteAssembliesTest"));
         Assert.Collection(
             result.TestOutput,
             m => Assert.Equal("default: hello", m),
diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/WasmAppBuilderDebugLevelTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/WasmAppBuilderDebugLevelTests.cs
new file mode 100644
index 00000000000000..60fb3d86f7d0ea
--- /dev/null
+++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/WasmAppBuilderDebugLevelTests.cs
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Xunit;
+using Xunit.Abstractions;
+
+#nullable enable
+
+namespace Wasm.Build.Tests.TestAppScenarios;
+
+public class WasmAppBuilderDebugLevelTests : DebugLevelTestsBase
+{
+    public WasmAppBuilderDebugLevelTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
+        : base(output, buildContext)
+    {
+    }
+
+    protected override void SetupProject(string projectId)
+    {
+        Id = $"{projectId}_{GetRandomId()}";
+        string projectfile = CreateWasmTemplateProject(Id, "wasmconsole", extraArgs: "-f net8.0");
+        string projectDir = Path.GetDirectoryName(projectfile)!;
+        string mainJs = Path.Combine(projectDir, "main.mjs");
+        string mainJsContent = File.ReadAllText(mainJs);
+        mainJsContent = mainJsContent
+            .Replace("await dotnet.run()", "console.log('TestOutput -> WasmDebugLevel: ' + config.debugLevel); exit(0)");
+        File.WriteAllText(mainJs, mainJsContent);
+    }
+
+    protected override Task<RunResult> RunForBuild(string configuration)
+    {
+        CommandResult res = new RunCommand(s_buildEnv, _testOutput)
+            .WithWorkingDirectory(_projectDir!)
+            .ExecuteWithCapturedOutput($"run --no-silent --no-build -c {configuration}");
+
+        return Task.FromResult(ProcessRunOutput(res));
+    }
+
+    private RunResult ProcessRunOutput(CommandResult res)
+    {
+        var output = res.Output.Split(Environment.NewLine);
+        _testOutput.WriteLine($"DEBUG: parsed lines '{String.Join(", ", output)}'");
+
+        var prefix = "[] TestOutput -> ";
+        var testOutput = output
+            .Where(l => l.StartsWith(prefix))
+            .Select(l => l.Substring(prefix.Length))
+            .ToArray();
+
+        _testOutput.WriteLine($"DEBUG: testOutput '{String.Join(", ", testOutput)}'");
+        return new RunResult(res.ExitCode, testOutput, output);
+    }
+
+    protected override Task<RunResult> RunForPublish(string configuration)
+    {
+        // WasmAppBuilder does publish to the same folder as build (it overrides the output), 
+        // and thus using dotnet run work correctly for publish as well.
+        CommandResult res = new RunCommand(s_buildEnv, _testOutput)
+            .WithWorkingDirectory(_projectDir!)
+            .ExecuteWithCapturedOutput($"run --no-silent --no-build -c {configuration}");
+
+        return Task.FromResult(ProcessRunOutput(res));
+    }
+}
diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/WasmSdkDebugLevelTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/WasmSdkDebugLevelTests.cs
new file mode 100644
index 00000000000000..f88bb3c7239c99
--- /dev/null
+++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/WasmSdkDebugLevelTests.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Xunit;
+using Xunit.Abstractions;
+
+#nullable enable
+
+namespace Wasm.Build.Tests.TestAppScenarios;
+
+public class WasmSdkDebugLevelTests : DebugLevelTestsBase
+{
+    public WasmSdkDebugLevelTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
+        : base(output, buildContext)
+    {
+    }
+
+    protected override void SetupProject(string projectId) => CopyTestAsset("WasmBasicTestApp", projectId);
+    
+    protected override Task<RunResult> RunForBuild(string configuration) => RunSdkStyleAppForBuild(new(
+        Configuration: configuration,
+        TestScenario: "DebugLevelTest"
+    ));
+
+    protected override Task<RunResult> RunForPublish(string configuration) => RunSdkStyleAppForPublish(new(
+        Configuration: configuration,
+        TestScenario: "DebugLevelTest"
+    ));
+
+    [Theory]
+    [InlineData("Debug")]
+    [InlineData("Release")]
+    public async Task PublishWithDefaultLevelAndPdbs(string configuration)
+    {
+        SetupProject($"DebugLevelTests_PublishWithDefaultLevelAndPdbs_{configuration}");
+        PublishProject(configuration, extraArgs: $"-p:CopyOutputSymbolsToPublishDirectory=true");
+
+        var result = await RunForPublish(configuration);
+        AssertDebugLevel(result, -1);
+    }
+}
diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTestBase.cs
index a7ae3fba70ed30..1cc70d823ef14e 100644
--- a/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTestBase.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTestBase.cs
@@ -21,7 +21,7 @@ protected WasmTemplateTestBase(ITestOutputHelper output, SharedBuildPerTestClass
         _provider.BundleDirName = "AppBundle";
     }
 
-    public string CreateWasmTemplateProject(string id, string template = "wasmbrowser", string extraArgs = "", bool runAnalyzers = true)
+    public string CreateWasmTemplateProject(string id, string template = "wasmbrowser", string extraArgs = "", bool runAnalyzers = true, string? extraProperties = null)
     {
         InitPaths(id);
         InitProjectDir(_projectDir, addNuGetSourceForLocalPackages: true);
@@ -42,7 +42,9 @@ public string CreateWasmTemplateProject(string id, string template = "wasmbrowse
                 .EnsureSuccessful();
 
         string projectfile = Path.Combine(_projectDir!, $"{id}.csproj");
-        string extraProperties = string.Empty;
+        if (extraProperties == null)
+            extraProperties = string.Empty;
+
         extraProperties += "<TreatWarningsAsErrors>true</TreatWarningsAsErrors>";
         if (runAnalyzers)
             extraProperties += "<RunAnalyzers>true</RunAnalyzers>";
diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets
index a640a128b25044..bc92659fa3479b 100644
--- a/src/mono/wasm/build/WasmApp.targets
+++ b/src/mono/wasm/build/WasmApp.targets
@@ -142,9 +142,6 @@
     <!-- Temporarily `false`, till sdk gets a fix for supporting the new file -->
     <WasmEmitSymbolMap Condition="'$(WasmEmitSymbolMap)' == '' and '$(RunAOTCompilation)' != 'true'">false</WasmEmitSymbolMap>
 
-    <!-- if DebuggerSupport==true, then ensure that WasmDebugLevel isn't disabling debugging -->
-    <WasmDebugLevel Condition="('$(WasmDebugLevel)' == '' or '$(WasmDebugLevel)' == '0') and ('$(DebuggerSupport)' == 'true' or '$(Configuration)' == 'Debug')">-1</WasmDebugLevel>
-
     <!-- by default, package assemblies as webcil -->
     <WasmEnableWebcil Condition="'$(WasmEnableWebcil)' == ''">true</WasmEnableWebcil>
     <WasmAssemblyExtension Condition="'$(WasmEnableWebcil)' == 'true'">.wasm</WasmAssemblyExtension>
@@ -210,7 +207,7 @@
     <!-- Use a unique property, so the already run wasm targets can also run -->
     <MSBuild Projects="$(MSBuildProjectFile)"
              Targets="WasmNestedPublishApp"
-             Properties="_WasmInNestedPublish_UniqueProperty_XYZ=true;;WasmBuildingForNestedPublish=true;DeployOnBuild=;_IsPublishing=">
+             Properties="_WasmInNestedPublish_UniqueProperty_XYZ=true;;WasmBuildingForNestedPublish=true;DeployOnBuild=;_IsPublishing=;_WasmIsPublishing=$(_IsPublishing)">
       <Output TaskParameter="TargetOutputs" ItemName="WasmNestedPublishAppResultItems" />
     </MSBuild>
 
@@ -420,6 +417,7 @@
       <_WasmAppIncludeThreadsWorker Condition="'$(WasmEnableThreads)' == 'true' or '$(MonoWasmBuildVariant)' == 'multithread'">true</_WasmAppIncludeThreadsWorker>
       <!-- TODO: set this from some user-facing property?  -1 means use the default baked into dotnet.native.js -->
       <_WasmPThreadPoolSize Condition="'$(_WasmPThreadPoolSize)' == ''">-1</_WasmPThreadPoolSize>
+      <_WasmIsPublishing Condition="'$(_WasmIsPublishing)' == '' and '$(_IsPublishing)' != ''">$(_IsPublishing)</_WasmIsPublishing>
     </PropertyGroup>
 
     <ItemGroup>
@@ -445,6 +443,7 @@
       ExtraConfig="@(WasmExtraConfig)"
       NativeAssets="@(WasmNativeAsset)"
       DebugLevel="$(WasmDebugLevel)"
+      IsPublish="$(_WasmIsPublishing)"
       IncludeThreadsWorker="$(_WasmAppIncludeThreadsWorker)"
       PThreadPoolSize="$(_WasmPThreadPoolSize)"
       UseWebcil="$(WasmEnableWebcil)"
diff --git a/src/mono/wasm/runtime/lazyLoading.ts b/src/mono/wasm/runtime/lazyLoading.ts
index 55bcfd67101e8c..85058f89819b7c 100644
--- a/src/mono/wasm/runtime/lazyLoading.ts
+++ b/src/mono/wasm/runtime/lazyLoading.ts
@@ -26,7 +26,7 @@ export async function loadLazyAssembly(assemblyNameToLoad: string): Promise<bool
     }
 
     const pdbNameToLoad = changeExtension(dllAsset.name, ".pdb");
-    const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(loaderHelpers.config) && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);
+    const shouldLoadPdb = loaderHelpers.config.debugLevel != 0 && loaderHelpers.isDebuggingSupported() && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);
 
     const dllBytesPromise = loaderHelpers.retrieve_asset_download(dllAsset);
 
diff --git a/src/mono/wasm/runtime/loader/assets.ts b/src/mono/wasm/runtime/loader/assets.ts
index 5e9eb8a8d3b75b..013ddd326a7093 100644
--- a/src/mono/wasm/runtime/loader/assets.ts
+++ b/src/mono/wasm/runtime/loader/assets.ts
@@ -296,7 +296,7 @@ export function prepareAssets() {
             }
         }
 
-        if (config.debugLevel != 0 && resources.pdb) {
+        if (config.debugLevel != 0 && loaderHelpers.isDebuggingSupported() && resources.pdb) {
             for (const name in resources.pdb) {
                 containedInSnapshotAssets.push({
                     name,
diff --git a/src/mono/wasm/runtime/loader/config.ts b/src/mono/wasm/runtime/loader/config.ts
index d9bcccd4ed933c..e5ee1e17ad621e 100644
--- a/src/mono/wasm/runtime/loader/config.ts
+++ b/src/mono/wasm/runtime/loader/config.ts
@@ -186,13 +186,6 @@ export function normalizeConfig() {
         config.cachedResourcesPurgeDelay = 10000;
     }
 
-    // Default values (when WasmDebugLevel is not set)
-    // - Build   (debug)    => debugBuild=true  & debugLevel=-1 => -1
-    // - Build   (release)  => debugBuild=true  & debugLevel=0  => 0
-    // - Publish (debug)    => debugBuild=false & debugLevel=-1 => 0
-    // - Publish (release)  => debugBuild=false & debugLevel=0  => 0
-    config.debugLevel = hasDebuggingEnabled(config) ? config.debugLevel : 0;
-
     if (config.diagnosticTracing === undefined && BuildConfiguration === "Debug") {
         config.diagnosticTracing = true;
     }
@@ -264,14 +257,13 @@ export async function mono_wasm_load_config(module: DotnetModuleInternal): Promi
     }
 }
 
-export function hasDebuggingEnabled(config: MonoConfigInternal): boolean {
+export function isDebuggingSupported(): boolean {
     // Copied from blazor MonoDebugger.ts/attachDebuggerHotkey
     if (!globalThis.navigator) {
         return false;
     }
 
-    const hasReferencedPdbs = !!config.resources!.pdb;
-    return (hasReferencedPdbs || config.debugLevel != 0) && (loaderHelpers.isChromium || loaderHelpers.isFirefox);
+    return loaderHelpers.isChromium || loaderHelpers.isFirefox;
 }
 
 async function loadBootConfig(module: DotnetModuleInternal): Promise<void> {
diff --git a/src/mono/wasm/runtime/loader/globals.ts b/src/mono/wasm/runtime/loader/globals.ts
index 88b0d472de3ca8..0bd081ed8a82cc 100644
--- a/src/mono/wasm/runtime/loader/globals.ts
+++ b/src/mono/wasm/runtime/loader/globals.ts
@@ -12,7 +12,7 @@ import { assertIsControllablePromise, createPromiseController, getPromiseControl
 import { mono_download_assets, resolve_single_asset_path, retrieve_asset_download } from "./assets";
 import { setup_proxy_console } from "./logging";
 import { invokeLibraryInitializers } from "./libraryInitializers";
-import { hasDebuggingEnabled } from "./config";
+import { isDebuggingSupported } from "./config";
 import { logDownloadStatsToConsole, purgeUnusedCacheEntriesAsync } from "./assetsCache";
 
 export const ENVIRONMENT_IS_NODE = typeof process == "object" && typeof process.versions == "object" && typeof process.versions.node == "string";
@@ -102,9 +102,9 @@ export function setLoaderGlobals(
         logDownloadStatsToConsole,
         purgeUnusedCacheEntriesAsync,
 
-        hasDebuggingEnabled,
         retrieve_asset_download,
         invokeLibraryInitializers,
+        isDebuggingSupported,
 
         // from wasm-feature-detect npm package
         exceptions,
diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts
index 324bdc78b0435d..6efa969a953a82 100644
--- a/src/mono/wasm/runtime/startup.ts
+++ b/src/mono/wasm/runtime/startup.ts
@@ -548,7 +548,7 @@ async function mono_wasm_before_memory_snapshot() {
     if (runtimeHelpers.config.browserProfilerOptions)
         mono_wasm_init_browser_profiler(runtimeHelpers.config.browserProfilerOptions);
 
-    mono_wasm_load_runtime("unused", runtimeHelpers.config.debugLevel);
+    mono_wasm_load_runtime();
 
     // we didn't have snapshot yet and the feature is enabled. Take snapshot now.
     if (runtimeHelpers.config.startupMemoryCache) {
@@ -561,17 +561,21 @@ async function mono_wasm_before_memory_snapshot() {
     endMeasure(mark, MeasuredBlock.memorySnapshot);
 }
 
-export function mono_wasm_load_runtime(unused?: string, debugLevel?: number): void {
+export function mono_wasm_load_runtime(): void {
     mono_log_debug("mono_wasm_load_runtime");
     try {
         const mark = startMeasure();
+        let debugLevel = runtimeHelpers.config.debugLevel;
         if (debugLevel == undefined) {
             debugLevel = 0;
             if (runtimeHelpers.config.debugLevel) {
                 debugLevel = 0 + debugLevel;
             }
         }
-        cwraps.mono_wasm_load_runtime(unused || "unused", debugLevel);
+        if (!loaderHelpers.isDebuggingSupported() || !runtimeHelpers.config.resources!.pdb) {
+            debugLevel = 0;
+        }
+        cwraps.mono_wasm_load_runtime("unused", debugLevel);
         endMeasure(mark, MeasuredBlock.loadRuntime);
 
     } catch (err: any) {
diff --git a/src/mono/wasm/runtime/types/internal.ts b/src/mono/wasm/runtime/types/internal.ts
index c43443a48da6bc..c0b14b72abe5da 100644
--- a/src/mono/wasm/runtime/types/internal.ts
+++ b/src/mono/wasm/runtime/types/internal.ts
@@ -145,7 +145,6 @@ export type LoaderHelpers = {
     out(message: string): void;
     err(message: string): void;
 
-    hasDebuggingEnabled(config: MonoConfig): boolean,
     retrieve_asset_download(asset: AssetEntry): Promise<ArrayBuffer>;
     onDownloadResourceProgress?: (resourcesLoaded: number, totalResources: number) => void;
     logDownloadStatsToConsole: () => void;
@@ -155,6 +154,7 @@ export type LoaderHelpers = {
     invokeLibraryInitializers: (functionName: string, args: any[]) => Promise<void>,
     libraryInitializers?: { scriptName: string, exports: any }[];
 
+    isDebuggingSupported(): boolean,
     isChromium: boolean,
     isFirefox: boolean
 
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/LazyLoadingTest.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/LazyLoadingTest.cs
index 5aba6b1ee48a0f..797956d23f8e4d 100644
--- a/src/mono/wasm/testassets/WasmBasicTestApp/App/LazyLoadingTest.cs
+++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/LazyLoadingTest.cs
@@ -4,6 +4,7 @@
 using Library;
 using System;
 using System.Text.Json;
+using System.Text.Json.Serialization;
 using System.Runtime.InteropServices.JavaScript;
 
 public partial class LazyLoadingTest
@@ -13,7 +14,12 @@ public static void Run()
     {
         // System.Text.Json is marked as lazy loaded in the csproj ("BlazorWebAssemblyLazyLoad"), this method can be called only after the assembly is lazy loaded
         // In the test case it is done in the JS before call to this method
-        var text = JsonSerializer.Serialize(new Person("John", "Doe"));
+        var text = JsonSerializer.Serialize(new Person("John", "Doe"), PersonJsonSerializerContext.Default.Person);
         TestOutput.WriteLine(text);
     }
 }
+
+[JsonSerializable(typeof(Person))]
+public partial class PersonJsonSerializerContext : JsonSerializerContext
+{
+}
\ No newline at end of file
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js
index 8e3485bc2e67cd..5092e4cb945b75 100644
--- a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js
+++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js
@@ -33,6 +33,8 @@ switch (testCase) {
                 Math.floor(Math.random() * 5) + 5,
                 Math.floor(Math.random() * 5) + 10
             ];
+            console.log(`Failing test at assembly indexes [${failAtAssemblyNumbers.join(", ")}]`);
+            let alreadyFailed = [];
             dotnet.withDiagnosticTracing(true).withResourceLoader((type, name, defaultUri, integrity, behavior) => {
                 if (type === "dotnetjs") {
                     // loadBootResource could return string with unqualified name of resource. 
@@ -45,9 +47,10 @@ switch (testCase) {
                 }
 
                 assemblyCounter++;
-                if (!failAtAssemblyNumbers.includes(assemblyCounter))
+                if (!failAtAssemblyNumbers.includes(assemblyCounter) || alreadyFailed.includes(defaultUri))
                     return defaultUri;
 
+                alreadyFailed.push(defaultUri);
                 testOutput("Throw error instead of downloading resource");
                 const error = new Error("Simulating a failed fetch");
                 error.silent = true;
@@ -106,6 +109,10 @@ try {
         case "DownloadResourceProgressTest":
             exit(0);
             break;
+        case "DebugLevelTest":
+            testOutput("WasmDebugLevel: " + config.debugLevel);
+            exit(0);
+            break;
         case "OutErrOverrideWorks":
             dotnet.run();
             break;
diff --git a/src/native/corehost/ijwhost/ijwhost.cpp b/src/native/corehost/ijwhost/ijwhost.cpp
index 7f1684cca62630..c2e1d22a32cc50 100644
--- a/src/native/corehost/ijwhost/ijwhost.cpp
+++ b/src/native/corehost/ijwhost/ijwhost.cpp
@@ -20,7 +20,7 @@
 #define IJW_API SHARED_API
 #endif // _WIN32
 
-pal::hresult_t get_load_in_memory_assembly_delegate(pal::dll_t handle, load_in_memory_assembly_fn* delegate)
+pal::hresult_t get_load_in_memory_assembly_delegate(pal::dll_t handle, load_in_memory_assembly_fn* delegate, void **load_context)
 {
     get_function_pointer_fn get_function_pointer;
     int status = load_fxr_and_get_delegate(
@@ -40,7 +40,17 @@ pal::hresult_t get_load_in_memory_assembly_delegate(pal::dll_t handle, load_in_m
 
             return StatusCode::Success;
         },
-        [](pal::dll_t fxr, hostfxr_handle context){ },
+        [load_context](pal::dll_t fxr, hostfxr_handle context)
+        {
+            *load_context = nullptr;   // default load context
+            auto get_runtime_property_value = reinterpret_cast<hostfxr_get_runtime_property_value_fn>(pal::get_symbol(fxr, "hostfxr_get_runtime_property_value"));
+            const pal::char_t* value;
+            if (get_runtime_property_value(context, _X("System.Runtime.InteropServices.CppCLI.LoadComponentInIsolatedContext"), &value) == StatusCode::Success
+                && pal::strcasecmp(value, _X("true")) == 0)
+            {
+                *load_context = ISOLATED_CONTEXT; // Isolated load context
+            }
+        },
         reinterpret_cast<void**>(&get_function_pointer)
     );
     if (status != StatusCode::Success)
diff --git a/src/native/corehost/ijwhost/ijwhost.h b/src/native/corehost/ijwhost/ijwhost.h
index c3698a4d4acb65..adfd52f71a99c9 100644
--- a/src/native/corehost/ijwhost/ijwhost.h
+++ b/src/native/corehost/ijwhost/ijwhost.h
@@ -15,8 +15,10 @@ bool are_thunks_installed_for_module(HMODULE instance);
 
 using load_in_memory_assembly_fn = void(STDMETHODCALLTYPE*)(pal::dll_t handle, const pal::char_t* path, void* load_context);
 
-pal::hresult_t get_load_in_memory_assembly_delegate(pal::dll_t handle, load_in_memory_assembly_fn* delegate);
+pal::hresult_t get_load_in_memory_assembly_delegate(pal::dll_t handle, load_in_memory_assembly_fn* delegate, void **load_context);
 
 extern HANDLE g_heapHandle;
 
+#define ISOLATED_CONTEXT (void*)-1
+
 #endif
diff --git a/src/native/corehost/ijwhost/ijwthunk.cpp b/src/native/corehost/ijwhost/ijwthunk.cpp
index eeddf10fd931c1..2c24f4d6f92078 100644
--- a/src/native/corehost/ijwhost/ijwthunk.cpp
+++ b/src/native/corehost/ijwhost/ijwthunk.cpp
@@ -119,7 +119,9 @@ extern "C" std::uintptr_t __stdcall start_runtime_and_get_target_address(std::ui
     bootstrap_thunk *pThunk = bootstrap_thunk::get_thunk_from_cookie(cookie);
     load_in_memory_assembly_fn loadInMemoryAssembly;
     pal::dll_t moduleHandle = pThunk->get_dll_handle();
-    pal::hresult_t status = get_load_in_memory_assembly_delegate(moduleHandle, &loadInMemoryAssembly);
+
+    void* load_context = nullptr;
+    pal::hresult_t status = get_load_in_memory_assembly_delegate(moduleHandle, &loadInMemoryAssembly, &load_context);
 
     if (status != StatusCode::Success)
     {
@@ -145,7 +147,7 @@ extern "C" std::uintptr_t __stdcall start_runtime_and_get_target_address(std::ui
 #pragma warning (pop)
     }
 
-    loadInMemoryAssembly(moduleHandle, app_path.c_str(), nullptr);
+    loadInMemoryAssembly(moduleHandle, app_path.c_str(), load_context);
 
     std::uintptr_t thunkAddress = *(pThunk->get_slot_address());
 
diff --git a/src/native/libs/System.Security.Cryptography.Native/configure.cmake b/src/native/libs/System.Security.Cryptography.Native/configure.cmake
index 74ed49f5d19168..4a70e70899c5e7 100644
--- a/src/native/libs/System.Security.Cryptography.Native/configure.cmake
+++ b/src/native/libs/System.Security.Cryptography.Native/configure.cmake
@@ -1,8 +1,10 @@
 include(CheckLibraryExists)
 include(CheckFunctionExists)
+include(CheckSourceCompiles)
 
 set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
 set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY})
+set(CMAKE_REQUIRED_DEFINITIONS -DOPENSSL_API_COMPAT=0x10100000L)
 
 check_function_exists(
     EC_GF2m_simple_method
@@ -22,6 +24,11 @@ check_function_exists(
     HAVE_OPENSSL_SHA3
 )
 
+check_source_compiles(C "
+#include <openssl/engine.h>
+int main(void) { ENGINE_init(NULL); return 1; }"
+HAVE_OPENSSL_ENGINE)
+
 configure_file(
     ${CMAKE_CURRENT_SOURCE_DIR}/pal_crypto_config.h.in
     ${CMAKE_CURRENT_BINARY_DIR}/pal_crypto_config.h)
diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h
index 57ba6a68096491..3d6d77895b64f6 100644
--- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h
+++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h
@@ -17,7 +17,6 @@
 #include <openssl/dsa.h>
 #include <openssl/ec.h>
 #include <openssl/ecdsa.h>
-#include <openssl/engine.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
@@ -46,6 +45,11 @@
 #include <openssl/provider.h>
 #endif
 
+#if HAVE_OPENSSL_ENGINE
+// Some Linux distributions build without engine support.
+#include <openssl/engine.h>
+#endif
+
 #if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_1_1_RTM
 #define HAVE_OPENSSL_SET_CIPHERSUITES 1
 #else
@@ -168,6 +172,24 @@ const EVP_MD *EVP_shake256(void);
 int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len);
 #endif
 
+#if !HAVE_OPENSSL_ENGINE
+#undef HAVE_OPENSSL_ENGINE
+#define HAVE_OPENSSL_ENGINE 1
+
+ENGINE *ENGINE_by_id(const char *id);
+int ENGINE_init(ENGINE *e);
+int ENGINE_finish(ENGINE *e);
+ENGINE *ENGINE_new(void);
+int ENGINE_free(ENGINE *e);
+typedef EVP_PKEY *(*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *,
+                                         UI_METHOD *ui_method,
+                                         void *callback_data);
+EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,
+                                  UI_METHOD *ui_method, void *callback_data);
+EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id,
+                                 UI_METHOD *ui_method, void *callback_data);
+#endif
+
 #define API_EXISTS(fn) (fn != NULL)
 
 // List of all functions from the libssl that are used in the System.Security.Cryptography.Native.
@@ -298,12 +320,12 @@ int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len);
     REQUIRED_FUNCTION(EC_POINT_mul) \
     REQUIRED_FUNCTION(EC_POINT_new) \
     REQUIRED_FUNCTION(EC_POINT_set_affine_coordinates_GFp) \
-    REQUIRED_FUNCTION(ENGINE_by_id) \
-    REQUIRED_FUNCTION(ENGINE_finish) \
-    REQUIRED_FUNCTION(ENGINE_free) \
-    REQUIRED_FUNCTION(ENGINE_init) \
-    REQUIRED_FUNCTION(ENGINE_load_public_key) \
-    REQUIRED_FUNCTION(ENGINE_load_private_key) \
+    LIGHTUP_FUNCTION(ENGINE_by_id) \
+    LIGHTUP_FUNCTION(ENGINE_finish) \
+    LIGHTUP_FUNCTION(ENGINE_free) \
+    LIGHTUP_FUNCTION(ENGINE_init) \
+    LIGHTUP_FUNCTION(ENGINE_load_public_key) \
+    LIGHTUP_FUNCTION(ENGINE_load_private_key) \
     REQUIRED_FUNCTION(ERR_clear_error) \
     REQUIRED_FUNCTION(ERR_error_string_n) \
     REQUIRED_FUNCTION(ERR_get_error) \
diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_crypto_config.h.in b/src/native/libs/System.Security.Cryptography.Native/pal_crypto_config.h.in
index d7aef5a7d1b674..30d1219eb98b0d 100644
--- a/src/native/libs/System.Security.Cryptography.Native/pal_crypto_config.h.in
+++ b/src/native/libs/System.Security.Cryptography.Native/pal_crypto_config.h.in
@@ -4,3 +4,4 @@
 #cmakedefine01 HAVE_OPENSSL_ALPN
 #cmakedefine01 HAVE_OPENSSL_CHACHA20POLY1305
 #cmakedefine01 HAVE_OPENSSL_SHA3
+#cmakedefine01 HAVE_OPENSSL_ENGINE
diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c b/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c
index 80183b97a77c90..dea4f277b8969d 100644
--- a/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c
+++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c
@@ -511,41 +511,72 @@ int32_t CryptoNative_EncodeSubjectPublicKeyInfo(EVP_PKEY* pkey, uint8_t* buf)
     return i2d_PUBKEY(pkey, &buf);
 }
 
+#if HAVE_OPENSSL_ENGINE
 static EVP_PKEY* LoadKeyFromEngine(
     const char* engineName,
     const char* keyName,
-    ENGINE_LOAD_KEY_PTR load_func)
+    ENGINE_LOAD_KEY_PTR load_func,
+    int32_t* haveEngine)
 {
+    assert(haveEngine);
     ERR_clear_error();
 
-    EVP_PKEY* ret = NULL;
-    ENGINE* engine = NULL;
+    if (API_EXISTS(ENGINE_by_id) && API_EXISTS(ENGINE_init) && API_EXISTS(ENGINE_finish) && API_EXISTS(ENGINE_free))
+    {
+        *haveEngine = 1;
+        EVP_PKEY* ret = NULL;
+        ENGINE* engine = NULL;
 
-    // Per https://github.com/openssl/openssl/discussions/21427
-    // using EVP_PKEY after freeing ENGINE is correct.
-    engine = ENGINE_by_id(engineName);
+        // Per https://github.com/openssl/openssl/discussions/21427
+        // using EVP_PKEY after freeing ENGINE is correct.
+        engine = ENGINE_by_id(engineName);
 
-    if (engine != NULL)
-    {
-        if (ENGINE_init(engine))
+        if (engine != NULL)
         {
-            ret = load_func(engine, keyName, NULL, NULL);
+            if (ENGINE_init(engine))
+            {
+                ret = load_func(engine, keyName, NULL, NULL);
+
+                ENGINE_finish(engine);
+            }
 
-            ENGINE_finish(engine);
+            ENGINE_free(engine);
         }
 
-        ENGINE_free(engine);
+        return ret;
     }
 
-    return ret;
+    *haveEngine = 0;
+    return NULL;
 }
+#endif
 
-EVP_PKEY* CryptoNative_LoadPrivateKeyFromEngine(const char* engineName, const char* keyName)
+EVP_PKEY* CryptoNative_LoadPrivateKeyFromEngine(const char* engineName, const char* keyName, int32_t* haveEngine)
 {
-    return LoadKeyFromEngine(engineName, keyName, ENGINE_load_private_key);
+#if HAVE_OPENSSL_ENGINE
+    if (API_EXISTS(ENGINE_load_private_key))
+    {
+        return LoadKeyFromEngine(engineName, keyName, ENGINE_load_private_key, haveEngine);
+    }
+#endif
+    (void)engineName;
+    (void)keyName;
+    (void)haveEngine;
+    *haveEngine = 0;
+    return NULL;
 }
 
-EVP_PKEY* CryptoNative_LoadPublicKeyFromEngine(const char* engineName, const char* keyName)
+EVP_PKEY* CryptoNative_LoadPublicKeyFromEngine(const char* engineName, const char* keyName, int32_t* haveEngine)
 {
-    return LoadKeyFromEngine(engineName, keyName, ENGINE_load_public_key);
+#if HAVE_OPENSSL_ENGINE
+    if (API_EXISTS(ENGINE_load_private_key))
+    {
+        return LoadKeyFromEngine(engineName, keyName, ENGINE_load_public_key, haveEngine);
+    }
+#endif
+    (void)engineName;
+    (void)keyName;
+    (void)haveEngine;
+    *haveEngine = 0;
+    return NULL;
 }
diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h b/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h
index 64d289dc6f4884..e4d5f85d4b9ec3 100644
--- a/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h
+++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h
@@ -93,12 +93,14 @@ PALEXPORT int32_t CryptoNative_EncodeSubjectPublicKeyInfo(EVP_PKEY* pkey, uint8_
 Load a named key, via ENGINE_load_private_key, from the named engine.
 
 Returns a valid EVP_PKEY* on success, NULL on failure.
+haveEngine is 1 if OpenSSL ENGINE's are supported, otherwise 0.
 */
-PALEXPORT EVP_PKEY* CryptoNative_LoadPrivateKeyFromEngine(const char* engineName, const char* keyName);
+PALEXPORT EVP_PKEY* CryptoNative_LoadPrivateKeyFromEngine(const char* engineName, const char* keyName, int32_t* haveEngine);
 
 /*
 Load a named key, via ENGINE_load_public_key, from the named engine.
 
 Returns a valid EVP_PKEY* on success, NULL on failure.
+haveEngine is 1 if OpenSSL ENGINE's are supported, otherwise 0.
 */
-PALEXPORT EVP_PKEY* CryptoNative_LoadPublicKeyFromEngine(const char* engineName, const char* keyName);
+PALEXPORT EVP_PKEY* CryptoNative_LoadPublicKeyFromEngine(const char* engineName, const char* keyName, int32_t* haveEngine);
diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonBuilderHelper.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonBuilderHelper.cs
index 07c05113ac843f..748283e74e673b 100644
--- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonBuilderHelper.cs
+++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonBuilderHelper.cs
@@ -10,7 +10,7 @@
 
 namespace Microsoft.NET.Sdk.WebAssembly
 {
-    public class BootJsonBuilderHelper(TaskLoggingHelper Log)
+    public class BootJsonBuilderHelper(TaskLoggingHelper Log, string DebugLevel, bool IsPublish)
     {
         public void ComputeResourcesHash(BootJsonData bootConfig)
         {
@@ -73,5 +73,35 @@ static void AddDictionary(StringBuilder sb, Dictionary<string, string>? res)
 
             return null;
         }
+
+        public int GetDebugLevel(bool hasPdb)
+        {
+            int? debugLevel = ParseOptionalInt(DebugLevel);
+
+            // If user didn't give us a value, check if we have any PDB.
+            if (debugLevel == null && hasPdb)
+                debugLevel = -1;
+
+            // Fallback to -1 for build, or 0 for publish
+            debugLevel ??= IsPublish ? 0 : -1;
+
+            return debugLevel.Value;
+        }
+
+        public bool? ParseOptionalBool(string value)
+        {
+            if (string.IsNullOrEmpty(value) || !bool.TryParse(value, out var boolValue))
+                return null;
+
+            return boolValue;
+        }
+
+        public int? ParseOptionalInt(string value)
+        {
+            if (string.IsNullOrEmpty(value) || !int.TryParse(value, out var intValue))
+                return null;
+
+            return intValue;
+        }
     }
 }
diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs
index ef42b6fa952f10..3f12c54e07f9c5 100644
--- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs
+++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs
@@ -71,6 +71,8 @@ public class GenerateWasmBootJson : Task
 
     public ITaskItem[] LazyLoadedAssemblies { get; set; }
 
+    public bool IsPublish { get; set; }
+
     public override bool Execute()
     {
         using var fileStream = File.Create(OutputPath);
@@ -91,17 +93,16 @@ public override bool Execute()
     // Internal for tests
     public void WriteBootJson(Stream output, string entryAssemblyName)
     {
-        var helper = new BootJsonBuilderHelper(Log);
+        var helper = new BootJsonBuilderHelper(Log, DebugLevel, IsPublish);
 
         var result = new BootJsonData
         {
             resources = new ResourcesData(),
-            startupMemoryCache = ParseOptionalBool(StartupMemoryCache),
+            startupMemoryCache = helper.ParseOptionalBool(StartupMemoryCache),
         };
 
         if (IsTargeting80OrLater())
         {
-            result.debugLevel = ParseOptionalInt(DebugLevel) ?? (DebugBuild ? 1 : 0);
             result.mainAssemblyName = entryAssemblyName;
             result.globalizationMode = GetGlobalizationMode().ToString().ToLowerInvariant();
 
@@ -127,7 +128,7 @@ public void WriteBootJson(Stream output, string entryAssemblyName)
             result.runtimeOptions = runtimeOptions;
         }
 
-        bool? jiterpreter = ParseOptionalBool(Jiterpreter);
+        bool? jiterpreter = helper.ParseOptionalBool(Jiterpreter);
         if (jiterpreter != null)
         {
             var runtimeOptions = result.runtimeOptions?.ToHashSet() ?? new HashSet<string>(3);
@@ -329,6 +330,20 @@ public void WriteBootJson(Stream output, string entryAssemblyName)
             }
         }
 
+        if (IsTargeting80OrLater())
+        {
+            int? debugLevel = helper.ParseOptionalInt(DebugLevel);
+
+            // If user didn't give us a value, check if we have any PDB.
+            if (debugLevel == null && result.resources?.pdb?.Count > 0)
+                debugLevel = -1;
+
+            // Fallback to -1 for build, or 0 for publish
+            debugLevel ??= IsPublish ? 0 : -1;
+
+            result.debugLevel = debugLevel.Value;
+        }
+
         if (ConfigurationFiles != null)
         {
             foreach (var configFile in ConfigurationFiles)
@@ -394,22 +409,6 @@ private GlobalizationMode GetGlobalizationMode()
         return GlobalizationMode.Sharded;
     }
 
-    private static bool? ParseOptionalBool(string value)
-    {
-        if (string.IsNullOrEmpty(value) || !bool.TryParse(value, out var boolValue))
-            return null;
-
-        return boolValue;
-    }
-
-    private static int? ParseOptionalInt(string value)
-    {
-        if (string.IsNullOrEmpty(value) || !int.TryParse(value, out var intValue))
-            return null;
-
-        return intValue;
-    }
-
     private void AddToAdditionalResources(ITaskItem resource, Dictionary<string, AdditionalAsset> additionalResources, string resourceName, string behavior)
     {
         if (!additionalResources.ContainsKey(resourceName))
diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs
index 9c7d8a6799134e..d5e2aa53e14862 100644
--- a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs
+++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs
@@ -27,6 +27,8 @@ public class WasmAppBuilder : WasmAppBuilderBaseTask
     public bool WasmIncludeFullIcuData { get; set; }
     public string? WasmIcuDataFileName { get; set; }
     public string? RuntimeAssetsLocation { get; set; }
+    public string? DebugLevel { get; set; }
+    public bool IsPublish { get; set; }
 
     // <summary>
     // Extra json elements to add to _framework/blazor.boot.json
@@ -83,7 +85,7 @@ private GlobalizationMode GetGlobalizationMode()
 
     protected override bool ExecuteInternal()
     {
-        var helper = new BootJsonBuilderHelper(Log);
+        var helper = new BootJsonBuilderHelper(Log, DebugLevel!, IsPublish);
 
         if (!ValidateArguments())
             return false;
@@ -115,6 +117,8 @@ protected override bool ExecuteInternal()
         if (UseWebcil)
             Log.LogMessage(MessageImportance.Normal, "Converting assemblies to Webcil");
 
+        int baseDebugLevel = helper.GetDebugLevel(false);
+
         foreach (var assembly in _assemblies)
         {
             if (UseWebcil)
@@ -133,7 +137,7 @@ protected override bool ExecuteInternal()
             {
                 FileCopyChecked(assembly, Path.Combine(runtimeAssetsPath, Path.GetFileName(assembly)), "Assemblies");
             }
-            if (DebugLevel != 0)
+            if (baseDebugLevel != 0)
             {
                 var pdb = assembly;
                 pdb = Path.ChangeExtension(pdb, ".pdb");
@@ -191,7 +195,7 @@ protected override bool ExecuteInternal()
                 }
 
                 bootConfig.resources.assembly[Path.GetFileName(assemblyPath)] = Utils.ComputeIntegrity(bytes);
-                if (DebugLevel != 0)
+                if (baseDebugLevel != 0)
                 {
                     var pdb = Path.ChangeExtension(assembly, ".pdb");
                     if (File.Exists(pdb))
@@ -205,7 +209,7 @@ protected override bool ExecuteInternal()
             }
         }
 
-        bootConfig.debugLevel = DebugLevel;
+        bootConfig.debugLevel = helper.GetDebugLevel(bootConfig.resources.pdb?.Count > 0);
 
         ProcessSatelliteAssemblies(args =>
         {
diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilderBaseTask.cs b/src/tasks/WasmAppBuilder/WasmAppBuilderBaseTask.cs
index c533e404c41739..feee565ad4f6cc 100644
--- a/src/tasks/WasmAppBuilder/WasmAppBuilderBaseTask.cs
+++ b/src/tasks/WasmAppBuilder/WasmAppBuilderBaseTask.cs
@@ -36,7 +36,6 @@ public abstract class WasmAppBuilderBaseTask : Task
     // https://github.com/dotnet/icu/tree/maint/maint-67/icu-filters
     public string[] IcuDataFileNames { get; set; } = Array.Empty<string>();
 
-    public int DebugLevel { get; set; }
     public ITaskItem[] SatelliteAssemblies { get; set; } = Array.Empty<ITaskItem>();
     public bool HybridGlobalization { get; set; }
     public bool InvariantGlobalization { get; set; }
diff --git a/src/tasks/WasmAppBuilder/wasi/WasiAppBuilder.cs b/src/tasks/WasmAppBuilder/wasi/WasiAppBuilder.cs
index 0974904e6627bd..521284dd56c779 100644
--- a/src/tasks/WasmAppBuilder/wasi/WasiAppBuilder.cs
+++ b/src/tasks/WasmAppBuilder/wasi/WasiAppBuilder.cs
@@ -11,6 +11,7 @@ namespace Microsoft.WebAssembly.Build.Tasks;
 public class WasiAppBuilder : WasmAppBuilderBaseTask
 {
     public bool IsSingleFileBundle { get; set; }
+    public bool OutputSymbolsToAppBundle { get; set; }
 
     protected override bool ValidateArguments()
     {
@@ -53,7 +54,7 @@ protected override bool ExecuteInternal()
             {
                 FileCopyChecked(assembly, Path.Combine(asmRootPath, Path.GetFileName(assembly)), "Assemblies");
 
-                if (DebugLevel != 0)
+                if (OutputSymbolsToAppBundle)
                 {
                     string pdb = Path.ChangeExtension(assembly, ".pdb");
                     if (File.Exists(pdb))
diff --git a/src/tests/JIT/Directed/tls/CMakeLists.txt b/src/tests/JIT/Directed/tls/CMakeLists.txt
new file mode 100644
index 00000000000000..3eaf0d3b22a0c0
--- /dev/null
+++ b/src/tests/JIT/Directed/tls/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+
+include_directories(${INC_PLATFORM_DIR})
+
+add_library(usetls SHARED testtls.cpp)
+
+install (TARGETS usetls DESTINATION bin)
diff --git a/src/tests/JIT/Directed/tls/TestTLSWithLoadedDlls.cs b/src/tests/JIT/Directed/tls/TestTLSWithLoadedDlls.cs
new file mode 100644
index 00000000000000..18385bb14cd612
--- /dev/null
+++ b/src/tests/JIT/Directed/tls/TestTLSWithLoadedDlls.cs
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+
+// This test is verifying that the runtime properly handles the cases where the TLS infra in the runtime is forced
+// to use a dynamic resolver. This is done by means of a private config variable to validate the behavior on Linux Arm64
+// and a set of multithreaded tasks, that has been known to cause the runtime to crash when this is handled incorrectly.
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.Loader;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace TestTLSWithLoadedDlls
+{
+    static class TLSWithLoadedDlls
+    {
+        private const int CountOfLibTlsToLoad = 40;
+
+        static async Task DoLotsOfAsyncWork(int loopCount)
+        {
+            for (int i = 0; i < loopCount; i++)
+            {
+                Console.WriteLine("Starting a new batch of tasks...");
+                var tasks = Enumerable.Range(1, 100).Select(i => Task.Run(async () =>
+                {
+                    await Task.Delay(1);
+                })).ToArray();
+
+                await Task.WhenAll(tasks);
+
+                Console.WriteLine("Batch of tasks completed. Main loop sleeping for 20 ms...");
+                await Task.Delay(20);
+            }
+        }
+
+        static int Main(string[] args)
+        {
+            if ((args.Length == 1) && (args[0] == "RunLotsOfTasks"))
+            {
+                DoLotsOfAsyncWork(100).GetAwaiter().GetResult();
+                return 100;
+            }
+
+            int CountOfLibTlsToLoad = 60;
+
+            if (OperatingSystem.IsWindows()) // Windows does not have a really long command line length limit, and doesn't have a problem with many TLS using images used
+                CountOfLibTlsToLoad = 10;
+
+            StringBuilder arguments = new();
+
+            (string prefix, string suffix) = GetSharedLibraryPrefixSuffix();
+
+            string UseTlsFileName = GetSharedLibraryFileNameForCurrentPlatform("usetls");
+            string testDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
+            string UseTlsFilePath = Path.Combine(testDirectory, UseTlsFileName);
+
+            for (int i = 0; i < CountOfLibTlsToLoad; i++)
+            {
+                string tlsNumberSpecificPath = Path.Combine(testDirectory, i.ToString());
+                string finalUseTlsPath = Path.Combine(tlsNumberSpecificPath, prefix + "usetls" + suffix);
+
+                Directory.CreateDirectory(tlsNumberSpecificPath);
+                if (!File.Exists(finalUseTlsPath))
+                {
+                    File.Copy(
+                        UseTlsFilePath,
+                        finalUseTlsPath);
+                }
+
+                arguments.Append(" -l ");
+                arguments.Append(finalUseTlsPath);
+            }
+
+            arguments.Append(' ');
+            arguments.Append(System.Reflection.Assembly.GetExecutingAssembly().Location);
+            arguments.Append(" RunLotsOfTasks");
+
+            Process process = new Process();
+            process.StartInfo.FileName = GetCorerunPath();
+            process.StartInfo.Arguments = arguments.ToString();
+            process.StartInfo.UseShellExecute = false;
+            process.StartInfo.EnvironmentVariables["DOTNET_AssertNotStaticTlsResolver"] = "1";
+
+            Console.WriteLine($"Launching {process.StartInfo.FileName} {process.StartInfo.Arguments}");
+
+            process.Start();
+            process.WaitForExit();
+            return process.ExitCode;
+        }
+
+        private static string GetCorerunPath()
+        {
+            string corerunName;
+            if (OperatingSystem.IsWindows())
+            {
+                corerunName = "CoreRun.exe";
+            }
+            else
+            {
+                corerunName = "corerun";
+            }
+
+            return Path.Combine(Environment.GetEnvironmentVariable("CORE_ROOT"), corerunName);
+        }
+
+        public static (string, string) GetSharedLibraryPrefixSuffix()
+        {
+            if (OperatingSystem.IsWindows())
+                return (string.Empty, ".dll");
+
+            if (OperatingSystem.IsMacOS())
+                return ("lib", ".dylib");
+
+            return ("lib", ".so");
+        }
+
+        public static string GetSharedLibraryFileNameForCurrentPlatform(string libraryName)
+        {
+            (string prefix, string suffix) = GetSharedLibraryPrefixSuffix();
+            return prefix + libraryName + suffix;
+        }
+    }
+}
diff --git a/src/tests/JIT/Directed/tls/TestTLSWithLoadedDlls.csproj b/src/tests/JIT/Directed/tls/TestTLSWithLoadedDlls.csproj
new file mode 100644
index 00000000000000..c17a210af0c9de
--- /dev/null
+++ b/src/tests/JIT/Directed/tls/TestTLSWithLoadedDlls.csproj
@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <CLRTestPriority>0</CLRTestPriority>
+    <RequiresProcessIsolation>true</RequiresProcessIsolation>
+    <ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>
+    <NativeAotIncompatible>true</NativeAotIncompatible>
+  </PropertyGroup>
+  <PropertyGroup>
+    <DebugType>PdbOnly</DebugType>
+    <Optimize>True</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildProjectName).cs" />
+    <CMakeProjectReference Include="CMakeLists.txt" />
+  </ItemGroup>
+</Project>
diff --git a/src/tests/JIT/Directed/tls/testtls.cpp b/src/tests/JIT/Directed/tls/testtls.cpp
new file mode 100644
index 00000000000000..24dfbe5d0af2c3
--- /dev/null
+++ b/src/tests/JIT/Directed/tls/testtls.cpp
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#ifdef _MSC_VER
+#define DLLEXPORT __declspec(dllexport)
+#else
+#define DLLEXPORT __attribute__((visibility("default")))
+#endif // _MSC_VER
+
+thread_local int tls0; 
+thread_local int tls1;
+thread_local int tls2;
+thread_local int tls3;
+thread_local int tls4;
+thread_local int tls5;
+thread_local int tls6;
+thread_local int tls7;
+thread_local int tls8;
+thread_local int tls9;
+thread_local int tls10;
+thread_local int tls11;
+thread_local int tls12;
+thread_local int tls13;
+thread_local int tls14;
+thread_local int tls15;
+thread_local int tls16;
+
+extern "C" DLLEXPORT void initializeTLS() {
+    tls0=0;
+    tls1=0;
+    tls2=0;
+    tls3=0;
+    tls4=0;
+    tls5=0;
+    tls6=0;
+    tls7=0;
+    tls8=0;
+    tls9=0;
+    tls10=0;
+    tls11=0;
+    tls12=0;
+    tls13=0;
+    tls14=0;
+    tls15=0;
+    tls16=0;
+}
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_96156/Runtime_96156.cs b/src/tests/JIT/Regression/JitBlue/Runtime_96156/Runtime_96156.cs
new file mode 100644
index 00000000000000..15fe1b0f93842b
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_96156/Runtime_96156.cs
@@ -0,0 +1,34 @@
+﻿// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+public class Runtime_96156
+{
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private unsafe static Vector128<float> BroadcastScalarToVector128(float value)
+    {
+        return Avx.BroadcastScalarToVector128(&value);
+    }
+
+    [Fact]
+    public static void TestEntryPoint()
+    {
+        if (Avx.IsSupported)
+        {
+            Vector128<float> c = Vector128.Create(1.0f);
+            Vector128<float> r = Problem(2.0f, 0.5f, c);
+            Assert.Equal(Vector128.Create(4.0f), r);
+        }
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    private static Vector128<float> Problem(float a, float b, Vector128<float> c)
+    {
+        return Avx.Multiply(c, BroadcastScalarToVector128(a / b));
+    }
+}
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_96156/Runtime_96156.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_96156/Runtime_96156.csproj
new file mode 100644
index 00000000000000..37d1a42b02dbe1
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_96156/Runtime_96156.csproj
@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+    <Optimize>True</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildProjectName).cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <CLRTestEnvironmentVariable Include="DOTNET_EnableAVX512F" Value="0" />
+    <CLRTestEnvironmentVariable Include="DOTNET_TieredCompilation" Value="0" />
+  </ItemGroup>
+</Project>
diff --git a/src/tests/profiler/native/profiler.def b/src/tests/profiler/native/profiler.def
index 37a59858dbfe0a..11976272a21331 100644
--- a/src/tests/profiler/native/profiler.def
+++ b/src/tests/profiler/native/profiler.def
@@ -5,4 +5,5 @@ EXPORTS
             DllCanUnloadNow         PRIVATE
             PassCallbackToProfiler  PRIVATE
             DoPInvoke               PRIVATE
+            DoPInvokeWithCallbackOnOtherThread PRIVATE
 
diff --git a/src/tests/profiler/native/transitions/transitions.cpp b/src/tests/profiler/native/transitions/transitions.cpp
index 13984e0837cb2e..3966c887440e9a 100644
--- a/src/tests/profiler/native/transitions/transitions.cpp
+++ b/src/tests/profiler/native/transitions/transitions.cpp
@@ -69,6 +69,14 @@ extern "C" EXPORT void STDMETHODCALLTYPE DoPInvoke(int(*callback)(int), int i)
     printf("PInvoke received i=%d\n", callback(i));
 }
 
+extern "C" EXPORT void STDMETHODCALLTYPE DoPInvokeWithCallbackOnOtherThread(int(*callback)(int), int i)
+{
+    int j = 0;
+    std::thread t([&j, callback, i] { j = callback(i); });
+    t.join();
+    printf("PInvoke with callback on other thread received i=%d\n", j);
+}
+
 
 HRESULT Transitions::UnmanagedToManagedTransition(FunctionID functionID, COR_PRF_TRANSITION_REASON reason)
 {
@@ -124,4 +132,4 @@ bool Transitions::FunctionIsTargetFunction(FunctionID functionID, TransitionInst
     }
 
     return true;
-}
\ No newline at end of file
+}
diff --git a/src/tests/profiler/transitions/transitions.cs b/src/tests/profiler/transitions/transitions.cs
index b513d9c7717def..d0d6a7df67825c 100644
--- a/src/tests/profiler/transitions/transitions.cs
+++ b/src/tests/profiler/transitions/transitions.cs
@@ -32,7 +32,7 @@ private static int DoDelegateReversePInvokeNonBlittable(bool b)
         public static int BlittablePInvokeToBlittableInteropDelegate()
         {
             InteropDelegate del = DoDelegateReversePInvoke;
-            
+
             DoPInvoke((delegate* unmanaged<int,int>)Marshal.GetFunctionPointerForDelegate(del), 13);
             GC.KeepAlive(del);
 
@@ -42,13 +42,23 @@ public static int BlittablePInvokeToBlittableInteropDelegate()
         public static int NonBlittablePInvokeToNonBlittableInteropDelegate()
         {
             InteropDelegateNonBlittable del = DoDelegateReversePInvokeNonBlittable;
-            
+
             DoPInvokeNonBlitable((delegate* unmanaged<int,int>)Marshal.GetFunctionPointerForDelegate(del), true);
             GC.KeepAlive(del);
 
             return 100;
         }
 
+        public static int BlittablePInvokeToBlittableInteropDelegateOnOtherThread()
+        {
+            InteropDelegate del = DoDelegateReversePInvoke;
+
+            DoPInvokeWithCallbackOnOtherThread((delegate* unmanaged<int,int>)Marshal.GetFunctionPointerForDelegate(del), 13);
+            GC.KeepAlive(del);
+
+            return 100;
+        }
+
         [UnmanagedCallersOnly]
         private static int DoReversePInvoke(int i)
         {
@@ -61,6 +71,9 @@ private static int DoReversePInvoke(int i)
         [DllImport("Profiler", EntryPoint = nameof(DoPInvoke))]
         public static extern void DoPInvokeNonBlitable(delegate* unmanaged<int,int> callback, bool i);
 
+        [DllImport("Profiler")]
+        public static extern void DoPInvokeWithCallbackOnOtherThread(delegate* unmanaged<int,int> callback, int i);
+
         public static int BlittablePInvokeToUnmanagedCallersOnly()
         {
             DoPInvoke(&DoReversePInvoke, 13);
@@ -75,6 +88,13 @@ public static int NonBlittablePInvokeToUnmanagedCallersOnly()
             return 100;
         }
 
+        public static int BlittablePInvokeToUnmanagedCallersOnlyOnOtherThread()
+        {
+            DoPInvokeWithCallbackOnOtherThread(&DoReversePInvoke, 13);
+
+            return 100;
+        }
+
         public static int Main(string[] args)
         {
             if (args.Length > 1 && args[0].Equals("RunTest", StringComparison.OrdinalIgnoreCase))
@@ -89,6 +109,10 @@ public static int Main(string[] args)
                         return NonBlittablePInvokeToUnmanagedCallersOnly();
                     case nameof(NonBlittablePInvokeToNonBlittableInteropDelegate):
                         return NonBlittablePInvokeToNonBlittableInteropDelegate();
+                    case nameof(BlittablePInvokeToUnmanagedCallersOnlyOnOtherThread):
+                        return BlittablePInvokeToUnmanagedCallersOnlyOnOtherThread();
+                    case nameof(BlittablePInvokeToBlittableInteropDelegateOnOtherThread):
+                        return BlittablePInvokeToBlittableInteropDelegateOnOtherThread();
                 }
             }
 
@@ -104,12 +128,22 @@ public static int Main(string[] args)
 
             if (!RunProfilerTest(nameof(NonBlittablePInvokeToUnmanagedCallersOnly), nameof(DoPInvokeNonBlitable), nameof(DoReversePInvoke)))
             {
-                return 101;
+                return 103;
             }
 
             if (!RunProfilerTest(nameof(NonBlittablePInvokeToNonBlittableInteropDelegate), nameof(DoPInvokeNonBlitable), "Invoke"))
             {
-                return 102;
+                return 104;
+            }
+
+            if (!RunProfilerTest(nameof(BlittablePInvokeToUnmanagedCallersOnlyOnOtherThread), nameof(DoPInvokeWithCallbackOnOtherThread), nameof(DoReversePInvoke)))
+            {
+                return 105;
+            }
+
+            if (!RunProfilerTest(nameof(BlittablePInvokeToBlittableInteropDelegateOnOtherThread), nameof(DoPInvokeWithCallbackOnOtherThread), "Invoke"))
+            {
+                return 106;
             }
 
             return 100;
