diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
index bc765b59ba93b9eaec464aaa976e0261de3b3ad2..71c0246b6fce07bf9af20aade370be360bd45d39 100644
--- a/.github/workflows/validate.yml
+++ b/.github/workflows/validate.yml
@@ -70,7 +70,7 @@ jobs:
         # If you remove something from here, then add it to the old-ghcs job.
         # Also a removed GHC from here means that we are actually dropping
         # support, so the PR *must* have a changelog entry.
-        ghc: ['9.8.2', '9.6.4', '9.4.8', '9.2.8', '9.0.2', '8.10.7', '8.8.4', '8.6.5']
+        ghc: ['9.10.1', '9.8.2', '9.6.4', '9.4.8', '9.2.8', '9.0.2', '8.10.7', '8.8.4', '8.6.5']
         exclude:
           # corrupts GHA cache or the fabric of reality itself, see https://github.com/haskell/cabal/issues/8356
           - os: windows-latest
@@ -104,6 +104,7 @@ jobs:
         with:
           ghc-version: ${{ matrix.ghc }}
           cabal-version: latest # latest is mandatory for cabal-testsuite, see https://github.com/haskell/cabal/issues/8133
+          ghcup-release-channel: https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.8.yaml
 
       #  See the following link for a breakdown of the following step
       #  https://github.com/haskell/actions/issues/7#issuecomment-745697160
diff --git a/cabal-install/src/Distribution/Client/TargetSelector.hs b/cabal-install/src/Distribution/Client/TargetSelector.hs
index f287400e1e173a392ac7fcf50758d08a8692a157..8dabe33f22a14294de7ecbe99b43e413c9d18174 100644
--- a/cabal-install/src/Distribution/Client/TargetSelector.hs
+++ b/cabal-install/src/Distribution/Client/TargetSelector.hs
@@ -101,6 +101,11 @@ import Control.Arrow ((&&&))
 import Control.Monad hiding
   ( mfilter
   )
+#if MIN_VERSION_base(4,20,0)
+import Data.Functor as UZ (unzip)
+#else
+import qualified Data.List.NonEmpty as UZ (unzip)
+#endif
 import Data.List
   ( stripPrefix
   )
@@ -585,7 +590,7 @@ resolveTargetSelector knowntargets@KnownTargets{..} mfilter targetStrStatus =
 
     classifyMatchErrors errs
       | Just expectedNE <- NE.nonEmpty expected =
-          let (things, got :| _) = NE.unzip expectedNE
+          let (things, got :| _) = UZ.unzip expectedNE
            in TargetSelectorExpected targetStr (NE.toList things) got
       | not (null nosuch) =
           TargetSelectorNoSuch targetStr nosuch
diff --git a/cabal-install/tests/IntegrationTests2.hs b/cabal-install/tests/IntegrationTests2.hs
index 3598b357d699004f98885d56836a7b9794accdf9..a917e48efadec0df1f5ca91a9691c623e576b42e 100644
--- a/cabal-install/tests/IntegrationTests2.hs
+++ b/cabal-install/tests/IntegrationTests2.hs
@@ -1438,9 +1438,11 @@ testSetupScriptStyles config reportSubCase = do
 
   let isOSX (Platform _ OSX) = True
       isOSX _ = False
+      compilerVer = compilerVersion (pkgConfigCompiler sharedConfig)
   -- Skip the Custom tests when the shipped Cabal library is buggy
-  unless (isOSX (pkgConfigPlatform sharedConfig)
-       && compilerVersion (pkgConfigCompiler sharedConfig) < mkVersion [7,10]) $ do
+  unless ((isOSX (pkgConfigPlatform sharedConfig) && (compilerVer < mkVersion [7,10]))
+       -- 9.10 ships Cabal 3.12.0.0 affected by #9940
+       || (mkVersion [9,10] <= compilerVer && compilerVer < mkVersion [9,11])) $ do
 
     (plan1, res1) <- executePlan plan0
     pkg1          <- expectPackageInstalled plan1 res1 pkgidA
diff --git a/cabal-install/tests/UnitTests/Distribution/Client/Init/NonInteractive.hs b/cabal-install/tests/UnitTests/Distribution/Client/Init/NonInteractive.hs
index d35ab35a659ee31d4dbcd59356d1d29fdc1acbdc..cd618622201a558f6a7a33ef4e2b0b9cf730a792 100644
--- a/cabal-install/tests/UnitTests/Distribution/Client/Init/NonInteractive.hs
+++ b/cabal-install/tests/UnitTests/Distribution/Client/Init/NonInteractive.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE LambdaCase #-}
 
 module UnitTests.Distribution.Client.Init.NonInteractive
@@ -12,7 +13,9 @@ import UnitTests.Distribution.Client.Init.Utils
 import qualified Data.List.NonEmpty as NEL
 import qualified Distribution.SPDX as SPDX
 
