diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 168fe4b760f5cd0e8de1014e5c4ed873f20599e4..107469465fa423d55fd282b6592bc3af8e734d2f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -2,7 +2,7 @@ variables:
   GIT_SSL_NO_VERIFY: "1"
 
   # Commit of ghc/ci-images repository from which to pull Docker images
-  DOCKER_REV: 59da90988f9f3caa36572bf47d5f78704a969dea
+  DOCKER_REV: 6e9f8f17086e56e83adae4a8a9d63e2fec3cb6c7
 
   # Sequential version number of all cached things.
   # Bump to invalidate GitLab CI cache.
diff --git a/.gitlab/ci.sh b/.gitlab/ci.sh
index 33574ac7f11800a71f569e9ca3ee2f6cc3ab8ae6..59b8d09104bfac20b1f503c02f733d08c37f8f4a 100755
--- a/.gitlab/ci.sh
+++ b/.gitlab/ci.sh
@@ -561,9 +561,17 @@ function install_bindist() {
     *)
       read -r -a args <<< "${INSTALL_CONFIGURE_ARGS:-}"
 
+      if [[ "${CROSS_TARGET:-no_cross_target}" =~ "mingw" ]]; then
+          # We suppose that host target = build target.
+          # By the fact above it is clearly turning out which host value is
+          # for currently built compiler.
+          # The fix for #21970 will probably remove this if-branch.
+          local -r CROSS_HOST_GUESS=$($SHELL ./config.guess)
+          args+=( "--target=$CROSS_TARGET" "--host=$CROSS_HOST_GUESS" )
+
       # FIXME: The bindist configure script shouldn't need to be reminded of
       # the target platform. See #21970.
-      if [ -n "${CROSS_TARGET:-}" ]; then
+      elif [ -n "${CROSS_TARGET:-}" ]; then
           args+=( "--target=$CROSS_TARGET" "--host=$CROSS_TARGET" )
       fi
 
