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

* 'ppc-next' of git://repo.or.cz/qemu/agraf:
  PPC: Add description for the Freescale e500mc core.
  pseries: Check for duplicate addresses on the spapr-vio bus
  pseries: Populate "/chosen/linux,stdout-path" in the FDT
  pseries: Add a routine to find a stable "default" vty and use it
  pseries: Emit device tree nodes in reg order
  pseries: FDT NUMA extensions to support multi-node guests
  pseries: Remove hcalls callback
  kvm-ppc: halt secondary cpus when guest reset
  console: Fix segfault on screendump without VGA adapter
  PPC: monitor: add ability to dump SLB entries
This commit is contained in:
Aurelien Jarno 2012-01-07 22:01:57 +01:00
commit 15f43ccda1
11 changed files with 347 additions and 65 deletions

View File

@ -186,7 +186,9 @@ void vga_hw_screen_dump(const char *filename)
consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
}
console_select(previous_active_console->index);
if (previous_active_console) {
console_select(previous_active_console->index);
}
}
void vga_hw_text_update(console_ch_t *chardata)

View File

@ -112,6 +112,7 @@ static void spin_kick(void *data)
env->halted = 0;
env->exception_index = -1;
env->stopped = 0;
qemu_cpu_kick(env);
}

View File

@ -97,6 +97,44 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num)
return qirq;
}
static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr)
{
int ret = 0, offset;
CPUState *env;
char cpu_model[32];
int smt = kvmppc_smt_threads();
assert(spapr->cpu_model);
for (env = first_cpu; env != NULL; env = env->next_cpu) {
uint32_t associativity[] = {cpu_to_be32(0x5),
cpu_to_be32(0x0),
cpu_to_be32(0x0),
cpu_to_be32(0x0),
cpu_to_be32(env->numa_node),
cpu_to_be32(env->cpu_index)};
if ((env->cpu_index % smt) != 0) {
continue;
}
snprintf(cpu_model, 32, "/cpus/%s@%x", spapr->cpu_model,
env->cpu_index);
offset = fdt_path_offset(fdt, cpu_model);
if (offset < 0) {
return offset;
}
ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity,
sizeof(associativity));
if (ret < 0) {
return ret;
}
}
return ret;
}
static void *spapr_create_fdt_skel(const char *cpu_model,
target_phys_addr_t rma_size,
target_phys_addr_t initrd_base,
@ -107,9 +145,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
{
void *fdt;
CPUState *env;
uint64_t mem_reg_property_rma[] = { 0, cpu_to_be64(rma_size) };
uint64_t mem_reg_property_nonrma[] = { cpu_to_be64(rma_size),
cpu_to_be64(ram_size - rma_size) };
uint64_t mem_reg_property[2];
uint32_t start_prop = cpu_to_be32(initrd_base);
uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
@ -119,6 +155,13 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
int i;
char *modelname;
int smt = kvmppc_smt_threads();
unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
cpu_to_be32(0x0), cpu_to_be32(0x0),
cpu_to_be32(0x0)};
char mem_name[32];
target_phys_addr_t node0_size, mem_start;
#define _FDT(exp) \
do { \
@ -146,6 +189,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
/* /chosen */
_FDT((fdt_begin_node(fdt, "chosen")));
/* Set Form1_affinity */
_FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
_FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline)));
_FDT((fdt_property(fdt, "linux,initrd-start",
&start_prop, sizeof(start_prop))));
@ -164,24 +210,54 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
_FDT((fdt_end_node(fdt)));
/* memory node(s) */
_FDT((fdt_begin_node(fdt, "memory@0")));
node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
if (rma_size > node0_size) {
rma_size = node0_size;
}
/* RMA */
mem_reg_property[0] = 0;
mem_reg_property[1] = cpu_to_be64(rma_size);
_FDT((fdt_begin_node(fdt, "memory@0")));
_FDT((fdt_property_string(fdt, "device_type", "memory")));
_FDT((fdt_property(fdt, "reg", mem_reg_property_rma,
sizeof(mem_reg_property_rma))));
_FDT((fdt_property(fdt, "reg", mem_reg_property,
sizeof(mem_reg_property))));
_FDT((fdt_property(fdt, "ibm,associativity", associativity,
sizeof(associativity))));
_FDT((fdt_end_node(fdt)));
if (ram_size > rma_size) {
char mem_name[32];
/* RAM: Node 0 */
if (node0_size > rma_size) {
mem_reg_property[0] = cpu_to_be64(rma_size);
mem_reg_property[1] = cpu_to_be64(node0_size - rma_size);
sprintf(mem_name, "memory@%" PRIx64, (uint64_t)rma_size);
sprintf(mem_name, "memory@" TARGET_FMT_lx, rma_size);
_FDT((fdt_begin_node(fdt, mem_name)));
_FDT((fdt_property_string(fdt, "device_type", "memory")));
_FDT((fdt_property(fdt, "reg", mem_reg_property_nonrma,
sizeof(mem_reg_property_nonrma))));
_FDT((fdt_property(fdt, "reg", mem_reg_property,
sizeof(mem_reg_property))));
_FDT((fdt_property(fdt, "ibm,associativity", associativity,
sizeof(associativity))));
_FDT((fdt_end_node(fdt)));
}
/* RAM: Node 1 and beyond */
mem_start = node0_size;
for (i = 1; i < nb_numa_nodes; i++) {
mem_reg_property[0] = cpu_to_be64(mem_start);
mem_reg_property[1] = cpu_to_be64(node_mem[i]);
associativity[3] = associativity[4] = cpu_to_be32(i);
sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start);
_FDT((fdt_begin_node(fdt, mem_name)));
_FDT((fdt_property_string(fdt, "device_type", "memory")));
_FDT((fdt_property(fdt, "reg", mem_reg_property,
sizeof(mem_reg_property))));
_FDT((fdt_property(fdt, "ibm,associativity", associativity,
sizeof(associativity))));
_FDT((fdt_end_node(fdt)));
mem_start += node_mem[i];
}
/* cpus */
_FDT((fdt_begin_node(fdt, "cpus")));
@ -194,6 +270,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
modelname[i] = toupper(modelname[i]);
}
/* This is needed during FDT finalization */
spapr->cpu_model = g_strdup(modelname);
for (env = first_cpu; env != NULL; env = env->next_cpu) {
int index = env->cpu_index;
uint32_t servers_prop[smp_threads];
@ -280,6 +359,9 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
_FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas_prop,
sizeof(hypertas_prop))));
_FDT((fdt_property(fdt, "ibm,associativity-reference-points",
refpoints, sizeof(refpoints))));
_FDT((fdt_end_node(fdt)));
/* interrupt controller */
@ -351,6 +433,16 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
fprintf(stderr, "Couldn't set up RTAS device tree properties\n");
}
/* Advertise NUMA via ibm,associativity */
if (nb_numa_nodes > 1) {
ret = spapr_set_associativity(fdt, spapr);
if (ret < 0) {
fprintf(stderr, "Couldn't set up NUMA device tree properties\n");
}
}
spapr_populate_chosen_stdout(fdt, spapr->vio_bus);
_FDT((fdt_pack(fdt)));
cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));

