1
0
mirror of https://gitlab.com/qemu-project/qemu synced 2024-07-09 04:27:12 +00:00

ppc patch queue for 2022-10-18:

This queue contains improvements in the e500 and ppc4xx boards, changes
 in the maintainership of the project, a new QMP/HMP command and bug
 fixes:
 
 - Cedric is stepping back from qemu-ppc maintainership;
 - ppc4xx_sdram: QOMification and clean ups;
 - e500: add new types of flash and clean ups;
 - QMP/HMP: introduce dumpdtb command;
 - spapr_pci, booke doorbell interrupt and xvcmp* bit fixes;
 
 The 'dumpdtb' implementation is also making changes to RISC-V files that
 were acked by Alistair Francis and are being included in this queue.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQQX6/+ZI9AYAK8oOBk82cqW3gMxZAUCY02qEgAKCRA82cqW3gMx
 ZIadAQCYY9f+NFrSJBm3z4JjUaP+GmbgEjibjZW05diyKwbqzQEAjE1KXFCcd40D
 3Brs2Dm4YruaJCwb68vswVQAYteXaQ8=
 =hl94
 -----END PGP SIGNATURE-----

Merge tag 'pull-ppc-20221017' of https://gitlab.com/danielhb/qemu into staging

ppc patch queue for 2022-10-18:

This queue contains improvements in the e500 and ppc4xx boards, changes
in the maintainership of the project, a new QMP/HMP command and bug
fixes:

- Cedric is stepping back from qemu-ppc maintainership;
- ppc4xx_sdram: QOMification and clean ups;
- e500: add new types of flash and clean ups;
- QMP/HMP: introduce dumpdtb command;
- spapr_pci, booke doorbell interrupt and xvcmp* bit fixes;

The 'dumpdtb' implementation is also making changes to RISC-V files that
were acked by Alistair Francis and are being included in this queue.

# -----BEGIN PGP SIGNATURE-----
#
# iHUEABYKAB0WIQQX6/+ZI9AYAK8oOBk82cqW3gMxZAUCY02qEgAKCRA82cqW3gMx
# ZIadAQCYY9f+NFrSJBm3z4JjUaP+GmbgEjibjZW05diyKwbqzQEAjE1KXFCcd40D
# 3Brs2Dm4YruaJCwb68vswVQAYteXaQ8=
# =hl94
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 17 Oct 2022 15:16:34 EDT
# gpg:                using EDDSA key 17EBFF9923D01800AF2838193CD9CA96DE033164
# gpg: Good signature from "Daniel Henrique Barboza <danielhb413@gmail.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 17EB FF99 23D0 1800 AF28  3819 3CD9 CA96 DE03 3164

* tag 'pull-ppc-20221017' of https://gitlab.com/danielhb/qemu: (38 commits)
  hw/riscv: set machine->fdt in spike_board_init()
  hw/riscv: set machine->fdt in sifive_u_machine_init()
  hw/ppc: set machine->fdt in spapr machine
  hw/ppc: set machine->fdt in pnv_reset()
  hw/ppc: set machine->fdt in pegasos2_machine_reset()
  hw/ppc: set machine->fdt in xilinx_load_device_tree()
  hw/ppc: set machine->fdt in sam460ex_load_device_tree()
  hw/ppc: set machine->fdt in bamboo_load_device_tree()
  hw/nios2: set machine->fdt in nios2_load_dtb()
  qmp/hmp, device_tree.c: introduce dumpdtb
  hw/ppc/spapr_pci.c: Use device_cold_reset() rather than device_legacy_reset()
  target/ppc: Fix xvcmp* clearing FI bit
  hw/ppc/e500: Remove if statement which is now always true
  hw/ppc/mpc8544ds: Add platform bus
  hw/ppc/mpc8544ds: Rename wrongly named method
  hw/ppc/e500: Reduce usage of sysbus API
  docs/system/ppc/ppce500: Add heading for networking chapter
  hw/gpio/meson: Introduce dedicated config switch for hw/gpio/mpc8xxx
  hw/ppc/meson: Allow e500 boards to be enabled separately
  ppc440_uc.c: Remove unneeded parenthesis
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2022-10-18 11:13:57 -04:00
commit 2c65091fd9
37 changed files with 586 additions and 367 deletions

View File

