Patch queue for ppc - 2013-12-20

Alexander Graf (3):
       PPC: Use default pci bus name for grackle and heathrow
       roms: Flush icache when writing roms to guest memory
       PPC: Add VSX to hflags
 
 Alexey Kardashevskiy (5):
       powerpc: add PVR mask support
       target-ppc: move POWER7+ to a separate family
       spapr-rtas: replace return code constants with macros
       spapr-rtas: add ibm, (get|set)-system-parameter
       spapr: make sure RMA is in first mode of first memory node
 
 Greg Kurz (1):
       target-ppc: add stubs for KVM breakpoints
 
 Paolo Bonzini (1):
       spapr: tie spapr-nvram to -pflash
 
 Paul Mackerras (1):
       spapr: limit numa memory regions by ram size
 
 Peter Crosthwaite (2):
       device_tree: s/qemu_devtree/qemu_fdt globally
       device_tree: qemu_fdt_setprop: Rename val_array arg
 
 Tom Musta (19):
       Declare and Enable VSX
       Add MSR VSX and Associated Exception
       Add VSX Instruction Decoders
       Add VSR to Global Registers
       Add lxvd2x
       Add stxvd2x
       Add xxpermdi
       Add lxsdx
       Add lxvdsx
       Add lxvw4x
       Add stxsdx
       Add stxvw4x
       Add VSX Scalar Move Instructions
       Add VSX Vector Move Instructions
       Add Power7 VSX Logical Instructions
       Add xxmrgh/xxmrgl
       Add xxsel
       Add xxspltw
       Add xxsldwi
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.19 (GNU/Linux)
 
 iQIcBAABAgAGBQJSs5ZfAAoJECszeR4D/txgvxEP/2J1FFHFLNTOyvrlDl5gpIBK
 Bq5O5JYIYqEaOSkn1xq5wl5i/V9pM5EgxbJYEXslBBA9uSs4rNSsC558pfjM5nl1
 L2pFbpmy1fgz6dGwdPpUgwPZKzutI2+FXvE+HI3Ee8LrIC24TGMni6hmmXSrhNaa
 962G3kev/pKocBZBKa8Uj49n1T8voHEI0lrPa1Y+IWhPrmO4X2zqBOQEaFmOUxw5
 5MO+veFe7w9iw8gZKjyiS6Q46ootsczzd9lKf2cq9mmSN5IxQsMeRZj0GEIOjL1M
 ibhQT6f1pRXlKVLdNuNMA1YrGlyT+HWiyZSXjq4uQsMWjOk+WiUJkiQcftjitBRV
 UUBQ+kf6GcEPJNaz0WdJrkgacHrqQJ0W21wxZYf5q4/KSdUDX9hbjdmsM87jwWGS
 /eZqsbo/0s+fpSNS5hAbmVJuZHEyeN/g6VJDFLcURApt8oYt05xIMflyeUSO0RJW
 rG2GFJEMfUKCGFPEKrZ30d91m7DSnh75EabMwHxIq2TMHL1u9UWEP6DXjnIWiZWt
 X9qG3T84elsCowWzsTWlKhdjoI3YVcYek0L8LOp1JBINX/GyK4xij7abwqmhjyef
 gC3+uIinm3PecIH/gLzJcKRBbcywGqKYOIE2iyaM8Nk8XXBUjaMWp37p33C2XhKh
 hB1+q8+Bjx0PEJDKAfPI
 =70tP
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'agraf/tags/signed-ppc-for-upstream' into staging

Patch queue for ppc - 2013-12-20

Alexander Graf (3):
      PPC: Use default pci bus name for grackle and heathrow
      roms: Flush icache when writing roms to guest memory
      PPC: Add VSX to hflags

Alexey Kardashevskiy (5):
      powerpc: add PVR mask support
      target-ppc: move POWER7+ to a separate family
      spapr-rtas: replace return code constants with macros
      spapr-rtas: add ibm, (get|set)-system-parameter
      spapr: make sure RMA is in first mode of first memory node

Greg Kurz (1):
      target-ppc: add stubs for KVM breakpoints

Paolo Bonzini (1):
      spapr: tie spapr-nvram to -pflash

Paul Mackerras (1):
      spapr: limit numa memory regions by ram size

Peter Crosthwaite (2):
      device_tree: s/qemu_devtree/qemu_fdt globally
      device_tree: qemu_fdt_setprop: Rename val_array arg

Tom Musta (19):
      Declare and Enable VSX
      Add MSR VSX and Associated Exception
      Add VSX Instruction Decoders
      Add VSR to Global Registers
      Add lxvd2x
      Add stxvd2x
      Add xxpermdi
      Add lxsdx
      Add lxvdsx
      Add lxvw4x
      Add stxsdx
      Add stxvw4x
      Add VSX Scalar Move Instructions
      Add VSX Vector Move Instructions
      Add Power7 VSX Logical Instructions
      Add xxmrgh/xxmrgl
      Add xxsel
      Add xxspltw
      Add xxsldwi

* agraf/tags/signed-ppc-for-upstream: (32 commits)
  spapr: limit numa memory regions by ram size
  spapr: make sure RMA is in first mode of first memory node
  device_tree: qemu_fdt_setprop: Rename val_array arg
  device_tree: s/qemu_devtree/qemu_fdt globally
  PPC: Add VSX to hflags
  Add xxsldwi
  Add xxspltw
  Add xxsel
  Add xxmrgh/xxmrgl
  Add Power7 VSX Logical Instructions
  Add VSX Vector Move Instructions
  Add VSX Scalar Move Instructions
  roms: Flush icache when writing roms to guest memory
  spapr: tie spapr-nvram to -pflash
  PPC: Use default pci bus name for grackle and heathrow
  spapr-rtas: add ibm, (get|set)-system-parameter
  spapr-rtas: replace return code constants with macros
  target-ppc: move POWER7+ to a separate family
  Add stxvw4x
  Add stxsdx
  ...
master
Anthony Liguori 2013-12-19 17:03:17 -08:00
commit f8251db121
33 changed files with 1237 additions and 387 deletions

View File

@ -131,12 +131,12 @@ static int findnode_nofail(void *fdt, const char *node_path)
return offset;
}
int qemu_devtree_setprop(void *fdt, const char *node_path,
const char *property, const void *val_array, int size)
int qemu_fdt_setprop(void *fdt, const char *node_path,
const char *property, const void *val, int size)
{
int r;
r = fdt_setprop(fdt, findnode_nofail(fdt, node_path), property, val_array, size);
r = fdt_setprop(fdt, findnode_nofail(fdt, node_path), property, val, size);
if (r < 0) {
fprintf(stderr, "%s: Couldn't set %s/%s: %s\n", __func__, node_path,
property, fdt_strerror(r));
@ -146,8 +146,8 @@ int qemu_devtree_setprop(void *fdt, const char *node_path,
return r;
}
int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
const char *property, uint32_t val)
int qemu_fdt_setprop_cell(void *fdt, const char *node_path,
const char *property, uint32_t val)
{
int r;
@ -161,15 +161,15 @@ int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
return r;
}
int qemu_devtree_setprop_u64(void *fdt, const char *node_path,
const char *property, uint64_t val)
int qemu_fdt_setprop_u64(void *fdt, const char *node_path,
const char *property, uint64_t val)
{
val = cpu_to_be64(val);
return qemu_devtree_setprop(fdt, node_path, property, &val, sizeof(val));
return qemu_fdt_setprop(fdt, node_path, property, &val, sizeof(val));
}
int qemu_devtree_setprop_string(void *fdt, const char *node_path,
const char *property, const char *string)
int qemu_fdt_setprop_string(void *fdt, const char *node_path,
const char *property, const char *string)
{
int r;
@ -183,8 +183,8 @@ int qemu_devtree_setprop_string(void *fdt, const char *node_path,
return r;
}
const void *qemu_devtree_getprop(void *fdt, const char *node_path,
const char *property, int *lenp)
const void *qemu_fdt_getprop(void *fdt, const char *node_path,
const char *property, int *lenp)
{
int len;
const void *r;
@ -200,11 +200,11 @@ const void *qemu_devtree_getprop(void *fdt, const char *node_path,
return r;
}
uint32_t qemu_devtree_getprop_cell(void *fdt, const char *node_path,
const char *property)
uint32_t qemu_fdt_getprop_cell(void *fdt, const char *node_path,
const char *property)
{
int len;
const uint32_t *p = qemu_devtree_getprop(fdt, node_path, property, &len);
const uint32_t *p = qemu_fdt_getprop(fdt, node_path, property, &len);
if (len != 4) {
fprintf(stderr, "%s: %s/%s not 4 bytes long (not a cell?)\n",
__func__, node_path, property);
@ -213,7 +213,7 @@ uint32_t qemu_devtree_getprop_cell(void *fdt, const char *node_path,
return be32_to_cpu(*p);
}
uint32_t qemu_devtree_get_phandle(void *fdt, const char *path)
uint32_t qemu_fdt_get_phandle(void *fdt, const char *path)
{
uint32_t r;
@ -227,15 +227,15 @@ uint32_t qemu_devtree_get_phandle(void *fdt, const char *path)
return r;
}
int qemu_devtree_setprop_phandle(void *fdt, const char *node_path,
const char *property,
const char *target_node_path)
int qemu_fdt_setprop_phandle(void *fdt, const char *node_path,
const char *property,
const char *target_node_path)
{
uint32_t phandle = qemu_devtree_get_phandle(fdt, target_node_path);
return qemu_devtree_setprop_cell(fdt, node_path, property, phandle);
uint32_t phandle = qemu_fdt_get_phandle(fdt, target_node_path);
return qemu_fdt_setprop_cell(fdt, node_path, property, phandle);
}
uint32_t qemu_devtree_alloc_phandle(void *fdt)
uint32_t qemu_fdt_alloc_phandle(void *fdt)
{
static int phandle = 0x0;
@ -259,7 +259,7 @@ uint32_t qemu_devtree_alloc_phandle(void *fdt)
return phandle++;
}
int qemu_devtree_nop_node(void *fdt, const char *node_path)
int qemu_fdt_nop_node(void *fdt, const char *node_path)
{
int r;
@ -273,7 +273,7 @@ int qemu_devtree_nop_node(void *fdt, const char *node_path)
return r;
}
int qemu_devtree_add_subnode(void *fdt, const char *name)
int qemu_fdt_add_subnode(void *fdt, const char *name)
{
char *dupname = g_strdup(name);
char *basename = strrchr(dupname, '/');
@ -303,7 +303,7 @@ int qemu_devtree_add_subnode(void *fdt, const char *name)
return retval;
}
void qemu_devtree_dumpdtb(void *fdt, int size)
void qemu_fdt_dumpdtb(void *fdt, int size)
{
const char *dumpdtb = qemu_opt_get(qemu_get_machine_opts(), "dumpdtb");
@ -313,11 +313,11 @@ void qemu_devtree_dumpdtb(void *fdt, int size)
}
}
int qemu_devtree_setprop_sized_cells_from_array(void *fdt,
const char *node_path,
const char *property,
int numvalues,
uint64_t *values)
int qemu_fdt_setprop_sized_cells_from_array(void *fdt,
const char *node_path,
const char *property,
int numvalues,
uint64_t *values)
{
uint32_t *propcells;
uint64_t value;
@ -342,6 +342,6 @@ int qemu_devtree_setprop_sized_cells_from_array(void *fdt,
propcells[cellnum++] = cpu_to_be32(value);
}
return qemu_devtree_setprop(fdt, node_path, property, propcells,
cellnum * sizeof(uint32_t));
return qemu_fdt_setprop(fdt, node_path, property, propcells,
cellnum * sizeof(uint32_t));
}

44
exec.c
View File

@ -50,6 +50,7 @@
#include "translate-all.h"
#include "exec/memory-internal.h"
#include "qemu/cache-utils.h"
#include "qemu/range.h"
@ -2070,9 +2071,13 @@ void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
address_space_rw(&address_space_memory, addr, buf, len, is_write);
}
/* used for ROM loading : can write in RAM and ROM */
void cpu_physical_memory_write_rom(hwaddr addr,
const uint8_t *buf, int len)
enum write_rom_type {
WRITE_DATA,
FLUSH_CACHE,
};
static inline void cpu_physical_memory_write_rom_internal(
hwaddr addr, const uint8_t *buf, int len, enum write_rom_type type)
{
hwaddr l;
uint8_t *ptr;
@ -2091,8 +2096,15 @@ void cpu_physical_memory_write_rom(hwaddr addr,
addr1 += memory_region_get_ram_addr(mr);
/* ROM/RAM case */
ptr = qemu_get_ram_ptr(addr1);
memcpy(ptr, buf, l);
invalidate_and_set_dirty(addr1, l);
switch (type) {
case WRITE_DATA:
memcpy(ptr, buf, l);
invalidate_and_set_dirty(addr1, l);
break;
case FLUSH_CACHE:
flush_icache_range((uintptr_t)ptr, (uintptr_t)ptr + l);
break;
}
}
len -= l;
buf += l;
@ -2100,6 +2112,28 @@ void cpu_physical_memory_write_rom(hwaddr addr,
}
}
/* used for ROM loading : can write in RAM and ROM */
void cpu_physical_memory_write_rom(hwaddr addr,
const uint8_t *buf, int len)
{
cpu_physical_memory_write_rom_internal(addr, buf, len, WRITE_DATA);
}
void cpu_flush_icache_range(hwaddr start, int len)
{
/*
* This function should do the same thing as an icache flush that was
* triggered from within the guest. For TCG we are always cache coherent,
* so there is no need to flush anything. For KVM / Xen we need to flush
* the host's instruction cache at least.
*/
if (tcg_enabled()) {
return;
}
cpu_physical_memory_write_rom_internal(start, NULL, len, FLUSH_CACHE);
}
typedef struct {
MemoryRegion *mr;
void *buffer;

View File

@ -335,8 +335,8 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
}
}
acells = qemu_devtree_getprop_cell(fdt, "/", "#address-cells");
scells = qemu_devtree_getprop_cell(fdt, "/", "#size-cells");
acells = qemu_fdt_getprop_cell(fdt, "/", "#address-cells");
scells = qemu_fdt_getprop_cell(fdt, "/", "#size-cells");
if (acells == 0 || scells == 0) {
fprintf(stderr, "dtb file invalid (#address-cells or #size-cells 0)\n");
goto fail;
@ -351,17 +351,17 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
goto fail;
}
rc = qemu_devtree_setprop_sized_cells(fdt, "/memory", "reg",
acells, binfo->loader_start,
scells, binfo->ram_size);
rc = qemu_fdt_setprop_sized_cells(fdt, "/memory", "reg",
acells, binfo->loader_start,
scells, binfo->ram_size);
if (rc < 0) {
fprintf(stderr, "couldn't set /memory/reg\n");
goto fail;
}
if (binfo->kernel_cmdline && *binfo->kernel_cmdline) {
rc = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
binfo->kernel_cmdline);
rc = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
binfo->kernel_cmdline);
if (rc < 0) {
fprintf(stderr, "couldn't set /chosen/bootargs\n");
goto fail;
@ -369,15 +369,15 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
}
if (binfo->initrd_size) {
rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
binfo->initrd_start);
rc = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
binfo->initrd_start);
if (rc < 0) {
fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
goto fail;
}
rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
binfo->initrd_start + binfo->initrd_size);
rc = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
binfo->initrd_start + binfo->initrd_size);
if (rc < 0) {
fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
goto fail;
@ -388,7 +388,7 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
binfo->modify_dtb(binfo, fdt);
}
qemu_devtree_dumpdtb(fdt, size);
qemu_fdt_dumpdtb(fdt, size);
cpu_physical_memory_write(addr, fdt, size);