View File

@ -21,6 +21,7 @@ typedef struct sPAPREnvironment {
target_ulong entry_point;
int next_irq;
int rtc_offset;
char *cpu_model;
} sPAPREnvironment;
#define H_SUCCESS 0

View File

@ -474,16 +474,6 @@ static target_ulong h_multicast_ctrl(CPUState *env, sPAPREnvironment *spapr,
return H_SUCCESS;
}
static void vlan_hcalls(VIOsPAPRBus *bus)
{
spapr_register_hypercall(H_REGISTER_LOGICAL_LAN, h_register_logical_lan);
spapr_register_hypercall(H_FREE_LOGICAL_LAN, h_free_logical_lan);
spapr_register_hypercall(H_SEND_LOGICAL_LAN, h_send_logical_lan);
spapr_register_hypercall(H_ADD_LOGICAL_LAN_BUFFER,
h_add_logical_lan_buffer);
spapr_register_hypercall(H_MULTICAST_CTRL, h_multicast_ctrl);
}
static VIOsPAPRDeviceInfo spapr_vlan = {
.init = spapr_vlan_init,
.devnode = spapr_vlan_devnode,
@ -491,7 +481,6 @@ static VIOsPAPRDeviceInfo spapr_vlan = {
.dt_type = "network",
.dt_compatible = "IBM,l-lan",
.signal_mask = 0x1,
.hcalls = vlan_hcalls,
.qdev.name = "spapr-vlan",
.qdev.size = sizeof(VIOsPAPRVLANDevice),
.qdev.props = (Property[]) {
@ -504,5 +493,11 @@ static VIOsPAPRDeviceInfo spapr_vlan = {
static void spapr_vlan_register(void)
{
spapr_vio_bus_register_withprop(&spapr_vlan);
spapr_register_hypercall(H_REGISTER_LOGICAL_LAN, h_register_logical_lan);
spapr_register_hypercall(H_FREE_LOGICAL_LAN, h_free_logical_lan);
spapr_register_hypercall(H_SEND_LOGICAL_LAN, h_send_logical_lan);
spapr_register_hypercall(H_ADD_LOGICAL_LAN_BUFFER,
h_add_logical_lan_buffer);
spapr_register_hypercall(H_MULTICAST_CTRL, h_multicast_ctrl);
}
device_init(spapr_vlan_register);

View File

@ -621,11 +621,43 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
rtas_st(rets, 0, 0);
}
static int spapr_vio_check_reg(VIOsPAPRDevice *sdev, VIOsPAPRDeviceInfo *info)
{
VIOsPAPRDevice *other_sdev;
DeviceState *qdev;
VIOsPAPRBus *sbus;
sbus = DO_UPCAST(VIOsPAPRBus, bus, sdev->qdev.parent_bus);
/*
* Check two device aren't given clashing addresses by the user (or some
* other mechanism). We have to open code this because we have to check
* for matches with devices other than us.
*/
QTAILQ_FOREACH(qdev, &sbus->bus.children, sibling) {
other_sdev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
if (other_sdev != sdev && other_sdev->reg == sdev->reg) {
fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",
info->qdev.name, other_sdev->qdev.info->name, sdev->reg);
return -EEXIST;
}
}
return 0;
}
static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
{
VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
char *id;
int ret;
ret = spapr_vio_check_reg(dev, info);
if (ret) {
return ret;
}
/* Don't overwrite ids assigned on the command line */
if (!dev->qdev.id) {
@ -684,7 +716,6 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
VIOsPAPRBus *bus;
BusState *qbus;
DeviceState *dev;
DeviceInfo *qinfo;
/* Create bridge device */
dev = qdev_create(NULL, "spapr-vio-bridge");
@ -711,18 +742,6 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
spapr_rtas_register("ibm,set-tce-bypass", rtas_set_tce_bypass);
spapr_rtas_register("quiesce", rtas_quiesce);
for (qinfo = device_info_list; qinfo; qinfo = qinfo->next) {
VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
if (qinfo->bus_info != &spapr_vio_bus_info) {
continue;
}
if (info->hcalls) {
info->hcalls(bus);
}
}
return bus;
}
@ -749,21 +768,95 @@ static void spapr_vio_register_devices(void)
device_init(spapr_vio_register_devices)
#ifdef CONFIG_FDT
static int compare_reg(const void *p1, const void *p2)
{
VIOsPAPRDevice const *dev1, *dev2;
dev1 = (VIOsPAPRDevice *)*(DeviceState **)p1;
dev2 = (VIOsPAPRDevice *)*(DeviceState **)p2;
if (dev1->reg < dev2->reg) {
return -1;
}
if (dev1->reg == dev2->reg) {
return 0;
}
/* dev1->reg > dev2->reg */
return 1;
}
int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
{
DeviceState *qdev;
int ret = 0;
DeviceState *qdev, **qdevs;
int i, num, ret = 0;
/* Count qdevs on the bus list */
num = 0;
QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
num++;
}
/* Copy out into an array of pointers */
qdevs = g_malloc(sizeof(qdev) * num);
num = 0;
QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
qdevs[num++] = qdev;
}
/* Sort the array */
qsort(qdevs, num, sizeof(qdev), compare_reg);
/* Hack alert. Give the devices to libfdt in reverse order, we happen
* to know that will mean they are in forward order in the tree. */
for (i = num - 1; i >= 0; i--) {
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)(qdevs[i]);
ret = vio_make_devnode(dev, fdt);
if (ret < 0) {
return ret;
goto out;
}
}
return 0;
ret = 0;
out:
free(qdevs);
return ret;
}
int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus)
{
VIOsPAPRDevice *dev;
char *name, *path;
int ret, offset;
dev = spapr_vty_get_default(bus);
if (!dev)
return 0;
offset = fdt_path_offset(fdt, "/chosen");
if (offset < 0) {
return offset;
}
name = vio_format_dev_name(dev);
if (!name) {
return -ENOMEM;
}
if (asprintf(&path, "/vdevice/%s", name) < 0) {
path = NULL;
ret = -ENOMEM;
goto out;
}
ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path);
out:
free(name);
free(path);
return ret;
}
#endif /* CONFIG_FDT */

