Merge branch 'ppc-next' of git://repo.or.cz/qemu/agraf

* 'ppc-next' of git://repo.or.cz/qemu/agraf:
  PPC: Qdev'ify e500 pci
  PPC MPC7544DS: Use new TLB helper function
  PPC: Implement e500 (FSL) MMU
  PPC: Add another 64 bits to instruction feature mask
  PPC: Add GS MSR definition
  PPC: Make MPC8544DS emulation work w/o KVM
  PPC: Make MPC8544DS obey -cpu switch
  Fix off-by-one error in sizing pSeries hcall table
  ppc64: Fix out-of-tree builds
  kvm: ppc: warn user on PAGE_SIZE mismatch
  kvm: ppc: detect old headers
  monitor: add PPC BookE SPRs
  kvm: ppc: fixes for KVM_SET_SREGS on init
  ppc64: Don't try to build sPAPR RTAS on Darwin
  Place pseries vty devices at addresses more similar to existing machines
  Make pSeries 'model' property more closely resemble real hardware
  pseries: Increase maximum CPUs to 256
This commit is contained in:
Aurelien Jarno 2011-05-14 16:54:59 +02:00
commit 091959defe
18 changed files with 1666 additions and 278 deletions

22
configure vendored
View File

@ -1833,6 +1833,21 @@ recent kvm-kmod from http://sourceforge.net/projects/kvm."
fi
fi
##########################################
# test for ppc kvm pvr setting
if test "$kvm" = "yes" && test "$cpu" = "ppc" -o "$cpu" = "ppc64"; then
cat > $TMPC <<EOF
#include <asm/kvm.h>
int main(void) { struct kvm_sregs s; s.pvr = 0; return 0; }
EOF
if compile_prog "$kvm_cflags" "" ; then
kvm_ppc_pvr=yes
else
kvm_ppc_pvr=no
fi
fi
##########################################
# test for vhost net
@ -2602,7 +2617,7 @@ if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) -a \
"$softmmu" = yes ; then
roms="optionrom"
fi
if test "$cpu" = "ppc64" ; then
if test "$cpu" = "ppc64" -a "$targetos" != "Darwin" ; then
roms="$roms spapr-rtas"
fi
@ -3324,6 +3339,9 @@ case "$target_arch2" in
if test $vhost_net = "yes" ; then
echo "CONFIG_VHOST_NET=y" >> $config_target_mak
fi
if test $kvm_ppc_pvr = "yes" ; then
echo "CONFIG_KVM_PPC_PVR=y" >> $config_target_mak
fi
fi
esac
if test "$target_bigendian" = "yes" ; then
@ -3524,11 +3542,13 @@ done # for target in $targets
# build tree in object directory in case the source is not in the current directory
DIRS="tests tests/cris slirp audio block net pc-bios/optionrom"
DIRS="$DIRS pc-bios/spapr-rtas"
DIRS="$DIRS roms/seabios roms/vgabios"
DIRS="$DIRS fsdev ui"
FILES="Makefile tests/Makefile"
FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
FILES="$FILES pc-bios/spapr-rtas/Makefile"
FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.rom $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
FILES="$FILES pc-bios/`basename $bios_file`"

View File

@ -452,6 +452,10 @@ uint64_t cpu_ppc_load_tbl (CPUState *env)
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
if (kvm_enabled()) {
return env->spr[SPR_TBL];
}
tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
@ -471,6 +475,10 @@ static inline uint32_t _cpu_ppc_load_tbu(CPUState *env)
uint32_t cpu_ppc_load_tbu (CPUState *env)
{
if (kvm_enabled()) {
return env->spr[SPR_TBU];
}
return _cpu_ppc_load_tbu(env);
}
@ -616,6 +624,10 @@ uint32_t cpu_ppc_load_decr (CPUState *env)
{
ppc_tb_t *tb_env = env->tb_env;
if (kvm_enabled()) {
return env->spr[SPR_DECR];
}
return _cpu_ppc_load_decr(env, tb_env->decr_next);
}

View File

@ -1,22 +0,0 @@
/*
* QEMU PowerPC E500 emulation shared definitions
*
* Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
*
* Author: Yu Liu, <yu.liu@freescale.com>
*
* This file is derived from hw/ppc440.h
* the copyright for that material belongs to the original owners.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#if !defined(PPC_E500_H)
#define PPC_E500_H
PCIBus *ppce500_pci_init(qemu_irq *pic, target_phys_addr_t registers);
#endif /* !defined(PPC_E500_H) */

View File

@ -28,9 +28,10 @@
#include "kvm_ppc.h"
#include "device_tree.h"
#include "openpic.h"
#include "ppce500.h"
#include "ppc.h"
#include "loader.h"
#include "elf.h"
#include "sysbus.h"
#define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb"
#define UIMAGE_LOAD_BASE 0
@ -50,6 +51,12 @@
#define MPC8544_PCI_IO 0xE1000000
#define MPC8544_PCI_IOLEN 0x10000
struct boot_info
{
uint32_t dt_base;
uint32_t entry;
};
#ifdef CONFIG_FDT
static int mpc8544_copy_soc_cell(void *fdt, const char *node, const char *prop)
{
@ -82,7 +89,7 @@ static int mpc8544_load_device_tree(target_phys_addr_t addr,
{
int ret = -1;
#ifdef CONFIG_FDT
uint32_t mem_reg_property[] = {0, ramsize};
uint32_t mem_reg_property[] = {0, cpu_to_be32(ramsize)};
char *filename;
int fdt_size;
void *fdt;
@ -103,15 +110,19 @@ static int mpc8544_load_device_tree(target_phys_addr_t addr,
if (ret < 0)
fprintf(stderr, "couldn't set /memory/reg\n");
ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
initrd_base);
if (ret < 0)
fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
if (initrd_size) {
ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
initrd_base);
if (ret < 0) {
fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
}
ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
(initrd_base + initrd_size));
if (ret < 0)
fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
(initrd_base + initrd_size));
if (ret < 0) {
fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
}
}
ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
kernel_cmdline);
@ -145,6 +156,13 @@ static int mpc8544_load_device_tree(target_phys_addr_t addr,
mpc8544_copy_soc_cell(fdt, buf, "clock-frequency");
mpc8544_copy_soc_cell(fdt, buf, "timebase-frequency");
} else {
const uint32_t freq = 400000000;
qemu_devtree_setprop_cell(fdt, "/cpus/PowerPC,8544@0",
"clock-frequency", freq);
qemu_devtree_setprop_cell(fdt, "/cpus/PowerPC,8544@0",
"timebase-frequency", freq);
}
ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
@ -156,6 +174,35 @@ out:
return ret;
}
/* Create -kernel TLB entries for BookE, linearly spanning 256MB. */
static void mmubooke_create_initial_mapping(CPUState *env,
target_ulong va,
target_phys_addr_t pa)
{
ppcemb_tlb_t *tlb = booke206_get_tlbe(env, 1, 0, 0);
tlb->attr = 0;
tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
tlb->size = 256 * 1024 * 1024;
tlb->EPN = va & TARGET_PAGE_MASK;
tlb->RPN = pa & TARGET_PAGE_MASK;
tlb->PID = 0;
}
static void mpc8544ds_cpu_reset(void *opaque)
{
CPUState *env = opaque;
struct boot_info *bi = env->load_info;
cpu_reset(env);
/* Set initial guest state. */
env->gpr[1] = (16<<20) - 8;
env->gpr[3] = bi->dt_base;
env->nip = bi->entry;
mmubooke_create_initial_mapping(env, 0, 0);
}
static void mpc8544ds_init(ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename,
@ -175,15 +222,28 @@ static void mpc8544ds_init(ram_addr_t ram_size,
target_long initrd_size=0;
int i=0;
unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
qemu_irq *irqs, *mpic, *pci_irqs;
qemu_irq *irqs, *mpic;
DeviceState *dev;
struct boot_info *boot_info;
/* Setup CPU */
env = cpu_ppc_init("e500v2_v30");
if (cpu_model == NULL) {
cpu_model = "e500v2_v30";
}
env = cpu_ppc_init(cpu_model);
if (!env) {
fprintf(stderr, "Unable to initialize CPU!\n");
exit(1);
}
/* XXX register timer? */
ppc_emb_timers_init(env, 400000000, PPC_INTERRUPT_DECR);
ppc_dcr_init(env, NULL, NULL);
/* Register reset handler */
qemu_register_reset(mpc8544ds_cpu_reset, env);
/* Fixup Memory size on a alignment boundary */
ram_size &= ~(RAM_SIZES_ALIGN - 1);
@ -211,12 +271,11 @@ static void mpc8544ds_init(ram_addr_t ram_size,
}
/* PCI */
pci_irqs = qemu_malloc(sizeof(qemu_irq) * 4);
pci_irqs[0] = mpic[pci_irq_nrs[0]];
pci_irqs[1] = mpic[pci_irq_nrs[1]];
pci_irqs[2] = mpic[pci_irq_nrs[2]];
pci_irqs[3] = mpic[pci_irq_nrs[3]];
pci_bus = ppce500_pci_init(pci_irqs, MPC8544_PCI_REGS_BASE);
dev = sysbus_create_varargs("e500-pcihost", MPC8544_PCI_REGS_BASE,
mpic[pci_irq_nrs[0]], mpic[pci_irq_nrs[1]],
mpic[pci_irq_nrs[2]], mpic[pci_irq_nrs[3]],
NULL);
pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
if (!pci_bus)
printf("couldn't create PCI controller!\n");
@ -259,8 +318,13 @@ static void mpc8544ds_init(ram_addr_t ram_size,
}
}
boot_info = qemu_mallocz(sizeof(struct boot_info));
/* If we're loading a kernel directly, we must load the device tree too. */
if (kernel_filename) {
#ifndef CONFIG_FDT
cpu_abort(env, "Compiled without FDT support - can't load kernel\n");
#endif
dt_base = (kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
if (mpc8544_load_device_tree(dt_base, ram_size,
initrd_base, initrd_size, kernel_cmdline) < 0) {
@ -268,17 +332,14 @@ static void mpc8544ds_init(ram_addr_t ram_size,
exit(1);
}
/* Set initial guest state. */
env->gpr[1] = (16<<20) - 8;
env->gpr[3] = dt_base;
env->nip = entry;
/* XXX we currently depend on KVM to create some initial TLB entries. */
boot_info->entry = entry;
boot_info->dt_base = dt_base;
}
env->load_info = boot_info;
if (kvm_enabled())
if (kvm_enabled()) {
kvmppc_init();
return;
}
}
static QEMUMachine mpc8544ds_machine = {

View File

@ -15,7 +15,6 @@
*/
#include "hw.h"
#include "ppce500.h"
#include "pci.h"
#include "pci_host.h"
#include "bswap.h"
@ -29,7 +28,8 @@
#define PCIE500_CFGADDR 0x0
#define PCIE500_CFGDATA 0x4
#define PCIE500_REG_BASE 0xC00
#define PCIE500_REG_SIZE (0x1000 - PCIE500_REG_BASE)
#define PCIE500_ALL_SIZE 0x1000
#define PCIE500_REG_SIZE (PCIE500_ALL_SIZE - PCIE500_REG_BASE)
#define PPCE500_PCI_CONFIG_ADDR 0x0
#define PPCE500_PCI_CONFIG_DATA 0x4
@ -73,11 +73,15 @@ struct pci_inbound {
};
struct PPCE500PCIState {
PCIHostState pci_state;
struct pci_outbound pob[PPCE500_PCI_NR_POBS];
struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
uint32_t gasket_time;
PCIHostState pci_state;
PCIDevice *pci_dev;
qemu_irq irq[4];
/* mmio maps */
int cfgaddr;
int cfgdata;
int reg;
};
typedef struct PPCE500PCIState PPCE500PCIState;
@ -250,7 +254,6 @@ static const VMStateDescription vmstate_ppce500_pci = {
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE_POINTER(pci_dev, PPCE500PCIState),
VMSTATE_STRUCT_ARRAY(pob, PPCE500PCIState, PPCE500_PCI_NR_POBS, 1,
vmstate_pci_outbound, struct pci_outbound),
VMSTATE_STRUCT_ARRAY(pib, PPCE500PCIState, PPCE500_PCI_NR_PIBS, 1,
@ -260,60 +263,73 @@ static const VMStateDescription vmstate_ppce500_pci = {
}
};
PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
static void e500_pci_map(SysBusDevice *dev, target_phys_addr_t base)
{
PPCE500PCIState *controller;
PCIDevice *d;
int index;
static int ppce500_pci_id;
PCIHostState *h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
PPCE500PCIState *s = DO_UPCAST(PPCE500PCIState, pci_state, h);
controller = qemu_mallocz(sizeof(PPCE500PCIState));
controller->pci_state.bus = pci_register_bus(NULL, "pci",
mpc85xx_pci_set_irq,
mpc85xx_pci_map_irq,
pci_irqs, PCI_DEVFN(0x11, 0),
4);
d = pci_register_device(controller->pci_state.bus,
"host bridge", sizeof(PCIDevice),
0, NULL, NULL);
pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_FREESCALE);
pci_config_set_device_id(d->config, PCI_DEVICE_ID_MPC8533E);
pci_config_set_class(d->config, PCI_CLASS_PROCESSOR_POWERPC);
controller->pci_dev = d;
/* CFGADDR */
index = pci_host_conf_register_mmio(&controller->pci_state,
DEVICE_BIG_ENDIAN);
if (index < 0)
goto free;
cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index);
/* CFGDATA */
index = pci_host_data_register_mmio(&controller->pci_state,
DEVICE_BIG_ENDIAN);
if (index < 0)
goto free;
cpu_register_physical_memory(registers + PCIE500_CFGDATA, 4, index);
index = cpu_register_io_memory(e500_pci_reg_read,
e500_pci_reg_write, controller,
DEVICE_NATIVE_ENDIAN);
if (index < 0)
goto free;
cpu_register_physical_memory(registers + PCIE500_REG_BASE,
PCIE500_REG_SIZE, index);
/* XXX load/save code not tested. */
vmstate_register(&d->qdev, ppce500_pci_id++, &vmstate_ppce500_pci,
controller);
return controller->pci_state.bus;
free:
printf("%s error\n", __func__);
qemu_free(controller);
return NULL;
cpu_register_physical_memory(base + PCIE500_CFGADDR, 4, s->cfgaddr);
cpu_register_physical_memory(base + PCIE500_CFGDATA, 4, s->cfgdata);
cpu_register_physical_memory(base + PCIE500_REG_BASE, PCIE500_REG_SIZE,
s->reg);
}
static int e500_pcihost_initfn(SysBusDevice *dev)
{
PCIHostState *h;
PPCE500PCIState *s;
PCIBus *b;
int i;
h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
s = DO_UPCAST(PPCE500PCIState, pci_state, h);
for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
sysbus_init_irq(dev, &s->irq[i]);
}
b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq,
mpc85xx_pci_map_irq, s->irq, PCI_DEVFN(0x11, 0), 4);
s->pci_state.bus = b;
pci_create_simple(b, 0, "e500-host-bridge");
s->cfgaddr = pci_host_conf_register_mmio(&s->pci_state, DEVICE_BIG_ENDIAN);
s->cfgdata = pci_host_data_register_mmio(&s->pci_state,
DEVICE_LITTLE_ENDIAN);
s->reg = cpu_register_io_memory(e500_pci_reg_read, e500_pci_reg_write, s,
DEVICE_BIG_ENDIAN);
sysbus_init_mmio_cb(dev, PCIE500_ALL_SIZE, e500_pci_map);
return 0;
}
static int e500_host_bridge_initfn(PCIDevice *dev)
{
pci_config_set_vendor_id(dev->config, PCI_VENDOR_ID_FREESCALE);
pci_config_set_device_id(dev->config, PCI_DEVICE_ID_MPC8533E);
pci_config_set_class(dev->config, PCI_CLASS_PROCESSOR_POWERPC);
return 0;
}
static PCIDeviceInfo e500_host_bridge_info = {
.qdev.name = "e500-host-bridge",
.qdev.desc = "Host bridge",
.qdev.size = sizeof(PCIDevice),
.init = e500_host_bridge_initfn,
};
static SysBusDeviceInfo e500_pcihost_info = {
.init = e500_pcihost_initfn,
.qdev.name = "e500-pcihost",
.qdev.size = sizeof(PPCE500PCIState),
.qdev.vmsd = &vmstate_ppce500_pci,
};
static void e500_pci_register(void)
{
sysbus_register_withprop(&e500_pcihost_info);
pci_qdev_register(&e500_host_bridge_info);
}
device_init(e500_pci_register);

