diff --git a/qapi/misc.json b/qapi/misc.json
index 460866cf542f..74e5c2e3b8f7 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -550,41 +550,72 @@
 # Information about a virtual CPU
 #
 # @cpu-index: index of the virtual CPU
 #
 # @qom-path: path to the CPU object in the QOM tree
 #
 # @thread-id: ID of the underlying host thread
 #
 # @props: properties describing to which node/socket/core/thread
 #         virtual CPU belongs to, provided if supported by board
 #
-# @arch: architecture of the cpu, which determines which additional fields
-#        will be listed
+# @arch: base architecture of the cpu
+#
+# @target: the QEMU system emulation target, which is more specific than
+#          @arch and determines which additional fields will be listed
+#          (since 2.13)
+#
 #
 # Since: 2.12
 #
 ##
-{ 'union': 'CpuInfoFast',
-  'base': {'cpu-index': 'int', 'qom-path': 'str',
-           'thread-id': 'int', '*props': 'CpuInstanceProperties',
-           'arch': 'CpuInfoArch' },
-  'discriminator': 'arch',
-  'data': { 'x86': 'CpuInfoOther',
-            'sparc': 'CpuInfoOther',
-            'ppc': 'CpuInfoOther',
-            'mips': 'CpuInfoOther',
-            'tricore': 'CpuInfoOther',
-            's390': 'CpuInfoS390',
-            'riscv': 'CpuInfoOther',
-            'other': 'CpuInfoOther' } }
+{ 'union'         : 'CpuInfoFast',
+  'base'          : { 'cpu-index'    : 'int',
+                      'qom-path'     : 'str',
+                      'thread-id'    : 'int',
+                      '*props'       : 'CpuInstanceProperties',
+                      'arch'         : 'CpuInfoArch',
+                      'target'       : 'SysEmuTarget' },
+  'discriminator' : 'target',
+  'data'          : { 'aarch64'      : 'CpuInfoOther',
+                      'alpha'        : 'CpuInfoOther',
+                      'arm'          : 'CpuInfoOther',
+                      'cris'         : 'CpuInfoOther',
+                      'hppa'         : 'CpuInfoOther',
+                      'i386'         : 'CpuInfoOther',
+                      'lm32'         : 'CpuInfoOther',
+                      'm68k'         : 'CpuInfoOther',
+                      'microblaze'   : 'CpuInfoOther',
+                      'microblazeel' : 'CpuInfoOther',
+                      'mips'         : 'CpuInfoOther',
+                      'mips64'       : 'CpuInfoOther',
+                      'mips64el'     : 'CpuInfoOther',
+                      'mipsel'       : 'CpuInfoOther',
+                      'moxie'        : 'CpuInfoOther',
+                      'nios2'        : 'CpuInfoOther',
+                      'or1k'         : 'CpuInfoOther',
+                      'ppc'          : 'CpuInfoOther',
+                      'ppc64'        : 'CpuInfoOther',
+                      'ppcemb'       : 'CpuInfoOther',
+                      'riscv32'      : 'CpuInfoOther',
+                      'riscv64'      : 'CpuInfoOther',
+                      's390x'        : 'CpuInfoS390',
+                      'sh4'          : 'CpuInfoOther',
+                      'sh4eb'        : 'CpuInfoOther',
+                      'sparc'        : 'CpuInfoOther',
+                      'sparc64'      : 'CpuInfoOther',
+                      'tricore'      : 'CpuInfoOther',
+                      'unicore32'    : 'CpuInfoOther',
+                      'x86_64'       : 'CpuInfoOther',
+                      'xtensa'       : 'CpuInfoOther',
+                      'xtensaeb'     : 'CpuInfoOther' } }
 
 ##
 # @query-cpus-fast:
 #
 # Returns information about all virtual CPUs. This command does not
 # incur a performance penalty and should be used in production
 # instead of query-cpus.
 #
 # Returns: list of @CpuInfoFast
 #
 # Since: 2.12
@@ -594,33 +625,35 @@
 # -> { "execute": "query-cpus-fast" }
 # <- { "return": [
 #         {
 #             "thread-id": 25627,
 #             "props": {
 #                 "core-id": 0,
 #                 "thread-id": 0,
 #                 "socket-id": 0
 #             },
 #             "qom-path": "/machine/unattached/device[0]",
 #             "arch":"x86",
+#             "target":"x86_64",
 #             "cpu-index": 0
 #         },
 #         {
 #             "thread-id": 25628,
 #             "props": {
 #                 "core-id": 0,
 #                 "thread-id": 0,
 #                 "socket-id": 1
 #             },
 #             "qom-path": "/machine/unattached/device[2]",
 #             "arch":"x86",
+#             "target":"x86_64",
 #             "cpu-index": 1
 #         }
 #     ]
 # }
 ##
 { 'command': 'query-cpus-fast', 'returns': [ 'CpuInfoFast' ] }
 
 ##
 # @IOThreadInfo:
 #
 # Information about an iothread
diff --git a/cpus.c b/cpus.c
index 60563a6d54ec..5bcd3ecf3848 100644
--- a/cpus.c
+++ b/cpus.c
@@ -2179,73 +2179,112 @@ CpuInfoList *qmp_query_cpus(Error **errp)
         if (!cur_item) {
             head = cur_item = info;
         } else {
             cur_item->next = info;
             cur_item = info;
         }
     }
 
     return head;
 }
 
