* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "disas/bfd.h"
+#include "disas/dis-asm.h"
#include "exec/gdbstub.h"
#include "kvm_ppc.h"
#include "sysemu/arch_init.h"
#include "sysemu/cpus.h"
#include "sysemu/hw_accel.h"
+#include "sysemu/tcg.h"
#include "cpu-models.h"
#include "mmu-hash32.h"
#include "mmu-hash64.h"
#include "qemu/error-report.h"
+#include "qemu/module.h"
+#include "qemu/qemu-print.h"
#include "qapi/error.h"
#include "qapi/qmp/qnull.h"
#include "qapi/visitor.h"
#include "qemu/cutils.h"
#include "disas/capstone.h"
#include "fpu/softfloat.h"
-#include "qapi/qapi-commands-target.h"
+#include "qapi/qapi-commands-machine-target.h"
-//#define PPC_DUMP_CPU
-//#define PPC_DEBUG_SPR
-//#define PPC_DUMP_SPR_ACCESSES
+/* #define PPC_DUMP_CPU */
+/* #define PPC_DEBUG_SPR */
+/* #define PPC_DUMP_SPR_ACCESSES */
/* #define USE_APPLE_GDB */
-/* Generic callbacks:
+/*
+ * Generic callbacks:
* do nothing but store/retrieve spr value
*/
static void spr_load_dump_spr(int sprn)
#endif
}
-static void spr_read_generic (DisasContext *ctx, int gprn, int sprn)
+static void spr_read_generic(DisasContext *ctx, int gprn, int sprn)
{
gen_load_spr(cpu_gpr[gprn], sprn);
spr_load_dump_spr(sprn);
}
gen_helper_load_decr(cpu_gpr[gprn], cpu_env);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
- gen_io_end();
gen_stop_exception(ctx);
}
}
}
gen_helper_store_decr(cpu_env, cpu_gpr[gprn]);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
- gen_io_end();
gen_stop_exception(ctx);
}
}
}
}
-__attribute__ (( unused ))
+ATTRIBUTE_UNUSED
static void spr_read_atbl(DisasContext *ctx, int gprn, int sprn)
{
gen_helper_load_atbl(cpu_gpr[gprn], cpu_env);
}
-__attribute__ (( unused ))
+ATTRIBUTE_UNUSED
static void spr_read_atbu(DisasContext *ctx, int gprn, int sprn)
{
gen_helper_load_atbu(cpu_gpr[gprn], cpu_env);
}
}
-__attribute__ (( unused ))
+ATTRIBUTE_UNUSED
static void spr_write_atbl(DisasContext *ctx, int sprn, int gprn)
{
gen_helper_store_atbl(cpu_env, cpu_gpr[gprn]);
}
-__attribute__ (( unused ))
+ATTRIBUTE_UNUSED
static void spr_write_atbu(DisasContext *ctx, int sprn, int gprn)
{
gen_helper_store_atbu(cpu_env, cpu_gpr[gprn]);
}
#if defined(TARGET_PPC64)
-__attribute__ (( unused ))
+ATTRIBUTE_UNUSED
static void spr_read_purr(DisasContext *ctx, int gprn, int sprn)
{
gen_helper_load_purr(cpu_gpr[gprn], cpu_env);
/* IBAT0L...IBAT7L */
static void spr_read_ibat(DisasContext *ctx, int gprn, int sprn)
{
- tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
+ tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
+ offsetof(CPUPPCState,
+ IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
}
static void spr_read_ibat_h(DisasContext *ctx, int gprn, int sprn)
{
- tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][((sprn - SPR_IBAT4U) / 2) + 4]));
+ tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
+ offsetof(CPUPPCState,
+ IBAT[sprn & 1][((sprn - SPR_IBAT4U) / 2) + 4]));
}
static void spr_write_ibatu(DisasContext *ctx, int sprn, int gprn)
/* DBAT0L...DBAT7L */
static void spr_read_dbat(DisasContext *ctx, int gprn, int sprn)
{
- tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, DBAT[sprn & 1][(sprn - SPR_DBAT0U) / 2]));
+ tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
+ offsetof(CPUPPCState,
+ DBAT[sprn & 1][(sprn - SPR_DBAT0U) / 2]));
}
static void spr_read_dbat_h(DisasContext *ctx, int gprn, int sprn)
{
- tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, DBAT[sprn & 1][((sprn - SPR_DBAT4U) / 2) + 4]));
+ tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
+ offsetof(CPUPPCState,
+ DBAT[sprn & 1][((sprn - SPR_DBAT4U) / 2) + 4]));
}
static void spr_write_dbatu(DisasContext *ctx, int sprn, int gprn)
#if !defined(CONFIG_USER_ONLY)
static void spr_read_601_ubat(DisasContext *ctx, int gprn, int sprn)
{
- tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
+ tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
+ offsetof(CPUPPCState,
+ IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
}
static void spr_write_601_ubatu(DisasContext *ctx, int sprn, int gprn)
#if !defined(CONFIG_USER_ONLY)
static void spr_read_403_pbr(DisasContext *ctx, int gprn, int sprn)
{
- tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, pb[sprn - SPR_403_PBL1]));
+ tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
+ offsetof(CPUPPCState, pb[sprn - SPR_403_PBL1]));
}
static void spr_write_403_pbr(DisasContext *ctx, int sprn, int gprn)
static inline void _spr_register(CPUPPCState *env, int num,
const char *name,
- void (*uea_read)(DisasContext *ctx, int gprn, int sprn),
- void (*uea_write)(DisasContext *ctx, int sprn, int gprn),
+ void (*uea_read)(DisasContext *ctx,
+ int gprn, int sprn),
+ void (*uea_write)(DisasContext *ctx,
+ int sprn, int gprn),
#if !defined(CONFIG_USER_ONLY)
- void (*oea_read)(DisasContext *ctx, int gprn, int sprn),
- void (*oea_write)(DisasContext *ctx, int sprn, int gprn),
- void (*hea_read)(DisasContext *opaque, int gprn, int sprn),
- void (*hea_write)(DisasContext *opaque, int sprn, int gprn),
+ void (*oea_read)(DisasContext *ctx,
+ int gprn, int sprn),
+ void (*oea_write)(DisasContext *ctx,
+ int sprn, int gprn),
+ void (*hea_read)(DisasContext *opaque,
+ int gprn, int sprn),
+ void (*hea_write)(DisasContext *opaque,
+ int sprn, int gprn),
#endif
#if defined(CONFIG_KVM)
uint64_t one_reg_id,
ppc_spr_t *spr;
spr = &env->spr_cb[num];
- if (spr->name != NULL ||env-> spr[num] != 0x00000000 ||
+ if (spr->name != NULL || env->spr[num] != 0x00000000 ||
#if !defined(CONFIG_USER_ONLY)
spr->oea_read != NULL || spr->oea_write != NULL ||
#endif
{
#ifndef CONFIG_USER_ONLY
if (env->has_hv_mode) {
- /* SDR1 is a hypervisor resource on CPUs which have a
- * hypervisor mode */
+ /*
+ * SDR1 is a hypervisor resource on CPUs which have a
+ * hypervisor mode
+ */
spr_register_hv(env, SPR_SDR1, "SDR1",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
TCGv t1 = tcg_temp_new();
TCGv t2 = tcg_temp_new();
- /* Note, the HV=1 PR=0 case is handled earlier by simply using
+ /*
+ * Note, the HV=1 PR=0 case is handled earlier by simply using
* spr_write_generic for HV mode in the SPR table
*/
TCGv t1 = tcg_temp_new();
TCGv t2 = tcg_temp_new();
- /* Note, the HV=1 case is handled earlier by simply using
+ /*
+ * Note, the HV=1 case is handled earlier by simply using
* spr_write_generic for HV mode in the SPR table
*/
TCGv t1 = tcg_temp_new();
TCGv t2 = tcg_temp_new();
- /* Note, the HV=1 case is handled earlier by simply using
+ /*
+ * Note, the HV=1 case is handled earlier by simply using
* spr_write_generic for HV mode in the SPR table
*/
static void gen_spr_amr(CPUPPCState *env)
{
#ifndef CONFIG_USER_ONLY
- /* Virtual Page Class Key protection */
- /* The AMR is accessible either via SPR 13 or SPR 29. 13 is
+ /*
+ * Virtual Page Class Key protection
+ *
+ * The AMR is accessible either via SPR 13 or SPR 29. 13 is
* userspace accessible, 29 is privileged. So we only need to set
- * the kvm ONE_REG id on one of them, we use 29 */
+ * the kvm ONE_REG id on one of them, we use 29
+ */
spr_register(env, SPR_UAMR, "UAMR",
&spr_read_generic, &spr_write_amr,
&spr_read_generic, &spr_write_amr,
/* TLB assist registers */
/* XXX : not implemented */
for (i = 0; i < 8; i++) {
- void (*uea_write)(DisasContext *ctx, int sprn, int gprn) = &spr_write_generic32;
+ void (*uea_write)(DisasContext *ctx, int sprn, int gprn) =
+ &spr_write_generic32;
if (i == 2 && (mas_mask & (1 << i)) && (env->insns_flags & PPC_64B)) {
uea_write = &spr_write_generic;
}
0x00000000);
}
-// XXX: TODO
/*
* AMR => SPR 29 (Power 2.04)
* CTRL => SPR 136 (Power 2.04)
static int check_pow_hid0(CPUPPCState *env)
{
- if (env->spr[SPR_HID0] & 0x00E00000)
+ if (env->spr[SPR_HID0] & 0x00E00000) {
return 1;
+ }
return 0;
}
static int check_pow_hid0_74xx(CPUPPCState *env)
{
- if (env->spr[SPR_HID0] & 0x00600000)
+ if (env->spr[SPR_HID0] & 0x00600000) {
return 1;
+ }
return 0;
}
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc40x_irq_init(ppc_env_get_cpu(env));
+ ppc40x_irq_init(env_archcpu(env));
SET_FIT_PERIOD(12, 16, 20, 24);
SET_WDT_PERIOD(16, 20, 24, 28);
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc40x_irq_init(ppc_env_get_cpu(env));
+ ppc40x_irq_init(env_archcpu(env));
SET_FIT_PERIOD(12, 16, 20, 24);
SET_WDT_PERIOD(16, 20, 24, 28);
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc40x_irq_init(ppc_env_get_cpu(env));
+ ppc40x_irq_init(env_archcpu(env));
SET_FIT_PERIOD(12, 16, 20, 24);
SET_WDT_PERIOD(16, 20, 24, 28);
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc40x_irq_init(ppc_env_get_cpu(env));
+ ppc40x_irq_init(env_archcpu(env));
SET_FIT_PERIOD(8, 12, 16, 20);
SET_WDT_PERIOD(16, 20, 24, 28);
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc40x_irq_init(ppc_env_get_cpu(env));
+ ppc40x_irq_init(env_archcpu(env));
SET_FIT_PERIOD(8, 12, 16, 20);
SET_WDT_PERIOD(16, 20, 24, 28);
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc40x_irq_init(ppc_env_get_cpu(env));
+ ppc40x_irq_init(env_archcpu(env));
SET_FIT_PERIOD(8, 12, 16, 20);
SET_WDT_PERIOD(16, 20, 24, 28);
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc40x_irq_init(ppc_env_get_cpu(env));
+ ppc40x_irq_init(env_archcpu(env));
SET_FIT_PERIOD(8, 12, 16, 20);
SET_WDT_PERIOD(16, 20, 24, 28);
init_excp_BookE(env);
env->dcache_line_size = 32;
env->icache_line_size = 32;
- ppc40x_irq_init(ppc_env_get_cpu(env));
+ ppc40x_irq_init(env_archcpu(env));
SET_FIT_PERIOD(12, 16, 20, 24);
SET_WDT_PERIOD(20, 24, 28, 32);
init_excp_BookE(env);
env->dcache_line_size = 32;
env->icache_line_size = 32;
- ppc40x_irq_init(ppc_env_get_cpu(env));
+ ppc40x_irq_init(env_archcpu(env));
SET_FIT_PERIOD(12, 16, 20, 24);
SET_WDT_PERIOD(20, 24, 28, 32);
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(G2)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(G2LE)(ObjectClass *oc, void *data)
dc->desc = "e200 core";
pcc->init_proc = init_proc_e200;
pcc->check_pow = check_pow_hid0;
- /* XXX: unimplemented instructions:
+ /*
+ * XXX: unimplemented instructions:
* dcblc
* dcbtlst
* dcbtstls
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(e300)(ObjectClass *oc, void *data)
static void init_proc_e500(CPUPPCState *env, int version)
{
- PowerPCCPU *cpu = ppc_env_get_cpu(env);
uint32_t tlbncfg[2];
uint64_t ivor_mask;
uint64_t ivpr_mask = 0xFFFF0000ULL;
* gen_spr_BookE(env, 0x0000000F0000FD7FULL);
*/
switch (version) {
- case fsl_e500v1:
- case fsl_e500v2:
- default:
- ivor_mask = 0x0000000F0000FFFFULL;
- break;
- case fsl_e500mc:
- case fsl_e5500:
- ivor_mask = 0x000003FE0000FFFFULL;
- break;
- case fsl_e6500:
- ivor_mask = 0x000003FF0000FFFFULL;
- break;
+ case fsl_e500v1:
+ case fsl_e500v2:
+ default:
+ ivor_mask = 0x0000000F0000FFFFULL;
+ break;
+ case fsl_e500mc:
+ case fsl_e5500:
+ ivor_mask = 0x000003FE0000FFFFULL;
+ break;
+ case fsl_e6500:
+ ivor_mask = 0x000003FF0000FFFFULL;
+ break;
}
gen_spr_BookE(env, ivor_mask);
gen_spr_usprg3(env);
tlbncfg[1] = 0x40028040;
break;
default:
- cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]);
+ cpu_abort(env_cpu(env), "Unknown CPU: " TARGET_FMT_lx "\n",
+ env->spr[SPR_PVR]);
}
#endif
/* Cache sizes */
l1cfg1 |= 0x0B83820;
break;
default:
- cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]);
+ cpu_abort(env_cpu(env), "Unknown CPU: " TARGET_FMT_lx "\n",
+ env->spr[SPR_PVR]);
}
gen_spr_BookE206(env, 0x000000DF, tlbncfg, mmucfg);
/* XXX : not implemented */
init_excp_e200(env, ivpr_mask);
/* Allocate hardware IRQ controller */
- ppce500_irq_init(ppc_env_get_cpu(env));
+ ppce500_irq_init(env_archcpu(env));
}
static void init_proc_e500v1(CPUPPCState *env)
0x00000000);
/* Memory management */
init_excp_601(env);
- /* XXX: beware that dcache line size is 64
+ /*
+ * XXX: beware that dcache line size is 64
* but dcbz uses 32 bytes "sectors"
* XXX: this breaks clcs instruction !
*/
env->dcache_line_size = 32;
env->icache_line_size = 64;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(601)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(602)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(603)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(603E)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(604)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(604E)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(740)(ObjectClass *oc, void *data)
0x00000000);
/* Memory management */
gen_low_BATs(env);
- /* XXX: high BATs are also present but are known to be bugged on
+ /*
+ * XXX: high BATs are also present but are known to be bugged on
* die version 1.x
*/
init_excp_7x0(env);
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(750)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 750 CL";
pcc->init_proc = init_proc_750cl;
pcc->check_pow = check_pow_hid0;
- /* XXX: not implemented:
+ /*
+ * XXX: not implemented:
* cache lock instructions:
* dcbz_l
* floating point paired instructions
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(745)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(755)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(7400)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(7410)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(7440)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(7450)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(7445)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(7455)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(7457)(ObjectClass *oc, void *data)
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
- ppc6xx_irq_init(ppc_env_get_cpu(env));
+ ppc6xx_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(e600)(ObjectClass *oc, void *data)
&spr_read_generic, &spr_write_generic,
KVM_REG_PPC_VRSAVE, 0x00000000);
- /* Can't find information on what this should be on reset. This
- * value is the one used by 74xx processors. */
+ /*
+ * Can't find information on what this should be on reset. This
+ * value is the one used by 74xx processors.
+ */
vscr_init(env, 0x00010000);
}
KVM_REG_PPC_PSPB, 0);
}
+static void gen_spr_power8_dpdes(CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+ /* Directed Privileged Door-bell Exception State, used for IPI */
+ spr_register_kvm_hv(env, SPR_DPDES, "DPDES",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_DPDES, 0x00000000);
+#endif
+}
+
static void gen_spr_power8_ic(CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
/* Allocate hardware IRQ controller */
init_excp_970(env);
- ppc970_irq_init(ppc_env_get_cpu(env));
+ ppc970_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
/* Allocate hardware IRQ controller */
init_excp_970(env);
- ppc970_irq_init(ppc_env_get_cpu(env));
+ ppc970_irq_init(env_archcpu(env));
}
POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
pcc->hash64_opts = &ppc_hash64_opts_basic;
+ pcc->lrg_decr_bits = 32;
#endif
pcc->excp_model = POWERPC_EXCP_970;
pcc->bus_model = PPC_FLAGS_INPUT_970;
/* Allocate hardware IRQ controller */
init_excp_POWER7(env);
- ppcPOWER7_irq_init(ppc_env_get_cpu(env));
+ ppcPOWER7_irq_init(env_archcpu(env));
}
static bool ppc_pvr_match_power7(PowerPCCPUClass *pcc, uint32_t pvr)
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
pcc->hash64_opts = &ppc_hash64_opts_POWER7;
+ pcc->lrg_decr_bits = 32;
#endif
pcc->excp_model = POWERPC_EXCP_POWER7;
pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
gen_spr_power8_pmu_user(env);
gen_spr_power8_tm(env);
gen_spr_power8_pspb(env);
+ gen_spr_power8_dpdes(env);
gen_spr_vtb(env);
gen_spr_power8_ic(env);
gen_spr_power8_book4(env);
/* Allocate hardware IRQ controller */
init_excp_POWER8(env);
- ppcPOWER7_irq_init(ppc_env_get_cpu(env));
+ ppcPOWER7_irq_init(env_archcpu(env));
}
static bool ppc_pvr_match_power8(PowerPCCPUClass *pcc, uint32_t pvr)
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
pcc->hash64_opts = &ppc_hash64_opts_POWER7;
+ pcc->lrg_decr_bits = 32;
+ pcc->n_host_threads = 8;
#endif
pcc->excp_model = POWERPC_EXCP_POWER8;
pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
gen_spr_power8_pmu_user(env);
gen_spr_power8_tm(env);
gen_spr_power8_pspb(env);
+ gen_spr_power8_dpdes(env);
gen_spr_vtb(env);
gen_spr_power8_ic(env);
gen_spr_power8_book4(env);
/* Allocate hardware IRQ controller */
init_excp_POWER9(env);
- ppcPOWER9_irq_init(ppc_env_get_cpu(env));
+ ppcPOWER9_irq_init(env_archcpu(env));
}
static bool ppc_pvr_match_power9(PowerPCCPUClass *pcc, uint32_t pvr)
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBSYNC |
- PPC_64B | PPC_64BX | PPC_ALTIVEC |
+ PPC_64B | PPC_64H | PPC_64BX | PPC_ALTIVEC |
PPC_SEGMENT_64B | PPC_SLBI |
PPC_POPCNTB | PPC_POPCNTWD |
PPC_CILDST;
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL;
pcc->msr_mask = (1ull << MSR_SF) |
+ (1ull << MSR_SHV) |
(1ull << MSR_TM) |
(1ull << MSR_VR) |
(1ull << MSR_VSX) |
/* segment page size remain the same */
pcc->hash64_opts = &ppc_hash64_opts_POWER7;
pcc->radix_page_info = &POWER9_radix_page_info;
+ pcc->lrg_decr_bits = 56;
+ pcc->n_host_threads = 4;
#endif
pcc->excp_model = POWERPC_EXCP_POWER9;
pcc->bus_model = PPC_FLAGS_INPUT_POWER9;
env->irq_inputs = NULL;
/* Set all exception vectors to an invalid address */
- for (i = 0; i < POWERPC_EXCP_NB; i++)
+ for (i = 0; i < POWERPC_EXCP_NB; i++) {
env->excp_vectors[i] = (target_ulong)(-1ULL);
+ }
env->ivor_mask = 0x00000000;
env->ivpr_mask = 0x00000000;
/* Default MMU definitions */
#if !defined(CONFIG_USER_ONLY)
if (env->nb_tlb != 0) {
int nb_tlb = env->nb_tlb;
- if (env->id_tlbs != 0)
+ if (env->id_tlbs != 0) {
nb_tlb *= 2;
+ }
switch (env->tlb_type) {
case TLB_6XX:
env->tlb.tlb6 = g_new0(ppc6xx_tlb_t, nb_tlb);
{
int i;
- for (i = 0; i < len; i++)
+ for (i = 0; i < len; i++) {
table[i] = &invalid_handler;
+ }
}
static int create_new_table(opc_handler_t **table, unsigned char idx)
static int insert_in_table(opc_handler_t **table, unsigned char idx,
opc_handler_t *handler)
{
- if (table[idx] != &invalid_handler)
+ if (table[idx] != &invalid_handler) {
return -1;
+ }
table[idx] = handler;
return 0;
}
} else {
if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2,
- insn->opc3, &insn->handler) < 0)
+ insn->opc3, &insn->handler) < 0) {
return -1;
+ }
}
} else {
if (register_ind_insn(ppc_opcodes, insn->opc1,
- insn->opc2, &insn->handler) < 0)
+ insn->opc2, &insn->handler) < 0) {
return -1;
+ }
}
} else {
- if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0)
+ if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0) {
return -1;
+ }
}
return 0;
for (i = 0, count = 0; i < len; i++) {
/* Consistency fixup */
- if (table[i] == NULL)
+ if (table[i] == NULL) {
table[i] = &invalid_handler;
+ }
if (table[i] != &invalid_handler) {
if (is_indirect_opcode(table[i])) {
tmp = test_opcode_table(ind_table(table[i]),
static void fix_opcode_tables(opc_handler_t **ppc_opcodes)
{
- if (test_opcode_table(ppc_opcodes, PPC_CPU_OPCODES_LEN) == 0)
+ if (test_opcode_table(ppc_opcodes, PPC_CPU_OPCODES_LEN) == 0) {
printf("*** WARNING: no opcode defined !\n");
+ }
}
/*****************************************************************************/
static void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp)
{
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
- CPUPPCState *env = &cpu->env;
opcode_t *opc;
- fill_new_table(env->opcodes, PPC_CPU_OPCODES_LEN);
+ fill_new_table(cpu->opcodes, PPC_CPU_OPCODES_LEN);
for (opc = opcodes; opc < &opcodes[ARRAY_SIZE(opcodes)]; opc++) {
if (((opc->handler.type & pcc->insns_flags) != 0) ||
((opc->handler.type2 & pcc->insns_flags2) != 0)) {
- if (register_insn(env->opcodes, opc) < 0) {
+ if (register_insn(cpu->opcodes, opc) < 0) {
error_setg(errp, "ERROR initializing PowerPC instruction "
"0x%02x 0x%02x 0x%02x", opc->opc1, opc->opc2,
opc->opc3);
}
}
}
- fix_opcode_tables(env->opcodes);
+ fix_opcode_tables(cpu->opcodes);
fflush(stdout);
fflush(stderr);
}
{
CPUPPCState *env = &cpu->env;
- /* TCG doesn't (yet) emulate some groups of instructions that
- * are implemented on some otherwise supported CPUs (e.g. VSX
- * and decimal floating point instructions on POWER7). We
- * remove unsupported instruction groups from the cpu state's
- * instruction masks and hope the guest can cope. For at
- * least the pseries machine, the unavailability of these
- * instructions can be advertised to the guest via the device
- * tree. */
+ /*
+ * TCG doesn't (yet) emulate some groups of instructions that are
+ * implemented on some otherwise supported CPUs (e.g. VSX and
+ * decimal floating point instructions on POWER7). We remove
+ * unsupported instruction groups from the cpu state's instruction
+ * masks and hope the guest can cope. For at least the pseries
+ * machine, the unavailability of these instructions can be
+ * advertised to the guest via the device tree.
+ */
if ((env->insns_flags & ~PPC_TCG_INSNS)
|| (env->insns_flags2 & ~PPC_TCG_INSNS2)) {
warn_report("Disabling some instructions which are not "
" Bus model : %s\n",
excp_model, bus_model);
printf(" MSR features :\n");
- if (env->flags & POWERPC_FLAG_SPE)
+ if (env->flags & POWERPC_FLAG_SPE) {
printf(" signal processing engine enable"
"\n");
- else if (env->flags & POWERPC_FLAG_VRE)
+ } else if (env->flags & POWERPC_FLAG_VRE) {
printf(" vector processor enable\n");
- if (env->flags & POWERPC_FLAG_TGPR)
+ }
+ if (env->flags & POWERPC_FLAG_TGPR) {
printf(" temporary GPRs\n");
- else if (env->flags & POWERPC_FLAG_CE)
+ } else if (env->flags & POWERPC_FLAG_CE) {
printf(" critical input enable\n");
- if (env->flags & POWERPC_FLAG_SE)
+ }
+ if (env->flags & POWERPC_FLAG_SE) {
printf(" single-step trace mode\n");
- else if (env->flags & POWERPC_FLAG_DWE)
+ } else if (env->flags & POWERPC_FLAG_DWE) {
printf(" debug wait enable\n");
- else if (env->flags & POWERPC_FLAG_UBLE)
+ } else if (env->flags & POWERPC_FLAG_UBLE) {
printf(" user BTB lock enable\n");
- if (env->flags & POWERPC_FLAG_BE)
+ }
+ if (env->flags & POWERPC_FLAG_BE) {
printf(" branch-step trace mode\n");
- else if (env->flags & POWERPC_FLAG_DE)
+ } else if (env->flags & POWERPC_FLAG_DE) {
printf(" debug interrupt enable\n");
- if (env->flags & POWERPC_FLAG_PX)
+ }
+ if (env->flags & POWERPC_FLAG_PX) {
printf(" inclusive protection\n");
- else if (env->flags & POWERPC_FLAG_PMM)
+ } else if (env->flags & POWERPC_FLAG_PMM) {
printf(" performance monitor mark\n");
- if (env->flags == POWERPC_FLAG_NONE)
+ }
+ if (env->flags == POWERPC_FLAG_NONE) {
printf(" none\n");
+ }
printf(" Time-base/decrementer clock source: %s\n",
env->flags & POWERPC_FLAG_RTC_CLK ? "RTC clock" : "bus clock");
dump_ppc_insns(env);
{
PowerPCCPU *cpu = POWERPC_CPU(dev);
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
- CPUPPCState *env = &cpu->env;
Error *local_err = NULL;
opc_handler_t **table, **table_2;
int i, j, k;
}
for (i = 0; i < PPC_CPU_OPCODES_LEN; i++) {
- if (env->opcodes[i] == &invalid_handler) {
+ if (cpu->opcodes[i] == &invalid_handler) {
continue;
}
- if (is_indirect_opcode(env->opcodes[i])) {
- table = ind_table(env->opcodes[i]);
+ if (is_indirect_opcode(cpu->opcodes[i])) {
+ table = ind_table(cpu->opcodes[i]);
for (j = 0; j < PPC_CPU_INDIRECT_OPCODES_LEN; j++) {
if (table[j] == &invalid_handler) {
continue;
~PPC_INDIRECT));
}
}
- g_free((opc_handler_t *)((uintptr_t)env->opcodes[i] &
+ g_free((opc_handler_t *)((uintptr_t)cpu->opcodes[i] &
~PPC_INDIRECT));
}
}
const char *p;
unsigned long pvr;
- /* Lookup by PVR if cpu_model is valid 8 digit hex number
- * (excl: 0x prefix if present)
+ /*
+ * Lookup by PVR if cpu_model is valid 8 digit hex number (excl:
+ * 0x prefix if present)
*/
if (!qemu_strtoul(name, &p, 16, &pvr)) {
int len = p - name;
static void ppc_cpu_list_entry(gpointer data, gpointer user_data)
{
ObjectClass *oc = data;
- CPUListState *s = user_data;
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
DeviceClass *family = DEVICE_CLASS(ppc_cpu_get_family_class(pcc));
const char *typename = object_class_get_name(oc);
name = g_strndup(typename,
strlen(typename) - strlen(POWERPC_CPU_TYPE_SUFFIX));
- (*s->cpu_fprintf)(s->file, "PowerPC %-16s PVR %08x\n",
- name, pcc->pvr);
+ qemu_printf("PowerPC %-16s PVR %08x\n", name, pcc->pvr);
for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) {
PowerPCCPUAlias *alias = &ppc_cpu_aliases[i];
ObjectClass *alias_oc = ppc_cpu_class_by_name(alias->model);
* avoid printing the wrong alias here and use "preferred" instead
*/
if (strcmp(alias->alias, family->desc) == 0) {
- (*s->cpu_fprintf)(s->file,
- "PowerPC %-16s (alias for preferred %s CPU)\n",
- alias->alias, family->desc);
+ qemu_printf("PowerPC %-16s (alias for preferred %s CPU)\n",
+ alias->alias, family->desc);
} else {
- (*s->cpu_fprintf)(s->file, "PowerPC %-16s (alias for %s)\n",
- alias->alias, name);
+ qemu_printf("PowerPC %-16s (alias for %s)\n",
+ alias->alias, name);
}
}
g_free(name);
}
-void ppc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+void ppc_cpu_list(void)
{
- CPUListState s = {
- .file = f,
- .cpu_fprintf = cpu_fprintf,
- };
GSList *list;
list = object_class_get_list(TYPE_POWERPC_CPU, false);
list = g_slist_sort(list, ppc_cpu_list_compare);
- g_slist_foreach(list, ppc_cpu_list_entry, &s);
+ g_slist_foreach(list, ppc_cpu_list_entry, NULL);
g_slist_free(list);
#ifdef CONFIG_KVM
- cpu_fprintf(f, "\n");
- cpu_fprintf(f, "PowerPC %-16s\n", "host");
+ qemu_printf("\n");
+ qemu_printf("PowerPC %-16s\n", "host");
#endif
}
s->exception_index = POWERPC_EXCP_NONE;
env->error_code = 0;
+ /* tininess for underflow is detected before rounding */
+ set_float_detect_tininess(float_tininess_before_rounding,
+ &env->fp_status);
+
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
ppc_spr_t *spr = &env->spr_cb[i];
return !msr_le;
}
+
+static void ppc_cpu_exec_enter(CPUState *cs)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+
+ if (cpu->vhyp) {
+ PPCVirtualHypervisorClass *vhc =
+ PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+ vhc->cpu_exec_enter(cpu->vhyp, cpu);
+ }
+}
+
+static void ppc_cpu_exec_exit(CPUState *cs)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+
+ if (cpu->vhyp) {
+ PPCVirtualHypervisorClass *vhc =
+ PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+ vhc->cpu_exec_exit(cpu->vhyp, cpu);
+ }
+}
#endif
static void ppc_cpu_instance_init(Object *obj)
{
- CPUState *cs = CPU(obj);
PowerPCCPU *cpu = POWERPC_CPU(obj);
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
CPUPPCState *env = &cpu->env;
- cs->env_ptr = env;
+ cpu_set_cpustate_pointers(cpu);
cpu->vcpu_id = UNASSIGNED_CPU_INDEX;
env->msr_mask = pcc->msr_mask;
env->bfd_mach = pcc->bfd_mach;
env->check_pow = pcc->check_pow;
- /* Mark HV mode as supported if the CPU has an MSR_HV bit
- * in the msr_mask. The mask can later be cleared by PAPR
- * mode but the hv mode support will remain, thus enforcing
- * that we cannot use priv. instructions in guest in PAPR
- * mode. For 970 we currently simply don't set HV in msr_mask
- * thus simulating an "Apple mode" 970. If we ever want to
- * support 970 HV mode, we'll have to add a processor attribute
- * of some sort.
+ /*
+ * Mark HV mode as supported if the CPU has an MSR_HV bit in the
+ * msr_mask. The mask can later be cleared by PAPR mode but the hv
+ * mode support will remain, thus enforcing that we cannot use
+ * priv. instructions in guest in PAPR mode. For 970 we currently
+ * simply don't set HV in msr_mask thus simulating an "Apple mode"
+ * 970. If we ever want to support 970 HV mode, we'll have to add
+ * a processor attribute of some sort.
*/
#if !defined(CONFIG_USER_ONLY)
env->has_hv_mode = !!(env->msr_mask & MSR_HVB);
cc->gdb_read_register = ppc_cpu_gdb_read_register;
cc->gdb_write_register = ppc_cpu_gdb_write_register;
cc->do_unaligned_access = ppc_cpu_do_unaligned_access;
-#ifdef CONFIG_USER_ONLY
- cc->handle_mmu_fault = ppc_cpu_handle_mmu_fault;
-#else
+#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = ppc_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_ppc_cpu;
#endif
#endif
#ifdef CONFIG_TCG
cc->tcg_initialize = ppc_translate_init;
+ cc->tlb_fill = ppc_cpu_tlb_fill;
+#endif
+#ifndef CONFIG_USER_ONLY
+ cc->cpu_exec_enter = ppc_cpu_exec_enter;
+ cc->cpu_exec_exit = ppc_cpu_exec_exit;
#endif
+
cc->disas_set_info = ppc_disas_set_info;
-
+
dc->fw_name = "PowerPC,UNKNOWN";
}