- Ignore writes to CNTP_CTL_EL0 on HVF ARM (Alexander)
 - Add '-d invalid_mem' logging option (Zoltan)
 - Create QOM containers explicitly (Peter)
 - Rename sysemu/ -> system/ (Philippe)
 - Re-orderning of include/exec/ headers (Philippe)
   Move a lot of declarations from these legacy mixed bag headers:
     . "exec/cpu-all.h"
     . "exec/cpu-common.h"
     . "exec/cpu-defs.h"
     . "exec/exec-all.h"
     . "exec/translate-all"
   to these more specific ones:
     . "exec/page-protection.h"
     . "exec/translation-block.h"
     . "user/cpu_loop.h"
     . "user/guest-host.h"
     . "user/page-protection.h"
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmdlnyAACgkQ4+MsLN6t
 wN6mBw//QFWi7CrU+bb8KMM53kOU9C507tjn99LLGFb5or73/umDsw6eo/b8DHBt
 KIwGLgATel42oojKfNKavtAzLK5rOrywpboPDpa3SNeF1onW+99NGJ52LQUqIX6K
 A6bS0fPdGG9ZzEuPpbjDXlp++0yhDcdSgZsS42fEsT7Dyj5gzJYlqpqhiXGqpsn8
 4Y0UMxSL21K3HEexlzw2hsoOBFA3tUm2ujNDhNkt8QASr85yQVLCypABJnuoe///
 5Ojl5wTBeDwhANET0rhwHK8eIYaNboiM9fHopJYhvyw1bz6yAu9jQwzF/MrL3s/r
 xa4OBHBy5mq2hQV9Shcl3UfCQdk/vDaYaWpgzJGX8stgMGYfnfej1SIl8haJIfcl
 VMX8/jEFdYbjhO4AeGRYcBzWjEJymkDJZoiSWp2NuEDi6jqIW+7yW1q0Rnlg9lay
 ShAqLK5Pv4zUw3t0Jy3qv9KSW8sbs6PQxtzXjk8p97rTf76BJ2pF8sv1tVzmsidP
 9L92Hv5O34IqzBu2oATOUZYJk89YGmTIUSLkpT7asJZpBLwNM2qLp5jO00WVU0Sd
 +kAn324guYPkko/TVnjC/AY7CMu55EOtD9NU35k3mUAnxXT9oDUeL4NlYtfgrJx6
 x1Nzr2FkS68+wlPAFKNSSU5lTjsjNaFM0bIJ4LCNtenJVP+SnRo=
 =cjz8
 -----END PGP SIGNATURE-----