View File

@ -419,13 +419,13 @@ static int add_virtio_mmio_node(void *fdt, uint32_t acells, uint32_t scells,
int rc;
char *nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, addr);
rc = qemu_devtree_add_subnode(fdt, nodename);
rc |= qemu_devtree_setprop_string(fdt, nodename,
"compatible", "virtio,mmio");
rc |= qemu_devtree_setprop_sized_cells(fdt, nodename, "reg",
acells, addr, scells, size);
qemu_devtree_setprop_cells(fdt, nodename, "interrupt-parent", intc);
qemu_devtree_setprop_cells(fdt, nodename, "interrupts", 0, irq, 1);
rc = qemu_fdt_add_subnode(fdt, nodename);
rc |= qemu_fdt_setprop_string(fdt, nodename,
"compatible", "virtio,mmio");
rc |= qemu_fdt_setprop_sized_cells(fdt, nodename, "reg",
acells, addr, scells, size);
qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", intc);
qemu_fdt_setprop_cells(fdt, nodename, "interrupts", 0, irq, 1);
g_free(nodename);
if (rc) {
return -1;
@ -456,8 +456,8 @@ static void vexpress_modify_dtb(const struct arm_boot_info *info, void *fdt)
uint32_t acells, scells, intc;
const VEDBoardInfo *daughterboard = (const VEDBoardInfo *)info;
acells = qemu_devtree_getprop_cell(fdt, "/", "#address-cells");
scells = qemu_devtree_getprop_cell(fdt, "/", "#size-cells");
acells = qemu_fdt_getprop_cell(fdt, "/", "#address-cells");
scells = qemu_fdt_getprop_cell(fdt, "/", "#size-cells");
intc = find_int_controller(fdt);
if (!intc) {
/* Not fatal, we just won't provide virtio. This will

View File

@ -156,42 +156,42 @@ static void create_fdt(VirtBoardInfo *vbi)
vbi->fdt = fdt;
/* Header */
qemu_devtree_setprop_string(fdt, "/", "compatible", "linux,dummy-virt");
qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 0x2);
qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 0x2);
qemu_fdt_setprop_string(fdt, "/", "compatible", "linux,dummy-virt");
qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
/*
* /chosen and /memory nodes must exist for load_dtb
* to fill in necessary properties later
*/
qemu_devtree_add_subnode(fdt, "/chosen");
qemu_devtree_add_subnode(fdt, "/memory");
qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory");
qemu_fdt_add_subnode(fdt, "/chosen");
qemu_fdt_add_subnode(fdt, "/memory");
qemu_fdt_setprop_string(fdt, "/memory", "device_type", "memory");
/* Clock node, for the benefit of the UART. The kernel device tree
* binding documentation claims the PL011 node clock properties are
* optional but in practice if you omit them the kernel refuses to
* probe for the device.
*/
vbi->clock_phandle = qemu_devtree_alloc_phandle(fdt);
qemu_devtree_add_subnode(fdt, "/apb-pclk");
qemu_devtree_setprop_string(fdt, "/apb-pclk", "compatible", "fixed-clock");
qemu_devtree_setprop_cell(fdt, "/apb-pclk", "#clock-cells", 0x0);
qemu_devtree_setprop_cell(fdt, "/apb-pclk", "clock-frequency", 24000000);
qemu_devtree_setprop_string(fdt, "/apb-pclk", "clock-output-names",
vbi->clock_phandle = qemu_fdt_alloc_phandle(fdt);
qemu_fdt_add_subnode(fdt, "/apb-pclk");
qemu_fdt_setprop_string(fdt, "/apb-pclk", "compatible", "fixed-clock");
qemu_fdt_setprop_cell(fdt, "/apb-pclk", "#clock-cells", 0x0);
qemu_fdt_setprop_cell(fdt, "/apb-pclk", "clock-frequency", 24000000);
qemu_fdt_setprop_string(fdt, "/apb-pclk", "clock-output-names",
"clk24mhz");
qemu_devtree_setprop_cell(fdt, "/apb-pclk", "phandle", vbi->clock_phandle);
qemu_fdt_setprop_cell(fdt, "/apb-pclk", "phandle", vbi->clock_phandle);
/* No PSCI for TCG yet */
if (kvm_enabled()) {
qemu_devtree_add_subnode(fdt, "/psci");
qemu_devtree_setprop_string(fdt, "/psci", "compatible", "arm,psci");
qemu_devtree_setprop_string(fdt, "/psci", "method", "hvc");
qemu_devtree_setprop_cell(fdt, "/psci", "cpu_suspend",
qemu_fdt_add_subnode(fdt, "/psci");
qemu_fdt_setprop_string(fdt, "/psci", "compatible", "arm,psci");
qemu_fdt_setprop_string(fdt, "/psci", "method", "hvc");
qemu_fdt_setprop_cell(fdt, "/psci", "cpu_suspend",
PSCI_FN_CPU_SUSPEND);
qemu_devtree_setprop_cell(fdt, "/psci", "cpu_off", PSCI_FN_CPU_OFF);
qemu_devtree_setprop_cell(fdt, "/psci", "cpu_on", PSCI_FN_CPU_ON);
qemu_devtree_setprop_cell(fdt, "/psci", "migrate", PSCI_FN_MIGRATE);
qemu_fdt_setprop_cell(fdt, "/psci", "cpu_off", PSCI_FN_CPU_OFF);
qemu_fdt_setprop_cell(fdt, "/psci", "cpu_on", PSCI_FN_CPU_ON);
qemu_fdt_setprop_cell(fdt, "/psci", "migrate", PSCI_FN_MIGRATE);
}
}
@ -206,10 +206,10 @@ static void fdt_add_timer_nodes(const VirtBoardInfo *vbi)
irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
GIC_FDT_IRQ_PPI_CPU_WIDTH, (1 << vbi->smp_cpus) - 1);
qemu_devtree_add_subnode(vbi->fdt, "/timer");
qemu_devtree_setprop_string(vbi->fdt, "/timer",
qemu_fdt_add_subnode(vbi->fdt, "/timer");
qemu_fdt_setprop_string(vbi->fdt, "/timer",
"compatible", "arm,armv7-timer");
qemu_devtree_setprop_cells(vbi->fdt, "/timer", "interrupts",
qemu_fdt_setprop_cells(vbi->fdt, "/timer", "interrupts",
GIC_FDT_IRQ_TYPE_PPI, 13, irqflags,
GIC_FDT_IRQ_TYPE_PPI, 14, irqflags,
GIC_FDT_IRQ_TYPE_PPI, 11, irqflags,
@ -220,25 +220,25 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
{
int cpu;
qemu_devtree_add_subnode(vbi->fdt, "/cpus");
qemu_devtree_setprop_cell(vbi->fdt, "/cpus", "#address-cells", 0x1);
qemu_devtree_setprop_cell(vbi->fdt, "/cpus", "#size-cells", 0x0);
qemu_fdt_add_subnode(vbi->fdt, "/cpus");
qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#address-cells", 0x1);
qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#size-cells", 0x0);
for (cpu = vbi->smp_cpus - 1; cpu >= 0; cpu--) {
char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
qemu_devtree_add_subnode(vbi->fdt, nodename);
qemu_devtree_setprop_string(vbi->fdt, nodename, "device_type", "cpu");
qemu_devtree_setprop_string(vbi->fdt, nodename, "compatible",
qemu_fdt_add_subnode(vbi->fdt, nodename);
qemu_fdt_setprop_string(vbi->fdt, nodename, "device_type", "cpu");
qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible",
armcpu->dtb_compatible);
if (vbi->smp_cpus > 1) {
qemu_devtree_setprop_string(vbi->fdt, nodename,
qemu_fdt_setprop_string(vbi->fdt, nodename,
"enable-method", "psci");
}
qemu_devtree_setprop_cell(vbi->fdt, nodename, "reg", cpu);
qemu_fdt_setprop_cell(vbi->fdt, nodename, "reg", cpu);
g_free(nodename);
}
}
@ -247,20 +247,20 @@ static void fdt_add_gic_node(const VirtBoardInfo *vbi)
{
uint32_t gic_phandle;
gic_phandle = qemu_devtree_alloc_phandle(vbi->fdt);
qemu_devtree_setprop_cell(vbi->fdt, "/", "interrupt-parent", gic_phandle);
gic_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", gic_phandle);
qemu_devtree_add_subnode(vbi->fdt, "/intc");
qemu_devtree_setprop_string(vbi->fdt, "/intc", "compatible",
qemu_fdt_add_subnode(vbi->fdt, "/intc");
qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
vbi->gic_compatible);
qemu_devtree_setprop_cell(vbi->fdt, "/intc", "#interrupt-cells", 3);
qemu_devtree_setprop(vbi->fdt, "/intc", "interrupt-controller", NULL, 0);
qemu_devtree_setprop_sized_cells(vbi->fdt, "/intc", "reg",
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#interrupt-cells", 3);
qemu_fdt_setprop(vbi->fdt, "/intc", "interrupt-controller", NULL, 0);
qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
2, vbi->memmap[VIRT_GIC_DIST].base,
2, vbi->memmap[VIRT_GIC_DIST].size,
2, vbi->memmap[VIRT_GIC_CPU].base,
2, vbi->memmap[VIRT_GIC_CPU].size);
qemu_devtree_setprop_cell(vbi->fdt, "/intc", "phandle", gic_phandle);
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", gic_phandle);
}
static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
@ -275,18 +275,18 @@ static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
sysbus_create_simple("pl011", base, pic[irq]);
nodename = g_strdup_printf("/pl011@%" PRIx64, base);
qemu_devtree_add_subnode(vbi->fdt, nodename);
qemu_fdt_add_subnode(vbi->fdt, nodename);
/* Note that we can't use setprop_string because of the embedded NUL */
qemu_devtree_setprop(vbi->fdt, nodename, "compatible",
qemu_fdt_setprop(vbi->fdt, nodename, "compatible",
compat, sizeof(compat));
qemu_devtree_setprop_sized_cells(vbi->fdt, nodename, "reg",
qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
2, base, 2, size);
qemu_devtree_setprop_cells(vbi->fdt, nodename, "interrupts",
qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_SPI, irq,
GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
qemu_devtree_setprop_cells(vbi->fdt, nodename, "clocks",
qemu_fdt_setprop_cells(vbi->fdt, nodename, "clocks",
vbi->clock_phandle, vbi->clock_phandle);
qemu_devtree_setprop(vbi->fdt, nodename, "clock-names",
qemu_fdt_setprop(vbi->fdt, nodename, "clock-names",
clocknames, sizeof(clocknames));
g_free(nodename);
}
@ -314,14 +314,14 @@ static void create_virtio_devices(const VirtBoardInfo *vbi, qemu_irq *pic)
hwaddr base = vbi->memmap[VIRT_MMIO].base + i * size;
nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
qemu_devtree_add_subnode(vbi->fdt, nodename);
qemu_devtree_setprop_string(vbi->fdt, nodename,
"compatible", "virtio,mmio");
qemu_devtree_setprop_sized_cells(vbi->fdt, nodename, "reg",
2, base, 2, size);
qemu_devtree_setprop_cells(vbi->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_SPI, irq,
GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
qemu_fdt_add_subnode(vbi->fdt, nodename);
qemu_fdt_setprop_string(vbi->fdt, nodename,
"compatible", "virtio,mmio");
qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
2, base, 2, size);
qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts",
GIC_FDT_IRQ_TYPE_SPI, irq,
GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
g_free(nodename);
}
}

View File

@ -785,6 +785,13 @@ static void rom_reset(void *unused)
g_free(rom->data);
rom->data = NULL;
}
/*
* The rom loader is really on the same level as firmware in the guest
* shadowing a ROM into RAM. Such a shadowing mechanism needs to ensure
* that the instruction cache for that new region is clear, so that the
* CPU definitely fetches its instructions from the just written data.
*/
cpu_flush_icache_range(rom->addr, rom->datasize);
}
}

View File

@ -723,7 +723,7 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t nr, server, priority;
if ((nargs != 3) || (nret != 1)) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
@ -733,13 +733,13 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
|| (priority > 0xff)) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
ics_write_xive(ics, nr, server, priority, priority);
rtas_st(rets, 0, 0); /* Success */
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
static void rtas_get_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
@ -751,18 +751,18 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t nr;
if ((nargs != 1) || (nret != 3)) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
nr = rtas_ld(args, 0);
if (!ics_valid_irq(ics, nr)) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
rtas_st(rets, 0, 0); /* Success */
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
}
@ -776,21 +776,21 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t nr;
if ((nargs != 1) || (nret != 1)) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
nr = rtas_ld(args, 0);
if (!ics_valid_irq(ics, nr)) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
ics->irqs[nr - ics->offset].priority);
rtas_st(rets, 0, 0); /* Success */
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
static void rtas_int_on(PowerPCCPU *cpu, sPAPREnvironment *spapr,
@ -802,14 +802,14 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t nr;
if ((nargs != 1) || (nret != 1)) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
nr = rtas_ld(args, 0);
if (!ics_valid_irq(ics, nr)) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
@ -817,7 +817,7 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPREnvironment *spapr,
ics->irqs[nr - ics->offset].saved_priority,
ics->irqs[nr - ics->offset].saved_priority);
rtas_st(rets, 0, 0); /* Success */
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
/*

View File

@ -79,19 +79,19 @@ static int microblaze_load_dtb(hwaddr addr,
}
if (kernel_cmdline) {
r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
kernel_cmdline);
r = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
kernel_cmdline);
if (r < 0) {
fprintf(stderr, "couldn't set /chosen/bootargs\n");
}
}
if (initrd_start) {
qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
initrd_start);
qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
initrd_start);
qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
initrd_end);
qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
initrd_end);
}
cpu_physical_memory_write(addr, fdt, fdt_size);

View File

@ -55,12 +55,12 @@ static void rtas_nvram_fetch(PowerPCCPU *cpu, sPAPREnvironment *spapr,
void *membuf;
if ((nargs != 3) || (nret != 2)) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
if (!nvram) {
rtas_st(rets, 0, -1);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
rtas_st(rets, 1, 0);
return;
}
@ -71,7 +71,7 @@ static void rtas_nvram_fetch(PowerPCCPU *cpu, sPAPREnvironment *spapr,
if (((offset + len) < offset)
|| ((offset + len) > nvram->size)) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
rtas_st(rets, 1, 0);
return;
}
@ -87,7 +87,7 @@ static void rtas_nvram_fetch(PowerPCCPU *cpu, sPAPREnvironment *spapr,
}
cpu_physical_memory_unmap(membuf, len, 1, len);
rtas_st(rets, 0, (alen < len) ? -1 : 0);
rtas_st(rets, 0, (alen < len) ? RTAS_OUT_HW_ERROR : RTAS_OUT_SUCCESS);
rtas_st(rets, 1, (alen < 0) ? 0 : alen);
}
@ -102,12 +102,12 @@ static void rtas_nvram_store(PowerPCCPU *cpu, sPAPREnvironment *spapr,
void *membuf;
if ((nargs != 3) || (nret != 2)) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
if (!nvram) {
rtas_st(rets, 0, -1);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
@ -117,7 +117,7 @@ static void rtas_nvram_store(PowerPCCPU *cpu, sPAPREnvironment *spapr,
if (((offset + len) < offset)
|| ((offset + len) > nvram->size)) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
@ -132,7 +132,7 @@ static void rtas_nvram_store(PowerPCCPU *cpu, sPAPREnvironment *spapr,
}
cpu_physical_memory_unmap(membuf, len, 0, len);
rtas_st(rets, 0, (alen < len) ? -1 : 0);
rtas_st(rets, 0, (alen < len) ? RTAS_OUT_HW_ERROR : RTAS_OUT_SUCCESS);
rtas_st(rets, 1, (alen < 0) ? 0 : alen);
}

View File

@ -82,7 +82,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
memory_region_add_subregion(address_space_mem, 0x80000000ULL,
&d->pci_hole);
phb->bus = pci_register_bus(dev, "pci",
phb->bus = pci_register_bus(dev, NULL,
pci_grackle_set_irq,
pci_grackle_map_irq,
pic,

View File

@ -234,7 +234,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic,
memory_region_add_subregion(address_space_mem, 0x80000000ULL,
&d->pci_hole);
h->bus = pci_register_bus(dev, "pci",
h->bus = pci_register_bus(dev, NULL,
pci_unin_set_irq, pci_unin_map_irq,
pic,
&d->pci_mmio,
@ -300,7 +300,7 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic,
memory_region_add_subregion(address_space_mem, 0x80000000ULL,
&d->pci_hole);
h->bus = pci_register_bus(dev, "pci",
h->bus = pci_register_bus(dev, NULL,
pci_unin_set_irq, pci_unin_map_irq,
pic,
&d->pci_mmio,

View File

@ -108,18 +108,18 @@ static void dt_serial_create(void *fdt, unsigned long long offset,
char ser[128];
snprintf(ser, sizeof(ser), "%s/serial@%llx", soc, offset);
qemu_devtree_add_subnode(fdt, ser);
qemu_devtree_setprop_string(fdt, ser, "device_type", "serial");
qemu_devtree_setprop_string(fdt, ser, "compatible", "ns16550");
qemu_devtree_setprop_cells(fdt, ser, "reg", offset, 0x100);
qemu_devtree_setprop_cell(fdt, ser, "cell-index", idx);
qemu_devtree_setprop_cell(fdt, ser, "clock-frequency", 0);
qemu_devtree_setprop_cells(fdt, ser, "interrupts", 42, 2);
qemu_devtree_setprop_phandle(fdt, ser, "interrupt-parent", mpic);
qemu_devtree_setprop_string(fdt, "/aliases", alias, ser);
qemu_fdt_add_subnode(fdt, ser);
qemu_fdt_setprop_string(fdt, ser, "device_type", "serial");
qemu_fdt_setprop_string(fdt, ser, "compatible", "ns16550");
qemu_fdt_setprop_cells(fdt, ser, "reg", offset, 0x100);
qemu_fdt_setprop_cell(fdt, ser, "cell-index", idx);
qemu_fdt_setprop_cell(fdt, ser, "clock-frequency", 0);
qemu_fdt_setprop_cells(fdt, ser, "interrupts", 42, 2);
qemu_fdt_setprop_phandle(fdt, ser, "interrupt-parent", mpic);
qemu_fdt_setprop_string(fdt, "/aliases", alias, ser);
if (defcon) {
qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser);
qemu_fdt_setprop_string(fdt, "/chosen", "linux,stdout-path", ser);
}
}
@ -183,30 +183,30 @@ static int ppce500_load_device_tree(QEMUMachineInitArgs *args,
}
/* Manipulate device tree in memory. */
qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2);
qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2);
qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 2);
qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 2);
qemu_devtree_add_subnode(fdt, "/memory");
qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory");
qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
sizeof(mem_reg_property));
qemu_fdt_add_subnode(fdt, "/memory");
qemu_fdt_setprop_string(fdt, "/memory", "device_type", "memory");
qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property,
sizeof(mem_reg_property));
qemu_devtree_add_subnode(fdt, "/chosen");
qemu_fdt_add_subnode(fdt, "/chosen");
if (initrd_size) {
ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
initrd_base);
ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
initrd_base);
if (ret < 0) {
fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
}
ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
(initrd_base + initrd_size));
ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
(initrd_base + initrd_size));
if (ret < 0) {
fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
}
}
ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
args->kernel_cmdline);
if (ret < 0)
fprintf(stderr, "couldn't set /chosen/bootargs\n");
@ -217,22 +217,22 @@ static int ppce500_load_device_tree(QEMUMachineInitArgs *args,
tb_freq = kvmppc_get_tbfreq();
/* indicate KVM hypercall interface */
qemu_devtree_add_subnode(fdt, "/hypervisor");
qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible",
"linux,kvm");
qemu_fdt_add_subnode(fdt, "/hypervisor");
qemu_fdt_setprop_string(fdt, "/hypervisor", "compatible",
"linux,kvm");
kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
hypercall, sizeof(hypercall));
qemu_fdt_setprop(fdt, "/hypervisor", "hcall-instructions",
hypercall, sizeof(hypercall));
/* if KVM supports the idle hcall, set property indicating this */
if (kvmppc_get_hasidle(env)) {
qemu_devtree_setprop(fdt, "/hypervisor", "has-idle", NULL, 0);
qemu_fdt_setprop(fdt, "/hypervisor", "has-idle", NULL, 0);
}
}
/* Create CPU nodes */
qemu_devtree_add_subnode(fdt, "/cpus");
qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 1);
qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0);
qemu_fdt_add_subnode(fdt, "/cpus");
qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 1);
qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0);
/* We need to generate the cpu nodes in reverse order, so Linux can pick
the first node as boot node and be happy */
@ -249,55 +249,56 @@ static int ppce500_load_device_tree(QEMUMachineInitArgs *args,
snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x",
cpu->cpu_index);
qemu_devtree_add_subnode(fdt, cpu_name);
qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu");
qemu_devtree_setprop_cell(fdt, cpu_name, "reg", cpu->cpu_index);
qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size",
env->dcache_line_size);
qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size",
env->icache_line_size);
qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);
qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);
qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0);
qemu_fdt_add_subnode(fdt, cpu_name);
qemu_fdt_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
qemu_fdt_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu");
qemu_fdt_setprop_cell(fdt, cpu_name, "reg", cpu->cpu_index);
qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-line-size",
env->dcache_line_size);
qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-line-size",
env->icache_line_size);
qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);
qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);
qemu_fdt_setprop_cell(fdt, cpu_name, "bus-frequency", 0);
if (cpu->cpu_index) {
qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled");
qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table");
qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr",
cpu_release_addr);
qemu_fdt_setprop_string(fdt, cpu_name, "status", "disabled");
qemu_fdt_setprop_string(fdt, cpu_name, "enable-method",
"spin-table");
qemu_fdt_setprop_u64(fdt, cpu_name, "cpu-release-addr",
cpu_release_addr);
} else {
qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay");
qemu_fdt_setprop_string(fdt, cpu_name, "status", "okay");
}
}
qemu_devtree_add_subnode(fdt, "/aliases");
qemu_fdt_add_subnode(fdt, "/aliases");
/* XXX These should go into their respective devices' code */
snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE);
qemu_devtree_add_subnode(fdt, soc);
qemu_devtree_setprop_string(fdt, soc, "device_type", "soc");
qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb,
sizeof(compatible_sb));
qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1);
qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1);
qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0,
MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE,
MPC8544_CCSRBAR_SIZE);
qemu_fdt_add_subnode(fdt, soc);
qemu_fdt_setprop_string(fdt, soc, "device_type", "soc");
qemu_fdt_setprop(fdt, soc, "compatible", compatible_sb,
sizeof(compatible_sb));
qemu_fdt_setprop_cell(fdt, soc, "#address-cells", 1);
qemu_fdt_setprop_cell(fdt, soc, "#size-cells", 1);
qemu_fdt_setprop_cells(fdt, soc, "ranges", 0x0,
MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE,
MPC8544_CCSRBAR_SIZE);
/* XXX should contain a reasonable value */
qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0);
qemu_fdt_setprop_cell(fdt, soc, "bus-frequency", 0);
snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET);
qemu_devtree_add_subnode(fdt, mpic);
qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic");
qemu_devtree_setprop_string(fdt, mpic, "compatible", "fsl,mpic");
qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET,
0x40000);
qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0);
qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2);
mpic_ph = qemu_devtree_alloc_phandle(fdt);
qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph);
qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph);
qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0);
qemu_fdt_add_subnode(fdt, mpic);
qemu_fdt_setprop_string(fdt, mpic, "device_type", "open-pic");
qemu_fdt_setprop_string(fdt, mpic, "compatible", "fsl,mpic");
qemu_fdt_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET,
0x40000);
qemu_fdt_setprop_cell(fdt, mpic, "#address-cells", 0);
qemu_fdt_setprop_cell(fdt, mpic, "#interrupt-cells", 2);
mpic_ph = qemu_fdt_alloc_phandle(fdt);
qemu_fdt_setprop_cell(fdt, mpic, "phandle", mpic_ph);
qemu_fdt_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph);
qemu_fdt_setprop(fdt, mpic, "interrupt-controller", NULL, 0);
/*
* We have to generate ser1 first, because Linux takes the first
@ -311,19 +312,19 @@ static int ppce500_load_device_tree(QEMUMachineInitArgs *args,
snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc,
MPC8544_UTIL_OFFSET);
qemu_devtree_add_subnode(fdt, gutil);
qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts");
qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000);
qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0);
qemu_fdt_add_subnode(fdt, gutil);
qemu_fdt_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts");
qemu_fdt_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000);
qemu_fdt_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0);
snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET);
qemu_devtree_add_subnode(fdt, msi);
qemu_devtree_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi");
qemu_devtree_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200);
msi_ph = qemu_devtree_alloc_phandle(fdt);
qemu_devtree_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100);
qemu_devtree_setprop_phandle(fdt, msi, "interrupt-parent", mpic);
qemu_devtree_setprop_cells(fdt, msi, "interrupts",
qemu_fdt_add_subnode(fdt, msi);
qemu_fdt_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi");
qemu_fdt_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200);
msi_ph = qemu_fdt_alloc_phandle(fdt);
qemu_fdt_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100);
qemu_fdt_setprop_phandle(fdt, msi, "interrupt-parent", mpic);
qemu_fdt_setprop_cells(fdt, msi, "interrupts",
0xe0, 0x0,
0xe1, 0x0,
0xe2, 0x0,
@ -332,46 +333,46 @@ static int ppce500_load_device_tree(QEMUMachineInitArgs *args,
0xe5, 0x0,
0xe6, 0x0,
0xe7, 0x0);
qemu_devtree_setprop_cell(fdt, msi, "phandle", msi_ph);
qemu_devtree_setprop_cell(fdt, msi, "linux,phandle", msi_ph);
qemu_fdt_setprop_cell(fdt, msi, "phandle", msi_ph);
qemu_fdt_setprop_cell(fdt, msi, "linux,phandle", msi_ph);
snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE);
qemu_devtree_add_subnode(fdt, pci);
qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0);
qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci");
qemu_devtree_setprop_string(fdt, pci, "device_type", "pci");
qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0,
0x0, 0x7);
pci_map = pci_map_create(fdt, qemu_devtree_get_phandle(fdt, mpic),
qemu_fdt_add_subnode(fdt, pci);
qemu_fdt_setprop_cell(fdt, pci, "cell-index", 0);
qemu_fdt_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci");
qemu_fdt_setprop_string(fdt, pci, "device_type", "pci");
qemu_fdt_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0,
0x0, 0x7);
pci_map = pci_map_create(fdt, qemu_fdt_get_phandle(fdt, mpic),
params->pci_first_slot, params->pci_nr_slots,
&len);
qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, len);
qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic);
qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2);
qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255);
qemu_fdt_setprop(fdt, pci, "interrupt-map", pci_map, len);
qemu_fdt_setprop_phandle(fdt, pci, "interrupt-parent", mpic);
qemu_fdt_setprop_cells(fdt, pci, "interrupts", 24, 2);
qemu_fdt_setprop_cells(fdt, pci, "bus-range", 0, 255);
for (i = 0; i < 14; i++) {
pci_ranges[i] = cpu_to_be32(pci_ranges[i]);
}
qemu_devtree_setprop_cell(fdt, pci, "fsl,msi", msi_ph);
qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));
qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32,
MPC8544_PCI_REGS_BASE, 0, 0x1000);
qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666);
qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1);
qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2);
qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3);
qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci);
qemu_fdt_setprop_cell(fdt, pci, "fsl,msi", msi_ph);
qemu_fdt_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));
qemu_fdt_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32,
MPC8544_PCI_REGS_BASE, 0, 0x1000);
qemu_fdt_setprop_cell(fdt, pci, "clock-frequency", 66666666);
qemu_fdt_setprop_cell(fdt, pci, "#interrupt-cells", 1);
qemu_fdt_setprop_cell(fdt, pci, "#size-cells", 2);
qemu_fdt_setprop_cell(fdt, pci, "#address-cells", 3);
qemu_fdt_setprop_string(fdt, "/aliases", "pci0", pci);
params->fixup_devtree(params, fdt);
if (toplevel_compat) {
qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat,
strlen(toplevel_compat) + 1);
qemu_fdt_setprop(fdt, "/", "compatible", toplevel_compat,
strlen(toplevel_compat) + 1);
}
done:
if (!dry_run) {
qemu_devtree_dumpdtb(fdt, fdt_size);
qemu_fdt_dumpdtb(fdt, fdt_size);
cpu_physical_memory_write(addr, fdt, fdt_size);
}
ret = fdt_size;

View File

@ -23,9 +23,9 @@ static void e500plat_fixup_devtree(PPCE500Params *params, void *fdt)
const char model[] = "QEMU ppce500";
const char compatible[] = "fsl,qemu-e500";
qemu_devtree_setprop(fdt, "/", "model", model, sizeof(model));
qemu_devtree_setprop(fdt, "/", "compatible", compatible,
sizeof(compatible));
qemu_fdt_setprop(fdt, "/", "model", model, sizeof(model));
qemu_fdt_setprop(fdt, "/", "compatible", compatible,
sizeof(compatible));
}
static void e500plat_init(QEMUMachineInitArgs *args)

View File

@ -21,9 +21,9 @@ static void mpc8544ds_fixup_devtree(PPCE500Params *params, void *fdt)
const char model[] = "MPC8544DS";
const char compatible[] = "MPC8544DS\0MPC85xxDS";
qemu_devtree_setprop(fdt, "/", "model", model, sizeof(model));
qemu_devtree_setprop(fdt, "/", "compatible", compatible,
sizeof(compatible));
qemu_fdt_setprop(fdt, "/", "model", model, sizeof(model));
qemu_fdt_setprop(fdt, "/", "compatible", compatible,
sizeof(compatible));
}
static void mpc8544ds_init(QEMUMachineInitArgs *args)

View File

@ -77,23 +77,23 @@ static int bamboo_load_device_tree(hwaddr addr,
/* Manipulate device tree in memory. */
ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
sizeof(mem_reg_property));
ret = qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property,
sizeof(mem_reg_property));
if (ret < 0)
fprintf(stderr, "couldn't set /memory/reg\n");
ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
initrd_base);
ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
initrd_base);
if (ret < 0)
fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
(initrd_base + initrd_size));
ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
(initrd_base + initrd_size));
if (ret < 0)
fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
kernel_cmdline);
ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
kernel_cmdline);
if (ret < 0)
fprintf(stderr, "couldn't set /chosen/bootargs\n");
@ -105,10 +105,10 @@ static int bamboo_load_device_tree(hwaddr addr,
clock_freq = kvmppc_get_clockfreq();
}
qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
clock_freq);
qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
tb_freq);
qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
clock_freq);
qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
tb_freq);
rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
g_free(fdt);

