mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-4.0-20190204' into staging
ppc patch queue 2019-02-04 Here's the next batch of ppc target and spapr related changes. Highlights are: * A number of endianness handling cleanups from Mark Cave-Ayland * Updated Mac VGA driver * Updated SLOF image * Some XIVE cleanups and small fixes * ppc4xx cleanups and fixes from BALATON Zoltan There are a few chances not technically in the ppc target code: * Several MAINTAINERS updates * Fixes for unmapping of hugepages on power hosts The latter is included because it's primarily of interest for ppc KVM setups. # gpg: Signature made Mon 04 Feb 2019 07:52:26 GMT # gpg: using RSA key 75F46586AE61A66CC44E87DC6C38CACA20D9B392 # gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" [full] # gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" [full] # gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" [full] # gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" [unknown] # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dgibson/tags/ppc-for-4.0-20190204: (37 commits) mmap-alloc: fix hugetlbfs misaligned length in ppc64 mmap-alloc: unfold qemu_ram_mmap() hw/ppc: Don't include m48t59.h if it is not necessary spapr_pci: Fix endianness in assigned-addresses property target/ppc: remove various HOST_WORDS_BIGENDIAN hacks in int_helper.c target/ppc: remove ROTRu32 and ROTRu64 macros from int_helper.c target/ppc: simplify VEXT_SIGNED macro in int_helper.c target/ppc: eliminate use of EL_IDX macros from int_helper.c target/ppc: eliminate use of HI_IDX and LO_IDX macros from int_helper.c target/ppc: rework vmul{e,o}{s,u}{b,h,w} instructions to use Vsr* macros target/ppc: rework vmrg{l,h}{b,h,w} instructions to use Vsr* macros hw/ppc/spapr: Add support for "-vga cirrus" QemuMacDrivers: update qemu_vga.ndrv to 90c488d built from submodule MAINTAINERS: add myself as maintainer for Mac Old World and New World machines spapr: Drop unused parameters from fdt building helper MAINTAINERS: Merge the two e500 sections MAINTAINERS: XIVE is an interrupt controller, not a machine hw/ppc: Move ppc40x_*reset() functions from ppc405_uc.c to ppc.c ppc: remove the interrupt presenters from under PowerPCCPU target/ppc: implement complete set of Vsr* macros ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+15
-20
@@ -960,9 +960,10 @@ e500
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/ppc/e500.[hc]
|
||||
F: hw/ppc/e500plat.c
|
||||
F: hw/ppc/e500*
|
||||
F: hw/gpio/mpc8xxx.c
|
||||
F: hw/net/fsl_etsec/
|
||||
F: hw/pci-host/ppce500.c
|
||||
F: include/hw/ppc/ppc_e500.h
|
||||
F: include/hw/pci-host/ppce500.h
|
||||
F: pc-bios/u-boot.e500
|
||||
@@ -975,7 +976,8 @@ F: hw/ppc/mpc8544ds.c
|
||||
F: hw/ppc/mpc8544_guts.c
|
||||
|
||||
New World (mac99)
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/ppc/mac_newworld.c
|
||||
@@ -993,7 +995,8 @@ F: include/hw/input/adb*
|
||||
F: pc-bios/qemu_vga.ndrv
|
||||
|
||||
Old World (g3beige)
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/ppc/mac_oldworld.c
|
||||
@@ -1041,14 +1044,6 @@ F: tests/libqos/*spapr*
|
||||
F: tests/rtas*
|
||||
F: tests/libqos/rtas*
|
||||
|
||||
XIVE
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Cédric Le Goater <clg@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Supported
|
||||
F: hw/*/*xive*
|
||||
F: include/hw/*/*xive*
|
||||
|
||||
virtex_ml507
|
||||
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
L: qemu-ppc@nongnu.org
|
||||
@@ -1327,14 +1322,6 @@ F: hw/i2c/ppc4xx_i2c.c
|
||||
F: include/hw/ppc/ppc4xx.h
|
||||
F: include/hw/i2c/ppc4xx_i2c.h
|
||||
|
||||
ppce500
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/ppc/e500*
|
||||
F: hw/pci-host/ppce500.c
|
||||
F: hw/net/fsl_etsec/
|
||||
|
||||
Character devices
|
||||
M: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
R: Paolo Bonzini <pbonzini@redhat.com>
|
||||
@@ -1648,6 +1635,14 @@ F: tests/libqos/fw_cfg.c
|
||||
F: tests/fw_cfg-test.c
|
||||
T: git https://github.com/philmd/qemu.git fw_cfg-next
|
||||
|
||||
XIVE
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Cédric Le Goater <clg@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Supported
|
||||
F: hw/*/*xive*
|
||||
F: include/hw/*/*xive*
|
||||
|
||||
Subsystems
|
||||
----------
|
||||
Audio
|
||||
|
||||
@@ -1873,7 +1873,7 @@ static void *file_ram_alloc(RAMBlock *block,
|
||||
if (mem_prealloc) {
|
||||
os_mem_prealloc(fd, area, memory, smp_cpus, errp);
|
||||
if (errp && *errp) {
|
||||
qemu_ram_munmap(area, memory);
|
||||
qemu_ram_munmap(fd, area, memory);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -2394,7 +2394,7 @@ static void reclaim_ramblock(RAMBlock *block)
|
||||
xen_invalidate_map_cache_entry(block->host);
|
||||
#ifndef _WIN32
|
||||
} else if (block->fd >= 0) {
|
||||
qemu_ram_munmap(block->host, block->max_length);
|
||||
qemu_ram_munmap(block->fd, block->host, block->max_length);
|
||||
close(block->fd);
|
||||
#endif
|
||||
} else {
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/i2c/i2c.h"
|
||||
#include "hw/i2c/smbus.h"
|
||||
@@ -162,3 +164,130 @@ void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom,
|
||||
smbus_eeprom_init_one(smbus, 0x50 + i, eeprom_buf + (i * 256));
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate SDRAM SPD EEPROM data describing a module of type and size */
|
||||
uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t ram_size,
|
||||
Error **errp)
|
||||
{
|
||||
uint8_t *spd;
|
||||
uint8_t nbanks;
|
||||
uint16_t density;
|
||||
uint32_t size;
|
||||
int min_log2, max_log2, sz_log2;
|
||||
int i;
|
||||
|
||||
switch (type) {
|
||||
case SDR:
|
||||
min_log2 = 2;
|
||||
max_log2 = 9;
|
||||
break;
|
||||
case DDR:
|
||||
min_log2 = 5;
|
||||
max_log2 = 12;
|
||||
break;
|
||||
case DDR2:
|
||||
min_log2 = 7;
|
||||
max_log2 = 14;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
size = ram_size >> 20; /* work in terms of megabytes */
|
||||
if (size < 4) {
|
||||
error_setg(errp, "SDRAM size is too small");
|
||||
return NULL;
|
||||
}
|
||||
sz_log2 = 31 - clz32(size);
|
||||
size = 1U << sz_log2;
|
||||
if (ram_size > size * MiB) {
|
||||
error_setg(errp, "SDRAM size 0x"RAM_ADDR_FMT" is not a power of 2, "
|
||||
"truncating to %u MB", ram_size, size);
|
||||
}
|
||||
if (sz_log2 < min_log2) {
|
||||
error_setg(errp,
|
||||
"Memory size is too small for SDRAM type, adjusting type");
|
||||
if (size >= 32) {
|
||||
type = DDR;
|
||||
min_log2 = 5;
|
||||
max_log2 = 12;
|
||||
} else {
|
||||
type = SDR;
|
||||
min_log2 = 2;
|
||||
max_log2 = 9;
|
||||
}
|
||||
}
|
||||
|
||||
nbanks = 1;
|
||||
while (sz_log2 > max_log2 && nbanks < 8) {
|
||||
sz_log2--;
|
||||
nbanks++;
|
||||
}
|
||||
|
||||
if (size > (1ULL << sz_log2) * nbanks) {
|
||||
error_setg(errp, "Memory size is too big for SDRAM, truncating");
|
||||
}
|
||||
|
||||
/* split to 2 banks if possible to avoid a bug in MIPS Malta firmware */
|
||||
if (nbanks == 1 && sz_log2 > min_log2) {
|
||||
sz_log2--;
|
||||
nbanks++;
|
||||
}
|
||||
|
||||
density = 1ULL << (sz_log2 - 2);
|
||||
switch (type) {
|
||||
case DDR2:
|
||||
density = (density & 0xe0) | (density >> 8 & 0x1f);
|
||||
break;
|
||||
case DDR:
|
||||
density = (density & 0xf8) | (density >> 8 & 0x07);
|
||||
break;
|
||||
case SDR:
|
||||
default:
|
||||
density &= 0xff;
|
||||
break;
|
||||
}
|
||||
|
||||
spd = g_malloc0(256);
|
||||
spd[0] = 128; /* data bytes in EEPROM */
|
||||
spd[1] = 8; /* log2 size of EEPROM */
|
||||
spd[2] = type;
|
||||
spd[3] = 13; /* row address bits */
|
||||
spd[4] = 10; /* column address bits */
|
||||
spd[5] = (type == DDR2 ? nbanks - 1 : nbanks);
|
||||
spd[6] = 64; /* module data width */
|
||||
/* reserved / data width high */
|
||||
spd[8] = 4; /* interface voltage level */
|
||||
spd[9] = 0x25; /* highest CAS latency */
|
||||
spd[10] = 1; /* access time */
|
||||
/* DIMM configuration 0 = non-ECC */
|
||||
spd[12] = 0x82; /* refresh requirements */
|
||||
spd[13] = 8; /* primary SDRAM width */
|
||||
/* ECC SDRAM width */
|
||||
spd[15] = (type == DDR2 ? 0 : 1); /* reserved / delay for random col rd */
|
||||
spd[16] = 12; /* burst lengths supported */
|
||||
spd[17] = 4; /* banks per SDRAM device */
|
||||
spd[18] = 12; /* ~CAS latencies supported */
|
||||
spd[19] = (type == DDR2 ? 0 : 1); /* reserved / ~CS latencies supported */
|
||||
spd[20] = 2; /* DIMM type / ~WE latencies */
|
||||
/* module features */
|
||||
/* memory chip features */
|
||||
spd[23] = 0x12; /* clock cycle time @ medium CAS latency */
|
||||
/* data access time */
|
||||
/* clock cycle time @ short CAS latency */
|
||||
/* data access time */
|
||||
spd[27] = 20; /* min. row precharge time */
|
||||
spd[28] = 15; /* min. row active row delay */
|
||||
spd[29] = 20; /* min. ~RAS to ~CAS delay */
|
||||
spd[30] = 45; /* min. active to precharge time */
|
||||
spd[31] = density;
|
||||
spd[32] = 20; /* addr/cmd setup time */
|
||||
spd[33] = 8; /* addr/cmd hold time */
|
||||
spd[34] = 20; /* data input setup time */
|
||||
spd[35] = 8; /* data input hold time */
|
||||
|
||||
/* checksum */
|
||||
for (i = 0; i < 63; i++) {
|
||||
spd[63] += spd[i];
|
||||
}
|
||||
return spd;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "monitor/monitor.h"
|
||||
#include "hw/ppc/fdt.h"
|
||||
#include "hw/ppc/spapr.h"
|
||||
#include "hw/ppc/spapr_cpu_core.h"
|
||||
#include "hw/ppc/spapr_xive.h"
|
||||
#include "hw/ppc/xive.h"
|
||||
#include "hw/ppc/xive_regs.h"
|
||||
@@ -390,6 +391,13 @@ static int spapr_xive_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk,
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static XiveTCTX *spapr_xive_get_tctx(XiveRouter *xrtr, CPUState *cs)
|
||||
{
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
|
||||
return spapr_cpu_state(cpu)->tctx;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_spapr_xive_end = {
|
||||
.name = TYPE_SPAPR_XIVE "/end",
|
||||
.version_id = 1,
|
||||
@@ -454,6 +462,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data)
|
||||
xrc->write_end = spapr_xive_write_end;
|
||||
xrc->get_nvt = spapr_xive_get_nvt;
|
||||
xrc->write_nvt = spapr_xive_write_nvt;
|
||||
xrc->get_tctx = spapr_xive_get_tctx;
|
||||
}
|
||||
|
||||
static const TypeInfo spapr_xive_info = {
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "trace.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/ppc/spapr.h"
|
||||
#include "hw/ppc/spapr_cpu_core.h"
|
||||
#include "hw/ppc/xics.h"
|
||||
#include "hw/ppc/xics_spapr.h"
|
||||
#include "hw/ppc/fdt.h"
|
||||
@@ -45,7 +46,7 @@ static target_ulong h_cppr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
{
|
||||
target_ulong cppr = args[0];
|
||||
|
||||
icp_set_cppr(cpu->icp, cppr);
|
||||
icp_set_cppr(spapr_cpu_state(cpu)->icp, cppr);
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -66,7 +67,7 @@ static target_ulong h_ipi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
static target_ulong h_xirr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
target_ulong opcode, target_ulong *args)
|
||||
{
|
||||
uint32_t xirr = icp_accept(cpu->icp);
|
||||
uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp);
|
||||
|
||||
args[0] = xirr;
|
||||
return H_SUCCESS;
|
||||
@@ -75,7 +76,7 @@ static target_ulong h_xirr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
target_ulong opcode, target_ulong *args)
|
||||
{
|
||||
uint32_t xirr = icp_accept(cpu->icp);
|
||||
uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp);
|
||||
|
||||
args[0] = xirr;
|
||||
args[1] = cpu_get_host_ticks();
|
||||
@@ -87,7 +88,7 @@ static target_ulong h_eoi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
{
|
||||
target_ulong xirr = args[0];
|
||||
|
||||
icp_eoi(cpu->icp, xirr);
|
||||
icp_eoi(spapr_cpu_state(cpu)->icp, xirr);
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -95,7 +96,7 @@ static target_ulong h_ipoll(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
target_ulong opcode, target_ulong *args)
|
||||
{
|
||||
uint32_t mfrr;
|
||||
uint32_t xirr = icp_ipoll(cpu->icp, &mfrr);
|
||||
uint32_t xirr = icp_ipoll(spapr_cpu_state(cpu)->icp, &mfrr);
|
||||
|
||||
args[0] = xirr;
|
||||
args[1] = mfrr;
|
||||
|
||||
+13
-9
@@ -320,8 +320,7 @@ static const XiveTmOp *xive_tm_find_op(hwaddr offset, unsigned size, bool write)
|
||||
static void xive_tm_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
PowerPCCPU *cpu = POWERPC_CPU(current_cpu);
|
||||
XiveTCTX *tctx = cpu->tctx;
|
||||
XiveTCTX *tctx = xive_router_get_tctx(XIVE_ROUTER(opaque), current_cpu);
|
||||
const XiveTmOp *xto;
|
||||
|
||||
/*
|
||||
@@ -359,8 +358,7 @@ static void xive_tm_write(void *opaque, hwaddr offset,
|
||||
|
||||
static uint64_t xive_tm_read(void *opaque, hwaddr offset, unsigned size)
|
||||
{
|
||||
PowerPCCPU *cpu = POWERPC_CPU(current_cpu);
|
||||
XiveTCTX *tctx = cpu->tctx;
|
||||
XiveTCTX *tctx = xive_router_get_tctx(XIVE_ROUTER(opaque), current_cpu);
|
||||
const XiveTmOp *xto;
|
||||
|
||||
/*
|
||||
@@ -1107,6 +1105,13 @@ int xive_router_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx,
|
||||
return xrc->write_nvt(xrtr, nvt_blk, nvt_idx, nvt, word_number);
|
||||
}
|
||||
|
||||
XiveTCTX *xive_router_get_tctx(XiveRouter *xrtr, CPUState *cs)
|
||||
{
|
||||
XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(xrtr);
|
||||
|
||||
return xrc->get_tctx(xrtr, cs);
|
||||
}
|
||||
|
||||
/*
|
||||
* The thread context register words are in big-endian format.
|
||||
*/
|
||||
@@ -1182,8 +1187,7 @@ static bool xive_presenter_match(XiveRouter *xrtr, uint8_t format,
|
||||
*/
|
||||
|
||||
CPU_FOREACH(cs) {
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
XiveTCTX *tctx = cpu->tctx;
|
||||
XiveTCTX *tctx = xive_router_get_tctx(xrtr, cs);
|
||||
int ring;
|
||||
|
||||
/*
|
||||
@@ -1576,9 +1580,9 @@ static const TypeInfo xive_end_source_info = {
|
||||
};
|
||||
|
||||
/*
|
||||
* XIVE Fabric
|
||||
* XIVE Notifier
|
||||
*/
|
||||
static const TypeInfo xive_fabric_info = {
|
||||
static const TypeInfo xive_notifier_info = {
|
||||
.name = TYPE_XIVE_NOTIFIER,
|
||||
.parent = TYPE_INTERFACE,
|
||||
.class_size = sizeof(XiveNotifierClass),
|
||||
@@ -1587,7 +1591,7 @@ static const TypeInfo xive_fabric_info = {
|
||||
static void xive_register_types(void)
|
||||
{
|
||||
type_register_static(&xive_source_info);
|
||||
type_register_static(&xive_fabric_info);
|
||||
type_register_static(&xive_notifier_info);
|
||||
type_register_static(&xive_router_info);
|
||||
type_register_static(&xive_end_source_info);
|
||||
type_register_static(&xive_tctx_info);
|
||||
|
||||
@@ -13,8 +13,7 @@ obj-y += spapr_pci_vfio.o
|
||||
endif
|
||||
obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
|
||||
# PowerPC 4xx boards
|
||||
obj-y += ppc4xx_devs.o ppc405_uc.o
|
||||
obj-$(CONFIG_PPC4XX) += ppc4xx_pci.o ppc405_boards.o
|
||||
obj-$(CONFIG_PPC4XX) += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
|
||||
obj-$(CONFIG_PPC4XX) += ppc440_bamboo.o ppc440_pcix.o ppc440_uc.o
|
||||
obj-$(CONFIG_SAM460EX) += sam460ex.o
|
||||
# PReP
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
#include "hw/ppc/mac.h"
|
||||
#include "hw/input/adb.h"
|
||||
#include "hw/ppc/mac_dbdma.h"
|
||||
#include "hw/timer/m48t59.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "net/net.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "hw/ppc/ppc.h"
|
||||
#include "mac.h"
|
||||
#include "hw/input/adb.h"
|
||||
#include "hw/timer/m48t59.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "net/net.h"
|
||||
#include "hw/isa/isa.h"
|
||||
|
||||
+4
-3
@@ -673,6 +673,7 @@ static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
Object *obj;
|
||||
PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
|
||||
|
||||
obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()),
|
||||
&local_err);
|
||||
@@ -681,7 +682,7 @@ static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
|
||||
return;
|
||||
}
|
||||
|
||||
cpu->icp = ICP(obj);
|
||||
pnv_cpu->icp = ICP(obj);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1099,7 +1100,7 @@ static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
|
||||
|
||||
return cpu ? cpu->icp : NULL;
|
||||
return cpu ? pnv_cpu_state(cpu)->icp : NULL;
|
||||
}
|
||||
|
||||
static void pnv_pic_print_info(InterruptStatsProvider *obj,
|
||||
@@ -1112,7 +1113,7 @@ static void pnv_pic_print_info(InterruptStatsProvider *obj,
|
||||
CPU_FOREACH(cs) {
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
|
||||
icp_pic_print_info(cpu->icp, mon);
|
||||
icp_pic_print_info(pnv_cpu_state(cpu)->icp, mon);
|
||||
}
|
||||
|
||||
for (i = 0; i < pnv->num_chips; i++) {
|
||||
|
||||
+11
-1
@@ -155,7 +155,10 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
pc->threads = g_new(PowerPCCPU *, cc->nr_threads);
|
||||
for (i = 0; i < cc->nr_threads; i++) {
|
||||
PowerPCCPU *cpu;
|
||||
|
||||
obj = object_new(typename);
|
||||
cpu = POWERPC_CPU(obj);
|
||||
|
||||
pc->threads[i] = POWERPC_CPU(obj);
|
||||
|
||||
@@ -163,6 +166,9 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
|
||||
object_property_add_child(OBJECT(pc), name, obj, &error_abort);
|
||||
object_property_add_alias(obj, "core-pir", OBJECT(pc),
|
||||
"pir", &error_abort);
|
||||
|
||||
cpu->machine_data = g_new0(PnvCPUState, 1);
|
||||
|
||||
object_unref(obj);
|
||||
}
|
||||
|
||||
@@ -189,9 +195,13 @@ err:
|
||||
|
||||
static void pnv_unrealize_vcpu(PowerPCCPU *cpu)
|
||||
{
|
||||
PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
|
||||
|
||||
qemu_unregister_reset(pnv_cpu_reset, cpu);
|
||||
object_unparent(OBJECT(cpu->icp));
|
||||
object_unparent(OBJECT(pnv_cpu_state(cpu)->icp));
|
||||
cpu_remove_sync(CPU(cpu));
|
||||
cpu->machine_data = NULL;
|
||||
g_free(pnv_cpu);
|
||||
object_unparent(OBJECT(cpu));
|
||||
}
|
||||
|
||||
|
||||
+56
-2
@@ -30,10 +30,8 @@
|
||||
#include "qemu/timer.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "hw/timer/m48t59.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/loader.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "kvm_ppc.h"
|
||||
#include "trace.h"
|
||||
@@ -310,6 +308,62 @@ void ppcPOWER7_irq_init(PowerPCCPU *cpu)
|
||||
}
|
||||
#endif /* defined(TARGET_PPC64) */
|
||||
|
||||
void ppc40x_core_reset(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
target_ulong dbsr;
|
||||
|
||||
qemu_log_mask(CPU_LOG_RESET, "Reset PowerPC core\n");
|
||||
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_RESET);
|
||||
dbsr = env->spr[SPR_40x_DBSR];
|
||||
dbsr &= ~0x00000300;
|
||||
dbsr |= 0x00000100;
|
||||
env->spr[SPR_40x_DBSR] = dbsr;
|
||||
}
|
||||
|
||||
void ppc40x_chip_reset(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
target_ulong dbsr;
|
||||
|
||||
qemu_log_mask(CPU_LOG_RESET, "Reset PowerPC chip\n");
|
||||
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_RESET);
|
||||
/* XXX: TODO reset all internal peripherals */
|
||||
dbsr = env->spr[SPR_40x_DBSR];
|
||||
dbsr &= ~0x00000300;
|
||||
dbsr |= 0x00000200;
|
||||
env->spr[SPR_40x_DBSR] = dbsr;
|
||||
}
|
||||
|
||||
void ppc40x_system_reset(PowerPCCPU *cpu)
|
||||
{
|
||||
qemu_log_mask(CPU_LOG_RESET, "Reset PowerPC system\n");
|
||||
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
|
||||
}
|
||||
|
||||
void store_40x_dbcr0(CPUPPCState *env, uint32_t val)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
|
||||
switch ((val >> 28) & 0x3) {
|
||||
case 0x0:
|
||||
/* No action */
|
||||
break;
|
||||
case 0x1:
|
||||
/* Core reset */
|
||||
ppc40x_core_reset(cpu);
|
||||
break;
|
||||
case 0x2:
|
||||
/* Chip reset */
|
||||
ppc40x_chip_reset(cpu);
|
||||
break;
|
||||
case 0x3:
|
||||
/* System reset */
|
||||
ppc40x_system_reset(cpu);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* PowerPC 40x internal IRQ controller */
|
||||
static void ppc40x_set_irq(void *opaque, int pin, int level)
|
||||
{
|
||||
|
||||
@@ -1155,64 +1155,6 @@ static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5])
|
||||
qemu_register_reset(ppc4xx_gpt_reset, gpt);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* SPR */
|
||||
void ppc40x_core_reset(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
target_ulong dbsr;
|
||||
|
||||
printf("Reset PowerPC core\n");
|
||||
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_RESET);
|
||||
dbsr = env->spr[SPR_40x_DBSR];
|
||||
dbsr &= ~0x00000300;
|
||||
dbsr |= 0x00000100;
|
||||
env->spr[SPR_40x_DBSR] = dbsr;
|
||||
}
|
||||
|
||||
void ppc40x_chip_reset(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
target_ulong dbsr;
|
||||
|
||||
printf("Reset PowerPC chip\n");
|
||||
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_RESET);
|
||||
/* XXX: TODO reset all internal peripherals */
|
||||
dbsr = env->spr[SPR_40x_DBSR];
|
||||
dbsr &= ~0x00000300;
|
||||
dbsr |= 0x00000200;
|
||||
env->spr[SPR_40x_DBSR] = dbsr;
|
||||
}
|
||||
|
||||
void ppc40x_system_reset(PowerPCCPU *cpu)
|
||||
{
|
||||
printf("Reset PowerPC system\n");
|
||||
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
|
||||
}
|
||||
|
||||
void store_40x_dbcr0 (CPUPPCState *env, uint32_t val)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
|
||||
switch ((val >> 28) & 0x3) {
|
||||
case 0x0:
|
||||
/* No action */
|
||||
break;
|
||||
case 0x1:
|
||||
/* Core reset */
|
||||
ppc40x_core_reset(cpu);
|
||||
break;
|
||||
case 0x2:
|
||||
/* Chip reset */
|
||||
ppc40x_chip_reset(cpu);
|
||||
break;
|
||||
case 0x3:
|
||||
/* System reset */
|
||||
ppc40x_system_reset(cpu);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* PowerPC 405CR */
|
||||
enum {
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
#define PPC440EP_SDRAM_NR_BANKS 4
|
||||
|
||||
static const unsigned int ppc440ep_sdram_bank_sizes[] = {
|
||||
static const ram_addr_t ppc440ep_sdram_bank_sizes[] = {
|
||||
256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 0
|
||||
};
|
||||
|
||||
|
||||
+38
-38
@@ -2,7 +2,7 @@
|
||||
* QEMU PowerPC 440 embedded processors emulation
|
||||
*
|
||||
* Copyright (c) 2012 François Revol
|
||||
* Copyright (c) 2016-2018 BALATON Zoltan
|
||||
* Copyright (c) 2016-2019 BALATON Zoltan
|
||||
*
|
||||
* This work is licensed under the GNU GPL license version 2 or later.
|
||||
*
|
||||
@@ -481,7 +481,7 @@ void ppc4xx_sdr_init(CPUPPCState *env)
|
||||
|
||||
/*****************************************************************************/
|
||||
/* SDRAM controller */
|
||||
typedef struct ppc4xx_sdram_t {
|
||||
typedef struct ppc440_sdram_t {
|
||||
uint32_t addr;
|
||||
int nbanks;
|
||||
MemoryRegion containers[4]; /* used for clipping */
|
||||
@@ -489,7 +489,7 @@ typedef struct ppc4xx_sdram_t {
|
||||
hwaddr ram_bases[4];
|
||||
hwaddr ram_sizes[4];
|
||||
uint32_t bcr[4];
|
||||
} ppc4xx_sdram_t;
|
||||
} ppc440_sdram_t;
|
||||
|
||||
enum {
|
||||
SDRAM0_CFGADDR = 0x10,
|
||||
@@ -505,10 +505,6 @@ enum {
|
||||
SDRAM_PLBADDUHB = 0x50,
|
||||
};
|
||||
|
||||
/* XXX: TOFIX: some patches have made this code become inconsistent:
|
||||
* there are type inconsistencies, mixing hwaddr, target_ulong
|
||||
* and uint32_t
|
||||
*/
|
||||
static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
|
||||
{
|
||||
uint32_t bcr;
|
||||
@@ -538,11 +534,17 @@ static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
|
||||
case (1 * GiB):
|
||||
bcr = 0xe000;
|
||||
break;
|
||||
case (2 * GiB):
|
||||
bcr = 0xc000;
|
||||
break;
|
||||
case (4 * GiB):
|
||||
bcr = 0x8000;
|
||||
break;
|
||||
default:
|
||||
error_report("invalid RAM size " TARGET_FMT_plx, ram_size);
|
||||
return 0;
|
||||
}
|
||||
bcr |= ram_base & 0xFF800000;
|
||||
bcr |= ram_base >> 2 & 0xffe00000;
|
||||
bcr |= 1;
|
||||
|
||||
return bcr;
|
||||
@@ -550,12 +552,12 @@ static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
|
||||
|
||||
static inline hwaddr sdram_base(uint32_t bcr)
|
||||
{
|
||||
return bcr & 0xFF800000;
|
||||
return (bcr & 0xffe00000) << 2;
|
||||
}
|
||||
|
||||
static target_ulong sdram_size(uint32_t bcr)
|
||||
static uint64_t sdram_size(uint32_t bcr)
|
||||
{
|
||||
target_ulong size;
|
||||
uint64_t size;
|
||||
int sh;
|
||||
|
||||
sh = 1024 - ((bcr >> 6) & 0x3ff);
|
||||
@@ -564,50 +566,46 @@ static target_ulong sdram_size(uint32_t bcr)
|
||||
return size;
|
||||
}
|
||||
|
||||
static void sdram_set_bcr(ppc4xx_sdram_t *sdram,
|
||||
uint32_t *bcrp, uint32_t bcr, int enabled)
|
||||
static void sdram_set_bcr(ppc440_sdram_t *sdram, int i,
|
||||
uint32_t bcr, int enabled)
|
||||
{
|
||||
unsigned n = bcrp - sdram->bcr;
|
||||
|
||||
if (*bcrp & 1) {
|
||||
/* Unmap RAM */
|
||||
if (sdram->bcr[i] & 1) {
|
||||
/* First unmap RAM if enabled */
|
||||
memory_region_del_subregion(get_system_memory(),
|
||||
&sdram->containers[n]);
|
||||
memory_region_del_subregion(&sdram->containers[n],
|
||||
&sdram->ram_memories[n]);
|
||||
object_unparent(OBJECT(&sdram->containers[n]));
|
||||
&sdram->containers[i]);
|
||||
memory_region_del_subregion(&sdram->containers[i],
|
||||
&sdram->ram_memories[i]);
|
||||
object_unparent(OBJECT(&sdram->containers[i]));
|
||||
}
|
||||
*bcrp = bcr & 0xFFDEE001;
|
||||
sdram->bcr[i] = bcr & 0xffe0ffc1;
|
||||
if (enabled && (bcr & 1)) {
|
||||
memory_region_init(&sdram->containers[n], NULL, "sdram-containers",
|
||||
memory_region_init(&sdram->containers[i], NULL, "sdram-containers",
|
||||
sdram_size(bcr));
|
||||
memory_region_add_subregion(&sdram->containers[n], 0,
|
||||
&sdram->ram_memories[n]);
|
||||
memory_region_add_subregion(&sdram->containers[i], 0,
|
||||
&sdram->ram_memories[i]);
|
||||
memory_region_add_subregion(get_system_memory(),
|
||||
sdram_base(bcr),
|
||||
&sdram->containers[n]);
|
||||
&sdram->containers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void sdram_map_bcr(ppc4xx_sdram_t *sdram)
|
||||
static void sdram_map_bcr(ppc440_sdram_t *sdram)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sdram->nbanks; i++) {
|
||||
if (sdram->ram_sizes[i] != 0) {
|
||||
sdram_set_bcr(sdram,
|
||||
&sdram->bcr[i],
|
||||
sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
|
||||
1);
|
||||
sdram_set_bcr(sdram, i, sdram_bcr(sdram->ram_bases[i],
|
||||
sdram->ram_sizes[i]), 1);
|
||||
} else {
|
||||
sdram_set_bcr(sdram, &sdram->bcr[i], 0, 0);
|
||||
sdram_set_bcr(sdram, i, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t dcr_read_sdram(void *opaque, int dcrn)
|
||||
{
|
||||
ppc4xx_sdram_t *sdram = opaque;
|
||||
ppc440_sdram_t *sdram = opaque;
|
||||
uint32_t ret = 0;
|
||||
|
||||
switch (dcrn) {
|
||||
@@ -615,8 +613,10 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
|
||||
case SDRAM_R1BAS:
|
||||
case SDRAM_R2BAS:
|
||||
case SDRAM_R3BAS:
|
||||
ret = sdram_bcr(sdram->ram_bases[dcrn - SDRAM_R0BAS],
|
||||
sdram->ram_sizes[dcrn - SDRAM_R0BAS]);
|
||||
if (sdram->ram_sizes[dcrn - SDRAM_R0BAS]) {
|
||||
ret = sdram_bcr(sdram->ram_bases[dcrn - SDRAM_R0BAS],
|
||||
sdram->ram_sizes[dcrn - SDRAM_R0BAS]);
|
||||
}
|
||||
break;
|
||||
case SDRAM_CONF1HB:
|
||||
case SDRAM_CONF1LL:
|
||||
@@ -658,7 +658,7 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
|
||||
|
||||
static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
|
||||
{
|
||||
ppc4xx_sdram_t *sdram = opaque;
|
||||
ppc440_sdram_t *sdram = opaque;
|
||||
|
||||
switch (dcrn) {
|
||||
case SDRAM_R0BAS:
|
||||
@@ -689,7 +689,7 @@ static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
|
||||
|
||||
static void sdram_reset(void *opaque)
|
||||
{
|
||||
ppc4xx_sdram_t *sdram = opaque;
|
||||
ppc440_sdram_t *sdram = opaque;
|
||||
|
||||
sdram->addr = 0;
|
||||
}
|
||||
@@ -699,7 +699,7 @@ void ppc440_sdram_init(CPUPPCState *env, int nbanks,
|
||||
hwaddr *ram_bases, hwaddr *ram_sizes,
|
||||
int do_init)
|
||||
{
|
||||
ppc4xx_sdram_t *sdram;
|
||||
ppc440_sdram_t *sdram;
|
||||
|
||||
sdram = g_malloc0(sizeof(*sdram));
|
||||
sdram->nbanks = nbanks;
|
||||
|
||||
+22
-26
@@ -405,36 +405,34 @@ static target_ulong sdram_size (uint32_t bcr)
|
||||
return size;
|
||||
}
|
||||
|
||||
static void sdram_set_bcr(ppc4xx_sdram_t *sdram,
|
||||
uint32_t *bcrp, uint32_t bcr, int enabled)
|
||||
static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i,
|
||||
uint32_t bcr, int enabled)
|
||||
{
|
||||
unsigned n = bcrp - sdram->bcr;
|
||||
|
||||
if (*bcrp & 0x00000001) {
|
||||
if (sdram->bcr[i] & 0x00000001) {
|
||||
/* Unmap RAM */
|
||||
#ifdef DEBUG_SDRAM
|
||||
printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
|
||||
__func__, sdram_base(*bcrp), sdram_size(*bcrp));
|
||||
__func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
|
||||
#endif
|
||||
memory_region_del_subregion(get_system_memory(),
|
||||
&sdram->containers[n]);
|
||||
memory_region_del_subregion(&sdram->containers[n],
|
||||
&sdram->ram_memories[n]);
|
||||
object_unparent(OBJECT(&sdram->containers[n]));
|
||||
&sdram->containers[i]);
|
||||
memory_region_del_subregion(&sdram->containers[i],
|
||||
&sdram->ram_memories[i]);
|
||||
object_unparent(OBJECT(&sdram->containers[i]));
|
||||
}
|
||||
*bcrp = bcr & 0xFFDEE001;
|
||||
sdram->bcr[i] = bcr & 0xFFDEE001;
|
||||
if (enabled && (bcr & 0x00000001)) {
|
||||
#ifdef DEBUG_SDRAM
|
||||
printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
|
||||
__func__, sdram_base(bcr), sdram_size(bcr));
|
||||
#endif
|
||||
memory_region_init(&sdram->containers[n], NULL, "sdram-containers",
|
||||
memory_region_init(&sdram->containers[i], NULL, "sdram-containers",
|
||||
sdram_size(bcr));
|
||||
memory_region_add_subregion(&sdram->containers[n], 0,
|
||||
&sdram->ram_memories[n]);
|
||||
memory_region_add_subregion(&sdram->containers[i], 0,
|
||||
&sdram->ram_memories[i]);
|
||||
memory_region_add_subregion(get_system_memory(),
|
||||
sdram_base(bcr),
|
||||
&sdram->containers[n]);
|
||||
&sdram->containers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,12 +442,10 @@ static void sdram_map_bcr (ppc4xx_sdram_t *sdram)
|
||||
|
||||
for (i = 0; i < sdram->nbanks; i++) {
|
||||
if (sdram->ram_sizes[i] != 0) {
|
||||
sdram_set_bcr(sdram,
|
||||
&sdram->bcr[i],
|
||||
sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
|
||||
1);
|
||||
sdram_set_bcr(sdram, i, sdram_bcr(sdram->ram_bases[i],
|
||||
sdram->ram_sizes[i]), 1);
|
||||
} else {
|
||||
sdram_set_bcr(sdram, &sdram->bcr[i], 0x00000000, 0);
|
||||
sdram_set_bcr(sdram, i, 0x00000000, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -589,16 +585,16 @@ static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val)
|
||||
sdram->pmit = (val & 0xF8000000) | 0x07C00000;
|
||||
break;
|
||||
case 0x40: /* SDRAM_B0CR */
|
||||
sdram_set_bcr(sdram, &sdram->bcr[0], val, sdram->cfg & 0x80000000);
|
||||
sdram_set_bcr(sdram, 0, val, sdram->cfg & 0x80000000);
|
||||
break;
|
||||
case 0x44: /* SDRAM_B1CR */
|
||||
sdram_set_bcr(sdram, &sdram->bcr[1], val, sdram->cfg & 0x80000000);
|
||||
sdram_set_bcr(sdram, 1, val, sdram->cfg & 0x80000000);
|
||||
break;
|
||||
case 0x48: /* SDRAM_B2CR */
|
||||
sdram_set_bcr(sdram, &sdram->bcr[2], val, sdram->cfg & 0x80000000);
|
||||
sdram_set_bcr(sdram, 2, val, sdram->cfg & 0x80000000);
|
||||
break;
|
||||
case 0x4C: /* SDRAM_B3CR */
|
||||
sdram_set_bcr(sdram, &sdram->bcr[3], val, sdram->cfg & 0x80000000);
|
||||
sdram_set_bcr(sdram, 3, val, sdram->cfg & 0x80000000);
|
||||
break;
|
||||
case 0x80: /* SDRAM_TR */
|
||||
sdram->tr = val & 0x018FC01F;
|
||||
@@ -679,12 +675,12 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
|
||||
MemoryRegion ram_memories[],
|
||||
hwaddr ram_bases[],
|
||||
hwaddr ram_sizes[],
|
||||
const unsigned int sdram_bank_sizes[])
|
||||
const ram_addr_t sdram_bank_sizes[])
|
||||
{
|
||||
MemoryRegion *ram = g_malloc0(sizeof(*ram));
|
||||
ram_addr_t size_left = ram_size;
|
||||
ram_addr_t base = 0;
|
||||
unsigned int bank_size;
|
||||
ram_addr_t bank_size;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "hw/ppc/ppc.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/timer/m48t59.h"
|
||||
#include "qemu/log.h"
|
||||
#include "hw/loader.h"
|
||||
#include "kvm_ppc.h"
|
||||
|
||||
+25
-156
@@ -2,7 +2,7 @@
|
||||
* QEMU aCube Sam460ex board emulation
|
||||
*
|
||||
* Copyright (c) 2012 François Revol
|
||||
* Copyright (c) 2016-2018 BALATON Zoltan
|
||||
* Copyright (c) 2016-2019 BALATON Zoltan
|
||||
*
|
||||
* This file is derived from hw/ppc440_bamboo.c,
|
||||
* the copyright for that material belongs to the original owners.
|
||||
@@ -76,9 +76,11 @@
|
||||
#define UART_FREQ 11059200
|
||||
#define SDRAM_NR_BANKS 4
|
||||
|
||||
/* FIXME: See u-boot.git 8ac41e, also fix in ppc440_uc.c */
|
||||
static const unsigned int ppc460ex_sdram_bank_sizes[] = {
|
||||
1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 0
|
||||
/* The SoC could also handle 4 GiB but firmware does not work with that. */
|
||||
/* Maybe it overflows a signed 32 bit number somewhere? */
|
||||
static const ram_addr_t ppc460ex_sdram_bank_sizes[] = {
|
||||
2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * MiB,
|
||||
32 * MiB, 0
|
||||
};
|
||||
|
||||
struct boot_info {
|
||||
@@ -87,135 +89,6 @@ struct boot_info {
|
||||
uint32_t entry;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/* SPD eeprom content from mips_malta.c */
|
||||
|
||||
struct _eeprom24c0x_t {
|
||||
uint8_t tick;
|
||||
uint8_t address;
|
||||
uint8_t command;
|
||||
uint8_t ack;
|
||||
uint8_t scl;
|
||||
uint8_t sda;
|
||||
uint8_t data;
|
||||
uint8_t contents[256];
|
||||
};
|
||||
|
||||
typedef struct _eeprom24c0x_t eeprom24c0x_t;
|
||||
|
||||
static eeprom24c0x_t spd_eeprom = {
|
||||
.contents = {
|
||||
/* 00000000: */ 0x80, 0x08, 0xFF, 0x0D, 0x0A, 0xFF, 0x40, 0x00,
|
||||
/* 00000008: */ 0x04, 0x75, 0x54, 0x00, 0x82, 0x08, 0x00, 0x01,
|
||||
/* 00000010: */ 0x8F, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
|
||||
/* 00000018: */ 0x00, 0x00, 0x00, 0x14, 0x0F, 0x14, 0x2D, 0xFF,
|
||||
/* 00000020: */ 0x15, 0x08, 0x15, 0x08, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 00000028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 00000030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 00000038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xD0,
|
||||
/* 00000040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 00000048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 00000050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 00000058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 00000060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 00000068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 00000070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 00000078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xF4,
|
||||
},
|
||||
};
|
||||
|
||||
static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size)
|
||||
{
|
||||
enum { SDR = 0x4, DDR1 = 0x7, DDR2 = 0x8 } type;
|
||||
uint8_t *spd = spd_eeprom.contents;
|
||||
uint8_t nbanks = 0;
|
||||
uint16_t density = 0;
|
||||
int i;
|
||||
|
||||
/* work in terms of MB */
|
||||
ram_size /= MiB;
|
||||
|
||||
while ((ram_size >= 4) && (nbanks <= 2)) {
|
||||
int sz_log2 = MIN(31 - clz32(ram_size), 14);
|
||||
nbanks++;
|
||||
density |= 1 << (sz_log2 - 2);
|
||||
ram_size -= 1 << sz_log2;
|
||||
}
|
||||
|
||||
/* split to 2 banks if possible */
|
||||
if ((nbanks == 1) && (density > 1)) {
|
||||
nbanks++;
|
||||
density >>= 1;
|
||||
}
|
||||
|
||||
if (density & 0xff00) {
|
||||
density = (density & 0xe0) | ((density >> 8) & 0x1f);
|
||||
type = DDR2;
|
||||
} else if (!(density & 0x1f)) {
|
||||
type = DDR2;
|
||||
} else {
|
||||
type = SDR;
|
||||
}
|
||||
|
||||
if (ram_size) {
|
||||
warn_report("SPD cannot represent final " RAM_ADDR_FMT "MB"
|
||||
" of SDRAM", ram_size);
|
||||
}
|
||||
|
||||
/* fill in SPD memory information */
|
||||
spd[2] = type;
|
||||
spd[5] = nbanks;
|
||||
spd[31] = density;
|
||||
|
||||
/* XXX: this is totally random */
|
||||
spd[9] = 0x10; /* CAS tcyc */
|
||||
spd[18] = 0x20; /* CAS bit */
|
||||
spd[23] = 0x10; /* CAS tcyc */
|
||||
spd[25] = 0x10; /* CAS tcyc */
|
||||
|
||||
/* checksum */
|
||||
spd[63] = 0;
|
||||
for (i = 0; i < 63; i++) {
|
||||
spd[63] += spd[i];
|
||||
}
|
||||
|
||||
/* copy for SMBUS */
|
||||
memcpy(eeprom, spd, sizeof(spd_eeprom.contents));
|
||||
}
|
||||
|
||||
static void generate_eeprom_serial(uint8_t *eeprom)
|
||||
{
|
||||
int i, pos = 0;
|
||||
uint8_t mac[6] = { 0x00 };
|
||||
uint8_t sn[5] = { 0x01, 0x23, 0x45, 0x67, 0x89 };
|
||||
|
||||
/* version */
|
||||
eeprom[pos++] = 0x01;
|
||||
|
||||
/* count */
|
||||
eeprom[pos++] = 0x02;
|
||||
|
||||
/* MAC address */
|
||||
eeprom[pos++] = 0x01; /* MAC */
|
||||
eeprom[pos++] = 0x06; /* length */
|
||||
memcpy(&eeprom[pos], mac, sizeof(mac));
|
||||
pos += sizeof(mac);
|
||||
|
||||
/* serial number */
|
||||
eeprom[pos++] = 0x02; /* serial */
|
||||
eeprom[pos++] = 0x05; /* length */
|
||||
memcpy(&eeprom[pos], sn, sizeof(sn));
|
||||
pos += sizeof(sn);
|
||||
|
||||
/* checksum */
|
||||
eeprom[pos] = 0;
|
||||
for (i = 0; i < pos; i++) {
|
||||
eeprom[pos] += eeprom[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int sam460ex_load_uboot(void)
|
||||
{
|
||||
DriveInfo *dinfo;
|
||||
@@ -393,24 +266,23 @@ static void sam460ex_init(MachineState *machine)
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
MemoryRegion *isa = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *ram_memories = g_new(MemoryRegion, SDRAM_NR_BANKS);
|
||||
hwaddr ram_bases[SDRAM_NR_BANKS];
|
||||
hwaddr ram_sizes[SDRAM_NR_BANKS];
|
||||
hwaddr ram_bases[SDRAM_NR_BANKS] = {0};
|
||||
hwaddr ram_sizes[SDRAM_NR_BANKS] = {0};
|
||||
MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
|
||||
qemu_irq *irqs, *uic[4];
|
||||
PCIBus *pci_bus;
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
PPC4xxI2CState *i2c[2];
|
||||
I2CBus *i2c;
|
||||
hwaddr entry = UBOOT_ENTRY;
|
||||
hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
|
||||
target_long initrd_size = 0;
|
||||
DeviceState *dev;
|
||||
SysBusDevice *sbdev;
|
||||
int success;
|
||||
int i;
|
||||
struct boot_info *boot_info;
|
||||
const size_t smbus_eeprom_size = 8 * 256;
|
||||
uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size);
|
||||
uint8_t *spd_data;
|
||||
Error *err = NULL;
|
||||
int success;
|
||||
|
||||
cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
|
||||
env = &cpu->env;
|
||||
@@ -439,8 +311,6 @@ static void sam460ex_init(MachineState *machine)
|
||||
uic[3] = ppcuic_init(env, &uic[0][16], 0xf0, 0, 1);
|
||||
|
||||
/* SDRAM controller */
|
||||
memset(ram_bases, 0, sizeof(ram_bases));
|
||||
memset(ram_sizes, 0, sizeof(ram_sizes));
|
||||
/* put all RAM on first bank because board has one slot
|
||||
* and firmware only checks that */
|
||||
machine->ram_size = ppc4xx_sdram_adjust(machine->ram_size, 1,
|
||||
@@ -451,23 +321,22 @@ static void sam460ex_init(MachineState *machine)
|
||||
ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories,
|
||||
ram_bases, ram_sizes, 1);
|
||||
|
||||
/* generate SPD EEPROM data */
|
||||
for (i = 0; i < SDRAM_NR_BANKS; i++) {
|
||||
generate_eeprom_spd(&smbus_eeprom_buf[i * 256], ram_sizes[i]);
|
||||
}
|
||||
generate_eeprom_serial(&smbus_eeprom_buf[4 * 256]);
|
||||
generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]);
|
||||
|
||||
/* IIC controllers */
|
||||
/* IIC controllers and devices */
|
||||
dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]);
|
||||
i2c[0] = PPC4xx_I2C(dev);
|
||||
object_property_set_bool(OBJECT(dev), true, "realized", NULL);
|
||||
smbus_eeprom_init(i2c[0]->bus, 8, smbus_eeprom_buf, smbus_eeprom_size);
|
||||
g_free(smbus_eeprom_buf);
|
||||
i2c_create_slave(i2c[0]->bus, "m41t80", 0x68);
|
||||
i2c = PPC4xx_I2C(dev)->bus;
|
||||
/* SPD EEPROM on RAM module */
|
||||
spd_data = spd_data_generate(DDR2, ram_sizes[0], &err);
|
||||
if (err) {
|
||||
warn_report_err(err);
|
||||
}
|
||||
if (spd_data) {
|
||||
spd_data[20] = 4; /* SO-DIMM module */
|
||||
smbus_eeprom_init_one(i2c, 0x50, spd_data);
|
||||
}
|
||||
/* RTC */
|
||||
i2c_create_slave(i2c, "m41t80", 0x68);
|
||||
|
||||
dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]);
|
||||
i2c[1] = PPC4xx_I2C(dev);
|
||||
|
||||
/* External bus controller */
|
||||
ppc405_ebc_init(env);
|
||||
|
||||
+14
-9
@@ -1225,9 +1225,7 @@ static void spapr_dt_hypervisor(sPAPRMachineState *spapr, void *fdt)
|
||||
}
|
||||
}
|
||||
|
||||
static void *spapr_build_fdt(sPAPRMachineState *spapr,
|
||||
hwaddr rtas_addr,
|
||||
hwaddr rtas_size)
|
||||
static void *spapr_build_fdt(sPAPRMachineState *spapr)
|
||||
{
|
||||
MachineState *machine = MACHINE(spapr);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
@@ -1644,14 +1642,14 @@ static void spapr_machine_reset(void)
|
||||
|
||||
/*
|
||||
* We place the device tree and RTAS just below either the top of the RMA,
|
||||
* or just below 2GB, whichever is lowere, so that it can be
|
||||
* or just below 2GB, whichever is lower, so that it can be
|
||||
* processed with 32-bit real mode code if necessary
|
||||
*/
|
||||
rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR);
|
||||
rtas_addr = rtas_limit - RTAS_MAX_SIZE;
|
||||
fdt_addr = rtas_addr - FDT_MAX_SIZE;
|
||||
|
||||
fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size);
|
||||
fdt = spapr_build_fdt(spapr);
|
||||
|
||||
spapr_load_rtas(spapr, fdt, rtas_addr);
|
||||
|
||||
@@ -1717,6 +1715,7 @@ static bool spapr_vga_init(PCIBus *pci_bus, Error **errp)
|
||||
return true;
|
||||
case VGA_STD:
|
||||
case VGA_VIRTIO:
|
||||
case VGA_CIRRUS:
|
||||
return pci_vga_init(pci_bus) != NULL;
|
||||
default:
|
||||
error_setg(errp,
|
||||
@@ -2959,10 +2958,11 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus,
|
||||
if (spapr) {
|
||||
/*
|
||||
* Replace "channel@0/disk@0,0" with "disk@8000000000000000":
|
||||
* We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun
|
||||
* in the top 16 bits of the 64-bit LUN
|
||||
* In the top 16 bits of the 64-bit LUN, we use SRP luns of the form
|
||||
* 0x8000 | (target << 8) | (bus << 5) | lun
|
||||
* (see the "Logical unit addressing format" table in SAM5)
|
||||
*/
|
||||
unsigned id = 0x8000 | (d->id << 8) | d->lun;
|
||||
unsigned id = 0x8000 | (d->id << 8) | (d->channel << 5) | d->lun;
|
||||
return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),
|
||||
(uint64_t)id << 48);
|
||||
} else if (virtio) {
|
||||
@@ -3126,6 +3126,11 @@ static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
|
||||
{
|
||||
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
|
||||
|
||||
if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
|
||||
error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode");
|
||||
return;
|
||||
}
|
||||
|
||||
/* The legacy IRQ backend can not be set */
|
||||
if (strcmp(value, "xics") == 0) {
|
||||
spapr->irq = &spapr_irq_xics;
|
||||
@@ -3896,7 +3901,7 @@ static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id)
|
||||
{
|
||||
PowerPCCPU *cpu = spapr_find_cpu(vcpu_id);
|
||||
|
||||
return cpu ? cpu->icp : NULL;
|
||||
return cpu ? spapr_cpu_state(cpu)->icp : NULL;
|
||||
}
|
||||
|
||||
static void spapr_pic_print_info(InterruptStatsProvider *obj,
|
||||
|
||||
@@ -194,11 +194,11 @@ static void spapr_unrealize_vcpu(PowerPCCPU *cpu, sPAPRCPUCore *sc)
|
||||
vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data);
|
||||
}
|
||||
qemu_unregister_reset(spapr_cpu_reset, cpu);
|
||||
if (cpu->icp) {
|
||||
object_unparent(OBJECT(cpu->icp));
|
||||
if (spapr_cpu_state(cpu)->icp) {
|
||||
object_unparent(OBJECT(spapr_cpu_state(cpu)->icp));
|
||||
}
|
||||
if (cpu->tctx) {
|
||||
object_unparent(OBJECT(cpu->tctx));
|
||||
if (spapr_cpu_state(cpu)->tctx) {
|
||||
object_unparent(OBJECT(spapr_cpu_state(cpu)->tctx));
|
||||
}
|
||||
cpu_remove_sync(CPU(cpu));
|
||||
object_unparent(OBJECT(cpu));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user