Merge tag 'exec-20241220' of https://github.com/philmd/qemu into staging
Accel & Exec patch queue
- Ignore writes to CNTP_CTL_EL0 on HVF ARM (Alexander)
- Add '-d invalid_mem' logging option (Zoltan)
- Create QOM containers explicitly (Peter)
- Rename sysemu/ -> system/ (Philippe)
- Re-orderning of include/exec/ headers (Philippe)
  Move a lot of declarations from these legacy mixed bag headers:
    . "exec/cpu-all.h"
    . "exec/cpu-common.h"
    . "exec/cpu-defs.h"
    . "exec/exec-all.h"
    . "exec/translate-all"
  to these more specific ones:
    . "exec/page-protection.h"
    . "exec/translation-block.h"
    . "user/cpu_loop.h"
    . "user/guest-host.h"
    . "user/page-protection.h"
 # -----BEGIN PGP SIGNATURE-----
 #
 # iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmdlnyAACgkQ4+MsLN6t
 # wN6mBw//QFWi7CrU+bb8KMM53kOU9C507tjn99LLGFb5or73/umDsw6eo/b8DHBt
 # KIwGLgATel42oojKfNKavtAzLK5rOrywpboPDpa3SNeF1onW+99NGJ52LQUqIX6K
 # A6bS0fPdGG9ZzEuPpbjDXlp++0yhDcdSgZsS42fEsT7Dyj5gzJYlqpqhiXGqpsn8
 # 4Y0UMxSL21K3HEexlzw2hsoOBFA3tUm2ujNDhNkt8QASr85yQVLCypABJnuoe///
 # 5Ojl5wTBeDwhANET0rhwHK8eIYaNboiM9fHopJYhvyw1bz6yAu9jQwzF/MrL3s/r
 # xa4OBHBy5mq2hQV9Shcl3UfCQdk/vDaYaWpgzJGX8stgMGYfnfej1SIl8haJIfcl
 # VMX8/jEFdYbjhO4AeGRYcBzWjEJymkDJZoiSWp2NuEDi6jqIW+7yW1q0Rnlg9lay
 # ShAqLK5Pv4zUw3t0Jy3qv9KSW8sbs6PQxtzXjk8p97rTf76BJ2pF8sv1tVzmsidP
 # 9L92Hv5O34IqzBu2oATOUZYJk89YGmTIUSLkpT7asJZpBLwNM2qLp5jO00WVU0Sd
 # +kAn324guYPkko/TVnjC/AY7CMu55EOtD9NU35k3mUAnxXT9oDUeL4NlYtfgrJx6
 # x1Nzr2FkS68+wlPAFKNSSU5lTjsjNaFM0bIJ4LCNtenJVP+SnRo=
 # =cjz8
 # -----END PGP SIGNATURE-----
 # gpg: Signature made Fri 20 Dec 2024 11:45:20 EST
 # gpg:                using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
 # gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [unknown]
 # gpg: WARNING: This key is not certified with a trusted signature!
 # gpg:          There is no indication that the signature belongs to the owner.
 # Primary key fingerprint: FAAB E75E 1291 7221 DCFD  6BB2 E3E3 2C2C DEAD C0DE
* tag 'exec-20241220' of https://github.com/philmd/qemu: (59 commits)
  util/qemu-timer: fix indentation
  meson: Do not define CONFIG_DEVICES on user emulation
  system/accel-ops: Remove unnecessary 'exec/cpu-common.h' header
  system/numa: Remove unnecessary 'exec/cpu-common.h' header
  hw/xen: Remove unnecessary 'exec/cpu-common.h' header
  target/mips: Drop left-over comment about Jazz machine
  target/mips: Remove tswap() calls in semihosting uhi_fstat_cb()
  target/xtensa: Remove tswap() calls in semihosting simcall() helper
  accel/tcg: Un-inline translator_is_same_page()
  accel/tcg: Include missing 'exec/translation-block.h' header
  accel/tcg: Move tcg_cflags_has/set() to 'exec/translation-block.h'
  accel/tcg: Restrict curr_cflags() declaration to 'internal-common.h'
  qemu/coroutine: Include missing 'qemu/atomic.h' header
  exec/translation-block: Include missing 'qemu/atomic.h' header
  accel/tcg: Declare cpu_loop_exit_requested() in 'exec/cpu-common.h'
  exec/cpu-all: Include 'cpu.h' earlier so MMU_USER_IDX is always defined
  target/sparc: Move sparc_restore_state_to_opc() to cpu.c
  target/sparc: Uninline cpu_get_tb_cpu_state()
  target/loongarch: Declare loongarch_cpu_dump_state() locally
  user: Move various declarations out of 'exec/exec-all.h'
  ...
Conflicts:
	hw/char/riscv_htif.c
	hw/intc/riscv_aplic.c
	target/s390x/cpu.c
	Apply sysemu header path changes to not in the pull request.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
		
	
			
		
			
				
	
	
		
			415 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			415 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * sPAPR CPU core device, acts as container of CPU thread devices.
 | 
						|
 *
 | 
						|
 * Copyright (C) 2016 Bharata B Rao <bharata@linux.vnet.ibm.com>
 | 
						|
 *
 | 
						|
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | 
						|
 * See the COPYING file in the top-level directory.
 | 
						|
 */
 | 
						|
 | 
						|
#include "qemu/osdep.h"
 | 
						|
#include "hw/cpu/core.h"
 | 
						|