View File

@ -526,14 +526,15 @@ static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
cpu_to_be32(0x0), cpu_to_be32(0x0),
cpu_to_be32(0x0)};
char mem_name[32];
hwaddr node0_size, mem_start;
hwaddr node0_size, mem_start, node_size;
uint64_t mem_reg_property[2];
int i, off;
/* memory node(s) */
node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
if (spapr->rma_size > node0_size) {
spapr->rma_size = node0_size;
if (nb_numa_nodes > 1 && node_mem[0] < ram_size) {
node0_size = node_mem[0];
} else {
node0_size = ram_size;
}
/* RMA */
@ -566,7 +567,15 @@ static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
mem_start = node0_size;
for (i = 1; i < nb_numa_nodes; i++) {
mem_reg_property[0] = cpu_to_be64(mem_start);
mem_reg_property[1] = cpu_to_be64(node_mem[i]);
if (mem_start >= ram_size) {
node_size = 0;
} else {
node_size = node_mem[i];
if (node_size > ram_size - mem_start) {
node_size = ram_size - mem_start;
}
}
mem_reg_property[1] = cpu_to_be64(node_size);
associativity[3] = associativity[4] = cpu_to_be32(i);
sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start);
off = fdt_add_subnode(fdt, 0, mem_name);
@ -576,7 +585,7 @@ static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
sizeof(mem_reg_property))));
_FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
sizeof(associativity))));
mem_start += node_mem[i];
mem_start += node_size;
}
return 0;
@ -688,7 +697,8 @@ static void spapr_reset_htab(sPAPREnvironment *spapr)
/* Update the RMA size if necessary */
if (spapr->vrma_adjust) {
spapr->rma_size = kvmppc_rma_size(ram_size, spapr->htab_shift);
hwaddr node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
spapr->rma_size = kvmppc_rma_size(node0_size, spapr->htab_shift);
}
}
@ -739,18 +749,10 @@ static void spapr_cpu_reset(void *opaque)
static void spapr_create_nvram(sPAPREnvironment *spapr)
{
DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
const char *drivename = qemu_opt_get(qemu_get_machine_opts(), "nvram");
DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
if (drivename) {
BlockDriverState *bs;
bs = bdrv_find(drivename);
if (!bs) {
fprintf(stderr, "No such block device \"%s\" for nvram\n",
drivename);
exit(1);
}
qdev_prop_set_drive_nofail(dev, "drive", bs);
if (dinfo) {
qdev_prop_set_drive_nofail(dev, "drive", dinfo->bdrv);
}
qdev_init_nofail(dev);
@ -1113,6 +1115,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
hwaddr rma_alloc_size;
hwaddr node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
uint32_t initrd_base = 0;
long kernel_size = 0, initrd_size = 0;
long load_limit, rtas_limit, fw_size;
@ -1134,10 +1137,10 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
exit(1);
}
if (rma_alloc_size && (rma_alloc_size < ram_size)) {
if (rma_alloc_size && (rma_alloc_size < node0_size)) {
spapr->rma_size = rma_alloc_size;
} else {
spapr->rma_size = ram_size;
spapr->rma_size = node0_size;
/* With KVM, we don't actually know whether KVM supports an
* unbounded RMA (PR KVM) or is limited by the hash table size
@ -1154,6 +1157,12 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
}
}
if (spapr->rma_size > node0_size) {
fprintf(stderr, "Error: Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")\n",
spapr->rma_size);
exit(1);
}
/* 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
* processed with 32-bit real mode code if necessary */

View File

@ -286,7 +286,7 @@ static void check_exception(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint64_t xinfo;
if ((nargs < 6) || (nargs > 7) || nret != 1) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
@ -306,9 +306,9 @@ static void check_exception(PowerPCCPU *cpu, sPAPREnvironment *spapr,
cpu_physical_memory_write(buf, pending_epow, len);
g_free(pending_epow);
pending_epow = NULL;
rtas_st(rets, 0, 0);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
} else {
rtas_st(rets, 0, 1);
rtas_st(rets, 0, RTAS_OUT_NO_ERRORS_FOUND);
}
}

View File

@ -90,7 +90,7 @@ static void finish_read_pci_config(sPAPREnvironment *spapr, uint64_t buid,
if ((size != 1) && (size != 2) && (size != 4)) {
/* access must be 1, 2 or 4 bytes */
rtas_st(rets, 0, -1);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
@ -100,14 +100,14 @@ static void finish_read_pci_config(sPAPREnvironment *spapr, uint64_t buid,
if (!pci_dev || (addr % size) || (addr >= pci_config_size(pci_dev))) {
/* Access must be to a valid device, within bounds and
* naturally aligned */
rtas_st(rets, 0, -1);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
val = pci_host_config_read_common(pci_dev, addr,
pci_config_size(pci_dev), size);
rtas_st(rets, 0, 0);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
rtas_st(rets, 1, val);
}
@ -120,7 +120,7 @@ static void rtas_ibm_read_pci_config(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t size, addr;
if ((nargs != 4) || (nret != 2)) {
rtas_st(rets, 0, -1);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
@ -139,7 +139,7 @@ static void rtas_read_pci_config(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t size, addr;
if ((nargs != 2) || (nret != 2)) {
rtas_st(rets, 0, -1);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
@ -157,7 +157,7 @@ static void finish_write_pci_config(sPAPREnvironment *spapr, uint64_t buid,
if ((size != 1) && (size != 2) && (size != 4)) {
/* access must be 1, 2 or 4 bytes */
rtas_st(rets, 0, -1);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
@ -167,14 +167,14 @@ static void finish_write_pci_config(sPAPREnvironment *spapr, uint64_t buid,
if (!pci_dev || (addr % size) || (addr >= pci_config_size(pci_dev))) {
/* Access must be to a valid device, within bounds and
* naturally aligned */
rtas_st(rets, 0, -1);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
pci_host_config_write_common(pci_dev, addr, pci_config_size(pci_dev),
val, size);
rtas_st(rets, 0, 0);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
static void rtas_ibm_write_pci_config(PowerPCCPU *cpu, sPAPREnvironment *spapr,
@ -186,7 +186,7 @@ static void rtas_ibm_write_pci_config(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t val, size, addr;
if ((nargs != 5) || (nret != 1)) {
rtas_st(rets, 0, -1);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
@ -206,7 +206,7 @@ static void rtas_write_pci_config(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t val, size, addr;
if ((nargs != 3) || (nret != 1)) {
rtas_st(rets, 0, -1);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
@ -293,7 +293,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
break;
default:
fprintf(stderr, "rtas_ibm_change_msi(%u) is not implemented\n", func);
rtas_st(rets, 0, -3); /* Parameter error */
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
@ -303,7 +303,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
pdev = find_dev(spapr, buid, config_addr);
}
if (!phb || !pdev) {
rtas_st(rets, 0, -3); /* Parameter error */
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
@ -312,11 +312,11 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
ndev = spapr_msicfg_find(phb, config_addr, false);
if (ndev < 0) {
trace_spapr_pci_msi("MSI has not been enabled", -1, config_addr);
rtas_st(rets, 0, -1); /* Hardware error */
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
trace_spapr_pci_msi("Released MSIs", ndev, config_addr);
rtas_st(rets, 0, 0);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
rtas_st(rets, 1, 0);
return;
}
@ -327,7 +327,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
ndev = spapr_msicfg_find(phb, config_addr, true);
if (ndev >= SPAPR_MSIX_MAX_DEVS || ndev < 0) {
fprintf(stderr, "No free entry for a new MSI device\n");
rtas_st(rets, 0, -1); /* Hardware error */
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
trace_spapr_pci_msi("Configuring MSI", ndev, config_addr);
@ -336,7 +336,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
if (phb->msi_table[ndev].nvec && (req_num != phb->msi_table[ndev].nvec)) {
/* Unexpected behaviour */
fprintf(stderr, "Cannot reuse MSI config for device#%d", ndev);
rtas_st(rets, 0, -1); /* Hardware error */
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
@ -346,7 +346,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
ret_intr_type == RTAS_TYPE_MSI);
if (irq < 0) {
fprintf(stderr, "Cannot allocate MSIs for device#%d", ndev);
rtas_st(rets, 0, -1); /* Hardware error */
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
phb->msi_table[ndev].irq = irq;
@ -358,7 +358,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
spapr_msi_setmsg(pdev, spapr->msi_win_addr, ret_intr_type == RTAS_TYPE_MSIX,
phb->msi_table[ndev].irq, req_num);
rtas_st(rets, 0, 0);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
rtas_st(rets, 1, req_num);
rtas_st(rets, 2, ++seq_num);
rtas_st(rets, 3, ret_intr_type);
@ -383,7 +383,7 @@ static void rtas_ibm_query_interrupt_source_number(PowerPCCPU *cpu,
/* Fins sPAPRPHBState */
phb = find_phb(spapr, buid);
if (!phb) {
rtas_st(rets, 0, -3); /* Parameter error */
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
@ -391,7 +391,7 @@ static void rtas_ibm_query_interrupt_source_number(PowerPCCPU *cpu,
ndev = spapr_msicfg_find(phb, config_addr, false);
if (ndev < 0) {
trace_spapr_pci_msi("MSI has not been enabled", -1, config_addr);
rtas_st(rets, 0, -1); /* Hardware error */
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
@ -399,7 +399,7 @@ static void rtas_ibm_query_interrupt_source_number(PowerPCCPU *cpu,
trace_spapr_pci_rtas_ibm_query_interrupt_source_number(ioa_intr_num,
intr_src_num);
rtas_st(rets, 0, 0);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
rtas_st(rets, 1, intr_src_num);
rtas_st(rets, 2, 1);/* 0 == level; 1 == edge */
}

View File

@ -47,10 +47,10 @@ static void rtas_display_character(PowerPCCPU *cpu, sPAPREnvironment *spapr,
VIOsPAPRDevice *sdev = vty_lookup(spapr, 0);
if (!sdev) {
rtas_st(rets, 0, -1);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
} else {
vty_putchars(sdev, &c, sizeof(c));
rtas_st(rets, 0, 0);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
}
@ -62,13 +62,13 @@ static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
struct tm tm;
if (nret != 8) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
qemu_get_timedate(&tm, spapr->rtc_offset);
rtas_st(rets, 0, 0); /* Success */
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
rtas_st(rets, 1, tm.tm_year + 1900);
rtas_st(rets, 2, tm.tm_mon + 1);
rtas_st(rets, 3, tm.tm_mday);
@ -96,7 +96,7 @@ static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
rtc_change_mon_event(&tm);
spapr->rtc_offset = qemu_timedate_diff(&tm);
rtas_st(rets, 0, 0); /* Success */
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
static void rtas_power_off(PowerPCCPU *cpu, sPAPREnvironment *spapr,
@ -104,11 +104,11 @@ static void rtas_power_off(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t nret, target_ulong rets)
{
if (nargs != 2 || nret != 1) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
qemu_system_shutdown_request();
rtas_st(rets, 0, 0);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
static void rtas_system_reboot(PowerPCCPU *cpu, sPAPREnvironment *spapr,
@ -117,11 +117,11 @@ static void rtas_system_reboot(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t nret, target_ulong rets)
{
if (nargs != 0 || nret != 1) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
qemu_system_reset_request();
rtas_st(rets, 0, 0);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
@ -134,7 +134,7 @@ static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
CPUState *cpu;
if (nargs != 1 || nret != 2) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
@ -147,12 +147,12 @@ static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
rtas_st(rets, 1, 2);
}
rtas_st(rets, 0, 0);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
return;
}
/* Didn't find a matching cpu */
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
}
static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPREnvironment *spapr,
@ -164,7 +164,7 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPREnvironment *spapr,
CPUState *cs;
if (nargs != 3 || nret != 1) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
@ -178,7 +178,7 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPREnvironment *spapr,
CPUPPCState *env = &cpu->env;
if (!cs->halted) {
rtas_st(rets, 0, -1);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
@ -194,12 +194,12 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPREnvironment *spapr,
qemu_cpu_kick(cs);
rtas_st(rets, 0, 0);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
return;
}
/* Didn't find a matching cpu */
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
}
static void rtas_stop_self(PowerPCCPU *cpu, sPAPREnvironment *spapr,
@ -224,6 +224,49 @@ static void rtas_stop_self(PowerPCCPU *cpu, sPAPREnvironment *spapr,
env->msr = 0;
}
#define DIAGNOSTICS_RUN_MODE 42
static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
sPAPREnvironment *spapr,
uint32_t token, uint32_t nargs,
target_ulong args,
uint32_t nret, target_ulong rets)
{
target_ulong parameter = rtas_ld(args, 0);
target_ulong buffer = rtas_ld(args, 1);
target_ulong length = rtas_ld(args, 2);
target_ulong ret = RTAS_OUT_NOT_SUPPORTED;
switch (parameter) {
case DIAGNOSTICS_RUN_MODE:
if (length == 1) {
rtas_st(buffer, 0, 0);
ret = RTAS_OUT_SUCCESS;
}
break;
}
rtas_st(rets, 0, ret);
}
static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu,
sPAPREnvironment *spapr,
uint32_t token, uint32_t nargs,
target_ulong args,
uint32_t nret, target_ulong rets)
{
target_ulong parameter = rtas_ld(args, 0);
target_ulong ret = RTAS_OUT_NOT_SUPPORTED;
switch (parameter) {
case DIAGNOSTICS_RUN_MODE:
ret = RTAS_OUT_NOT_AUTHORIZED;
break;
}
rtas_st(rets, 0, ret);
}
static struct rtas_call {
const char *name;
spapr_rtas_fn fn;
@ -255,7 +298,7 @@ target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPREnvironment *spapr,
}
hcall_dprintf("Unknown RTAS token 0x%x\n", token);
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return H_PARAMETER;
}
@ -291,24 +334,24 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
return ret;
}
ret = qemu_devtree_setprop_cell(fdt, "/rtas", "linux,rtas-base",
rtas_addr);
ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-base",
rtas_addr);
if (ret < 0) {
fprintf(stderr, "Couldn't add linux,rtas-base property: %s\n",
fdt_strerror(ret));
return ret;
}
ret = qemu_devtree_setprop_cell(fdt, "/rtas", "linux,rtas-entry",
rtas_addr);
ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-entry",
rtas_addr);
if (ret < 0) {
fprintf(stderr, "Couldn't add linux,rtas-entry property: %s\n",
fdt_strerror(ret));
return ret;
}
ret = qemu_devtree_setprop_cell(fdt, "/rtas", "rtas-size",
rtas_size);
ret = qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-size",
rtas_size);
if (ret < 0) {
fprintf(stderr, "Couldn't add rtas-size property: %s\n",
fdt_strerror(ret));
@ -322,8 +365,8 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
continue;
}
ret = qemu_devtree_setprop_cell(fdt, "/rtas", call->name,
i + TOKEN_BASE);
ret = qemu_fdt_setprop_cell(fdt, "/rtas", call->name,
i + TOKEN_BASE);
if (ret < 0) {
fprintf(stderr, "Couldn't add rtas token for %s: %s\n",
call->name, fdt_strerror(ret));
@ -345,6 +388,10 @@ static void core_rtas_register_types(void)
rtas_query_cpu_stopped_state);
spapr_rtas_register("start-cpu", rtas_start_cpu);
spapr_rtas_register("stop-self", rtas_stop_self);
spapr_rtas_register("ibm,get-system-parameter",
rtas_ibm_get_system_parameter);
spapr_rtas_register("ibm,set-system-parameter",
rtas_ibm_set_system_parameter);
}
type_init(core_rtas_register_types)

View File

@ -331,25 +331,25 @@ static void rtas_set_tce_bypass(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t unit, enable;
if (nargs != 2) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
unit = rtas_ld(args, 0);
enable = rtas_ld(args, 1);
dev = spapr_vio_find_by_reg(bus, unit);
if (!dev) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
if (!dev->tcet) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
spapr_tce_set_bypass(dev->tcet, !!enable);
rtas_st(rets, 0, 0);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
static void rtas_quiesce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
@ -362,7 +362,7 @@ static void rtas_quiesce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
VIOsPAPRDevice *dev = NULL;
if (nargs != 0) {
rtas_st(rets, 0, -3);
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
@ -371,7 +371,7 @@ static void rtas_quiesce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
spapr_vio_quiesce_one(dev);
}
rtas_st(rets, 0, 0);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)

View File

@ -166,7 +166,7 @@ static int xilinx_load_device_tree(hwaddr addr,
if (!fdt) {
return 0;
}
r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
r = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
if (r < 0)
fprintf(stderr, "couldn't set /chosen/bootargs\n");
cpu_physical_memory_write(addr, fdt, fdt_size);

View File

@ -110,6 +110,7 @@ void stq_phys(hwaddr addr, uint64_t val);
void cpu_physical_memory_write_rom(hwaddr addr,
const uint8_t *buf, int len);
void cpu_flush_icache_range(hwaddr start, int len);
extern struct MemoryRegion io_mem_rom;
extern struct MemoryRegion io_mem_notdirty;

View File

@ -332,6 +332,15 @@ static inline int spapr_allocate_lsi(int hint)
return spapr_allocate_irq(hint, true);
}
/* RTAS return codes */
#define RTAS_OUT_SUCCESS 0
#define RTAS_OUT_NO_ERRORS_FOUND 1
#define RTAS_OUT_HW_ERROR -1
#define RTAS_OUT_BUSY -2
#define RTAS_OUT_PARAM_ERROR -3
#define RTAS_OUT_NOT_SUPPORTED -3
#define RTAS_OUT_NOT_AUTHORIZED -9002
static inline uint64_t ppc64_phys_to_real(uint64_t addr)
{
return addr & ~0xF000000000000000ULL;

View File

@ -17,27 +17,27 @@
void *create_device_tree(int *sizep);
void *load_device_tree(const char *filename_path, int *sizep);
int qemu_devtree_setprop(void *fdt, const char *node_path,
const char *property, const void *val_array, int size);
int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
const char *property, uint32_t val);
int qemu_devtree_setprop_u64(void *fdt, const char *node_path,
const char *property, uint64_t val);
int qemu_devtree_setprop_string(void *fdt, const char *node_path,
const char *property, const char *string);
int qemu_devtree_setprop_phandle(void *fdt, const char *node_path,
const char *property,
const char *target_node_path);
const void *qemu_devtree_getprop(void *fdt, const char *node_path,
const char *property, int *lenp);
uint32_t qemu_devtree_getprop_cell(void *fdt, const char *node_path,
const char *property);
uint32_t qemu_devtree_get_phandle(void *fdt, const char *path);
uint32_t qemu_devtree_alloc_phandle(void *fdt);
int qemu_devtree_nop_node(void *fdt, const char *node_path);
int qemu_devtree_add_subnode(void *fdt, const char *name);
int qemu_fdt_setprop(void *fdt, const char *node_path,
const char *property, const void *val, int size);
int qemu_fdt_setprop_cell(void *fdt, const char *node_path,
const char *property, uint32_t val);
int qemu_fdt_setprop_u64(void *fdt, const char *node_path,
const char *property, uint64_t val);
int qemu_fdt_setprop_string(void *fdt, const char *node_path,
const char *property, const char *string);
int qemu_fdt_setprop_phandle(void *fdt, const char *node_path,
const char *property,
const char *target_node_path);
const void *qemu_fdt_getprop(void *fdt, const char *node_path,
const char *property, int *lenp);
uint32_t qemu_fdt_getprop_cell(void *fdt, const char *node_path,
const char *property);
uint32_t qemu_fdt_get_phandle(void *fdt, const char *path);
uint32_t qemu_fdt_alloc_phandle(void *fdt);
int qemu_fdt_nop_node(void *fdt, const char *node_path);
int qemu_fdt_add_subnode(void *fdt, const char *name);
#define qemu_devtree_setprop_cells(fdt, node_path, property, ...) \
#define qemu_fdt_setprop_cells(fdt, node_path, property, ...) \
do { \
uint32_t qdt_tmp[] = { __VA_ARGS__ }; \
int i; \
@ -45,14 +45,14 @@ int qemu_devtree_add_subnode(void *fdt, const char *name);
for (i = 0; i < ARRAY_SIZE(qdt_tmp); i++) { \
qdt_tmp[i] = cpu_to_be32(qdt_tmp[i]); \
} \
qemu_devtree_setprop(fdt, node_path, property, qdt_tmp, \
sizeof(qdt_tmp)); \
qemu_fdt_setprop(fdt, node_path, property, qdt_tmp, \
sizeof(qdt_tmp)); \
} while (0)
void qemu_devtree_dumpdtb(void *fdt, int size);
void qemu_fdt_dumpdtb(void *fdt, int size);
/**
* qemu_devtree_setprop_sized_cells_from_array:
* qemu_fdt_setprop_sized_cells_from_array:
* @fdt: device tree blob
* @node_path: node to set property on
* @property: property to set
@ -72,20 +72,20 @@ void qemu_devtree_dumpdtb(void *fdt, int size);
* the number of cells used for each element vary depending on the
* #address-cells and #size-cells properties of their parent node.
* If you know all your cell elements are one cell wide you can use the
* simpler qemu_devtree_setprop_cells(). If you're not setting up the
* array programmatically, qemu_devtree_setprop_sized_cells may be more
* simpler qemu_fdt_setprop_cells(). If you're not setting up the
* array programmatically, qemu_fdt_setprop_sized_cells may be more
* convenient.
*
* Return value: 0 on success, <0 on error.
*/
int qemu_devtree_setprop_sized_cells_from_array(void *fdt,
const char *node_path,
const char *property,
int numvalues,
uint64_t *values);
int qemu_fdt_setprop_sized_cells_from_array(void *fdt,
const char *node_path,
const char *property,
int numvalues,
uint64_t *values);
/**
* qemu_devtree_setprop_sized_cells:
* qemu_fdt_setprop_sized_cells:
* @fdt: device tree blob
* @node_path: node to set property on
* @property: property to set
@ -97,17 +97,17 @@ int qemu_devtree_setprop_sized_cells_from_array(void *fdt,
* used by this value" and "value".
*
* This is a convenience wrapper for the function
* qemu_devtree_setprop_sized_cells_from_array().
* qemu_fdt_setprop_sized_cells_from_array().
*
* Return value: 0 on success, <0 on error.
*/
#define qemu_devtree_setprop_sized_cells(fdt, node_path, property, ...) \
({ \
uint64_t qdt_tmp[] = { __VA_ARGS__ }; \
qemu_devtree_setprop_sized_cells_from_array(fdt, node_path, \
property, \
ARRAY_SIZE(qdt_tmp) / 2, \
qdt_tmp); \
#define qemu_fdt_setprop_sized_cells(fdt, node_path, property, ...) \
({ \
uint64_t qdt_tmp[] = { __VA_ARGS__ }; \
qemu_fdt_setprop_sized_cells_from_array(fdt, node_path, \
property, \
ARRAY_SIZE(qdt_tmp) / 2, \
qdt_tmp); \
})
#endif /* __DEVICE_TREE_H__ */

View File

@ -44,6 +44,7 @@
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); \
\
pcc->pvr = _pvr; \
pcc->pvr_mask = CPU_POWERPC_DEFAULT_MASK; \
pcc->svr = _svr; \
dc->desc = _desc; \
} \
@ -1139,7 +1140,7 @@
"POWER7 v2.1")
POWERPC_DEF("POWER7_v2.3", CPU_POWERPC_POWER7_v23, POWER7,
"POWER7 v2.3")
POWERPC_DEF("POWER7+_v2.1", CPU_POWERPC_POWER7P_v21, POWER7,
POWERPC_DEF("POWER7+_v2.1", CPU_POWERPC_POWER7P_v21, POWER7P,
"POWER7+ v2.1")
POWERPC_DEF("POWER8_v1.0", CPU_POWERPC_POWER8_v10, POWER8,
"POWER8 v1.0")

View File

@ -39,6 +39,7 @@ extern PowerPCCPUAlias ppc_cpu_aliases[];
/*****************************************************************************/
/* PVR definitions for most known PowerPC */
enum {
CPU_POWERPC_DEFAULT_MASK = 0xFFFFFFFF,
/* PowerPC 401 family */
/* Generic PowerPC 401 */
#define CPU_POWERPC_401 CPU_POWERPC_401G2
@ -552,10 +553,16 @@ enum {
CPU_POWERPC_POWER6 = 0x003E0000,
CPU_POWERPC_POWER6_5 = 0x0F000001, /* POWER6 in POWER5 mode */
CPU_POWERPC_POWER6A = 0x0F000002,
CPU_POWERPC_POWER7_BASE = 0x003F0000,
CPU_POWERPC_POWER7_MASK = 0xFFFF0000,
CPU_POWERPC_POWER7_v20 = 0x003F0200,
CPU_POWERPC_POWER7_v21 = 0x003F0201,
CPU_POWERPC_POWER7_v23 = 0x003F0203,
CPU_POWERPC_POWER7P_BASE = 0x004A0000,
CPU_POWERPC_POWER7P_MASK = 0xFFFF0000,
CPU_POWERPC_POWER7P_v21 = 0x004A0201,
CPU_POWERPC_POWER8_BASE = 0x004B0000,
CPU_POWERPC_POWER8_MASK = 0xFFFF0000,
CPU_POWERPC_POWER8_v10 = 0x004B0100,
CPU_POWERPC_970 = 0x00390202,
CPU_POWERPC_970FX_v10 = 0x00391100,

View File

@ -54,6 +54,7 @@ typedef struct PowerPCCPUClass {
void (*parent_reset)(CPUState *cpu);
uint32_t pvr;
uint32_t pvr_mask;
uint32_t svr;
uint64_t insns_flags;
uint64_t insns_flags2;
@ -99,6 +100,7 @@ static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
#define ENV_OFFSET offsetof(PowerPCCPU, env)
PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr);
PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr);
void ppc_cpu_do_interrupt(CPUState *cpu);
void ppc_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,

View File

@ -236,6 +236,8 @@ enum {
POWERPC_EXCP_NMEXTBR = 91, /* Non maskable external breakpoint */
POWERPC_EXCP_ITLBE = 92, /* Instruction TLB error */
POWERPC_EXCP_DTLBE = 93, /* Data TLB error */
/* VSX Unavailable (Power ISA 2.06 and later) */
POWERPC_EXCP_VSXU = 94, /* VSX Unavailable */
/* EOL */
POWERPC_EXCP_NB = 96,
/* QEMU exceptions: used internally during code translation */
@ -427,6 +429,7 @@ struct ppc_slb_t {
#define MSR_VR 25 /* altivec available x hflags */
#define MSR_SPE 25 /* SPE enable for BookE x hflags */
#define MSR_AP 23 /* Access privilege state on 602 hflags */
#define MSR_VSX 23 /* Vector Scalar Extension (ISA 2.06 and later) x hflags */
#define MSR_SA 22 /* Supervisor access mode on 602 hflags */
#define MSR_KEY 19 /* key bit on 603e */
#define MSR_POW 18 /* Power management */
@ -467,6 +470,7 @@ struct ppc_slb_t {
#define msr_vr ((env->msr >> MSR_VR) & 1)
#define msr_spe ((env->msr >> MSR_SPE) & 1)
#define msr_ap ((env->msr >> MSR_AP) & 1)
#define msr_vsx ((env->msr >> MSR_VSX) & 1)
#define msr_sa ((env->msr >> MSR_SA) & 1)
#define msr_key ((env->msr >> MSR_KEY) & 1)
#define msr_pow ((env->msr >> MSR_POW) & 1)
@ -549,6 +553,8 @@ enum {
POWERPC_FLAG_BUS_CLK = 0x00020000,
/* Has CFAR */
POWERPC_FLAG_CFAR = 0x00040000,
/* Has VSX */
POWERPC_FLAG_VSX = 0x00080000,
};
/*****************************************************************************/
@ -1870,7 +1876,8 @@ enum {
/* Book I 2.05 PowerPC specification */
PPC2_ISA205 = 0x0000000000000020ULL,
#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_DBRX | PPC2_ISA205)
#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_VSX | PPC2_PRCNTL | PPC2_DBRX | \
PPC2_ISA205)
};
/*****************************************************************************/

View File

@ -390,6 +390,11 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
new_msr |= (target_ulong)MSR_HVB;
}
goto store_current;
case POWERPC_EXCP_VSXU: /* VSX unavailable exception */
if (lpes1 == 0) {
new_msr |= (target_ulong)MSR_HVB;
}
goto store_current;
case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
LOG_EXCP("PIT exception\n");
goto store_next;

View File

@ -56,7 +56,7 @@ static inline void hreg_compute_hflags(CPUPPCState *env)
/* We 'forget' FE0 & FE1: we'll never generate imprecise exceptions */
hflags_mask = (1 << MSR_VR) | (1 << MSR_AP) | (1 << MSR_SA) |
(1 << MSR_PR) | (1 << MSR_FP) | (1 << MSR_SE) | (1 << MSR_BE) |
(1 << MSR_LE);
(1 << MSR_LE) | (1 << MSR_VSX);
hflags_mask |= (1ULL << MSR_CM) | (1ULL << MSR_SF) | MSR_HVB;
hreg_compute_mem_idx(env);
env->hflags = env->msr & hflags_mask;

View File

@ -1745,6 +1745,7 @@ static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
uint32_t icache_size = kvmppc_read_int_cpu_dt("i-cache-size");
/* Now fix up the class with information we can query from the host */
pcc->pvr = mfpvr();
if (vmx != -1) {
/* Only override when we know what the host supports */
@ -1794,6 +1795,9 @@ static int kvm_ppc_register_host_cpu_type(void)
PowerPCCPUClass *pvr_pcc;
pvr_pcc = ppc_cpu_class_by_pvr(host_pvr);
if (pvr_pcc == NULL) {
pvr_pcc = ppc_cpu_class_by_pvr_mask(host_pvr);
}
if (pvr_pcc == NULL) {
return -1;
}
@ -1902,3 +1906,31 @@ int kvm_arch_on_sigbus(int code, void *addr)
void kvm_arch_init_irq_routing(KVMState *s)
{
}
int kvm_arch_insert_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp)
{
return -EINVAL;
}
int kvm_arch_remove_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp)
{
return -EINVAL;
}
int kvm_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len, int type)
{
return -EINVAL;
}
int kvm_arch_remove_hw_breakpoint(target_ulong addr, target_ulong len, int type)
{
return -EINVAL;
}
void kvm_arch_remove_all_hw_breakpoints(void)
{
}
void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg)
{
}

View File

@ -51,6 +51,7 @@ static char cpu_reg_names[10*3 + 22*4 /* GPR */
#endif
+ 10*4 + 22*5 /* FPR */
+ 2*(10*6 + 22*7) /* AVRh, AVRl */
+ 10*5 + 22*6 /* VSR */
+ 8*5 /* CRF */];
static TCGv cpu_gpr[32];
#if !defined(TARGET_PPC64)
@ -58,6 +59,7 @@ static TCGv cpu_gprh[32];
#endif
static TCGv_i64 cpu_fpr[32];
static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
static TCGv_i64 cpu_vsr[32];
static TCGv_i32 cpu_crf[8];
static TCGv cpu_nip;
static TCGv cpu_msr;
@ -137,6 +139,11 @@ void ppc_translate_init(void)
#endif
p += (i < 10) ? 6 : 7;
cpu_reg_names_size -= (i < 10) ? 6 : 7;
snprintf(p, cpu_reg_names_size, "vsr%d", i);
cpu_vsr[i] = tcg_global_mem_new_i64(TCG_AREG0,
offsetof(CPUPPCState, vsr[i]), p);
p += (i < 10) ? 5 : 6;
cpu_reg_names_size -= (i < 10) ? 5 : 6;
}
cpu_nip = tcg_global_mem_new(TCG_AREG0,
@ -195,6 +202,7 @@ typedef struct DisasContext {
#endif
int fpu_enabled;
int altivec_enabled;
int vsx_enabled;
int spe_enabled;
ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
int singlestep_enabled;
@ -365,6 +373,12 @@ static inline int32_t name(uint32_t opcode) \
return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1)); \
}
#define EXTRACT_HELPER_SPLIT(name, shift1, nb1, shift2, nb2) \
static inline uint32_t name(uint32_t opcode) \
{ \
return (((opcode >> (shift1)) & ((1 << (nb1)) - 1)) << nb2) | \
((opcode >> (shift2)) & ((1 << (nb2)) - 1)); \
}
/* Opcode part 1 */
EXTRACT_HELPER(opc1, 26, 6);
/* Opcode part 2 */
@ -479,6 +493,14 @@ static inline target_ulong MASK(uint32_t start, uint32_t end)
return ret;
}
EXTRACT_HELPER_SPLIT(xT, 0, 1, 21, 5);
EXTRACT_HELPER_SPLIT(xS, 0, 1, 21, 5);
EXTRACT_HELPER_SPLIT(xA, 2, 1, 16, 5);
EXTRACT_HELPER_SPLIT(xB, 1, 1, 11, 5);
EXTRACT_HELPER_SPLIT(xC, 3, 1, 6, 5);
EXTRACT_HELPER(DM, 8, 2);
EXTRACT_HELPER(UIM, 16, 2);
EXTRACT_HELPER(SHW, 8, 2);
/*****************************************************************************/
/* PowerPC instructions table */
@ -6964,10 +6986,473 @@ GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
GEN_VAFORM_PAIRED(vsel, vperm, 21)
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
/*** VSX extension ***/
static inline TCGv_i64 cpu_vsrh(int n)
{
if (n < 32) {
return cpu_fpr[n];
} else {
return cpu_avrh[n-32];
}
}
static inline TCGv_i64 cpu_vsrl(int n)
{
if (n < 32) {
return cpu_vsr[n];
} else {
return cpu_avrl[n-32];
}
}
static void gen_lxsdx(DisasContext *ctx)
{
TCGv EA;
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
return;
}
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
/* NOTE: cpu_vsrl is undefined */
tcg_temp_free(EA);
}
static void gen_lxvd2x(DisasContext *ctx)
{
TCGv EA;
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
return;
}
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
tcg_gen_addi_tl(EA, EA, 8);
gen_qemu_ld64(ctx, cpu_vsrl(xT(ctx->opcode)), EA);
tcg_temp_free(EA);
}
static void gen_lxvdsx(DisasContext *ctx)
{
TCGv EA;
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
return;
}
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
gen_qemu_ld64(ctx, cpu_vsrh(xT(ctx->opcode)), EA);
tcg_gen_mov_tl(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xT(ctx->opcode)));
tcg_temp_free(EA);
}
static void gen_lxvw4x(DisasContext *ctx)
{
TCGv EA, tmp;
TCGv_i64 xth = cpu_vsrh(xT(ctx->opcode));
TCGv_i64 xtl = cpu_vsrl(xT(ctx->opcode));
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
return;
}
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
tmp = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
gen_qemu_ld32u(ctx, tmp, EA);
tcg_gen_addi_tl(EA, EA, 4);
gen_qemu_ld32u(ctx, xth, EA);
tcg_gen_deposit_i64(xth, xth, tmp, 32, 32);
tcg_gen_addi_tl(EA, EA, 4);
gen_qemu_ld32u(ctx, tmp, EA);
tcg_gen_addi_tl(EA, EA, 4);
gen_qemu_ld32u(ctx, xtl, EA);
tcg_gen_deposit_i64(xtl, xtl, tmp, 32, 32);
tcg_temp_free(EA);
tcg_temp_free(tmp);
}
static void gen_stxsdx(DisasContext *ctx)
{
TCGv EA;
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
return;
}
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
gen_qemu_st64(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
tcg_temp_free(EA);
}
static void gen_stxvd2x(DisasContext *ctx)
{
TCGv EA;
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
return;
}
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
gen_qemu_st64(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
tcg_gen_addi_tl(EA, EA, 8);
gen_qemu_st64(ctx, cpu_vsrl(xS(ctx->opcode)), EA);
tcg_temp_free(EA);
}
static void gen_stxvw4x(DisasContext *ctx)
{
TCGv EA, tmp;
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
return;
}
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
tmp = tcg_temp_new();
tcg_gen_shri_i64(tmp, cpu_vsrh(xS(ctx->opcode)), 32);
gen_qemu_st32(ctx, tmp, EA);
tcg_gen_addi_tl(EA, EA, 4);
gen_qemu_st32(ctx, cpu_vsrh(xS(ctx->opcode)), EA);
tcg_gen_shri_i64(tmp, cpu_vsrl(xS(ctx->opcode)), 32);
tcg_gen_addi_tl(EA, EA, 4);
gen_qemu_st32(ctx, tmp, EA);
tcg_gen_addi_tl(EA, EA, 4);
gen_qemu_st32(ctx, cpu_vsrl(xS(ctx->opcode)), EA);
tcg_temp_free(EA);
tcg_temp_free(tmp);
}
static void gen_xxpermdi(DisasContext *ctx)
{
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
return;
}
if ((DM(ctx->opcode) & 2) == 0) {
tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrh(xA(ctx->opcode)));
} else {
tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrl(xA(ctx->opcode)));
}
if ((DM(ctx->opcode) & 1) == 0) {
tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xB(ctx->opcode)));
} else {
tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrl(xB(ctx->opcode)));
}
}
#define OP_ABS 1
#define OP_NABS 2
#define OP_NEG 3
#define OP_CPSGN 4
#define SGN_MASK_DP 0x8000000000000000ul
#define SGN_MASK_SP 0x8000000080000000ul
#define VSX_SCALAR_MOVE(name, op, sgn_mask) \
static void glue(gen_, name)(DisasContext * ctx) \
{ \
TCGv_i64 xb, sgm; \
if (unlikely(!ctx->vsx_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
return; \
} \
xb = tcg_temp_new(); \
sgm = tcg_temp_new(); \
tcg_gen_mov_i64(xb, cpu_vsrh(xB(ctx->opcode))); \
tcg_gen_movi_i64(sgm, sgn_mask); \
switch (op) { \
case OP_ABS: { \
tcg_gen_andc_i64(xb, xb, sgm); \
break; \
} \
case OP_NABS: { \
tcg_gen_or_i64(xb, xb, sgm); \
break; \
} \
case OP_NEG: { \
tcg_gen_xor_i64(xb, xb, sgm); \
break; \
} \
case OP_CPSGN: { \
TCGv_i64 xa = tcg_temp_new(); \
tcg_gen_mov_i64(xa, cpu_vsrh(xA(ctx->opcode))); \
tcg_gen_and_i64(xa, xa, sgm); \
tcg_gen_andc_i64(xb, xb, sgm); \
tcg_gen_or_i64(xb, xb, xa); \
tcg_temp_free(xa); \
break; \
} \
} \
tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xb); \
tcg_temp_free(xb); \
tcg_temp_free(sgm); \
}
VSX_SCALAR_MOVE(xsabsdp, OP_ABS, SGN_MASK_DP)
VSX_SCALAR_MOVE(xsnabsdp, OP_NABS, SGN_MASK_DP)
VSX_SCALAR_MOVE(xsnegdp, OP_NEG, SGN_MASK_DP)
VSX_SCALAR_MOVE(xscpsgndp, OP_CPSGN, SGN_MASK_DP)
#define VSX_VECTOR_MOVE(name, op, sgn_mask) \
static void glue(gen_, name)(DisasContext * ctx) \
{ \
TCGv_i64 xbh, xbl, sgm; \
if (unlikely(!ctx->vsx_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
return; \
} \
xbh = tcg_temp_new(); \
xbl = tcg_temp_new(); \
sgm = tcg_temp_new(); \
tcg_gen_mov_i64(xbh, cpu_vsrh(xB(ctx->opcode))); \
tcg_gen_mov_i64(xbl, cpu_vsrl(xB(ctx->opcode))); \
tcg_gen_movi_i64(sgm, sgn_mask); \
switch (op) { \
case OP_ABS: { \
tcg_gen_andc_i64(xbh, xbh, sgm); \
tcg_gen_andc_i64(xbl, xbl, sgm); \
break; \
} \
case OP_NABS: { \
tcg_gen_or_i64(xbh, xbh, sgm); \
tcg_gen_or_i64(xbl, xbl, sgm); \
break; \
} \
case OP_NEG: { \
tcg_gen_xor_i64(xbh, xbh, sgm); \
tcg_gen_xor_i64(xbl, xbl, sgm); \
break; \
} \
case OP_CPSGN: { \
TCGv_i64 xah = tcg_temp_new(); \
TCGv_i64 xal = tcg_temp_new(); \
tcg_gen_mov_i64(xah, cpu_vsrh(xA(ctx->opcode))); \
tcg_gen_mov_i64(xal, cpu_vsrl(xA(ctx->opcode))); \
tcg_gen_and_i64(xah, xah, sgm); \
tcg_gen_and_i64(xal, xal, sgm); \
tcg_gen_andc_i64(xbh, xbh, sgm); \
tcg_gen_andc_i64(xbl, xbl, sgm); \
tcg_gen_or_i64(xbh, xbh, xah); \
tcg_gen_or_i64(xbl, xbl, xal); \
tcg_temp_free(xah); \
tcg_temp_free(xal); \
break; \
} \
} \
tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xbh); \
tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), xbl); \
tcg_temp_free(xbh); \
tcg_temp_free(xbl); \
tcg_temp_free(sgm); \
}
VSX_VECTOR_MOVE(xvabsdp, OP_ABS, SGN_MASK_DP)
VSX_VECTOR_MOVE(xvnabsdp, OP_NABS, SGN_MASK_DP)
VSX_VECTOR_MOVE(xvnegdp, OP_NEG, SGN_MASK_DP)
VSX_VECTOR_MOVE(xvcpsgndp, OP_CPSGN, SGN_MASK_DP)
VSX_VECTOR_MOVE(xvabssp, OP_ABS, SGN_MASK_SP)
VSX_VECTOR_MOVE(xvnabssp, OP_NABS, SGN_MASK_SP)
VSX_VECTOR_MOVE(xvnegsp, OP_NEG, SGN_MASK_SP)
VSX_VECTOR_MOVE(xvcpsgnsp, OP_CPSGN, SGN_MASK_SP)
#define VSX_LOGICAL(name, tcg_op) \
static void glue(gen_, name)(DisasContext * ctx) \
{ \
if (unlikely(!ctx->vsx_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
return; \
} \
tcg_op(cpu_vsrh(xT(ctx->opcode)), cpu_vsrh(xA(ctx->opcode)), \
cpu_vsrh(xB(ctx->opcode))); \
tcg_op(cpu_vsrl(xT(ctx->opcode)), cpu_vsrl(xA(ctx->opcode)), \
cpu_vsrl(xB(ctx->opcode))); \
}
VSX_LOGICAL(xxland, tcg_gen_and_tl)
VSX_LOGICAL(xxlandc, tcg_gen_andc_tl)
VSX_LOGICAL(xxlor, tcg_gen_or_tl)
VSX_LOGICAL(xxlxor, tcg_gen_xor_tl)
VSX_LOGICAL(xxlnor, tcg_gen_nor_tl)
#define VSX_XXMRG(name, high) \
static void glue(gen_, name)(DisasContext * ctx) \
{ \
TCGv_i64 a0, a1, b0, b1; \
if (unlikely(!ctx->vsx_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
return; \
} \
a0 = tcg_temp_new(); \
a1 = tcg_temp_new(); \
b0 = tcg_temp_new(); \
b1 = tcg_temp_new(); \
if (high) { \
tcg_gen_mov_i64(a0, cpu_vsrh(xA(ctx->opcode))); \
tcg_gen_mov_i64(a1, cpu_vsrh(xA(ctx->opcode))); \
tcg_gen_mov_i64(b0, cpu_vsrh(xB(ctx->opcode))); \
tcg_gen_mov_i64(b1, cpu_vsrh(xB(ctx->opcode))); \
} else { \
tcg_gen_mov_i64(a0, cpu_vsrl(xA(ctx->opcode))); \
tcg_gen_mov_i64(a1, cpu_vsrl(xA(ctx->opcode))); \
tcg_gen_mov_i64(b0, cpu_vsrl(xB(ctx->opcode))); \
tcg_gen_mov_i64(b1, cpu_vsrl(xB(ctx->opcode))); \
} \
tcg_gen_shri_i64(a0, a0, 32); \
tcg_gen_shri_i64(b0, b0, 32); \
tcg_gen_deposit_i64(cpu_vsrh(xT(ctx->opcode)), \
b0, a0, 32, 32); \
tcg_gen_deposit_i64(cpu_vsrl(xT(ctx->opcode)), \
b1, a1, 32, 32); \
tcg_temp_free(a0); \
tcg_temp_free(a1); \
tcg_temp_free(b0); \
tcg_temp_free(b1); \
}
VSX_XXMRG(xxmrghw, 1)
VSX_XXMRG(xxmrglw, 0)
static void gen_xxsel(DisasContext * ctx)
{
TCGv_i64 a, b, c;
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
return;
}
a = tcg_temp_new();
b = tcg_temp_new();
c = tcg_temp_new();
tcg_gen_mov_i64(a, cpu_vsrh(xA(ctx->opcode)));
tcg_gen_mov_i64(b, cpu_vsrh(xB(ctx->opcode)));
tcg_gen_mov_i64(c, cpu_vsrh(xC(ctx->opcode)));
tcg_gen_and_i64(b, b, c);
tcg_gen_andc_i64(a, a, c);
tcg_gen_or_i64(cpu_vsrh(xT(ctx->opcode)), a, b);
tcg_gen_mov_i64(a, cpu_vsrl(xA(ctx->opcode)));
tcg_gen_mov_i64(b, cpu_vsrl(xB(ctx->opcode)));
tcg_gen_mov_i64(c, cpu_vsrl(xC(ctx->opcode)));
tcg_gen_and_i64(b, b, c);
tcg_gen_andc_i64(a, a, c);
tcg_gen_or_i64(cpu_vsrl(xT(ctx->opcode)), a, b);
tcg_temp_free(a);
tcg_temp_free(b);
tcg_temp_free(c);
}
static void gen_xxspltw(DisasContext *ctx)
{
TCGv_i64 b, b2;
TCGv_i64 vsr = (UIM(ctx->opcode) & 2) ?
cpu_vsrl(xB(ctx->opcode)) :
cpu_vsrh(xB(ctx->opcode));
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
return;
}
b = tcg_temp_new();
b2 = tcg_temp_new();
if (UIM(ctx->opcode) & 1) {
tcg_gen_ext32u_i64(b, vsr);
} else {
tcg_gen_shri_i64(b, vsr, 32);
}
tcg_gen_shli_i64(b2, b, 32);
tcg_gen_or_i64(cpu_vsrh(xT(ctx->opcode)), b, b2);
tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xT(ctx->opcode)));
tcg_temp_free(b);
tcg_temp_free(b2);
}
static void gen_xxsldwi(DisasContext *ctx)
{
TCGv_i64 xth, xtl;
if (unlikely(!ctx->vsx_enabled)) {
gen_exception(ctx, POWERPC_EXCP_VSXU);
return;
}
xth = tcg_temp_new();
xtl = tcg_temp_new();
switch (SHW(ctx->opcode)) {
case 0: {
tcg_gen_mov_i64(xth, cpu_vsrh(xA(ctx->opcode)));
tcg_gen_mov_i64(xtl, cpu_vsrl(xA(ctx->opcode)));
break;
}
case 1: {
TCGv_i64 t0 = tcg_temp_new();
tcg_gen_mov_i64(xth, cpu_vsrh(xA(ctx->opcode)));
tcg_gen_shli_i64(xth, xth, 32);
tcg_gen_mov_i64(t0, cpu_vsrl(xA(ctx->opcode)));
tcg_gen_shri_i64(t0, t0, 32);
tcg_gen_or_i64(xth, xth, t0);
tcg_gen_mov_i64(xtl, cpu_vsrl(xA(ctx->opcode)));
tcg_gen_shli_i64(xtl, xtl, 32);
tcg_gen_mov_i64(t0, cpu_vsrh(xB(ctx->opcode)));
tcg_gen_shri_i64(t0, t0, 32);
tcg_gen_or_i64(xtl, xtl, t0);
tcg_temp_free(t0);
break;
}
case 2: {
tcg_gen_mov_i64(xth, cpu_vsrl(xA(ctx->opcode)));
tcg_gen_mov_i64(xtl, cpu_vsrh(xB(ctx->opcode)));
break;
}
case 3: {
TCGv_i64 t0 = tcg_temp_new();
tcg_gen_mov_i64(xth, cpu_vsrl(xA(ctx->opcode)));
tcg_gen_shli_i64(xth, xth, 32);
tcg_gen_mov_i64(t0, cpu_vsrh(xB(ctx->opcode)));
tcg_gen_shri_i64(t0, t0, 32);
tcg_gen_or_i64(xth, xth, t0);
tcg_gen_mov_i64(xtl, cpu_vsrh(xB(ctx->opcode)));
tcg_gen_shli_i64(xtl, xtl, 32);
tcg_gen_mov_i64(t0, cpu_vsrl(xB(ctx->opcode)));
tcg_gen_shri_i64(t0, t0, 32);
tcg_gen_or_i64(xtl, xtl, t0);
tcg_temp_free(t0);
break;
}
}
tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xth);
tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), xtl);
tcg_temp_free(xth);
tcg_temp_free(xtl);
}
/*** SPE extension ***/
/* Register moves */
static inline void gen_evmra(DisasContext *ctx)
{
@ -9413,6 +9898,119 @@ GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20),
GEN_VAFORM_PAIRED(vsel, vperm, 21),
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23),
GEN_HANDLER_E(lxsdx, 0x1F, 0x0C, 0x12, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(lxvd2x, 0x1F, 0x0C, 0x1A, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(lxvdsx, 0x1F, 0x0C, 0x0A, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(lxvw4x, 0x1F, 0x0C, 0x18, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(stxsdx, 0x1F, 0xC, 0x16, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(stxvd2x, 0x1F, 0xC, 0x1E, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(stxvw4x, 0x1F, 0xC, 0x1C, 0, PPC_NONE, PPC2_VSX),
#undef GEN_XX2FORM
#define GEN_XX2FORM(name, opc2, opc3, fl2) \
GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \
GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2)
#undef GEN_XX3FORM
#define GEN_XX3FORM(name, opc2, opc3, fl2) \
GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 0, opc3, 0, PPC_NONE, fl2), \
GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 1, opc3, 0, PPC_NONE, fl2), \
GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 2, opc3, 0, PPC_NONE, fl2), \
GEN_HANDLER2_E(name, #name, 0x3C, opc2 | 3, opc3, 0, PPC_NONE, fl2)
#undef GEN_XX3FORM_DM
#define GEN_XX3FORM_DM(name, opc2, opc3) \
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x00, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x04, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x08, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x00, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x01, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x02, opc3|0x0C, 0, PPC_NONE, PPC2_VSX),\
GEN_HANDLER2_E(name, #name, 0x3C, opc2|0x03, opc3|0x0C, 0, PPC_NONE, PPC2_VSX)
GEN_XX2FORM(xsabsdp, 0x12, 0x15, PPC2_VSX),
GEN_XX2FORM(xsnabsdp, 0x12, 0x16, PPC2_VSX),
GEN_XX2FORM(xsnegdp, 0x12, 0x17, PPC2_VSX),
GEN_XX3FORM(xscpsgndp, 0x00, 0x16, PPC2_VSX),
GEN_XX2FORM(xvabsdp, 0x12, 0x1D, PPC2_VSX),
GEN_XX2FORM(xvnabsdp, 0x12, 0x1E, PPC2_VSX),
GEN_XX2FORM(xvnegdp, 0x12, 0x1F, PPC2_VSX),
GEN_XX3FORM(xvcpsgndp, 0x00, 0x1E, PPC2_VSX),
GEN_XX2FORM(xvabssp, 0x12, 0x19, PPC2_VSX),
GEN_XX2FORM(xvnabssp, 0x12, 0x1A, PPC2_VSX),
GEN_XX2FORM(xvnegsp, 0x12, 0x1B, PPC2_VSX),
GEN_XX3FORM(xvcpsgnsp, 0x00, 0x1A, PPC2_VSX),
#undef VSX_LOGICAL
#define VSX_LOGICAL(name, opc2, opc3, fl2) \
GEN_XX3FORM(name, opc2, opc3, fl2)
VSX_LOGICAL(xxland, 0x8, 0x10, PPC2_VSX),
VSX_LOGICAL(xxlandc, 0x8, 0x11, PPC2_VSX),
VSX_LOGICAL(xxlor, 0x8, 0x12, PPC2_VSX),
VSX_LOGICAL(xxlxor, 0x8, 0x13, PPC2_VSX),
VSX_LOGICAL(xxlnor, 0x8, 0x14, PPC2_VSX),
GEN_XX3FORM(xxmrghw, 0x08, 0x02, PPC2_VSX),
GEN_XX3FORM(xxmrglw, 0x08, 0x06, PPC2_VSX),
GEN_XX2FORM(xxspltw, 0x08, 0x0A, PPC2_VSX),
GEN_XX3FORM_DM(xxsldwi, 0x08, 0x00),
#define GEN_XXSEL_ROW(opc3) \
GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x18, opc3, 0, PPC_NONE, PPC2_VSX), \
GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x19, opc3, 0, PPC_NONE, PPC2_VSX), \
GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1A, opc3, 0, PPC_NONE, PPC2_VSX), \
GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1B, opc3, 0, PPC_NONE, PPC2_VSX), \
GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1C, opc3, 0, PPC_NONE, PPC2_VSX), \
GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1D, opc3, 0, PPC_NONE, PPC2_VSX), \
GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1E, opc3, 0, PPC_NONE, PPC2_VSX), \
GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1F, opc3, 0, PPC_NONE, PPC2_VSX), \
GEN_XXSEL_ROW(0x00)
GEN_XXSEL_ROW(0x01)
GEN_XXSEL_ROW(0x02)
GEN_XXSEL_ROW(0x03)
GEN_XXSEL_ROW(0x04)
GEN_XXSEL_ROW(0x05)
GEN_XXSEL_ROW(0x06)
GEN_XXSEL_ROW(0x07)
GEN_XXSEL_ROW(0x08)
GEN_XXSEL_ROW(0x09)
GEN_XXSEL_ROW(0x0A)
GEN_XXSEL_ROW(0x0B)
GEN_XXSEL_ROW(0x0C)
GEN_XXSEL_ROW(0x0D)
GEN_XXSEL_ROW(0x0E)
GEN_XXSEL_ROW(0x0F)
GEN_XXSEL_ROW(0x10)
GEN_XXSEL_ROW(0x11)
GEN_XXSEL_ROW(0x12)
GEN_XXSEL_ROW(0x13)
GEN_XXSEL_ROW(0x14)
GEN_XXSEL_ROW(0x15)
GEN_XXSEL_ROW(0x16)
GEN_XXSEL_ROW(0x17)
GEN_XXSEL_ROW(0x18)
GEN_XXSEL_ROW(0x19)
GEN_XXSEL_ROW(0x1A)
GEN_XXSEL_ROW(0x1B)
GEN_XXSEL_ROW(0x1C)
GEN_XXSEL_ROW(0x1D)
GEN_XXSEL_ROW(0x1E)
GEN_XXSEL_ROW(0x1F)
GEN_XX3FORM_DM(xxpermdi, 0x08, 0x01),
#undef GEN_SPE
#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
@ -9759,6 +10357,11 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
ctx.altivec_enabled = msr_vr;
else
ctx.altivec_enabled = 0;
if ((env->flags & POWERPC_FLAG_VSX) && msr_vsx) {
ctx.vsx_enabled = msr_vsx;
} else {
ctx.vsx_enabled = 0;
}
if ((env->flags & POWERPC_FLAG_SE) && msr_se)
ctx.singlestep_enabled = CPU_SINGLE_STEP;
else