View File

@ -51,7 +51,7 @@
#define TIMEBASE_FREQ 512000000ULL
#define MAX_CPUS 32
#define MAX_CPUS 256
#define XICS_IRQS 1024
sPAPREnvironment *spapr;
@ -93,7 +93,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
/* Root node */
_FDT((fdt_begin_node(fdt, "")));
_FDT((fdt_property_string(fdt, "device_type", "chrp")));
_FDT((fdt_property_string(fdt, "model", "qemu,emulated-pSeries-LPAR")));
_FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
_FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
_FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
@ -362,8 +362,9 @@ static void ppc_spapr_init(ram_addr_t ram_size,
for (i = 0; i < MAX_SERIAL_PORTS; i++, irq++) {
if (serial_hds[i]) {
spapr_vty_create(spapr->vio_bus, i, serial_hds[i],
xics_find_qirq(spapr->icp, irq), irq);
spapr_vty_create(spapr->vio_bus, SPAPR_VTY_BASE_ADDRESS + i,
serial_hds[i], xics_find_qirq(spapr->icp, irq),
irq);
}
}

View File

@ -455,8 +455,8 @@ static target_ulong h_rtas(CPUState *env, sPAPREnvironment *spapr,
nret, rtas_r3 + 12 + 4*nargs);
}
spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE];
static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];
void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
{

View File

@ -44,7 +44,8 @@ static void rtas_display_character(sPAPREnvironment *spapr,
uint32_t nret, target_ulong rets)
{
uint8_t c = rtas_ld(args, 0);
VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, 0);
VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus,
SPAPR_VTY_BASE_ADDRESS);
if (!sdev) {
rtas_st(rets, 0, -1);

View File

@ -32,6 +32,8 @@ enum VIOsPAPR_TCEAccess {
SPAPR_TCE_RW = 3,
};
#define SPAPR_VTY_BASE_ADDRESS 0x30000000
struct VIOsPAPRDevice;
typedef struct VIOsPAPR_RTCE {

View File

@ -603,6 +603,11 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
if (err) {
fprintf(stderr, "%s: error registering prefix slot: %s\n",
__func__, strerror(-err));
#ifdef TARGET_PPC
fprintf(stderr, "%s: This is probably because your kernel's " \
"PAGE_SIZE is too big. Please try to use 4k " \
"PAGE_SIZE!\n", __func__);
#endif
abort();
}
}

View File

@ -3466,7 +3466,76 @@ static const MonitorDef monitor_defs[] = {
{ "sr13", offsetof(CPUState, sr[13]) },
{ "sr14", offsetof(CPUState, sr[14]) },
{ "sr15", offsetof(CPUState, sr[15]) },
/* Too lazy to put BATs and SPRs ... */
/* Too lazy to put BATs... */
{ "pvr", offsetof(CPUState, spr[SPR_PVR]) },
{ "srr0", offsetof(CPUState, spr[SPR_SRR0]) },
{ "srr1", offsetof(CPUState, spr[SPR_SRR1]) },
{ "sprg0", offsetof(CPUState, spr[SPR_SPRG0]) },
{ "sprg1", offsetof(CPUState, spr[SPR_SPRG1]) },
{ "sprg2", offsetof(CPUState, spr[SPR_SPRG2]) },
{ "sprg3", offsetof(CPUState, spr[SPR_SPRG3]) },
{ "sprg4", offsetof(CPUState, spr[SPR_SPRG4]) },
{ "sprg5", offsetof(CPUState, spr[SPR_SPRG5]) },
{ "sprg6", offsetof(CPUState, spr[SPR_SPRG6]) },
{ "sprg7", offsetof(CPUState, spr[SPR_SPRG7]) },
{ "pid", offsetof(CPUState, spr[SPR_BOOKE_PID]) },
{ "csrr0", offsetof(CPUState, spr[SPR_BOOKE_CSRR0]) },
{ "csrr1", offsetof(CPUState, spr[SPR_BOOKE_CSRR1]) },
{ "esr", offsetof(CPUState, spr[SPR_BOOKE_ESR]) },
{ "dear", offsetof(CPUState, spr[SPR_BOOKE_DEAR]) },
{ "mcsr", offsetof(CPUState, spr[SPR_BOOKE_MCSR]) },
{ "tsr", offsetof(CPUState, spr[SPR_BOOKE_TSR]) },
{ "tcr", offsetof(CPUState, spr[SPR_BOOKE_TCR]) },
{ "vrsave", offsetof(CPUState, spr[SPR_VRSAVE]) },
{ "pir", offsetof(CPUState, spr[SPR_BOOKE_PIR]) },
{ "mcsrr0", offsetof(CPUState, spr[SPR_BOOKE_MCSRR0]) },
{ "mcsrr1", offsetof(CPUState, spr[SPR_BOOKE_MCSRR1]) },
{ "decar", offsetof(CPUState, spr[SPR_BOOKE_DECAR]) },
{ "ivpr", offsetof(CPUState, spr[SPR_BOOKE_IVPR]) },
{ "epcr", offsetof(CPUState, spr[SPR_BOOKE_EPCR]) },
{ "sprg8", offsetof(CPUState, spr[SPR_BOOKE_SPRG8]) },
{ "ivor0", offsetof(CPUState, spr[SPR_BOOKE_IVOR0]) },
{ "ivor1", offsetof(CPUState, spr[SPR_BOOKE_IVOR1]) },
{ "ivor2", offsetof(CPUState, spr[SPR_BOOKE_IVOR2]) },
{ "ivor3", offsetof(CPUState, spr[SPR_BOOKE_IVOR3]) },
{ "ivor4", offsetof(CPUState, spr[SPR_BOOKE_IVOR4]) },
{ "ivor5", offsetof(CPUState, spr[SPR_BOOKE_IVOR5]) },
{ "ivor6", offsetof(CPUState, spr[SPR_BOOKE_IVOR6]) },
{ "ivor7", offsetof(CPUState, spr[SPR_BOOKE_IVOR7]) },
{ "ivor8", offsetof(CPUState, spr[SPR_BOOKE_IVOR8]) },
{ "ivor9", offsetof(CPUState, spr[SPR_BOOKE_IVOR9]) },
{ "ivor10", offsetof(CPUState, spr[SPR_BOOKE_IVOR10]) },
{ "ivor11", offsetof(CPUState, spr[SPR_BOOKE_IVOR11]) },
{ "ivor12", offsetof(CPUState, spr[SPR_BOOKE_IVOR12]) },
{ "ivor13", offsetof(CPUState, spr[SPR_BOOKE_IVOR13]) },
{ "ivor14", offsetof(CPUState, spr[SPR_BOOKE_IVOR14]) },
{ "ivor15", offsetof(CPUState, spr[SPR_BOOKE_IVOR15]) },
{ "ivor32", offsetof(CPUState, spr[SPR_BOOKE_IVOR32]) },
{ "ivor33", offsetof(CPUState, spr[SPR_BOOKE_IVOR33]) },
{ "ivor34", offsetof(CPUState, spr[SPR_BOOKE_IVOR34]) },
{ "ivor35", offsetof(CPUState, spr[SPR_BOOKE_IVOR35]) },
{ "ivor36", offsetof(CPUState, spr[SPR_BOOKE_IVOR36]) },
{ "ivor37", offsetof(CPUState, spr[SPR_BOOKE_IVOR37]) },
{ "mas0", offsetof(CPUState, spr[SPR_BOOKE_MAS0]) },
{ "mas1", offsetof(CPUState, spr[SPR_BOOKE_MAS1]) },
{ "mas2", offsetof(CPUState, spr[SPR_BOOKE_MAS2]) },
{ "mas3", offsetof(CPUState, spr[SPR_BOOKE_MAS3]) },
{ "mas4", offsetof(CPUState, spr[SPR_BOOKE_MAS4]) },
{ "mas6", offsetof(CPUState, spr[SPR_BOOKE_MAS6]) },
{ "mas7", offsetof(CPUState, spr[SPR_BOOKE_MAS7]) },
{ "mmucfg", offsetof(CPUState, spr[SPR_MMUCFG]) },
{ "tlb0cfg", offsetof(CPUState, spr[SPR_BOOKE_TLB0CFG]) },
{ "tlb1cfg", offsetof(CPUState, spr[SPR_BOOKE_TLB1CFG]) },
{ "epr", offsetof(CPUState, spr[SPR_BOOKE_EPR]) },
{ "eplc", offsetof(CPUState, spr[SPR_BOOKE_EPLC]) },
{ "epsc", offsetof(CPUState, spr[SPR_BOOKE_EPSC]) },
{ "svr", offsetof(CPUState, spr[SPR_E500_SVR]) },
{ "mcar", offsetof(CPUState, spr[SPR_Exxx_MCAR]) },
{ "pid1", offsetof(CPUState, spr[SPR_BOOKE_PID1]) },
{ "pid2", offsetof(CPUState, spr[SPR_BOOKE_PID2]) },
{ "hid0", offsetof(CPUState, spr[SPR_HID0]) },
#elif defined(TARGET_SPARC)
{ "g0", offsetof(CPUState, gregs[0]) },
{ "g1", offsetof(CPUState, gregs[1]) },

View File

@ -108,8 +108,8 @@ enum powerpc_mmu_t {
POWERPC_MMU_MPC8xx = 0x00000007,
/* BookE MMU model */
POWERPC_MMU_BOOKE = 0x00000008,
/* BookE FSL MMU model */
POWERPC_MMU_BOOKE_FSL = 0x00000009,
/* BookE 2.06 MMU model */
POWERPC_MMU_BOOKE206 = 0x00000009,
/* PowerPC 601 MMU model (specific BATs format) */
POWERPC_MMU_601 = 0x0000000A,
#if defined(TARGET_PPC64)
@ -420,6 +420,7 @@ struct ppc_slb_t {
#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 */
#define MSR_GS 28 /* guest state for BookE */
#define MSR_UCLE 26 /* User-mode cache lock enable for BookE */
#define MSR_VR 25 /* altivec available x hflags */
#define MSR_SPE 25 /* SPE enable for BookE x hflags */
@ -457,6 +458,7 @@ struct ppc_slb_t {
#define msr_cm ((env->msr >> MSR_CM) & 1)
#define msr_icm ((env->msr >> MSR_ICM) & 1)
#define msr_thv ((env->msr >> MSR_THV) & 1)
#define msr_gs ((env->msr >> MSR_GS) & 1)
#define msr_ucle ((env->msr >> MSR_UCLE) & 1)
#define msr_vr ((env->msr >> MSR_VR) & 1)
#define msr_spe ((env->msr >> MSR_SPE) & 1)
@ -605,6 +607,224 @@ enum {
#define vscr_nj (((env->vscr) >> VSCR_NJ) & 0x1)
#define vscr_sat (((env->vscr) >> VSCR_SAT) & 0x1)
/*****************************************************************************/
/* BookE e500 MMU registers */
#define MAS0_NV_SHIFT 0
#define MAS0_NV_MASK (0xfff << MAS0_NV_SHIFT)
#define MAS0_WQ_SHIFT 12
#define MAS0_WQ_MASK (3 << MAS0_WQ_SHIFT)
/* Write TLB entry regardless of reservation */
#define MAS0_WQ_ALWAYS (0 << MAS0_WQ_SHIFT)
/* Write TLB entry only already in use */
#define MAS0_WQ_COND (1 << MAS0_WQ_SHIFT)
/* Clear TLB entry */
#define MAS0_WQ_CLR_RSRV (2 << MAS0_WQ_SHIFT)
#define MAS0_HES_SHIFT 14
#define MAS0_HES (1 << MAS0_HES_SHIFT)
#define MAS0_ESEL_SHIFT 16
#define MAS0_ESEL_MASK (0xfff << MAS0_ESEL_SHIFT)
#define MAS0_TLBSEL_SHIFT 28
#define MAS0_TLBSEL_MASK (3 << MAS0_TLBSEL_SHIFT)
#define MAS0_TLBSEL_TLB0 (0 << MAS0_TLBSEL_SHIFT)
#define MAS0_TLBSEL_TLB1 (1 << MAS0_TLBSEL_SHIFT)
#define MAS0_TLBSEL_TLB2 (2 << MAS0_TLBSEL_SHIFT)
#define MAS0_TLBSEL_TLB3 (3 << MAS0_TLBSEL_SHIFT)
#define MAS0_ATSEL_SHIFT 31
#define MAS0_ATSEL (1 << MAS0_ATSEL_SHIFT)
#define MAS0_ATSEL_TLB 0
#define MAS0_ATSEL_LRAT MAS0_ATSEL
#define MAS1_TSIZE_SHIFT 8
#define MAS1_TSIZE_MASK (0xf << MAS1_TSIZE_SHIFT)
#define MAS1_TS_SHIFT 12
#define MAS1_TS (1 << MAS1_TS_SHIFT)
#define MAS1_IND_SHIFT 13
#define MAS1_IND (1 << MAS1_IND_SHIFT)
#define MAS1_TID_SHIFT 16
#define MAS1_TID_MASK (0x3fff << MAS1_TID_SHIFT)
#define MAS1_IPROT_SHIFT 30
#define MAS1_IPROT (1 << MAS1_IPROT_SHIFT)
#define MAS1_VALID_SHIFT 31
#define MAS1_VALID 0x80000000
#define MAS2_EPN_SHIFT 12
#define MAS2_EPN_MASK (0xfffff << MAS2_EPN_SHIFT)
#define MAS2_ACM_SHIFT 6
#define MAS2_ACM (1 << MAS2_ACM_SHIFT)
#define MAS2_VLE_SHIFT 5
#define MAS2_VLE (1 << MAS2_VLE_SHIFT)
#define MAS2_W_SHIFT 4
#define MAS2_W (1 << MAS2_W_SHIFT)
#define MAS2_I_SHIFT 3
#define MAS2_I (1 << MAS2_I_SHIFT)
#define MAS2_M_SHIFT 2
#define MAS2_M (1 << MAS2_M_SHIFT)
#define MAS2_G_SHIFT 1
#define MAS2_G (1 << MAS2_G_SHIFT)
#define MAS2_E_SHIFT 0
#define MAS2_E (1 << MAS2_E_SHIFT)
#define MAS3_RPN_SHIFT 12
#define MAS3_RPN_MASK (0xfffff << MAS3_RPN_SHIFT)
#define MAS3_U0 0x00000200
#define MAS3_U1 0x00000100
#define MAS3_U2 0x00000080
#define MAS3_U3 0x00000040
#define MAS3_UX 0x00000020
#define MAS3_SX 0x00000010
#define MAS3_UW 0x00000008
#define MAS3_SW 0x00000004
#define MAS3_UR 0x00000002
#define MAS3_SR 0x00000001
#define MAS3_SPSIZE_SHIFT 1
#define MAS3_SPSIZE_MASK (0x3e << MAS3_SPSIZE_SHIFT)
#define MAS4_TLBSELD_SHIFT MAS0_TLBSEL_SHIFT
#define MAS4_TLBSELD_MASK MAS0_TLBSEL_MASK
#define MAS4_TIDSELD_MASK 0x00030000
#define MAS4_TIDSELD_PID0 0x00000000
#define MAS4_TIDSELD_PID1 0x00010000
#define MAS4_TIDSELD_PID2 0x00020000
#define MAS4_TIDSELD_PIDZ 0x00030000
#define MAS4_INDD 0x00008000 /* Default IND */
#define MAS4_TSIZED_SHIFT MAS1_TSIZE_SHIFT
#define MAS4_TSIZED_MASK MAS1_TSIZE_MASK
#define MAS4_ACMD 0x00000040
#define MAS4_VLED 0x00000020
#define MAS4_WD 0x00000010
#define MAS4_ID 0x00000008
#define MAS4_MD 0x00000004
#define MAS4_GD 0x00000002
#define MAS4_ED 0x00000001
#define MAS4_WIMGED_MASK 0x0000001f /* Default WIMGE */
#define MAS4_WIMGED_SHIFT 0
#define MAS5_SGS 0x80000000
#define MAS5_SLPID_MASK 0x00000fff
#define MAS6_SPID0 0x3fff0000
#define MAS6_SPID1 0x00007ffe
#define MAS6_ISIZE(x) MAS1_TSIZE(x)
#define MAS6_SAS 0x00000001
#define MAS6_SPID MAS6_SPID0
#define MAS6_SIND 0x00000002 /* Indirect page */
#define MAS6_SIND_SHIFT 1
#define MAS6_SPID_MASK 0x3fff0000
#define MAS6_SPID_SHIFT 16
#define MAS6_ISIZE_MASK 0x00000f80
#define MAS6_ISIZE_SHIFT 7
#define MAS7_RPN 0xffffffff
#define MAS8_TGS 0x80000000
#define MAS8_VF 0x40000000
#define MAS8_TLBPID 0x00000fff
/* Bit definitions for MMUCFG */
#define MMUCFG_MAVN 0x00000003 /* MMU Architecture Version Number */
#define MMUCFG_MAVN_V1 0x00000000 /* v1.0 */
#define MMUCFG_MAVN_V2 0x00000001 /* v2.0 */
#define MMUCFG_NTLBS 0x0000000c /* Number of TLBs */
#define MMUCFG_PIDSIZE 0x000007c0 /* PID Reg Size */
#define MMUCFG_TWC 0x00008000 /* TLB Write Conditional (v2.0) */
#define MMUCFG_LRAT 0x00010000 /* LRAT Supported (v2.0) */
#define MMUCFG_RASIZE 0x00fe0000 /* Real Addr Size */
#define MMUCFG_LPIDSIZE 0x0f000000 /* LPID Reg Size */
/* Bit definitions for MMUCSR0 */
#define MMUCSR0_TLB1FI 0x00000002 /* TLB1 Flash invalidate */
#define MMUCSR0_TLB0FI 0x00000004 /* TLB0 Flash invalidate */
#define MMUCSR0_TLB2FI 0x00000040 /* TLB2 Flash invalidate */
#define MMUCSR0_TLB3FI 0x00000020 /* TLB3 Flash invalidate */
#define MMUCSR0_TLBFI (MMUCSR0_TLB0FI | MMUCSR0_TLB1FI | \
MMUCSR0_TLB2FI | MMUCSR0_TLB3FI)
#define MMUCSR0_TLB0PS 0x00000780 /* TLB0 Page Size */
#define MMUCSR0_TLB1PS 0x00007800 /* TLB1 Page Size */
#define MMUCSR0_TLB2PS 0x00078000 /* TLB2 Page Size */
#define MMUCSR0_TLB3PS 0x00780000 /* TLB3 Page Size */
/* TLBnCFG encoding */
#define TLBnCFG_N_ENTRY 0x00000fff /* number of entries */
#define TLBnCFG_HES 0x00002000 /* HW select supported */
#define TLBnCFG_AVAIL 0x00004000 /* variable page size */
#define TLBnCFG_IPROT 0x00008000 /* IPROT supported */
#define TLBnCFG_GTWE 0x00010000 /* Guest can write */
#define TLBnCFG_IND 0x00020000 /* IND entries supported */
#define TLBnCFG_PT 0x00040000 /* Can load from page table */
#define TLBnCFG_MINSIZE 0x00f00000 /* Minimum Page Size (v1.0) */
#define TLBnCFG_MINSIZE_SHIFT 20
#define TLBnCFG_MAXSIZE 0x000f0000 /* Maximum Page Size (v1.0) */
#define TLBnCFG_MAXSIZE_SHIFT 16
#define TLBnCFG_ASSOC 0xff000000 /* Associativity */
#define TLBnCFG_ASSOC_SHIFT 24
/* TLBnPS encoding */
#define TLBnPS_4K 0x00000004
#define TLBnPS_8K 0x00000008
#define TLBnPS_16K 0x00000010
#define TLBnPS_32K 0x00000020
#define TLBnPS_64K 0x00000040
#define TLBnPS_128K 0x00000080
#define TLBnPS_256K 0x00000100
#define TLBnPS_512K 0x00000200
#define TLBnPS_1M 0x00000400
#define TLBnPS_2M 0x00000800
#define TLBnPS_4M 0x00001000
#define TLBnPS_8M 0x00002000
#define TLBnPS_16M 0x00004000
#define TLBnPS_32M 0x00008000
#define TLBnPS_64M 0x00010000
#define TLBnPS_128M 0x00020000
#define TLBnPS_256M 0x00040000
#define TLBnPS_512M 0x00080000
#define TLBnPS_1G 0x00100000
#define TLBnPS_2G 0x00200000
#define TLBnPS_4G 0x00400000
#define TLBnPS_8G 0x00800000
#define TLBnPS_16G 0x01000000
#define TLBnPS_32G 0x02000000
#define TLBnPS_64G 0x04000000
#define TLBnPS_128G 0x08000000
#define TLBnPS_256G 0x10000000
/* tlbilx action encoding */
#define TLBILX_T_ALL 0
#define TLBILX_T_TID 1
#define TLBILX_T_FULLMATCH 3
#define TLBILX_T_CLASS0 4
#define TLBILX_T_CLASS1 5
#define TLBILX_T_CLASS2 6
#define TLBILX_T_CLASS3 7
/* BookE 2.06 helper defines */
#define BOOKE206_FLUSH_TLB0 (1 << 0)
#define BOOKE206_FLUSH_TLB1 (1 << 1)
#define BOOKE206_FLUSH_TLB2 (1 << 2)
#define BOOKE206_FLUSH_TLB3 (1 << 3)
/* number of possible TLBs */
#define BOOKE206_MAX_TLBN 4
/*****************************************************************************/
/* The whole PowerPC CPU context */
#define NB_MMU_MODES 3
@ -676,7 +896,7 @@ struct CPUPPCState {
int nb_BATs;
target_ulong DBAT[2][8];
target_ulong IBAT[2][8];
/* PowerPC TLB registers (for 4xx and 60x software driven TLBs) */
/* PowerPC TLB registers (for 4xx, e500 and 60x software driven TLBs) */
int nb_tlb; /* Total number of TLB */
int tlb_per_way; /* Speed-up helper: used to avoid divisions at run time */
int nb_ways; /* Number of ways in the TLB set */
@ -720,6 +940,7 @@ struct CPUPPCState {
int bfd_mach;
uint32_t flags;
uint64_t insns_flags;
uint64_t insns_flags2;
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
target_phys_addr_t vpa;
@ -853,6 +1074,10 @@ void store_40x_dbcr0 (CPUPPCState *env, uint32_t val);
void store_40x_sler (CPUPPCState *env, uint32_t val);
void store_booke_tcr (CPUPPCState *env, target_ulong val);
void store_booke_tsr (CPUPPCState *env, target_ulong val);
void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot);
int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
target_phys_addr_t *raddrp, target_ulong address,
uint32_t pid, int ext, int i);
void ppc_tlb_invalidate_all (CPUPPCState *env);
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr);
#if defined(TARGET_PPC64)
@ -1016,6 +1241,7 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
#define SPR_HSPRG1 (0x131)
#define SPR_HDSISR (0x132)
#define SPR_HDAR (0x133)
#define SPR_BOOKE_EPCR (0x133)
#define SPR_SPURR (0x134)
#define SPR_BOOKE_DBCR0 (0x134)
#define SPR_IBCR (0x135)
@ -1543,6 +1769,11 @@ enum {
PPC_DCRUX = 0x4000000000000000ULL,
/* popcntw and popcntd instructions */
PPC_POPCNTWD = 0x8000000000000000ULL,
/* extended type values */
/* BookE 2.06 PowerPC specification */
PPC2_BOOKE206 = 0x0000000000000001ULL,
};
/*****************************************************************************/
@ -1695,6 +1926,77 @@ static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
#endif
}
#if !defined(CONFIG_USER_ONLY)
static inline int booke206_tlbe_id(CPUState *env, ppcemb_tlb_t *tlbe)
{
ulong tlbel = (ulong)tlbe;
ulong tlbl = (ulong)env->tlb;
return (tlbel - tlbl) / sizeof(env->tlb[0]);
}
static inline int booke206_tlb_size(CPUState *env, int tlbn)
{
uint32_t tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
int r = tlbncfg & TLBnCFG_N_ENTRY;
return r;
}
static inline int booke206_tlb_ways(CPUState *env, int tlbn)
{
uint32_t tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
int r = tlbncfg >> TLBnCFG_ASSOC_SHIFT;
return r;
}
static inline int booke206_tlbe_to_tlbn(CPUState *env, ppcemb_tlb_t *tlbe)
{
int id = booke206_tlbe_id(env, tlbe);
int end = 0;
int i;
for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
end += booke206_tlb_size(env, i);
if (id < end) {
return i;
}
}
cpu_abort(env, "Unknown TLBe: %d\n", id);
return 0;
}
static inline int booke206_tlbe_to_way(CPUState *env, ppcemb_tlb_t *tlb)
{
int tlbn = booke206_tlbe_to_tlbn(env, tlb);
int tlbid = booke206_tlbe_id(env, tlb);
return tlbid & (booke206_tlb_ways(env, tlbn) - 1);
}
static inline ppcemb_tlb_t *booke206_get_tlbe(CPUState *env, const int tlbn,
target_ulong ea, int way)
{
int r;
uint32_t ways = booke206_tlb_ways(env, tlbn);
int ways_bits = ffs(ways) - 1;
int tlb_bits = ffs(booke206_tlb_size(env, tlbn)) - 1;
int i;
way &= ways - 1;
ea >>= MAS2_EPN_SHIFT;
ea &= (1 << (tlb_bits - ways_bits)) - 1;
r = (ea << ways_bits) | way;
/* bump up to tlbn index */
for (i = 0; i < tlbn; i++) {
r += booke206_tlb_size(env, i);
}
return &env->tlb[r].tlbe;
}
#endif
extern void (*cpu_ppc_hypercall)(CPUState *);
#endif /* !defined (__CPU_PPC_H__) */

View File

@ -993,10 +993,10 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
}
/* Generic TLB check function for embedded PowerPC implementations */
static inline int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
target_phys_addr_t *raddrp,
target_ulong address, uint32_t pid, int ext,
int i)
int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
target_phys_addr_t *raddrp,
target_ulong address, uint32_t pid, int ext,
int i)
{
target_ulong mask;
@ -1006,8 +1006,8 @@ static inline int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
}
mask = ~(tlb->size - 1);
LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
" " TARGET_FMT_lx " %u\n", __func__, i, address, pid, tlb->EPN,
mask, (uint32_t)tlb->PID);
" " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
mask, (uint32_t)tlb->PID, tlb->prot);
/* Check PID */
if (tlb->PID != 0 && tlb->PID != pid)
return -1;
@ -1153,48 +1153,164 @@ void store_40x_sler (CPUPPCState *env, uint32_t val)
env->spr[SPR_405_SLER] = val;
}
static inline int mmubooke_check_tlb (CPUState *env, ppcemb_tlb_t *tlb,
target_phys_addr_t *raddr, int *prot,
target_ulong address, int rw,
int access_type, int i)
{
int ret, _prot;
if (ppcemb_tlb_check(env, tlb, raddr, address,
env->spr[SPR_BOOKE_PID],
!env->nb_pids, i) >= 0) {
goto found_tlb;
}
if (env->spr[SPR_BOOKE_PID1] &&
ppcemb_tlb_check(env, tlb, raddr, address,
env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
goto found_tlb;
}
if (env->spr[SPR_BOOKE_PID2] &&
ppcemb_tlb_check(env, tlb, raddr, address,
env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
goto found_tlb;
}
LOG_SWTLB("%s: TLB entry not found\n", __func__);
return -1;
found_tlb:
if (msr_pr != 0) {
_prot = tlb->prot & 0xF;
} else {
_prot = (tlb->prot >> 4) & 0xF;
}
/* Check the address space */
if (access_type == ACCESS_CODE) {
if (msr_ir != (tlb->attr & 1)) {
LOG_SWTLB("%s: AS doesn't match\n", __func__);
return -1;
}
*prot = _prot;
if (_prot & PAGE_EXEC) {
LOG_SWTLB("%s: good TLB!\n", __func__);
return 0;
}
LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
ret = -3;
} else {
if (msr_dr != (tlb->attr & 1)) {
LOG_SWTLB("%s: AS doesn't match\n", __func__);
return -1;
}
*prot = _prot;
if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
LOG_SWTLB("%s: found TLB!\n", __func__);
return 0;
}
LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
ret = -2;
}
return ret;
}
static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
target_ulong address, int rw,
int access_type)
{
ppcemb_tlb_t *tlb;
target_phys_addr_t raddr;
int i, prot, ret;
int i, ret;
ret = -1;
raddr = (target_phys_addr_t)-1ULL;
for (i = 0; i < env->nb_tlb; i++) {
tlb = &env->tlb[i].tlbe;
if (ppcemb_tlb_check(env, tlb, &raddr, address,
env->spr[SPR_BOOKE_PID], 1, i) < 0)
continue;
if (msr_pr != 0)
prot = tlb->prot & 0xF;
else
prot = (tlb->prot >> 4) & 0xF;
/* Check the address space */
if (access_type == ACCESS_CODE) {
if (msr_ir != (tlb->attr & 1))
continue;
ctx->prot = prot;
if (prot & PAGE_EXEC) {
ret = 0;
break;
}
ret = -3;
} else {
if (msr_dr != (tlb->attr & 1))
continue;
ctx->prot = prot;
if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
ret = 0;
break;
}
ret = -2;
ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
access_type, i);
if (!ret) {
break;
}
}
if (ret >= 0)
if (ret >= 0) {
ctx->raddr = raddr;
LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
" %d %d\n", __func__, address, ctx->raddr, ctx->prot,
ret);
} else {
LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
" %d %d\n", __func__, address, raddr, ctx->prot, ret);
}
return ret;
}
void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
{
int tlb_size;
int i, j;
ppc_tlb_t *tlb = env->tlb;
for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
if (flags & (1 << i)) {
tlb_size = booke206_tlb_size(env, i);
for (j = 0; j < tlb_size; j++) {
if (!check_iprot || !(tlb[j].tlbe.attr & MAS1_IPROT)) {
tlb[j].tlbe.prot = 0;
}
}
}
tlb += booke206_tlb_size(env, i);
}
tlb_flush(env, 1);
}
static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
target_ulong address, int rw,
int access_type)
{
ppcemb_tlb_t *tlb;
target_phys_addr_t raddr;
int i, j, ret;
ret = -1;
raddr = (target_phys_addr_t)-1ULL;
for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
int ways = booke206_tlb_ways(env, i);
for (j = 0; j < ways; j++) {
tlb = booke206_get_tlbe(env, i, address, j);
ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
access_type, j);
if (ret != -1) {
goto found_tlb;
}
}
}
found_tlb:
if (ret >= 0) {
ctx->raddr = raddr;
LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
" %d %d\n", __func__, address, ctx->raddr, ctx->prot,
ret);
} else {
LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
" %d %d\n", __func__, address, raddr, ctx->prot, ret);
}
return ret;
}
@ -1254,9 +1370,8 @@ static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
/* XXX: TODO */
cpu_abort(env, "MPC8xx MMU model is not implemented\n");
break;
case POWERPC_MMU_BOOKE_FSL:
/* XXX: TODO */
cpu_abort(env, "BookE FSL MMU model not implemented\n");
case POWERPC_MMU_BOOKE206:
cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");
break;
default:
cpu_abort(env, "Unknown or invalid MMU model\n");
@ -1281,6 +1396,9 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
IS and DS bits only affect the address space. */
ret = mmubooke_get_physical_address(env, ctx, eaddr,
rw, access_type);
} else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
access_type);
} else {
/* No address translation. */
ret = check_physical(env, ctx, eaddr, rw);
@ -1314,14 +1432,14 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
ret = mmubooke_get_physical_address(env, ctx, eaddr,
rw, access_type);
break;
case POWERPC_MMU_BOOKE206:
ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
access_type);
break;
case POWERPC_MMU_MPC8xx:
/* XXX: TODO */
cpu_abort(env, "MPC8xx MMU model is not implemented\n");
break;
case POWERPC_MMU_BOOKE_FSL:
/* XXX: TODO */
cpu_abort(env, "BookE FSL MMU model not implemented\n");
return -1;
case POWERPC_MMU_REAL:
cpu_abort(env, "PowerPC in real mode do not do any translation\n");
return -1;
@ -1348,6 +1466,46 @@ target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
return ctx.raddr & TARGET_PAGE_MASK;
}
static void booke206_update_mas_tlb_miss(CPUState *env, target_ulong address,
int rw)
{
env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
env->spr[SPR_BOOKE_MAS3] = 0;
env->spr[SPR_BOOKE_MAS6] = 0;
env->spr[SPR_BOOKE_MAS7] = 0;
/* AS */
if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
}
env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
case MAS4_TIDSELD_PID0:
env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
break;
case MAS4_TIDSELD_PID1:
env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
break;
case MAS4_TIDSELD_PID2:
env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
break;
}
env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
/* next victim logic */
env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
env->last_way++;
env->last_way &= booke206_tlb_ways(env, 0) - 1;
env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
}
/* Perform address translation */
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
int mmu_idx, int is_softmmu)
@ -1403,15 +1561,14 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
env->exception_index = POWERPC_EXCP_ISI;
env->error_code = 0x40000000;
break;
case POWERPC_MMU_BOOKE206:
booke206_update_mas_tlb_miss(env, address, rw);
/* fall through */
case POWERPC_MMU_BOOKE:
env->exception_index = POWERPC_EXCP_ITLB;
env->error_code = 0;
env->spr[SPR_BOOKE_DEAR] = address;
return -1;
case POWERPC_MMU_BOOKE_FSL:
/* XXX: TODO */
cpu_abort(env, "BookE FSL MMU model is not implemented\n");
return -1;
case POWERPC_MMU_MPC8xx:
/* XXX: TODO */
cpu_abort(env, "MPC8xx MMU model is not implemented\n");
@ -1432,7 +1589,8 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
break;
case -3:
/* No execute protection violation */
if (env->mmu_model == POWERPC_MMU_BOOKE) {
if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
(env->mmu_model == POWERPC_MMU_BOOKE206)) {
env->spr[SPR_BOOKE_ESR] = 0x00000000;
}
env->exception_index = POWERPC_EXCP_ISI;
@ -1522,16 +1680,15 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
/* XXX: TODO */
cpu_abort(env, "MPC8xx MMU model is not implemented\n");
break;
case POWERPC_MMU_BOOKE206:
booke206_update_mas_tlb_miss(env, address, rw);
/* fall through */
case POWERPC_MMU_BOOKE:
env->exception_index = POWERPC_EXCP_DTLB;
env->error_code = 0;
env->spr[SPR_BOOKE_DEAR] = address;
env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
return -1;
case POWERPC_MMU_BOOKE_FSL:
/* XXX: TODO */
cpu_abort(env, "BookE FSL MMU model is not implemented\n");
return -1;
case POWERPC_MMU_REAL:
cpu_abort(env, "PowerPC in real mode should never raise "
"any MMU exceptions\n");
@ -1551,7 +1708,8 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
if (rw) {
env->spr[SPR_40x_ESR] |= 0x00800000;
}
} else if (env->mmu_model == POWERPC_MMU_BOOKE) {
} else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
(env->mmu_model == POWERPC_MMU_BOOKE206)) {
env->spr[SPR_BOOKE_DEAR] = address;
env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
} else {
@ -1822,10 +1980,8 @@ void ppc_tlb_invalidate_all (CPUPPCState *env)
case POWERPC_MMU_BOOKE:
tlb_flush(env, 1);
break;
case POWERPC_MMU_BOOKE_FSL:
/* XXX: TODO */
if (!kvm_enabled())
cpu_abort(env, "BookE MMU model is not implemented\n");
case POWERPC_MMU_BOOKE206:
booke206_flush_tlb(env, -1, 0);
break;
case POWERPC_MMU_32B:
case POWERPC_MMU_601:
@ -1869,9 +2025,9 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
/* XXX: TODO */
cpu_abort(env, "BookE MMU model is not implemented\n");
break;
case POWERPC_MMU_BOOKE_FSL:
case POWERPC_MMU_BOOKE206:
/* XXX: TODO */
cpu_abort(env, "BookE FSL MMU model is not implemented\n");
cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
break;
case POWERPC_MMU_32B:
case POWERPC_MMU_601:
@ -2589,7 +2745,8 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
env->exception_index = POWERPC_EXCP_NONE;
env->error_code = 0;
if (env->mmu_model == POWERPC_MMU_BOOKE) {
if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
(env->mmu_model == POWERPC_MMU_BOOKE206)) {
/* XXX: The BookE changes address space when switching modes,
we should probably implement that as different MMU indexes,
but for the moment we do it the slow way and flush all. */

View File

@ -334,6 +334,12 @@ DEF_HELPER_1(4xx_tlbsx, tl, tl)
DEF_HELPER_2(440_tlbre, tl, i32, tl)
DEF_HELPER_3(440_tlbwe, void, i32, tl, tl)
DEF_HELPER_1(440_tlbsx, tl, tl)
DEF_HELPER_0(booke206_tlbre, void)
DEF_HELPER_0(booke206_tlbwe, void)
DEF_HELPER_1(booke206_tlbsx, void, tl)
DEF_HELPER_1(booke206_tlbivax, void, tl)
DEF_HELPER_1(booke206_tlbflush, void, i32)
DEF_HELPER_2(booke_setpid, void, i32, tl)
DEF_HELPER_1(6xx_tlbd, void, tl)
DEF_HELPER_1(6xx_tlbi, void, tl)
DEF_HELPER_1(74xx_tlbd, void, tl)

View File

@ -2,6 +2,7 @@
* PowerPC implementation of KVM hooks
*
* Copyright IBM Corp. 2007
* Copyright (C) 2011 Freescale Semiconductor, Inc.
*
* Authors:
* Jerone Young <jyoung5@us.ibm.com>
@ -43,6 +44,10 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
static int cap_interrupt_unset = false;
static int cap_interrupt_level = false;
static int cap_segstate;
#ifdef KVM_CAP_PPC_BOOKE_SREGS
static int cap_booke_sregs;
#endif
/* XXX We have a race condition where we actually have a level triggered
* interrupt, but the infrastructure can't expose that yet, so the guest
@ -68,6 +73,12 @@ int kvm_arch_init(KVMState *s)
#ifdef KVM_CAP_PPC_IRQ_LEVEL
cap_interrupt_level = kvm_check_extension(s, KVM_CAP_PPC_IRQ_LEVEL);
#endif
#ifdef KVM_CAP_PPC_SEGSTATE
cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE);
#endif
#ifdef KVM_CAP_PPC_BOOKE_SREGS
cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS);
#endif
if (!cap_interrupt_level) {
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@ -77,13 +88,50 @@ int kvm_arch_init(KVMState *s)
return 0;
}
static int kvm_arch_sync_sregs(CPUState *cenv)
{
struct kvm_sregs sregs;
int ret;
if (cenv->excp_model == POWERPC_EXCP_BOOKE) {
/* What we're really trying to say is "if we're on BookE, we use
the native PVR for now". This is the only sane way to check
it though, so we potentially confuse users that they can run
BookE guests on BookS. Let's hope nobody dares enough :) */
return 0;
} else {
if (!cap_segstate) {
fprintf(stderr, "kvm error: missing PVR setting capability\n");
return -ENOSYS;
}
}
#if !defined(CONFIG_KVM_PPC_PVR)
if (1) {
fprintf(stderr, "kvm error: missing PVR setting capability\n");
return -ENOSYS;
}
#endif
ret = kvm_vcpu_ioctl(cenv, KVM_GET_SREGS, &sregs);
if (ret) {
return ret;
}
#ifdef CONFIG_KVM_PPC_PVR
sregs.pvr = cenv->spr[SPR_PVR];
#endif
return kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
}
int kvm_arch_init_vcpu(CPUState *cenv)
{
int ret = 0;
struct kvm_sregs sregs;
int ret;
sregs.pvr = cenv->spr[SPR_PVR];
ret = kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
ret = kvm_arch_sync_sregs(cenv);
if (ret) {
return ret;
}
idle_timer = qemu_new_timer_ns(vm_clock, kvm_kick_env, cenv);
@ -122,6 +170,8 @@ int kvm_arch_put_registers(CPUState *env, int level)
regs.sprg6 = env->spr[SPR_SPRG6];
regs.sprg7 = env->spr[SPR_SPRG7];
regs.pid = env->spr[SPR_BOOKE_PID];
for (i = 0;i < 32; i++)
regs.gpr[i] = env->gpr[i];
@ -136,15 +186,18 @@ int kvm_arch_get_registers(CPUState *env)
{
struct kvm_regs regs;
struct kvm_sregs sregs;
uint32_t cr;
int i, ret;
ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
if (ret < 0)
return ret;
ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
if (ret < 0)
return ret;
cr = regs.cr;
for (i = 7; i >= 0; i--) {
env->crf[i] = cr & 15;
cr >>= 4;
}
env->ctr = regs.ctr;
env->lr = regs.lr;
@ -164,11 +217,124 @@ int kvm_arch_get_registers(CPUState *env)
env->spr[SPR_SPRG6] = regs.sprg6;
env->spr[SPR_SPRG7] = regs.sprg7;
env->spr[SPR_BOOKE_PID] = regs.pid;
for (i = 0;i < 32; i++)
env->gpr[i] = regs.gpr[i];
#ifdef KVM_CAP_PPC_BOOKE_SREGS
if (cap_booke_sregs) {
ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
if (ret < 0) {
return ret;
}
if (sregs.u.e.features & KVM_SREGS_E_BASE) {
env->spr[SPR_BOOKE_CSRR0] = sregs.u.e.csrr0;
env->spr[SPR_BOOKE_CSRR1] = sregs.u.e.csrr1;
env->spr[SPR_BOOKE_ESR] = sregs.u.e.esr;
env->spr[SPR_BOOKE_DEAR] = sregs.u.e.dear;
env->spr[SPR_BOOKE_MCSR] = sregs.u.e.mcsr;
env->spr[SPR_BOOKE_TSR] = sregs.u.e.tsr;
env->spr[SPR_BOOKE_TCR] = sregs.u.e.tcr;
env->spr[SPR_DECR] = sregs.u.e.dec;
env->spr[SPR_TBL] = sregs.u.e.tb & 0xffffffff;
env->spr[SPR_TBU] = sregs.u.e.tb >> 32;
env->spr[SPR_VRSAVE] = sregs.u.e.vrsave;
}
if (sregs.u.e.features & KVM_SREGS_E_ARCH206) {
env->spr[SPR_BOOKE_PIR] = sregs.u.e.pir;
env->spr[SPR_BOOKE_MCSRR0] = sregs.u.e.mcsrr0;
env->spr[SPR_BOOKE_MCSRR1] = sregs.u.e.mcsrr1;
env->spr[SPR_BOOKE_DECAR] = sregs.u.e.decar;
env->spr[SPR_BOOKE_IVPR] = sregs.u.e.ivpr;
}
if (sregs.u.e.features & KVM_SREGS_E_64) {
env->spr[SPR_BOOKE_EPCR] = sregs.u.e.epcr;
}
if (sregs.u.e.features & KVM_SREGS_E_SPRG8) {
env->spr[SPR_BOOKE_SPRG8] = sregs.u.e.sprg8;
}
if (sregs.u.e.features & KVM_SREGS_E_IVOR) {
env->spr[SPR_BOOKE_IVOR0] = sregs.u.e.ivor_low[0];
env->spr[SPR_BOOKE_IVOR1] = sregs.u.e.ivor_low[1];
env->spr[SPR_BOOKE_IVOR2] = sregs.u.e.ivor_low[2];
env->spr[SPR_BOOKE_IVOR3] = sregs.u.e.ivor_low[3];
env->spr[SPR_BOOKE_IVOR4] = sregs.u.e.ivor_low[4];
env->spr[SPR_BOOKE_IVOR5] = sregs.u.e.ivor_low[5];
env->spr[SPR_BOOKE_IVOR6] = sregs.u.e.ivor_low[6];
env->spr[SPR_BOOKE_IVOR7] = sregs.u.e.ivor_low[7];
env->spr[SPR_BOOKE_IVOR8] = sregs.u.e.ivor_low[8];
env->spr[SPR_BOOKE_IVOR9] = sregs.u.e.ivor_low[9];
env->spr[SPR_BOOKE_IVOR10] = sregs.u.e.ivor_low[10];
env->spr[SPR_BOOKE_IVOR11] = sregs.u.e.ivor_low[11];
env->spr[SPR_BOOKE_IVOR12] = sregs.u.e.ivor_low[12];
env->spr[SPR_BOOKE_IVOR13] = sregs.u.e.ivor_low[13];
env->spr[SPR_BOOKE_IVOR14] = sregs.u.e.ivor_low[14];
env->spr[SPR_BOOKE_IVOR15] = sregs.u.e.ivor_low[15];
if (sregs.u.e.features & KVM_SREGS_E_SPE) {
env->spr[SPR_BOOKE_IVOR32] = sregs.u.e.ivor_high[0];
env->spr[SPR_BOOKE_IVOR33] = sregs.u.e.ivor_high[1];
env->spr[SPR_BOOKE_IVOR34] = sregs.u.e.ivor_high[2];
}
if (sregs.u.e.features & KVM_SREGS_E_PM) {
env->spr[SPR_BOOKE_IVOR35] = sregs.u.e.ivor_high[3];
}
if (sregs.u.e.features & KVM_SREGS_E_PC) {
env->spr[SPR_BOOKE_IVOR36] = sregs.u.e.ivor_high[4];
env->spr[SPR_BOOKE_IVOR37] = sregs.u.e.ivor_high[5];
}
}
if (sregs.u.e.features & KVM_SREGS_E_ARCH206_MMU) {
env->spr[SPR_BOOKE_MAS0] = sregs.u.e.mas0;
env->spr[SPR_BOOKE_MAS1] = sregs.u.e.mas1;
env->spr[SPR_BOOKE_MAS2] = sregs.u.e.mas2;
env->spr[SPR_BOOKE_MAS3] = sregs.u.e.mas7_3 & 0xffffffff;
env->spr[SPR_BOOKE_MAS4] = sregs.u.e.mas4;
env->spr[SPR_BOOKE_MAS6] = sregs.u.e.mas6;
env->spr[SPR_BOOKE_MAS7] = sregs.u.e.mas7_3 >> 32;
env->spr[SPR_MMUCFG] = sregs.u.e.mmucfg;
env->spr[SPR_BOOKE_TLB0CFG] = sregs.u.e.tlbcfg[0];
env->spr[SPR_BOOKE_TLB1CFG] = sregs.u.e.tlbcfg[1];
}
if (sregs.u.e.features & KVM_SREGS_EXP) {
env->spr[SPR_BOOKE_EPR] = sregs.u.e.epr;
}
if (sregs.u.e.features & KVM_SREGS_E_PD) {
env->spr[SPR_BOOKE_EPLC] = sregs.u.e.eplc;
env->spr[SPR_BOOKE_EPSC] = sregs.u.e.epsc;
}
if (sregs.u.e.impl_id == KVM_SREGS_E_IMPL_FSL) {
env->spr[SPR_E500_SVR] = sregs.u.e.impl.fsl.svr;
env->spr[SPR_Exxx_MCAR] = sregs.u.e.impl.fsl.mcar;
env->spr[SPR_HID0] = sregs.u.e.impl.fsl.hid0;
if (sregs.u.e.impl.fsl.features & KVM_SREGS_E_FSL_PIDn) {
env->spr[SPR_BOOKE_PID1] = sregs.u.e.impl.fsl.pid1;
env->spr[SPR_BOOKE_PID2] = sregs.u.e.impl.fsl.pid2;
}
}
}
#endif
#ifdef KVM_CAP_PPC_SEGSTATE
if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_SEGSTATE)) {
if (cap_segstate) {
ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
if (ret < 0) {
return ret;
}
ppc_store_sdr1(env, sregs.u.s.sdr1);
/* Sync SLB */

View File

@ -4206,4 +4206,300 @@ target_ulong helper_440_tlbsx (target_ulong address)
return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
}
/* PowerPC BookE 2.06 TLB management */
static ppcemb_tlb_t *booke206_cur_tlb(CPUState *env)
{
uint32_t tlbncfg = 0;
int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
int tlb;
tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb];
if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) {
cpu_abort(env, "we don't support HES yet\n");
}
return booke206_get_tlbe(env, tlb, ea, esel);
}
static inline target_phys_addr_t booke206_tlb_to_page_size(int size)
{
return (1 << (size << 1)) << 10;
}
static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size)
{
return (ffs(size >> 10) - 1) >> 1;
}
void helper_booke_setpid(uint32_t pidn, target_ulong pid)
{
env->spr[pidn] = pid;
/* changing PIDs mean we're in a different address space now */
tlb_flush(env, 1);
}
void helper_booke206_tlbwe(void)
{
uint32_t tlbncfg, tlbn;
ppcemb_tlb_t *tlb;
target_phys_addr_t rpn;
int tlbe_size;
switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
case MAS0_WQ_ALWAYS:
/* good to go, write that entry */
break;
case MAS0_WQ_COND:
/* XXX check if reserved */
if (0) {
return;
}
break;
case MAS0_WQ_CLR_RSRV:
/* XXX clear entry */
return;
default:
/* no idea what to do */
return;
}
if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) &&
!msr_gs) {
/* XXX we don't support direct LRAT setting yet */
fprintf(stderr, "cpu: don't support LRAT setting yet\n");
return;
}
tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
tlb = booke206_cur_tlb(env);
if (msr_gs) {
cpu_abort(env, "missing HV implementation\n");
} else {
rpn = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
(env->spr[SPR_BOOKE_MAS3] & 0xfffff000);
}
tlb->RPN = rpn;
tlb->PID = (env->spr[SPR_BOOKE_MAS1] & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
if (tlbncfg & TLBnCFG_AVAIL) {
tlbe_size = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK)
>> MAS1_TSIZE_SHIFT;
} else {
tlbe_size = (tlbncfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
}
tlb->size = booke206_tlb_to_page_size(tlbe_size);
tlb->EPN = (uint32_t)(env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
tlb->attr = env->spr[SPR_BOOKE_MAS2] & (MAS2_ACM | MAS2_VLE | MAS2_W |
MAS2_I | MAS2_M | MAS2_G | MAS2_E)
<< 1;
if (tlbncfg & TLBnCFG_IPROT) {
tlb->attr |= env->spr[SPR_BOOKE_MAS1] & MAS1_IPROT;
}
tlb->attr |= (env->spr[SPR_BOOKE_MAS3] &
((MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3)) << 8);
if (env->spr[SPR_BOOKE_MAS1] & MAS1_TS) {
tlb->attr |= 1;
}
tlb->prot = 0;
if (env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) {
tlb->prot |= PAGE_VALID;
}
if (env->spr[SPR_BOOKE_MAS3] & MAS3_UX) {
tlb->prot |= PAGE_EXEC;
}
if (env->spr[SPR_BOOKE_MAS3] & MAS3_SX) {
tlb->prot |= PAGE_EXEC << 4;
}
if (env->spr[SPR_BOOKE_MAS3] & MAS3_UW) {
tlb->prot |= PAGE_WRITE;
}
if (env->spr[SPR_BOOKE_MAS3] & MAS3_SW) {
tlb->prot |= PAGE_WRITE << 4;
}
if (env->spr[SPR_BOOKE_MAS3] & MAS3_UR) {
tlb->prot |= PAGE_READ;
}
if (env->spr[SPR_BOOKE_MAS3] & MAS3_SR) {
tlb->prot |= PAGE_READ << 4;
}
if (tlb->size == TARGET_PAGE_SIZE) {
tlb_flush_page(env, tlb->EPN);
} else {
tlb_flush(env, 1);
}
}
static inline void booke206_tlb_to_mas(CPUState *env, ppcemb_tlb_t *tlb)
{
int tlbn = booke206_tlbe_to_tlbn(env, tlb);
int way = booke206_tlbe_to_way(env, tlb);
env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT;
env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT;
env->spr[SPR_BOOKE_MAS1] = MAS1_VALID;
env->spr[SPR_BOOKE_MAS2] = 0;
env->spr[SPR_BOOKE_MAS7] = (uint64_t)tlb->RPN >> 32;
env->spr[SPR_BOOKE_MAS3] = tlb->RPN;
env->spr[SPR_BOOKE_MAS1] |= tlb->PID << MAS1_TID_SHIFT;
env->spr[SPR_BOOKE_MAS1] |= booke206_page_size_to_tlb(tlb->size)
<< MAS1_TSIZE_SHIFT;
env->spr[SPR_BOOKE_MAS1] |= tlb->attr & MAS1_IPROT;
if (tlb->attr & 1) {
env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
}
env->spr[SPR_BOOKE_MAS2] = tlb->EPN;
env->spr[SPR_BOOKE_MAS2] |= (tlb->attr >> 1) &
(MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E);
if (tlb->prot & PAGE_EXEC) {
env->spr[SPR_BOOKE_MAS3] |= MAS3_UX;
}
if (tlb->prot & (PAGE_EXEC << 4)) {
env->spr[SPR_BOOKE_MAS3] |= MAS3_SX;
}
if (tlb->prot & PAGE_WRITE) {
env->spr[SPR_BOOKE_MAS3] |= MAS3_UW;
}
if (tlb->prot & (PAGE_WRITE << 4)) {
env->spr[SPR_BOOKE_MAS3] |= MAS3_SW;
}
if (tlb->prot & PAGE_READ) {
env->spr[SPR_BOOKE_MAS3] |= MAS3_UR;
}
if (tlb->prot & (PAGE_READ << 4)) {
env->spr[SPR_BOOKE_MAS3] |= MAS3_SR;
}
env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
}
void helper_booke206_tlbre(void)
{
ppcemb_tlb_t *tlb = NULL;
tlb = booke206_cur_tlb(env);
booke206_tlb_to_mas(env, tlb);
}
void helper_booke206_tlbsx(target_ulong address)
{
ppcemb_tlb_t *tlb = NULL;
int i, j;
target_phys_addr_t raddr;
uint32_t spid, sas;
spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT;
sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS;
for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
int ways = booke206_tlb_ways(env, i);
for (j = 0; j < ways; j++) {
tlb = booke206_get_tlbe(env, i, address, j);
if (ppcemb_tlb_check(env, tlb, &raddr, address, spid, 0, j)) {
continue;
}
if (sas != (tlb->attr & MAS6_SAS)) {
continue;
}
booke206_tlb_to_mas(env, tlb);
return;
}
}
/* no entry found, fill with defaults */
env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
env->spr[SPR_BOOKE_MAS3] = 0;
env->spr[SPR_BOOKE_MAS7] = 0;
if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) {
env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
}
env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16)
<< MAS1_TID_SHIFT;
/* next victim logic */
env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
env->last_way++;
env->last_way &= booke206_tlb_ways(env, 0) - 1;
env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
}
static inline void booke206_invalidate_ea_tlb(CPUState *env, int tlbn,
uint32_t ea)
{
int i;
int ways = booke206_tlb_ways(env, tlbn);
for (i = 0; i < ways; i++) {
ppcemb_tlb_t *tlb = booke206_get_tlbe(env, tlbn, ea, i);
target_phys_addr_t masked_ea = ea & ~(tlb->size - 1);
if ((tlb->EPN == (masked_ea >> MAS2_EPN_SHIFT)) &&
!(tlb->attr & MAS1_IPROT)) {
tlb->prot = 0;
}
}
}
void helper_booke206_tlbivax(target_ulong address)
{
if (address & 0x4) {
/* flush all entries */
if (address & 0x8) {
/* flush all of TLB1 */
booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1);
} else {
/* flush all of TLB0 */
booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0);
}
return;
}
if (address & 0x8) {
/* flush TLB1 entries */
booke206_invalidate_ea_tlb(env, 1, address);
tlb_flush(env, 1);
} else {
/* flush TLB0 entries */
booke206_invalidate_ea_tlb(env, 0, address);
tlb_flush_page(env, address & MAS2_EPN_MASK);
}
}
void helper_booke206_tlbflush(uint32_t type)
{
int flags = 0;
if (type & 2) {
flags |= BOOKE206_FLUSH_TLB1;
}
if (type & 4) {
flags |= BOOKE206_FLUSH_TLB0;
}
booke206_flush_tlb(env, flags, 1);
}
#endif /* !CONFIG_USER_ONLY */