@ -267,8 +267,8 @@ F: hw/openrisc/
F: tests/tcg/openrisc/
PowerPC TCG CPUs
M: Cédric Le Goater <clg@kaod.org>
M: Daniel Henrique Barboza <danielhb413@gmail.com>
R: Cédric Le Goater <clg@kaod.org>
R: David Gibson <david@gibson.dropbear.id.au>
R: Greg Kurz <groug@kaod.org>
L: qemu-ppc@nongnu.org
@ -392,8 +392,8 @@ F: target/mips/kvm*
F: target/mips/sysemu/
PPC KVM CPUs
M: Cédric Le Goater <clg@kaod.org>
M: Daniel Henrique Barboza <danielhb413@gmail.com>
R: Cédric Le Goater <clg@kaod.org>
R: David Gibson <david@gibson.dropbear.id.au>
R: Greg Kurz <groug@kaod.org>
S: Maintained
@ -1365,8 +1365,8 @@ F: include/hw/rtc/m48t59.h
F: tests/avocado/ppc_prep_40p.py
sPAPR (pseries)
M: Cédric Le Goater <clg@kaod.org>
M: Daniel Henrique Barboza <danielhb413@gmail.com>
R: Cédric Le Goater <clg@kaod.org>
R: David Gibson <david@gibson.dropbear.id.au>
R: Greg Kurz <groug@kaod.org>
L: qemu-ppc@nongnu.org
@ -1387,7 +1387,7 @@ F: tests/avocado/ppc_pseries.py
PowerNV (Non-Virtualized)
M: Cédric Le Goater <clg@kaod.org>
L: qemu-ppc@nongnu.org
S: Maintained
S: Odd Fixes
F: docs/system/ppc/powernv.rst
F: hw/ppc/pnv*
F: hw/intc/pnv*
@ -2333,7 +2333,7 @@ T: git https://github.com/philmd/qemu.git fw_cfg-next
XIVE
M: Cédric Le Goater <clg@kaod.org>
L: qemu-ppc@nongnu.org
S: Supported
S: Odd Fixes
F: hw/*/*xive*
F: include/hw/*/*xive*
F: docs/*/*xive*

View File

@ -1,7 +1,8 @@
# Default configuration for ppc-softmmu
# For embedded PPCs:
CONFIG_E500=y
CONFIG_E500PLAT=y
CONFIG_MPC8544DS=y
CONFIG_PPC405=y
CONFIG_PPC440=y
CONFIG_VIRTEX=y

View File

@ -146,6 +146,9 @@ You can specify a real world SoC device that QEMU has built-in support but all
these SoCs are e500v2 based MPC85xx series, hence you cannot test anything
built for P4080 (e500mc), P5020 (e5500) and T2080 (e6500).
Networking
----------
By default a VirtIO standard PCI networking device is connected as an ethernet
interface at PCI address 0.1.0, but we can switch that to an e1000 NIC by:

View File

@ -1800,3 +1800,18 @@ ERST
.sub_table = hmp_info_cmds,
.flags = "p",
},
#if defined(CONFIG_FDT)
{
.name = "dumpdtb",
.args_type = "filename:F",
.params = "filename",
.help = "dump the FDT in dtb format to 'filename'",
.cmd = hmp_dumpdtb,
},
SRST
``dumpdtb`` *filename*
Dump the FDT in dtb format to *filename*.
ERST
#endif

View File

@ -8,6 +8,9 @@ config PL061
config GPIO_KEY
bool
config GPIO_MPC8XXX
bool
config GPIO_PWR
bool

View File

@ -1,5 +1,5 @@
softmmu_ss.add(when: 'CONFIG_E500', if_true: files('mpc8xxx.c'))
softmmu_ss.add(when: 'CONFIG_GPIO_KEY', if_true: files('gpio_key.c'))
softmmu_ss.add(when: 'CONFIG_GPIO_MPC8XXX', if_true: files('mpc8xxx.c'))
softmmu_ss.add(when: 'CONFIG_GPIO_PWR', if_true: files('gpio_pwr.c'))
softmmu_ss.add(when: 'CONFIG_MAX7310', if_true: files('max7310.c'))
softmmu_ss.add(when: 'CONFIG_PL061', if_true: files('pl061.c'))

View File

@ -43,6 +43,8 @@
#include "boot.h"
#include <libfdt.h>
#define NIOS2_MAGIC 0x534f494e
static struct nios2_boot_info {
@ -81,6 +83,7 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
static int nios2_load_dtb(struct nios2_boot_info bi, const uint32_t ramsize,
const char *kernel_cmdline, const char *dtb_filename)
{
MachineState *machine = MACHINE(qdev_get_machine());
int fdt_size;
void *fdt = NULL;
int r;
@ -113,7 +116,10 @@ static int nios2_load_dtb(struct nios2_boot_info bi, const uint32_t ramsize,
}
cpu_physical_memory_write(bi.fdt, fdt, fdt_size);
g_free(fdt);
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
machine->fdt = fdt;
return fdt_size;
}

View File

@ -1,5 +1,5 @@
nios2_ss = ss.source_set()
nios2_ss.add(files('boot.c'))
nios2_ss.add(files('boot.c'), fdt)
nios2_ss.add(when: 'CONFIG_NIOS2_10M50', if_true: files('10m50_devboard.c'))
nios2_ss.add(when: 'CONFIG_NIOS2_GENERIC_NOMMU', if_true: files('generic_nommu.c'))

View File

@ -124,6 +124,7 @@ config E500
imply AT24C
imply VIRTIO_PCI
select ETSEC
select GPIO_MPC8XXX
select OPENPIC
select PLATFORM_BUS
select PPCE500_PCI
@ -132,6 +133,14 @@ config E500
select FDT_PPC
select DS1338
config E500PLAT
bool
select E500
config MPC8544DS
bool
select E500
config VIRTEX
bool
select PPC4XX

View File

@ -1007,25 +1007,23 @@ void ppce500_init(MachineState *machine)
}
/* Platform Bus Device */
if (pmc->has_platform_bus) {
dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE);
dev->id = g_strdup(TYPE_PLATFORM_BUS_DEVICE);
qdev_prop_set_uint32(dev, "num_irqs", pmc->platform_bus_num_irqs);
qdev_prop_set_uint32(dev, "mmio_size", pmc->platform_bus_size);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
pms->pbus_dev = PLATFORM_BUS_DEVICE(dev);
dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE);
dev->id = g_strdup(TYPE_PLATFORM_BUS_DEVICE);
qdev_prop_set_uint32(dev, "num_irqs", pmc->platform_bus_num_irqs);
qdev_prop_set_uint32(dev, "mmio_size", pmc->platform_bus_size);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
pms->pbus_dev = PLATFORM_BUS_DEVICE(dev);
s = SYS_BUS_DEVICE(pms->pbus_dev);
for (i = 0; i < pmc->platform_bus_num_irqs; i++) {
int irqn = pmc->platform_bus_first_irq + i;
sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, irqn));
}
memory_region_add_subregion(address_space_mem,
pmc->platform_bus_base,
sysbus_mmio_get_region(s, 0));
s = SYS_BUS_DEVICE(pms->pbus_dev);
for (i = 0; i < pmc->platform_bus_num_irqs; i++) {
int irqn = pmc->platform_bus_first_irq + i;
sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, irqn));
}
memory_region_add_subregion(address_space_mem,
pmc->platform_bus_base,
&pms->pbus_dev->mmio);
/*
* Smart firmware defaults ahead!
*

View File

@ -27,7 +27,6 @@ struct PPCE500MachineClass {
int mpic_version;
bool has_mpc8xxx_gpio;
bool has_platform_bus;
hwaddr platform_bus_base;
hwaddr platform_bus_size;
int platform_bus_first_irq;

View File

@ -86,7 +86,6 @@ static void e500plat_machine_class_init(ObjectClass *oc, void *data)
pmc->fixup_devtree = e500plat_fixup_devtree;
pmc->mpic_version = OPENPIC_MODEL_FSL_MPIC_42;
pmc->has_mpc8xxx_gpio = true;
pmc->has_platform_bus = true;
pmc->platform_bus_base = 0xf00000000ULL;
pmc->platform_bus_size = 128 * MiB;
pmc->platform_bus_first_irq = 5;

View File

@ -71,12 +71,10 @@ ppc_ss.add(when: 'CONFIG_MAC_OLDWORLD', if_true: files('mac_oldworld.c'))
# NewWorld PowerMac
ppc_ss.add(when: 'CONFIG_MAC_NEWWORLD', if_true: files('mac_newworld.c'))
# e500
ppc_ss.add(when: 'CONFIG_E500PLAT', if_true: files('e500plat.c'))
ppc_ss.add(when: 'CONFIG_MPC8544DS', if_true: files('mpc8544ds.c'))
ppc_ss.add(when: 'CONFIG_E500', if_true: files(
'e500.c',
'mpc8544ds.c',
'e500plat.c'
))
ppc_ss.add(when: 'CONFIG_E500', if_true: files(
'mpc8544_guts.c',
'ppce500_spin.c'
))

View File

@ -14,6 +14,7 @@
#include "sysemu/device_tree.h"
#include "hw/ppc/openpic.h"
#include "qemu/error-report.h"
#include "qemu/units.h"
#include "cpu.h"
static void mpc8544ds_fixup_devtree(void *fdt)
@ -36,7 +37,7 @@ static void mpc8544ds_init(MachineState *machine)
ppce500_init(machine);
}
static void e500plat_machine_class_init(ObjectClass *oc, void *data)
static void mpc8544ds_machine_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
PPCE500MachineClass *pmc = PPCE500_MACHINE_CLASS(oc);
@ -45,6 +46,10 @@ static void e500plat_machine_class_init(ObjectClass *oc, void *data)
pmc->pci_nr_slots = 2;
pmc->fixup_devtree = mpc8544ds_fixup_devtree;
pmc->mpic_version = OPENPIC_MODEL_FSL_MPIC_20;
pmc->platform_bus_base = 0xFF800000ULL;
pmc->platform_bus_size = 8 * MiB;
pmc->platform_bus_first_irq = 5;
pmc->platform_bus_num_irqs = 10;
pmc->ccsrbar_base = 0xE0000000ULL;
pmc->pci_mmio_base = 0xC0000000ULL;
pmc->pci_mmio_bus_base = 0xC0000000ULL;
@ -63,7 +68,7 @@ static void e500plat_machine_class_init(ObjectClass *oc, void *data)
static const TypeInfo mpc8544ds_info = {
.name = TYPE_MPC8544DS_MACHINE,
.parent = TYPE_PPCE500_MACHINE,
.class_init = e500plat_machine_class_init,
.class_init = mpc8544ds_machine_class_init,
};
static void mpc8544ds_register_types(void)

View File

@ -331,6 +331,10 @@ static void pegasos2_machine_reset(MachineState *machine)
vof_build_dt(fdt, pm->vof);
vof_client_open_store(fdt, pm->vof, "/chosen", "stdout", "/failsafe");
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
machine->fdt = fdt;
pm->cpu->vhyp = PPC_VIRTUAL_HYPERVISOR(machine);
}

View File

@ -678,7 +678,13 @@ static void pnv_reset(MachineState *machine)
qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
g_free(fdt);
/*
* Set machine->fdt for 'dumpdtb' QMP/HMP command. Free
* the existing machine->fdt to avoid leaking it during
* a reset.
*/
g_free(machine->fdt);
machine->fdt = fdt;
}
static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)

View File

@ -167,13 +167,6 @@ struct Ppc405SoCState {
DeviceState parent_obj;
/* Public */
MemoryRegion ram_banks[2];
hwaddr ram_bases[2], ram_sizes[2];
bool do_dram_init;
MemoryRegion *dram_mr;
hwaddr ram_size;
PowerPCCPU cpu;
PPCUIC uic;
Ppc405CpcState cpc;
@ -187,6 +180,7 @@ struct Ppc405SoCState {
Ppc405PobState pob;
Ppc4xxPlbState plb;
Ppc4xxMalState mal;
Ppc4xxSdramDdrState sdram;
};
#endif /* PPC405_H */

View File

@ -271,25 +271,13 @@ static void boot_from_kernel(MachineState *machine, PowerPCCPU *cpu)
static void ppc405_init(MachineState *machine)
{
Ppc405MachineState *ppc405 = PPC405_MACHINE(machine);
MachineClass *mc = MACHINE_GET_CLASS(machine);
const char *kernel_filename = machine->kernel_filename;
MemoryRegion *sysmem = get_system_memory();
if (machine->ram_size != mc->default_ram_size) {
char *sz = size_to_str(mc->default_ram_size);
error_report("Invalid RAM size, should be %s", sz);
g_free(sz);
exit(EXIT_FAILURE);
}
object_initialize_child(OBJECT(machine), "soc", &ppc405->soc,
TYPE_PPC405_SOC);
object_property_set_uint(OBJECT(&ppc405->soc), "ram-size",
machine->ram_size, &error_fatal);
object_property_set_link(OBJECT(&ppc405->soc), "dram",
OBJECT(machine->ram), &error_abort);
object_property_set_bool(OBJECT(&ppc405->soc), "dram-init",
kernel_filename != NULL, &error_abort);
object_property_set_uint(OBJECT(&ppc405->soc), "sys-clk", 33333333,
&error_abort);
qdev_realize(DEVICE(&ppc405->soc), NULL, &error_fatal);
@ -349,6 +337,7 @@ static void ppc405_init(MachineState *machine)
/* Load ELF kernel and rootfs.cpio */
} else if (kernel_filename && !machine->firmware) {
ppc4xx_sdram_ddr_enable(&ppc405->soc.sdram);
boot_from_kernel(machine, &ppc405->soc.cpu);
}
}

