diff --git a/aclocal.m4 b/aclocal.m4
index c39aff28c8da0754176eb2cba8a88f9ac81b3847..73791cd1b3d96ef312de860613b347ec4fdd24ec 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -328,7 +328,8 @@ AC_DEFUN([FPTOOLS_SET_HASKELL_PLATFORM_VARS],
         [AC_LANG_PROGRAM([], [__asm__ (".subsections_via_symbols");])],
         [AC_MSG_RESULT(yes)
          if test x"$TargetArch" = xaarch64; then
-            dnl subsections via symbols is busted on arm64
+            dnl subsections via symbols is busted on arm64 (aarch64-darwin)
+            dnl see #19379
             TargetHasSubsectionsViaSymbols=NO
          else
             TargetHasSubsectionsViaSymbols=YES
diff --git a/compiler/main/DynFlags.hs b/compiler/main/DynFlags.hs
index 2ea0b3d5e957f5a97a3721bf55479fa779afd1dc..8432c57cc08192c308d02d7421ee87689e51162c 100644
--- a/compiler/main/DynFlags.hs
+++ b/compiler/main/DynFlags.hs
@@ -4646,14 +4646,28 @@ validHoleFitsImpliedGFlags
 default_PIC :: Platform -> [GeneralFlag]
 default_PIC platform =
   case (platformOS platform, platformArch platform) of
-    (OSDarwin, ArchX86_64) -> [Opt_PIC]
-    (OSOpenBSD, ArchX86_64) -> [Opt_PIC] -- Due to PIE support in
-                                         -- OpenBSD since 5.3 release
-                                         -- (1 May 2013) we need to
-                                         -- always generate PIC. See
-                                         -- #10597 for more
-                                         -- information.
-    _                      -> []
+    -- Darwin always requires PIC.  Especially on more recent macOS releases
+    -- there will be a 4GB __ZEROPAGE that prevents us from using 32bit addresses
+    -- while we could work around this on x86_64 (like WINE does), we won't be
+    -- able on aarch64, where this is enforced.
+    (OSDarwin,  ArchX86_64) -> [Opt_PIC]
+    -- For AArch64, we need to always have PIC enabled.  The relocation model
+    -- on AArch64 does not permit arbitrary relocations.  Under ASLR, we can't
+    -- control much how far apart symbols are in memory for our in-memory static
+    -- linker;  and thus need to ensure we get sufficiently capable relocations.
+    -- This requires PIC on AArch64, and ExternalDynamicRefs on Linux on top
+    -- of that.  Subsequently we expect all code on aarch64/linux (and macOS) to
+    -- be built with -fPIC.
+    -- See #15275, #18892
+    (OSDarwin,  ArchAArch64) -> [Opt_PIC]
+    (OSLinux,   ArchAArch64) -> [Opt_PIC, Opt_ExternalDynamicRefs]
+    (OSOpenBSD, ArchX86_64)  -> [Opt_PIC] -- Due to PIE support in
+                                          -- OpenBSD since 5.3 release
+                                          -- (1 May 2013) we need to
+                                          -- always generate PIC. See
+                                          -- #10597 for more
+                                          -- information.
+    _                        -> []
 
 
 -- We usually want to use RPath, except on macOS (OSDarwin).  On recent macOS
diff --git a/compiler/main/SysTools.hs b/compiler/main/SysTools.hs
index 4a301e0837dd5fad9c8cb790d98cdbd5f823c984..bed0251a471ef95ec701cbb1b47563d6ecb851bb 100644
--- a/compiler/main/SysTools.hs
+++ b/compiler/main/SysTools.hs
@@ -370,7 +370,7 @@ linkDynLib dflags0 o_files dep_packages
                  ++ [ Option "-undefined",
                       Option "dynamic_lookup",
                       Option "-single_module" ]
-                 ++ (if platformArch platform == ArchX86_64
+                 ++ (if platformArch platform `elem` [ ArchX86_64, ArchAArch64 ]
                      then [ ]
                      else [ Option "-Wl,-read_only_relocs,suppress" ])
                  ++ [ Option "-install_name", Option instName ]
diff --git a/docs/users_guide/runtime_control.rst b/docs/users_guide/runtime_control.rst
index 73e8824154861414345b999d445ff9ed94b400af..d341a763ce64e7a80db1fc592c31f72a9ed36455 100644
--- a/docs/users_guide/runtime_control.rst
+++ b/docs/users_guide/runtime_control.rst
@@ -313,8 +313,10 @@ Miscellaneous RTS options
     an object, the linker will probably fail with an error message when the
     problem is detected.
 
-    On some platforms where PIC is always the case, e.g. x86_64 MacOS X, this
-    flag is enabled by default.
+    On some platforms where PIC is always the case, e.g. macOS and OpenBSD on
+    x86_64, and macOS and Linux on aarch64 this flag is enabled by default.
+    One repercussion of this is that referenced system libraries also need to be
+    compiled with ``-fPIC`` if we need to load them in the runtime linker.
 
 .. rts-flag:: -xm ⟨address⟩
 
diff --git a/rts/package.conf.in b/rts/package.conf.in
index e4cb159cb8d230664bd7eca2c5569e1a36bb6f59..6e1d19d58822471ed303c460e0249d132a689bca 100644
--- a/rts/package.conf.in
+++ b/rts/package.conf.in
@@ -296,7 +296,7 @@ ld-options:
          , "-Wl,-search_paths_first"
 #endif
 
-#if defined(darwin_HOST_OS) && !defined(x86_64_HOST_ARCH)
+#if defined(darwin_HOST_OS) && !defined(x86_64_HOST_ARCH) && !defined(aarch64_HOST_ARCH)
          , "-read_only_relocs", "warning"
 #endif
 
diff --git a/rts/rts.cabal.in b/rts/rts.cabal.in
index cab390ed30e3c1533c3d34cf0f4ff67d94826201..478e545589320877897708f1039870ae0d2f7fe0 100644
--- a/rts/rts.cabal.in
+++ b/rts/rts.cabal.in
@@ -368,7 +368,7 @@ library
 
     if os(osx)
       ld-options: "-Wl,-search_paths_first"
-      if !arch(x86_64)
+      if !arch(x86_64) && !arch(aarch64)
          ld-options: -read_only_relocs warning
 
     cmm-sources: Apply.cmm