This enabled KVM and migration support for a number of POWER8 registers: * Program Prioirty Register (PPR) * Sampled Instruction Address Register (SIAR) * Sampled Data Address Register (SDAR) * Vector Registers Save Register (VRSAVE)
This enables save/restore of transactional state if MSR_TS is set in the MSR. This adds new POWER8 registers support required for migration. Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru> --- target-ppc/cpu.h | 18 ++++++++++++++++++ target-ppc/kvm.c | 38 ++++++++++++++++++++++++++++++++++++++ target-ppc/machine.c | 34 ++++++++++++++++++++++++++++++++++ target-ppc/translate_init.c | 24 ++++++++++++++++-------- 4 files changed, 106 insertions(+), 8 deletions(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 2719c08..2b476b4 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -426,6 +426,8 @@ struct ppc_slb_t { #define MSR_TAG 62 /* Tag-active mode (POWERx ?) */ #define MSR_ISF 61 /* Sixty-four-bit interrupt mode on 630 */ #define MSR_SHV 60 /* hypervisor state hflags */ +#define MSR_TS 33 /* Transactional state, 2 bits (Book3s) */ +#define MSR_TM 32 /* Transactional Memory Available (Book3s) */ #define MSR_CM 31 /* Computation mode for BookE hflags */ #define MSR_ICM 30 /* Interrupt computation mode for BookE */ #define MSR_THV 29 /* hypervisor state for 32 bits PowerPC hflags */ @@ -1081,6 +1083,20 @@ struct CPUPPCState { */ uint8_t fit_period[4]; uint8_t wdt_period[4]; + + /* Transactional memory state migration */ + target_ulong tm_gpr[32]; + ppc_avr_t tm_vsr[64]; + uint64_t tm_cr; + uint64_t tm_lr; + uint64_t tm_ctr; + uint64_t tm_fpscr; + uint64_t tm_amr; + uint64_t tm_ppr; + uint64_t tm_vrsave; + uint32_t tm_vscr; + uint64_t tm_dscr; + uint64_t tm_tar; }; #define SET_FIT_PERIOD(a_, b_, c_, d_) \ @@ -1479,6 +1495,8 @@ static inline int cpu_mmu_index (CPUPPCState *env) #define SPR_MPC_MD_EPN (0x30B) #define SPR_PERFC (0x30C) #define SPR_MPC_MD_TWB (0x30C) +#define SPR_BOOK3S_SIAR (0x30C) +#define SPR_BOOK3S_SDAR (0x30D) #define SPR_PERFD (0x30D) #define SPR_MPC_MD_TWC (0x30D) #define SPR_PERFE (0x30E) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 9974b10..ead69fa 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -866,6 +866,25 @@ int kvm_arch_put_registers(CPUState *cs, int level) } #ifdef TARGET_PPC64 + if ((cpu->env.msr >> MSR_TS) & 3) { + for (i = 0; i < sizeof(env->tm_gpr)/sizeof(env->tm_gpr[0]); i++) { + kvm_set_one_reg(cs, KVM_REG_PPC_TM_GPR(i), &env->tm_gpr[i]); + } + for (i = 0; i < sizeof(env->tm_vsr)/sizeof(env->tm_vsr[0]); i++) { + kvm_set_one_reg(cs, KVM_REG_PPC_TM_VSR(i), &env->tm_vsr[i]); + } + kvm_set_one_reg(cs, KVM_REG_PPC_TM_CR, &env->tm_cr); + kvm_set_one_reg(cs, KVM_REG_PPC_TM_LR, &env->tm_lr); + kvm_set_one_reg(cs, KVM_REG_PPC_TM_CTR, &env->tm_ctr); + kvm_set_one_reg(cs, KVM_REG_PPC_TM_FPSCR, &env->tm_fpscr); + kvm_set_one_reg(cs, KVM_REG_PPC_TM_AMR, &env->tm_amr); + kvm_set_one_reg(cs, KVM_REG_PPC_TM_PPR, &env->tm_ppr); + kvm_set_one_reg(cs, KVM_REG_PPC_TM_VRSAVE, &env->tm_vrsave); + kvm_set_one_reg(cs, KVM_REG_PPC_TM_VSCR, &env->tm_vscr); + kvm_set_one_reg(cs, KVM_REG_PPC_TM_DSCR, &env->tm_dscr); + kvm_set_one_reg(cs, KVM_REG_PPC_TM_TAR, &env->tm_tar); + } + if (cap_papr) { if (kvm_put_vpa(cs) < 0) { DPRINTF("Warning: Unable to set VPA information to KVM\n"); @@ -1090,6 +1109,25 @@ int kvm_arch_get_registers(CPUState *cs) } #ifdef TARGET_PPC64 + if ((cpu->env.msr >> MSR_TS) & 3) { + for (i = 0; i < sizeof(env->tm_gpr)/sizeof(env->tm_gpr[0]); i++) { + kvm_get_one_reg(cs, KVM_REG_PPC_TM_GPR(i), &env->tm_gpr[i]); + } + for (i = 0; i < sizeof(env->tm_vsr)/sizeof(env->tm_vsr[0]); i++) { + kvm_get_one_reg(cs, KVM_REG_PPC_TM_VSR(i), &env->tm_vsr[i]); + } + kvm_get_one_reg(cs, KVM_REG_PPC_TM_CR, &env->tm_cr); + kvm_get_one_reg(cs, KVM_REG_PPC_TM_LR, &env->tm_lr); + kvm_get_one_reg(cs, KVM_REG_PPC_TM_CTR, &env->tm_ctr); + kvm_get_one_reg(cs, KVM_REG_PPC_TM_FPSCR, &env->tm_fpscr); + kvm_get_one_reg(cs, KVM_REG_PPC_TM_AMR, &env->tm_amr); + kvm_get_one_reg(cs, KVM_REG_PPC_TM_PPR, &env->tm_ppr); + kvm_get_one_reg(cs, KVM_REG_PPC_TM_VRSAVE, &env->tm_vrsave); + kvm_get_one_reg(cs, KVM_REG_PPC_TM_VSCR, &env->tm_vscr); + kvm_get_one_reg(cs, KVM_REG_PPC_TM_DSCR, &env->tm_dscr); + kvm_get_one_reg(cs, KVM_REG_PPC_TM_TAR, &env->tm_tar); + } + if (cap_papr) { if (kvm_get_vpa(cs) < 0) { DPRINTF("Warning: Unable to get VPA information from KVM\n"); diff --git a/target-ppc/machine.c b/target-ppc/machine.c index 063b379..691071d 100644 --- a/target-ppc/machine.c +++ b/target-ppc/machine.c @@ -247,6 +247,37 @@ static const VMStateDescription vmstate_vsx = { }, }; +#ifdef TARGET_PPC64 +/* Transactional memory state */ +static bool tm_needed(void *opaque) +{ + PowerPCCPU *cpu = opaque; + return (cpu->env.msr >> MSR_TS) & 3; +} + +static const VMStateDescription vmstate_tm = { + .name = "cpu/tm", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_UINTTL_ARRAY(env.tm_gpr, PowerPCCPU, 32), + VMSTATE_AVR_ARRAY(env.tm_vsr, PowerPCCPU, 64), + VMSTATE_UINT64(env.tm_cr, PowerPCCPU), + VMSTATE_UINT64(env.tm_lr, PowerPCCPU), + VMSTATE_UINT64(env.tm_ctr, PowerPCCPU), + VMSTATE_UINT64(env.tm_fpscr, PowerPCCPU), + VMSTATE_UINT64(env.tm_amr, PowerPCCPU), + VMSTATE_UINT64(env.tm_ppr, PowerPCCPU), + VMSTATE_UINT64(env.tm_vrsave, PowerPCCPU), + VMSTATE_UINT32(env.tm_vscr, PowerPCCPU), + VMSTATE_UINT64(env.tm_dscr, PowerPCCPU), + VMSTATE_UINT64(env.tm_tar, PowerPCCPU), + VMSTATE_END_OF_LIST() + }, +}; +#endif + static bool sr_needed(void *opaque) { #ifdef TARGET_PPC64 @@ -518,6 +549,9 @@ const VMStateDescription vmstate_ppc_cpu = { .needed = sr_needed, } , { #ifdef TARGET_PPC64 + .vmsd = &vmstate_tm, + .needed = tm_needed, + } , { .vmsd = &vmstate_slb, .needed = slb_needed, } , { diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 1627bb0..4b20c29 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -7025,14 +7025,22 @@ static void init_proc_POWER7 (CPUPPCState *env) SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, SPR_NOACCESS, 0x80800000); - spr_register(env, SPR_VRSAVE, "SPR_VRSAVE", - &spr_read_generic, &spr_write_generic, - &spr_read_generic, &spr_write_generic, - 0x00000000); - spr_register(env, SPR_PPR, "PPR", - &spr_read_generic, &spr_write_generic, - &spr_read_generic, &spr_write_generic, - 0x00000000); + spr_register_kvm(env, SPR_VRSAVE, "VRSAVE", + &spr_read_generic, &spr_write_generic, + &spr_read_generic, &spr_write_generic, + KVM_REG_PPC_VRSAVE, 0x00000000); + spr_register_kvm(env, SPR_PPR, "PPR", + &spr_read_generic, &spr_write_generic, + &spr_read_generic, &spr_write_generic, + KVM_REG_PPC_PPR, 0x00000000); + spr_register_kvm(env, SPR_BOOK3S_SIAR, "SIAR", + &spr_read_generic, &spr_write_generic, + &spr_read_generic, &spr_write_generic, + KVM_REG_PPC_SIAR, 0x00000000); + spr_register_kvm(env, SPR_BOOK3S_SDAR, "SDAR", + &spr_read_generic, &spr_write_generic, + &spr_read_generic, &spr_write_generic, + KVM_REG_PPC_SDAR, 0x00000000); /* Logical partitionning */ spr_register_kvm(env, SPR_LPCR, "LPCR", SPR_NOACCESS, SPR_NOACCESS, -- 1.8.4.rc4