+#if !MIN_VERSION_base(4,20,0)
 import Data.List (foldl')
+#endif
 import qualified Data.Set as Set
 import Distribution.CabalSpecVersion
 import Distribution.Client.Init.Defaults
diff --git a/cabal-testsuite/PackageTests/CCompilerOverride/foo.c b/cabal-testsuite/PackageTests/CCompilerOverride/foo.c
index 30892bef07e8d4419b4972fa73db02765b5b3b10..03ddd01e14b1121b2533ac597ae7e3401fd07563 100644
--- a/cabal-testsuite/PackageTests/CCompilerOverride/foo.c
+++ b/cabal-testsuite/PackageTests/CCompilerOverride/foo.c
@@ -1,16 +1,8 @@
 
-#ifndef NOERROR1
-#error "NOERROR1 was not passed"
-#endif
-
 #ifndef NOERROR2
 #error "NOERROR2 was not passed"
 #endif
 
-#ifndef NOERROR3
-#error "NOERROR3 was not passed"
-#endif
-
 #ifndef NOERROR4
 #error "NOERROR4 was not passed"
 #endif
diff --git a/cabal-testsuite/PackageTests/CCompilerOverride/my.cabal b/cabal-testsuite/PackageTests/CCompilerOverride/my.cabal
index 31a79f93a60cf7dc0b46327ce18538177215fbb9..14772f3894f6d58b3e0fb4c63bec75a11b53d468 100644
--- a/cabal-testsuite/PackageTests/CCompilerOverride/my.cabal
+++ b/cabal-testsuite/PackageTests/CCompilerOverride/my.cabal
@@ -9,5 +9,5 @@ executable foo
     main-is:          Main.hs
     c-sources:        foo.c
     build-depends:    base
-    ghc-options:      -DNOERROR4
+    ghc-options:      -optc=-DNOERROR4
     cc-options:       -DNOERROR5 -march=native
diff --git a/cabal-testsuite/PackageTests/CCompilerOverride/setup.cabal.out b/cabal-testsuite/PackageTests/CCompilerOverride/setup.cabal.out
index 21981fd9b76cb8d9627ddc6106b105ebd6017154..6d0c3265de9f7dab52a30d53fbcbffbb9418fa84 100644
--- a/cabal-testsuite/PackageTests/CCompilerOverride/setup.cabal.out
+++ b/cabal-testsuite/PackageTests/CCompilerOverride/setup.cabal.out
@@ -1,4 +1,3 @@
 # Setup configure
 Configuring my-0.1...
-Warning: [misplaced-c-opt] Instead of 'ghc-options: -DNOERROR4' use 'cpp-options: -DNOERROR4'
 # Setup build
diff --git a/cabal-testsuite/PackageTests/CCompilerOverride/setup.out b/cabal-testsuite/PackageTests/CCompilerOverride/setup.out
index 21981fd9b76cb8d9627ddc6106b105ebd6017154..6d0c3265de9f7dab52a30d53fbcbffbb9418fa84 100644
--- a/cabal-testsuite/PackageTests/CCompilerOverride/setup.out
+++ b/cabal-testsuite/PackageTests/CCompilerOverride/setup.out
@@ -1,4 +1,3 @@
 # Setup configure
 Configuring my-0.1...
-Warning: [misplaced-c-opt] Instead of 'ghc-options: -DNOERROR4' use 'cpp-options: -DNOERROR4'
 # Setup build
diff --git a/cabal-testsuite/PackageTests/CCompilerOverride/setup.test.hs b/cabal-testsuite/PackageTests/CCompilerOverride/setup.test.hs
index 5843cb2b7df4765ef3601736a0d266aa74d40040..b4f7f04ddb16230c8595fbe89cc474524f38388b 100644
--- a/cabal-testsuite/PackageTests/CCompilerOverride/setup.test.hs
+++ b/cabal-testsuite/PackageTests/CCompilerOverride/setup.test.hs
@@ -3,6 +3,10 @@ import Test.Cabal.Prelude
 -- Test that all the respective defines -DNOERROR... specified in various ways
 -- all end up routed to the C compiler. Otherwise the C file we depend on will
 -- not compile.
+--
+-- This has been largely gutted, as ghc 9.10 no longer passes through most
+-- of the defines we were testing; see
+-- https://gitlab.haskell.org/ghc/ghc/-/commit/8ff3134ed4aa323b0199ad683f72165e51a59ab6
 main = setupAndCabalTest $ do
   skipUnlessGhcVersion ">= 8.8"
   isWin <- isWindows
@@ -14,9 +18,7 @@ main = setupAndCabalTest $ do
         pwd ++ "/custom-cc" ++ if isWin then win_suffix else ""
 
   setup "configure"
-    [ "--ghc-option=-DNOERROR1"
-    , "--ghc-option=-optc=-DNOERROR2"
-    , "--ghc-option=-optP=-DNOERROR3"
+    [ "--ghc-option=-optc=-DNOERROR2"
     , "--with-gcc=" ++ customCC
     ]
   setup "build" ["-v2"]
diff --git a/project-cabal/ghc-latest.config b/project-cabal/ghc-latest.config
index bff5d80c2412249e60ce9207fe221bfec67d469f..5f8d40290dbd927f23b0a75b1b2e181ad7aa07a5 100644
--- a/project-cabal/ghc-latest.config
+++ b/project-cabal/ghc-latest.config
@@ -8,5 +8,17 @@
 
 -- NOTE: don't forget to update the compiler version in the conditional
 -- when upgrading to a newer GHC
-if impl(ghc >= 9.8.1)
-    -- allow-newer: windns:*
+if impl(ghc >= 9.10.0)
+    allow-newer:
+    --windns:*, rere:*, tree-diff:*, uuid-types:*, these:*, hashable:*, assoc:*, semialign:*, indexed-traversable-instances:*, indexed-traversable:*, OneTuple:*, scientific:*, time-compat:*, text-short:*, integer-conversion:*, generically:*, data-fix:*, binary:*
+    -- Artem, 2024-04-21: I started and then gave up...
+        *:base, *:template-haskell, text-short, *:deepseq, *:bytestring, *:ghc-prim
+
+    repository head.hackage.ghc.haskell.org
+        url: https://ghc.gitlab.haskell.org/head.hackage/
+        secure: True
+        key-threshold: 3
+        root-keys:
+            26021a13b401500c8eb2761ca95c61f2d625bfef951b939a8124ed12ecf07329
+            7541f32a4ccca4f97aea3b22f5e593ba2c0267546016b992dfadcd2fe944e55d
+            f76d08be13e9a61a377a85e2fb63f4c5435d40f8feb3e12eb05905edb8cdea89