View File

@ -2,6 +2,7 @@
* PowerPC emulation for qemu: main translation routines.
*
* Copyright (c) 2003-2007 Jocelyn Mayer
* Copyright (C) 2011 Freescale Semiconductor, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -200,6 +201,8 @@ struct opc_handler_t {
uint32_t inval;
/* instruction type */
uint64_t type;
/* extended instruction type */
uint64_t type2;
/* handler */
void (*handler)(DisasContext *ctx);
#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
@ -313,10 +316,16 @@ static inline void gen_sync_exception(DisasContext *ctx)
}
#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
GEN_OPCODE(name, opc1, opc2, opc3, inval, type)
GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)
#define GEN_HANDLER_E(name, opc1, opc2, opc3, inval, type, type2) \
GEN_OPCODE(name, opc1, opc2, opc3, inval, type, type2)
#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type)
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, PPC_NONE)
#define GEN_HANDLER2_E(name, onam, opc1, opc2, opc3, inval, type, type2) \
GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, type2)
typedef struct opcode_t {
unsigned char opc1, opc2, opc3;
@ -456,7 +465,7 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
/* PowerPC instructions table */
#if defined(DO_PPC_STATISTICS)
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \
{ \
.opc1 = op1, \
.opc2 = op2, \
@ -465,12 +474,13 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
.handler = { \
.inval = invl, \
.type = _typ, \
.type2 = _typ2, \
.handler = &gen_##name, \
.oname = stringify(name), \
}, \
.oname = stringify(name), \
}
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \
{ \
.opc1 = op1, \
.opc2 = op2, \
@ -479,13 +489,14 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
.handler = { \
.inval = invl, \
.type = _typ, \
.type2 = _typ2, \
.handler = &gen_##name, \
.oname = onam, \
}, \
.oname = onam, \
}
#else
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2) \
{ \
.opc1 = op1, \
.opc2 = op2, \
@ -494,11 +505,12 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
.handler = { \
.inval = invl, \
.type = _typ, \
.type2 = _typ2, \
.handler = &gen_##name, \
}, \
.oname = stringify(name), \
}
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ, _typ2) \
{ \
.opc1 = op1, \
.opc2 = op2, \
@ -507,6 +519,7 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
.handler = { \
.inval = invl, \
.type = _typ, \
.type2 = _typ2, \
.handler = &gen_##name, \
}, \
.oname = onam, \
@ -533,6 +546,7 @@ static void gen_invalid(DisasContext *ctx)
static opc_handler_t invalid_handler = {
.inval = 0xFFFFFFFF,
.type = PPC_NONE,
.type2 = PPC_NONE,
.handler = gen_invalid,
};
@ -5974,6 +5988,80 @@ static void gen_tlbwe_440(DisasContext *ctx)
#endif
}
/* TLB management - PowerPC BookE 2.06 implementation */
/* tlbre */
static void gen_tlbre_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
if (unlikely(!ctx->mem_idx)) {
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
return;
}
gen_helper_booke206_tlbre();
#endif
}
/* tlbsx - tlbsx. */
static void gen_tlbsx_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
TCGv t0;
if (unlikely(!ctx->mem_idx)) {
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
return;
}
if (rA(ctx->opcode)) {
t0 = tcg_temp_new();
tcg_gen_mov_tl(t0, cpu_gpr[rD(ctx->opcode)]);
} else {
t0 = tcg_const_tl(0);
}
tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]);
gen_helper_booke206_tlbsx(t0);
#endif
}
/* tlbwe */
static void gen_tlbwe_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
if (unlikely(!ctx->mem_idx)) {
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
return;
}
gen_helper_booke206_tlbwe();
#endif
}
static void gen_tlbivax_booke206(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
TCGv t0;
if (unlikely(!ctx->mem_idx)) {
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
return;
}
t0 = tcg_temp_new();
gen_addr_reg_index(ctx, t0);
gen_helper_booke206_tlbivax(t0);
#endif
}
/* wrtee */
static void gen_wrtee(DisasContext *ctx)
{
@ -8420,7 +8508,7 @@ GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT),
GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON),
GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON),
GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP),
GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE),
GEN_HANDLER_E(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE, PPC2_BOOKE206),
GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI),
GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI),
GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB),
@ -8429,12 +8517,23 @@ GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB),
GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE),
GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE),
GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE),
GEN_HANDLER2_E(tlbre_booke206, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001,
PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER2_E(tlbsx_booke206, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000,
PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001,
PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
GEN_HANDLER(mbar, 0x1F, 0x16, 0x1a, 0x001FF801, PPC_BOOKE),
GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE),
GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE),
GEN_HANDLER_E(mbar, 0x1F, 0x16, 0x1a, 0x001FF801,
PPC_BOOKE, PPC2_BOOKE206),
GEN_HANDLER_E(msync, 0x1F, 0x16, 0x12, 0x03FFF801,
PPC_BOOKE, PPC2_BOOKE206),
GEN_HANDLER2_E(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001,
PPC_BOOKE, PPC2_BOOKE206),
GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC),
GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC),
GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC),
@ -9124,9 +9223,84 @@ void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
}
cpu_fprintf(f, "FPSCR %08x\n", env->fpscr);
#if !defined(CONFIG_USER_ONLY)
cpu_fprintf(f, "SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx " SDR1 "
TARGET_FMT_lx "\n", env->spr[SPR_SRR0], env->spr[SPR_SRR1],
env->spr[SPR_SDR1]);
cpu_fprintf(f, " SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx
" PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n",
env->spr[SPR_SRR0], env->spr[SPR_SRR1],
env->spr[SPR_PVR], env->spr[SPR_VRSAVE]);
cpu_fprintf(f, "SPRG0 " TARGET_FMT_lx " SPRG1 " TARGET_FMT_lx
" SPRG2 " TARGET_FMT_lx " SPRG3 " TARGET_FMT_lx "\n",
env->spr[SPR_SPRG0], env->spr[SPR_SPRG1],
env->spr[SPR_SPRG2], env->spr[SPR_SPRG3]);
cpu_fprintf(f, "SPRG4 " TARGET_FMT_lx " SPRG5 " TARGET_FMT_lx
" SPRG6 " TARGET_FMT_lx " SPRG7 " TARGET_FMT_lx "\n",
env->spr[SPR_SPRG4], env->spr[SPR_SPRG5],
env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]);
if (env->excp_model == POWERPC_EXCP_BOOKE) {
cpu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx
" MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n",
env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
cpu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
" ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n",
env->spr[SPR_BOOKE_TCR], env->spr[SPR_BOOKE_TSR],
env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
cpu_fprintf(f, " PIR " TARGET_FMT_lx " DECAR " TARGET_FMT_lx
" IVPR " TARGET_FMT_lx " EPCR " TARGET_FMT_lx "\n",
env->spr[SPR_BOOKE_PIR], env->spr[SPR_BOOKE_DECAR],
env->spr[SPR_BOOKE_IVPR], env->spr[SPR_BOOKE_EPCR]);
cpu_fprintf(f, " MCSR " TARGET_FMT_lx " SPRG8 " TARGET_FMT_lx
" EPR " TARGET_FMT_lx "\n",
env->spr[SPR_BOOKE_MCSR], env->spr[SPR_BOOKE_SPRG8],
env->spr[SPR_BOOKE_EPR]);
/* FSL-specific */
cpu_fprintf(f, " MCAR " TARGET_FMT_lx " PID1 " TARGET_FMT_lx
" PID2 " TARGET_FMT_lx " SVR " TARGET_FMT_lx "\n",
env->spr[SPR_Exxx_MCAR], env->spr[SPR_BOOKE_PID1],
env->spr[SPR_BOOKE_PID2], env->spr[SPR_E500_SVR]);
/*
* IVORs are left out as they are large and do not change often --
* they can be read with "p $ivor0", "p $ivor1", etc.
*/
}
switch (env->mmu_model) {
case POWERPC_MMU_32B:
case POWERPC_MMU_601:
case POWERPC_MMU_SOFT_6xx:
case POWERPC_MMU_SOFT_74xx:
#if defined(TARGET_PPC64)
case POWERPC_MMU_620:
case POWERPC_MMU_64B:
#endif
cpu_fprintf(f, " SDR1 " TARGET_FMT_lx "\n", env->spr[SPR_SDR1]);
break;
case POWERPC_MMU_BOOKE206:
cpu_fprintf(f, " MAS0 " TARGET_FMT_lx " MAS1 " TARGET_FMT_lx
" MAS2 " TARGET_FMT_lx " MAS3 " TARGET_FMT_lx "\n",
env->spr[SPR_BOOKE_MAS0], env->spr[SPR_BOOKE_MAS1],
env->spr[SPR_BOOKE_MAS2], env->spr[SPR_BOOKE_MAS3]);
cpu_fprintf(f, " MAS4 " TARGET_FMT_lx " MAS6 " TARGET_FMT_lx
" MAS7 " TARGET_FMT_lx " PID " TARGET_FMT_lx "\n",
env->spr[SPR_BOOKE_MAS4], env->spr[SPR_BOOKE_MAS6],
env->spr[SPR_BOOKE_MAS7], env->spr[SPR_BOOKE_PID]);
cpu_fprintf(f, "MMUCFG " TARGET_FMT_lx " TLB0CFG " TARGET_FMT_lx
" TLB1CFG " TARGET_FMT_lx "\n",
env->spr[SPR_MMUCFG], env->spr[SPR_BOOKE_TLB0CFG],
env->spr[SPR_BOOKE_TLB1CFG]);
break;
default:
break;
}
#endif
#undef RGPL