#include "hw/ppc/spapr_cpu_core.h"
 | 
						|
#include "hw/qdev-properties.h"
 | 
						|
#include "migration/vmstate.h"
 | 
						|
#include "target/ppc/cpu.h"
 | 
						|
#include "hw/ppc/spapr.h"
 | 
						|
#include "qapi/error.h"
 | 
						|
#include "system/cpus.h"
 | 
						|
#include "system/kvm.h"
 | 
						|
#include "target/ppc/kvm_ppc.h"
 | 
						|
#include "hw/ppc/ppc.h"
 | 
						|
#include "target/ppc/mmu-hash64.h"
 | 
						|
#include "target/ppc/power8-pmu.h"
 | 
						|
#include "system/numa.h"
 | 
						|
#include "system/reset.h"
 | 
						|
#include "system/hw_accel.h"
 | 
						|
#include "qemu/error-report.h"
 | 
						|
 | 
						|
static void spapr_reset_vcpu(PowerPCCPU *cpu)
 | 
						|
{
 | 
						|
    CPUState *cs = CPU(cpu);
 | 
						|
    CPUPPCState *env = &cpu->env;
 | 
						|
    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
 | 
						|
    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
 | 
						|
    target_ulong lpcr;
 | 
						|
    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
 | 
						|
 | 
						|
    cpu_reset(cs);
 | 
						|
 | 
						|
    /*
 | 
						|
     * "PowerPC Processor binding to IEEE 1275" defines the initial MSR state
 | 
						|
     * as 32bit (MSR_SF=0) with MSR_ME=1 and MSR_FP=1 in "8.2.1. Initial
 | 
						|
     * Register Values". This can also be found in "LoPAPR 1.1" "C.9.2.1
 | 
						|
     * Initial Register Values".
 | 
						|
     */
 | 
						|
    env->msr &= ~(1ULL << MSR_SF);
 | 
						|
    env->msr |= (1ULL << MSR_ME) | (1ULL << MSR_FP);
 | 
						|
 | 
						|
    env->spr[SPR_HIOR] = 0;
 | 
						|
 | 
						|
    lpcr = env->spr[SPR_LPCR];
 | 
						|
 | 
						|
    /* Set emulated LPCR to not send interrupts to hypervisor. Note that
 | 
						|
     * under KVM, the actual HW LPCR will be set differently by KVM itself,
 | 
						|
     * the settings below ensure proper operations with TCG in absence of
 | 
						|
     * a real hypervisor.
 | 
						|
     *
 | 
						|
     * Disable Power-saving mode Exit Cause exceptions for the CPU, so
 | 
						|
     * we don't get spurious wakups before an RTAS start-cpu call.
 | 
						|
     * For the same reason, set PSSCR_EC.
 | 
						|
     */
 | 
						|
    lpcr &= ~(LPCR_VPM1 | LPCR_ISL | LPCR_KBV | pcc->lpcr_pm);
 | 
						|
    lpcr |= LPCR_LPES0 | LPCR_LPES1;
 | 
						|
    env->spr[SPR_PSSCR] |= PSSCR_EC;
 | 
						|
 | 
						|
    ppc_store_lpcr(cpu, lpcr);
 | 
						|
 | 
						|
    /* Set a full AMOR so guest can use the AMR as it sees fit */
 | 
						|
    env->spr[SPR_AMOR] = 0xffffffffffffffffull;
 | 
						|
 | 
						|
    spapr_cpu->vpa_addr = 0;
 | 
						|
    spapr_cpu->slb_shadow_addr = 0;
 | 
						|
    spapr_cpu->slb_shadow_size = 0;
 | 
						|
    spapr_cpu->dtl_addr = 0;
 | 
						|
    spapr_cpu->dtl_size = 0;
 | 
						|
 | 
						|
    spapr_caps_cpu_apply(spapr, cpu);
 | 
						|
 | 
						|
    kvm_check_mmu(cpu, &error_fatal);
 | 
						|
 | 
						|
    cpu_ppc_tb_reset(env);
 | 
						|
 | 
						|
    spapr_irq_cpu_intc_reset(spapr, cpu);
 | 
						|
}
 | 
						|
 | 
						|