@@ -572,7 +580,7 @@ function install_bindist() {
           "${args[@]+"${args[@]}"}" || fail "bindist configure failed"
       make_install_destdir "$TOP"/destdir "$instdir"
       # And check the `--info` of the installed compiler, sometimes useful in CI log.
-      "$instdir"/bin/ghc --info
+      "$instdir/bin/${cross_prefix}ghc$exe" --info
       ;;
   esac
   popd
@@ -629,8 +637,23 @@ function test_hadrian() {
     install_bindist _build/bindist/ghc-*/ "$instdir"
     echo 'main = putStrLn "hello world"' > expected
     run "$test_compiler" -package ghc "$TOP/.gitlab/hello.hs" -o hello
-    ${CROSS_EMULATOR:-} ./hello > actual
-    run diff expected actual
+
+    if [[ "${CROSS_TARGET:-no_cross_target}" =~ "mingw" ]]; then
+      ${CROSS_EMULATOR:-} ./hello.exe > actual
+    else
+      ${CROSS_EMULATOR:-} ./hello > actual
+    fi
+
+    # We have to use `-w` to make the test more stable across supported
+    # platforms, i.e. Windows:
+    # $ cmp expected actual
+    # differ: byte 30, line 1
+    # $ diff expected actual
+    # 1c1
+    # < main = putStrLn "hello world"
+    # ---
+    # > main = putStrLn "hello world"
+    run diff -w expected actual
   elif [[ -n "${REINSTALL_GHC:-}" ]]; then
     run_hadrian \
       test \
diff --git a/.gitlab/generate-ci/gen_ci.hs b/.gitlab/generate-ci/gen_ci.hs
index ed285ca703a050508fa60066cc157284814cb9ff..de041435e7b0aaafe2ca0cac3655f7401b6fa963 100644
--- a/.gitlab/generate-ci/gen_ci.hs
+++ b/.gitlab/generate-ci/gen_ci.hs
@@ -112,6 +112,7 @@ data Opsys
 
 data LinuxDistro
   = Debian12
+  | Debian12Wine
   | Debian12Riscv
   | Debian11
   | Debian11Js
@@ -315,6 +316,7 @@ distroName Debian12      = "deb12"
 distroName Debian11      = "deb11"
 distroName Debian11Js    = "deb11-emsdk-closure"
 distroName Debian12Riscv = "deb12-riscv"
+distroName Debian12Wine  = "deb12-wine"
 distroName Debian10      = "deb10"
 distroName Debian9       = "deb9"
 distroName Fedora33      = "fedora33"
@@ -724,6 +726,8 @@ data ValidateRule
   | IpeData      -- ^ Run this job when the "IPE" label is set
   | TestPrimops  -- ^ Run this job when "test-primops" label is set
   | I386Backend  -- ^ Run this job when the "i386" label is set
+  | WinArm64     -- ^ Run this job when the "aarch64" and "Windows" labels are set together without "LLVM backend"
+  | WinArm64LLVM -- ^ Run this job when the "aarch64" and "Windows" labels are set together with "LLVM backend"
   deriving (Show, Ord, Eq)
 
 -- | Convert the state of the rule into a string that gitlab understand.
@@ -768,6 +772,15 @@ validateRuleString NonmovingGc  = labelString "non-moving GC"
 validateRuleString IpeData      = labelString "IPE"
 validateRuleString TestPrimops  = labelString "test-primops"
 validateRuleString I386Backend  = labelString "i386"
+validateRuleString WinArm64     = and_all
+                                    [ labelString "aarch64"
+                                    , labelString "Windows"
+                                    ]
+validateRuleString WinArm64LLVM = and_all
+                                    [ labelString "aarch64"
+                                    , labelString "Windows"
+                                    , validateRuleString LLVMBackend
+                                    ]
 
 ---------------------------------------------------------------------
 -- The Job type
@@ -1260,11 +1273,51 @@ cross_jobs = [
       make_wasm_jobs wasm_build_config {bignumBackend = Native}
   , modifyValidateJobs manual $
       make_wasm_jobs wasm_build_config {unregisterised = True}
+
+    -- Linux Aarch64 (Wine + FEX + MSYS64) => Windows Aarch64
+  , makeWinArmJobs
+      $ addValidateRule WinArm64
+        (validateBuilds AArch64 (Linux Debian12Wine) winAarch64Config)
+  , makeWinArmJobs
+      $ addValidateRule WinArm64LLVM
+        (validateBuilds AArch64 (Linux Debian12Wine) (winAarch64Config {llvmBootstrap = True}))
   ]
   where
     javascriptConfig = (crossConfig "javascript-unknown-ghcjs" (Emulator "js-emulator") (Just "emconfigure"))
                          { bignumBackend = Native }
 
+    makeWinArmJobs = modifyJobs
+        ( -- Cross compiler validate does not need any docs
+          setVariable "HADRIAN_ARGS" "--docs=none"
+        . setVariable "AR" (llvm_prefix ++ "llvm-ar")
+        . setVariable "CC" (llvm_prefix ++ "clang")
+        . setVariable "CXX" (llvm_prefix ++ "clang++")
+        . setVariable "NM" (llvm_prefix ++ "nm")
+        . setVariable "OBJCOPY" (llvm_prefix ++ "objcopy")
+        . setVariable "OBJDUMP" (llvm_prefix ++ "objdump")
+        . setVariable "RANLIB" (llvm_prefix ++ "llvm-ranlib")
+        . setVariable "SIZE" (llvm_prefix ++ "size")
+        . setVariable "STRINGS" (llvm_prefix ++ "strings")
+        . setVariable "STRIP" (llvm_prefix ++ "strip")
+        . setVariable "WindresCmd" (llvm_prefix ++ "windres")
+        . setVariable "LLVMAS" (llvm_prefix ++ "clang")
+        . setVariable "LD" (llvm_prefix ++ "ld")
+          -- Windows target require to make linker merge feature check disabled.
+        . setVariable "MergeObjsCmd" ""
+          -- LLVM MinGW Linux Toolchain expects to recieve "aarch64-w64-mingw32"
+          -- as a triple but we use more common "aarch64-unknown-mingw32".
+          -- Due of this we need configure ld manually for clang beacause
+          -- it will use system's ld otherwise when --target will be specified to
+          -- unexpected triple.
+        . setVariable "CFLAGS" cflags
+        . setVariable "CONF_CC_OPTS_STAGE2" cflags
+        ) where
+            llvm_prefix = "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-"
+            cflags = "-fuse-ld=" ++ llvm_prefix ++ "ld --rtlib=compiler-rt"
+
+    winAarch64Config = (crossConfig "aarch64-unknown-mingw32" (Emulator "/opt/wine-arm64ec-msys2-deb12/bin/wine") Nothing)
+                         { bignumBackend = Native }
+
     make_wasm_jobs cfg =
       modifyJobs
         ( -- See Note [Testing wasm ghci browser mode]
@@ -1323,6 +1376,7 @@ platform_mapping = Map.map go combined_result
                 , "x86_64-linux-deb11-cross_aarch64-linux-gnu-validate"
                 , "x86_64-windows-validate"
                 , "aarch64-linux-deb12-validate"
+                , "aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate"
                 , "nightly-x86_64-linux-alpine3_20-wasm-cross_wasm32-wasi-release+host_fully_static+text_simdutf"
                 , "nightly-x86_64-linux-deb11-validate"
                 , "nightly-x86_64-linux-deb12-validate"
@@ -1330,6 +1384,7 @@ platform_mapping = Map.map go combined_result
                 , "x86_64-linux-deb12-validate+thread_sanitizer_cmm"
                 , "nightly-aarch64-linux-deb10-validate"
                 , "nightly-aarch64-linux-deb12-validate"
+                , "nightly-aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate"
                 , "nightly-x86_64-linux-alpine3_12-validate"
                 , "nightly-x86_64-linux-deb10-validate"
                 , "nightly-x86_64-linux-fedora33-release"
diff --git a/.gitlab/hello.hs b/.gitlab/hello.hs
index 4b1c65932ccd33da02ef16fd64f67a324b9983cb..486778c3a414327dc3f711d476403eaa19d3e1c5 100644
--- a/.gitlab/hello.hs
+++ b/.gitlab/hello.hs
@@ -1,6 +1,5 @@
 {-# OPTIONS_GHC -Wall -Wno-missing-fields #-}
 
-import GHC.Unit.Types (stringToUnitId)
 import GHC hiding (parseModule)
 import GHC.Data.StringBuffer
 import GHC.Driver.Config.Parser
diff --git a/.gitlab/jobs.yaml b/.gitlab/jobs.yaml
index 961d10794d362641a70adb2dd8385a2458a393b2..c26705a754e1a99e7d2a7616ae282f0d0424e250 100644
--- a/.gitlab/jobs.yaml
+++ b/.gitlab/jobs.yaml
@@ -315,6 +315,168 @@
       "TEST_ENV": "aarch64-linux-deb12-validate+llvm"
     }
   },
+  "aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate": {
+    "after_script": [
+      ".gitlab/ci.sh save_cache",
+      ".gitlab/ci.sh save_test_output",
+      ".gitlab/ci.sh clean",
+      "cat ci_timings"
+    ],
+    "allow_failure": false,
+    "artifacts": {
+      "expire_in": "2 weeks",
+      "paths": [
+        "ghc-aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate.tar.xz",
+        "junit.xml",
+        "unexpected-test-output.tar.gz"
+      ],
+      "reports": {
+        "junit": "junit.xml"
+      },
+      "when": "always"
+    },
+    "cache": {
+      "key": "aarch64-linux-deb12-wine-$CACHE_REV",
+      "paths": [
+        "cabal-cache",
+        "toolchain"
+      ]
+    },
+    "dependencies": [],
+    "image": "registry.gitlab.haskell.org/ghc/ci-images/aarch64-linux-deb12-wine:$DOCKER_REV",
+    "needs": [
+      {
+        "artifacts": false,
+        "job": "hadrian-ghc-in-ghci"
+      }
+    ],
+    "rules": [
+      {
+        "if": "((($ONLY_JOBS) && ($ONLY_JOBS =~ /.*\\baarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate(\\s|$).*/)) || (($ONLY_JOBS == null) && ((($CI_MERGE_REQUEST_LABELS =~ /.*full-ci.*/) || ($CI_MERGE_REQUEST_LABELS =~ /.*marge_bot_batch_merge_job.*/) || ($CI_COMMIT_BRANCH == \"master\") || ($CI_COMMIT_BRANCH =~ /ghc-[0-9]+\\.[0-9]+/)) || (($CI_MERGE_REQUEST_LABELS =~ /.*aarch64.*/) && ($CI_MERGE_REQUEST_LABELS =~ /.*Windows.*/))))) && ($RELEASE_JOB != \"yes\") && ($NIGHTLY == null)",
+        "when": "on_success"
+      }
+    ],
+    "script": [
+      "sudo chown ghc:ghc -R .",
+      ".gitlab/ci.sh setup",
+      ".gitlab/ci.sh configure",
+      ".gitlab/ci.sh build_hadrian",
+      ".gitlab/ci.sh test_hadrian"
+    ],
+    "stage": "full-build",
+    "tags": [
+      "aarch64-linux"
+    ],
+    "variables": {
+      "AR": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-llvm-ar",
+      "BIGNUM_BACKEND": "native",
+      "BIN_DIST_NAME": "ghc-aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate",
+      "BUILD_FLAVOUR": "validate",
+      "CC": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang",
+      "CFLAGS": "-fuse-ld=/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld --rtlib=compiler-rt",
+      "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
+      "CONF_CC_OPTS_STAGE2": "-fuse-ld=/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld --rtlib=compiler-rt",
+      "CROSS_EMULATOR": "/opt/wine-arm64ec-msys2-deb12/bin/wine",
+      "CROSS_TARGET": "aarch64-unknown-mingw32",
+      "CXX": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang++",
+      "HADRIAN_ARGS": "--docs=none",
+      "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
+      "LD": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld",
+      "LLVMAS": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang",
+      "MergeObjsCmd": "",
+      "NM": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-nm",
+      "OBJCOPY": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-objcopy",
+      "OBJDUMP": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-objdump",
+      "RANLIB": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-llvm-ranlib",
+      "RUNTEST_ARGS": "",
+      "SIZE": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-size",
+      "STRINGS": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-strings",
+      "STRIP": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-strip",
+      "TEST_ENV": "aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate",
+      "WindresCmd": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-windres"
+    }
+  },
+  "aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate+llvm": {
+    "after_script": [
+      ".gitlab/ci.sh save_cache",
+      ".gitlab/ci.sh save_test_output",
+      ".gitlab/ci.sh clean",
+      "cat ci_timings"
+    ],
+    "allow_failure": false,
+    "artifacts": {
+      "expire_in": "2 weeks",
+      "paths": [
+        "ghc-aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate+llvm.tar.xz",
+        "junit.xml",
+        "unexpected-test-output.tar.gz"
+      ],
+      "reports": {
+        "junit": "junit.xml"
+      },
+      "when": "always"
+    },
+    "cache": {
+      "key": "aarch64-linux-deb12-wine-$CACHE_REV",
+      "paths": [
+        "cabal-cache",
+        "toolchain"
+      ]
+    },
+    "dependencies": [],
+    "image": "registry.gitlab.haskell.org/ghc/ci-images/aarch64-linux-deb12-wine:$DOCKER_REV",
+    "needs": [
+      {
+        "artifacts": false,
+        "job": "hadrian-ghc-in-ghci"
+      }
+    ],
+    "rules": [
+      {
+        "if": "((($ONLY_JOBS) && ($ONLY_JOBS =~ /.*\\baarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate\\+llvm(\\s|$).*/)) || (($ONLY_JOBS == null) && ((($CI_MERGE_REQUEST_LABELS =~ /.*full-ci.*/) || ($CI_MERGE_REQUEST_LABELS =~ /.*marge_bot_batch_merge_job.*/) || ($CI_COMMIT_BRANCH == \"master\") || ($CI_COMMIT_BRANCH =~ /ghc-[0-9]+\\.[0-9]+/)) || (($CI_MERGE_REQUEST_LABELS =~ /.*aarch64.*/) && ($CI_MERGE_REQUEST_LABELS =~ /.*Windows.*/) && ($CI_MERGE_REQUEST_LABELS =~ /.*LLVM backend.*/))))) && ($RELEASE_JOB != \"yes\") && ($NIGHTLY == null)",
+        "when": "on_success"
+      }
+    ],
+    "script": [
+      "sudo chown ghc:ghc -R .",
+      ".gitlab/ci.sh setup",
+      ".gitlab/ci.sh configure",
+      ".gitlab/ci.sh build_hadrian",
+      ".gitlab/ci.sh test_hadrian"
+    ],
+    "stage": "full-build",
+    "tags": [
+      "aarch64-linux"
+    ],
+    "variables": {
+      "AR": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-llvm-ar",
+      "BIGNUM_BACKEND": "native",
+      "BIN_DIST_NAME": "ghc-aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate+llvm",
+      "BUILD_FLAVOUR": "validate+llvm",
+      "CC": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang",
+      "CFLAGS": "-fuse-ld=/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld --rtlib=compiler-rt",
+      "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
+      "CONF_CC_OPTS_STAGE2": "-fuse-ld=/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld --rtlib=compiler-rt",
+      "CROSS_EMULATOR": "/opt/wine-arm64ec-msys2-deb12/bin/wine",
+      "CROSS_TARGET": "aarch64-unknown-mingw32",
+      "CXX": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang++",
+      "HADRIAN_ARGS": "--docs=none",
+      "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
+      "LD": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld",
+      "LLVMAS": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang",
+      "MergeObjsCmd": "",
+      "NM": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-nm",
+      "OBJCOPY": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-objcopy",
+      "OBJDUMP": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-objdump",
+      "RANLIB": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-llvm-ranlib",
+      "RUNTEST_ARGS": "",
+      "SIZE": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-size",
+      "STRINGS": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-strings",
+      "STRIP": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-strip",
+      "TEST_ENV": "aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate+llvm",
+      "WindresCmd": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-windres"
+    }
+  },
   "i386-linux-alpine3_20-validate": {
     "after_script": [
       ".gitlab/ci.sh save_cache",
@@ -822,6 +984,170 @@
       "XZ_OPT": "-9"
     }
   },
+  "nightly-aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate": {
+    "after_script": [
+      ".gitlab/ci.sh save_cache",
+      ".gitlab/ci.sh save_test_output",
+      ".gitlab/ci.sh clean",
+      "cat ci_timings"
+    ],
+    "allow_failure": false,
+    "artifacts": {
+      "expire_in": "8 weeks",
+      "paths": [
+        "ghc-aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate.tar.xz",
+        "junit.xml",
+        "unexpected-test-output.tar.gz"
+      ],
+      "reports": {
+        "junit": "junit.xml"
+      },
+      "when": "always"
+    },
+    "cache": {
+      "key": "aarch64-linux-deb12-wine-$CACHE_REV",
+      "paths": [
+        "cabal-cache",
+        "toolchain"
+      ]
+    },
+    "dependencies": [],
+    "image": "registry.gitlab.haskell.org/ghc/ci-images/aarch64-linux-deb12-wine:$DOCKER_REV",
+    "needs": [
+      {
+        "artifacts": false,
+        "job": "hadrian-ghc-in-ghci"
+      }
+    ],
+    "rules": [
+      {
+        "if": "(\"true\" == \"true\") && ($RELEASE_JOB != \"yes\") && ($NIGHTLY)",
+        "when": "on_success"
+      }
+    ],
+    "script": [
+      "sudo chown ghc:ghc -R .",
+      ".gitlab/ci.sh setup",
+      ".gitlab/ci.sh configure",
+      ".gitlab/ci.sh build_hadrian",
+      ".gitlab/ci.sh test_hadrian"
+    ],
+    "stage": "full-build",
+    "tags": [
+      "aarch64-linux"
+    ],
+    "variables": {
+      "AR": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-llvm-ar",
+      "BIGNUM_BACKEND": "native",
+      "BIN_DIST_NAME": "ghc-aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate",
+      "BUILD_FLAVOUR": "validate",
+      "CC": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang",
+      "CFLAGS": "-fuse-ld=/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld --rtlib=compiler-rt",
+      "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
+      "CONF_CC_OPTS_STAGE2": "-fuse-ld=/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld --rtlib=compiler-rt",
+      "CROSS_EMULATOR": "/opt/wine-arm64ec-msys2-deb12/bin/wine",
+      "CROSS_TARGET": "aarch64-unknown-mingw32",
+      "CXX": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang++",
+      "HADRIAN_ARGS": "--docs=none",
+      "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
+      "LD": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld",
+      "LLVMAS": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang",
+      "MergeObjsCmd": "",
+      "NM": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-nm",
+      "OBJCOPY": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-objcopy",
+      "OBJDUMP": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-objdump",
+      "RANLIB": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-llvm-ranlib",
+      "RUNTEST_ARGS": "",
+      "SIZE": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-size",
+      "STRINGS": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-strings",
+      "STRIP": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-strip",
+      "TEST_ENV": "aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate",
+      "WindresCmd": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-windres",
+      "XZ_OPT": "-9"
+    }
+  },
+  "nightly-aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate+llvm": {
+    "after_script": [
+      ".gitlab/ci.sh save_cache",
+      ".gitlab/ci.sh save_test_output",
+      ".gitlab/ci.sh clean",
+      "cat ci_timings"
+    ],
+    "allow_failure": false,
+    "artifacts": {
+      "expire_in": "8 weeks",
+      "paths": [
+        "ghc-aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate+llvm.tar.xz",
+        "junit.xml",
+        "unexpected-test-output.tar.gz"
+      ],
+      "reports": {
+        "junit": "junit.xml"
+      },
+      "when": "always"
+    },
+    "cache": {
+      "key": "aarch64-linux-deb12-wine-$CACHE_REV",
+      "paths": [
+        "cabal-cache",
+        "toolchain"
+      ]
+    },
+    "dependencies": [],
+    "image": "registry.gitlab.haskell.org/ghc/ci-images/aarch64-linux-deb12-wine:$DOCKER_REV",
+    "needs": [
+      {
+        "artifacts": false,
+        "job": "hadrian-ghc-in-ghci"
+      }
+    ],
+    "rules": [
+      {
+        "if": "(\"true\" == \"true\") && ($RELEASE_JOB != \"yes\") && ($NIGHTLY)",
+        "when": "on_success"
+      }
+    ],
+    "script": [
+      "sudo chown ghc:ghc -R .",
+      ".gitlab/ci.sh setup",
+      ".gitlab/ci.sh configure",
+      ".gitlab/ci.sh build_hadrian",
+      ".gitlab/ci.sh test_hadrian"
+    ],
+    "stage": "full-build",
+    "tags": [
+      "aarch64-linux"
+    ],
+    "variables": {
+      "AR": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-llvm-ar",
+      "BIGNUM_BACKEND": "native",
+      "BIN_DIST_NAME": "ghc-aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate+llvm",
+      "BUILD_FLAVOUR": "validate+llvm",
+      "CC": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang",
+      "CFLAGS": "-fuse-ld=/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld --rtlib=compiler-rt",
+      "CONFIGURE_ARGS": "--with-intree-gmp --enable-strict-ghc-toolchain-check",
+      "CONF_CC_OPTS_STAGE2": "-fuse-ld=/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld --rtlib=compiler-rt",
+      "CROSS_EMULATOR": "/opt/wine-arm64ec-msys2-deb12/bin/wine",
+      "CROSS_TARGET": "aarch64-unknown-mingw32",
+      "CXX": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang++",
+      "HADRIAN_ARGS": "--docs=none",
+      "INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
+      "LD": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld",
+      "LLVMAS": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang",
+      "MergeObjsCmd": "",
+      "NM": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-nm",
+      "OBJCOPY": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-objcopy",
+      "OBJDUMP": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-objdump",
+      "RANLIB": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-llvm-ranlib",
+      "RUNTEST_ARGS": "",
+      "SIZE": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-size",
+      "STRINGS": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-strings",
+      "STRIP": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-strip",
+      "TEST_ENV": "aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate+llvm",
+      "WindresCmd": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-windres",
+      "XZ_OPT": "-9"
+    }
+  },
   "nightly-i386-linux-alpine3_20-validate": {
     "after_script": [
       ".gitlab/ci.sh save_cache",
diff --git a/compiler/CodeGen.Platform.h b/compiler/CodeGen.Platform.h
index 78a712072d5e5773be79f93ba7107aab542704f0..989528526a3637ccc145a6c1ecdb3ff1a87fb380 100644
--- a/compiler/CodeGen.Platform.h
+++ b/compiler/CodeGen.Platform.h
@@ -1032,11 +1032,15 @@ freeReg 29 = False
 -- ip0 -- used for spill offset computations
 freeReg 16 = False
 
-#if defined(darwin_HOST_OS) || defined(ios_HOST_OS)
+-- Note [Aarch64 Register x18 at Darwin and Windows]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 -- x18 is reserved by the platform on Darwin/iOS, and can not be used
 -- More about ARM64 ABI that Apple platforms support:
 -- https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms
 -- https://github.com/Siguza/ios-resources/blob/master/bits/arm64.md
+-- It is a reserved at Windows as well. Acts like TEB register in user mode at Windows.
+-- https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions
+#if defined(darwin_HOST_OS) || defined(ios_HOST_OS) || defined(mingw32_HOST_OS)
 freeReg 18 = False
 #endif
 
diff --git a/compiler/GHC/CmmToAsm/AArch64/CodeGen.hs b/compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
index 300f46c29846479cd059aa10b9d364279f74054c..780af270d7c0b56b5eb217c39828bd79e3f10071 100644
--- a/compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
+++ b/compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
@@ -1,5 +1,6 @@
 {-# language GADTs, LambdaCase #-}
 {-# LANGUAGE OverloadedStrings #-}
+
 module GHC.CmmToAsm.AArch64.CodeGen (
       cmmTopCodeGen
     , generateJumpTableForInstr
@@ -281,7 +282,11 @@ generateJumpTableForInstr config (J_TBL ids (Just lbl) _) =
               )
             where
               blockLabel = blockLbl blockid
-   in Just (CmmData (Section ReadOnlyData lbl) (CmmStaticsRaw lbl jumpTable))
+      sectionType = case platformOS (ncgPlatform config) of
+        -- Aarch64 Windows platform requires LLVM 20 to support .rodata
+        OSMinGW32 -> Text
+        _         -> ReadOnlyData
+   in Just (CmmData (Section sectionType lbl) (CmmStaticsRaw lbl jumpTable))
 generateJumpTableForInstr _ _ = Nothing
 
 -- -----------------------------------------------------------------------------
diff --git a/compiler/GHC/CmmToAsm/AArch64/Instr.hs b/compiler/GHC/CmmToAsm/AArch64/Instr.hs
index 968ff50063e2167c6c03dc47fc918003914c512c..39182be09f61508a2fbffe556db6d789f8545c09 100644
--- a/compiler/GHC/CmmToAsm/AArch64/Instr.hs
+++ b/compiler/GHC/CmmToAsm/AArch64/Instr.hs
@@ -211,7 +211,7 @@ regUsageOfInstr platform instr = case instr of
 -- | <---- argument passing -------------> | <-- callee saved (lower 64 bits) ---> | <--------------------------------------- caller saved ----------------------> |
 -- | <------ free registers -------------> | F1 | F2 | F3 | F4 | D1 | D2 | D3 | D4 | <------ free registers -----------------------------------------------------> |
 -- '---------------------------------------------------------------------------------------------------------------------------------------------------------------'
--- IR: Indirect result location register, IP: Intra-procedure register, PL: Platform register, FP: Frame pointer, LR: Link register, SP: Stack pointer
+-- IR: Indirect result location register, IP: Intra-procedure register, PL: Platform register (See Note [Aarch64 Register x18 at Darwin and Windows]), FP: Frame pointer, LR: Link register, SP: Stack pointer
 -- BR: Base, SL: SpLim
 --
 -- TODO: The zero register is currently mapped to -1 but should get it's own separate number.
diff --git a/compiler/GHC/CmmToAsm/AArch64/Ppr.hs b/compiler/GHC/CmmToAsm/AArch64/Ppr.hs
index 80fe6f02cce2c69a6cc3033d7215570a1a52ab2c..25c448feaf30e8097685ac835bfde26329c172ae 100644
--- a/compiler/GHC/CmmToAsm/AArch64/Ppr.hs
+++ b/compiler/GHC/CmmToAsm/AArch64/Ppr.hs
@@ -1,5 +1,4 @@
 {-# OPTIONS_GHC -fno-warn-orphans #-}
-{-# LANGUAGE CPP #-}
 
 module GHC.CmmToAsm.AArch64.Ppr (pprNatCmmDecl, pprInstr, pprBasicBlock) where
 
@@ -43,7 +42,9 @@ pprNatCmmDecl config proc@(CmmProc top_info lbl _ (ListGraph blocks)) =
         pprSectionAlign config (Section Text lbl) $$
         -- do not
         -- pprProcAlignment config $$
-        pprLabel platform lbl $$ -- blocks guaranteed not null, so label needed
+        (if lbl /= blockLbl (blockId (head blocks)) -- blocks can have clashed names
+          then pprLabel platform lbl -- blocks guaranteed not null, so label needed
+          else empty) $$
         vcat (map (pprBasicBlock platform with_dwarf top_info) blocks) $$
         (if ncgDwarfEnabled config
          then line (pprAsmLabel platform (mkAsmTempEndLabel lbl) <> char ':') else empty) $$
@@ -461,63 +462,51 @@ pprInstr platform instr = case instr of
   STR _f o1 o2 -> op2 (text "\tstr") o1 o2
   STLR _f o1 o2 -> op2 (text "\tstlr") o1 o2
 
-#if defined(darwin_HOST_OS)
   LDR _f o1 (OpImm (ImmIndex lbl' off)) | Just (_info, lbl) <- dynamicLinkerLabelInfo lbl' ->
-    op_adrp o1 (pprAsmLabel platform lbl <> text "@gotpage") $$
-    op_ldr o1 (pprAsmLabel platform lbl <> text "@gotpageoff") $$
-    op_add o1 (char '#' <> int off) -- TODO: check that off is in 12bits.
+    let (adrp', ldr') = op_adrp_reloc_dynamic $ pprAsmLabel platform lbl in
+    op_adrp o1 (adrp') $$
+    op_ldr o1 (ldr') $$
+    op_add o1 (check_off off)
 
   LDR _f o1 (OpImm (ImmIndex lbl off)) | isForeignLabel lbl ->
-    op_adrp o1 (pprAsmLabel platform lbl <> text "@gotpage") $$
-    op_ldr o1 (pprAsmLabel platform lbl <> text "@gotpageoff") $$
-    op_add o1 (char '#' <> int off) -- TODO: check that off is in 12bits.
+    case platformOS platform of
+      OSMinGW32 ->
+        let (adrp', add') = op_adrp_reloc_local $ pprAsmLabel platform lbl in
+        op_adrp o1 (adrp') $$
+        op_add o1 add' $$
+        op_add o1 (check_off off)
+      _ ->
+        let (adrp', ldr') = op_adrp_reloc_dynamic $ pprAsmLabel platform lbl in
+        op_adrp o1 (adrp') $$
+        op_ldr o1 (ldr') $$
+        op_add o1 (check_off off)
 
   LDR _f o1 (OpImm (ImmIndex lbl off)) ->
-    op_adrp o1 (pprAsmLabel platform lbl <> text "@page") $$
-    op_add o1 (pprAsmLabel platform lbl <> text "@pageoff") $$
-    op_add o1 (char '#' <> int off) -- TODO: check that off is in 12bits.
+    let (adrp', add') = op_adrp_reloc_local $ pprAsmLabel platform lbl in
+    op_adrp o1 (adrp') $$
+    op_add o1 (add') $$
+    op_add o1 (check_off off)
 
   LDR _f o1 (OpImm (ImmCLbl lbl')) | Just (_info, lbl) <- dynamicLinkerLabelInfo lbl' ->
-    op_adrp o1 (pprAsmLabel platform lbl <> text "@gotpage") $$
-    op_ldr o1 (pprAsmLabel platform lbl <> text "@gotpageoff")
+    let (adrp', ldr') = op_adrp_reloc_dynamic $ pprAsmLabel platform lbl in
+    op_adrp o1 (adrp') $$
+    op_ldr o1 (ldr')
 
   LDR _f o1 (OpImm (ImmCLbl lbl)) | isForeignLabel lbl ->
-    op_adrp o1 (pprAsmLabel platform lbl <> text "@gotpage") $$
-    op_ldr o1 (pprAsmLabel platform lbl <> text "@gotpageoff")
+    case platformOS platform of
+      OSMinGW32 ->
+        let (adrp', add') = op_adrp_reloc_local $ pprAsmLabel platform lbl in
+        op_adrp o1 (adrp') $$
+        op_add o1 add'
+      _ ->
+        let (adrp', ldr') = op_adrp_reloc_dynamic $ pprAsmLabel platform lbl in
+        op_adrp o1 (adrp') $$
+        op_ldr o1 (ldr')
 
   LDR _f o1 (OpImm (ImmCLbl lbl)) ->
-    op_adrp o1 (pprAsmLabel platform lbl <> text "@page") $$
-    op_add o1 (pprAsmLabel platform lbl <> text "@pageoff")
-
-#else
-  LDR _f o1 (OpImm (ImmIndex lbl' off)) | Just (_info, lbl) <- dynamicLinkerLabelInfo lbl' ->
-    op_adrp o1 (text ":got:" <> pprAsmLabel platform lbl) $$
-    op_ldr o1 (text ":got_lo12:" <> pprAsmLabel platform lbl) $$
-    op_add o1 (char '#' <> int off) -- TODO: check that off is in 12bits.
-
-  LDR _f o1 (OpImm (ImmIndex lbl off)) | isForeignLabel lbl ->
-    op_adrp o1 (text ":got:" <> pprAsmLabel platform lbl) $$
-    op_ldr o1 (text ":got_lo12:" <> pprAsmLabel platform lbl) $$
-    op_add o1 (char '#' <> int off) -- TODO: check that off is in 12bits.
-
-  LDR _f o1 (OpImm (ImmIndex lbl off)) ->
-    op_adrp o1 (pprAsmLabel platform lbl) $$
-    op_add o1 (text ":lo12:" <> pprAsmLabel platform lbl) $$
-    op_add o1 (char '#' <> int off) -- TODO: check that off is in 12bits.
-
-  LDR _f o1 (OpImm (ImmCLbl lbl')) | Just (_info, lbl) <- dynamicLinkerLabelInfo lbl' ->
-    op_adrp o1 (text ":got:" <> pprAsmLabel platform lbl) $$
-    op_ldr o1 (text ":got_lo12:" <> pprAsmLabel platform lbl)
-
-  LDR _f o1 (OpImm (ImmCLbl lbl)) | isForeignLabel lbl ->
-    op_adrp o1 (text ":got:" <> pprAsmLabel platform lbl) $$
-    op_ldr o1 (text ":got_lo12:" <> pprAsmLabel platform lbl)
-
-  LDR _f o1 (OpImm (ImmCLbl lbl)) ->
-    op_adrp o1 (pprAsmLabel platform lbl) $$
-    op_add o1 (text ":lo12:" <> pprAsmLabel platform lbl)
-
-#endif
+    let (adrp', ldr') = op_adrp_reloc_local $ pprAsmLabel platform lbl in
+    op_adrp o1 adrp' $$
+    op_add o1 ldr'
 
   LDR _f o1@(OpReg W8 (RegReal (RealRegSingle i))) o2 | i < 32 ->
     op2 (text "\tldrb") o1 o2
@@ -553,6 +542,21 @@ pprInstr platform instr = case instr of
        op_adrp o1 rest     = line $ text "\tadrp" <+> pprOp platform o1 <> comma <+> rest
        op_add o1 rest      = line $ text "\tadd" <+> pprOp platform o1 <> comma <+> pprOp platform o1 <> comma <+> rest
 
+       op_adrp_reloc_dynamic asm_lbl = case platformOS platform of
+          OSDarwin -> (asm_lbl <> text "@gotpage", asm_lbl <> text "@gotpageoff")
+          OSLinux -> (text ":got:" <> asm_lbl, text ":got_lo12:" <> asm_lbl)
+          OSMinGW32 -> (text "__imp_" <> asm_lbl, text ":lo12:__imp_" <> asm_lbl)
+          os' -> pgmError $ "GHC.CmmToAsm.AArch64.Ppr.op_adrp_reloc_dynamic : " ++ show os' ++ " is unsuppported by relocations"
+
+       op_adrp_reloc_local asm_lbl = case platformOS platform of
+          OSDarwin -> (asm_lbl <> text "@page", asm_lbl <> text "@pageoff")
+          OSLinux -> (asm_lbl, text ":lo12:" <> asm_lbl)
+          OSMinGW32 -> (asm_lbl, text ":lo12:" <> asm_lbl)
+          os' -> pgmError $ "GHC.CmmToAsm.AArch64.Ppr.op_adrp_reloc_local : " ++ show os' ++ " is unsuppported by relocations"
+
+       check_off off = if off >= 0 && off <= 4095 then char '#' <> int off else
+         pgmError $ "GHC.CmmToAsm.AArch64.Ppr.check_off : " ++ show off ++ " is out of 12 bit"
+
 pprBcond :: IsLine doc => Cond -> doc
 pprBcond c = text "b." <> pprCond c
 
diff --git a/compiler/GHC/CmmToAsm/Reg/Linear/AArch64.hs b/compiler/GHC/CmmToAsm/Reg/Linear/AArch64.hs
index 64ed25e92ddc934e76c08ab77b377699f09100ae..95fbe77fbb986a32a67a7b73eeb6aa51796d4b6c 100644
--- a/compiler/GHC/CmmToAsm/Reg/Linear/AArch64.hs
+++ b/compiler/GHC/CmmToAsm/Reg/Linear/AArch64.hs
@@ -118,6 +118,7 @@ getFreeRegs :: RegClass -> FreeRegs -> [RealReg]
 getFreeRegs cls (FreeRegs g f) =
   case cls of
     RcFloatOrVector -> go 32 f 31
+    -- x18 is a platform-reserved register for Win/Mac and free for Linux (See Note [Aarch64 Register x18 at Darwin and Windows])
     RcInteger       -> go  0 g 18
     where
         go _   _ i | i < 0 = []
diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs
index aeed58acaafaeb6cd02f4cd90f24a657c434274a..cfdd08fd9e67840deb95477429436180eb9c05cc 100644
--- a/compiler/GHC/Driver/Session.hs
+++ b/compiler/GHC/Driver/Session.hs
@@ -3652,6 +3652,14 @@ makeDynFlagsConsistent dflags
  , Nothing <- outputFile dflags
     = pgmError "--output must be specified when using --merge-objs"
 
+ | platformTablesNextToCode platform
+   && os == OSMinGW32
+   && arch == ArchAArch64
+    = case backendCodeOutput (backend dflags) of
+        LlvmCodeOutput -> pgmError "-fllvm is incompatible with enabled TablesNextToCode at Windows Aarch64"
+        NcgCodeOutput -> pgmError "-fasm is incompatible with enabled TablesNextToCode at Windows Aarch64"
+        _ -> (dflags, mempty, mempty)
+
   -- When we do ghci, force using dyn ways if the target RTS linker
   -- only supports dynamic code
  | LinkInMemory <- ghcLink dflags
diff --git a/compiler/GHC/Platform/Regs.hs b/compiler/GHC/Platform/Regs.hs
index 429f977a99c54859a2c5769ff6f424b4d3721783..bdb3a5897556cce45002394c36febc73a24176b7 100644
--- a/compiler/GHC/Platform/Regs.hs
+++ b/compiler/GHC/Platform/Regs.hs
@@ -112,7 +112,18 @@ freeReg platform
    ArchX86_64  -> X86_64.freeReg
    ArchS390X   -> S390X.freeReg
    ArchARM {}  -> ARM.freeReg
-   ArchAArch64 -> AArch64.freeReg
+   ArchAArch64 ->
+    -- See Note [Aarch64 Register x18 at Darwin and Windows].
+    -- It already has `freeReg 18 = False` but that line does not work for cross-compile when
+    -- we use host not from the list (darwin_HOST_OS, ios_HOST_OS, mingw32_HOST_OS) i.e. Linux
+    if platformOS platform == OSMinGW32 || platformOS platform == OSDarwin
+        then
+            let
+                x18Check :: RegNo -> Bool
+                x18Check 18 = False
+                x18Check a = AArch64.freeReg a
+            in x18Check
+        else AArch64.freeReg
    ArchRISCV64 -> RISCV64.freeReg
    ArchWasm32  -> Wasm32.freeReg
    ArchLoongArch64 -> LoongArch64.freeReg
diff --git a/hadrian/src/Oracles/Setting.hs b/hadrian/src/Oracles/Setting.hs
index 807fab63bfcb913f4e7adcc8e95f63ff4ebefc82..b6a8943abf14876988dd7983f0c26debe1a5d2fa 100644
--- a/hadrian/src/Oracles/Setting.hs
+++ b/hadrian/src/Oracles/Setting.hs
@@ -11,6 +11,7 @@ module Oracles.Setting (
     -- ** Target platform things
     anyTargetOs, anyTargetArch, anyHostOs,
     isElfTarget, isOsxTarget, isWinTarget, isJsTarget, isArmTarget,
+    isWinHost,
     targetArmVersion
     ) where
 
@@ -156,6 +157,9 @@ getSetting = expr . setting
 bashPath :: Action FilePath
 bashPath = setting BourneShell
 
+isWinHost :: Action Bool
+isWinHost = anyHostOs [OSMinGW32]
+
 isWinTarget :: Action Bool
 isWinTarget = anyTargetOs [OSMinGW32]
 
diff --git a/hadrian/src/Rules/BinaryDist.hs b/hadrian/src/Rules/BinaryDist.hs
index 187ae211344de006cfa6f9bef7feefc428ae079c..af8fa5c7d36e715a691a1f4417c135dd8166a029 100644
--- a/hadrian/src/Rules/BinaryDist.hs
+++ b/hadrian/src/Rules/BinaryDist.hs
@@ -301,7 +301,8 @@ bindistRules = do
 
     let buildBinDist compressor = do
           win_target <- isWinTarget
-          when win_target (error "normal binary-dist does not work for Windows targets, use `reloc-binary-dist-*` target instead.")
+          win_host <- isWinHost
+          when (win_target && win_host) (error "normal binary-dist does not work at Windows, use `reloc-binary-dist-*` target instead.")
           buildBinDistX "binary-dist-dir" "bindist" compressor
         buildBinDistReloc = buildBinDistX "reloc-binary-dist-dir" "reloc-bindist"
 
diff --git a/libraries/Cabal b/libraries/Cabal
index 269fd808e5d80223a229b6b19edfe6f5b109007a..703582f80f6d7f0c914ef4b885affcfc7b7b6ec8 160000
--- a/libraries/Cabal
+++ b/libraries/Cabal
@@ -1 +1 @@
-Subproject commit 269fd808e5d80223a229b6b19edfe6f5b109007a
+Subproject commit 703582f80f6d7f0c914ef4b885affcfc7b7b6ec8
diff --git a/libraries/Win32 b/libraries/Win32
index 027cbcf0de25d681823ea92fb545a2604c3a6a8b..f340d2c3d846fce73117dd2548ad1bf0c56ceb9d 160000
--- a/libraries/Win32
+++ b/libraries/Win32
@@ -1 +1 @@
-Subproject commit 027cbcf0de25d681823ea92fb545a2604c3a6a8b
+Subproject commit f340d2c3d846fce73117dd2548ad1bf0c56ceb9d
diff --git a/libraries/base/src/System/CPUTime/Windows.hsc b/libraries/base/src/System/CPUTime/Windows.hsc
index 547e7fa4805bdbb5158d13ef4abda66fe5cd7562..4bae075d4645b6e65688fc561fd4c31fae312735 100644
--- a/libraries/base/src/System/CPUTime/Windows.hsc
+++ b/libraries/base/src/System/CPUTime/Windows.hsc
@@ -60,7 +60,7 @@ type HANDLE = ()
 #if defined(i386_HOST_ARCH)
 foreign import stdcall unsafe "GetCurrentProcess" getCurrentProcess :: IO (Ptr HANDLE)
 foreign import stdcall unsafe "GetProcessTimes" getProcessTimes :: Ptr HANDLE -> Ptr FILETIME -> Ptr FILETIME -> Ptr FILETIME -> Ptr FILETIME -> IO CInt
-#elif defined(x86_64_HOST_ARCH)
+#elif defined(x86_64_HOST_ARCH) || defined(aarch64_HOST_ARCH)
 foreign import ccall unsafe "GetCurrentProcess" getCurrentProcess :: IO (Ptr HANDLE)
 foreign import ccall unsafe "GetProcessTimes" getProcessTimes :: Ptr HANDLE -> Ptr FILETIME -> Ptr FILETIME -> Ptr FILETIME -> Ptr FILETIME -> IO CInt
 #else
diff --git a/libraries/base/tests/perf/encodingAllocations.hs b/libraries/base/tests/perf/encodingAllocations.hs
index cd136963cb948c6365d934dc863b7b7af2f72816..58b31b0853383ea14fc68eff31e33ad39a06dce9 100755
--- a/libraries/base/tests/perf/encodingAllocations.hs
+++ b/libraries/base/tests/perf/encodingAllocations.hs
@@ -13,13 +13,13 @@ import Distribution.Simple.Utils
 
 
 main :: IO ()
-main = withTempFile "." "encodingAllocations.tmp" (const $ loop 1000000)
+main = withTempFile "encodingAllocations.tmp" (loop 1000000)
 
-loop :: Int -> Handle -> IO ()
-loop 0  !_ = pure ()
-loop !n !h = do
+loop :: Int -> FilePath -> Handle -> IO ()
+loop 0  !_ !_ = pure ()
+loop !n !fp !h = do
   hPutChar h $! dummy_char n
-  loop (n-1) h
+  loop (n-1) fp h
 
 -- unsafe efficient version of `chr`
 my_chr :: Int -> Char
diff --git a/libraries/directory b/libraries/directory
index 005fa061171a55d35ce8dfe936cf3703525a8616..eb40bbebcaf86153bbc60772fb2e0466d35c95c4 160000
--- a/libraries/directory
+++ b/libraries/directory
@@ -1 +1 @@
-Subproject commit 005fa061171a55d35ce8dfe936cf3703525a8616
+Subproject commit eb40bbebcaf86153bbc60772fb2e0466d35c95c4
diff --git a/libraries/ghc-internal/jsbits/base.js b/libraries/ghc-internal/jsbits/base.js
index 9150799d130d885c2e356f3b2696adfa7d15b91f..d7a78a46379c96a99e06d6f90569f432867d356b 100644
--- a/libraries/ghc-internal/jsbits/base.js
+++ b/libraries/ghc-internal/jsbits/base.js
@@ -44,30 +44,45 @@ function h$base_close(fd, c) {
 }
 
 function h$close(fd,c) {
-  if (c) {
-    //asynchronous
-    var fdo = h$base_fds[fd];
-    if(fdo) {
+  var fdo = h$base_fds[fd];
+
+  // File descriptor was closed already?
+  // It may happen only if its reference count reached <1 and actual closing is processed at underlying fd
+  if (!fdo) {
+    h$setErrno('EINVAL');
+
+    if (c) {
+      TRACE_IO("base_close: file descriptor not found, already closed?")
+      c(-1);
+      return;
+    }
+
+    TRACE_IO("base_close sync: file descriptor not found, already closed?")
+    return (-1);
+  }
+
+  fdo.refs--;
+
+  if (fdo.refs < 1) {
+    // Process closing at underlying fd
+
+    if (c) {
+      TRACE_IO("base_close: closing underlying fd")
+      if (fdo.close) {
+        fdo.close(fd, fdo, c);
+      } else {
+        TRACE_IO("base_close: no actual underlying fd close, dummy implementation")
         delete h$base_fds[fd];
-        if(--fdo.refs < 1) {
-          TRACE_IO("base_close: closing underlying fd")
-          if(fdo.close) {
-            fdo.close(fd, fdo, c);
-          } else {
-            c(0);
-          }
-        } else {
-          TRACE_IO("base_close: remaining references, not closing underlying fd")
-          c(0);
-        }
-    } else {
-        TRACE_IO("base_close: file descriptor not found, already closed?")
-        h$errno = CONST_EINVAL;
-        c(-1);
+        c(0);
+      }
+      return;
     }
-  } else {
-    //synchronous
+
+    TRACE_IO("base_close sync: closing underlying fd")
     try {
+      // See: https://nodejs.org/api/fs.html#fsclosesyncfd
+      // Calling fs.closeSync() on any file descriptor (fd) that is currently in use through any other fs operation may lead to undefined behavior.
+      delete h$base_fds[fd];
       h$fs.closeSync(fd);
       return 0;
     } catch(err) {
@@ -75,6 +90,16 @@ function h$close(fd,c) {
       return (-1);
     }
   }
+
+  // Dummy process closing due of remaining references
+  if (c) {
+    TRACE_IO("base_close: remaining references, not closing underlying fd")
+    c(0);
+    return;
+  }
+
+  TRACE_IO("base_close sync: remaining references, not closing underlying fd")
+  return 0;
 }
 
 function h$base_dup(fd, c) {
@@ -122,7 +147,7 @@ function h$base_dup2(fd, new_fd, c) {
 }
 
 function h$base_fstat(fd, stat, stat_off, c) {
-    TRACE_IO("base_stat")
+    TRACE_IO("base_fstat")
 #ifndef GHCJS_BROWSER
     if(h$isNode()) {
         h$fs.fstat(fd, function(err, fs) {
@@ -384,11 +409,13 @@ function h$rmdir(file, file_off) {
 }
 
 function h$rename(old_path, old_path_off, new_path, new_path_off) {
-  TRACE_IO("rename")
+  var old_path_str = h$decodeUtf8z(old_path, old_path_off);
+  var new_path_str = h$decodeUtf8z(new_path, new_path_off);
+  TRACE_IO("rename sync: " + old_path_str + " -> " + new_path_str)
 #ifndef GHCJS_BROWSER
   if (h$isNode()) {
     try {
-      h$fs.renameSync(h$decodeUtf8z(old_path, old_path_off), h$decodeUtf8z(new_path, new_path_off));
+      h$fs.renameSync(old_path_str, new_path_str);
       return 0;
     } catch(e) {
       h$setErrno(e);
@@ -473,11 +500,13 @@ function h$calculate_at(dirfd, file, file_off) {
 
 function h$openat(dirfd, file, file_off, how, mode, c) {
   var path = h$calculate_at(dirfd, file, file_off);
+  TRACE_IO("openat" + (!!c ? ": " : " sync: ") + path)
   return h$base_open(path, how, mode, c);
 }
 
 function h$open(file, file_off, how, mode, c) {
   var path = h$decodeUtf8z(file, file_off);
+  TRACE_IO("open" + (!!c ? ": " : " sync: ") + path)
   return h$base_open(path, how, mode, c);
 }
 
@@ -485,7 +514,7 @@ function h$base_open(fp, how, mode, c) {
 #ifndef GHCJS_BROWSER
     if(h$isNode()) {
         var flags, off;
-        TRACE_IO("open: " + fp)
+        TRACE_IO("base_open" + (!!c ? ": " : " sync: ") + fp)
         var acc  = how & h$base_o_accmode;
         // passing a number lets node.js use it directly as the flags (undocumented)
         if(acc === h$base_o_rdonly) {
@@ -539,7 +568,7 @@ function h$base_open(fp, how, mode, c) {
                                        , pos:   p
                                        , refs:  1
                                        };
-                      TRACE_IO("open: " + fp + " -> " + fd)
+                      TRACE_IO("base_open sync: " + fp + " -> " + fd)
                   }
             if(off === -1) {
               var fs = h$fs.statSync(fp);
@@ -944,8 +973,8 @@ if(h$isNode()) {
     h$base_closeFile = function(fd, fdo, c) {
         TRACE_IO("base_closeFile: " + fd + " (" + fdo.fd + ")")
         var real_fd = typeof fdo.fd === 'number' ? fdo.fd : fd;
+        delete h$base_fds[fd];
         h$fs.close(real_fd, function(err) {
-            delete h$base_fds[fd];
             h$handleErrnoC(err, -1, 0, c);
         });
     }
diff --git a/libraries/ghc-internal/jsbits/errno.js b/libraries/ghc-internal/jsbits/errno.js
index ff31029baaa5f15e84c28776eba6685fa6d9279f..7bfd3dae83893269144b3434052ed8001758ae06 100644
--- a/libraries/ghc-internal/jsbits/errno.js
+++ b/libraries/ghc-internal/jsbits/errno.js
@@ -52,6 +52,7 @@ function h$setErrno(e) {
       if(es.indexOf('EBADF') !== -1)        return CONST_EBADF;
       if(es.indexOf('ENOSPC') !== -1)       return CONST_ENOSPC;
       if(es.indexOf('EACCES') !== -1)       return CONST_EACCES;
+      if(es.indexOf('EXDEV') !== -1)        return CONST_EXDEV;
       if(es.indexOf('Bad argument') !== -1) return CONST_ENOENT; // fixme?
       throw ("setErrno not yet implemented for: " + e);
 
@@ -72,6 +73,7 @@ var h$errorStrs =  { CONST_E2BIG:   "Argument list too long"
                    , CONST_EPIPE:   "Broken pipe"
                    , CONST_EAGAIN:  "Resource temporarily unavailable"
                    , CONST_ESPIPE:  "Illegal seek"
+                   , CONST_EXDEV:   "Cross-device link" // See https://en.cppreference.com/w/cpp/error/errno_macros
                    }
 
 function h$handleErrno(r_err, f) {
diff --git a/libraries/ghc-internal/src/GHC/Internal/System/Posix/Internals.hs b/libraries/ghc-internal/src/GHC/Internal/System/Posix/Internals.hs
index db100866e0a506df3c1d160dd18e602a9751eb56..7fd0fe75159d1d3971a50e0079cf16935c79cfe2 100644
--- a/libraries/ghc-internal/src/GHC/Internal/System/Posix/Internals.hs
+++ b/libraries/ghc-internal/src/GHC/Internal/System/Posix/Internals.hs
@@ -556,6 +556,8 @@ foreign import javascript interruptible "h$open"
    c_interruptible_open_ :: CFilePath -> CInt -> CMode -> IO CInt
 foreign import javascript interruptible "h$open"
    c_safe_open_ :: CFilePath -> CInt -> CMode -> IO CInt
+foreign import javascript interruptible "h$openat"
+   c_openat :: CInt -> CFilePath -> CInt -> CMode -> IO CInt
 foreign import javascript interruptible "h$base_read"
    c_read :: CInt -> Ptr Word8 -> CSize -> IO CSsize
 foreign import javascript interruptible "h$base_read"
diff --git a/libraries/haskeline b/libraries/haskeline
index 5f4bf62bf1f4846ad0b8d1fa9d45f902e3934511..5f1a790a5db1cb3708d105d4f532c32fcbeb4296 160000
--- a/libraries/haskeline
+++ b/libraries/haskeline
@@ -1 +1 @@
-Subproject commit 5f4bf62bf1f4846ad0b8d1fa9d45f902e3934511
+Subproject commit 5f1a790a5db1cb3708d105d4f532c32fcbeb4296
diff --git a/libraries/process b/libraries/process
index 9c3bfc214c72bbd0c8a30a1c41465deed0feaf47..fbbe60718736999db701c12528c85cbc605ab4fb 160000
--- a/libraries/process
+++ b/libraries/process
@@ -1 +1 @@
-Subproject commit 9c3bfc214c72bbd0c8a30a1c41465deed0feaf47
+Subproject commit fbbe60718736999db701c12528c85cbc605ab4fb
diff --git a/libraries/unix b/libraries/unix
index 74ae1c0d9dd1518434f7d6cd3e63d7769599e0f9..47d5fc4a8f19207819030725e7de23c65fa61a04 160000
--- a/libraries/unix
+++ b/libraries/unix
@@ -1 +1 @@
-Subproject commit 74ae1c0d9dd1518434f7d6cd3e63d7769599e0f9
+Subproject commit 47d5fc4a8f19207819030725e7de23c65fa61a04
diff --git a/llvm-targets b/llvm-targets
index c42f3e7d8b28a1619033c2a5a5123714f485ee85..daafe8c18fcad65de1f4a2178b25f259b9ccca00 100644
--- a/llvm-targets
+++ b/llvm-targets
@@ -1,4 +1,5 @@
 [("x86_64-unknown-windows-gnu", ("e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "x86-64", ""))
+,("aarch64-unknown-windows-gnu", ("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32", "generic", "+v8a +fp-armv8 +neon"))
 ,("arm-unknown-linux-gnueabi", ("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", "arm7tdmi", "+strict-align"))
 ,("arm-unknown-linux-gnueabihf", ("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", "arm1176jzf-s", "+strict-align"))
 ,("arm-unknown-linux-musleabihf", ("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", "arm1176jzf-s", "+strict-align"))
diff --git a/m4/fp_cc_supports_target.m4 b/m4/fp_cc_supports_target.m4
index a8b8bf907432133823f31bd58a7a6788d2f224ad..177c9824bd90d6e678d7f3054fe034c16ca672c5 100644
--- a/m4/fp_cc_supports_target.m4
+++ b/m4/fp_cc_supports_target.m4
@@ -20,7 +20,7 @@ AC_DEFUN([FP_CC_SUPPORTS_TARGET],
        # See Note [Don't pass --target to emscripten toolchain] in GHC.Toolchain.Program
        CONF_CC_SUPPORTS_TARGET=NO
        AC_MSG_RESULT([no])
-   elif $1 --target=$LlvmTarget -Werror conftest.c > /dev/null 2>&1 ; then
+   elif $1 --target=$LlvmTarget -Werror -c conftest.c > /dev/null 2>&1 ; then
        CONF_CC_SUPPORTS_TARGET=YES
        AC_MSG_RESULT([yes])
    else
diff --git a/m4/fptools_set_platform_vars.m4 b/m4/fptools_set_platform_vars.m4
index 4c022da52b0e4507f05dc7a64c8cbb80c971491f..3f82257501e31f14cc04198052f7056757ae3adb 100644
--- a/m4/fptools_set_platform_vars.m4
+++ b/m4/fptools_set_platform_vars.m4
@@ -93,7 +93,7 @@ AC_DEFUN([FPTOOLS_OVERRIDE_PLATFORM_FROM_BOOTSTRAP],
 
 # FPTOOLS_SET_PLATFORM_VARS(platform,Platform)
 # ----------------------------------
-# Set the platform variables for a single plaform (one of build, host,
+# Set the platform variables for a single platform (one of build, host,
 # or target). Assumes <platform>Arch, <platform>Vendor, and <platform>OS
 # are defined, and does everything else in terms of them.
 AC_DEFUN([FPTOOLS_SET_PLATFORM_VARS],
diff --git a/m4/ghc_tables_next_to_code.m4 b/m4/ghc_tables_next_to_code.m4
index 3e0ced2137dfaa0f0a1798ac1867aa7e0f25a65c..9bf473a712cb03d8132cf32ee5e9d476ace5a254 100644
--- a/m4/ghc_tables_next_to_code.m4
+++ b/m4/ghc_tables_next_to_code.m4
@@ -22,8 +22,13 @@ AC_DEFUN([GHC_TABLES_NEXT_TO_CODE],
                   AC_MSG_RESULT([no])
                   ;;
               *)
-                  TablesNextToCodeDefault=YES
-                  AC_MSG_RESULT([yes])
+                  if test "$TargetOS" = "mingw32" && test "$TargetArch" = "aarch64"; then
+                    TablesNextToCodeDefault=NO
+                    AC_MSG_RESULT([no])
+                  else
+                    TablesNextToCodeDefault=YES
+                    AC_MSG_RESULT([yes])
+                  fi
                   ;;
           esac
           ;;
diff --git a/rts/StgCRun.c b/rts/StgCRun.c
index 2e283a73bfee56611bc624ad6476478dae75cbc5..fe6cde6f99979546096e47a2961a98e0ef0f3588 100644
--- a/rts/StgCRun.c
+++ b/rts/StgCRun.c
@@ -863,8 +863,12 @@ StgRun(StgFunPtr f, StgRegTable *basereg) {
          */
         "br %1\n\t"
 
+#if defined(mingw32_HOST_OS)
+        ".globl " STG_RETURN "\n"
+#else
         ".globl " STG_RETURN "\n\t"
-#if !defined(ios_HOST_OS) && !defined(darwin_HOST_OS)
+#endif
+#if !defined(ios_HOST_OS) && !defined(darwin_HOST_OS) && !defined(mingw32_HOST_OS)
         ".type " STG_RETURN ", %%function\n"
 #endif
         STG_RETURN ":\n\t"
diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c
index 5f22d74da87963798146251b2b9c310c8704cdf1..8764c173274a59087f143159c3d87dafba6c1bb6 100644
--- a/rts/linker/PEi386.c
+++ b/rts/linker/PEi386.c
@@ -1195,6 +1195,12 @@ verifyCOFFHeader ( uint16_t machine, IMAGE_FILE_HEADER *hdr,
       errorBelch("%" PATH_FMT ": Not a x86_64 PE+ file.", fileName);
       return false;
    }
+#elif defined(aarch64_HOST_ARCH)
+   if (machine != IMAGE_FILE_MACHINE_ARM64) {
+      errorBelch("%" PATH_FMT ": Not a ARM64 PE+ file.", fileName);
+      return false;
+   }
+   errorBelch("PE/PE+ not supported on ARM64.");
 #else
    errorBelch("PE/PE+ not supported on this arch.");
 #endif
@@ -2132,6 +2138,19 @@ ocResolve_PEi386 ( ObjectCode* oc )
                    *(uint32_t *)pP = (uint32_t)v;
                    break;
                }
+#elif defined(aarch64_HOST_ARCH)
+            case 1: // IMAGE_REL_ARM64_ADDR32, see https://llvm.org/doxygen/namespacellvm_1_1COFF.html, https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#arm64-processors
+               {
+                    // We have to put this stub due of errors like:
+                    // warning: variable 'A' set but not used.
+                    uint64_t v;
+                    v = S + A;
+
+                    debugBelch("%" PATH_FMT ": Catch ARM64 PEi386 relocation type %d, %llx\n",
+                        oc->fileName, reloc->Type, v);
+                    releaseOcInfo (oc);
+                    return false;
+               }
 #endif
             default:
                debugBelch("%" PATH_FMT ": unhandled PEi386 relocation type %d\n",
diff --git a/rts/win32/veh_excn.c b/rts/win32/veh_excn.c
index 999580c7ef310f0e8349f6b9fa4b0bee684b132b..183c4657e9ad1b29148bd65c783266c567c5ea4e 100644
--- a/rts/win32/veh_excn.c
+++ b/rts/win32/veh_excn.c
@@ -287,6 +287,16 @@ void generateStack (EXCEPTION_POINTERS* pExceptionPointers)
 
     stackFrame.AddrStack.Offset = context->Rsp;
     stackFrame.AddrStack.Mode = AddrModeFlat;
+#elif defined(aarch64_HOST_ARCH)
+    machineType = IMAGE_FILE_MACHINE_ARM64;
+    stackFrame.AddrPC.Offset = context->Pc;
+    stackFrame.AddrPC.Mode = AddrModeFlat;
+
+    stackFrame.AddrFrame.Offset = context->Fp;
+    stackFrame.AddrFrame.Mode = AddrModeFlat;
+
+    stackFrame.AddrStack.Offset = context->Sp;
+    stackFrame.AddrStack.Mode = AddrModeFlat;
 #endif
     fprintf (stderr, "\n Attempting to reconstruct a stack trace...\n\n");
     if (!SymInitialize (GetCurrentProcess (), NULL, true))
diff --git a/testsuite/tests/ghc-api/fixed-nodes/all.T b/testsuite/tests/ghc-api/fixed-nodes/all.T
index 7d512269d258482185efb1a1182bd6556692c2d7..961b3e66172c8ded16e3b228208dd768f067a17e 100644
--- a/testsuite/tests/ghc-api/fixed-nodes/all.T
+++ b/testsuite/tests/ghc-api/fixed-nodes/all.T
@@ -2,7 +2,6 @@ test('FixedNodes',
      [extra_run_opts(f'"{config.libdir}"'),
      extra_files(['T1A.hs', 'T1B.hs', 'T1C.hs']),
      wasm_broken(25953),
-     js_broken(25953)
      ],
      compile_and_run,
      ['-package ghc'])
diff --git a/testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs b/testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
index 43f9b7bcb2c48c155edad04799c7f87425b3e023..d67be89fb65b19ebcd25b5c93d4a38c76a35d2dd 100644
--- a/testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
+++ b/testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
@@ -13536,6 +13536,7 @@ module System.Posix.Internals where
   c_lseek :: GHC.Internal.Foreign.C.Types.CInt -> GHC.Internal.System.Posix.Types.COff -> GHC.Internal.Foreign.C.Types.CInt -> GHC.Internal.Types.IO GHC.Internal.System.Posix.Types.COff
   c_mkfifo :: GHC.Internal.Foreign.C.String.Encoding.CString -> GHC.Internal.System.Posix.Types.CMode -> GHC.Internal.Types.IO GHC.Internal.Foreign.C.Types.CInt
   c_open :: CFilePath -> GHC.Internal.Foreign.C.Types.CInt -> GHC.Internal.System.Posix.Types.CMode -> GHC.Internal.Types.IO GHC.Internal.Foreign.C.Types.CInt
+  c_openat :: GHC.Internal.Foreign.C.Types.CInt -> CFilePath -> GHC.Internal.Foreign.C.Types.CInt -> GHC.Internal.System.Posix.Types.CMode -> GHC.Internal.Types.IO GHC.Internal.Foreign.C.Types.CInt
   c_pipe :: GHC.Internal.Ptr.Ptr GHC.Internal.Foreign.C.Types.CInt -> GHC.Internal.Types.IO GHC.Internal.Foreign.C.Types.CInt
   c_read :: GHC.Internal.Foreign.C.Types.CInt -> GHC.Internal.Ptr.Ptr GHC.Internal.Word.Word8 -> GHC.Internal.Foreign.C.Types.CSize -> GHC.Internal.Types.IO GHC.Internal.System.Posix.Types.CSsize
   c_s_isblk :: GHC.Internal.System.Posix.Types.CMode -> GHC.Internal.Foreign.C.Types.CInt
diff --git a/utils/ghc-toolchain/exe/Main.hs b/utils/ghc-toolchain/exe/Main.hs
index 71faaf79a171fb87219f1d4bebb1822f084060bf..7e75e7b1bb3670b9f90c9164c128108e7269695d 100644
--- a/utils/ghc-toolchain/exe/Main.hs
+++ b/utils/ghc-toolchain/exe/Main.hs
@@ -348,6 +348,7 @@ tablesNextToCodeSupported archOs =
       ArchPPC      -> False
       ArchPPC_64 _ -> False
       ArchS390X    -> False
+      ArchAArch64  -> archOS_OS archOs /= OSMinGW32
       _            -> True
 
 determineTablesNextToCode
diff --git a/utils/hsc2hs b/utils/hsc2hs
index c3b21800a67366c9591dc85a471d1dfdb1efcf29..2fab2f4cdffef12afe561ef03f5ebdace7dbae67 160000
--- a/utils/hsc2hs
+++ b/utils/hsc2hs
@@ -1 +1 @@
-Subproject commit c3b21800a67366c9591dc85a471d1dfdb1efcf29
+Subproject commit 2fab2f4cdffef12afe561ef03f5ebdace7dbae67
diff --git a/utils/llvm-targets/gen-data-layout.sh b/utils/llvm-targets/gen-data-layout.sh
index 2f50bf15de3a37de111eb899d825342e20abc62d..b594f141a936660be75a9b9790bfccab9368bd10 100755
--- a/utils/llvm-targets/gen-data-layout.sh
+++ b/utils/llvm-targets/gen-data-layout.sh
@@ -27,6 +27,7 @@ TARGETS=(
 
     # Windows
     "x86_64-unknown-windows-gnu"
+    "aarch64-unknown-windows-gnu"
 
     #########################
     # Linux