View File

@ -75,7 +75,6 @@ typedef struct {
const char *dt_name, *dt_type, *dt_compatible;
target_ulong signal_mask;
int (*init)(VIOsPAPRDevice *dev);
void (*hcalls)(VIOsPAPRBus *bus);
int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
} VIOsPAPRDeviceInfo;
@ -83,6 +82,7 @@ extern VIOsPAPRBus *spapr_vio_bus_init(void);
extern VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg);
extern void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info);
extern int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt);
extern int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus);
extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode);
@ -108,6 +108,8 @@ void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev);
void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd);
void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg);
VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus);
int spapr_tce_set_bypass(uint32_t unit, uint32_t enable);
void spapr_vio_quiesce(void);

View File

@ -135,18 +135,11 @@ void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev)
qdev_init_nofail(dev);
}
static void vty_hcalls(VIOsPAPRBus *bus)
{
spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
}
static VIOsPAPRDeviceInfo spapr_vty = {
.init = spapr_vty_init,
.dt_name = "vty",
.dt_type = "serial",
.dt_compatible = "hvterm1",
.hcalls = vty_hcalls,
.qdev.name = "spapr-vty",
.qdev.size = sizeof(VIOsPAPRVTYDevice),
.qdev.props = (Property[]) {
@ -156,24 +149,53 @@ static VIOsPAPRDeviceInfo spapr_vty = {
},
};
VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
{
VIOsPAPRDevice *sdev, *selected;
DeviceState *iter;
/*
* To avoid the console bouncing around we want one VTY to be
* the "default". We haven't really got anything to go on, so
* arbitrarily choose the one with the lowest reg value.
*/
selected = NULL;
QTAILQ_FOREACH(iter, &bus->bus.children, sibling) {
/* Only look at VTY devices */
if (iter->info != &spapr_vty.qdev) {
continue;
}
sdev = DO_UPCAST(VIOsPAPRDevice, qdev, iter);
/* First VTY we've found, so it is selected for now */
if (!selected) {
selected = sdev;
continue;
}
/* Choose VTY with lowest reg value */
if (sdev->reg < selected->reg) {
selected = sdev;
}
}
return selected;
}
static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
{
VIOsPAPRDevice *sdev;
sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
if (!sdev && reg == 0) {
DeviceState *qdev;
/* Hack for kernel early debug, which always specifies reg==0.
* We search all VIO devices, and grab the first available vty
* device. This attempts to mimic existing PowerVM behaviour
* We search all VIO devices, and grab the vty with the lowest
* reg. This attempts to mimic existing PowerVM behaviour
* (early debug does work there, despite having no vty with
* reg==0. */
QTAILQ_FOREACH(qdev, &spapr->vio_bus->bus.children, sibling) {
if (qdev->info == &spapr_vty.qdev) {
return DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
}
}
return spapr_vty_get_default(spapr->vio_bus);
}
return sdev;
@ -182,5 +204,7 @@ static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
static void spapr_vty_register(void)
{
spapr_vio_bus_register_withprop(&spapr_vty);
spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
}
device_init(spapr_vty_register);

View File

@ -1545,12 +1545,40 @@ static void mmubooke206_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
}
}
#if defined(TARGET_PPC64)
static void mmubooks_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
CPUState *env)
{
int i;
uint64_t slbe, slbv;
cpu_synchronize_state(env);
cpu_fprintf(f, "SLB\tESID\t\t\tVSID\n");
for (i = 0; i < env->slb_nr; i++) {
slbe = env->slb[i].esid;
slbv = env->slb[i].vsid;
if (slbe == 0 && slbv == 0) {
continue;
}
cpu_fprintf(f, "%d\t0x%016" PRIx64 "\t0x%016" PRIx64 "\n",
i, slbe, slbv);
}
}
#endif
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
{
switch (env->mmu_model) {
case POWERPC_MMU_BOOKE206:
mmubooke206_dump_mmu(f, cpu_fprintf, env);
break;
#if defined(TARGET_PPC64)
case POWERPC_MMU_64B:
case POWERPC_MMU_2_06:
mmubooks_dump_mmu(f, cpu_fprintf, env);
break;
#endif
default:
cpu_fprintf(f, "%s: unimplemented\n", __func__);
}

View File

@ -504,7 +504,7 @@ void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
int kvm_arch_process_async_events(CPUState *env)
{
return 0;
return env->halted;
}
static int kvmppc_handle_halt(CPUState *env)

View File

@ -2,6 +2,7 @@
* PowerPC CPU initialization for qemu.
*
* Copyright (c) 2003-2007 Jocelyn Mayer
* Copyright 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
@ -4399,6 +4400,33 @@ static void init_proc_e300 (CPUPPCState *env)
#define check_pow_e500v2 check_pow_hid0
#define init_proc_e500v2 init_proc_e500v2
/* e500mc core */
#define POWERPC_INSNS_e500mc (PPC_INSNS_BASE | PPC_ISEL | \
PPC_WRTEE | PPC_RFDI | PPC_RFMCI | \
PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \
PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \
PPC_FLOAT | PPC_FLOAT_FRES | \
PPC_FLOAT_FRSQRTE | PPC_FLOAT_FSEL | \
PPC_FLOAT_STFIWX | PPC_WAIT | \
PPC_MEM_TLBSYNC | PPC_TLBIVAX)
#define POWERPC_INSNS2_e500mc (PPC2_BOOKE206)
#define POWERPC_MSRM_e500mc (0x000000001402FB36ULL)
#define POWERPC_MMU_e500mc (POWERPC_MMU_BOOKE206)
#define POWERPC_EXCP_e500mc (POWERPC_EXCP_BOOKE)
#define POWERPC_INPUT_e500mc (PPC_FLAGS_INPUT_BookE)
/* Fixme: figure out the correct flag for e500mc */
#define POWERPC_BFDM_e500mc (bfd_mach_ppc_e500)
#define POWERPC_FLAG_e500mc (POWERPC_FLAG_CE | POWERPC_FLAG_DE | \
POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
#define check_pow_e500mc check_pow_none
#define init_proc_e500mc init_proc_e500mc
enum fsl_e500_version {
fsl_e500v1,
fsl_e500v2,
fsl_e500mc,
};
static void init_proc_e500 (CPUPPCState *env, int version)
{
uint32_t tlbncfg[2];
@ -4430,15 +4458,26 @@ static void init_proc_e500 (CPUPPCState *env, int version)
env->nb_ways = 2;
env->id_tlbs = 0;
switch (version) {
case 1:
case fsl_e500v1:
/* e500v1 */
tlbncfg[0] = gen_tlbncfg(2, 1, 1, 0, 256);
tlbncfg[1] = gen_tlbncfg(16, 1, 9, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16);
env->dcache_line_size = 32;
env->icache_line_size = 32;
break;
case 2:
case fsl_e500v2:
/* e500v2 */
tlbncfg[0] = gen_tlbncfg(4, 1, 1, 0, 512);
tlbncfg[1] = gen_tlbncfg(16, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16);
env->dcache_line_size = 32;
env->icache_line_size = 32;
break;
case fsl_e500mc:
/* e500mc */
tlbncfg[0] = gen_tlbncfg(4, 1, 1, 0, 512);
tlbncfg[1] = gen_tlbncfg(64, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 64);
env->dcache_line_size = 64;
env->icache_line_size = 64;
break;
default:
cpu_abort(env, "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]);
@ -4522,20 +4561,23 @@ static void init_proc_e500 (CPUPPCState *env, int version)
#endif
init_excp_e200(env);
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
ppce500_irq_init(env);
}
static void init_proc_e500v1(CPUPPCState *env)
{
init_proc_e500(env, 1);
init_proc_e500(env, fsl_e500v1);
}
static void init_proc_e500v2(CPUPPCState *env)
{
init_proc_e500(env, 2);
init_proc_e500(env, fsl_e500v2);
}
static void init_proc_e500mc(CPUPPCState *env)
{
init_proc_e500(env, fsl_e500mc);
}
/* Non-embedded PowerPC */
@ -7070,6 +7112,7 @@ enum {
CPU_POWERPC_e500v2_v21 = 0x80210021,
CPU_POWERPC_e500v2_v22 = 0x80210022,
CPU_POWERPC_e500v2_v30 = 0x80210030,
CPU_POWERPC_e500mc = 0x80230020,
/* MPC85xx microcontrollers */
#define CPU_POWERPC_MPC8533 CPU_POWERPC_MPC8533_v11
#define CPU_POWERPC_MPC8533_v10 CPU_POWERPC_e500v2_v21
@ -8471,6 +8514,7 @@ static const ppc_def_t ppc_defs[] = {
POWERPC_DEF("e500v2_v22", CPU_POWERPC_e500v2_v22, e500v2),
/* PowerPC e500v2 v3.0 core */
POWERPC_DEF("e500v2_v30", CPU_POWERPC_e500v2_v30, e500v2),
POWERPC_DEF("e500mc", CPU_POWERPC_e500mc, e500mc),
/* PowerPC e500 microcontrollers */
/* MPC8533 */
POWERPC_DEF_SVR("MPC8533",