void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip,
 | 
						|
                               target_ulong r1, target_ulong r3,
 | 
						|
                               target_ulong r4)
 | 
						|
{
 | 
						|
    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
 | 
						|
    CPUPPCState *env = &cpu->env;
 | 
						|
 | 
						|
    env->nip = nip;
 | 
						|
    env->gpr[1] = r1;
 | 
						|
    env->gpr[3] = r3;
 | 
						|
    env->gpr[4] = r4;
 | 
						|
    kvmppc_set_reg_ppc_online(cpu, 1);
 | 
						|
    CPU(cpu)->halted = 0;
 | 
						|
    /* Enable Power-saving mode Exit Cause exceptions */
 | 
						|
    ppc_store_lpcr(cpu, env->spr[SPR_LPCR] | pcc->lpcr_pm);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Return the sPAPR CPU core type for @model which essentially is the CPU
 | 
						|
 * model specified with -cpu cmdline option.
 | 
						|
 */
 | 
						|
const char *spapr_get_cpu_core_type(const char *cpu_type)
 | 
						|
{
 | 
						|
    int len = strlen(cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
 | 
						|
    char *core_type = g_strdup_printf(SPAPR_CPU_CORE_TYPE_NAME("%.*s"),
 | 
						|
                                      len, cpu_type);
 | 
						|
    ObjectClass *oc = object_class_by_name(core_type);
 | 
						|
 | 
						|
    g_free(core_type);
 | 
						|
    if (!oc) {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    return object_class_get_name(oc);
 | 
						|
}
 | 
						|
 | 
						|
static bool slb_shadow_needed(void *opaque)
 | 
						|
{
 | 
						|
    SpaprCpuState *spapr_cpu = opaque;
 | 
						|
 | 
						|
    return spapr_cpu->slb_shadow_addr != 0;
 | 
						|
}
 | 
						|
 | 
						|
static const VMStateDescription vmstate_spapr_cpu_slb_shadow = {
 | 
						|
    .name = "spapr_cpu/vpa/slb_shadow",
 | 
						|
    .version_id = 1,
 | 
						|
    .minimum_version_id = 1,
 | 
						|
    .needed = slb_shadow_needed,
 | 
						|
    .fields = (const VMStateField[]) {
 | 
						|
        VMSTATE_UINT64(slb_shadow_addr, SpaprCpuState),
 | 
						|
        VMSTATE_UINT64(slb_shadow_size, SpaprCpuState),
 | 
						|
        VMSTATE_END_OF_LIST()
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
static bool dtl_needed(void *opaque)
 | 
						|
{
 | 
						|
    SpaprCpuState *spapr_cpu = opaque;
 | 
						|
 | 
						|
    return spapr_cpu->dtl_addr != 0;
 | 
						|
}
 | 
						|
 | 
						|
static const VMStateDescription vmstate_spapr_cpu_dtl = {
 | 
						|
    .name = "spapr_cpu/vpa/dtl",
 | 
						|
    .version_id = 1,
 | 
						|
    .minimum_version_id = 1,
 | 
						|
    .needed = dtl_needed,
 | 
						|
    .fields = (const VMStateField[]) {
 | 
						|
        VMSTATE_UINT64(dtl_addr, SpaprCpuState),
 | 
						|
        VMSTATE_UINT64(dtl_size, SpaprCpuState),
 | 
						|
        VMSTATE_END_OF_LIST()
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
static bool vpa_needed(void *opaque)
 | 
						|
{
 | 
						|
    SpaprCpuState *spapr_cpu = opaque;
 | 
						|
 | 
						|
    return spapr_cpu->vpa_addr != 0;
 | 
						|
}
 | 
						|
 | 
						|
static const VMStateDescription vmstate_spapr_cpu_vpa = {
 | 
						|
    .name = "spapr_cpu/vpa",
 | 
						|
    .version_id = 1,
 | 
						|
    .minimum_version_id = 1,
 | 
						|
    .needed = vpa_needed,
 | 
						|
    .fields = (const VMStateField[]) {
 | 
						|
        VMSTATE_UINT64(vpa_addr, SpaprCpuState),
 | 
						|
        VMSTATE_END_OF_LIST()
 | 
						|
    },
 | 
						|
    .subsections = (const VMStateDescription * const []) {
 | 
						|
        &vmstate_spapr_cpu_slb_shadow,
 | 
						|
        &vmstate_spapr_cpu_dtl,
 | 
						|
        NULL
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
static const VMStateDescription vmstate_spapr_cpu_state = {
 | 
						|
    .name = "spapr_cpu",
 | 
						|
    .version_id = 1,
 | 
						|
    .minimum_version_id = 1,
 | 
						|
    .fields = (const VMStateField[]) {
 | 
						|
        VMSTATE_END_OF_LIST()
 | 
						|
    },
 | 
						|
    .subsections = (const VMStateDescription * const []) {
 | 
						|
        &vmstate_spapr_cpu_vpa,
 | 
						|
        NULL
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
static void spapr_unrealize_vcpu(PowerPCCPU *cpu, SpaprCpuCore *sc)
 | 
						|
{
 | 
						|
    CPUPPCState *env = &cpu->env;
 | 
						|
 | 
						|
    vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data);
 | 
						|
    spapr_irq_cpu_intc_destroy(SPAPR_MACHINE(qdev_get_machine()), cpu);
 | 
						|
    cpu_ppc_tb_free(env);
 | 
						|
    qdev_unrealize(DEVICE(cpu));
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Called when CPUs are hot-plugged.
 | 
						|
 */
 | 
						|
static void spapr_cpu_core_reset(DeviceState *dev)
 | 
						|
{
 | 
						|
    CPUCore *cc = CPU_CORE(dev);
 | 
						|
    SpaprCpuCore *sc = SPAPR_CPU_CORE(dev);
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < cc->nr_threads; i++) {
 | 
						|
        spapr_reset_vcpu(sc->threads[i]);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Called by the machine reset.
 | 
						|
 */
 | 
						|
static void spapr_cpu_core_reset_handler(void *opaque)
 | 
						|
{
 | 
						|
    spapr_cpu_core_reset(opaque);
 | 
						|
}
 | 
						|
 | 
						|
static void spapr_delete_vcpu(PowerPCCPU *cpu)
 | 
						|
{
 | 
						|
    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
 | 
						|
 | 
						|
    cpu->machine_data = NULL;
 | 
						|
    g_free(spapr_cpu);
 | 
						|
    object_unparent(OBJECT(cpu));
 | 
						|
}
 | 
						|
 | 
						|
static void spapr_cpu_core_unrealize(DeviceState *dev)
 | 
						|
{
 | 
						|
    SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
 | 
						|
    CPUCore *cc = CPU_CORE(dev);
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < cc->nr_threads; i++) {
 | 
						|
        if (sc->threads[i]) {
 | 
						|
            /*
 | 
						|
             * Since this we can get here from the error path of
 | 
						|
             * spapr_cpu_core_realize(), make sure we only unrealize
 | 
						|
             * vCPUs that have already been realized.
 | 
						|
             */
 | 
						|
            if (qdev_is_realized(DEVICE(sc->threads[i]))) {
 | 
						|
                spapr_unrealize_vcpu(sc->threads[i], sc);
 | 
						|
            }
 | 
						|
            spapr_delete_vcpu(sc->threads[i]);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    g_free(sc->threads);
 | 
						|
    qemu_unregister_reset(spapr_cpu_core_reset_handler, sc);
 | 
						|
}
 | 
						|
 | 
						|
static bool spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr,
 | 
						|
                               SpaprCpuCore *sc, int thread_index, Error **errp)
 | 
						|
{
 | 
						|
    CPUPPCState *env = &cpu->env;
 | 
						|
    CPUState *cs = CPU(cpu);
 | 
						|
 | 
						|
    if (!qdev_realize(DEVICE(cpu), NULL, errp)) {
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    cpu_ppc_set_vhyp(cpu, PPC_VIRTUAL_HYPERVISOR(spapr));
 | 
						|
    kvmppc_set_papr(cpu);
 | 
						|
 | 
						|
    env->spr_cb[SPR_PIR].default_value = cs->cpu_index;
 | 
						|
    env->spr_cb[SPR_TIR].default_value = thread_index;
 | 
						|
 | 
						|
    cpu_ppc_set_1lpar(cpu);
 | 
						|
 | 
						|
    /* Set time-base frequency to 512 MHz. vhyp must be set first. */
 | 
						|
    cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);
 | 
						|
 | 
						|
    if (spapr_irq_cpu_intc_create(spapr, cpu, errp) < 0) {
 | 
						|
        qdev_unrealize(DEVICE(cpu));
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    vmstate_register(NULL, cs->cpu_index, &vmstate_spapr_cpu_state,
 | 
						|
                     cpu->machine_data);
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
static PowerPCCPU *spapr_create_vcpu(SpaprCpuCore *sc, int i, Error **errp)
 | 
						|
{
 | 
						|
    SpaprCpuCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(sc);
 | 
						|
    CPUCore *cc = CPU_CORE(sc);
 | 
						|
    g_autoptr(Object) obj = NULL;
 | 
						|
    g_autofree char *id = NULL;
 | 
						|
    CPUState *cs;
 | 
						|
    PowerPCCPU *cpu;
 | 
						|
    CPUPPCState *env;
 | 
						|
 | 
						|
    obj = object_new(scc->cpu_type);
 | 
						|
 | 
						|
    cs = CPU(obj);
 | 
						|
    cpu = POWERPC_CPU(obj);
 | 
						|
    env = &cpu->env;
 | 
						|
    /*
 | 
						|
     * All CPUs start halted. CPU0 is unhalted from the machine level reset code
 | 
						|
     * and the rest are explicitly started up by the guest using an RTAS call.
 | 
						|
     */
 | 
						|
    qdev_prop_set_bit(DEVICE(obj), "start-powered-off", true);
 | 
						|
    cs->cpu_index = cc->core_id + i;
 | 
						|
    if (!spapr_set_vcpu_id(cpu, cs->cpu_index, errp)) {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    env->chip_index = sc->node_id;
 | 
						|
    env->core_index = cc->core_id;
 | 
						|
 | 
						|
    cpu->node_id = sc->node_id;
 | 
						|
 | 
						|
    id = g_strdup_printf("thread[%d]", i);
 | 
						|
    object_property_add_child(OBJECT(sc), id, obj);
 | 
						|
 | 
						|
    cpu->machine_data = g_new0(SpaprCpuState, 1);
 | 
						|
 | 
						|
    return cpu;
 | 
						|
}
 | 
						|
 | 
						|
static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
 | 
						|
{
 | 
						|
    /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
 | 
						|
     * tries to add a sPAPR CPU core to a non-pseries machine.
 | 
						|
     */
 | 
						|
    SpaprMachineState *spapr =
 | 
						|
        (SpaprMachineState *) object_dynamic_cast(qdev_get_machine(),
 | 
						|
                                                  TYPE_SPAPR_MACHINE);
 | 
						|
    SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
 | 
						|
    CPUCore *cc = CPU_CORE(OBJECT(dev));
 | 
						|
    int i;
 | 
						|
 | 
						|
    if (!spapr) {
 | 
						|
        error_setg(errp, TYPE_SPAPR_CPU_CORE " needs a pseries machine");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    qemu_register_reset(spapr_cpu_core_reset_handler, sc);
 | 
						|
    sc->threads = g_new0(PowerPCCPU *, cc->nr_threads);
 | 
						|
    for (i = 0; i < cc->nr_threads; i++) {
 | 
						|
        PowerPCCPU *cpu;
 | 
						|
 | 
						|
        cpu = spapr_create_vcpu(sc, i, errp);
 | 
						|
        sc->threads[i] = cpu;
 | 
						|
        if (cpu && cc->nr_threads > 1) {
 | 
						|
            cpu->env.has_smt_siblings = true;
 | 
						|
        }
 | 
						|
 | 
						|
        if (!cpu || !spapr_realize_vcpu(cpu, spapr, sc, i, errp)) {
 | 
						|
            spapr_cpu_core_unrealize(dev);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static const Property spapr_cpu_core_properties[] = {
 | 
						|
    DEFINE_PROP_INT32("node-id", SpaprCpuCore, node_id, CPU_UNSET_NUMA_NODE_ID),
 | 
						|
};
 | 
						|
 | 
						|
static void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
 | 
						|
{
 | 
						|
    DeviceClass *dc = DEVICE_CLASS(oc);
 | 
						|
    SpaprCpuCoreClass *scc = SPAPR_CPU_CORE_CLASS(oc);
 | 
						|
 | 
						|
    dc->realize = spapr_cpu_core_realize;
 | 
						|
    dc->unrealize = spapr_cpu_core_unrealize;
 | 
						|
    device_class_set_legacy_reset(dc, spapr_cpu_core_reset);
 | 
						|
    device_class_set_props(dc, spapr_cpu_core_properties);
 | 
						|
    scc->cpu_type = data;
 | 
						|
}
 | 
						|
 | 
						|
#define DEFINE_SPAPR_CPU_CORE_TYPE(cpu_model) \
 | 
						|
    {                                                   \
 | 
						|
        .parent = TYPE_SPAPR_CPU_CORE,                  \
 | 
						|
        .class_data = (void *) POWERPC_CPU_TYPE_NAME(cpu_model), \
 | 
						|
        .class_init = spapr_cpu_core_class_init,        \
 | 
						|
        .name = SPAPR_CPU_CORE_TYPE_NAME(cpu_model),    \
 | 
						|
    }
 | 
						|
 | 
						|
static const TypeInfo spapr_cpu_core_type_infos[] = {
 | 
						|
    {
 | 
						|
        .name = TYPE_SPAPR_CPU_CORE,
 | 
						|
        .parent = TYPE_CPU_CORE,
 | 
						|
        .abstract = true,
 | 
						|
        .instance_size = sizeof(SpaprCpuCore),
 | 
						|
        .class_size = sizeof(SpaprCpuCoreClass),
 | 
						|
    },
 | 
						|
    DEFINE_SPAPR_CPU_CORE_TYPE("970_v2.2"),
 | 
						|
    DEFINE_SPAPR_CPU_CORE_TYPE("970mp_v1.0"),
 | 
						|
    DEFINE_SPAPR_CPU_CORE_TYPE("970mp_v1.1"),
 | 
						|
    DEFINE_SPAPR_CPU_CORE_TYPE("power5p_v2.1"),
 | 
						|
    DEFINE_SPAPR_CPU_CORE_TYPE("power7_v2.3"),
 | 
						|
    DEFINE_SPAPR_CPU_CORE_TYPE("power7p_v2.1"),
 | 
						|
    DEFINE_SPAPR_CPU_CORE_TYPE("power8_v2.0"),
 | 
						|
    DEFINE_SPAPR_CPU_CORE_TYPE("power8e_v2.1"),
 | 
						|
    DEFINE_SPAPR_CPU_CORE_TYPE("power8nvl_v1.0"),
 | 
						|
    DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"),
 | 
						|
    DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.2"),
 | 
						|
    DEFINE_SPAPR_CPU_CORE_TYPE("power10_v2.0"),
 | 
						|
    DEFINE_SPAPR_CPU_CORE_TYPE("power11_v2.0"),
 | 
						|
#ifdef CONFIG_KVM
 | 
						|
    DEFINE_SPAPR_CPU_CORE_TYPE("host"),
 | 
						|
#endif
 | 
						|
};
 | 
						|
 | 
						|
DEFINE_TYPES(spapr_cpu_core_type_infos)
 |