View File

@ -37,6 +37,7 @@ struct ppc_def_t {
uint32_t pvr;
uint32_t svr;
uint64_t insns_flags;
uint64_t insns_flags2;
uint64_t msr_mask;
powerpc_mmu_t mmu_model;
powerpc_excp_t excp_model;
@ -1354,6 +1355,31 @@ static void gen_74xx_soft_tlb (CPUPPCState *env, int nb_tlbs, int nb_ways)
#endif
}
#if !defined(CONFIG_USER_ONLY)
static void spr_write_e500_l1csr0 (void *opaque, int sprn, int gprn)
{
TCGv t0 = tcg_temp_new();
tcg_gen_andi_tl(t0, cpu_gpr[gprn], ~256);
gen_store_spr(sprn, t0);
tcg_temp_free(t0);
}
static void spr_write_booke206_mmucsr0 (void *opaque, int sprn, int gprn)
{
TCGv t0 = tcg_const_i32(sprn);
gen_helper_booke206_tlbflush(t0);
tcg_temp_free(t0);
}
static void spr_write_booke_pid (void *opaque, int sprn, int gprn)
{
TCGv t0 = tcg_const_i32(sprn);
gen_helper_booke_setpid(t0, cpu_gpr[gprn]);
tcg_temp_free(t0);
}
#endif
static void gen_spr_usprgh (CPUPPCState *env)
{
spr_register(env, SPR_USPRG4, "USPRG4",
@ -1493,7 +1519,7 @@ static void gen_spr_BookE (CPUPPCState *env, uint64_t ivor_mask)
}
spr_register(env, SPR_BOOKE_PID, "PID",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
&spr_read_generic, &spr_write_booke_pid,
0x00000000);
spr_register(env, SPR_BOOKE_TCR, "TCR",
SPR_NOACCESS, SPR_NOACCESS,
@ -1535,8 +1561,19 @@ static void gen_spr_BookE (CPUPPCState *env, uint64_t ivor_mask)
0x00000000);
}
/* FSL storage control registers */
static void gen_spr_BookE_FSL (CPUPPCState *env, uint32_t mas_mask)
static inline uint32_t gen_tlbncfg(uint32_t assoc, uint32_t minsize,
uint32_t maxsize, uint32_t flags,
uint32_t nentries)
{
return (assoc << TLBnCFG_ASSOC_SHIFT) |
(minsize << TLBnCFG_MINSIZE_SHIFT) |
(maxsize << TLBnCFG_MAXSIZE_SHIFT) |
flags | nentries;
}
/* BookE 2.06 storage control registers */
static void gen_spr_BookE206(CPUPPCState *env, uint32_t mas_mask,
uint32_t *tlbncfg)
{
#if !defined(CONFIG_USER_ONLY)
const char *mas_names[8] = {
@ -1562,14 +1599,14 @@ static void gen_spr_BookE_FSL (CPUPPCState *env, uint32_t mas_mask)
/* XXX : not implemented */
spr_register(env, SPR_BOOKE_PID1, "PID1",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
&spr_read_generic, &spr_write_booke_pid,
0x00000000);
}
if (env->nb_pids > 2) {
/* XXX : not implemented */
spr_register(env, SPR_BOOKE_PID2, "PID2",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
&spr_read_generic, &spr_write_booke_pid,
0x00000000);
}
/* XXX : not implemented */
@ -1577,45 +1614,38 @@ static void gen_spr_BookE_FSL (CPUPPCState *env, uint32_t mas_mask)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, SPR_NOACCESS,
0x00000000); /* TOFIX */
/* XXX : not implemented */
spr_register(env, SPR_MMUCSR0, "MMUCSR0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000); /* TOFIX */
switch (env->nb_ways) {
case 4:
/* XXX : not implemented */
spr_register(env, SPR_BOOKE_TLB3CFG, "TLB3CFG",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, SPR_NOACCESS,
0x00000000); /* TOFIX */
tlbncfg[3]);
/* Fallthru */
case 3:
/* XXX : not implemented */
spr_register(env, SPR_BOOKE_TLB2CFG, "TLB2CFG",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, SPR_NOACCESS,
0x00000000); /* TOFIX */
tlbncfg[2]);
/* Fallthru */
case 2:
/* XXX : not implemented */
spr_register(env, SPR_BOOKE_TLB1CFG, "TLB1CFG",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, SPR_NOACCESS,
0x00000000); /* TOFIX */
tlbncfg[1]);
/* Fallthru */
case 1:
/* XXX : not implemented */
spr_register(env, SPR_BOOKE_TLB0CFG, "TLB0CFG",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, SPR_NOACCESS,
0x00000000); /* TOFIX */
tlbncfg[0]);
/* Fallthru */
case 0:
default:
break;
}
#endif
gen_spr_usprgh(env);
}
/* SPR specific to PowerPC 440 implementation */
@ -3201,6 +3231,7 @@ static int check_pow_hid0_74xx (CPUPPCState *env)
PPC_CACHE_DCBZ | \
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_4xx_COMMON | PPC_40x_EXCP)
#define POWERPC_INSNS2_401 (PPC_NONE)
#define POWERPC_MSRM_401 (0x00000000000FD201ULL)
#define POWERPC_MMU_401 (POWERPC_MMU_REAL)
#define POWERPC_EXCP_401 (POWERPC_EXCP_40x)
@ -3230,6 +3261,7 @@ static void init_proc_401 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
PPC_4xx_COMMON | PPC_40x_EXCP)
#define POWERPC_INSNS2_401x2 (PPC_NONE)
#define POWERPC_MSRM_401x2 (0x00000000001FD231ULL)
#define POWERPC_MMU_401x2 (POWERPC_MMU_SOFT_4xx_Z)
#define POWERPC_EXCP_401x2 (POWERPC_EXCP_40x)
@ -3266,6 +3298,7 @@ static void init_proc_401x2 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
PPC_4xx_COMMON | PPC_40x_EXCP)
#define POWERPC_INSNS2_401x3 (PPC_NONE)
#define POWERPC_MSRM_401x3 (0x00000000001FD631ULL)
#define POWERPC_MMU_401x3 (POWERPC_MMU_SOFT_4xx_Z)
#define POWERPC_EXCP_401x3 (POWERPC_EXCP_40x)
@ -3298,6 +3331,7 @@ static void init_proc_401x3 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
PPC_4xx_COMMON | PPC_40x_EXCP)
#define POWERPC_INSNS2_IOP480 (PPC_NONE)
#define POWERPC_MSRM_IOP480 (0x00000000001FD231ULL)
#define POWERPC_MMU_IOP480 (POWERPC_MMU_SOFT_4xx_Z)
#define POWERPC_EXCP_IOP480 (POWERPC_EXCP_40x)
@ -3333,6 +3367,7 @@ static void init_proc_IOP480 (CPUPPCState *env)
PPC_CACHE_DCBZ | \
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_4xx_COMMON | PPC_40x_EXCP)
#define POWERPC_INSNS2_403 (PPC_NONE)
#define POWERPC_MSRM_403 (0x000000000007D00DULL)
#define POWERPC_MMU_403 (POWERPC_MMU_REAL)
#define POWERPC_EXCP_403 (POWERPC_EXCP_40x)
@ -3363,6 +3398,7 @@ static void init_proc_403 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
PPC_4xx_COMMON | PPC_40x_EXCP)
#define POWERPC_INSNS2_403GCX (PPC_NONE)
#define POWERPC_MSRM_403GCX (0x000000000007D00DULL)
#define POWERPC_MMU_403GCX (POWERPC_MMU_SOFT_4xx_Z)
#define POWERPC_EXCP_403GCX (POWERPC_EXCP_40x)
@ -3411,6 +3447,7 @@ static void init_proc_403GCX (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
PPC_4xx_COMMON | PPC_405_MAC | PPC_40x_EXCP)
#define POWERPC_INSNS2_405 (PPC_NONE)
#define POWERPC_MSRM_405 (0x000000000006E630ULL)
#define POWERPC_MMU_405 (POWERPC_MMU_SOFT_4xx)
#define POWERPC_EXCP_405 (POWERPC_EXCP_40x)
@ -3458,6 +3495,7 @@ static void init_proc_405 (CPUPPCState *env)
PPC_MEM_TLBSYNC | PPC_MFTB | \
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \
PPC_440_SPEC)
#define POWERPC_INSNS2_440EP (PPC_NONE)
#define POWERPC_MSRM_440EP (0x000000000006D630ULL)
#define POWERPC_MMU_440EP (POWERPC_MMU_BOOKE)
#define POWERPC_EXCP_440EP (POWERPC_EXCP_BOOKE)
@ -3538,6 +3576,7 @@ static void init_proc_440EP (CPUPPCState *env)
PPC_MEM_TLBSYNC | PPC_TLBIVA | PPC_MFTB | \
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \
PPC_440_SPEC)
#define POWERPC_INSNS2_440GP (PPC_NONE)
#define POWERPC_MSRM_440GP (0x000000000006FF30ULL)
#define POWERPC_MMU_440GP (POWERPC_MMU_BOOKE)
#define POWERPC_EXCP_440GP (POWERPC_EXCP_BOOKE)
@ -3600,6 +3639,7 @@ static void init_proc_440GP (CPUPPCState *env)
PPC_MEM_TLBSYNC | PPC_MFTB | \
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \
PPC_440_SPEC)
#define POWERPC_INSNS2_440x4 (PPC_NONE)
#define POWERPC_MSRM_440x4 (0x000000000006FF30ULL)
#define POWERPC_MMU_440x4 (POWERPC_MMU_BOOKE)
#define POWERPC_EXCP_440x4 (POWERPC_EXCP_BOOKE)
@ -3662,6 +3702,7 @@ static void init_proc_440x4 (CPUPPCState *env)
PPC_MEM_TLBSYNC | PPC_MFTB | \
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \
PPC_440_SPEC)
#define POWERPC_INSNS2_440x5 (PPC_NONE)
#define POWERPC_MSRM_440x5 (0x000000000006FF30ULL)
#define POWERPC_MMU_440x5 (POWERPC_MMU_BOOKE)
#define POWERPC_EXCP_440x5 (POWERPC_EXCP_BOOKE)
@ -3742,6 +3783,7 @@ static void init_proc_440x5 (CPUPPCState *env)
PPC_MEM_TLBSYNC | PPC_TLBIVA | \
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \
PPC_440_SPEC)
#define POWERPC_INSNS2_460 (PPC_NONE)
#define POWERPC_MSRM_460 (0x000000000006FF30ULL)
#define POWERPC_MMU_460 (POWERPC_MMU_BOOKE)
#define POWERPC_EXCP_460 (POWERPC_EXCP_BOOKE)
@ -3831,6 +3873,7 @@ static void init_proc_460 (CPUPPCState *env)
PPC_MEM_TLBSYNC | PPC_TLBIVA | \
PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | \
PPC_440_SPEC)
#define POWERPC_INSNS2_460F (PPC_NONE)
#define POWERPC_MSRM_460 (0x000000000006FF30ULL)
#define POWERPC_MMU_460F (POWERPC_MMU_BOOKE)
#define POWERPC_EXCP_460F (POWERPC_EXCP_BOOKE)
@ -3913,6 +3956,7 @@ static void init_proc_460F (CPUPPCState *env)
PPC_MEM_EIEIO | PPC_MEM_SYNC | \
PPC_CACHE_ICBI | PPC_FLOAT | PPC_FLOAT_STFIWX | \
PPC_MFTB)
#define POWERPC_INSNS2_MPC5xx (PPC_NONE)
#define POWERPC_MSRM_MPC5xx (0x000000000001FF43ULL)
#define POWERPC_MMU_MPC5xx (POWERPC_MMU_REAL)
#define POWERPC_EXCP_MPC5xx (POWERPC_EXCP_603)
@ -3939,6 +3983,7 @@ static void init_proc_MPC5xx (CPUPPCState *env)
#define POWERPC_INSNS_MPC8xx (PPC_INSNS_BASE | PPC_STRING | \
PPC_MEM_EIEIO | PPC_MEM_SYNC | \
PPC_CACHE_ICBI | PPC_MFTB)
#define POWERPC_INSNS2_MPC8xx (PPC_NONE)
#define POWERPC_MSRM_MPC8xx (0x000000000001F673ULL)
#define POWERPC_MMU_MPC8xx (POWERPC_MMU_MPC8xx)
#define POWERPC_EXCP_MPC8xx (POWERPC_EXCP_603)
@ -3970,6 +4015,7 @@ static void init_proc_MPC8xx (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_G2 (PPC_NONE)
#define POWERPC_MSRM_G2 (0x000000000006FFF2ULL)
#define POWERPC_MMU_G2 (POWERPC_MMU_SOFT_6xx)
//#define POWERPC_EXCP_G2 (POWERPC_EXCP_G2)
@ -4027,6 +4073,7 @@ static void init_proc_G2 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_G2LE (PPC_NONE)
#define POWERPC_MSRM_G2LE (0x000000000007FFF3ULL)
#define POWERPC_MMU_G2LE (POWERPC_MMU_SOFT_6xx)
#define POWERPC_EXCP_G2LE (POWERPC_EXCP_G2)
@ -4093,8 +4140,9 @@ static void init_proc_G2LE (CPUPPCState *env)
PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \
PPC_MEM_TLBSYNC | PPC_TLBIVAX | \
PPC_BOOKE)
#define POWERPC_INSNS2_e200 (PPC_NONE)
#define POWERPC_MSRM_e200 (0x000000000606FF30ULL)
#define POWERPC_MMU_e200 (POWERPC_MMU_BOOKE_FSL)
#define POWERPC_MMU_e200 (POWERPC_MMU_BOOKE206)
#define POWERPC_EXCP_e200 (POWERPC_EXCP_BOOKE)
#define POWERPC_INPUT_e200 (PPC_FLAGS_INPUT_BookE)
#define POWERPC_BFDM_e200 (bfd_mach_ppc_860)
@ -4115,7 +4163,7 @@ static void init_proc_e200 (CPUPPCState *env)
&spr_read_spefscr, &spr_write_spefscr,
0x00000000);
/* Memory management */
gen_spr_BookE_FSL(env, 0x0000005D);
gen_spr_BookE206(env, 0x0000005D, NULL);
/* XXX : not implemented */
spr_register(env, SPR_HID0, "HID0",
SPR_NOACCESS, SPR_NOACCESS,
@ -4186,6 +4234,11 @@ static void init_proc_e200 (CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
spr_register(env, SPR_MMUCSR0, "MMUCSR0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000); /* TOFIX */
spr_register(env, SPR_BOOKE_DSRR0, "DSRR0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
@ -4213,6 +4266,7 @@ static void init_proc_e200 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_e300 (PPC_NONE)
#define POWERPC_MSRM_e300 (0x000000000007FFF3ULL)
#define POWERPC_MMU_e300 (POWERPC_MMU_SOFT_6xx)
#define POWERPC_EXCP_e300 (POWERPC_EXCP_603)
@ -4262,10 +4316,10 @@ static void init_proc_e300 (CPUPPCState *env)
PPC_WRTEE | PPC_RFDI | \
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \
PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \
PPC_MEM_TLBSYNC | PPC_TLBIVAX | \
PPC_BOOKE)
PPC_MEM_TLBSYNC | PPC_TLBIVAX)
#define POWERPC_INSNS2_e500v1 (PPC2_BOOKE206)
#define POWERPC_MSRM_e500v1 (0x000000000606FF30ULL)
#define POWERPC_MMU_e500v1 (POWERPC_MMU_BOOKE_FSL)
#define POWERPC_MMU_e500v1 (POWERPC_MMU_BOOKE206)
#define POWERPC_EXCP_e500v1 (POWERPC_EXCP_BOOKE)
#define POWERPC_INPUT_e500v1 (PPC_FLAGS_INPUT_BookE)
#define POWERPC_BFDM_e500v1 (bfd_mach_ppc_860)
@ -4273,7 +4327,7 @@ static void init_proc_e300 (CPUPPCState *env)
POWERPC_FLAG_UBLE | POWERPC_FLAG_DE | \
POWERPC_FLAG_BUS_CLK)
#define check_pow_e500v1 check_pow_hid0
#define init_proc_e500v1 init_proc_e500
#define init_proc_e500v1 init_proc_e500v1
/* e500v2 core */
#define POWERPC_INSNS_e500v2 (PPC_INSNS_BASE | PPC_ISEL | \
@ -4281,10 +4335,10 @@ static void init_proc_e300 (CPUPPCState *env)
PPC_WRTEE | PPC_RFDI | \
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \
PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \
PPC_MEM_TLBSYNC | PPC_TLBIVAX | \
PPC_BOOKE)
PPC_MEM_TLBSYNC | PPC_TLBIVAX)
#define POWERPC_INSNS2_e500v2 (PPC2_BOOKE206)
#define POWERPC_MSRM_e500v2 (0x000000000606FF30ULL)
#define POWERPC_MMU_e500v2 (POWERPC_MMU_BOOKE_FSL)
#define POWERPC_MMU_e500v2 (POWERPC_MMU_BOOKE206)
#define POWERPC_EXCP_e500v2 (POWERPC_EXCP_BOOKE)
#define POWERPC_INPUT_e500v2 (PPC_FLAGS_INPUT_BookE)
#define POWERPC_BFDM_e500v2 (bfd_mach_ppc_860)
@ -4292,13 +4346,23 @@ static void init_proc_e300 (CPUPPCState *env)
POWERPC_FLAG_UBLE | POWERPC_FLAG_DE | \
POWERPC_FLAG_BUS_CLK)
#define check_pow_e500v2 check_pow_hid0
#define init_proc_e500v2 init_proc_e500
#define init_proc_e500v2 init_proc_e500v2
static void init_proc_e500 (CPUPPCState *env)
static void init_proc_e500 (CPUPPCState *env, int version)
{
uint32_t tlbncfg[2];
#if !defined(CONFIG_USER_ONLY)
int i;
#endif
/* Time base */
gen_tbl(env);
gen_spr_BookE(env, 0x0000000F0000FD7FULL);
/*
* XXX The e500 doesn't implement IVOR7 and IVOR9, but doesn't
* complain when accessing them.
* gen_spr_BookE(env, 0x0000000F0000FD7FULL);
*/
gen_spr_BookE(env, 0x0000000F0000FFFFULL);
/* Processor identification */
spr_register(env, SPR_BOOKE_PIR, "PIR",
SPR_NOACCESS, SPR_NOACCESS,
@ -4312,8 +4376,24 @@ static void init_proc_e500 (CPUPPCState *env)
/* Memory management */
#if !defined(CONFIG_USER_ONLY)
env->nb_pids = 3;
env->nb_ways = 2;
env->id_tlbs = 0;
switch (version) {
case 1:
/* e500v1 */
tlbncfg[0] = gen_tlbncfg(2, 1, 1, 0, 256);
tlbncfg[1] = gen_tlbncfg(16, 1, 9, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16);
break;
case 2:
/* e500v2 */
tlbncfg[0] = gen_tlbncfg(4, 1, 1, 0, 512);
tlbncfg[1] = gen_tlbncfg(16, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16);
break;
default:
cpu_abort(env, "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]);
}
#endif
gen_spr_BookE_FSL(env, 0x0000005F);
gen_spr_BookE206(env, 0x000000DF, tlbncfg);
/* XXX : not implemented */
spr_register(env, SPR_HID0, "HID0",
SPR_NOACCESS, SPR_NOACCESS,
@ -4362,23 +4442,13 @@ static void init_proc_e500 (CPUPPCState *env)
/* XXX : not implemented */
spr_register(env, SPR_Exxx_L1CSR0, "L1CSR0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
&spr_read_generic, &spr_write_e500_l1csr0,
0x00000000);
/* XXX : not implemented */
spr_register(env, SPR_Exxx_L1CSR1, "L1CSR1",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
spr_register(env, SPR_BOOKE_TLB0CFG, "TLB0CFG",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* XXX : not implemented */
spr_register(env, SPR_BOOKE_TLB1CFG, "TLB1CFG",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
spr_register(env, SPR_BOOKE_MCSRR0, "MCSRR0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
@ -4387,11 +4457,18 @@ static void init_proc_e500 (CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
spr_register(env, SPR_MMUCSR0, "MMUCSR0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_booke206_mmucsr0,
0x00000000);
#if !defined(CONFIG_USER_ONLY)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
env->nb_tlb = 0;
for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
env->nb_tlb += booke206_tlb_size(env, i);
}
#endif
init_excp_e200(env);
env->dcache_line_size = 32;
env->icache_line_size = 32;
@ -4399,6 +4476,16 @@ static void init_proc_e500 (CPUPPCState *env)
ppce500_irq_init(env);
}
static void init_proc_e500v1(CPUPPCState *env)
{
init_proc_e500(env, 1);
}
static void init_proc_e500v2(CPUPPCState *env)
{
init_proc_e500(env, 2);
}
/* Non-embedded PowerPC */
/* POWER : same as 601, without mfmsr, mfsr */
@ -4414,6 +4501,7 @@ static void init_proc_e500 (CPUPPCState *env)
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | \
PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_601 (PPC_NONE)
#define POWERPC_MSRM_601 (0x000000000000FD70ULL)
#define POWERPC_MSRR_601 (0x0000000000001040ULL)
//#define POWERPC_MMU_601 (POWERPC_MMU_601)
@ -4466,6 +4554,7 @@ static void init_proc_601 (CPUPPCState *env)
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | \
PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_601v (PPC_NONE)
#define POWERPC_MSRM_601v (0x000000000000FD70ULL)
#define POWERPC_MSRR_601v (0x0000000000001040ULL)
#define POWERPC_MMU_601v (POWERPC_MMU_601)
@ -4493,6 +4582,7 @@ static void init_proc_601v (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_6xx_TLB | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_602_SPEC)
#define POWERPC_INSNS2_602 (PPC_NONE)
#define POWERPC_MSRM_602 (0x0000000000C7FF73ULL)
/* XXX: 602 MMU is quite specific. Should add a special case */
#define POWERPC_MMU_602 (POWERPC_MMU_SOFT_6xx)
@ -4538,6 +4628,7 @@ static void init_proc_602 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_603 (PPC_NONE)
#define POWERPC_MSRM_603 (0x000000000007FF73ULL)
#define POWERPC_MMU_603 (POWERPC_MMU_SOFT_6xx)
//#define POWERPC_EXCP_603 (POWERPC_EXCP_603)
@ -4582,6 +4673,7 @@ static void init_proc_603 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_603E (PPC_NONE)
#define POWERPC_MSRM_603E (0x000000000007FF73ULL)
#define POWERPC_MMU_603E (POWERPC_MMU_SOFT_6xx)
//#define POWERPC_EXCP_603E (POWERPC_EXCP_603E)
@ -4631,6 +4723,7 @@ static void init_proc_603E (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_604 (PPC_NONE)
#define POWERPC_MSRM_604 (0x000000000005FF77ULL)
#define POWERPC_MMU_604 (POWERPC_MMU_32B)
//#define POWERPC_EXCP_604 (POWERPC_EXCP_604)
@ -4669,6 +4762,7 @@ static void init_proc_604 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_604E (PPC_NONE)
#define POWERPC_MSRM_604E (0x000000000005FF77ULL)
#define POWERPC_MMU_604E (POWERPC_MMU_32B)
#define POWERPC_EXCP_604E (POWERPC_EXCP_604)
@ -4727,6 +4821,7 @@ static void init_proc_604E (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_740 (PPC_NONE)
#define POWERPC_MSRM_740 (0x000000000005FF77ULL)
#define POWERPC_MMU_740 (POWERPC_MMU_32B)
#define POWERPC_EXCP_740 (POWERPC_EXCP_7x0)
@ -4772,6 +4867,7 @@ static void init_proc_740 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_750 (PPC_NONE)
#define POWERPC_MSRM_750 (0x000000000005FF77ULL)
#define POWERPC_MMU_750 (POWERPC_MMU_32B)
#define POWERPC_EXCP_750 (POWERPC_EXCP_7x0)
@ -4863,6 +4959,7 @@ static void init_proc_750 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_750cl (PPC_NONE)
#define POWERPC_MSRM_750cl (0x000000000005FF77ULL)
#define POWERPC_MMU_750cl (POWERPC_MMU_32B)
#define POWERPC_EXCP_750cl (POWERPC_EXCP_7x0)
@ -5001,6 +5098,7 @@ static void init_proc_750cl (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_750cx (PPC_NONE)
#define POWERPC_MSRM_750cx (0x000000000005FF77ULL)
#define POWERPC_MMU_750cx (POWERPC_MMU_32B)
#define POWERPC_EXCP_750cx (POWERPC_EXCP_7x0)
@ -5058,6 +5156,7 @@ static void init_proc_750cx (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_750fx (PPC_NONE)
#define POWERPC_MSRM_750fx (0x000000000005FF77ULL)
#define POWERPC_MMU_750fx (POWERPC_MMU_32B)
#define POWERPC_EXCP_750fx (POWERPC_EXCP_7x0)
@ -5120,6 +5219,7 @@ static void init_proc_750fx (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_750gx (PPC_NONE)
#define POWERPC_MSRM_750gx (0x000000000005FF77ULL)
#define POWERPC_MMU_750gx (POWERPC_MMU_32B)
#define POWERPC_EXCP_750gx (POWERPC_EXCP_7x0)
@ -5182,6 +5282,7 @@ static void init_proc_750gx (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_745 (PPC_NONE)
#define POWERPC_MSRM_745 (0x000000000005FF77ULL)
#define POWERPC_MMU_745 (POWERPC_MMU_SOFT_6xx)
#define POWERPC_EXCP_745 (POWERPC_EXCP_7x5)
@ -5235,6 +5336,7 @@ static void init_proc_745 (CPUPPCState *env)
PPC_MEM_SYNC | PPC_MEM_EIEIO | \
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
PPC_SEGMENT | PPC_EXTERN)
#define POWERPC_INSNS2_755 (PPC_NONE)
#define POWERPC_MSRM_755 (0x000000000005FF77ULL)
#define POWERPC_MMU_755 (POWERPC_MMU_SOFT_6xx)
#define POWERPC_EXCP_755 (POWERPC_EXCP_7x5)
@ -5303,6 +5405,7 @@ static void init_proc_755 (CPUPPCState *env)
PPC_MEM_TLBIA | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_ALTIVEC)
#define POWERPC_INSNS2_7400 (PPC_NONE)
#define POWERPC_MSRM_7400 (0x000000000205FF77ULL)
#define POWERPC_MMU_7400 (POWERPC_MMU_32B)
#define POWERPC_EXCP_7400 (POWERPC_EXCP_74xx)
@ -5355,6 +5458,7 @@ static void init_proc_7400 (CPUPPCState *env)
PPC_MEM_TLBIA | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_ALTIVEC)
#define POWERPC_INSNS2_7410 (PPC_NONE)
#define POWERPC_MSRM_7410 (0x000000000205FF77ULL)
#define POWERPC_MMU_7410 (POWERPC_MMU_32B)
#define POWERPC_EXCP_7410 (POWERPC_EXCP_74xx)
@ -5413,6 +5517,7 @@ static void init_proc_7410 (CPUPPCState *env)
PPC_MEM_TLBIA | PPC_74xx_TLB | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_ALTIVEC)
#define POWERPC_INSNS2_7440 (PPC_NONE)
#define POWERPC_MSRM_7440 (0x000000000205FF77ULL)
#define POWERPC_MMU_7440 (POWERPC_MMU_SOFT_74xx)
#define POWERPC_EXCP_7440 (POWERPC_EXCP_74xx)
@ -5498,6 +5603,7 @@ static void init_proc_7440 (CPUPPCState *env)
PPC_MEM_TLBIA | PPC_74xx_TLB | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_ALTIVEC)
#define POWERPC_INSNS2_7450 (PPC_NONE)
#define POWERPC_MSRM_7450 (0x000000000205FF77ULL)
#define POWERPC_MMU_7450 (POWERPC_MMU_SOFT_74xx)
#define POWERPC_EXCP_7450 (POWERPC_EXCP_74xx)
@ -5609,6 +5715,7 @@ static void init_proc_7450 (CPUPPCState *env)
PPC_MEM_TLBIA | PPC_74xx_TLB | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_ALTIVEC)
#define POWERPC_INSNS2_7445 (PPC_NONE)
#define POWERPC_MSRM_7445 (0x000000000205FF77ULL)
#define POWERPC_MMU_7445 (POWERPC_MMU_SOFT_74xx)
#define POWERPC_EXCP_7445 (POWERPC_EXCP_74xx)
@ -5723,6 +5830,7 @@ static void init_proc_7445 (CPUPPCState *env)
PPC_MEM_TLBIA | PPC_74xx_TLB | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_ALTIVEC)
#define POWERPC_INSNS2_7455 (PPC_NONE)
#define POWERPC_MSRM_7455 (0x000000000205FF77ULL)
#define POWERPC_MMU_7455 (POWERPC_MMU_SOFT_74xx)
#define POWERPC_EXCP_7455 (POWERPC_EXCP_74xx)
@ -5839,6 +5947,7 @@ static void init_proc_7455 (CPUPPCState *env)
PPC_MEM_TLBIA | PPC_74xx_TLB | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_ALTIVEC)
#define POWERPC_INSNS2_7457 (PPC_NONE)
#define POWERPC_MSRM_7457 (0x000000000205FF77ULL)
#define POWERPC_MMU_7457 (POWERPC_MMU_SOFT_74xx)
#define POWERPC_EXCP_7457 (POWERPC_EXCP_74xx)
@ -5978,6 +6087,7 @@ static void init_proc_7457 (CPUPPCState *env)
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_64B | PPC_ALTIVEC | \
PPC_SEGMENT_64B | PPC_SLBI)
#define POWERPC_INSNS2_970 (PPC_NONE)
#define POWERPC_MSRM_970 (0x900000000204FF36ULL)
#define POWERPC_MMU_970 (POWERPC_MMU_64B)
//#define POWERPC_EXCP_970 (POWERPC_EXCP_970)
@ -6073,6 +6183,7 @@ static void init_proc_970 (CPUPPCState *env)
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_64B | PPC_ALTIVEC | \
PPC_SEGMENT_64B | PPC_SLBI)
#define POWERPC_INSNS2_970FX (PPC_NONE)
#define POWERPC_MSRM_970FX (0x800000000204FF36ULL)
#define POWERPC_MMU_970FX (POWERPC_MMU_64B)
#define POWERPC_EXCP_970FX (POWERPC_EXCP_970)
@ -6174,6 +6285,7 @@ static void init_proc_970FX (CPUPPCState *env)
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_64B | PPC_ALTIVEC | \
PPC_SEGMENT_64B | PPC_SLBI)
#define POWERPC_INSNS2_970GX (PPC_NONE)
#define POWERPC_MSRM_970GX (0x800000000204FF36ULL)
#define POWERPC_MMU_970GX (POWERPC_MMU_64B)
#define POWERPC_EXCP_970GX (POWERPC_EXCP_970)
@ -6263,6 +6375,7 @@ static void init_proc_970GX (CPUPPCState *env)
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_64B | PPC_ALTIVEC | \
PPC_SEGMENT_64B | PPC_SLBI)
#define POWERPC_INSNS2_970MP (PPC_NONE)
#define POWERPC_MSRM_970MP (0x900000000204FF36ULL)
#define POWERPC_MMU_970MP (POWERPC_MMU_64B)
#define POWERPC_EXCP_970MP (POWERPC_EXCP_970)
@ -6354,6 +6467,7 @@ static void init_proc_970MP (CPUPPCState *env)
PPC_64B | PPC_ALTIVEC | \
PPC_SEGMENT_64B | PPC_SLBI | \
PPC_POPCNTB | PPC_POPCNTWD)
#define POWERPC_INSNS2_POWER7 (PPC_NONE)
#define POWERPC_MSRM_POWER7 (0x800000000204FF36ULL)
#define POWERPC_MMU_POWER7 (POWERPC_MMU_2_06)
#define POWERPC_EXCP_POWER7 (POWERPC_EXCP_POWER7)
@ -6424,6 +6538,7 @@ static void init_proc_POWER7 (CPUPPCState *env)
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | \
PPC_SEGMENT | PPC_EXTERN | \
PPC_64B | PPC_SLBI)
#define POWERPC_INSNS2_620 (PPC_NONE)
#define POWERPC_MSRM_620 (0x800000000005FF77ULL)
//#define POWERPC_MMU_620 (POWERPC_MMU_620)
#define POWERPC_EXCP_620 (POWERPC_EXCP_970)
@ -6459,6 +6574,7 @@ static void init_proc_620 (CPUPPCState *env)
/* Default 32 bits PowerPC target will be 604 */
#define CPU_POWERPC_PPC32 CPU_POWERPC_604
#define POWERPC_INSNS_PPC32 POWERPC_INSNS_604
#define POWERPC_INSNS2_PPC32 POWERPC_INSNS2_604
#define POWERPC_MSRM_PPC32 POWERPC_MSRM_604
#define POWERPC_MMU_PPC32 POWERPC_MMU_604
#define POWERPC_EXCP_PPC32 POWERPC_EXCP_604
@ -6471,6 +6587,7 @@ static void init_proc_620 (CPUPPCState *env)
/* Default 64 bits PowerPC target will be 970 FX */
#define CPU_POWERPC_PPC64 CPU_POWERPC_970FX
#define POWERPC_INSNS_PPC64 POWERPC_INSNS_970FX
#define POWERPC_INSNS2_PPC64 POWERPC_INSNS2_970FX
#define POWERPC_MSRM_PPC64 POWERPC_MSRM_970FX
#define POWERPC_MMU_PPC64 POWERPC_MMU_970FX
#define POWERPC_EXCP_PPC64 POWERPC_EXCP_970FX
@ -6482,27 +6599,29 @@ static void init_proc_620 (CPUPPCState *env)
/* Default PowerPC target will be PowerPC 32 */
#if defined (TARGET_PPC64) && 0 // XXX: TODO
#define CPU_POWERPC_DEFAULT CPU_POWERPC_PPC64
#define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC64
#define POWERPC_MSRM_DEFAULT POWERPC_MSRM_PPC64
#define POWERPC_MMU_DEFAULT POWERPC_MMU_PPC64
#define POWERPC_EXCP_DEFAULT POWERPC_EXCP_PPC64
#define POWERPC_INPUT_DEFAULT POWERPC_INPUT_PPC64
#define POWERPC_BFDM_DEFAULT POWERPC_BFDM_PPC64
#define POWERPC_FLAG_DEFAULT POWERPC_FLAG_PPC64
#define check_pow_DEFAULT check_pow_PPC64
#define init_proc_DEFAULT init_proc_PPC64
#define CPU_POWERPC_DEFAULT CPU_POWERPC_PPC64
#define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC64
#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS_PPC64
#define POWERPC_MSRM_DEFAULT POWERPC_MSRM_PPC64
#define POWERPC_MMU_DEFAULT POWERPC_MMU_PPC64
#define POWERPC_EXCP_DEFAULT POWERPC_EXCP_PPC64
#define POWERPC_INPUT_DEFAULT POWERPC_INPUT_PPC64
#define POWERPC_BFDM_DEFAULT POWERPC_BFDM_PPC64
#define POWERPC_FLAG_DEFAULT POWERPC_FLAG_PPC64
#define check_pow_DEFAULT check_pow_PPC64
#define init_proc_DEFAULT init_proc_PPC64
#else
#define CPU_POWERPC_DEFAULT CPU_POWERPC_PPC32
#define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC32
#define POWERPC_MSRM_DEFAULT POWERPC_MSRM_PPC32
#define POWERPC_MMU_DEFAULT POWERPC_MMU_PPC32
#define POWERPC_EXCP_DEFAULT POWERPC_EXCP_PPC32
#define POWERPC_INPUT_DEFAULT POWERPC_INPUT_PPC32
#define POWERPC_BFDM_DEFAULT POWERPC_BFDM_PPC32
#define POWERPC_FLAG_DEFAULT POWERPC_FLAG_PPC32
#define check_pow_DEFAULT check_pow_PPC32
#define init_proc_DEFAULT init_proc_PPC32
#define CPU_POWERPC_DEFAULT CPU_POWERPC_PPC32
#define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC32
#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS_PPC32
#define POWERPC_MSRM_DEFAULT POWERPC_MSRM_PPC32
#define POWERPC_MMU_DEFAULT POWERPC_MMU_PPC32
#define POWERPC_EXCP_DEFAULT POWERPC_EXCP_PPC32
#define POWERPC_INPUT_DEFAULT POWERPC_INPUT_PPC32
#define POWERPC_BFDM_DEFAULT POWERPC_BFDM_PPC32
#define POWERPC_FLAG_DEFAULT POWERPC_FLAG_PPC32
#define check_pow_DEFAULT check_pow_PPC32
#define init_proc_DEFAULT init_proc_PPC32
#endif
/*****************************************************************************/
@ -7351,18 +7470,19 @@ enum {
/* PowerPC CPU definitions */
#define POWERPC_DEF_SVR(_name, _pvr, _svr, _type) \
{ \
.name = _name, \
.pvr = _pvr, \
.svr = _svr, \
.insns_flags = glue(POWERPC_INSNS_,_type), \
.msr_mask = glue(POWERPC_MSRM_,_type), \
.mmu_model = glue(POWERPC_MMU_,_type), \
.excp_model = glue(POWERPC_EXCP_,_type), \
.bus_model = glue(POWERPC_INPUT_,_type), \
.bfd_mach = glue(POWERPC_BFDM_,_type), \
.flags = glue(POWERPC_FLAG_,_type), \
.init_proc = &glue(init_proc_,_type), \
.check_pow = &glue(check_pow_,_type), \
.name = _name, \
.pvr = _pvr, \
.svr = _svr, \
.insns_flags = glue(POWERPC_INSNS_,_type), \
.insns_flags2 = glue(POWERPC_INSNS2_,_type), \
.msr_mask = glue(POWERPC_MSRM_,_type), \
.mmu_model = glue(POWERPC_MMU_,_type), \
.excp_model = glue(POWERPC_EXCP_,_type), \
.bus_model = glue(POWERPC_INPUT_,_type), \
.bfd_mach = glue(POWERPC_BFDM_,_type), \
.flags = glue(POWERPC_FLAG_,_type), \
.init_proc = &glue(init_proc_,_type), \
.check_pow = &glue(check_pow_,_type), \
}
#define POWERPC_DEF(_name, _pvr, _type) \
POWERPC_DEF_SVR(_name, _pvr, POWERPC_SVR_NONE, _type)
@ -9437,7 +9557,8 @@ static int create_ppc_opcodes (CPUPPCState *env, const ppc_def_t *def)
fill_new_table(env->opcodes, 0x40);
for (opc = opcodes; opc < &opcodes[ARRAY_SIZE(opcodes)]; opc++) {
if ((opc->handler.type & def->insns_flags) != 0) {
if (((opc->handler.type & def->insns_flags) != 0) ||
((opc->handler.type2 & def->insns_flags2) != 0)) {
if (register_insn(env->opcodes, opc) < 0) {
printf("*** ERROR initializing PowerPC instruction "
"0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
@ -9650,6 +9771,7 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
env->excp_model = def->excp_model;
env->bus_model = def->bus_model;
env->insns_flags = def->insns_flags;
env->insns_flags2 = def->insns_flags2;
env->flags = def->flags;
env->bfd_mach = def->bfd_mach;
env->check_pow = def->check_pow;
@ -9699,8 +9821,8 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
case POWERPC_MMU_BOOKE:
mmu_model = "PowerPC BookE";
break;
case POWERPC_MMU_BOOKE_FSL:
mmu_model = "PowerPC BookE FSL";
case POWERPC_MMU_BOOKE206:
mmu_model = "PowerPC BookE 2.06";
break;
case POWERPC_MMU_601:
mmu_model = "PowerPC 601";