+static CpuInfoArch sysemu_target_to_cpuinfo_arch(SysEmuTarget target)
+{
+    /*
+     * The @SysEmuTarget -> @CpuInfoArch mapping below is based on the
+     * TARGET_ARCH -> TARGET_BASE_ARCH mapping in the "configure" script.
+     */
+    switch (target) {
+    case SYS_EMU_TARGET_I386:
+    case SYS_EMU_TARGET_X86_64:
+        return CPU_INFO_ARCH_X86;
+
+    case SYS_EMU_TARGET_PPC:
+    case SYS_EMU_TARGET_PPCEMB:
+    case SYS_EMU_TARGET_PPC64:
+        return CPU_INFO_ARCH_PPC;
+
+    case SYS_EMU_TARGET_SPARC:
+    case SYS_EMU_TARGET_SPARC64:
+        return CPU_INFO_ARCH_SPARC;
+
+    case SYS_EMU_TARGET_MIPS:
+    case SYS_EMU_TARGET_MIPSEL:
+    case SYS_EMU_TARGET_MIPS64:
+    case SYS_EMU_TARGET_MIPS64EL:
+        return CPU_INFO_ARCH_MIPS;
+
+    case SYS_EMU_TARGET_TRICORE:
+        return CPU_INFO_ARCH_TRICORE;
+
+    case SYS_EMU_TARGET_S390X:
+        return CPU_INFO_ARCH_S390;
+
+    case SYS_EMU_TARGET_RISCV32:
+    case SYS_EMU_TARGET_RISCV64:
+        return CPU_INFO_ARCH_RISCV;
+
+    default:
+        return CPU_INFO_ARCH_OTHER;
+    }
+}
+
+static void cpustate_to_cpuinfo_s390(CpuInfoS390 *info, const CPUState *cpu)
+{
+#ifdef TARGET_S390X
+    S390CPU *s390_cpu = S390_CPU(cpu);
+    CPUS390XState *env = &s390_cpu->env;
+
+    info->cpu_state = env->cpu_state;
+#else
+    abort();
+#endif
+}
+
 /*
  * fast means: we NEVER interrupt vCPU threads to retrieve
  * information from KVM.
  */
 CpuInfoFastList *qmp_query_cpus_fast(Error **errp)
 {
     MachineState *ms = MACHINE(qdev_get_machine());
     MachineClass *mc = MACHINE_GET_CLASS(ms);
     CpuInfoFastList *head = NULL, *cur_item = NULL;
+    SysEmuTarget target = qapi_enum_parse(&SysEmuTarget_lookup, TARGET_NAME,
+                                          -1, &error_abort);
     CPUState *cpu;
-#if defined(TARGET_S390X)
-    S390CPU *s390_cpu;
-    CPUS390XState *env;
-#endif
 
     CPU_FOREACH(cpu) {
         CpuInfoFastList *info = g_malloc0(sizeof(*info));
         info->value = g_malloc0(sizeof(*info->value));
 
         info->value->cpu_index = cpu->cpu_index;
         info->value->qom_path = object_get_canonical_path(OBJECT(cpu));
         info->value->thread_id = cpu->thread_id;
 
         info->value->has_props = !!mc->cpu_index_to_instance_props;
         if (info->value->has_props) {
             CpuInstanceProperties *props;
             props = g_malloc0(sizeof(*props));
             *props = mc->cpu_index_to_instance_props(ms, cpu->cpu_index);
             info->value->props = props;
         }
 
-#if defined(TARGET_I386)
-        info->value->arch = CPU_INFO_ARCH_X86;
-#elif defined(TARGET_PPC)
-        info->value->arch = CPU_INFO_ARCH_PPC;
-#elif defined(TARGET_SPARC)
-        info->value->arch = CPU_INFO_ARCH_SPARC;
-#elif defined(TARGET_MIPS)
-        info->value->arch = CPU_INFO_ARCH_MIPS;
-#elif defined(TARGET_TRICORE)
-        info->value->arch = CPU_INFO_ARCH_TRICORE;
-#elif defined(TARGET_S390X)
-        s390_cpu = S390_CPU(cpu);
-        env = &s390_cpu->env;
-        info->value->arch = CPU_INFO_ARCH_S390;
-        info->value->u.s390.cpu_state = env->cpu_state;
-#elif defined(TARGET_RISCV)
-        info->value->arch = CPU_INFO_ARCH_RISCV;
-#else
-        info->value->arch = CPU_INFO_ARCH_OTHER;
-#endif
+        info->value->arch = sysemu_target_to_cpuinfo_arch(target);
+        info->value->target = target;
+        if (target == SYS_EMU_TARGET_S390X) {
+            cpustate_to_cpuinfo_s390(&info->value->u.s390x, cpu);
+        } else {
+            /* do nothing for @CpuInfoOther */
+        }
+
         if (!cur_item) {
             head = cur_item = info;
         } else {
             cur_item->next = info;
             cur_item = info;
         }
     }
 
     return head;
 }
 