View File

@ -3061,6 +3061,7 @@ static void init_excp_POWER7 (CPUPPCState *env)
env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00;
env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00;
env->excp_vectors[POWERPC_EXCP_VPU] = 0x00000F20;
env->excp_vectors[POWERPC_EXCP_VSXU] = 0x00000F40;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_MAINT] = 0x00001600;
env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001700;
@ -7221,6 +7222,46 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER7";
dc->desc = "POWER7";
pcc->pvr = CPU_POWERPC_POWER7_BASE;
pcc->pvr_mask = CPU_POWERPC_POWER7_MASK;
pcc->init_proc = init_proc_POWER7;
pcc->check_pow = check_pow_nocheck;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
PPC_FLOAT_STFIWX |
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_64B | PPC_ALTIVEC |
PPC_SEGMENT_64B | PPC_SLBI |
PPC_POPCNTB | PPC_POPCNTWD;
pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX | PPC2_ISA205;
pcc->msr_mask = 0x800000000284FF37ULL;
pcc->mmu_model = POWERPC_MMU_2_06;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
#endif
pcc->excp_model = POWERPC_EXCP_POWER7;
pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
pcc->bfd_mach = bfd_mach_ppc64;
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR |
POWERPC_FLAG_VSX;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
}
POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
dc->fw_name = "PowerPC,POWER7+";
dc->desc = "POWER7+";
pcc->pvr = CPU_POWERPC_POWER7P_BASE;
pcc->pvr_mask = CPU_POWERPC_POWER7P_MASK;
pcc->init_proc = init_proc_POWER7;
pcc->check_pow = check_pow_nocheck;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
@ -7244,7 +7285,8 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
pcc->bfd_mach = bfd_mach_ppc64;
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR;
POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR |
POWERPC_FLAG_VSX;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
}
@ -7256,6 +7298,8 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER8";
dc->desc = "POWER8";
pcc->pvr = CPU_POWERPC_POWER8_BASE;
pcc->pvr_mask = CPU_POWERPC_POWER8_MASK;
pcc->init_proc = init_proc_POWER7;
pcc->check_pow = check_pow_nocheck;
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@ -7269,7 +7313,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
PPC_SEGMENT_64B | PPC_SLBI |
PPC_POPCNTB | PPC_POPCNTWD;
pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX;
pcc->msr_mask = 0x800000000204FF36ULL;
pcc->msr_mask = 0x800000000284FF36ULL;
pcc->mmu_model = POWERPC_MMU_2_06;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
@ -7279,7 +7323,8 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
pcc->bfd_mach = bfd_mach_ppc64;
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR;
POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR |
POWERPC_FLAG_VSX;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
}
@ -8188,6 +8233,44 @@ PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr)
return pcc;
}
static gint ppc_cpu_compare_class_pvr_mask(gconstpointer a, gconstpointer b)
{
ObjectClass *oc = (ObjectClass *)a;
uint32_t pvr = *(uint32_t *)b;
PowerPCCPUClass *pcc = (PowerPCCPUClass *)a;
gint ret;
/* -cpu host does a PVR lookup during construction */
if (unlikely(strcmp(object_class_get_name(oc),
TYPE_HOST_POWERPC_CPU) == 0)) {
return -1;
}
#if defined(TARGET_PPCEMB)
if (pcc->mmu_model != POWERPC_MMU_BOOKE) {
return -1;
}
#endif
ret = (((pcc->pvr & pcc->pvr_mask) == (pvr & pcc->pvr_mask)) ? 0 : -1);
return ret;
}
PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr)
{
GSList *list, *item;
PowerPCCPUClass *pcc = NULL;
list = object_class_get_list(TYPE_POWERPC_CPU, true);
item = g_slist_find_custom(list, &pvr, ppc_cpu_compare_class_pvr_mask);
if (item != NULL) {
pcc = POWERPC_CPU_CLASS(item->data);
}
g_slist_free(list);
return pcc;
}
static gint ppc_cpu_compare_class_name(gconstpointer a, gconstpointer b)
{
ObjectClass *oc = (ObjectClass *)a;
@ -8559,6 +8642,8 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
DeviceClass *dc = DEVICE_CLASS(oc);
pcc->parent_realize = dc->realize;
pcc->pvr = CPU_POWERPC_DEFAULT_MASK;
pcc->pvr_mask = CPU_POWERPC_DEFAULT_MASK;
dc->realize = ppc_cpu_realizefn;
dc->unrealize = ppc_cpu_unrealizefn;