diff --git a/hw/core/numa.c b/hw/core/numa.c
index 038c96d4ab..ba02a41421 100644
--- a/hw/core/numa.c
+++ b/hw/core/numa.c
@@ -33,6 +33,7 @@
 #include "qapi/error.h"
 #include "qapi/opts-visitor.h"
 #include "qapi/qapi-visit-machine.h"
+#include "qapi/clone-visitor.h"
 #include "sysemu/qtest.h"
 #include "hw/core/cpu.h"
 #include "hw/mem/pc-dimm.h"
@@ -59,11 +60,8 @@ static int max_numa_nodeid; /* Highest specified NUMA node ID, plus one.
 static void parse_numa_node(MachineState *ms, NumaNodeOptions *node,
                             Error **errp)
 {
-    Error *err = NULL;
     uint16_t nodenr;
-    uint16List *cpus = NULL;
     MachineClass *mc = MACHINE_GET_CLASS(ms);
-    unsigned int max_cpus = ms->smp.max_cpus;
     NodeInfo *numa_info = ms->numa_state->nodes;
 
     if (node->has_nodeid) {
@@ -87,24 +85,8 @@ static void parse_numa_node(MachineState *ms, NumaNodeOptions *node,
         error_setg(errp, "NUMA is not supported by this machine-type");
         return;
     }
-    for (cpus = node->cpus; cpus; cpus = cpus->next) {
-        CpuInstanceProperties props;
-        if (cpus->value >= max_cpus) {
-            error_setg(errp,
-                       "CPU index (%" PRIu16 ")"
-                       " should be smaller than maxcpus (%d)",
-                       cpus->value, max_cpus);
-            return;
-        }
-        props = mc->cpu_index_to_instance_props(ms, cpus->value);
-        props.node_id = nodenr;
-        props.has_node_id = true;
-        machine_set_cpu_numa_node(ms, &props, &err);
-        if (err) {
-            error_propagate(errp, err);
-            return;
-        }
-    }
+
+    numa_info[nodenr].cpu_indexes = QAPI_CLONE(uint16List, node->cpus);
 
     have_memdevs = have_memdevs ? : node->has_memdev;
     have_mem = have_mem ? : node->has_mem;
@@ -360,12 +342,50 @@ void numa_default_auto_assign_ram(MachineClass *mc, NodeInfo *nodes,
     nodes[i].node_mem = size - usedmem;
 }
 
+
+void numa_node_complete_configuration(MachineState *ms, NodeInfo *node,
+                                      uint16_t nodenr)
+{
+    Error *err = NULL;
+    uint16List *cpus = NULL;
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
+    unsigned int max_cpus = ms->smp.max_cpus;
+
+    for (cpus = node->cpu_indexes; cpus; cpus = cpus->next) {
+        CpuInstanceProperties props;
+        if (cpus->value >= max_cpus) {
+            error_report("CPU index (%" PRIu16 ")"
+                         " should be smaller than maxcpus (%d)",
+                         cpus->value, max_cpus);
+            return;
+        }
+        props = mc->cpu_index_to_instance_props(ms, cpus->value);
+        props.node_id = nodenr;
+        props.has_node_id = true;
+        machine_set_cpu_numa_node(ms, &props, &err);
+        if (err) {
+            error_report("Numa node initialization failed");
+            return;
+        }
+    }
+}
+
 void numa_complete_configuration(MachineState *ms)
 {
     int i;
     MachineClass *mc = MACHINE_GET_CLASS(ms);
     NodeInfo *numa_info = ms->numa_state->nodes;
 
+    for (i = 0; i < ms->numa_state->num_nodes; i++) {
+        /*
+         * numa_node_complete_configuration() needs to be called after all
+         * nodes were already parsed, because to support new epyc mode, we
+         * need to know the number of numa nodes in advance to generate
+         * apic id correctly.
+         */
+        numa_node_complete_configuration(ms, &numa_info[i], i);
+    }
+
     /*
      * If memory hotplug is enabled (slots > 0) but without '-numa'
      * options explicitly on CLI, guestes will break.
diff --git a/include/sysemu/numa.h b/include/sysemu/numa.h
index ae9c41d02b..91794d685f 100644
--- a/include/sysemu/numa.h
+++ b/include/sysemu/numa.h
@@ -19,6 +19,9 @@ struct NodeInfo {
     struct HostMemoryBackend *node_memdev;
     bool present;
     uint8_t distance[MAX_NODES];
+
+    /* These indexes are saved for numa node initialization later */
+    uint16List *cpu_indexes;
 };
 
 struct NumaNodeMem {
@@ -41,6 +44,8 @@ typedef struct NumaState NumaState;
 void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp);
 void parse_numa_opts(MachineState *ms);
 void numa_complete_configuration(MachineState *ms);
+void numa_node_complete_configuration(MachineState *ms, NodeInfo *node,
+                                      uint16_t nodenr);
 void query_numa_node_mem(NumaNodeMem node_mem[], MachineState *ms);
 extern QemuOptsList qemu_numa_opts;
 void numa_legacy_auto_assign_ram(MachineClass *mc, NodeInfo *nodes,