View File

@ -1016,6 +1016,9 @@ static void ppc405_soc_instance_init(Object *obj)
object_initialize_child(obj, "plb", &s->plb, TYPE_PPC4xx_PLB);
object_initialize_child(obj, "mal", &s->mal, TYPE_PPC4xx_MAL);
object_initialize_child(obj, "sdram", &s->sdram, TYPE_PPC4xx_SDRAM_DDR);
object_property_add_alias(obj, "dram", OBJECT(&s->sdram), "dram");
}
static void ppc405_reset(void *opaque)
@ -1073,16 +1076,17 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(DEVICE(&s->cpu), PPC40x_INPUT_CINT));
/* SDRAM controller */
/* XXX 405EP has no ECC interrupt */
s->ram_bases[0] = 0;
s->ram_sizes[0] = s->ram_size;
memory_region_init_alias(&s->ram_banks[0], OBJECT(s),
"ppc405.sdram0", s->dram_mr,
s->ram_bases[0], s->ram_sizes[0]);
ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(&s->uic), 17), 1,
s->ram_banks, s->ram_bases, s->ram_sizes,
s->do_dram_init);
/*
* We use the 440 DDR SDRAM controller which has more regs and features
* but it's compatible enough for now
*/
object_property_set_int(OBJECT(&s->sdram), "nbanks", 2, &error_abort);
if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->sdram), &s->cpu, errp)) {
return;
}
/* XXX 405EP has no ECC interrupt */
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdram), 0,
qdev_get_gpio_in(DEVICE(&s->uic), 17));
/* External bus controller */
if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->ebc), &s->cpu, errp)) {
@ -1157,14 +1161,6 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp)
/* Uses UIC IRQs 9, 15, 17 */
}
static Property ppc405_soc_properties[] = {
DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION,
MemoryRegion *),
DEFINE_PROP_BOOL("dram-init", Ppc405SoCState, do_dram_init, 0),
DEFINE_PROP_UINT64("ram-size", Ppc405SoCState, ram_size, 0),
DEFINE_PROP_END_OF_LIST(),
};
static void ppc405_soc_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
@ -1172,7 +1168,6 @@ static void ppc405_soc_class_init(ObjectClass *oc, void *data)
dc->realize = ppc405_soc_realize;
/* Reason: only works as part of a ppc405 board/machine */
dc->user_creatable = false;
device_class_set_props(dc, ppc405_soc_properties);
}
static const TypeInfo ppc405_types[] = {

View File

@ -16,10 +16,6 @@
void ppc4xx_l2sram_init(CPUPPCState *env);
void ppc4xx_cpr_init(CPUPPCState *env);
void ppc4xx_sdr_init(CPUPPCState *env);
void ppc440_sdram_init(CPUPPCState *env, int nbanks,
MemoryRegion *ram_memories,
hwaddr *ram_bases, hwaddr *ram_sizes,
int do_init);
void ppc4xx_ahb_init(CPUPPCState *env);
void ppc4xx_dma_init(CPUPPCState *env, int dcr_base);
void ppc460ex_pcie_init(CPUPPCState *env);

View File

@ -34,6 +34,8 @@
#include "hw/qdev-properties.h"
#include "qapi/error.h"
#include <libfdt.h>
#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
/* from u-boot */
@ -48,22 +50,15 @@
#define PPC440EP_PCI_IO 0xe8000000
#define PPC440EP_PCI_IOLEN 0x00010000
#define PPC440EP_SDRAM_NR_BANKS 4
static const ram_addr_t ppc440ep_sdram_bank_sizes[] = {
256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 0
};
static hwaddr entry;
static int bamboo_load_device_tree(hwaddr addr,
uint32_t ramsize,
hwaddr initrd_base,
hwaddr initrd_size,
const char *kernel_cmdline)
static int bamboo_load_device_tree(MachineState *machine,
hwaddr addr,
hwaddr initrd_base,
hwaddr initrd_size)
{
int ret = -1;
uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(machine->ram_size) };
char *filename;
int fdt_size;
void *fdt;
@ -98,7 +93,7 @@ static int bamboo_load_device_tree(hwaddr addr,
fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
}
ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
kernel_cmdline);
machine->kernel_cmdline);
if (ret < 0) {
fprintf(stderr, "couldn't set /chosen/bootargs\n");
}
@ -119,7 +114,10 @@ static int bamboo_load_device_tree(hwaddr addr,
tb_freq);
rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
g_free(fdt);
/* Set ms->fdt for 'dumpdtb' QMP/HMP command */
machine->fdt = fdt;
return 0;
}
@ -163,14 +161,10 @@ static void main_cpu_reset(void *opaque)
static void bamboo_init(MachineState *machine)
{
const char *kernel_filename = machine->kernel_filename;
const char *kernel_cmdline = machine->kernel_cmdline;
const char *initrd_filename = machine->initrd_filename;
unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *isa = g_new(MemoryRegion, 1);
MemoryRegion *ram_memories = g_new(MemoryRegion, PPC440EP_SDRAM_NR_BANKS);
hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS];
hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS];
PCIBus *pcibus;
PowerPCCPU *cpu;
CPUPPCState *env;
@ -205,15 +199,15 @@ static void bamboo_init(MachineState *machine)
qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT));
/* SDRAM controller */
memset(ram_bases, 0, sizeof(ram_bases));
memset(ram_sizes, 0, sizeof(ram_sizes));
ppc4xx_sdram_banks(machine->ram, PPC440EP_SDRAM_NR_BANKS, ram_memories,
ram_bases, ram_sizes, ppc440ep_sdram_bank_sizes);
dev = qdev_new(TYPE_PPC4xx_SDRAM_DDR);
object_property_set_link(OBJECT(dev), "dram", OBJECT(machine->ram),
&error_abort);
ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal);
object_unref(OBJECT(dev));
/* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
ppc4xx_sdram_init(env,
qdev_get_gpio_in(uicdev, 14),
PPC440EP_SDRAM_NR_BANKS, ram_memories,
ram_bases, ram_sizes, 1);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(uicdev, 14));
/* Enable SDRAM memory regions, this should be done by the firmware */
ppc4xx_sdram_ddr_enable(PPC4xx_SDRAM_DDR(dev));
/* PCI */
dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE,
@ -289,8 +283,8 @@ static void bamboo_init(MachineState *machine)
/* If we're loading a kernel directly, we must load the device tree too. */
if (kernel_filename) {
if (bamboo_load_device_tree(FDT_ADDR, machine->ram_size, RAMDISK_ADDR,
initrd_size, kernel_cmdline) < 0) {
if (bamboo_load_device_tree(machine, FDT_ADDR,
RAMDISK_ADDR, initrd_size) < 0) {
error_report("couldn't load device tree");
exit(1);
}

View File

@ -16,13 +16,15 @@
#include "qemu/module.h"
#include "hw/irq.h"
#include "exec/memory.h"
#include "hw/ppc/ppc.h"
#include "cpu.h"
#include "hw/ppc/ppc4xx.h"
#include "hw/qdev-properties.h"
#include "hw/pci/pci.h"
#include "sysemu/block-backend.h"
#include "sysemu/reset.h"
#include "ppc440.h"
#include "qom/object.h"
#include "trace.h"
/*****************************************************************************/
/* L2 Cache as SRAM */
@ -378,10 +380,6 @@ enum {
PESDR1_RSTSTA = 0x365,
};
#define SDR0_DDR0_DDRM_ENCODE(n) ((((unsigned long)(n)) & 0x03) << 29)
#define SDR0_DDR0_DDRM_DDR1 0x20000000
#define SDR0_DDR0_DDRM_DDR2 0x40000000
static uint32_t dcr_read_sdr(void *opaque, int dcrn)
{
ppc4xx_sdr_t *sdr = opaque;
@ -482,16 +480,6 @@ void ppc4xx_sdr_init(CPUPPCState *env)
/*****************************************************************************/
/* SDRAM controller */
typedef struct ppc440_sdram_t {
uint32_t addr;
int nbanks;
MemoryRegion containers[4]; /* used for clipping */
MemoryRegion *ram_memories;
hwaddr ram_bases[4];
hwaddr ram_sizes[4];
uint32_t bcr[4];
} ppc440_sdram_t;
enum {
SDRAM0_CFGADDR = 0x10,
SDRAM0_CFGDATA,
@ -506,39 +494,39 @@ enum {
SDRAM_PLBADDUHB = 0x50,
};
static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
static uint32_t sdram_ddr2_bcr(hwaddr ram_base, hwaddr ram_size)
{
uint32_t bcr;
switch (ram_size) {
case (8 * MiB):
case 8 * MiB:
bcr = 0xffc0;
break;
case (16 * MiB):
case 16 * MiB:
bcr = 0xff80;
break;
case (32 * MiB):
case 32 * MiB:
bcr = 0xff00;
break;
case (64 * MiB):
case 64 * MiB:
bcr = 0xfe00;
break;
case (128 * MiB):
case 128 * MiB:
bcr = 0xfc00;
break;
case (256 * MiB):
case 256 * MiB:
bcr = 0xf800;
break;
case (512 * MiB):
case 512 * MiB:
bcr = 0xf000;
break;
case (1 * GiB):
case 1 * GiB:
bcr = 0xe000;
break;
case (2 * GiB):
case 2 * GiB:
bcr = 0xc000;
break;
case (4 * GiB):
case 4 * GiB:
bcr = 0x8000;
break;
default:
@ -551,12 +539,12 @@ static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
return bcr;
}
static inline hwaddr sdram_base(uint32_t bcr)
static inline hwaddr sdram_ddr2_base(uint32_t bcr)
{
return (bcr & 0xffe00000) << 2;
}
static uint64_t sdram_size(uint32_t bcr)
static uint64_t sdram_ddr2_size(uint32_t bcr)
{
uint64_t size;
int sh;
@ -567,46 +555,66 @@ static uint64_t sdram_size(uint32_t bcr)
return size;
}
static void sdram_set_bcr(ppc440_sdram_t *sdram, int i,
uint32_t bcr, int enabled)
static void sdram_bank_map(Ppc4xxSdramBank *bank)
{
if (sdram->bcr[i] & 1) {
memory_region_init(&bank->container, NULL, "sdram-container", bank->size);
memory_region_add_subregion(&bank->container, 0, &bank->ram);
memory_region_add_subregion(get_system_memory(), bank->base,
&bank->container);
}
static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
{
memory_region_del_subregion(get_system_memory(), &bank->container);
memory_region_del_subregion(&bank->container, &bank->ram);
object_unparent(OBJECT(&bank->container));
}
static void sdram_ddr2_set_bcr(Ppc4xxSdramDdr2State *sdram, int i,
uint32_t bcr, int enabled)
{
if (sdram->bank[i].bcr & 1) {
/* First unmap RAM if enabled */
memory_region_del_subregion(get_system_memory(),
&sdram->containers[i]);
memory_region_del_subregion(&sdram->containers[i],
&sdram->ram_memories[i]);
object_unparent(OBJECT(&sdram->containers[i]));
trace_ppc4xx_sdram_unmap(sdram_ddr2_base(sdram->bank[i].bcr),
sdram_ddr2_size(sdram->bank[i].bcr));
sdram_bank_unmap(&sdram->bank[i]);
}
sdram->bcr[i] = bcr & 0xffe0ffc1;
sdram->bank[i].bcr = bcr & 0xffe0ffc1;
if (enabled && (bcr & 1)) {
memory_region_init(&sdram->containers[i], NULL, "sdram-containers",
sdram_size(bcr));
memory_region_add_subregion(&sdram->containers[i], 0,
&sdram->ram_memories[i]);
memory_region_add_subregion(get_system_memory(),
sdram_base(bcr),
&sdram->containers[i]);
trace_ppc4xx_sdram_map(sdram_ddr2_base(bcr), sdram_ddr2_size(bcr));
sdram_bank_map(&sdram->bank[i]);
}
}
static void sdram_map_bcr(ppc440_sdram_t *sdram)
static void sdram_ddr2_map_bcr(Ppc4xxSdramDdr2State *sdram)
{
int i;
for (i = 0; i < sdram->nbanks; i++) {
if (sdram->ram_sizes[i] != 0) {
sdram_set_bcr(sdram, i, sdram_bcr(sdram->ram_bases[i],
sdram->ram_sizes[i]), 1);
if (sdram->bank[i].size) {
sdram_ddr2_set_bcr(sdram, i,
sdram_ddr2_bcr(sdram->bank[i].base,
sdram->bank[i].size), 1);
} else {
sdram_set_bcr(sdram, i, 0, 0);
sdram_ddr2_set_bcr(sdram, i, 0, 0);
}
}
}
static uint32_t dcr_read_sdram(void *opaque, int dcrn)
static void sdram_ddr2_unmap_bcr(Ppc4xxSdramDdr2State *sdram)
{
ppc440_sdram_t *sdram = opaque;
int i;
for (i = 0; i < sdram->nbanks; i++) {
if (sdram->bank[i].size) {
sdram_ddr2_set_bcr(sdram, i, sdram->bank[i].bcr & ~1, 0);
}
}
}
static uint32_t sdram_ddr2_dcr_read(void *opaque, int dcrn)
{
Ppc4xxSdramDdr2State *sdram = opaque;
uint32_t ret = 0;
switch (dcrn) {
@ -614,9 +622,9 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
case SDRAM_R1BAS:
case SDRAM_R2BAS:
case SDRAM_R3BAS:
if (sdram->ram_sizes[dcrn - SDRAM_R0BAS]) {
ret = sdram_bcr(sdram->ram_bases[dcrn - SDRAM_R0BAS],
sdram->ram_sizes[dcrn - SDRAM_R0BAS]);
if (sdram->bank[dcrn - SDRAM_R0BAS].size) {
ret = sdram_ddr2_bcr(sdram->bank[dcrn - SDRAM_R0BAS].base,
sdram->bank[dcrn - SDRAM_R0BAS].size);
}
break;
case SDRAM_CONF1HB:
@ -635,7 +643,7 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
ret = 0x80000000;
break;
case 0x21: /* SDRAM_MCOPT2 */
ret = 0x08000000;
ret = sdram->mcopt2;
break;
case 0x40: /* SDRAM_MB0CF */
ret = 0x00008001;
@ -657,9 +665,11 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
return ret;
}
static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
#define SDRAM_DDR2_MCOPT2_DCEN BIT(27)
static void sdram_ddr2_dcr_write(void *opaque, int dcrn, uint32_t val)
{
ppc440_sdram_t *sdram = opaque;
Ppc4xxSdramDdr2State *sdram = opaque;
switch (dcrn) {
case SDRAM_R0BAS:
@ -679,6 +689,21 @@ static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
switch (sdram->addr) {
case 0x00: /* B0CR */
break;
case 0x21: /* SDRAM_MCOPT2 */
if (!(sdram->mcopt2 & SDRAM_DDR2_MCOPT2_DCEN) &&
(val & SDRAM_DDR2_MCOPT2_DCEN)) {
trace_ppc4xx_sdram_enable("enable");
/* validate all RAM mappings */
sdram_ddr2_map_bcr(sdram);
sdram->mcopt2 |= SDRAM_DDR2_MCOPT2_DCEN;
} else if ((sdram->mcopt2 & SDRAM_DDR2_MCOPT2_DCEN) &&
!(val & SDRAM_DDR2_MCOPT2_DCEN)) {
trace_ppc4xx_sdram_enable("disable");
/* invalidate all RAM mappings */
sdram_ddr2_unmap_bcr(sdram);
sdram->mcopt2 &= ~SDRAM_DDR2_MCOPT2_DCEN;
}
break;
default:
break;
}
@ -688,54 +713,96 @@ static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
}
}
static void sdram_reset(void *opaque)
static void ppc4xx_sdram_ddr2_reset(DeviceState *dev)
{
ppc440_sdram_t *sdram = opaque;
Ppc4xxSdramDdr2State *sdram = PPC4xx_SDRAM_DDR2(dev);
sdram->addr = 0;
sdram->mcopt2 = 0;
}
void ppc440_sdram_init(CPUPPCState *env, int nbanks,
MemoryRegion *ram_memories,
hwaddr *ram_bases, hwaddr *ram_sizes,
int do_init)
static void ppc4xx_sdram_ddr2_realize(DeviceState *dev, Error **errp)
{
ppc440_sdram_t *sdram;
Ppc4xxSdramDdr2State *s = PPC4xx_SDRAM_DDR2(dev);
Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
/*
* SoC also has 4 GiB but that causes problem with 32 bit
* builds (4*GiB overflows the 32 bit ram_addr_t).
*/
const ram_addr_t valid_bank_sizes[] = {
2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB,
64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 0
};
sdram = g_malloc0(sizeof(*sdram));
sdram->nbanks = nbanks;
sdram->ram_memories = ram_memories;
memcpy(sdram->ram_bases, ram_bases, nbanks * sizeof(hwaddr));
memcpy(sdram->ram_sizes, ram_sizes, nbanks * sizeof(hwaddr));
qemu_register_reset(&sdram_reset, sdram);
ppc_dcr_register(env, SDRAM0_CFGADDR,
sdram, &dcr_read_sdram, &dcr_write_sdram);
ppc_dcr_register(env, SDRAM0_CFGDATA,
sdram, &dcr_read_sdram, &dcr_write_sdram);
if (do_init) {
sdram_map_bcr(sdram);
if (s->nbanks < 1 || s->nbanks > 4) {
error_setg(errp, "Invalid number of RAM banks");
return;
}
if (!s->dram_mr) {
error_setg(errp, "Missing dram memory region");
return;
}
ppc4xx_sdram_banks(s->dram_mr, s->nbanks, s->bank, valid_bank_sizes);
ppc_dcr_register(env, SDRAM_R0BAS,
sdram, &dcr_read_sdram, &dcr_write_sdram);
ppc_dcr_register(env, SDRAM_R1BAS,
sdram, &dcr_read_sdram, &dcr_write_sdram);
ppc_dcr_register(env, SDRAM_R2BAS,
sdram, &dcr_read_sdram, &dcr_write_sdram);
ppc_dcr_register(env, SDRAM_R3BAS,
sdram, &dcr_read_sdram, &dcr_write_sdram);
ppc_dcr_register(env, SDRAM_CONF1HB,
sdram, &dcr_read_sdram, &dcr_write_sdram);
ppc_dcr_register(env, SDRAM_PLBADDULL,
sdram, &dcr_read_sdram, &dcr_write_sdram);
ppc_dcr_register(env, SDRAM_CONF1LL,
sdram, &dcr_read_sdram, &dcr_write_sdram);
ppc_dcr_register(env, SDRAM_CONFPATHB,
sdram, &dcr_read_sdram, &dcr_write_sdram);
ppc_dcr_register(env, SDRAM_PLBADDUHB,
sdram, &dcr_read_sdram, &dcr_write_sdram);
ppc4xx_dcr_register(dcr, SDRAM0_CFGADDR,
s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
ppc4xx_dcr_register(dcr, SDRAM0_CFGDATA,
s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
ppc4xx_dcr_register(dcr, SDRAM_R0BAS,
s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
ppc4xx_dcr_register(dcr, SDRAM_R1BAS,
s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
ppc4xx_dcr_register(dcr, SDRAM_R2BAS,
s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
ppc4xx_dcr_register(dcr, SDRAM_R3BAS,
s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
ppc4xx_dcr_register(dcr, SDRAM_CONF1HB,
s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
ppc4xx_dcr_register(dcr, SDRAM_PLBADDULL,
s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
ppc4xx_dcr_register(dcr, SDRAM_CONF1LL,
s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
ppc4xx_dcr_register(dcr, SDRAM_CONFPATHB,
s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
ppc4xx_dcr_register(dcr, SDRAM_PLBADDUHB,
s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
}
static Property ppc4xx_sdram_ddr2_props[] = {
DEFINE_PROP_LINK("dram", Ppc4xxSdramDdr2State, dram_mr, TYPE_MEMORY_REGION,
MemoryRegion *),
DEFINE_PROP_UINT32("nbanks", Ppc4xxSdramDdr2State, nbanks, 4),
DEFINE_PROP_END_OF_LIST(),
};
static void ppc4xx_sdram_ddr2_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = ppc4xx_sdram_ddr2_realize;
dc->reset = ppc4xx_sdram_ddr2_reset;
/* Reason: only works as function of a ppc4xx SoC */
dc->user_creatable = false;
device_class_set_props(dc, ppc4xx_sdram_ddr2_props);
}
void ppc4xx_sdram_ddr2_enable(Ppc4xxSdramDdr2State *s)
{
sdram_ddr2_dcr_write(s, SDRAM0_CFGADDR, 0x21);
sdram_ddr2_dcr_write(s, SDRAM0_CFGDATA, 0x08000000);
}
static const TypeInfo ppc4xx_types[] = {
{
.name = TYPE_PPC4xx_SDRAM_DDR2,
.parent = TYPE_PPC4xx_DCR_DEVICE,
.instance_size = sizeof(Ppc4xxSdramDdr2State),
.class_init = ppc4xx_sdram_ddr2_class_init,
}
};
DEFINE_TYPES(ppc4xx_types)
/*****************************************************************************/
/* PLB to AHB bridge */
enum {

View File

@ -38,28 +38,6 @@
/*****************************************************************************/
/* SDRAM controller */
typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
struct ppc4xx_sdram_t {
uint32_t addr;
int nbanks;
MemoryRegion containers[4]; /* used for clipping */
MemoryRegion *ram_memories;
hwaddr ram_bases[4];
hwaddr ram_sizes[4];
uint32_t besr0;
uint32_t besr1;
uint32_t bear;
uint32_t cfg;
uint32_t status;
uint32_t rtr;
uint32_t pmit;
uint32_t bcr[4];
uint32_t tr;
uint32_t ecccfg;
uint32_t eccesr;
qemu_irq irq;
};
enum {
SDRAM0_CFGADDR = 0x010,
SDRAM0_CFGDATA = 0x011,
@ -70,37 +48,37 @@ enum {
* there are type inconsistencies, mixing hwaddr, target_ulong
* and uint32_t
*/
static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size)
{
uint32_t bcr;
switch (ram_size) {
case 4 * MiB:
bcr = 0x00000000;
bcr = 0;
break;
case 8 * MiB:
bcr = 0x00020000;
bcr = 0x20000;
break;
case 16 * MiB:
bcr = 0x00040000;
bcr = 0x40000;
break;
case 32 * MiB:
bcr = 0x00060000;
bcr = 0x60000;
break;
case 64 * MiB:
bcr = 0x00080000;
bcr = 0x80000;
break;
case 128 * MiB:
bcr = 0x000A0000;
bcr = 0xA0000;
break;
case 256 * MiB:
bcr = 0x000C0000;
bcr = 0xC0000;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: invalid RAM size 0x%" HWADDR_PRIx "\n", __func__,
ram_size);
return 0x00000000;
return 0;
}
bcr |= ram_base & 0xFF800000;
bcr |= 1;
@ -108,12 +86,12 @@ static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
return bcr;
}
static inline hwaddr sdram_base(uint32_t bcr)
static inline hwaddr sdram_ddr_base(uint32_t bcr)
{
return bcr & 0xFF800000;
}
static target_ulong sdram_size(uint32_t bcr)
static target_ulong sdram_ddr_size(uint32_t bcr)
{
target_ulong size;
int sh;
@ -128,64 +106,63 @@ static target_ulong sdram_size(uint32_t bcr)
return size;
}
static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i,
uint32_t bcr, int enabled)
static void sdram_ddr_set_bcr(Ppc4xxSdramDdrState *sdram, int i,
uint32_t bcr, int enabled)
{
if (sdram->bcr[i] & 0x00000001) {
if (sdram->bank[i].bcr & 1) {
/* Unmap RAM */
trace_ppc4xx_sdram_unmap(sdram_base(sdram->bcr[i]),
sdram_size(sdram->bcr[i]));
trace_ppc4xx_sdram_unmap(sdram_ddr_base(sdram->bank[i].bcr),
sdram_ddr_size(sdram->bank[i].bcr));
memory_region_del_subregion(get_system_memory(),
&sdram->containers[i]);
memory_region_del_subregion(&sdram->containers[i],
&sdram->ram_memories[i]);
object_unparent(OBJECT(&sdram->containers[i]));
&sdram->bank[i].container);
memory_region_del_subregion(&sdram->bank[i].container,
&sdram->bank[i].ram);
object_unparent(OBJECT(&sdram->bank[i].container));
}
sdram->bcr[i] = bcr & 0xFFDEE001;
if (enabled && (bcr & 0x00000001)) {
trace_ppc4xx_sdram_map(sdram_base(bcr), sdram_size(bcr));
memory_region_init(&sdram->containers[i], NULL, "sdram-containers",
sdram_size(bcr));
memory_region_add_subregion(&sdram->containers[i], 0,
&sdram->ram_memories[i]);
sdram->bank[i].bcr = bcr & 0xFFDEE001;
if (enabled && (bcr & 1)) {
trace_ppc4xx_sdram_map(sdram_ddr_base(bcr), sdram_ddr_size(bcr));
memory_region_init(&sdram->bank[i].container, NULL, "sdram-container",
sdram_ddr_size(bcr));
memory_region_add_subregion(&sdram->bank[i].container, 0,
&sdram->bank[i].ram);
memory_region_add_subregion(get_system_memory(),
sdram_base(bcr),
&sdram->containers[i]);
sdram_ddr_base(bcr),
&sdram->bank[i].container);
}
}
static void sdram_map_bcr(ppc4xx_sdram_t *sdram)
static void sdram_ddr_map_bcr(Ppc4xxSdramDdrState *sdram)
{
int i;
for (i = 0; i < sdram->nbanks; i++) {
if (sdram->ram_sizes[i] != 0) {
sdram_set_bcr(sdram, i, sdram_bcr(sdram->ram_bases[i],
sdram->ram_sizes[i]), 1);
if (sdram->bank[i].size != 0) {
sdram_ddr_set_bcr(sdram, i, sdram_ddr_bcr(sdram->bank[i].base,
sdram->bank[i].size), 1);
} else {
sdram_set_bcr(sdram, i, 0x00000000, 0);
sdram_ddr_set_bcr(sdram, i, 0, 0);
}
}
}
static void sdram_unmap_bcr(ppc4xx_sdram_t *sdram)
static void sdram_ddr_unmap_bcr(Ppc4xxSdramDdrState *sdram)
{
int i;
for (i = 0; i < sdram->nbanks; i++) {
trace_ppc4xx_sdram_unmap(sdram_base(sdram->bcr[i]),
sdram_size(sdram->bcr[i]));
trace_ppc4xx_sdram_unmap(sdram_ddr_base(sdram->bank[i].bcr),
sdram_ddr_size(sdram->bank[i].bcr));
memory_region_del_subregion(get_system_memory(),
&sdram->ram_memories[i]);
&sdram->bank[i].ram);
}
}
static uint32_t dcr_read_sdram(void *opaque, int dcrn)
static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
{
ppc4xx_sdram_t *sdram;
Ppc4xxSdramDdrState *sdram = opaque;
uint32_t ret;
sdram = opaque;
switch (dcrn) {
case SDRAM0_CFGADDR:
ret = sdram->addr;
@ -214,16 +191,16 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
ret = sdram->pmit;
break;
case 0x40: /* SDRAM_B0CR */
ret = sdram->bcr[0];
ret = sdram->bank[0].bcr;
break;
case 0x44: /* SDRAM_B1CR */
ret = sdram->bcr[1];
ret = sdram->bank[1].bcr;
break;
case 0x48: /* SDRAM_B2CR */
ret = sdram->bcr[2];
ret = sdram->bank[2].bcr;
break;
case 0x4C: /* SDRAM_B3CR */
ret = sdram->bcr[3];
ret = sdram->bank[3].bcr;
break;
case 0x80: /* SDRAM_TR */
ret = -1; /* ? */
@ -241,18 +218,17 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
break;
default:
/* Avoid gcc warning */
ret = 0x00000000;
ret = 0;
break;
}
return ret;
}
static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
static void sdram_ddr_dcr_write(void *opaque, int dcrn, uint32_t val)
{
ppc4xx_sdram_t *sdram;
Ppc4xxSdramDdrState *sdram = opaque;
sdram = opaque;
switch (dcrn) {
case SDRAM0_CFGADDR:
sdram->addr = val;
@ -273,12 +249,12 @@ static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
trace_ppc4xx_sdram_enable("enable");
/* validate all RAM mappings */
sdram_map_bcr(sdram);
sdram_ddr_map_bcr(sdram);
sdram->status &= ~0x80000000;
} else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
trace_ppc4xx_sdram_enable("disable");
/* invalidate all RAM mappings */
sdram_unmap_bcr(sdram);
sdram_ddr_unmap_bcr(sdram);
sdram->status |= 0x80000000;
}
if (!(sdram->cfg & 0x40000000) && (val & 0x40000000)) {
@ -298,16 +274,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, 0, val, sdram->cfg & 0x80000000);
sdram_ddr_set_bcr(sdram, 0, val, sdram->cfg & 0x80000000);
break;
case 0x44: /* SDRAM_B1CR */
sdram_set_bcr(sdram, 1, val, sdram->cfg & 0x80000000);
sdram_ddr_set_bcr(sdram, 1, val, sdram->cfg & 0x80000000);
break;
case 0x48: /* SDRAM_B2CR */
sdram_set_bcr(sdram, 2, val, sdram->cfg & 0x80000000);
sdram_ddr_set_bcr(sdram, 2, val, sdram->cfg & 0x80000000);
break;
case 0x4C: /* SDRAM_B3CR */
sdram_set_bcr(sdram, 3, val, sdram->cfg & 0x80000000);
sdram_ddr_set_bcr(sdram, 3, val, sdram->cfg & 0x80000000);
break;
case 0x80: /* SDRAM_TR */
sdram->tr = val & 0x018FC01F;
@ -331,52 +307,73 @@ static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
}
}
static void sdram_reset(void *opaque)
static void ppc4xx_sdram_ddr_reset(DeviceState *dev)
{
ppc4xx_sdram_t *sdram;
Ppc4xxSdramDdrState *sdram = PPC4xx_SDRAM_DDR(dev);
sdram = opaque;
sdram->addr = 0x00000000;
sdram->bear = 0x00000000;
sdram->besr0 = 0x00000000; /* No error */
sdram->besr1 = 0x00000000; /* No error */
sdram->cfg = 0x00000000;
sdram->ecccfg = 0x00000000; /* No ECC */
sdram->eccesr = 0x00000000; /* No error */
sdram->addr = 0;
sdram->bear = 0;
sdram->besr0 = 0; /* No error */
sdram->besr1 = 0; /* No error */
sdram->cfg = 0;
sdram->ecccfg = 0; /* No ECC */
sdram->eccesr = 0; /* No error */
sdram->pmit = 0x07C00000;
sdram->rtr = 0x05F00000;
sdram->tr = 0x00854009;
/* We pre-initialize RAM banks */
sdram->status = 0x00000000;
sdram->status = 0;
sdram->cfg = 0x00800000;
}
void ppc4xx_sdram_init(CPUPPCState *env, qemu_irq irq, int nbanks,
MemoryRegion *ram_memories,
hwaddr *ram_bases,
hwaddr *ram_sizes,
int do_init)
static void ppc4xx_sdram_ddr_realize(DeviceState *dev, Error **errp)
{
ppc4xx_sdram_t *sdram;
Ppc4xxSdramDdrState *s = PPC4xx_SDRAM_DDR(dev);
Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
const ram_addr_t valid_bank_sizes[] = {
256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 4 * MiB, 0
};
sdram = g_new0(ppc4xx_sdram_t, 1);
sdram->irq = irq;
sdram->nbanks = nbanks;
sdram->ram_memories = ram_memories;
memset(sdram->ram_bases, 0, 4 * sizeof(hwaddr));
memcpy(sdram->ram_bases, ram_bases,
nbanks * sizeof(hwaddr));
memset(sdram->ram_sizes, 0, 4 * sizeof(hwaddr));
memcpy(sdram->ram_sizes, ram_sizes,
nbanks * sizeof(hwaddr));
qemu_register_reset(&sdram_reset, sdram);
ppc_dcr_register(env, SDRAM0_CFGADDR,
sdram, &dcr_read_sdram, &dcr_write_sdram);
ppc_dcr_register(env, SDRAM0_CFGDATA,
sdram, &dcr_read_sdram, &dcr_write_sdram);
if (do_init) {
sdram_map_bcr(sdram);
if (s->nbanks < 1 || s->nbanks > 4) {
error_setg(errp, "Invalid number of RAM banks");
return;
}
if (!s->dram_mr) {
error_setg(errp, "Missing dram memory region");
return;
}
ppc4xx_sdram_banks(s->dram_mr, s->nbanks, s->bank, valid_bank_sizes);
sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
ppc4xx_dcr_register(dcr, SDRAM0_CFGADDR,
s, &sdram_ddr_dcr_read, &sdram_ddr_dcr_write);
ppc4xx_dcr_register(dcr, SDRAM0_CFGDATA,
s, &sdram_ddr_dcr_read, &sdram_ddr_dcr_write);
}
static Property ppc4xx_sdram_ddr_props[] = {
DEFINE_PROP_LINK("dram", Ppc4xxSdramDdrState, dram_mr, TYPE_MEMORY_REGION,
MemoryRegion *),
DEFINE_PROP_UINT32("nbanks", Ppc4xxSdramDdrState, nbanks, 4),
DEFINE_PROP_END_OF_LIST(),
};
static void ppc4xx_sdram_ddr_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = ppc4xx_sdram_ddr_realize;
dc->reset = ppc4xx_sdram_ddr_reset;
/* Reason: only works as function of a ppc4xx SoC */
dc->user_creatable = false;
device_class_set_props(dc, ppc4xx_sdram_ddr_props);
}
void ppc4xx_sdram_ddr_enable(Ppc4xxSdramDdrState *s)
{
sdram_ddr_dcr_write(s, SDRAM0_CFGADDR, 0x20);
sdram_ddr_dcr_write(s, SDRAM0_CFGDATA, 0x80000000);
}
/*
@ -390,8 +387,7 @@ void ppc4xx_sdram_init(CPUPPCState *env, qemu_irq irq, int nbanks,
* sizes varies by SoC.
*/
void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
MemoryRegion ram_memories[],
hwaddr ram_bases[], hwaddr ram_sizes[],
Ppc4xxSdramBank ram_banks[],
const ram_addr_t sdram_bank_sizes[])
{
ram_addr_t size_left = memory_region_size(ram);
@ -406,13 +402,13 @@ void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
if (bank_size <= size_left) {
char name[32];
ram_bases[i] = base;
ram_sizes[i] = bank_size;
ram_banks[i].base = base;
ram_banks[i].size = bank_size;
base += bank_size;
size_left -= bank_size;
snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
memory_region_init_alias(&ram_memories[i], NULL, name, ram,
ram_bases[i], ram_sizes[i]);
memory_region_init_alias(&ram_banks[i].ram, NULL, name, ram,
ram_banks[i].base, ram_banks[i].size);
break;
}
}
@ -967,6 +963,11 @@ static void ppc4xx_dcr_class_init(ObjectClass *oc, void *data)
static const TypeInfo ppc4xx_types[] = {
{
.name = TYPE_PPC4xx_SDRAM_DDR,
.parent = TYPE_PPC4xx_DCR_DEVICE,
.instance_size = sizeof(Ppc4xxSdramDdrState),
.class_init = ppc4xx_sdram_ddr_class_init,
}, {
.name = TYPE_PPC4xx_MAL,
.parent = TYPE_PPC4xx_DCR_DEVICE,
.instance_size = sizeof(Ppc4xxMalState),

View File

@ -73,14 +73,6 @@
#define OPB_FREQ 115000000
#define EBC_FREQ 115000000
#define UART_FREQ 11059200
#define SDRAM_NR_BANKS 4
/* 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 {
uint32_t dt_base;
@ -131,13 +123,12 @@ static int sam460ex_load_uboot(void)
return 0;
}
static int sam460ex_load_device_tree(hwaddr addr,
uint32_t ramsize,
static int sam460ex_load_device_tree(MachineState *machine,
hwaddr addr,
hwaddr initrd_base,
hwaddr initrd_size,
const char *kernel_cmdline)
hwaddr initrd_size)
{
uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(machine->ram_size) };
char *filename;
int fdt_size;
void *fdt;
@ -171,7 +162,8 @@ static int sam460ex_load_device_tree(hwaddr addr,
qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
(initrd_base + initrd_size));
qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
machine->kernel_cmdline);
/* Copy data from the host device tree into the guest. Since the guest can
* directly access the timebase without host involvement, we must expose
@ -208,7 +200,9 @@ static int sam460ex_load_device_tree(hwaddr addr,
EBC_FREQ);
rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
g_free(fdt);
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
machine->fdt = fdt;
return fdt_size;
}
@ -274,9 +268,6 @@ 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] = {0};
hwaddr ram_sizes[SDRAM_NR_BANKS] = {0};
MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
DeviceState *uic[4];
int i;
@ -343,22 +334,37 @@ static void sam460ex_init(MachineState *machine)
}
/* SDRAM controller */
/* put all RAM on first bank because board has one slot
* and firmware only checks that */
ppc4xx_sdram_banks(machine->ram, 1, ram_memories, ram_bases, ram_sizes,
ppc460ex_sdram_bank_sizes);
/* The SoC could also handle 4 GiB but firmware does not work with that. */
if (machine->ram_size > 2 * GiB) {
error_report("Memory over 2 GiB is not supported");
exit(1);
}
/* Firmware needs at least 64 MiB */
if (machine->ram_size < 64 * MiB) {
error_report("Memory below 64 MiB is not supported");
exit(1);
}
dev = qdev_new(TYPE_PPC4xx_SDRAM_DDR2);
object_property_set_link(OBJECT(dev), "dram", OBJECT(machine->ram),
&error_abort);
/*
* Put all RAM on first bank because board has one slot
* and firmware only checks that
*/
object_property_set_int(OBJECT(dev), "nbanks", 1, &error_abort);
ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal);
object_unref(OBJECT(dev));
/* FIXME: does 460EX have ECC interrupts? */
ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories,
ram_bases, ram_sizes, 1);
/* Enable SDRAM memory regions as we may boot without firmware */
ppc4xx_sdram_ddr2_enable(PPC4xx_SDRAM_DDR2(dev));
/* IIC controllers and devices */
dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700,
qdev_get_gpio_in(uic[0], 2));
i2c = PPC4xx_I2C(dev)->bus;
/* SPD EEPROM on RAM module */
spd_data = spd_data_generate(ram_sizes[0] < 128 * MiB ? DDR : DDR2,
ram_sizes[0]);
spd_data = spd_data_generate(machine->ram_size < 128 * MiB ? DDR : DDR2,
machine->ram_size);
spd_data[20] = 4; /* SO-DIMM module */
smbus_eeprom_init_one(i2c, 0x50, spd_data);
/* RTC */
@ -496,9 +502,8 @@ static void sam460ex_init(MachineState *machine)
if (machine->kernel_filename) {
int dt_size;
dt_size = sam460ex_load_device_tree(FDT_ADDR, machine->ram_size,
RAMDISK_ADDR, initrd_size,
machine->kernel_cmdline);
dt_size = sam460ex_load_device_tree(machine, FDT_ADDR,
RAMDISK_ADDR, initrd_size);
boot_info->dt_base = FDT_ADDR;
boot_info->dt_size = dt_size;

View File

@ -1713,6 +1713,9 @@ static void spapr_machine_reset(MachineState *machine)
spapr->fdt_initial_size = spapr->fdt_size;
spapr->fdt_blob = fdt;
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
machine->fdt = fdt;
/* Set up the entry state */
first_ppc_cpu->env.gpr[5] = 0;

View File

@ -1256,6 +1256,14 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu,
spapr->fdt_initial_size = spapr->fdt_size;
spapr->fdt_blob = fdt;
/*
* Set the machine->fdt pointer again since we just freed
* it above (by freeing spapr->fdt_blob). We set this
* pointer to enable support for the 'dumpdtb' QMP/HMP
* command.
*/
MACHINE(spapr)->fdt = fdt;
return H_SUCCESS;
}

View File

@ -2045,7 +2045,7 @@ static int spapr_phb_children_reset(Object *child, void *opaque)
DeviceState *dev = (DeviceState *) object_dynamic_cast(child, TYPE_DEVICE);
if (dev) {
device_legacy_reset(dev);
device_cold_reset(dev);
}
return 0;

View File

@ -45,6 +45,8 @@
#include "hw/qdev-properties.h"
#include "ppc405.h"
#include <libfdt.h>
#define EPAPR_MAGIC (0x45504150)
#define FLASH_SIZE (16 * MiB)
@ -144,11 +146,10 @@ static void main_cpu_reset(void *opaque)
}
#define BINARY_DEVICE_TREE_FILE "virtex-ml507.dtb"
static int xilinx_load_device_tree(hwaddr addr,
uint32_t ramsize,
hwaddr initrd_base,
hwaddr initrd_size,
const char *kernel_cmdline)
static int xilinx_load_device_tree(MachineState *machine,
hwaddr addr,
hwaddr initrd_base,
hwaddr initrd_size)
{
char *path;
int fdt_size;
@ -190,18 +191,21 @@ static int xilinx_load_device_tree(hwaddr addr,
error_report("couldn't set /chosen/linux,initrd-end");
}
r = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
r = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
machine->kernel_cmdline);
if (r < 0)
fprintf(stderr, "couldn't set /chosen/bootargs\n");
cpu_physical_memory_write(addr, fdt, fdt_size);
g_free(fdt);
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
machine->fdt = fdt;
return fdt_size;
}
static void virtex_init(MachineState *machine)
{
const char *kernel_filename = machine->kernel_filename;
const char *kernel_cmdline = machine->kernel_cmdline;
hwaddr initrd_base = 0;
int initrd_size = 0;
MemoryRegion *address_space_mem = get_system_memory();
@ -294,9 +298,8 @@ static void virtex_init(MachineState *machine)
boot_info.fdt = high + (8192 * 2);
boot_info.fdt &= ~8191;
xilinx_load_device_tree(boot_info.fdt, machine->ram_size,
initrd_base, initrd_size,
kernel_cmdline);
xilinx_load_device_tree(machine, boot_info.fdt,
initrd_base, initrd_size);
}
env->load_info = &boot_info;
}

View File

@ -634,6 +634,9 @@ static void sifive_u_machine_init(MachineState *machine)
start_addr_hi32 = (uint64_t)start_addr >> 32;
}
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
machine->fdt = s->fdt;
/* reset vector */
uint32_t reset_vec[12] = {
s->msel, /* MSEL pin state */

View File

@ -40,6 +40,8 @@
#include "sysemu/device_tree.h"
#include "sysemu/sysemu.h"
#include <libfdt.h>
static const MemMapEntry spike_memmap[] = {
[SPIKE_MROM] = { 0x1000, 0xf000 },
[SPIKE_HTIF] = { 0x1000000, 0x1000 },
@ -304,6 +306,10 @@ static void spike_board_init(MachineState *machine)
/* Compute the fdt load address in dram */
fdt_load_addr = riscv_load_fdt(memmap[SPIKE_DRAM].base,
machine->ram_size, s->fdt);
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
machine->fdt = s->fdt;
/* load the reset vector */
riscv_setup_rom_reset_vec(machine, &s->soc[0], memmap[SPIKE_DRAM].base,
memmap[SPIKE_MROM].base,

View File

@ -29,16 +29,17 @@
#include "exec/memory.h"
#include "hw/sysbus.h"
void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
MemoryRegion ram_memories[],
hwaddr ram_bases[], hwaddr ram_sizes[],
const ram_addr_t sdram_bank_sizes[]);
typedef struct {
MemoryRegion ram;
MemoryRegion container; /* used for clipping */
hwaddr base;
hwaddr size;
uint32_t bcr;
} Ppc4xxSdramBank;
void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
MemoryRegion ram_memories[],
hwaddr *ram_bases,
hwaddr *ram_sizes,
int do_init);
void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
Ppc4xxSdramBank ram_banks[],
const ram_addr_t sdram_bank_sizes[]);
#define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"
@ -109,4 +110,50 @@ struct Ppc4xxEbcState {
uint32_t cfg;
};
/* SDRAM DDR controller */
#define SDR0_DDR0_DDRM_ENCODE(n) ((((unsigned long)(n)) & 0x03) << 29)
#define SDR0_DDR0_DDRM_DDR1 0x20000000
#define SDR0_DDR0_DDRM_DDR2 0x40000000
#define TYPE_PPC4xx_SDRAM_DDR "ppc4xx-sdram-ddr"
OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxSdramDdrState, PPC4xx_SDRAM_DDR);
struct Ppc4xxSdramDdrState {
Ppc4xxDcrDeviceState parent_obj;
MemoryRegion *dram_mr;
uint32_t nbanks; /* Banks to use from 4, e.g. when board has less slots */
Ppc4xxSdramBank bank[4];
qemu_irq irq;
uint32_t addr;
uint32_t besr0;
uint32_t besr1;
uint32_t bear;
uint32_t cfg;
uint32_t status;
uint32_t rtr;
uint32_t pmit;
uint32_t tr;
uint32_t ecccfg;
uint32_t eccesr;
};
void ppc4xx_sdram_ddr_enable(Ppc4xxSdramDdrState *s);
/* SDRAM DDR2 controller */
#define TYPE_PPC4xx_SDRAM_DDR2 "ppc4xx-sdram-ddr2"
OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxSdramDdr2State, PPC4xx_SDRAM_DDR2);
struct Ppc4xxSdramDdr2State {
Ppc4xxDcrDeviceState parent_obj;
MemoryRegion *dram_mr;
uint32_t nbanks; /* Banks to use from 4, e.g. when board has less slots */
Ppc4xxSdramBank bank[4];
uint32_t addr;
uint32_t mcopt2;
};
void ppc4xx_sdram_ddr2_enable(Ppc4xxSdramDdr2State *s);
#endif /* PPC4XX_H */

View File

@ -136,6 +136,7 @@ int qemu_fdt_add_path(void *fdt, const char *path);
} while (0)
void qemu_fdt_dumpdtb(void *fdt, int size);
void hmp_dumpdtb(Monitor *mon, const QDict *qdict);
/**
* qemu_fdt_setprop_sized_cells_from_array:

View File

@ -49,6 +49,7 @@
#include "sysemu/blockdev.h"
#include "sysemu/sysemu.h"
#include "sysemu/tpm.h"
#include "sysemu/device_tree.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.h"
#include "qapi/qmp/qstring.h"

View File

@ -1664,3 +1664,21 @@
'*size': 'size',
'*max-size': 'size',
'*slots': 'uint64' } }
##
# @dumpdtb:
#
# Save the FDT in dtb format.
#
# @filename: name of the dtb file to be created
#
# Since: 7.2
#
# Example:
# {"execute": "dumpdtb"}
# "arguments": { "filename": "fdt.dtb" } }
#
##
{ 'command': 'dumpdtb',
'data': { 'filename': 'str' },
'if': 'CONFIG_FDT' }

View File

@ -26,6 +26,9 @@
#include "hw/loader.h"
#include "hw/boards.h"
#include "qemu/config-file.h"
#include "qapi/qapi-commands-machine.h"
#include "qapi/qmp/qdict.h"
#include "monitor/hmp.h"
#include <libfdt.h>
@ -643,3 +646,37 @@ out:
g_free(propcells);
return ret;
}
void qmp_dumpdtb(const char *filename, Error **errp)
{
g_autoptr(GError) err = NULL;
uint32_t size;
if (!current_machine->fdt) {
error_setg(errp, "This machine doesn't have a FDT");
return;
}
size = fdt_totalsize(current_machine->fdt);
g_assert(size > 0);
if (!g_file_set_contents(filename, current_machine->fdt, size, &err)) {
error_setg(errp, "Error saving FDT to file %s: %s",
filename, err->message);
}
}
void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
{
const char *filename = qdict_get_str(qdict, "filename");
Error *local_err = NULL;
qmp_dumpdtb(filename, &local_err);
if (hmp_handle_error(mon, local_err)) {
return;
}
info_report("dtb dumped to %s", filename);
}

View File

@ -1247,6 +1247,12 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */
env->spr[SPR_BOOKE_ESR] = ESR_SPV;
break;
case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
break;
case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
srr0 = SPR_BOOKE_CSRR0;
srr1 = SPR_BOOKE_CSRR1;
break;
case POWERPC_EXCP_RESET: /* System reset exception */
if (FIELD_EX64(env->msr, MSR, POW)) {
cpu_abort(cs, "Trying to deliver power-saving system reset "

View File

@ -810,7 +810,6 @@ static void gen_##name(DisasContext *ctx) \
gen_helper_##name(ignored, cpu_env, xt, xa, xb); \
tcg_temp_free_i32(ignored); \
} \
gen_helper_float_check_status(cpu_env); \
tcg_temp_free_ptr(xt); \
tcg_temp_free_ptr(xa); \
tcg_temp_free_ptr(xb); \