diff --git a/common/spl/spl.c b/common/spl/spl.c
index 32b9f1e95c..9bcbd09ff3 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -513,6 +513,9 @@ ulong spl_relocate_stack_gd(void)
 	ptr = CONFIG_SPL_STACK_R_ADDR - roundup(sizeof(gd_t),16);
 	new_gd = (gd_t *)ptr;
 	memcpy(new_gd, (void *)gd, sizeof(gd_t));
+#if CONFIG_IS_ENABLED(DM)
+	dm_fixup_for_gd_move(new_gd);
+#endif
 #if !defined(CONFIG_ARM)
 	gd = new_gd;
 #endif
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 33dc9c0b2d..9edfc1efb6 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -41,6 +41,13 @@ struct udevice *dm_root(void)
 	return gd->dm_root;
 }
 
+void dm_fixup_for_gd_move(struct global_data *new_gd)
+{
+	/* The sentinel node has moved, so update things that point to it */
+	new_gd->uclass_root.next->prev = &new_gd->uclass_root;
+	new_gd->uclass_root.prev->next = &new_gd->uclass_root;
+}
+
 fdt_addr_t dm_get_translation_offset(void)
 {
 	struct udevice *root = dm_root();
diff --git a/include/dm/root.h b/include/dm/root.h
index c7f0c1d5ca..3cf730dcee 100644
--- a/include/dm/root.h
+++ b/include/dm/root.h
@@ -21,6 +21,16 @@ struct udevice;
  */
 struct udevice *dm_root(void);
 
+struct global_data;
+/**
+ * dm_fixup_for_gd_move() - Handle global_data moving to a new place
+ *
+ * The uclass list is part of global_data. Due to the way lists work, moving
+ * the list will cause it to become invalid. This function fixes that up so
+ * that the uclass list will work correctly.
+ */
+void dm_fixup_for_gd_move(struct global_data *new_gd);
+
 /**
  * dm_scan_platdata() - Scan all platform data and bind drivers
  *