ppc patch queue 2018-04-27

Here's the first batch of ppc patches for 2.13.  This has a lot of
 stuff that's accumulated during the 2.12 freeze.  Highlights are:
 
     * Many improvements for the Uninorth PCI host bridge for Mac
       machine types
     * Preliminary helpers improve handling of multiple backing
       pagesizes (not strictly ppc related, but have acks and aimed to
       allow future ppc changes)
     * Cleanups to pseries cpu initialization
     * Cleanups to hash64 MMU handling
     * Assorted bugfixes and improvements
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAlri614ACgkQbDjKyiDZ
 s5L1HRAAtK/QDUBVsMKylPSZ66AtoiqjBjEBGZrC5WznbwE+EPvuBLtYzugi60xh
 ieMH6AYTBrYgGvsqIncUmAONYqUvieLsDHEC2IS8sq6vI6etEEAWCY/1xAKV7+Vz
 KpGluT2YX1WPBxz+fK3yVJAFciEdsRtqS4+3+Ofa0YwxNFLX7d5/ZKHoh4CNSF6x
 zs9/15uhJZ8nZhjA7gx4naVTeFU4Tq9zcv45tnbwAVW0seNf9Q1kvpyomoWHhCBZ
 mhyS0LlMCtmVKx0WBU5npRYd33VBdtYdYsTzLfoFwYMhDghAccUv9w5810cYkOwR
 j8YW+AdWMZiigNk9KRGG7+x0NPB/aNyiK9a1wJ2C95i5sQSqs9HbPJFg5UoPl5HV
 4Pz8nC1g8Mzw6HrfXEZA1FaszL63MxOx8lD+C1+wnzv8YhaCuf45Yi+WAnhR9BVv
 qOU7ORpxZmURjc6Iuu5Omyx+04dlBOl98wVBPGxcSTW0Kyr5l4Pdg9A6ycEPanyW
 JT8JMQBL+wPufBSMLXgdjEZ1nffDEYVo2jcn2rxF1V5j1oY7Ibc0svG07wQwFlbb
 PoRskZkZdMLVOQLo1wj3phS1iwji+pq7aMHWcKa/I45f3D4MIKgvNZ3PAFFbdWM+
 92Bmm+NkcCggwHnSkRUAjqv2yF1zREWaz0N/jSuG7tIQWTLovqI=
 =H9b6
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.13-20180427' into staging

ppc patch queue 2018-04-27

Here's the first batch of ppc patches for 2.13.  This has a lot of
stuff that's accumulated during the 2.12 freeze.  Highlights are:

    * Many improvements for the Uninorth PCI host bridge for Mac
      machine types
    * Preliminary helpers improve handling of multiple backing
      pagesizes (not strictly ppc related, but have acks and aimed to
      allow future ppc changes)
    * Cleanups to pseries cpu initialization
    * Cleanups to hash64 MMU handling
    * Assorted bugfixes and improvements

# gpg: Signature made Fri 27 Apr 2018 10:20:30 BST
# gpg:                using RSA key 6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg:                 aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg:                 aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg:                 aka "David Gibson (kernel.org) <dwg@kernel.org>"
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-for-2.13-20180427: (49 commits)
  Clear mem_path if we fall back to anonymous RAM allocation
  spapr: Set compatibility mode before the rest of spapr_cpu_reset()
  target/ppc: Don't bother with MSR_EP in cpu_ppc_set_papr()
  spapr: Support ibm,dynamic-memory-v2 property
  ppc: e500: switch E500 based machines to full machine definition
  spapr: Add ibm,max-associativity-domains property
  target/ppc: Fold slb_nr into PPCHash64Options
  target/ppc: Get rid of POWERPC_MMU_VER() macros
  target/ppc: Remove unnecessary POWERPC_MMU_V3 flag from mmu_model
  target/ppc: Fold ci_large_pages flag into PPCHash64Options
  target/ppc: Move 1T segment and AMR options to PPCHash64Options
  target/ppc: Make hash64_opts field mandatory for 64-bit hash MMUs
  target/ppc: Split page size information into a separate allocation
  target/ppc: Move page size setup to helper function
  target/ppc: Remove fallback 64k pagesize information
  target/ppc: Avoid taking "env" parameter to mmu-hash64 functions
  target/ppc: Pass cpu instead of env to ppc_create_page_sizes_prop()
  target/ppc: Simplify cpu valid check in ppc_cpu_realize
  target/ppc: Standardize instance_init and realize function names
  spapr: drop useless dynamic sysbus device sanity check
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-04-27 10:49:23 +01:00
commit dcbd26f881
37 changed files with 1145 additions and 823 deletions

View File

@ -18,6 +18,7 @@
#include "qapi/visitor.h" #include "qapi/visitor.h"
#include "qemu/config-file.h" #include "qemu/config-file.h"
#include "qom/object_interfaces.h" #include "qom/object_interfaces.h"
#include "qemu/mmap-alloc.h"
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
#include <numaif.h> #include <numaif.h>
@ -262,6 +263,23 @@ bool host_memory_backend_is_mapped(HostMemoryBackend *backend)
return backend->is_mapped; return backend->is_mapped;
} }
#ifdef __linux__
size_t host_memory_backend_pagesize(HostMemoryBackend *memdev)
{
Object *obj = OBJECT(memdev);
char *path = object_property_get_str(obj, "mem-path", NULL);
size_t pagesize = qemu_mempath_getpagesize(path);
g_free(path);
return pagesize;
}
#else
size_t host_memory_backend_pagesize(HostMemoryBackend *memdev)
{
return getpagesize();
}
#endif
static void static void
host_memory_backend_memory_complete(UserCreatable *uc, Error **errp) host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
{ {

View File

@ -387,4 +387,23 @@ Each LMB list entry consists of the following elements:
- A 32bit flags word. The bit at bit position 0x00000008 defines whether - A 32bit flags word. The bit at bit position 0x00000008 defines whether
the LMB is assigned to the the partition as of boot time. the LMB is assigned to the the partition as of boot time.
ibm,dynamic-memory-v2
This property describes the dynamically reconfigurable memory. This is
an alternate and newer way to describe dyanamically reconfigurable memory.
It is a property encoded array that has an integer N (the number of
LMB set entries) followed by N LMB set entries. There is an LMB set entry
for each sequential group of LMBs that share common attributes.
Each LMB set entry consists of the following elements:
- Number of sequential LMBs in the entry represented by a 32bit integer.
- Logical address of the first LMB in the set encoded as a 64bit integer.
- DRC index of the first LMB in the set.
- Associativity list index that is used as an index into
ibm,associativity-lookup-arrays property described earlier. This
is used to retrieve the right associativity list to be used for all
the LMBs in this set.
- A 32bit flags word that applies to all the LMBs in the set.
[1] http://thread.gmane.org/gmane.linux.ports.ppc.embedded/75350/focus=106867 [1] http://thread.gmane.org/gmane.linux.ports.ppc.embedded/75350/focus=106867

20
exec.c
View File

@ -1488,19 +1488,13 @@ void ram_block_dump(Monitor *mon)
*/ */
static int find_max_supported_pagesize(Object *obj, void *opaque) static int find_max_supported_pagesize(Object *obj, void *opaque)
{ {
char *mem_path;
long *hpsize_min = opaque; long *hpsize_min = opaque;
if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) { if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
mem_path = object_property_get_str(obj, "mem-path", NULL); long hpsize = host_memory_backend_pagesize(MEMORY_BACKEND(obj));
if (mem_path) {
long hpsize = qemu_mempath_getpagesize(mem_path); if (hpsize < *hpsize_min) {
g_free(mem_path); *hpsize_min = hpsize;
if (hpsize < *hpsize_min) {
*hpsize_min = hpsize;
}
} else {
*hpsize_min = getpagesize();
} }
} }
@ -1513,11 +1507,7 @@ long qemu_getrampagesize(void)
long mainrampagesize; long mainrampagesize;
Object *memdev_root; Object *memdev_root;
if (mem_path) { mainrampagesize = qemu_mempath_getpagesize(mem_path);
mainrampagesize = qemu_mempath_getpagesize(mem_path);
} else {
mainrampagesize = getpagesize();
}
/* it's possible we have memory-backend objects with /* it's possible we have memory-backend objects with
* hugepage-backed RAM. these may get mapped into system * hugepage-backed RAM. these may get mapped into system

View File

@ -172,29 +172,16 @@ static void heathrow_init(Object *obj)
HeathrowState *s = HEATHROW(obj); HeathrowState *s = HEATHROW(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
/* only 1 CPU */
qdev_init_gpio_out(DEVICE(obj), s->irqs, 1);
qdev_init_gpio_in(DEVICE(obj), heathrow_set_irq, HEATHROW_NUM_IRQS);
memory_region_init_io(&s->mem, OBJECT(s), &heathrow_ops, s, memory_region_init_io(&s->mem, OBJECT(s), &heathrow_ops, s,
"heathrow-pic", 0x1000); "heathrow-pic", 0x1000);
sysbus_init_mmio(sbd, &s->mem); sysbus_init_mmio(sbd, &s->mem);
} }
DeviceState *heathrow_pic_init(int nb_cpus, qemu_irq **irqs,
qemu_irq **pic_irqs)
{
DeviceState *d;
HeathrowState *s;
d = qdev_create(NULL, TYPE_HEATHROW);
qdev_init_nofail(d);
s = HEATHROW(d);
/* only 1 CPU */
s->irqs = irqs[0];
*pic_irqs = qemu_allocate_irqs(heathrow_set_irq, s, HEATHROW_NUM_IRQS);
return d;
}
static void heathrow_class_init(ObjectClass *oc, void *data) static void heathrow_class_init(ObjectClass *oc, void *data)
{ {
DeviceClass *dc = DEVICE_CLASS(oc); DeviceClass *dc = DEVICE_CLASS(oc);

View File

@ -152,10 +152,9 @@ static void macio_oldworld_realize(PCIDevice *d, Error **errp)
{ {
MacIOState *s = MACIO(d); MacIOState *s = MACIO(d);
OldWorldMacIOState *os = OLDWORLD_MACIO(d); OldWorldMacIOState *os = OLDWORLD_MACIO(d);
DeviceState *pic_dev = DEVICE(os->pic);
Error *err = NULL; Error *err = NULL;
SysBusDevice *sysbus_dev; SysBusDevice *sysbus_dev;
int i;
int cur_irq = 0;
macio_common_realize(d, &err); macio_common_realize(d, &err);
if (err) { if (err) {
@ -164,11 +163,14 @@ static void macio_oldworld_realize(PCIDevice *d, Error **errp)
} }
sysbus_dev = SYS_BUS_DEVICE(&s->cuda); sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]); sysbus_connect_irq(sysbus_dev, 0, qdev_get_gpio_in(pic_dev,
OLDWORLD_CUDA_IRQ));
sysbus_dev = SYS_BUS_DEVICE(&s->escc); sysbus_dev = SYS_BUS_DEVICE(&s->escc);
sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]); sysbus_connect_irq(sysbus_dev, 0, qdev_get_gpio_in(pic_dev,
sysbus_connect_irq(sysbus_dev, 1, os->irqs[cur_irq++]); OLDWORLD_ESCCB_IRQ));
sysbus_connect_irq(sysbus_dev, 1, qdev_get_gpio_in(pic_dev,
OLDWORLD_ESCCA_IRQ));
object_property_set_bool(OBJECT(&os->nvram), true, "realized", &err); object_property_set_bool(OBJECT(&os->nvram), true, "realized", &err);
if (err) { if (err) {
@ -186,15 +188,22 @@ static void macio_oldworld_realize(PCIDevice *d, Error **errp)
sysbus_mmio_get_region(sysbus_dev, 0)); sysbus_mmio_get_region(sysbus_dev, 0));
/* IDE buses */ /* IDE buses */
for (i = 0; i < ARRAY_SIZE(os->ide); i++) { macio_realize_ide(s, &os->ide[0],
qemu_irq irq0 = os->irqs[cur_irq++]; qdev_get_gpio_in(pic_dev, OLDWORLD_IDE0_IRQ),
qemu_irq irq1 = os->irqs[cur_irq++]; qdev_get_gpio_in(pic_dev, OLDWORLD_IDE0_DMA_IRQ),
0x16, &err);
if (err) {
error_propagate(errp, err);
return;
}
macio_realize_ide(s, &os->ide[i], irq0, irq1, 0x16 + (i * 4), &err); macio_realize_ide(s, &os->ide[1],
if (err) { qdev_get_gpio_in(pic_dev, OLDWORLD_IDE1_IRQ),
error_propagate(errp, err); qdev_get_gpio_in(pic_dev, OLDWORLD_IDE1_DMA_IRQ),
return; 0x1a, &err);
} if (err) {
error_propagate(errp, err);
return;
} }
} }
@ -219,8 +228,6 @@ static void macio_oldworld_init(Object *obj)
DeviceState *dev; DeviceState *dev;
int i; int i;
qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs));
object_property_add_link(obj, "pic", TYPE_HEATHROW, object_property_add_link(obj, "pic", TYPE_HEATHROW,
(Object **) &os->pic, (Object **) &os->pic,
qdev_prop_allow_set_link_before_realize, qdev_prop_allow_set_link_before_realize,

View File

@ -27,6 +27,8 @@
#include "hw/pci/pci_host.h" #include "hw/pci/pci_host.h"
#include "hw/ppc/mac.h" #include "hw/ppc/mac.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "hw/intc/heathrow_pic.h"
#include "qapi/error.h"
#include "trace.h" #include "trace.h"
#define GRACKLE_PCI_HOST_BRIDGE(obj) \ #define GRACKLE_PCI_HOST_BRIDGE(obj) \
@ -35,8 +37,11 @@
typedef struct GrackleState { typedef struct GrackleState {
PCIHostState parent_obj; PCIHostState parent_obj;
HeathrowState *pic;
qemu_irq irqs[4];
MemoryRegion pci_mmio; MemoryRegion pci_mmio;
MemoryRegion pci_hole; MemoryRegion pci_hole;
MemoryRegion pci_io;
} GrackleState; } GrackleState;
/* Don't know if this matches real hardware, but it agrees with OHW. */ /* Don't know if this matches real hardware, but it agrees with OHW. */
@ -47,76 +52,78 @@ static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num)
static void pci_grackle_set_irq(void *opaque, int irq_num, int level) static void pci_grackle_set_irq(void *opaque, int irq_num, int level)
{ {
qemu_irq *pic = opaque; GrackleState *s = opaque;
trace_grackle_set_irq(irq_num, level); trace_grackle_set_irq(irq_num, level);
qemu_set_irq(pic[irq_num + 0x15], level); qemu_set_irq(s->irqs[irq_num], level);
} }
PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic, static void grackle_init_irqs(GrackleState *s)
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io)
{ {
DeviceState *dev; int i;
SysBusDevice *s;
PCIHostState *phb;
GrackleState *d;
dev = qdev_create(NULL, TYPE_GRACKLE_PCI_HOST_BRIDGE); for (i = 0; i < ARRAY_SIZE(s->irqs); i++) {
s = SYS_BUS_DEVICE(dev); s->irqs[i] = qdev_get_gpio_in(DEVICE(s->pic), 0x15 + i);
phb = PCI_HOST_BRIDGE(dev); }
d = GRACKLE_PCI_HOST_BRIDGE(dev); }
memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL); static void grackle_realize(DeviceState *dev, Error **errp)
memory_region_init_alias(&d->pci_hole, OBJECT(s), "pci-hole", &d->pci_mmio, {
0x80000000ULL, 0x7e000000ULL); GrackleState *s = GRACKLE_PCI_HOST_BRIDGE(dev);
memory_region_add_subregion(address_space_mem, 0x80000000ULL, PCIHostState *phb = PCI_HOST_BRIDGE(dev);
&d->pci_hole);
phb->bus = pci_register_root_bus(dev, NULL, phb->bus = pci_register_root_bus(dev, NULL,
pci_grackle_set_irq, pci_grackle_set_irq,
pci_grackle_map_irq, pci_grackle_map_irq,
pic, s,
&d->pci_mmio, &s->pci_mmio,
address_space_io, &s->pci_io,
0, 4, TYPE_PCI_BUS); 0, 4, TYPE_PCI_BUS);
pci_create_simple(phb->bus, 0, "grackle"); pci_create_simple(phb->bus, 0, "grackle");
qdev_init_nofail(dev); grackle_init_irqs(s);
sysbus_mmio_map(s, 0, base);
sysbus_mmio_map(s, 1, base + 0x00200000);
return phb->bus;
} }
static int pci_grackle_init_device(SysBusDevice *dev) static void grackle_init(Object *obj)
{ {
PCIHostState *phb; GrackleState *s = GRACKLE_PCI_HOST_BRIDGE(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
PCIHostState *phb = PCI_HOST_BRIDGE(obj);
phb = PCI_HOST_BRIDGE(dev); memory_region_init(&s->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL);
memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj,
"pci-isa-mmio", 0x00200000);
memory_region_init_io(&phb->conf_mem, OBJECT(dev), &pci_host_conf_le_ops, memory_region_init_alias(&s->pci_hole, OBJECT(s), "pci-hole", &s->pci_mmio,
dev, "pci-conf-idx", 0x1000); 0x80000000ULL, 0x7e000000ULL);
memory_region_init_io(&phb->data_mem, OBJECT(dev), &pci_host_data_le_ops,
dev, "pci-data-idx", 0x1000);
sysbus_init_mmio(dev, &phb->conf_mem);
sysbus_init_mmio(dev, &phb->data_mem);
return 0; memory_region_init_io(&phb->conf_mem, obj, &pci_host_conf_le_ops,
DEVICE(obj), "pci-conf-idx", 0x1000);
memory_region_init_io(&phb->data_mem, obj, &pci_host_data_le_ops,
DEVICE(obj), "pci-data-idx", 0x1000);
object_property_add_link(obj, "pic", TYPE_HEATHROW,
(Object **) &s->pic,
qdev_prop_allow_set_link_before_realize,
0, NULL);
sysbus_init_mmio(sbd, &phb->conf_mem);
sysbus_init_mmio(sbd, &phb->data_mem);
sysbus_init_mmio(sbd, &s->pci_hole);
sysbus_init_mmio(sbd, &s->pci_io);
} }
static void grackle_pci_host_realize(PCIDevice *d, Error **errp) static void grackle_pci_realize(PCIDevice *d, Error **errp)
{ {
d->config[0x09] = 0x01; d->config[0x09] = 0x01;
} }
static void grackle_pci_class_init(ObjectClass *klass, void *data) static void grackle_pci_class_init(ObjectClass *klass, void *data)
{ {
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->realize = grackle_pci_host_realize; k->realize = grackle_pci_realize;
k->vendor_id = PCI_VENDOR_ID_MOTOROLA; k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106; k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106;
k->revision = 0x00; k->revision = 0x00;
@ -139,26 +146,26 @@ static const TypeInfo grackle_pci_info = {
}, },
}; };
static void pci_grackle_class_init(ObjectClass *klass, void *data) static void grackle_class_init(ObjectClass *klass, void *data)
{ {
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
k->init = pci_grackle_init_device; dc->realize = grackle_realize;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
} }
static const TypeInfo grackle_pci_host_info = { static const TypeInfo grackle_host_info = {
.name = TYPE_GRACKLE_PCI_HOST_BRIDGE, .name = TYPE_GRACKLE_PCI_HOST_BRIDGE,
.parent = TYPE_PCI_HOST_BRIDGE, .parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(GrackleState), .instance_size = sizeof(GrackleState),
.class_init = pci_grackle_class_init, .instance_init = grackle_init,
.class_init = grackle_class_init,
}; };
static void grackle_register_types(void) static void grackle_register_types(void)
{ {
type_register_static(&grackle_pci_info); type_register_static(&grackle_pci_info);
type_register_static(&grackle_pci_host_info); type_register_static(&grackle_host_info);
} }
type_init(grackle_register_types) type_init(grackle_register_types)

View File

@ -26,31 +26,11 @@
#include "hw/ppc/mac.h" #include "hw/ppc/mac.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "hw/pci/pci_host.h" #include "hw/pci/pci_host.h"
#include "hw/pci-host/uninorth.h"
#include "trace.h" #include "trace.h"
static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e }; static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e };
#define TYPE_UNI_NORTH_PCI_HOST_BRIDGE "uni-north-pci-pcihost"
#define TYPE_UNI_NORTH_AGP_HOST_BRIDGE "uni-north-agp-pcihost"
#define TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE "uni-north-internal-pci-pcihost"
#define TYPE_U3_AGP_HOST_BRIDGE "u3-agp-pcihost"
#define UNI_NORTH_PCI_HOST_BRIDGE(obj) \
OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_PCI_HOST_BRIDGE)
#define UNI_NORTH_AGP_HOST_BRIDGE(obj) \
OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_AGP_HOST_BRIDGE)
#define UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj) \
OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE)
#define U3_AGP_HOST_BRIDGE(obj) \
OBJECT_CHECK(UNINState, (obj), TYPE_U3_AGP_HOST_BRIDGE)
typedef struct UNINState {
PCIHostState parent_obj;
MemoryRegion pci_mmio;
MemoryRegion pci_hole;
} UNINState;
static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num) static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
{ {
return (irq_num + (pci_dev->devfn >> 3)) & 3; return (irq_num + (pci_dev->devfn >> 3)) & 3;
@ -58,10 +38,10 @@ static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
static void pci_unin_set_irq(void *opaque, int irq_num, int level) static void pci_unin_set_irq(void *opaque, int irq_num, int level)
{ {
qemu_irq *pic = opaque; UNINHostState *s = opaque;
trace_unin_set_irq(unin_irq_line[irq_num], level); trace_unin_set_irq(unin_irq_line[irq_num], level);
qemu_set_irq(pic[unin_irq_line[irq_num]], level); qemu_set_irq(s->irqs[irq_num], level);
} }
static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr) static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr)
@ -101,7 +81,7 @@ static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr)
static void unin_data_write(void *opaque, hwaddr addr, static void unin_data_write(void *opaque, hwaddr addr,
uint64_t val, unsigned len) uint64_t val, unsigned len)
{ {
UNINState *s = opaque; UNINHostState *s = opaque;
PCIHostState *phb = PCI_HOST_BRIDGE(s); PCIHostState *phb = PCI_HOST_BRIDGE(s);
trace_unin_data_write(addr, len, val); trace_unin_data_write(addr, len, val);
pci_data_write(phb->bus, pci_data_write(phb->bus,
@ -112,7 +92,7 @@ static void unin_data_write(void *opaque, hwaddr addr,
static uint64_t unin_data_read(void *opaque, hwaddr addr, static uint64_t unin_data_read(void *opaque, hwaddr addr,
unsigned len) unsigned len)
{ {
UNINState *s = opaque; UNINHostState *s = opaque;
PCIHostState *phb = PCI_HOST_BRIDGE(s); PCIHostState *phb = PCI_HOST_BRIDGE(s);
uint32_t val; uint32_t val;
@ -129,189 +109,201 @@ static const MemoryRegionOps unin_data_ops = {
.endianness = DEVICE_LITTLE_ENDIAN, .endianness = DEVICE_LITTLE_ENDIAN,
}; };
static int pci_unin_main_init_device(SysBusDevice *dev) static void pci_unin_init_irqs(UNINHostState *s)
{ {
PCIHostState *h; int i;
/* Use values found on a real PowerMac */ for (i = 0; i < ARRAY_SIZE(s->irqs); i++) {
/* Uninorth main bus */ s->irqs[i] = qdev_get_gpio_in(DEVICE(s->pic), unin_irq_line[i]);
h = PCI_HOST_BRIDGE(dev); }
memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
dev, "pci-conf-idx", 0x1000);
memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, dev,
"pci-conf-data", 0x1000);
sysbus_init_mmio(dev, &h->conf_mem);
sysbus_init_mmio(dev, &h->data_mem);
return 0;
} }
static void pci_unin_main_realize(DeviceState *dev, Error **errp)
static int pci_u3_agp_init_device(SysBusDevice *dev)
{ {
PCIHostState *h; UNINHostState *s = UNI_NORTH_PCI_HOST_BRIDGE(dev);
PCIHostState *h = PCI_HOST_BRIDGE(dev);
/* Uninorth U3 AGP bus */
h = PCI_HOST_BRIDGE(dev);
memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
dev, "pci-conf-idx", 0x1000);
memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, dev,
"pci-conf-data", 0x1000);
sysbus_init_mmio(dev, &h->conf_mem);
sysbus_init_mmio(dev, &h->data_mem);
return 0;
}
static int pci_unin_agp_init_device(SysBusDevice *dev)
{
PCIHostState *h;
/* Uninorth AGP bus */
h = PCI_HOST_BRIDGE(dev);
memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
dev, "pci-conf-idx", 0x1000);
memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops,
dev, "pci-conf-data", 0x1000);
sysbus_init_mmio(dev, &h->conf_mem);
sysbus_init_mmio(dev, &h->data_mem);
return 0;
}
static int pci_unin_internal_init_device(SysBusDevice *dev)
{
PCIHostState *h;
/* Uninorth internal bus */
h = PCI_HOST_BRIDGE(dev);
memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
dev, "pci-conf-idx", 0x1000);
memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops,
dev, "pci-conf-data", 0x1000);
sysbus_init_mmio(dev, &h->conf_mem);
sysbus_init_mmio(dev, &h->data_mem);
return 0;
}
PCIBus *pci_pmac_init(qemu_irq *pic,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io)
{
DeviceState *dev;
SysBusDevice *s;
PCIHostState *h;
UNINState *d;
/* Use values found on a real PowerMac */
/* Uninorth main bus */
dev = qdev_create(NULL, TYPE_UNI_NORTH_PCI_HOST_BRIDGE);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
h = PCI_HOST_BRIDGE(s);
d = UNI_NORTH_PCI_HOST_BRIDGE(dev);
memory_region_init(&d->pci_mmio, OBJECT(d), "pci-mmio", 0x100000000ULL);
memory_region_init_alias(&d->pci_hole, OBJECT(d), "pci-hole", &d->pci_mmio,
0x80000000ULL, 0x10000000ULL);
memory_region_add_subregion(address_space_mem, 0x80000000ULL,
&d->pci_hole);
h->bus = pci_register_root_bus(dev, NULL, h->bus = pci_register_root_bus(dev, NULL,
pci_unin_set_irq, pci_unin_map_irq, pci_unin_set_irq, pci_unin_map_irq,
pic, s,
&d->pci_mmio, &s->pci_mmio,
address_space_io, &s->pci_io,
PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS); PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
#if 0 pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-pci");
pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north"); pci_unin_init_irqs(s);
#endif
sysbus_mmio_map(s, 0, 0xf2800000);
sysbus_mmio_map(s, 1, 0xf2c00000);
/* DEC 21154 bridge */ /* DEC 21154 bridge */
#if 0 #if 0
/* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */ /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
pci_create_simple(h->bus, PCI_DEVFN(12, 0), "dec-21154"); pci_create_simple(h->bus, PCI_DEVFN(12, 0), "dec-21154");
#endif #endif
/* Uninorth AGP bus */
pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-agp");
dev = qdev_create(NULL, TYPE_UNI_NORTH_AGP_HOST_BRIDGE);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(s, 0, 0xf0800000);
sysbus_mmio_map(s, 1, 0xf0c00000);
/* Uninorth internal bus */
#if 0
/* XXX: not needed for now */
pci_create_simple(h->bus, PCI_DEVFN(14, 0),
"uni-north-internal-pci");
dev = qdev_create(NULL, TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(s, 0, 0xf4800000);
sysbus_mmio_map(s, 1, 0xf4c00000);
#endif
return h->bus;
} }
PCIBus *pci_pmac_u3_init(qemu_irq *pic, static void pci_unin_main_init(Object *obj)
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io)
{ {
DeviceState *dev; UNINHostState *s = UNI_NORTH_PCI_HOST_BRIDGE(obj);
SysBusDevice *s; SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
PCIHostState *h; PCIHostState *h = PCI_HOST_BRIDGE(obj);
UNINState *d;
/* Uninorth AGP bus */ /* Use values found on a real PowerMac */
/* Uninorth main bus */
memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
obj, "unin-pci-conf-idx", 0x1000);
memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, obj,
"unin-pci-conf-data", 0x1000);
dev = qdev_create(NULL, TYPE_U3_AGP_HOST_BRIDGE); memory_region_init(&s->pci_mmio, OBJECT(s), "unin-pci-mmio",
qdev_init_nofail(dev); 0x100000000ULL);
s = SYS_BUS_DEVICE(dev); memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj,
h = PCI_HOST_BRIDGE(dev); "unin-pci-isa-mmio", 0x00800000);
d = U3_AGP_HOST_BRIDGE(dev);
memory_region_init(&d->pci_mmio, OBJECT(d), "pci-mmio", 0x100000000ULL); memory_region_init_alias(&s->pci_hole, OBJECT(s),
memory_region_init_alias(&d->pci_hole, OBJECT(d), "pci-hole", &d->pci_mmio, "unin-pci-hole", &s->pci_mmio,
0x80000000ULL, 0x70000000ULL); 0x80000000ULL, 0x10000000ULL);
memory_region_add_subregion(address_space_mem, 0x80000000ULL,
&d->pci_hole); object_property_add_link(obj, "pic", TYPE_OPENPIC,
(Object **) &s->pic,
qdev_prop_allow_set_link_before_realize,
0, NULL);
sysbus_init_mmio(sbd, &h->conf_mem);
sysbus_init_mmio(sbd, &h->data_mem);
sysbus_init_mmio(sbd, &s->pci_hole);
sysbus_init_mmio(sbd, &s->pci_io);
}
static void pci_u3_agp_realize(DeviceState *dev, Error **errp)
{
UNINHostState *s = U3_AGP_HOST_BRIDGE(dev);
PCIHostState *h = PCI_HOST_BRIDGE(dev);
h->bus = pci_register_root_bus(dev, NULL, h->bus = pci_register_root_bus(dev, NULL,
pci_unin_set_irq, pci_unin_map_irq, pci_unin_set_irq, pci_unin_map_irq,
pic, s,
&d->pci_mmio, &s->pci_mmio,
address_space_io, &s->pci_io,
PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS); PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
sysbus_mmio_map(s, 0, 0xf0800000); pci_create_simple(h->bus, PCI_DEVFN(11, 0), "u3-agp");
sysbus_mmio_map(s, 1, 0xf0c00000); pci_unin_init_irqs(s);
}
pci_create_simple(h->bus, 11 << 3, "u3-agp"); static void pci_u3_agp_init(Object *obj)
{
UNINHostState *s = U3_AGP_HOST_BRIDGE(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
PCIHostState *h = PCI_HOST_BRIDGE(obj);
return h->bus; /* Uninorth U3 AGP bus */
memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
obj, "unin-pci-conf-idx", 0x1000);
memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, obj,
"unin-pci-conf-data", 0x1000);
memory_region_init(&s->pci_mmio, OBJECT(s), "unin-pci-mmio",
0x100000000ULL);
memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj,
"unin-pci-isa-mmio", 0x00800000);
memory_region_init_alias(&s->pci_hole, OBJECT(s),
"unin-pci-hole", &s->pci_mmio,
0x80000000ULL, 0x70000000ULL);
object_property_add_link(obj, "pic", TYPE_OPENPIC,
(Object **) &s->pic,
qdev_prop_allow_set_link_before_realize,
0, NULL);
sysbus_init_mmio(sbd, &h->conf_mem);
sysbus_init_mmio(sbd, &h->data_mem);
sysbus_init_mmio(sbd, &s->pci_hole);
sysbus_init_mmio(sbd, &s->pci_io);
}
static void pci_unin_agp_realize(DeviceState *dev, Error **errp)
{
UNINHostState *s = UNI_NORTH_AGP_HOST_BRIDGE(dev);
PCIHostState *h = PCI_HOST_BRIDGE(dev);
h->bus = pci_register_root_bus(dev, NULL,
pci_unin_set_irq, pci_unin_map_irq,
s,
&s->pci_mmio,
&s->pci_io,
PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-agp");
pci_unin_init_irqs(s);
}
static void pci_unin_agp_init(Object *obj)
{
UNINHostState *s = UNI_NORTH_AGP_HOST_BRIDGE(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
PCIHostState *h = PCI_HOST_BRIDGE(obj);
/* Uninorth AGP bus */
memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
obj, "unin-agp-conf-idx", 0x1000);
memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops,
obj, "unin-agp-conf-data", 0x1000);
object_property_add_link(obj, "pic", TYPE_OPENPIC,
(Object **) &s->pic,
qdev_prop_allow_set_link_before_realize,
0, NULL);
sysbus_init_mmio(sbd, &h->conf_mem);
sysbus_init_mmio(sbd, &h->data_mem);
}
static void pci_unin_internal_realize(DeviceState *dev, Error **errp)
{
UNINHostState *s = UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(dev);
PCIHostState *h = PCI_HOST_BRIDGE(dev);
h->bus = pci_register_root_bus(dev, NULL,
pci_unin_set_irq, pci_unin_map_irq,
s,
&s->pci_mmio,
&s->pci_io,
PCI_DEVFN(14, 0), 4, TYPE_PCI_BUS);
pci_create_simple(h->bus, PCI_DEVFN(14, 0), "uni-north-internal-pci");
pci_unin_init_irqs(s);
}
static void pci_unin_internal_init(Object *obj)
{
UNINHostState *s = UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
PCIHostState *h = PCI_HOST_BRIDGE(obj);
/* Uninorth internal bus */
memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops,
obj, "unin-pci-conf-idx", 0x1000);
memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops,
obj, "unin-pci-conf-data", 0x1000);
object_property_add_link(obj, "pic", TYPE_OPENPIC,
(Object **) &s->pic,
qdev_prop_allow_set_link_before_realize,
0, NULL);
sysbus_init_mmio(sbd, &h->conf_mem);
sysbus_init_mmio(sbd, &h->data_mem);
} }
static void unin_main_pci_host_realize(PCIDevice *d, Error **errp) static void unin_main_pci_host_realize(PCIDevice *d, Error **errp)
{ {
d->config[0x0C] = 0x08; // cache_line_size /* cache_line_size */
d->config[0x0D] = 0x10; // latency_timer d->config[0x0C] = 0x08;
d->config[0x34] = 0x00; // capabilities_pointer /* latency_timer */
} d->config[0x0D] = 0x10;
/* capabilities_pointer */
d->config[0x34] = 0x00;
static void unin_agp_pci_host_realize(PCIDevice *d, Error **errp)
{
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x10; // latency_timer
// d->config[0x34] = 0x80; // capabilities_pointer
/* /*
* Set kMacRISCPCIAddressSelect (0x48) register to indicate PCI * Set kMacRISCPCIAddressSelect (0x48) register to indicate PCI
* memory space with base 0x80000000, size 0x10000000 for Apple's * memory space with base 0x80000000, size 0x10000000 for Apple's
@ -323,6 +315,16 @@ static void unin_agp_pci_host_realize(PCIDevice *d, Error **errp)
d->config[0x4b] = 0x1; d->config[0x4b] = 0x1;
} }
static void unin_agp_pci_host_realize(PCIDevice *d, Error **errp)
{
/* cache_line_size */
d->config[0x0C] = 0x08;
/* latency_timer */
d->config[0x0D] = 0x10;
/* capabilities_pointer
d->config[0x34] = 0x80; */
}
static void u3_agp_pci_host_realize(PCIDevice *d, Error **errp) static void u3_agp_pci_host_realize(PCIDevice *d, Error **errp)
{ {
/* cache line size */ /* cache line size */
@ -333,9 +335,12 @@ static void u3_agp_pci_host_realize(PCIDevice *d, Error **errp)
static void unin_internal_pci_host_realize(PCIDevice *d, Error **errp) static void unin_internal_pci_host_realize(PCIDevice *d, Error **errp)
{ {
d->config[0x0C] = 0x08; // cache_line_size /* cache_line_size */
d->config[0x0D] = 0x10; // latency_timer d->config[0x0C] = 0x08;
d->config[0x34] = 0x00; // capabilities_pointer /* latency_timer */
d->config[0x0D] = 0x10;
/* capabilities_pointer */
d->config[0x34] = 0x00;
} }
static void unin_main_pci_host_class_init(ObjectClass *klass, void *data) static void unin_main_pci_host_class_init(ObjectClass *klass, void *data)
@ -452,65 +457,65 @@ static const TypeInfo unin_internal_pci_host_info = {
static void pci_unin_main_class_init(ObjectClass *klass, void *data) static void pci_unin_main_class_init(ObjectClass *klass, void *data)
{ {
SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
sbc->init = pci_unin_main_init_device; dc->realize = pci_unin_main_realize;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
} }
static const TypeInfo pci_unin_main_info = { static const TypeInfo pci_unin_main_info = {
.name = TYPE_UNI_NORTH_PCI_HOST_BRIDGE, .name = TYPE_UNI_NORTH_PCI_HOST_BRIDGE,
.parent = TYPE_PCI_HOST_BRIDGE, .parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(UNINState), .instance_size = sizeof(UNINHostState),
.instance_init = pci_unin_main_init,
.class_init = pci_unin_main_class_init, .class_init = pci_unin_main_class_init,
}; };
static void pci_u3_agp_class_init(ObjectClass *klass, void *data) static void pci_u3_agp_class_init(ObjectClass *klass, void *data)
{ {
SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
sbc->init = pci_u3_agp_init_device; dc->realize = pci_u3_agp_realize;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
} }
static const TypeInfo pci_u3_agp_info = { static const TypeInfo pci_u3_agp_info = {
.name = TYPE_U3_AGP_HOST_BRIDGE, .name = TYPE_U3_AGP_HOST_BRIDGE,
.parent = TYPE_PCI_HOST_BRIDGE, .parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(UNINState), .instance_size = sizeof(UNINHostState),
.instance_init = pci_u3_agp_init,
.class_init = pci_u3_agp_class_init, .class_init = pci_u3_agp_class_init,
}; };
static void pci_unin_agp_class_init(ObjectClass *klass, void *data) static void pci_unin_agp_class_init(ObjectClass *klass, void *data)
{ {
SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
sbc->init = pci_unin_agp_init_device; dc->realize = pci_unin_agp_realize;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
} }
static const TypeInfo pci_unin_agp_info = { static const TypeInfo pci_unin_agp_info = {
.name = TYPE_UNI_NORTH_AGP_HOST_BRIDGE, .name = TYPE_UNI_NORTH_AGP_HOST_BRIDGE,
.parent = TYPE_PCI_HOST_BRIDGE, .parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(UNINState), .instance_size = sizeof(UNINHostState),
.instance_init = pci_unin_agp_init,
.class_init = pci_unin_agp_class_init, .class_init = pci_unin_agp_class_init,
}; };
static void pci_unin_internal_class_init(ObjectClass *klass, void *data) static void pci_unin_internal_class_init(ObjectClass *klass, void *data)
{ {
SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
sbc->init = pci_unin_internal_init_device; dc->realize = pci_unin_internal_realize;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
} }
static const TypeInfo pci_unin_internal_info = { static const TypeInfo pci_unin_internal_info = {
.name = TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE, .name = TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE,
.parent = TYPE_PCI_HOST_BRIDGE, .parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(UNINState), .instance_size = sizeof(UNINHostState),
.instance_init = pci_unin_internal_init,
.class_init = pci_unin_internal_class_init, .class_init = pci_unin_internal_class_init,
}; };

View File

@ -221,14 +221,14 @@ static void sysbus_device_create_devtree(SysBusDevice *sbdev, void *opaque)
} }
} }
static void platform_bus_create_devtree(PPCE500Params *params, void *fdt, static void platform_bus_create_devtree(const PPCE500MachineClass *pmc,
const char *mpic) void *fdt, const char *mpic)
{ {
gchar *node = g_strdup_printf("/platform@%"PRIx64, params->platform_bus_base); gchar *node = g_strdup_printf("/platform@%"PRIx64, pmc->platform_bus_base);
const char platcomp[] = "qemu,platform\0simple-bus"; const char platcomp[] = "qemu,platform\0simple-bus";
uint64_t addr = params->platform_bus_base; uint64_t addr = pmc->platform_bus_base;
uint64_t size = params->platform_bus_size; uint64_t size = pmc->platform_bus_size;
int irq_start = params->platform_bus_first_irq; int irq_start = pmc->platform_bus_first_irq;
PlatformBusDevice *pbus; PlatformBusDevice *pbus;
DeviceState *dev; DeviceState *dev;
@ -265,8 +265,7 @@ static void platform_bus_create_devtree(PPCE500Params *params, void *fdt,
g_free(node); g_free(node);
} }
static int ppce500_load_device_tree(MachineState *machine, static int ppce500_load_device_tree(PPCE500MachineState *pms,
PPCE500Params *params,
hwaddr addr, hwaddr addr,
hwaddr initrd_base, hwaddr initrd_base,
hwaddr initrd_size, hwaddr initrd_size,
@ -274,6 +273,8 @@ static int ppce500_load_device_tree(MachineState *machine,
hwaddr kernel_size, hwaddr kernel_size,
bool dry_run) bool dry_run)
{ {
MachineState *machine = MACHINE(pms);
const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
CPUPPCState *env = first_cpu->env_ptr; CPUPPCState *env = first_cpu->env_ptr;
int ret = -1; int ret = -1;
uint64_t mem_reg_property[] = { 0, cpu_to_be64(machine->ram_size) }; uint64_t mem_reg_property[] = { 0, cpu_to_be64(machine->ram_size) };
@ -295,12 +296,12 @@ static int ppce500_load_device_tree(MachineState *machine,
int len; int len;
uint32_t pci_ranges[14] = uint32_t pci_ranges[14] =
{ {
0x2000000, 0x0, params->pci_mmio_bus_base, 0x2000000, 0x0, pmc->pci_mmio_bus_base,
params->pci_mmio_base >> 32, params->pci_mmio_base, pmc->pci_mmio_base >> 32, pmc->pci_mmio_base,
0x0, 0x20000000, 0x0, 0x20000000,
0x1000000, 0x0, 0x0, 0x1000000, 0x0, 0x0,
params->pci_pio_base >> 32, params->pci_pio_base, pmc->pci_pio_base >> 32, pmc->pci_pio_base,
0x0, 0x10000, 0x0, 0x10000,
}; };
QemuOpts *machine_opts = qemu_get_machine_opts(); QemuOpts *machine_opts = qemu_get_machine_opts();
@ -391,7 +392,7 @@ static int ppce500_load_device_tree(MachineState *machine,
for (i = smp_cpus - 1; i >= 0; i--) { for (i = smp_cpus - 1; i >= 0; i--) {
CPUState *cpu; CPUState *cpu;
char cpu_name[128]; char cpu_name[128];
uint64_t cpu_release_addr = params->spin_base + (i * 0x20); uint64_t cpu_release_addr = pmc->spin_base + (i * 0x20);
cpu = qemu_get_cpu(i); cpu = qemu_get_cpu(i);
if (cpu == NULL) { if (cpu == NULL) {
@ -425,7 +426,7 @@ static int ppce500_load_device_tree(MachineState *machine,
qemu_fdt_add_subnode(fdt, "/aliases"); qemu_fdt_add_subnode(fdt, "/aliases");
/* XXX These should go into their respective devices' code */ /* XXX These should go into their respective devices' code */
snprintf(soc, sizeof(soc), "/soc@%"PRIx64, params->ccsrbar_base); snprintf(soc, sizeof(soc), "/soc@%"PRIx64, pmc->ccsrbar_base);
qemu_fdt_add_subnode(fdt, soc); qemu_fdt_add_subnode(fdt, soc);
qemu_fdt_setprop_string(fdt, soc, "device_type", "soc"); qemu_fdt_setprop_string(fdt, soc, "device_type", "soc");
qemu_fdt_setprop(fdt, soc, "compatible", compatible_sb, qemu_fdt_setprop(fdt, soc, "compatible", compatible_sb,
@ -433,7 +434,7 @@ static int ppce500_load_device_tree(MachineState *machine,
qemu_fdt_setprop_cell(fdt, soc, "#address-cells", 1); qemu_fdt_setprop_cell(fdt, soc, "#address-cells", 1);
qemu_fdt_setprop_cell(fdt, soc, "#size-cells", 1); qemu_fdt_setprop_cell(fdt, soc, "#size-cells", 1);
qemu_fdt_setprop_cells(fdt, soc, "ranges", 0x0, qemu_fdt_setprop_cells(fdt, soc, "ranges", 0x0,
params->ccsrbar_base >> 32, params->ccsrbar_base, pmc->ccsrbar_base >> 32, pmc->ccsrbar_base,
MPC8544_CCSRBAR_SIZE); MPC8544_CCSRBAR_SIZE);
/* XXX should contain a reasonable value */ /* XXX should contain a reasonable value */
qemu_fdt_setprop_cell(fdt, soc, "bus-frequency", 0); qemu_fdt_setprop_cell(fdt, soc, "bus-frequency", 0);
@ -493,7 +494,7 @@ static int ppce500_load_device_tree(MachineState *machine,
qemu_fdt_setprop_cell(fdt, msi, "linux,phandle", msi_ph); qemu_fdt_setprop_cell(fdt, msi, "linux,phandle", msi_ph);
snprintf(pci, sizeof(pci), "/pci@%llx", snprintf(pci, sizeof(pci), "/pci@%llx",
params->ccsrbar_base + MPC8544_PCI_REGS_OFFSET); pmc->ccsrbar_base + MPC8544_PCI_REGS_OFFSET);
qemu_fdt_add_subnode(fdt, pci); qemu_fdt_add_subnode(fdt, pci);
qemu_fdt_setprop_cell(fdt, pci, "cell-index", 0); 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, "compatible", "fsl,mpc8540-pci");
@ -501,7 +502,7 @@ static int ppce500_load_device_tree(MachineState *machine,
qemu_fdt_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0, qemu_fdt_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0,
0x0, 0x7); 0x0, 0x7);
pci_map = pci_map_create(fdt, qemu_fdt_get_phandle(fdt, mpic), pci_map = pci_map_create(fdt, qemu_fdt_get_phandle(fdt, mpic),
params->pci_first_slot, params->pci_nr_slots, pmc->pci_first_slot, pmc->pci_nr_slots,
&len); &len);
qemu_fdt_setprop(fdt, pci, "interrupt-map", pci_map, len); qemu_fdt_setprop(fdt, pci, "interrupt-map", pci_map, len);
qemu_fdt_setprop_phandle(fdt, pci, "interrupt-parent", mpic); qemu_fdt_setprop_phandle(fdt, pci, "interrupt-parent", mpic);
@ -513,8 +514,8 @@ static int ppce500_load_device_tree(MachineState *machine,
qemu_fdt_setprop_cell(fdt, pci, "fsl,msi", msi_ph); qemu_fdt_setprop_cell(fdt, pci, "fsl,msi", msi_ph);
qemu_fdt_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges)); qemu_fdt_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));
qemu_fdt_setprop_cells(fdt, pci, "reg", qemu_fdt_setprop_cells(fdt, pci, "reg",
(params->ccsrbar_base + MPC8544_PCI_REGS_OFFSET) >> 32, (pmc->ccsrbar_base + MPC8544_PCI_REGS_OFFSET) >> 32,
(params->ccsrbar_base + MPC8544_PCI_REGS_OFFSET), (pmc->ccsrbar_base + MPC8544_PCI_REGS_OFFSET),
0, 0x1000); 0, 0x1000);
qemu_fdt_setprop_cell(fdt, pci, "clock-frequency", 66666666); qemu_fdt_setprop_cell(fdt, pci, "clock-frequency", 66666666);
qemu_fdt_setprop_cell(fdt, pci, "#interrupt-cells", 1); qemu_fdt_setprop_cell(fdt, pci, "#interrupt-cells", 1);
@ -522,15 +523,15 @@ static int ppce500_load_device_tree(MachineState *machine,
qemu_fdt_setprop_cell(fdt, pci, "#address-cells", 3); qemu_fdt_setprop_cell(fdt, pci, "#address-cells", 3);
qemu_fdt_setprop_string(fdt, "/aliases", "pci0", pci); qemu_fdt_setprop_string(fdt, "/aliases", "pci0", pci);
if (params->has_mpc8xxx_gpio) { if (pmc->has_mpc8xxx_gpio) {
create_dt_mpc8xxx_gpio(fdt, soc, mpic); create_dt_mpc8xxx_gpio(fdt, soc, mpic);
} }
if (params->has_platform_bus) { if (pmc->has_platform_bus) {
platform_bus_create_devtree(params, fdt, mpic); platform_bus_create_devtree(pmc, fdt, mpic);
} }
params->fixup_devtree(params, fdt); pmc->fixup_devtree(fdt);
if (toplevel_compat) { if (toplevel_compat) {
qemu_fdt_setprop(fdt, "/", "compatible", toplevel_compat, qemu_fdt_setprop(fdt, "/", "compatible", toplevel_compat,
@ -551,8 +552,7 @@ out:
} }
typedef struct DeviceTreeParams { typedef struct DeviceTreeParams {
MachineState *machine; PPCE500MachineState *machine;
PPCE500Params params;
hwaddr addr; hwaddr addr;
hwaddr initrd_base; hwaddr initrd_base;
hwaddr initrd_size; hwaddr initrd_size;
@ -564,7 +564,7 @@ typedef struct DeviceTreeParams {
static void ppce500_reset_device_tree(void *opaque) static void ppce500_reset_device_tree(void *opaque)
{ {
DeviceTreeParams *p = opaque; DeviceTreeParams *p = opaque;
ppce500_load_device_tree(p->machine, &p->params, p->addr, p->initrd_base, ppce500_load_device_tree(p->machine, p->addr, p->initrd_base,
p->initrd_size, p->kernel_base, p->kernel_size, p->initrd_size, p->kernel_base, p->kernel_size,
false); false);
} }
@ -575,8 +575,7 @@ static void ppce500_init_notify(Notifier *notifier, void *data)
ppce500_reset_device_tree(p); ppce500_reset_device_tree(p);
} }
static int ppce500_prep_device_tree(MachineState *machine, static int ppce500_prep_device_tree(PPCE500MachineState *machine,
PPCE500Params *params,
hwaddr addr, hwaddr addr,
hwaddr initrd_base, hwaddr initrd_base,
hwaddr initrd_size, hwaddr initrd_size,
@ -585,7 +584,6 @@ static int ppce500_prep_device_tree(MachineState *machine,
{ {
DeviceTreeParams *p = g_new(DeviceTreeParams, 1); DeviceTreeParams *p = g_new(DeviceTreeParams, 1);
p->machine = machine; p->machine = machine;
p->params = *params;
p->addr = addr; p->addr = addr;
p->initrd_base = initrd_base; p->initrd_base = initrd_base;
p->initrd_size = initrd_size; p->initrd_size = initrd_size;
@ -597,9 +595,8 @@ static int ppce500_prep_device_tree(MachineState *machine,
qemu_add_machine_init_done_notifier(&p->notifier); qemu_add_machine_init_done_notifier(&p->notifier);
/* Issue the device tree loader once, so that we get the size of the blob */ /* Issue the device tree loader once, so that we get the size of the blob */
return ppce500_load_device_tree(machine, params, addr, initrd_base, return ppce500_load_device_tree(machine, addr, initrd_base, initrd_size,
initrd_size, kernel_base, kernel_size, kernel_base, kernel_size, true);
true);
} }
/* Create -kernel TLB entries for BookE. */ /* Create -kernel TLB entries for BookE. */
@ -685,17 +682,19 @@ static void ppce500_cpu_reset(void *opaque)
mmubooke_create_initial_mapping(env); mmubooke_create_initial_mapping(env);
} }
static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params, static DeviceState *ppce500_init_mpic_qemu(PPCE500MachineState *pms,
qemu_irq **irqs) qemu_irq **irqs)
{ {
DeviceState *dev; DeviceState *dev;
SysBusDevice *s; SysBusDevice *s;
int i, j, k; int i, j, k;
MachineState *machine = MACHINE(pms);
const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
dev = qdev_create(NULL, TYPE_OPENPIC); dev = qdev_create(NULL, TYPE_OPENPIC);
object_property_add_child(qdev_get_machine(), "pic", OBJECT(dev), object_property_add_child(OBJECT(machine), "pic", OBJECT(dev),
&error_fatal); &error_fatal);
qdev_prop_set_uint32(dev, "model", params->mpic_version); qdev_prop_set_uint32(dev, "model", pmc->mpic_version);
qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus); qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
qdev_init_nofail(dev); qdev_init_nofail(dev);
@ -711,7 +710,7 @@ static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params,
return dev; return dev;
} }
static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params, static DeviceState *ppce500_init_mpic_kvm(const PPCE500MachineClass *pmc,
qemu_irq **irqs, Error **errp) qemu_irq **irqs, Error **errp)
{ {
Error *err = NULL; Error *err = NULL;
@ -719,7 +718,7 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params,
CPUState *cs; CPUState *cs;
dev = qdev_create(NULL, TYPE_KVM_OPENPIC); dev = qdev_create(NULL, TYPE_KVM_OPENPIC);
qdev_prop_set_uint32(dev, "model", params->mpic_version); qdev_prop_set_uint32(dev, "model", pmc->mpic_version);
object_property_set_bool(OBJECT(dev), true, "realized", &err); object_property_set_bool(OBJECT(dev), true, "realized", &err);
if (err) { if (err) {
@ -739,11 +738,12 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params,
return dev; return dev;
} }
static DeviceState *ppce500_init_mpic(MachineState *machine, static DeviceState *ppce500_init_mpic(PPCE500MachineState *pms,
PPCE500Params *params,
MemoryRegion *ccsr, MemoryRegion *ccsr,
qemu_irq **irqs) qemu_irq **irqs)
{ {
MachineState *machine = MACHINE(pms);
const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
DeviceState *dev = NULL; DeviceState *dev = NULL;
SysBusDevice *s; SysBusDevice *s;
@ -751,7 +751,7 @@ static DeviceState *ppce500_init_mpic(MachineState *machine,
Error *err = NULL; Error *err = NULL;
if (machine_kernel_irqchip_allowed(machine)) { if (machine_kernel_irqchip_allowed(machine)) {
dev = ppce500_init_mpic_kvm(params, irqs, &err); dev = ppce500_init_mpic_kvm(pmc, irqs, &err);
} }
if (machine_kernel_irqchip_required(machine) && !dev) { if (machine_kernel_irqchip_required(machine) && !dev) {
error_reportf_err(err, error_reportf_err(err,
@ -761,7 +761,7 @@ static DeviceState *ppce500_init_mpic(MachineState *machine,
} }
if (!dev) { if (!dev) {
dev = ppce500_init_mpic_qemu(params, irqs); dev = ppce500_init_mpic_qemu(pms, irqs);
} }
s = SYS_BUS_DEVICE(dev); s = SYS_BUS_DEVICE(dev);
@ -778,10 +778,12 @@ static void ppce500_power_off(void *opaque, int line, int on)
} }
} }
void ppce500_init(MachineState *machine, PPCE500Params *params) void ppce500_init(MachineState *machine)
{ {
MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *ram = g_new(MemoryRegion, 1);
PPCE500MachineState *pms = PPCE500_MACHINE(machine);
const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(machine);
PCIBus *pci_bus; PCIBus *pci_bus;
CPUPPCState *env = NULL; CPUPPCState *env = NULL;
uint64_t loadaddr; uint64_t loadaddr;
@ -835,8 +837,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT]; irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT]; irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i; env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i;
env->mpic_iack = params->ccsrbar_base + env->mpic_iack = pmc->ccsrbar_base + MPC8544_MPIC_REGS_OFFSET + 0xa0;
MPC8544_MPIC_REGS_OFFSET + 0xa0;
ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500); ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500);
@ -869,10 +870,10 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
qdev_init_nofail(dev); qdev_init_nofail(dev);
ccsr = CCSR(dev); ccsr = CCSR(dev);
ccsr_addr_space = &ccsr->ccsr_space; ccsr_addr_space = &ccsr->ccsr_space;
memory_region_add_subregion(address_space_mem, params->ccsrbar_base, memory_region_add_subregion(address_space_mem, pmc->ccsrbar_base,
ccsr_addr_space); ccsr_addr_space);
mpicdev = ppce500_init_mpic(machine, params, ccsr_addr_space, irqs); mpicdev = ppce500_init_mpic(pms, ccsr_addr_space, irqs);
/* Serial */ /* Serial */
if (serial_hd(0)) { if (serial_hd(0)) {
@ -898,7 +899,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
dev = qdev_create(NULL, "e500-pcihost"); dev = qdev_create(NULL, "e500-pcihost");
object_property_add_child(qdev_get_machine(), "pci-host", OBJECT(dev), object_property_add_child(qdev_get_machine(), "pci-host", OBJECT(dev),
&error_abort); &error_abort);
qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot); qdev_prop_set_uint32(dev, "first_slot", pmc->pci_first_slot);
qdev_prop_set_uint32(dev, "first_pin_irq", pci_irq_nrs[0]); qdev_prop_set_uint32(dev, "first_pin_irq", pci_irq_nrs[0]);
qdev_init_nofail(dev); qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev); s = SYS_BUS_DEVICE(dev);
@ -921,9 +922,9 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
} }
/* Register spinning region */ /* Register spinning region */
sysbus_create_simple("e500-spin", params->spin_base, NULL); sysbus_create_simple("e500-spin", pmc->spin_base, NULL);
if (params->has_mpc8xxx_gpio) { if (pmc->has_mpc8xxx_gpio) {
qemu_irq poweroff_irq; qemu_irq poweroff_irq;
dev = qdev_create(NULL, "mpc8xxx_gpio"); dev = qdev_create(NULL, "mpc8xxx_gpio");
@ -939,21 +940,21 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
} }
/* Platform Bus Device */ /* Platform Bus Device */
if (params->has_platform_bus) { if (pmc->has_platform_bus) {
dev = qdev_create(NULL, TYPE_PLATFORM_BUS_DEVICE); dev = qdev_create(NULL, TYPE_PLATFORM_BUS_DEVICE);
dev->id = TYPE_PLATFORM_BUS_DEVICE; dev->id = TYPE_PLATFORM_BUS_DEVICE;
qdev_prop_set_uint32(dev, "num_irqs", params->platform_bus_num_irqs); qdev_prop_set_uint32(dev, "num_irqs", pmc->platform_bus_num_irqs);
qdev_prop_set_uint32(dev, "mmio_size", params->platform_bus_size); qdev_prop_set_uint32(dev, "mmio_size", pmc->platform_bus_size);
qdev_init_nofail(dev); qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev); s = SYS_BUS_DEVICE(dev);
for (i = 0; i < params->platform_bus_num_irqs; i++) { for (i = 0; i < pmc->platform_bus_num_irqs; i++) {
int irqn = params->platform_bus_first_irq + i; int irqn = pmc->platform_bus_first_irq + i;
sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, irqn)); sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, irqn));
} }
memory_region_add_subregion(address_space_mem, memory_region_add_subregion(address_space_mem,
params->platform_bus_base, pmc->platform_bus_base,
sysbus_mmio_get_region(s, 0)); sysbus_mmio_get_region(s, 0));
} }
@ -1056,7 +1057,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
exit(1); exit(1);
} }
dt_size = ppce500_prep_device_tree(machine, params, dt_base, dt_size = ppce500_prep_device_tree(pms, dt_base,
initrd_base, initrd_size, initrd_base, initrd_size,
kernel_base, kernel_size); kernel_base, kernel_size);
if (dt_size < 0) { if (dt_size < 0) {
@ -1085,9 +1086,17 @@ static const TypeInfo e500_ccsr_info = {
.instance_init = e500_ccsr_initfn, .instance_init = e500_ccsr_initfn,
}; };
static const TypeInfo ppce500_info = {
.name = TYPE_PPCE500_MACHINE,
.parent = TYPE_MACHINE,
.abstract = true,
.class_size = sizeof(PPCE500MachineClass),
};
static void e500_register_types(void) static void e500_register_types(void)
{ {
type_register_static(&e500_ccsr_info); type_register_static(&e500_ccsr_info);
type_register_static(&ppce500_info);
} }
type_init(e500_register_types) type_init(e500_register_types)

View File

@ -3,12 +3,21 @@
#include "hw/boards.h" #include "hw/boards.h"
typedef struct PPCE500Params { typedef struct PPCE500MachineState {
int pci_first_slot; /*< private >*/
int pci_nr_slots; MachineState parent_obj;
} PPCE500MachineState;
typedef struct PPCE500MachineClass {
/*< private >*/
MachineClass parent_class;
/* required -- must at least add toplevel board compatible */ /* required -- must at least add toplevel board compatible */
void (*fixup_devtree)(struct PPCE500Params *params, void *fdt); void (*fixup_devtree)(void *fdt);
int pci_first_slot;
int pci_nr_slots;
int mpic_version; int mpic_version;
bool has_mpc8xxx_gpio; bool has_mpc8xxx_gpio;
@ -22,10 +31,18 @@ typedef struct PPCE500Params {
hwaddr pci_mmio_base; hwaddr pci_mmio_base;
hwaddr pci_mmio_bus_base; hwaddr pci_mmio_bus_base;
hwaddr spin_base; hwaddr spin_base;
} PPCE500Params; } PPCE500MachineClass;
void ppce500_init(MachineState *machine, PPCE500Params *params); void ppce500_init(MachineState *machine);
hwaddr booke206_page_size_to_tlb(uint64_t size); hwaddr booke206_page_size_to_tlb(uint64_t size);
#define TYPE_PPCE500_MACHINE "ppce500-base-machine"
#define PPCE500_MACHINE(obj) \
OBJECT_CHECK(PPCE500MachineState, (obj), TYPE_PPCE500_MACHINE)
#define PPCE500_MACHINE_GET_CLASS(obj) \
OBJECT_GET_CLASS(PPCE500MachineClass, obj, TYPE_PPCE500_MACHINE)
#define PPCE500_MACHINE_CLASS(klass) \
OBJECT_CLASS_CHECK(PPCE500MachineClass, klass, TYPE_PPCE500_MACHINE)
#endif #endif

View File

@ -21,7 +21,7 @@
#include "hw/ppc/openpic.h" #include "hw/ppc/openpic.h"
#include "kvm_ppc.h" #include "kvm_ppc.h"
static void e500plat_fixup_devtree(PPCE500Params *params, void *fdt) static void e500plat_fixup_devtree(void *fdt)
{ {
const char model[] = "QEMU ppce500"; const char model[] = "QEMU ppce500";
const char compatible[] = "fsl,qemu-e500"; const char compatible[] = "fsl,qemu-e500";
@ -33,40 +33,54 @@ static void e500plat_fixup_devtree(PPCE500Params *params, void *fdt)
static void e500plat_init(MachineState *machine) static void e500plat_init(MachineState *machine)
{ {
PPCE500Params params = { PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(machine);
.pci_first_slot = 0x1,
.pci_nr_slots = PCI_SLOT_MAX - 1,
.fixup_devtree = e500plat_fixup_devtree,
.mpic_version = OPENPIC_MODEL_FSL_MPIC_42,
.has_mpc8xxx_gpio = true,
.has_platform_bus = true,
.platform_bus_base = 0xf00000000ULL,
.platform_bus_size = (128ULL * 1024 * 1024),
.platform_bus_first_irq = 5,
.platform_bus_num_irqs = 10,
.ccsrbar_base = 0xFE0000000ULL,
.pci_pio_base = 0xFE1000000ULL,
.pci_mmio_base = 0xC00000000ULL,
.pci_mmio_bus_base = 0xE0000000ULL,
.spin_base = 0xFEF000000ULL,
};
/* Older KVM versions don't support EPR which breaks guests when we announce /* Older KVM versions don't support EPR which breaks guests when we announce
MPIC variants that support EPR. Revert to an older one for those */ MPIC variants that support EPR. Revert to an older one for those */
if (kvm_enabled() && !kvmppc_has_cap_epr()) { if (kvm_enabled() && !kvmppc_has_cap_epr()) {
params.mpic_version = OPENPIC_MODEL_FSL_MPIC_20; pmc->mpic_version = OPENPIC_MODEL_FSL_MPIC_20;
} }
ppce500_init(machine, &params); ppce500_init(machine);
} }
static void e500plat_machine_init(MachineClass *mc) #define TYPE_E500PLAT_MACHINE MACHINE_TYPE_NAME("ppce500")
static void e500plat_machine_class_init(ObjectClass *oc, void *data)
{ {
PPCE500MachineClass *pmc = PPCE500_MACHINE_CLASS(oc);
MachineClass *mc = MACHINE_CLASS(oc);
pmc->pci_first_slot = 0x1;
pmc->pci_nr_slots = PCI_SLOT_MAX - 1;
pmc->fixup_devtree = e500plat_fixup_devtree;
pmc->mpic_version = OPENPIC_MODEL_FSL_MPIC_42;
pmc->has_mpc8xxx_gpio = true;
pmc->has_platform_bus = true;
pmc->platform_bus_base = 0xf00000000ULL;
pmc->platform_bus_size = (128ULL * 1024 * 1024);
pmc->platform_bus_first_irq = 5;
pmc->platform_bus_num_irqs = 10;
pmc->ccsrbar_base = 0xFE0000000ULL;
pmc->pci_pio_base = 0xFE1000000ULL;
pmc->pci_mmio_base = 0xC00000000ULL;
pmc->pci_mmio_bus_base = 0xE0000000ULL;
pmc->spin_base = 0xFEF000000ULL;
mc->desc = "generic paravirt e500 platform"; mc->desc = "generic paravirt e500 platform";
mc->init = e500plat_init; mc->init = e500plat_init;
mc->max_cpus = 32; mc->max_cpus = 32;
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ETSEC_COMMON);
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("e500v2_v30"); mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("e500v2_v30");
} machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ETSEC_COMMON);
}
DEFINE_MACHINE("ppce500", e500plat_machine_init) static const TypeInfo e500plat_info = {
.name = TYPE_E500PLAT_MACHINE,
.parent = TYPE_PPCE500_MACHINE,
.class_init = e500plat_machine_class_init,
};
static void e500plat_register_types(void)
{
type_register_static(&e500plat_info);
}
type_init(e500plat_register_types)

View File

@ -9,19 +9,20 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "target/ppc/cpu.h" #include "target/ppc/cpu.h"
#include "target/ppc/mmu-hash64.h"
#include "hw/ppc/fdt.h" #include "hw/ppc/fdt.h"
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
size_t ppc_create_page_sizes_prop(CPUPPCState *env, uint32_t *prop, size_t ppc_create_page_sizes_prop(PowerPCCPU *cpu, uint32_t *prop,
size_t maxsize) size_t maxsize)
{ {
size_t maxcells = maxsize / sizeof(uint32_t); size_t maxcells = maxsize / sizeof(uint32_t);
int i, j, count; int i, j, count;
uint32_t *p = prop; uint32_t *p = prop;
for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
struct ppc_one_seg_page_size *sps = &env->sps.sps[i]; PPCHash64SegmentPageSizes *sps = &cpu->hash64_opts->sps[i];
if (!sps->page_shift) { if (!sps->page_shift) {
break; break;

View File

@ -31,6 +31,8 @@
#include "hw/ide/internal.h" #include "hw/ide/internal.h"
#include "hw/input/adb.h" #include "hw/input/adb.h"
#include "hw/misc/mos6522.h" #include "hw/misc/mos6522.h"
#include "hw/pci/pci_host.h"
#include "hw/pci-host/uninorth.h"
/* SMP is not enabled, for now */ /* SMP is not enabled, for now */
#define MAX_CPUS 1 #define MAX_CPUS 1
@ -45,6 +47,14 @@
#define ESCC_CLOCK 3686400 #define ESCC_CLOCK 3686400
/* Old World IRQs */
#define OLDWORLD_CUDA_IRQ 0x12
#define OLDWORLD_ESCCB_IRQ 0x10
#define OLDWORLD_ESCCA_IRQ 0xf
#define OLDWORLD_IDE0_IRQ 0xd
#define OLDWORLD_IDE0_DMA_IRQ 0x2
#define OLDWORLD_IDE1_IRQ 0xe
#define OLDWORLD_IDE1_DMA_IRQ 0x3
/* MacIO */ /* MacIO */
#define TYPE_MACIO_IDE "macio-ide" #define TYPE_MACIO_IDE "macio-ide"
@ -75,23 +85,14 @@ void macio_ide_register_dma(MACIOIDEState *ide);
void macio_init(PCIDevice *dev, void macio_init(PCIDevice *dev,
MemoryRegion *pic_mem); MemoryRegion *pic_mem);
/* Heathrow PIC */
DeviceState *heathrow_pic_init(int nb_cpus, qemu_irq **irqs,
qemu_irq **pic_irqs);
/* Grackle PCI */ /* Grackle PCI */
#define TYPE_GRACKLE_PCI_HOST_BRIDGE "grackle-pcihost" #define TYPE_GRACKLE_PCI_HOST_BRIDGE "grackle-pcihost"
PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io);
/* UniNorth PCI */ /* UniNorth PCI */
PCIBus *pci_pmac_init(qemu_irq *pic, UNINHostState *pci_pmac_init(qemu_irq *pic,
MemoryRegion *address_space_mem, MemoryRegion *address_space_mem);
MemoryRegion *address_space_io); UNINHostState *pci_pmac_u3_init(qemu_irq *pic,
PCIBus *pci_pmac_u3_init(qemu_irq *pic, MemoryRegion *address_space_mem);
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io);
/* Mac NVRAM */ /* Mac NVRAM */
#define TYPE_MACIO_NVRAM "macio-nvram" #define TYPE_MACIO_NVRAM "macio-nvram"

View File

@ -145,13 +145,12 @@ static void ppc_core99_init(MachineState *machine)
CPUPPCState *env = NULL; CPUPPCState *env = NULL;
char *filename; char *filename;
qemu_irq *pic, **openpic_irqs; qemu_irq *pic, **openpic_irqs;
MemoryRegion *isa = g_new(MemoryRegion, 1);
MemoryRegion *unin_memory = g_new(MemoryRegion, 1); MemoryRegion *unin_memory = g_new(MemoryRegion, 1);
MemoryRegion *unin2_memory = g_new(MemoryRegion, 1);
int linux_boot, i, j, k; int linux_boot, i, j, k;
MemoryRegion *ram = g_new(MemoryRegion, 1), *bios = g_new(MemoryRegion, 1); MemoryRegion *ram = g_new(MemoryRegion, 1), *bios = g_new(MemoryRegion, 1);
hwaddr kernel_base, initrd_base, cmdline_base = 0; hwaddr kernel_base, initrd_base, cmdline_base = 0;
long kernel_size, initrd_size; long kernel_size, initrd_size;
UNINHostState *uninorth_pci;
PCIBus *pci_bus; PCIBus *pci_bus;
NewWorldMacIOState *macio; NewWorldMacIOState *macio;
MACIOIDEState *macio_ide; MACIOIDEState *macio_ide;
@ -273,18 +272,10 @@ static void ppc_core99_init(MachineState *machine)
} }
} }
/* Register 8 MB of ISA IO space */
memory_region_init_alias(isa, NULL, "isa_mmio",
get_system_io(), 0, 0x00800000);
memory_region_add_subregion(get_system_memory(), 0xf2000000, isa);
/* UniN init: XXX should be a real device */ /* UniN init: XXX should be a real device */
memory_region_init_io(unin_memory, NULL, &unin_ops, token, "unin", 0x1000); memory_region_init_io(unin_memory, NULL, &unin_ops, token, "unin", 0x1000);
memory_region_add_subregion(get_system_memory(), 0xf8000000, unin_memory); memory_region_add_subregion(get_system_memory(), 0xf8000000, unin_memory);
memory_region_init_io(unin2_memory, NULL, &unin_ops, token, "unin", 0x1000);
memory_region_add_subregion(get_system_memory(), 0xf3000000, unin2_memory);
openpic_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); openpic_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
openpic_irqs[0] = openpic_irqs[0] =
g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB); g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
@ -348,13 +339,61 @@ static void ppc_core99_init(MachineState *machine)
if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) { if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {
/* 970 gets a U3 bus */ /* 970 gets a U3 bus */
pci_bus = pci_pmac_u3_init(pic, get_system_memory(), get_system_io()); /* Uninorth AGP bus */
dev = qdev_create(NULL, TYPE_U3_AGP_HOST_BRIDGE);
object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic",
&error_abort);
qdev_init_nofail(dev);
uninorth_pci = U3_AGP_HOST_BRIDGE(dev);
s = SYS_BUS_DEVICE(dev);
/* PCI hole */
memory_region_add_subregion(get_system_memory(), 0x80000000ULL,
sysbus_mmio_get_region(s, 2));
/* Register 8 MB of ISA IO space */
memory_region_add_subregion(get_system_memory(), 0xf2000000,
sysbus_mmio_get_region(s, 3));
sysbus_mmio_map(s, 0, 0xf0800000);
sysbus_mmio_map(s, 1, 0xf0c00000);
machine_arch = ARCH_MAC99_U3; machine_arch = ARCH_MAC99_U3;
} else { } else {
pci_bus = pci_pmac_init(pic, get_system_memory(), get_system_io()); /* Use values found on a real PowerMac */
/* Uninorth AGP bus */
dev = qdev_create(NULL, TYPE_UNI_NORTH_AGP_HOST_BRIDGE);
object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic",
&error_abort);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(s, 0, 0xf0800000);
sysbus_mmio_map(s, 1, 0xf0c00000);
/* Uninorth internal bus */
dev = qdev_create(NULL, TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE);
object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic",
&error_abort);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(s, 0, 0xf4800000);
sysbus_mmio_map(s, 1, 0xf4c00000);
/* Uninorth main bus */
dev = qdev_create(NULL, TYPE_UNI_NORTH_PCI_HOST_BRIDGE);
object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic",
&error_abort);
qdev_init_nofail(dev);
uninorth_pci = UNI_NORTH_PCI_HOST_BRIDGE(dev);
s = SYS_BUS_DEVICE(dev);
/* PCI hole */
memory_region_add_subregion(get_system_memory(), 0x80000000ULL,
sysbus_mmio_get_region(s, 2));
/* Register 8 MB of ISA IO space */
memory_region_add_subregion(get_system_memory(), 0xf2000000,
sysbus_mmio_get_region(s, 3));
sysbus_mmio_map(s, 0, 0xf2800000);
sysbus_mmio_map(s, 1, 0xf2c00000);
machine_arch = ARCH_MAC99; machine_arch = ARCH_MAC99;
} }
object_property_set_bool(OBJECT(pci_bus), true, "realized", &error_abort);
machine->usb |= defaults_enabled() && !machine->usb_disabled; machine->usb |= defaults_enabled() && !machine->usb_disabled;
@ -365,6 +404,9 @@ static void ppc_core99_init(MachineState *machine)
tbfreq = TBFREQ; tbfreq = TBFREQ;
} }
/* init basic PC hardware */
pci_bus = PCI_HOST_BRIDGE(uninorth_pci)->bus;
/* MacIO */ /* MacIO */
macio = NEWWORLD_MACIO(pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO)); macio = NEWWORLD_MACIO(pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO));
dev = DEVICE(macio); dev = DEVICE(macio);

View File

@ -34,6 +34,7 @@
#include "net/net.h" #include "net/net.h"
#include "hw/isa/isa.h" #include "hw/isa/isa.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "hw/pci/pci_host.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/nvram/fw_cfg.h" #include "hw/nvram/fw_cfg.h"
#include "hw/char/escc.h" #include "hw/char/escc.h"
@ -55,6 +56,8 @@
#define NDRV_VGA_FILENAME "qemu_vga.ndrv" #define NDRV_VGA_FILENAME "qemu_vga.ndrv"
#define GRACKLE_BASE 0xfec00000
static void fw_cfg_boot_set(void *opaque, const char *boot_device, static void fw_cfg_boot_set(void *opaque, const char *boot_device,
Error **errp) Error **errp)
{ {
@ -84,16 +87,15 @@ static void ppc_heathrow_init(MachineState *machine)
PowerPCCPU *cpu = NULL; PowerPCCPU *cpu = NULL;
CPUPPCState *env = NULL; CPUPPCState *env = NULL;
char *filename; char *filename;
qemu_irq *pic, **heathrow_irqs;
int linux_boot, i; int linux_boot, i;
MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *bios = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1);
MemoryRegion *isa = g_new(MemoryRegion, 1);
uint32_t kernel_base, initrd_base, cmdline_base = 0; uint32_t kernel_base, initrd_base, cmdline_base = 0;
int32_t kernel_size, initrd_size; int32_t kernel_size, initrd_size;
PCIBus *pci_bus; PCIBus *pci_bus;
OldWorldMacIOState *macio; OldWorldMacIOState *macio;
MACIOIDEState *macio_ide; MACIOIDEState *macio_ide;
SysBusDevice *s;
DeviceState *dev, *pic_dev; DeviceState *dev, *pic_dev;
BusState *adb_bus; BusState *adb_bus;
int bios_size, ndrv_size; int bios_size, ndrv_size;
@ -221,22 +223,16 @@ static void ppc_heathrow_init(MachineState *machine)
} }
} }
/* Register 2 MB of ISA IO space */
memory_region_init_alias(isa, NULL, "isa_mmio",
get_system_io(), 0, 0x00200000);
memory_region_add_subregion(sysmem, 0xfe000000, isa);
/* XXX: we register only 1 output pin for heathrow PIC */ /* XXX: we register only 1 output pin for heathrow PIC */
heathrow_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); pic_dev = qdev_create(NULL, TYPE_HEATHROW);
heathrow_irqs[0] = qdev_init_nofail(pic_dev);
g_malloc0(smp_cpus * sizeof(qemu_irq) * 1);
/* Connect the heathrow PIC outputs to the 6xx bus */ /* Connect the heathrow PIC outputs to the 6xx bus */
for (i = 0; i < smp_cpus; i++) { for (i = 0; i < smp_cpus; i++) {
switch (PPC_INPUT(env)) { switch (PPC_INPUT(env)) {
case PPC_FLAGS_INPUT_6xx: case PPC_FLAGS_INPUT_6xx:
heathrow_irqs[i] = heathrow_irqs[0] + (i * 1); qdev_connect_gpio_out(pic_dev, 0,
heathrow_irqs[i][0] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]);
((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
break; break;
default: default:
error_report("Bus model not supported on OldWorld Mac machine"); error_report("Bus model not supported on OldWorld Mac machine");
@ -256,10 +252,24 @@ static void ppc_heathrow_init(MachineState *machine)
error_report("Only 6xx bus is supported on heathrow machine"); error_report("Only 6xx bus is supported on heathrow machine");
exit(1); exit(1);
} }
pic_dev = heathrow_pic_init(1, heathrow_irqs, &pic);
pci_bus = pci_grackle_init(0xfec00000, pic, /* Grackle PCI host bridge */
get_system_memory(), dev = qdev_create(NULL, TYPE_GRACKLE_PCI_HOST_BRIDGE);
get_system_io()); object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic",
&error_abort);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(s, 0, GRACKLE_BASE);
sysbus_mmio_map(s, 1, GRACKLE_BASE + 0x200000);
/* PCI hole */
memory_region_add_subregion(get_system_memory(), 0x80000000ULL,
sysbus_mmio_get_region(s, 2));
/* Register 2 MB of ISA IO space */
memory_region_add_subregion(get_system_memory(), 0xfe000000,
sysbus_mmio_get_region(s, 3));
pci_bus = PCI_HOST_BRIDGE(dev)->bus;
pci_vga_init(pci_bus); pci_vga_init(pci_bus);
for (i = 0; i < nb_nics; i++) { for (i = 0; i < nb_nics; i++) {
@ -271,13 +281,6 @@ static void ppc_heathrow_init(MachineState *machine)
/* MacIO */ /* MacIO */
macio = OLDWORLD_MACIO(pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO)); macio = OLDWORLD_MACIO(pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO));
dev = DEVICE(macio); dev = DEVICE(macio);
qdev_connect_gpio_out(dev, 0, pic[0x12]); /* CUDA */
qdev_connect_gpio_out(dev, 1, pic[0x10]); /* ESCC-B */
qdev_connect_gpio_out(dev, 2, pic[0x0F]); /* ESCC-A */
qdev_connect_gpio_out(dev, 3, pic[0x0D]); /* IDE-0 */
qdev_connect_gpio_out(dev, 4, pic[0x02]); /* IDE-0 DMA */
qdev_connect_gpio_out(dev, 5, pic[0x0E]); /* IDE-1 */
qdev_connect_gpio_out(dev, 6, pic[0x03]); /* IDE-1 DMA */
qdev_prop_set_uint64(dev, "frequency", tbfreq); qdev_prop_set_uint64(dev, "frequency", tbfreq);
object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic", object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic",
&error_abort); &error_abort);

View File

@ -18,7 +18,7 @@
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "cpu.h" #include "cpu.h"
static void mpc8544ds_fixup_devtree(PPCE500Params *params, void *fdt) static void mpc8544ds_fixup_devtree(void *fdt)
{ {
const char model[] = "MPC8544DS"; const char model[] = "MPC8544DS";
const char compatible[] = "MPC8544DS\0MPC85xxDS"; const char compatible[] = "MPC8544DS\0MPC85xxDS";
@ -30,33 +30,46 @@ static void mpc8544ds_fixup_devtree(PPCE500Params *params, void *fdt)
static void mpc8544ds_init(MachineState *machine) static void mpc8544ds_init(MachineState *machine)
{ {
PPCE500Params params = {
.pci_first_slot = 0x11,
.pci_nr_slots = 2,
.fixup_devtree = mpc8544ds_fixup_devtree,
.mpic_version = OPENPIC_MODEL_FSL_MPIC_20,
.ccsrbar_base = 0xE0000000ULL,
.pci_mmio_base = 0xC0000000ULL,
.pci_mmio_bus_base = 0xC0000000ULL,
.pci_pio_base = 0xE1000000ULL,
.spin_base = 0xEF000000ULL,
};
if (machine->ram_size > 0xc0000000) { if (machine->ram_size > 0xc0000000) {
error_report("The MPC8544DS board only supports up to 3GB of RAM"); error_report("The MPC8544DS board only supports up to 3GB of RAM");
exit(1); exit(1);
} }
ppce500_init(machine, &params); ppce500_init(machine);
} }
static void e500plat_machine_class_init(ObjectClass *oc, void *data)
static void ppce500_machine_init(MachineClass *mc)
{ {
MachineClass *mc = MACHINE_CLASS(oc);
PPCE500MachineClass *pmc = PPCE500_MACHINE_CLASS(oc);
pmc->pci_first_slot = 0x11;
pmc->pci_nr_slots = 2;
pmc->fixup_devtree = mpc8544ds_fixup_devtree;
pmc->mpic_version = OPENPIC_MODEL_FSL_MPIC_20;
pmc->ccsrbar_base = 0xE0000000ULL;
pmc->pci_mmio_base = 0xC0000000ULL;
pmc->pci_mmio_bus_base = 0xC0000000ULL;
pmc->pci_pio_base = 0xE1000000ULL;
pmc->spin_base = 0xEF000000ULL;
mc->desc = "mpc8544ds"; mc->desc = "mpc8544ds";
mc->init = mpc8544ds_init; mc->init = mpc8544ds_init;
mc->max_cpus = 15; mc->max_cpus = 15;
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("e500v2_v30"); mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("e500v2_v30");
} }
DEFINE_MACHINE("mpc8544ds", ppce500_machine_init) #define TYPE_MPC8544DS_MACHINE MACHINE_TYPE_NAME("mpc8544ds")
static const TypeInfo mpc8544ds_info = {
.name = TYPE_MPC8544DS_MACHINE,
.parent = TYPE_PPCE500_MACHINE,
.class_init = e500plat_machine_class_init,
};
static void mpc8544ds_register_types(void)
{
type_register_static(&mpc8544ds_info);
}
type_init(mpc8544ds_register_types)

View File

@ -36,6 +36,7 @@
#include "monitor/monitor.h" #include "monitor/monitor.h"
#include "hw/intc/intc.h" #include "hw/intc/intc.h"
#include "hw/ipmi/ipmi.h" #include "hw/ipmi/ipmi.h"
#include "target/ppc/mmu-hash64.h"
#include "hw/ppc/xics.h" #include "hw/ppc/xics.h"
#include "hw/ppc/pnv_xscom.h" #include "hw/ppc/pnv_xscom.h"
@ -179,7 +180,7 @@ static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
_FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
_FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
_FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr))); _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size)));
_FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
_FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
@ -187,7 +188,7 @@ static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
_FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
} }
if (env->mmu_model & POWERPC_MMU_1TSEG) { if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
_FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
segs, sizeof(segs)))); segs, sizeof(segs))));
} }
@ -209,8 +210,8 @@ static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
_FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
} }
page_sizes_prop_size = ppc_create_page_sizes_prop(env, page_sizes_prop, page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
sizeof(page_sizes_prop)); sizeof(page_sizes_prop));
if (page_sizes_prop_size) { if (page_sizes_prop_size) {
_FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
page_sizes_prop, page_sizes_prop_size))); page_sizes_prop, page_sizes_prop_size)));

View File

@ -263,7 +263,6 @@ static void spapr_populate_pa_features(sPAPRMachineState *spapr,
void *fdt, int offset, void *fdt, int offset,
bool legacy_guest) bool legacy_guest)
{ {
CPUPPCState *env = &cpu->env;
uint8_t pa_features_206[] = { 6, 0, uint8_t pa_features_206[] = { 6, 0,
0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 };
uint8_t pa_features_207[] = { 24, 0, uint8_t pa_features_207[] = { 24, 0,
@ -315,7 +314,7 @@ static void spapr_populate_pa_features(sPAPRMachineState *spapr,
return; return;
} }
if (env->ci_large_pages) { if (ppc_hash64_has(cpu, PPC_HASH64_CI_LARGEPAGE)) {
/* /*
* Note: we keep CI large pages off by default because a 64K capable * Note: we keep CI large pages off by default because a 64K capable
* guest provisioned with large pages might otherwise try to map a qemu * guest provisioned with large pages might otherwise try to map a qemu
@ -548,8 +547,8 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
_FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
_FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
_FDT((fdt_setprop_cell(fdt, offset, "slb-size", env->slb_nr))); _FDT((fdt_setprop_cell(fdt, offset, "slb-size", cpu->hash64_opts->slb_size)));
_FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr))); _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size)));
_FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
_FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
@ -557,7 +556,7 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
_FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
} }
if (env->mmu_model & POWERPC_MMU_1TSEG) { if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
_FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
segs, sizeof(segs)))); segs, sizeof(segs))));
} }
@ -581,8 +580,8 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
_FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
} }
page_sizes_prop_size = ppc_create_page_sizes_prop(env, page_sizes_prop, page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
sizeof(page_sizes_prop)); sizeof(page_sizes_prop));
if (page_sizes_prop_size) { if (page_sizes_prop_size) {
_FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
page_sizes_prop, page_sizes_prop_size))); page_sizes_prop, page_sizes_prop_size)));
@ -669,63 +668,137 @@ static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t addr)
return -1; return -1;
} }
/* struct sPAPRDrconfCellV2 {
* Adds ibm,dynamic-reconfiguration-memory node. uint32_t seq_lmbs;
* Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation uint64_t base_addr;
* of this device tree node. uint32_t drc_index;
*/ uint32_t aa_index;
static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) uint32_t flags;
} QEMU_PACKED;
typedef struct DrconfCellQueue {
struct sPAPRDrconfCellV2 cell;
QSIMPLEQ_ENTRY(DrconfCellQueue) entry;
} DrconfCellQueue;
static DrconfCellQueue *
spapr_get_drconf_cell(uint32_t seq_lmbs, uint64_t base_addr,
uint32_t drc_index, uint32_t aa_index,
uint32_t flags)
{ {
MachineState *machine = MACHINE(spapr); DrconfCellQueue *elem;
int ret, i, offset;
elem = g_malloc0(sizeof(*elem));
elem->cell.seq_lmbs = cpu_to_be32(seq_lmbs);
elem->cell.base_addr = cpu_to_be64(base_addr);
elem->cell.drc_index = cpu_to_be32(drc_index);
elem->cell.aa_index = cpu_to_be32(aa_index);
elem->cell.flags = cpu_to_be32(flags);
return elem;
}
/* ibm,dynamic-memory-v2 */
static int spapr_populate_drmem_v2(sPAPRMachineState *spapr, void *fdt,
int offset, MemoryDeviceInfoList *dimms)
{
uint8_t *int_buf, *cur_index, buf_len;
int ret;
uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
uint64_t addr, cur_addr, size;
uint32_t nr_boot_lmbs = (spapr->hotplug_memory.base / lmb_size);
uint64_t mem_end = spapr->hotplug_memory.base +
memory_region_size(&spapr->hotplug_memory.mr);
uint32_t node, nr_entries = 0;
sPAPRDRConnector *drc;
DrconfCellQueue *elem, *next;
MemoryDeviceInfoList *info;
QSIMPLEQ_HEAD(, DrconfCellQueue) drconf_queue
= QSIMPLEQ_HEAD_INITIALIZER(drconf_queue);
/* Entry to cover RAM and the gap area */
elem = spapr_get_drconf_cell(nr_boot_lmbs, 0, 0, -1,
SPAPR_LMB_FLAGS_RESERVED |
SPAPR_LMB_FLAGS_DRC_INVALID);
QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
nr_entries++;
cur_addr = spapr->hotplug_memory.base;
for (info = dimms; info; info = info->next) {
PCDIMMDeviceInfo *di = info->value->u.dimm.data;
addr = di->addr;
size = di->size;
node = di->node;
/* Entry for hot-pluggable area */
if (cur_addr < addr) {
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size);
g_assert(drc);
elem = spapr_get_drconf_cell((addr - cur_addr) / lmb_size,
cur_addr, spapr_drc_index(drc), -1, 0);
QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
nr_entries++;
}
/* Entry for DIMM */
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr / lmb_size);
g_assert(drc);
elem = spapr_get_drconf_cell(size / lmb_size, addr,
spapr_drc_index(drc), node,
SPAPR_LMB_FLAGS_ASSIGNED);
QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
nr_entries++;
cur_addr = addr + size;
}
/* Entry for remaining hotpluggable area */
if (cur_addr < mem_end) {
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, cur_addr / lmb_size);
g_assert(drc);
elem = spapr_get_drconf_cell((mem_end - cur_addr) / lmb_size,
cur_addr, spapr_drc_index(drc), -1, 0);
QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
nr_entries++;
}
buf_len = nr_entries * sizeof(struct sPAPRDrconfCellV2) + sizeof(uint32_t);
int_buf = cur_index = g_malloc0(buf_len);
*(uint32_t *)int_buf = cpu_to_be32(nr_entries);
cur_index += sizeof(nr_entries);
QSIMPLEQ_FOREACH_SAFE(elem, &drconf_queue, entry, next) {
memcpy(cur_index, &elem->cell, sizeof(elem->cell));
cur_index += sizeof(elem->cell);
QSIMPLEQ_REMOVE(&drconf_queue, elem, DrconfCellQueue, entry);
g_free(elem);
}
ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory-v2", int_buf, buf_len);
g_free(int_buf);
if (ret < 0) {
return -1;
}
return 0;
}
/* ibm,dynamic-memory */
static int spapr_populate_drmem_v1(sPAPRMachineState *spapr, void *fdt,
int offset, MemoryDeviceInfoList *dimms)
{
int i, ret;
uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)};
uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size; uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size;
uint32_t nr_lmbs = (spapr->hotplug_memory.base + uint32_t nr_lmbs = (spapr->hotplug_memory.base +
memory_region_size(&spapr->hotplug_memory.mr)) / memory_region_size(&spapr->hotplug_memory.mr)) /
lmb_size; lmb_size;
uint32_t *int_buf, *cur_index, buf_len; uint32_t *int_buf, *cur_index, buf_len;
int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1;
MemoryDeviceInfoList *dimms = NULL;
/*
* Don't create the node if there is no hotpluggable memory
*/
if (machine->ram_size == machine->maxram_size) {
return 0;
}
/* /*
* Allocate enough buffer size to fit in ibm,dynamic-memory * Allocate enough buffer size to fit in ibm,dynamic-memory
* or ibm,associativity-lookup-arrays
*/ */
buf_len = MAX(nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1, nr_nodes * 4 + 2) buf_len = (nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1) * sizeof(uint32_t);
* sizeof(uint32_t);
cur_index = int_buf = g_malloc0(buf_len); cur_index = int_buf = g_malloc0(buf_len);
offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory");
ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size,
sizeof(prop_lmb_size));
if (ret < 0) {
goto out;
}
ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff);
if (ret < 0) {
goto out;
}
ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0);
if (ret < 0) {
goto out;
}
if (hotplug_lmb_start) {
dimms = qmp_pc_dimm_device_list();
}
/* ibm,dynamic-memory */
int_buf[0] = cpu_to_be32(nr_lmbs); int_buf[0] = cpu_to_be32(nr_lmbs);
cur_index++; cur_index++;
for (i = 0; i < nr_lmbs; i++) { for (i = 0; i < nr_lmbs; i++) {
@ -765,13 +838,71 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE;
} }
qapi_free_MemoryDeviceInfoList(dimms);
ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len);
g_free(int_buf);
if (ret < 0) { if (ret < 0) {
goto out; return -1;
}
return 0;
}
/*
* Adds ibm,dynamic-reconfiguration-memory node.
* Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation
* of this device tree node.
*/
static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
{
MachineState *machine = MACHINE(spapr);
int ret, i, offset;
uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)};
uint32_t *int_buf, *cur_index, buf_len;
int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1;
MemoryDeviceInfoList *dimms = NULL;
/*
* Don't create the node if there is no hotpluggable memory
*/
if (machine->ram_size == machine->maxram_size) {
return 0;
}
offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory");
ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size,
sizeof(prop_lmb_size));
if (ret < 0) {
return ret;
}
ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff);
if (ret < 0) {
return ret;
}
ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0);
if (ret < 0) {
return ret;
}
/* ibm,dynamic-memory or ibm,dynamic-memory-v2 */
dimms = qmp_pc_dimm_device_list();
if (spapr_ovec_test(spapr->ov5_cas, OV5_DRMEM_V2)) {
ret = spapr_populate_drmem_v2(spapr, fdt, offset, dimms);
} else {
ret = spapr_populate_drmem_v1(spapr, fdt, offset, dimms);
}
qapi_free_MemoryDeviceInfoList(dimms);
if (ret < 0) {
return ret;
} }
/* ibm,associativity-lookup-arrays */ /* ibm,associativity-lookup-arrays */
buf_len = (nr_nodes * 4 + 2) * sizeof(uint32_t);
cur_index = int_buf = g_malloc0(buf_len);
cur_index = int_buf; cur_index = int_buf;
int_buf[0] = cpu_to_be32(nr_nodes); int_buf[0] = cpu_to_be32(nr_nodes);
int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */
@ -788,8 +919,8 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
} }
ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf,
(cur_index - int_buf) * sizeof(uint32_t)); (cur_index - int_buf) * sizeof(uint32_t));
out:
g_free(int_buf); g_free(int_buf);
return ret; return ret;
} }
@ -910,6 +1041,13 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE), 0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE),
cpu_to_be32(max_cpus / smp_threads), cpu_to_be32(max_cpus / smp_threads),
}; };
uint32_t maxdomains[] = {
cpu_to_be32(4),
cpu_to_be32(0),
cpu_to_be32(0),
cpu_to_be32(0),
cpu_to_be32(nb_numa_nodes ? nb_numa_nodes - 1 : 0),
};
_FDT(rtas = fdt_add_subnode(fdt, 0, "rtas")); _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas"));
@ -946,6 +1084,9 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
_FDT(fdt_setprop(fdt, rtas, "ibm,associativity-reference-points", _FDT(fdt_setprop(fdt, rtas, "ibm,associativity-reference-points",
refpoints, sizeof(refpoints))); refpoints, sizeof(refpoints)));
_FDT(fdt_setprop(fdt, rtas, "ibm,max-associativity-domains",
maxdomains, sizeof(maxdomains)));
_FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max", _FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max",
RTAS_ERROR_LOG_MAX)); RTAS_ERROR_LOG_MAX));
_FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate", _FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate",
@ -1440,21 +1581,6 @@ void spapr_setup_hpt_and_vrma(sPAPRMachineState *spapr)
} }
} }
static void find_unknown_sysbus_device(SysBusDevice *sbdev, void *opaque)
{
bool matched = false;
if (object_dynamic_cast(OBJECT(sbdev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
matched = true;
}
if (!matched) {
error_report("Device %s is not supported by this machine yet.",
qdev_fw_name(DEVICE(sbdev)));
exit(1);
}
}
static int spapr_reset_drcs(Object *child, void *opaque) static int spapr_reset_drcs(Object *child, void *opaque)
{ {
sPAPRDRConnector *drc = sPAPRDRConnector *drc =
@ -1478,9 +1604,6 @@ static void spapr_machine_reset(void)
void *fdt; void *fdt;
int rc; int rc;
/* Check for unknown sysbus devices */
foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL);
spapr_caps_reset(spapr); spapr_caps_reset(spapr);
first_ppc_cpu = POWERPC_CPU(first_cpu); first_ppc_cpu = POWERPC_CPU(first_cpu);
@ -2500,6 +2623,9 @@ static void spapr_machine_init(MachineState *machine)
spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE); spapr_ovec_set(spapr->ov5, OV5_HPT_RESIZE);
} }
/* advertise support for ibm,dyamic-memory-v2 */
spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2);
/* init CPUs */ /* init CPUs */
spapr_init_cpus(spapr); spapr_init_cpus(spapr);
@ -2927,7 +3053,6 @@ static void spapr_instance_init(Object *obj)
" place of standard EPOW events when possible" " place of standard EPOW events when possible"
" (required for memory hot-unplug support)", " (required for memory hot-unplug support)",
NULL); NULL);
ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr, ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr,
"Maximum permitted CPU compatibility mode", "Maximum permitted CPU compatibility mode",
&error_fatal); &error_fatal);
@ -3478,28 +3603,6 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
return; return;
} }
/*
* Currently PowerPC kernel doesn't allow hot-adding memory to
* memory-less node, but instead will silently add the memory
* to the first node that has some memory. This causes two
* unexpected behaviours for the user.
*
* - Memory gets hotplugged to a different node than what the user
* specified.
* - Since pc-dimm subsystem in QEMU still thinks that memory belongs
* to memory-less node, a reboot will set things accordingly
* and the previously hotplugged memory now ends in the right node.
* This appears as if some memory moved from one node to another.
*
* So until kernel starts supporting memory hotplug to memory-less
* nodes, just prevent such attempts upfront in QEMU.
*/
if (nb_numa_nodes && !numa_info[node].node_mem) {
error_setg(errp, "Can't hotplug memory to memory-less node %d",
node);
return;
}
spapr_memory_plug(hotplug_dev, dev, node, errp); spapr_memory_plug(hotplug_dev, dev, node, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
spapr_core_plug(hotplug_dev, dev, errp); spapr_core_plug(hotplug_dev, dev, errp);
@ -3719,9 +3822,8 @@ int spapr_irq_alloc(sPAPRMachineState *spapr, int irq_hint, bool lsi,
ICSState *ics = spapr->ics; ICSState *ics = spapr->ics;
int irq; int irq;
if (!ics) { assert(ics);
return -1;
}
if (irq_hint) { if (irq_hint) {
if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) { if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) {
error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint); error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint);
@ -3753,9 +3855,7 @@ int spapr_irq_alloc_block(sPAPRMachineState *spapr, int num, bool lsi,
ICSState *ics = spapr->ics; ICSState *ics = spapr->ics;
int i, first = -1; int i, first = -1;
if (!ics) { assert(ics);
return -1;
}
/* /*
* MSIMesage::data is used for storing VIRQ so * MSIMesage::data is used for storing VIRQ so
@ -3985,18 +4085,42 @@ static const TypeInfo spapr_machine_info = {
type_init(spapr_machine_register_##suffix) type_init(spapr_machine_register_##suffix)
/* /*
* pseries-2.12 * pseries-2.13
*/ */
static void spapr_machine_2_12_instance_options(MachineState *machine) static void spapr_machine_2_13_instance_options(MachineState *machine)
{ {
} }
static void spapr_machine_2_12_class_options(MachineClass *mc) static void spapr_machine_2_13_class_options(MachineClass *mc)
{ {
/* Defaults for the latest behaviour inherited from the base class */ /* Defaults for the latest behaviour inherited from the base class */
} }
DEFINE_SPAPR_MACHINE(2_12, "2.12", true); DEFINE_SPAPR_MACHINE(2_13, "2.13", true);
/*
* pseries-2.12
*/
#define SPAPR_COMPAT_2_12 \
HW_COMPAT_2_12 \
{ \
.driver = TYPE_POWERPC_CPU, \
.property = "pre-2.13-migration", \
.value = "on", \
},
static void spapr_machine_2_12_instance_options(MachineState *machine)
{
spapr_machine_2_13_instance_options(machine);
}
static void spapr_machine_2_12_class_options(MachineClass *mc)
{
spapr_machine_2_13_class_options(mc);
SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_12);
}
DEFINE_SPAPR_MACHINE(2_12, "2.12", false);
static void spapr_machine_2_12_sxxm_instance_options(MachineState *machine) static void spapr_machine_2_12_sxxm_instance_options(MachineState *machine)
{ {

View File

@ -31,6 +31,11 @@ static void spapr_cpu_reset(void *opaque)
cpu_reset(cs); cpu_reset(cs);
/* Set compatibility mode to match the boot CPU, which was either set
* by the machine reset code or by CAS. This should never fail.
*/
ppc_set_compat(cpu, POWERPC_CPU(first_cpu)->compat_pvr, &error_abort);
/* All CPUs start halted. CPU0 is unhalted from the machine level /* All CPUs start halted. CPU0 is unhalted from the machine level
* reset code and the rest are explicitly started up by the guest * reset code and the rest are explicitly started up by the guest
* using an RTAS call */ * using an RTAS call */
@ -45,12 +50,6 @@ static void spapr_cpu_reset(void *opaque)
env->spr[SPR_LPCR] &= ~pcc->lpcr_pm; env->spr[SPR_LPCR] &= ~pcc->lpcr_pm;
} }
/* Set compatibility mode to match the boot CPU, which was either set
* by the machine reset code or by CAS. This should never fail.
*/
if (cs != first_cpu) {
ppc_set_compat(cpu, POWERPC_CPU(first_cpu)->compat_pvr, &error_abort);
}
} }
static void spapr_cpu_destroy(PowerPCCPU *cpu) static void spapr_cpu_destroy(PowerPCCPU *cpu)

View File

@ -1,6 +1,8 @@
#ifndef HW_COMPAT_H #ifndef HW_COMPAT_H
#define HW_COMPAT_H #define HW_COMPAT_H
#define HW_COMPAT_2_12
#define HW_COMPAT_2_11 \ #define HW_COMPAT_2_11 \
{\ {\
.driver = "hpet",\ .driver = "hpet",\

View File

@ -41,7 +41,7 @@ typedef struct HeathrowState {
MemoryRegion mem; MemoryRegion mem;
HeathrowPICState pics[2]; HeathrowPICState pics[2];
qemu_irq *irqs; qemu_irq irqs[1];
} HeathrowState; } HeathrowState;
#define HEATHROW_NUM_IRQS 64 #define HEATHROW_NUM_IRQS 64

View File

@ -56,7 +56,6 @@ typedef struct OldWorldMacIOState {
/*< public >*/ /*< public >*/
HeathrowState *pic; HeathrowState *pic;
qemu_irq irqs[7];
MacIONVRAMState nvram; MacIONVRAMState nvram;
MACIOIDEState ide[2]; MACIOIDEState ide[2];

View File

@ -0,0 +1,56 @@
/*
* QEMU Uninorth PCI host (for all Mac99 and newer machines)
*
* Copyright (c) 2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef UNINORTH_H
#define UNINORTH_H
#include "hw/hw.h"
#include "hw/ppc/openpic.h"
#define TYPE_UNI_NORTH_PCI_HOST_BRIDGE "uni-north-pci-pcihost"
#define TYPE_UNI_NORTH_AGP_HOST_BRIDGE "uni-north-agp-pcihost"
#define TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE "uni-north-internal-pci-pcihost"
#define TYPE_U3_AGP_HOST_BRIDGE "u3-agp-pcihost"
#define UNI_NORTH_PCI_HOST_BRIDGE(obj) \
OBJECT_CHECK(UNINHostState, (obj), TYPE_UNI_NORTH_PCI_HOST_BRIDGE)
#define UNI_NORTH_AGP_HOST_BRIDGE(obj) \
OBJECT_CHECK(UNINHostState, (obj), TYPE_UNI_NORTH_AGP_HOST_BRIDGE)
#define UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj) \
OBJECT_CHECK(UNINHostState, (obj), TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE)
#define U3_AGP_HOST_BRIDGE(obj) \
OBJECT_CHECK(UNINHostState, (obj), TYPE_U3_AGP_HOST_BRIDGE)
typedef struct UNINHostState {
PCIHostState parent_obj;
OpenPICState *pic;
qemu_irq irqs[4];
MemoryRegion pci_mmio;
MemoryRegion pci_hole;
MemoryRegion pci_io;
} UNINHostState;
#endif /* UNINORTH_H */

View File

@ -23,7 +23,7 @@
} \ } \
} while (0) } while (0)
size_t ppc_create_page_sizes_prop(CPUPPCState *env, uint32_t *prop, size_t ppc_create_page_sizes_prop(PowerPCCPU *cpu, uint32_t *prop,
size_t maxsize); size_t maxsize);
#endif /* PPC_FDT_H */ #endif /* PPC_FDT_H */

View File

@ -51,6 +51,7 @@ typedef struct sPAPROptionVector sPAPROptionVector;
#define OV5_FORM1_AFFINITY OV_BIT(5, 0) #define OV5_FORM1_AFFINITY OV_BIT(5, 0)
#define OV5_HP_EVT OV_BIT(6, 5) #define OV5_HP_EVT OV_BIT(6, 5)
#define OV5_HPT_RESIZE OV_BIT(6, 7) #define OV5_HPT_RESIZE OV_BIT(6, 7)
#define OV5_DRMEM_V2 OV_BIT(22, 0)
#define OV5_XIVE_BOTH OV_BIT(23, 0) #define OV5_XIVE_BOTH OV_BIT(23, 0)
#define OV5_XIVE_EXPLOIT OV_BIT(23, 1) /* 1=exploitation 0=legacy */ #define OV5_XIVE_EXPLOIT OV_BIT(23, 1) /* 1=exploitation 0=legacy */

View File

@ -68,4 +68,6 @@ MemoryRegion *host_memory_backend_get_memory(HostMemoryBackend *backend,
void host_memory_backend_set_mapped(HostMemoryBackend *backend, bool mapped); void host_memory_backend_set_mapped(HostMemoryBackend *backend, bool mapped);
bool host_memory_backend_is_mapped(HostMemoryBackend *backend); bool host_memory_backend_is_mapped(HostMemoryBackend *backend);
size_t host_memory_backend_pagesize(HostMemoryBackend *memdev);
#endif #endif

1
numa.c
View File

@ -469,6 +469,7 @@ static void allocate_system_memory_nonnuma(MemoryRegion *mr, Object *owner,
/* Legacy behavior: if allocation failed, fall back to /* Legacy behavior: if allocation failed, fall back to
* regular RAM allocation. * regular RAM allocation.
*/ */
mem_path = NULL;
memory_region_init_ram_nomigrate(mr, owner, name, ram_size, &error_fatal); memory_region_init_ram_nomigrate(mr, owner, name, ram_size, &error_fatal);
} }
#else #else

View File

@ -68,34 +68,17 @@ enum powerpc_mmu_t {
/* PowerPC 601 MMU model (specific BATs format) */ /* PowerPC 601 MMU model (specific BATs format) */
POWERPC_MMU_601 = 0x0000000A, POWERPC_MMU_601 = 0x0000000A,
#define POWERPC_MMU_64 0x00010000 #define POWERPC_MMU_64 0x00010000
#define POWERPC_MMU_1TSEG 0x00020000
#define POWERPC_MMU_AMR 0x00040000
#define POWERPC_MMU_64K 0x00080000
#define POWERPC_MMU_V3 0x00100000 /* ISA V3.00 MMU Support */
/* 64 bits PowerPC MMU */ /* 64 bits PowerPC MMU */
POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001, POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001,
/* Architecture 2.03 and later (has LPCR) */ /* Architecture 2.03 and later (has LPCR) */
POWERPC_MMU_2_03 = POWERPC_MMU_64 | 0x00000002, POWERPC_MMU_2_03 = POWERPC_MMU_64 | 0x00000002,
/* Architecture 2.06 variant */ /* Architecture 2.06 variant */
POWERPC_MMU_2_06 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG POWERPC_MMU_2_06 = POWERPC_MMU_64 | 0x00000003,
| POWERPC_MMU_64K
| POWERPC_MMU_AMR | 0x00000003,
/* Architecture 2.07 variant */ /* Architecture 2.07 variant */
POWERPC_MMU_2_07 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG POWERPC_MMU_2_07 = POWERPC_MMU_64 | 0x00000004,
| POWERPC_MMU_64K
| POWERPC_MMU_AMR | 0x00000004,
/* Architecture 3.00 variant */ /* Architecture 3.00 variant */
POWERPC_MMU_3_00 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG POWERPC_MMU_3_00 = POWERPC_MMU_64 | 0x00000005,
| POWERPC_MMU_64K
| POWERPC_MMU_AMR | POWERPC_MMU_V3
| 0x00000005,
}; };
#define POWERPC_MMU_VER(x) ((x) & (POWERPC_MMU_64 | 0xFFFF))
#define POWERPC_MMU_VER_64B POWERPC_MMU_VER(POWERPC_MMU_64B)
#define POWERPC_MMU_VER_2_03 POWERPC_MMU_VER(POWERPC_MMU_2_03)
#define POWERPC_MMU_VER_2_06 POWERPC_MMU_VER(POWERPC_MMU_2_06)
#define POWERPC_MMU_VER_2_07 POWERPC_MMU_VER(POWERPC_MMU_2_07)
#define POWERPC_MMU_VER_3_00 POWERPC_MMU_VER(POWERPC_MMU_3_00)
/*****************************************************************************/ /*****************************************************************************/
/* Exception model */ /* Exception model */
@ -164,7 +147,7 @@ enum powerpc_input_t {
PPC_FLAGS_INPUT_RCPU, PPC_FLAGS_INPUT_RCPU,
}; };
struct ppc_segment_page_sizes; typedef struct PPCHash64Options PPCHash64Options;
/** /**
* PowerPCCPUClass: * PowerPCCPUClass:
@ -198,7 +181,7 @@ typedef struct PowerPCCPUClass {
uint32_t flags; uint32_t flags;
int bfd_mach; int bfd_mach;
uint32_t l1_dcache_size, l1_icache_size; uint32_t l1_dcache_size, l1_icache_size;
const struct ppc_segment_page_sizes *sps; const PPCHash64Options *hash64_opts;
struct ppc_radix_page_info *radix_page_info; struct ppc_radix_page_info *radix_page_info;
void (*init_proc)(CPUPPCState *env); void (*init_proc)(CPUPPCState *env);
int (*check_pow)(CPUPPCState *env); int (*check_pow)(CPUPPCState *env);

View File

@ -327,11 +327,13 @@ union ppc_tlb_t {
#define TLB_MAS 3 #define TLB_MAS 3
#endif #endif
typedef struct PPCHash64SegmentPageSizes PPCHash64SegmentPageSizes;
typedef struct ppc_slb_t ppc_slb_t; typedef struct ppc_slb_t ppc_slb_t;
struct ppc_slb_t { struct ppc_slb_t {
uint64_t esid; uint64_t esid;
uint64_t vsid; uint64_t vsid;
const struct ppc_one_seg_page_size *sps; const PPCHash64SegmentPageSizes *sps;
}; };
#define MAX_SLB_ENTRIES 64 #define MAX_SLB_ENTRIES 64
@ -948,28 +950,8 @@ enum {
#define DBELL_PROCIDTAG_MASK PPC_BITMASK(44, 63) #define DBELL_PROCIDTAG_MASK PPC_BITMASK(44, 63)
/*****************************************************************************/
/* Segment page size information, used by recent hash MMUs
* The format of this structure mirrors kvm_ppc_smmu_info
*/
#define PPC_PAGE_SIZES_MAX_SZ 8 #define PPC_PAGE_SIZES_MAX_SZ 8
struct ppc_one_page_size {
uint32_t page_shift; /* Page shift (or 0) */
uint32_t pte_enc; /* Encoding in the HPTE (>>12) */
};
struct ppc_one_seg_page_size {
uint32_t page_shift; /* Base page shift of segment (or 0) */
uint32_t slb_enc; /* SLB encoding for BookS */
struct ppc_one_page_size enc[PPC_PAGE_SIZES_MAX_SZ];
};
struct ppc_segment_page_sizes {
struct ppc_one_seg_page_size sps[PPC_PAGE_SIZES_MAX_SZ];
};
struct ppc_radix_page_info { struct ppc_radix_page_info {
uint32_t count; uint32_t count;
uint32_t entries[PPC_PAGE_SIZES_MAX_SZ]; uint32_t entries[PPC_PAGE_SIZES_MAX_SZ];
@ -1043,7 +1025,6 @@ struct CPUPPCState {
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
/* PowerPC 64 SLB area */ /* PowerPC 64 SLB area */
ppc_slb_t slb[MAX_SLB_ENTRIES]; ppc_slb_t slb[MAX_SLB_ENTRIES];
int32_t slb_nr;
/* tcg TLB needs flush (deferred slb inval instruction typically) */ /* tcg TLB needs flush (deferred slb inval instruction typically) */
#endif #endif
/* segment registers */ /* segment registers */
@ -1106,10 +1087,8 @@ struct CPUPPCState {
uint64_t insns_flags; uint64_t insns_flags;
uint64_t insns_flags2; uint64_t insns_flags2;
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
struct ppc_segment_page_sizes sps;
ppc_slb_t vrma_slb; ppc_slb_t vrma_slb;
target_ulong rmls; target_ulong rmls;
bool ci_large_pages;
#endif #endif
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
@ -1227,6 +1206,7 @@ struct PowerPCCPU {
PPCVirtualHypervisor *vhyp; PPCVirtualHypervisor *vhyp;
Object *intc; Object *intc;
int32_t node_id; /* NUMA node this CPU belongs to */ int32_t node_id; /* NUMA node this CPU belongs to */
PPCHash64Options *hash64_opts;
/* Fields related to migration compatibility hacks */ /* Fields related to migration compatibility hacks */
bool pre_2_8_migration; bool pre_2_8_migration;
@ -1235,6 +1215,8 @@ struct PowerPCCPU {
uint64_t mig_insns_flags2; uint64_t mig_insns_flags2;
uint32_t mig_nb_BATs; uint32_t mig_nb_BATs;
bool pre_2_10_migration; bool pre_2_10_migration;
bool pre_2_13_migration;
int32_t mig_slb_nr;
}; };
static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env) static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)

View File

@ -37,10 +37,10 @@ static int ppc_gdb_register_len_apple(int n)
case 65+32: /* msr */ case 65+32: /* msr */
case 67+32: /* lr */ case 67+32: /* lr */
case 68+32: /* ctr */ case 68+32: /* ctr */
case 69+32: /* xer */
case 70+32: /* fpscr */ case 70+32: /* fpscr */
return 8; return 8;
case 66+32: /* cr */ case 66+32: /* cr */
case 69+32: /* xer */
return 4; return 4;
default: default:
return 0; return 0;
@ -61,6 +61,8 @@ static int ppc_gdb_register_len(int n)
return 8; return 8;
case 66: case 66:
/* cr */ /* cr */
case 69:
/* xer */
return 4; return 4;
case 64: case 64:
/* nip */ /* nip */
@ -70,8 +72,6 @@ static int ppc_gdb_register_len(int n)
/* lr */ /* lr */
case 68: case 68:
/* ctr */ /* ctr */
case 69:
/* xer */
return sizeof(target_ulong); return sizeof(target_ulong);
case 70: case 70:
/* fpscr */ /* fpscr */
@ -152,7 +152,7 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
gdb_get_regl(mem_buf, env->ctr); gdb_get_regl(mem_buf, env->ctr);
break; break;
case 69: case 69:
gdb_get_regl(mem_buf, env->xer); gdb_get_reg32(mem_buf, env->xer);
break; break;
case 70: case 70:
gdb_get_reg32(mem_buf, env->fpscr); gdb_get_reg32(mem_buf, env->fpscr);
@ -208,7 +208,7 @@ int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
gdb_get_reg64(mem_buf, env->ctr); gdb_get_reg64(mem_buf, env->ctr);
break; break;
case 69 + 32: case 69 + 32:
gdb_get_reg64(mem_buf, env->xer); gdb_get_reg32(mem_buf, env->xer);
break; break;
case 70 + 32: case 70 + 32:
gdb_get_reg64(mem_buf, env->fpscr); gdb_get_reg64(mem_buf, env->fpscr);
@ -259,7 +259,7 @@ int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
env->ctr = ldtul_p(mem_buf); env->ctr = ldtul_p(mem_buf);
break; break;
case 69: case 69:
env->xer = ldtul_p(mem_buf); env->xer = ldl_p(mem_buf);
break; break;
case 70: case 70:
/* fpscr */ /* fpscr */
@ -309,7 +309,7 @@ int ppc_cpu_gdb_write_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
env->ctr = ldq_p(mem_buf); env->ctr = ldq_p(mem_buf);
break; break;
case 69 + 32: case 69 + 32:
env->xer = ldq_p(mem_buf); env->xer = ldl_p(mem_buf);
break; break;
case 70 + 32: case 70 + 32:
/* fpscr */ /* fpscr */

View File

@ -302,12 +302,12 @@ static void kvm_get_fallback_smmu_info(PowerPCCPU *cpu,
/* HV KVM has backing store size restrictions */ /* HV KVM has backing store size restrictions */
info->flags = KVM_PPC_PAGE_SIZES_REAL; info->flags = KVM_PPC_PAGE_SIZES_REAL;
if (env->mmu_model & POWERPC_MMU_1TSEG) { if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
info->flags |= KVM_PPC_1T_SEGMENTS; info->flags |= KVM_PPC_1T_SEGMENTS;
} }
if (POWERPC_MMU_VER(env->mmu_model) == POWERPC_MMU_VER_2_06 || if (env->mmu_model == POWERPC_MMU_2_06 ||
POWERPC_MMU_VER(env->mmu_model) == POWERPC_MMU_VER_2_07) { env->mmu_model == POWERPC_MMU_2_07) {
info->slb_size = 32; info->slb_size = 32;
} else { } else {
info->slb_size = 64; info->slb_size = 64;
@ -321,8 +321,8 @@ static void kvm_get_fallback_smmu_info(PowerPCCPU *cpu,
i++; i++;
/* 64K on MMU 2.06 and later */ /* 64K on MMU 2.06 and later */
if (POWERPC_MMU_VER(env->mmu_model) == POWERPC_MMU_VER_2_06 || if (env->mmu_model == POWERPC_MMU_2_06 ||
POWERPC_MMU_VER(env->mmu_model) == POWERPC_MMU_VER_2_07) { env->mmu_model == POWERPC_MMU_2_07) {
info->sps[i].page_shift = 16; info->sps[i].page_shift = 16;
info->sps[i].slb_enc = 0x110; info->sps[i].slb_enc = 0x110;
info->sps[i].enc[0].page_shift = 16; info->sps[i].enc[0].page_shift = 16;
@ -425,7 +425,6 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
static bool has_smmu_info; static bool has_smmu_info;
CPUPPCState *env = &cpu->env; CPUPPCState *env = &cpu->env;
int iq, ik, jq, jk; int iq, ik, jq, jk;
bool has_64k_pages = false;
/* We only handle page sizes for 64-bit server guests for now */ /* We only handle page sizes for 64-bit server guests for now */
if (!(env->mmu_model & POWERPC_MMU_64)) { if (!(env->mmu_model & POWERPC_MMU_64)) {
@ -443,13 +442,17 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
} }
/* Convert to QEMU form */ /* Convert to QEMU form */
memset(&env->sps, 0, sizeof(env->sps)); memset(cpu->hash64_opts->sps, 0, sizeof(*cpu->hash64_opts->sps));
/* If we have HV KVM, we need to forbid CI large pages if our /* If we have HV KVM, we need to forbid CI large pages if our
* host page size is smaller than 64K. * host page size is smaller than 64K.
*/ */
if (smmu_info.flags & KVM_PPC_PAGE_SIZES_REAL) { if (smmu_info.flags & KVM_PPC_PAGE_SIZES_REAL) {
env->ci_large_pages = getpagesize() >= 0x10000; if (getpagesize() >= 0x10000) {
cpu->hash64_opts->flags |= PPC_HASH64_CI_LARGEPAGE;
} else {
cpu->hash64_opts->flags &= ~PPC_HASH64_CI_LARGEPAGE;
}
} }
/* /*
@ -457,7 +460,7 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
* the selected CPU has with the capabilities that KVM supports. * the selected CPU has with the capabilities that KVM supports.
*/ */
for (ik = iq = 0; ik < KVM_PPC_PAGE_SIZES_MAX_SZ; ik++) { for (ik = iq = 0; ik < KVM_PPC_PAGE_SIZES_MAX_SZ; ik++) {
struct ppc_one_seg_page_size *qsps = &env->sps.sps[iq]; PPCHash64SegmentPageSizes *qsps = &cpu->hash64_opts->sps[iq];
struct kvm_ppc_one_seg_page_size *ksps = &smmu_info.sps[ik]; struct kvm_ppc_one_seg_page_size *ksps = &smmu_info.sps[ik];
if (!kvm_valid_page_size(smmu_info.flags, max_cpu_page_size, if (!kvm_valid_page_size(smmu_info.flags, max_cpu_page_size,
@ -471,9 +474,6 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
ksps->enc[jk].page_shift)) { ksps->enc[jk].page_shift)) {
continue; continue;
} }
if (ksps->enc[jk].page_shift == 16) {
has_64k_pages = true;
}
qsps->enc[jq].page_shift = ksps->enc[jk].page_shift; qsps->enc[jq].page_shift = ksps->enc[jk].page_shift;
qsps->enc[jq].pte_enc = ksps->enc[jk].pte_enc; qsps->enc[jq].pte_enc = ksps->enc[jk].pte_enc;
if (++jq >= PPC_PAGE_SIZES_MAX_SZ) { if (++jq >= PPC_PAGE_SIZES_MAX_SZ) {
@ -484,27 +484,16 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
break; break;
} }
} }
env->slb_nr = smmu_info.slb_size; cpu->hash64_opts->slb_size = smmu_info.slb_size;
if (!(smmu_info.flags & KVM_PPC_1T_SEGMENTS)) { if (!(smmu_info.flags & KVM_PPC_1T_SEGMENTS)) {
env->mmu_model &= ~POWERPC_MMU_1TSEG; cpu->hash64_opts->flags &= ~PPC_HASH64_1TSEG;
}
if (!has_64k_pages) {
env->mmu_model &= ~POWERPC_MMU_64K;
} }
} }
bool kvmppc_is_mem_backend_page_size_ok(const char *obj_path) bool kvmppc_is_mem_backend_page_size_ok(const char *obj_path)
{ {
Object *mem_obj = object_resolve_path(obj_path, NULL); Object *mem_obj = object_resolve_path(obj_path, NULL);
char *mempath = object_property_get_str(mem_obj, "mem-path", NULL); long pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(mem_obj));
long pagesize;
if (mempath) {
pagesize = qemu_mempath_getpagesize(mempath);
g_free(mempath);
} else {
pagesize = getpagesize();
}
return pagesize >= max_cpu_page_size; return pagesize >= max_cpu_page_size;
} }

View File

@ -18,6 +18,9 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
unsigned int i, j; unsigned int i, j;
target_ulong sdr1; target_ulong sdr1;
uint32_t fpscr; uint32_t fpscr;
#if defined(TARGET_PPC64)
int32_t slb_nr;
#endif
target_ulong xer; target_ulong xer;
for (i = 0; i < 32; i++) for (i = 0; i < 32; i++)
@ -49,7 +52,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
qemu_get_sbe32s(f, &env->access_type); qemu_get_sbe32s(f, &env->access_type);
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
qemu_get_betls(f, &env->spr[SPR_ASR]); qemu_get_betls(f, &env->spr[SPR_ASR]);
qemu_get_sbe32s(f, &env->slb_nr); qemu_get_sbe32s(f, &slb_nr);
#endif #endif
qemu_get_betls(f, &sdr1); qemu_get_betls(f, &sdr1);
for (i = 0; i < 32; i++) for (i = 0; i < 32; i++)
@ -146,6 +149,15 @@ static bool cpu_pre_2_8_migration(void *opaque, int version_id)
return cpu->pre_2_8_migration; return cpu->pre_2_8_migration;
} }
#if defined(TARGET_PPC64)
static bool cpu_pre_2_13_migration(void *opaque, int version_id)
{
PowerPCCPU *cpu = opaque;
return cpu->pre_2_13_migration;
}
#endif
static int cpu_pre_save(void *opaque) static int cpu_pre_save(void *opaque)
{ {
PowerPCCPU *cpu = opaque; PowerPCCPU *cpu = opaque;
@ -203,6 +215,11 @@ static int cpu_pre_save(void *opaque)
cpu->mig_insns_flags2 = env->insns_flags2 & insns_compat_mask2; cpu->mig_insns_flags2 = env->insns_flags2 & insns_compat_mask2;
cpu->mig_nb_BATs = env->nb_BATs; cpu->mig_nb_BATs = env->nb_BATs;
} }
if (cpu->pre_2_13_migration) {
if (cpu->hash64_opts) {
cpu->mig_slb_nr = cpu->hash64_opts->slb_size;
}
}
return 0; return 0;
} }
@ -478,7 +495,7 @@ static int slb_post_load(void *opaque, int version_id)
/* We've pulled in the raw esid and vsid values from the migration /* We've pulled in the raw esid and vsid values from the migration
* stream, but we need to recompute the page size pointers */ * stream, but we need to recompute the page size pointers */
for (i = 0; i < env->slb_nr; i++) { for (i = 0; i < cpu->hash64_opts->slb_size; i++) {
if (ppc_store_slb(cpu, i, env->slb[i].esid, env->slb[i].vsid) < 0) { if (ppc_store_slb(cpu, i, env->slb[i].esid, env->slb[i].vsid) < 0) {
/* Migration source had bad values in its SLB */ /* Migration source had bad values in its SLB */
return -1; return -1;
@ -495,7 +512,7 @@ static const VMStateDescription vmstate_slb = {
.needed = slb_needed, .needed = slb_needed,
.post_load = slb_post_load, .post_load = slb_post_load,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
VMSTATE_INT32_EQUAL(env.slb_nr, PowerPCCPU, NULL), VMSTATE_INT32_TEST(mig_slb_nr, PowerPCCPU, cpu_pre_2_13_migration),
VMSTATE_SLB_ARRAY(env.slb, PowerPCCPU, MAX_SLB_ENTRIES), VMSTATE_SLB_ARRAY(env.slb, PowerPCCPU, MAX_SLB_ENTRIES),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
} }

View File

@ -52,7 +52,7 @@ static ppc_slb_t *slb_lookup(PowerPCCPU *cpu, target_ulong eaddr)
esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V; esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V; esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V;
for (n = 0; n < env->slb_nr; n++) { for (n = 0; n < cpu->hash64_opts->slb_size; n++) {
ppc_slb_t *slb = &env->slb[n]; ppc_slb_t *slb = &env->slb[n];
LOG_SLB("%s: slot %d %016" PRIx64 " %016" LOG_SLB("%s: slot %d %016" PRIx64 " %016"
@ -80,7 +80,7 @@ void dump_slb(FILE *f, fprintf_function cpu_fprintf, PowerPCCPU *cpu)
cpu_synchronize_state(CPU(cpu)); cpu_synchronize_state(CPU(cpu));
cpu_fprintf(f, "SLB\tESID\t\t\tVSID\n"); cpu_fprintf(f, "SLB\tESID\t\t\tVSID\n");
for (i = 0; i < env->slb_nr; i++) { for (i = 0; i < cpu->hash64_opts->slb_size; i++) {
slbe = env->slb[i].esid; slbe = env->slb[i].esid;
slbv = env->slb[i].vsid; slbv = env->slb[i].vsid;
if (slbe == 0 && slbv == 0) { if (slbe == 0 && slbv == 0) {
@ -93,10 +93,11 @@ void dump_slb(FILE *f, fprintf_function cpu_fprintf, PowerPCCPU *cpu)
void helper_slbia(CPUPPCState *env) void helper_slbia(CPUPPCState *env)
{ {
PowerPCCPU *cpu = ppc_env_get_cpu(env);
int n; int n;
/* XXX: Warning: slbia never invalidates the first segment */ /* XXX: Warning: slbia never invalidates the first segment */
for (n = 1; n < env->slb_nr; n++) { for (n = 1; n < cpu->hash64_opts->slb_size; n++) {
ppc_slb_t *slb = &env->slb[n]; ppc_slb_t *slb = &env->slb[n];
if (slb->esid & SLB_ESID_V) { if (slb->esid & SLB_ESID_V) {
@ -148,10 +149,10 @@ int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot,
{ {
CPUPPCState *env = &cpu->env; CPUPPCState *env = &cpu->env;
ppc_slb_t *slb = &env->slb[slot]; ppc_slb_t *slb = &env->slb[slot];
const struct ppc_one_seg_page_size *sps = NULL; const PPCHash64SegmentPageSizes *sps = NULL;
int i; int i;
if (slot >= env->slb_nr) { if (slot >= cpu->hash64_opts->slb_size) {
return -1; /* Bad slot number */ return -1; /* Bad slot number */
} }
if (esid & ~(SLB_ESID_ESID | SLB_ESID_V)) { if (esid & ~(SLB_ESID_ESID | SLB_ESID_V)) {
@ -160,12 +161,12 @@ int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot,
if (vsid & (SLB_VSID_B & ~SLB_VSID_B_1T)) { if (vsid & (SLB_VSID_B & ~SLB_VSID_B_1T)) {
return -1; /* Bad segment size */ return -1; /* Bad segment size */
} }
if ((vsid & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG)) { if ((vsid & SLB_VSID_B) && !(ppc_hash64_has(cpu, PPC_HASH64_1TSEG))) {
return -1; /* 1T segment on MMU that doesn't support it */ return -1; /* 1T segment on MMU that doesn't support it */
} }
for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
const struct ppc_one_seg_page_size *sps1 = &env->sps.sps[i]; const PPCHash64SegmentPageSizes *sps1 = &cpu->hash64_opts->sps[i];
if (!sps1->page_shift) { if (!sps1->page_shift) {
break; break;
@ -202,7 +203,7 @@ static int ppc_load_slb_esid(PowerPCCPU *cpu, target_ulong rb,
int slot = rb & 0xfff; int slot = rb & 0xfff;
ppc_slb_t *slb = &env->slb[slot]; ppc_slb_t *slb = &env->slb[slot];
if (slot >= env->slb_nr) { if (slot >= cpu->hash64_opts->slb_size) {
return -1; return -1;
} }
@ -217,7 +218,7 @@ static int ppc_load_slb_vsid(PowerPCCPU *cpu, target_ulong rb,
int slot = rb & 0xfff; int slot = rb & 0xfff;
ppc_slb_t *slb = &env->slb[slot]; ppc_slb_t *slb = &env->slb[slot];
if (slot >= env->slb_nr) { if (slot >= cpu->hash64_opts->slb_size) {
return -1; return -1;
} }
@ -369,7 +370,7 @@ static int ppc_hash64_amr_prot(PowerPCCPU *cpu, ppc_hash_pte64_t pte)
int prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; int prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
/* Only recent MMUs implement Virtual Page Class Key Protection */ /* Only recent MMUs implement Virtual Page Class Key Protection */
if (!(env->mmu_model & POWERPC_MMU_AMR)) { if (!ppc_hash64_has(cpu, PPC_HASH64_AMR)) {
return prot; return prot;
} }
@ -451,8 +452,8 @@ void ppc_hash64_unmap_hptes(PowerPCCPU *cpu, const ppc_hash_pte64_t *hptes,
false, n * HASH_PTE_SIZE_64); false, n * HASH_PTE_SIZE_64);
} }
static unsigned hpte_page_shift(const struct ppc_one_seg_page_size *sps, static unsigned hpte_page_shift(const PPCHash64SegmentPageSizes *sps,
uint64_t pte0, uint64_t pte1) uint64_t pte0, uint64_t pte1)
{ {
int i; int i;
@ -466,7 +467,7 @@ static unsigned hpte_page_shift(const struct ppc_one_seg_page_size *sps,
} }
for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
const struct ppc_one_page_size *ps = &sps->enc[i]; const PPCHash64PageSize *ps = &sps->enc[i];
uint64_t mask; uint64_t mask;
if (!ps->page_shift) { if (!ps->page_shift) {
@ -489,7 +490,7 @@ static unsigned hpte_page_shift(const struct ppc_one_seg_page_size *sps,
} }
static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash, static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash,
const struct ppc_one_seg_page_size *sps, const PPCHash64SegmentPageSizes *sps,
target_ulong ptem, target_ulong ptem,
ppc_hash_pte64_t *pte, unsigned *pshift) ppc_hash_pte64_t *pte, unsigned *pshift)
{ {
@ -543,7 +544,7 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu,
CPUPPCState *env = &cpu->env; CPUPPCState *env = &cpu->env;
hwaddr hash, ptex; hwaddr hash, ptex;
uint64_t vsid, epnmask, epn, ptem; uint64_t vsid, epnmask, epn, ptem;
const struct ppc_one_seg_page_size *sps = slb->sps; const PPCHash64SegmentPageSizes *sps = slb->sps;
/* The SLB store path should prevent any bad page size encodings /* The SLB store path should prevent any bad page size encodings
* getting in there, so: */ * getting in there, so: */
@ -552,7 +553,7 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu,
/* If ISL is set in LPCR we need to clamp the page size to 4K */ /* If ISL is set in LPCR we need to clamp the page size to 4K */
if (env->spr[SPR_LPCR] & LPCR_ISL) { if (env->spr[SPR_LPCR] & LPCR_ISL) {
/* We assume that when using TCG, 4k is first entry of SPS */ /* We assume that when using TCG, 4k is first entry of SPS */
sps = &env->sps.sps[0]; sps = &cpu->hash64_opts->sps[0];
assert(sps->page_shift == 12); assert(sps->page_shift == 12);
} }
@ -605,7 +606,6 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu,
unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu, unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu,
uint64_t pte0, uint64_t pte1) uint64_t pte0, uint64_t pte1)
{ {
CPUPPCState *env = &cpu->env;
int i; int i;
if (!(pte0 & HPTE64_V_LARGE)) { if (!(pte0 & HPTE64_V_LARGE)) {
@ -617,7 +617,7 @@ unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu,
* this gives an unambiguous result. * this gives an unambiguous result.
*/ */
for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
const struct ppc_one_seg_page_size *sps = &env->sps.sps[i]; const PPCHash64SegmentPageSizes *sps = &cpu->hash64_opts->sps[i];
unsigned shift; unsigned shift;
if (!sps->page_shift) { if (!sps->page_shift) {
@ -633,9 +633,9 @@ unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu,
return 0; return 0;
} }
static void ppc_hash64_set_isi(CPUState *cs, CPUPPCState *env, static void ppc_hash64_set_isi(CPUState *cs, uint64_t error_code)
uint64_t error_code)
{ {
CPUPPCState *env = &POWERPC_CPU(cs)->env;
bool vpm; bool vpm;
if (msr_ir) { if (msr_ir) {
@ -659,9 +659,9 @@ static void ppc_hash64_set_isi(CPUState *cs, CPUPPCState *env,
env->error_code = error_code; env->error_code = error_code;
} }
static void ppc_hash64_set_dsi(CPUState *cs, CPUPPCState *env, uint64_t dar, static void ppc_hash64_set_dsi(CPUState *cs, uint64_t dar, uint64_t dsisr)
uint64_t dsisr)
{ {
CPUPPCState *env = &POWERPC_CPU(cs)->env;
bool vpm; bool vpm;
if (msr_dr) { if (msr_dr) {
@ -741,13 +741,13 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
} else { } else {
/* The access failed, generate the approriate interrupt */ /* The access failed, generate the approriate interrupt */
if (rwx == 2) { if (rwx == 2) {
ppc_hash64_set_isi(cs, env, SRR1_PROTFAULT); ppc_hash64_set_isi(cs, SRR1_PROTFAULT);
} else { } else {
int dsisr = DSISR_PROTFAULT; int dsisr = DSISR_PROTFAULT;
if (rwx == 1) { if (rwx == 1) {
dsisr |= DSISR_ISSTORE; dsisr |= DSISR_ISSTORE;
} }
ppc_hash64_set_dsi(cs, env, eaddr, dsisr); ppc_hash64_set_dsi(cs, eaddr, dsisr);
} }
return 1; return 1;
} }
@ -762,7 +762,7 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
slb = slb_lookup(cpu, eaddr); slb = slb_lookup(cpu, eaddr);
if (!slb) { if (!slb) {
/* No entry found, check if in-memory segment tables are in use */ /* No entry found, check if in-memory segment tables are in use */
if ((env->mmu_model & POWERPC_MMU_V3) && ppc64_use_proc_tbl(cpu)) { if (ppc64_use_proc_tbl(cpu)) {
/* TODO - Unsupported */ /* TODO - Unsupported */
error_report("Segment Table Support Unimplemented"); error_report("Segment Table Support Unimplemented");
exit(1); exit(1);
@ -783,7 +783,7 @@ skip_slb_search:
/* 3. Check for segment level no-execute violation */ /* 3. Check for segment level no-execute violation */
if ((rwx == 2) && (slb->vsid & SLB_VSID_N)) { if ((rwx == 2) && (slb->vsid & SLB_VSID_N)) {
ppc_hash64_set_isi(cs, env, SRR1_NOEXEC_GUARD); ppc_hash64_set_isi(cs, SRR1_NOEXEC_GUARD);
return 1; return 1;
} }
@ -791,13 +791,13 @@ skip_slb_search:
ptex = ppc_hash64_htab_lookup(cpu, slb, eaddr, &pte, &apshift); ptex = ppc_hash64_htab_lookup(cpu, slb, eaddr, &pte, &apshift);
if (ptex == -1) { if (ptex == -1) {
if (rwx == 2) { if (rwx == 2) {
ppc_hash64_set_isi(cs, env, SRR1_NOPTE); ppc_hash64_set_isi(cs, SRR1_NOPTE);
} else { } else {
int dsisr = DSISR_NOPTE; int dsisr = DSISR_NOPTE;
if (rwx == 1) { if (rwx == 1) {
dsisr |= DSISR_ISSTORE; dsisr |= DSISR_ISSTORE;
} }
ppc_hash64_set_dsi(cs, env, eaddr, dsisr); ppc_hash64_set_dsi(cs, eaddr, dsisr);
} }
return 1; return 1;
} }
@ -824,7 +824,7 @@ skip_slb_search:
if (PAGE_EXEC & ~amr_prot) { if (PAGE_EXEC & ~amr_prot) {
srr1 |= SRR1_IAMR; /* Access violates virt pg class key prot */ srr1 |= SRR1_IAMR; /* Access violates virt pg class key prot */
} }
ppc_hash64_set_isi(cs, env, srr1); ppc_hash64_set_isi(cs, srr1);
} else { } else {
int dsisr = 0; int dsisr = 0;
if (need_prot[rwx] & ~pp_prot) { if (need_prot[rwx] & ~pp_prot) {
@ -836,7 +836,7 @@ skip_slb_search:
if (need_prot[rwx] & ~amr_prot) { if (need_prot[rwx] & ~amr_prot) {
dsisr |= DSISR_AMR; dsisr |= DSISR_AMR;
} }
ppc_hash64_set_dsi(cs, env, eaddr, dsisr); ppc_hash64_set_dsi(cs, eaddr, dsisr);
} }
return 1; return 1;
} }
@ -942,8 +942,9 @@ void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong ptex,
cpu->env.tlb_need_flush = TLB_NEED_GLOBAL_FLUSH | TLB_NEED_LOCAL_FLUSH; cpu->env.tlb_need_flush = TLB_NEED_GLOBAL_FLUSH | TLB_NEED_LOCAL_FLUSH;
} }
void ppc_hash64_update_rmls(CPUPPCState *env) void ppc_hash64_update_rmls(PowerPCCPU *cpu)
{ {
CPUPPCState *env = &cpu->env;
uint64_t lpcr = env->spr[SPR_LPCR]; uint64_t lpcr = env->spr[SPR_LPCR];
/* /*
@ -976,9 +977,10 @@ void ppc_hash64_update_rmls(CPUPPCState *env)
} }
} }
void ppc_hash64_update_vrma(CPUPPCState *env) void ppc_hash64_update_vrma(PowerPCCPU *cpu)
{ {
const struct ppc_one_seg_page_size *sps = NULL; CPUPPCState *env = &cpu->env;
const PPCHash64SegmentPageSizes *sps = NULL;
target_ulong esid, vsid, lpcr; target_ulong esid, vsid, lpcr;
ppc_slb_t *slb = &env->vrma_slb; ppc_slb_t *slb = &env->vrma_slb;
uint32_t vrmasd; uint32_t vrmasd;
@ -1002,8 +1004,8 @@ void ppc_hash64_update_vrma(CPUPPCState *env)
vsid |= (vrmasd << 4) & (SLB_VSID_L | SLB_VSID_LP); vsid |= (vrmasd << 4) & (SLB_VSID_L | SLB_VSID_LP);
esid = SLB_ESID_V; esid = SLB_ESID_V;
for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
const struct ppc_one_seg_page_size *sps1 = &env->sps.sps[i]; const PPCHash64SegmentPageSizes *sps1 = &cpu->hash64_opts->sps[i];
if (!sps1->page_shift) { if (!sps1->page_shift) {
break; break;
@ -1028,11 +1030,12 @@ void ppc_hash64_update_vrma(CPUPPCState *env)
void helper_store_lpcr(CPUPPCState *env, target_ulong val) void helper_store_lpcr(CPUPPCState *env, target_ulong val)
{ {
PowerPCCPU *cpu = ppc_env_get_cpu(env);
uint64_t lpcr = 0; uint64_t lpcr = 0;
/* Filter out bits */ /* Filter out bits */
switch (POWERPC_MMU_VER(env->mmu_model)) { switch (env->mmu_model) {
case POWERPC_MMU_VER_64B: /* 970 */ case POWERPC_MMU_64B: /* 970 */
if (val & 0x40) { if (val & 0x40) {
lpcr |= LPCR_LPES0; lpcr |= LPCR_LPES0;
} }
@ -1058,26 +1061,26 @@ void helper_store_lpcr(CPUPPCState *env, target_ulong val)
* to dig HRMOR out of HID5 * to dig HRMOR out of HID5
*/ */
break; break;
case POWERPC_MMU_VER_2_03: /* P5p */ case POWERPC_MMU_2_03: /* P5p */
lpcr = val & (LPCR_RMLS | LPCR_ILE | lpcr = val & (LPCR_RMLS | LPCR_ILE |
LPCR_LPES0 | LPCR_LPES1 | LPCR_LPES0 | LPCR_LPES1 |
LPCR_RMI | LPCR_HDICE); LPCR_RMI | LPCR_HDICE);
break; break;
case POWERPC_MMU_VER_2_06: /* P7 */ case POWERPC_MMU_2_06: /* P7 */
lpcr = val & (LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_DPFD | lpcr = val & (LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_DPFD |
LPCR_VRMASD | LPCR_RMLS | LPCR_ILE | LPCR_VRMASD | LPCR_RMLS | LPCR_ILE |
LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2 | LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2 |
LPCR_MER | LPCR_TC | LPCR_MER | LPCR_TC |
LPCR_LPES0 | LPCR_LPES1 | LPCR_HDICE); LPCR_LPES0 | LPCR_LPES1 | LPCR_HDICE);
break; break;
case POWERPC_MMU_VER_2_07: /* P8 */ case POWERPC_MMU_2_07: /* P8 */
lpcr = val & (LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV | lpcr = val & (LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV |
LPCR_DPFD | LPCR_VRMASD | LPCR_RMLS | LPCR_ILE | LPCR_DPFD | LPCR_VRMASD | LPCR_RMLS | LPCR_ILE |
LPCR_AIL | LPCR_ONL | LPCR_P8_PECE0 | LPCR_P8_PECE1 | LPCR_AIL | LPCR_ONL | LPCR_P8_PECE0 | LPCR_P8_PECE1 |
LPCR_P8_PECE2 | LPCR_P8_PECE3 | LPCR_P8_PECE4 | LPCR_P8_PECE2 | LPCR_P8_PECE3 | LPCR_P8_PECE4 |
LPCR_MER | LPCR_TC | LPCR_LPES0 | LPCR_HDICE); LPCR_MER | LPCR_TC | LPCR_LPES0 | LPCR_HDICE);
break; break;
case POWERPC_MMU_VER_3_00: /* P9 */ case POWERPC_MMU_3_00: /* P9 */
lpcr = val & (LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD | lpcr = val & (LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD |
(LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL | (LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL |
LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_UPRT | LPCR_EVIRT | LPCR_ONL |
@ -1089,6 +1092,69 @@ void helper_store_lpcr(CPUPPCState *env, target_ulong val)
; ;
} }
env->spr[SPR_LPCR] = lpcr; env->spr[SPR_LPCR] = lpcr;
ppc_hash64_update_rmls(env); ppc_hash64_update_rmls(cpu);
ppc_hash64_update_vrma(env); ppc_hash64_update_vrma(cpu);
} }
void ppc_hash64_init(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
if (!pcc->hash64_opts) {
assert(!(env->mmu_model & POWERPC_MMU_64));
return;
}
cpu->hash64_opts = g_memdup(pcc->hash64_opts, sizeof(*cpu->hash64_opts));
}
void ppc_hash64_finalize(PowerPCCPU *cpu)
{
g_free(cpu->hash64_opts);
}
const PPCHash64Options ppc_hash64_opts_basic = {
.flags = 0,
.slb_size = 64,
.sps = {
{ .page_shift = 12, /* 4K */
.slb_enc = 0,
.enc = { { .page_shift = 12, .pte_enc = 0 } }
},
{ .page_shift = 24, /* 16M */
.slb_enc = 0x100,
.enc = { { .page_shift = 24, .pte_enc = 0 } }
},
},
};
const PPCHash64Options ppc_hash64_opts_POWER7 = {
.flags = PPC_HASH64_1TSEG | PPC_HASH64_AMR | PPC_HASH64_CI_LARGEPAGE,
.slb_size = 32,
.sps = {
{
.page_shift = 12, /* 4K */
.slb_enc = 0,
.enc = { { .page_shift = 12, .pte_enc = 0 },
{ .page_shift = 16, .pte_enc = 0x7 },
{ .page_shift = 24, .pte_enc = 0x38 }, },
},
{
.page_shift = 16, /* 64K */
.slb_enc = SLB_VSID_64K,
.enc = { { .page_shift = 16, .pte_enc = 0x1 },
{ .page_shift = 24, .pte_enc = 0x8 }, },
},
{
.page_shift = 24, /* 16M */
.slb_enc = SLB_VSID_16M,
.enc = { { .page_shift = 24, .pte_enc = 0 }, },
},
{
.page_shift = 34, /* 16G */
.slb_enc = SLB_VSID_16G,
.enc = { { .page_shift = 34, .pte_enc = 0x3 }, },
},
}
};

View File

@ -17,8 +17,10 @@ void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu,
target_ulong pte0, target_ulong pte1); target_ulong pte0, target_ulong pte1);
unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu, unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu,
uint64_t pte0, uint64_t pte1); uint64_t pte0, uint64_t pte1);
void ppc_hash64_update_vrma(CPUPPCState *env); void ppc_hash64_update_vrma(PowerPCCPU *cpu);
void ppc_hash64_update_rmls(CPUPPCState *env); void ppc_hash64_update_rmls(PowerPCCPU *cpu);
void ppc_hash64_init(PowerPCCPU *cpu);
void ppc_hash64_finalize(PowerPCCPU *cpu);
#endif #endif
/* /*
@ -134,6 +136,48 @@ static inline uint64_t ppc_hash64_hpte1(PowerPCCPU *cpu,
return ldq_p(&(hptes[i].pte1)); return ldq_p(&(hptes[i].pte1));
} }
/*
* MMU Options
*/
struct PPCHash64PageSize {
uint32_t page_shift; /* Page shift (or 0) */
uint32_t pte_enc; /* Encoding in the HPTE (>>12) */
};
typedef struct PPCHash64PageSize PPCHash64PageSize;
struct PPCHash64SegmentPageSizes {
uint32_t page_shift; /* Base page shift of segment (or 0) */
uint32_t slb_enc; /* SLB encoding for BookS */
PPCHash64PageSize enc[PPC_PAGE_SIZES_MAX_SZ];
};
struct PPCHash64Options {
#define PPC_HASH64_1TSEG 0x00001
#define PPC_HASH64_AMR 0x00002
#define PPC_HASH64_CI_LARGEPAGE 0x00004
unsigned flags;
unsigned slb_size;
PPCHash64SegmentPageSizes sps[PPC_PAGE_SIZES_MAX_SZ];
};
extern const PPCHash64Options ppc_hash64_opts_basic;
extern const PPCHash64Options ppc_hash64_opts_POWER7;
static inline bool ppc_hash64_has(PowerPCCPU *cpu, unsigned feature)
{
return !!(cpu->hash64_opts->flags & feature);
}
#endif /* CONFIG_USER_ONLY */ #endif /* CONFIG_USER_ONLY */
#if defined(CONFIG_USER_ONLY) || !defined(TARGET_PPC64)
static inline void ppc_hash64_init(PowerPCCPU *cpu)
{
}
static inline void ppc_hash64_finalize(PowerPCCPU *cpu)
{
}
#endif
#endif /* MMU_HASH64_H */ #endif /* MMU_HASH64_H */

View File

@ -1266,7 +1266,7 @@ static void mmu6xx_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env) void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
{ {
switch (POWERPC_MMU_VER(env->mmu_model)) { switch (env->mmu_model) {
case POWERPC_MMU_BOOKE: case POWERPC_MMU_BOOKE:
mmubooke_dump_mmu(f, cpu_fprintf, env); mmubooke_dump_mmu(f, cpu_fprintf, env);
break; break;
@ -1278,13 +1278,13 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
mmu6xx_dump_mmu(f, cpu_fprintf, env); mmu6xx_dump_mmu(f, cpu_fprintf, env);
break; break;
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
case POWERPC_MMU_VER_64B: case POWERPC_MMU_64B:
case POWERPC_MMU_VER_2_03: case POWERPC_MMU_2_03:
case POWERPC_MMU_VER_2_06: case POWERPC_MMU_2_06:
case POWERPC_MMU_VER_2_07: case POWERPC_MMU_2_07:
dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env)); dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env));
break; break;
case POWERPC_MMU_VER_3_00: case POWERPC_MMU_3_00:
if (ppc64_radix_guest(ppc_env_get_cpu(env))) { if (ppc64_radix_guest(ppc_env_get_cpu(env))) {
/* TODO - Unsupported */ /* TODO - Unsupported */
} else { } else {
@ -1423,14 +1423,14 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
CPUPPCState *env = &cpu->env; CPUPPCState *env = &cpu->env;
mmu_ctx_t ctx; mmu_ctx_t ctx;
switch (POWERPC_MMU_VER(env->mmu_model)) { switch (env->mmu_model) {
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
case POWERPC_MMU_VER_64B: case POWERPC_MMU_64B:
case POWERPC_MMU_VER_2_03: case POWERPC_MMU_2_03:
case POWERPC_MMU_VER_2_06: case POWERPC_MMU_2_06:
case POWERPC_MMU_VER_2_07: case POWERPC_MMU_2_07:
return ppc_hash64_get_phys_page_debug(cpu, addr); return ppc_hash64_get_phys_page_debug(cpu, addr);
case POWERPC_MMU_VER_3_00: case POWERPC_MMU_3_00:
if (ppc64_radix_guest(ppc_env_get_cpu(env))) { if (ppc64_radix_guest(ppc_env_get_cpu(env))) {
return ppc_radix64_get_phys_page_debug(cpu, addr); return ppc_radix64_get_phys_page_debug(cpu, addr);
} else { } else {

View File

@ -6561,7 +6561,7 @@ GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x00000001, PPC_CACHE),
GEN_HANDLER_E(dcbtls, 0x1F, 0x06, 0x05, 0x02000001, PPC_BOOKE, PPC2_BOOKE206), GEN_HANDLER_E(dcbtls, 0x1F, 0x06, 0x05, 0x02000001, PPC_BOOKE, PPC2_BOOKE206),
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ), GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC), GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC), GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x01800001, PPC_ALTIVEC),
GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC), GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI), GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA), GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
@ -7121,17 +7121,17 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
if (env->spr_cb[SPR_LPCR].name) if (env->spr_cb[SPR_LPCR].name)
cpu_fprintf(f, " LPCR " TARGET_FMT_lx "\n", env->spr[SPR_LPCR]); cpu_fprintf(f, " LPCR " TARGET_FMT_lx "\n", env->spr[SPR_LPCR]);
switch (POWERPC_MMU_VER(env->mmu_model)) { switch (env->mmu_model) {
case POWERPC_MMU_32B: case POWERPC_MMU_32B:
case POWERPC_MMU_601: case POWERPC_MMU_601:
case POWERPC_MMU_SOFT_6xx: case POWERPC_MMU_SOFT_6xx:
case POWERPC_MMU_SOFT_74xx: case POWERPC_MMU_SOFT_74xx:
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
case POWERPC_MMU_VER_64B: case POWERPC_MMU_64B:
case POWERPC_MMU_VER_2_03: case POWERPC_MMU_2_03:
case POWERPC_MMU_VER_2_06: case POWERPC_MMU_2_06:
case POWERPC_MMU_VER_2_07: case POWERPC_MMU_2_07:
case POWERPC_MMU_VER_3_00: case POWERPC_MMU_3_00:
#endif #endif
if (env->spr_cb[SPR_SDR1].name) { /* SDR1 Exists */ if (env->spr_cb[SPR_SDR1].name) { /* SDR1 Exists */
cpu_fprintf(f, " SDR1 " TARGET_FMT_lx " ", env->spr[SPR_SDR1]); cpu_fprintf(f, " SDR1 " TARGET_FMT_lx " ", env->spr[SPR_SDR1]);

View File

@ -8195,9 +8195,6 @@ static void init_proc_970(CPUPPCState *env)
gen_spr_970_dbg(env); gen_spr_970_dbg(env);
/* env variables */ /* env variables */
#if !defined(CONFIG_USER_ONLY)
env->slb_nr = 64;
#endif
env->dcache_line_size = 128; env->dcache_line_size = 128;
env->icache_line_size = 128; env->icache_line_size = 128;
@ -8242,6 +8239,7 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
pcc->mmu_model = POWERPC_MMU_64B; pcc->mmu_model = POWERPC_MMU_64B;
#if defined(CONFIG_SOFTMMU) #if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
pcc->hash64_opts = &ppc_hash64_opts_basic;
#endif #endif
pcc->excp_model = POWERPC_EXCP_970; pcc->excp_model = POWERPC_EXCP_970;
pcc->bus_model = PPC_FLAGS_INPUT_970; pcc->bus_model = PPC_FLAGS_INPUT_970;
@ -8271,9 +8269,6 @@ static void init_proc_power5plus(CPUPPCState *env)
gen_spr_power5p_ear(env); gen_spr_power5p_ear(env);
/* env variables */ /* env variables */
#if !defined(CONFIG_USER_ONLY)
env->slb_nr = 64;
#endif
env->dcache_line_size = 128; env->dcache_line_size = 128;
env->icache_line_size = 128; env->icache_line_size = 128;
@ -8319,6 +8314,7 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
pcc->mmu_model = POWERPC_MMU_2_03; pcc->mmu_model = POWERPC_MMU_2_03;
#if defined(CONFIG_SOFTMMU) #if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
pcc->hash64_opts = &ppc_hash64_opts_basic;
#endif #endif
pcc->excp_model = POWERPC_EXCP_970; pcc->excp_model = POWERPC_EXCP_970;
pcc->bus_model = PPC_FLAGS_INPUT_970; pcc->bus_model = PPC_FLAGS_INPUT_970;
@ -8368,36 +8364,6 @@ static Property powerpc_servercpu_properties[] = {
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
}; };
#ifdef CONFIG_SOFTMMU
static const struct ppc_segment_page_sizes POWER7_POWER8_sps = {
.sps = {
{
.page_shift = 12, /* 4K */
.slb_enc = 0,
.enc = { { .page_shift = 12, .pte_enc = 0 },
{ .page_shift = 16, .pte_enc = 0x7 },
{ .page_shift = 24, .pte_enc = 0x38 }, },
},
{
.page_shift = 16, /* 64K */
.slb_enc = SLB_VSID_64K,
.enc = { { .page_shift = 16, .pte_enc = 0x1 },
{ .page_shift = 24, .pte_enc = 0x8 }, },
},
{
.page_shift = 24, /* 16M */
.slb_enc = SLB_VSID_16M,
.enc = { { .page_shift = 24, .pte_enc = 0 }, },
},
{
.page_shift = 34, /* 16G */
.slb_enc = SLB_VSID_16G,
.enc = { { .page_shift = 34, .pte_enc = 0x3 }, },
},
}
};
#endif /* CONFIG_SOFTMMU */
static void init_proc_POWER7(CPUPPCState *env) static void init_proc_POWER7(CPUPPCState *env)
{ {
/* Common Registers */ /* Common Registers */
@ -8417,10 +8383,6 @@ static void init_proc_POWER7(CPUPPCState *env)
gen_spr_power7_book4(env); gen_spr_power7_book4(env);
/* env variables */ /* env variables */
#if !defined(CONFIG_USER_ONLY)
env->slb_nr = 32;
#endif
env->ci_large_pages = true;
env->dcache_line_size = 128; env->dcache_line_size = 128;
env->icache_line_size = 128; env->icache_line_size = 128;
@ -8526,7 +8488,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
pcc->mmu_model = POWERPC_MMU_2_06; pcc->mmu_model = POWERPC_MMU_2_06;
#if defined(CONFIG_SOFTMMU) #if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
pcc->sps = &POWER7_POWER8_sps; pcc->hash64_opts = &ppc_hash64_opts_POWER7;
#endif #endif
pcc->excp_model = POWERPC_EXCP_POWER7; pcc->excp_model = POWERPC_EXCP_POWER7;
pcc->bus_model = PPC_FLAGS_INPUT_POWER7; pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
@ -8572,10 +8534,6 @@ static void init_proc_POWER8(CPUPPCState *env)
gen_spr_power8_rpr(env); gen_spr_power8_rpr(env);
/* env variables */ /* env variables */
#if !defined(CONFIG_USER_ONLY)
env->slb_nr = 32;
#endif
env->ci_large_pages = true;
env->dcache_line_size = 128; env->dcache_line_size = 128;
env->icache_line_size = 128; env->icache_line_size = 128;
@ -8698,7 +8656,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
pcc->mmu_model = POWERPC_MMU_2_07; pcc->mmu_model = POWERPC_MMU_2_07;
#if defined(CONFIG_SOFTMMU) #if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
pcc->sps = &POWER7_POWER8_sps; pcc->hash64_opts = &ppc_hash64_opts_POWER7;
#endif #endif
pcc->excp_model = POWERPC_EXCP_POWER8; pcc->excp_model = POWERPC_EXCP_POWER8;
pcc->bus_model = PPC_FLAGS_INPUT_POWER7; pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
@ -8773,10 +8731,6 @@ static void init_proc_POWER9(CPUPPCState *env)
KVM_REG_PPC_PSSCR, 0); KVM_REG_PPC_PSSCR, 0);
/* env variables */ /* env variables */
#if !defined(CONFIG_USER_ONLY)
env->slb_nr = 32;
#endif
env->ci_large_pages = true;
env->dcache_line_size = 128; env->dcache_line_size = 128;
env->icache_line_size = 128; env->icache_line_size = 128;
@ -8893,7 +8847,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
#if defined(CONFIG_SOFTMMU) #if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc64_v3_handle_mmu_fault; pcc->handle_mmu_fault = ppc64_v3_handle_mmu_fault;
/* segment page size remain the same */ /* segment page size remain the same */
pcc->sps = &POWER7_POWER8_sps; pcc->hash64_opts = &ppc_hash64_opts_POWER7;
pcc->radix_page_info = &POWER9_radix_page_info; pcc->radix_page_info = &POWER9_radix_page_info;
#endif #endif
pcc->excp_model = POWERPC_EXCP_POWER8; pcc->excp_model = POWERPC_EXCP_POWER8;
@ -8920,12 +8874,11 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
cpu->vhyp = vhyp; cpu->vhyp = vhyp;
/* PAPR always has exception vectors in RAM not ROM. To ensure this, /*
* MSR[IP] should never be set. * With a virtual hypervisor mode we never allow the CPU to go
* * hypervisor mode itself
* We also disallow setting of MSR_HV
*/ */
env->msr_mask &= ~((1ull << MSR_EP) | MSR_HVB); env->msr_mask &= ~MSR_HVB;
/* Set emulated LPCR to not send interrupts to hypervisor. Note that /* Set emulated LPCR to not send interrupts to hypervisor. Note that
* under KVM, the actual HW LPCR will be set differently by KVM itself, * under KVM, the actual HW LPCR will be set differently by KVM itself,
@ -8975,8 +8928,8 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
env->spr[SPR_AMOR] = amor->default_value = 0xffffffffffffffffull; env->spr[SPR_AMOR] = amor->default_value = 0xffffffffffffffffull;
/* Update some env bits based on new LPCR value */ /* Update some env bits based on new LPCR value */
ppc_hash64_update_rmls(env); ppc_hash64_update_rmls(cpu);
ppc_hash64_update_vrma(env); ppc_hash64_update_vrma(cpu);
/* Tell KVM that we're in PAPR mode */ /* Tell KVM that we're in PAPR mode */
if (kvm_enabled()) { if (kvm_enabled()) {
@ -9726,7 +9679,7 @@ static inline bool ppc_cpu_is_valid(PowerPCCPUClass *pcc)
#endif #endif
} }
static void ppc_cpu_realizefn(DeviceState *dev, Error **errp) static void ppc_cpu_realize(DeviceState *dev, Error **errp)
{ {
CPUState *cs = CPU(dev); CPUState *cs = CPU(dev);
PowerPCCPU *cpu = POWERPC_CPU(dev); PowerPCCPU *cpu = POWERPC_CPU(dev);
@ -9749,14 +9702,7 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
} }
} }
#if defined(TARGET_PPCEMB) assert(ppc_cpu_is_valid(pcc));
if (!ppc_cpu_is_valid(pcc)) {
error_setg(errp, "CPU does not possess a BookE or 4xx MMU. "
"Please use qemu-system-ppc or qemu-system-ppc64 instead "
"or choose another CPU model.");
goto unrealize;
}
#endif
create_ppc_opcodes(cpu, &local_err); create_ppc_opcodes(cpu, &local_err);
if (local_err != NULL) { if (local_err != NULL) {
@ -9952,7 +9898,7 @@ unrealize:
cpu_exec_unrealizefn(cs); cpu_exec_unrealizefn(cs);
} }
static void ppc_cpu_unrealizefn(DeviceState *dev, Error **errp) static void ppc_cpu_unrealize(DeviceState *dev, Error **errp)
{ {
PowerPCCPU *cpu = POWERPC_CPU(dev); PowerPCCPU *cpu = POWERPC_CPU(dev);
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
@ -10438,7 +10384,7 @@ static bool ppc_cpu_is_big_endian(CPUState *cs)
} }
#endif #endif
static void ppc_cpu_initfn(Object *obj) static void ppc_cpu_instance_init(Object *obj)
{ {
CPUState *cs = CPU(obj); CPUState *cs = CPU(obj);
PowerPCCPU *cpu = POWERPC_CPU(obj); PowerPCCPU *cpu = POWERPC_CPU(obj);
@ -10471,42 +10417,14 @@ static void ppc_cpu_initfn(Object *obj)
env->has_hv_mode = !!(env->msr_mask & MSR_HVB); env->has_hv_mode = !!(env->msr_mask & MSR_HVB);
#endif #endif
#if defined(TARGET_PPC64) ppc_hash64_init(cpu);
if (pcc->sps) { }
env->sps = *pcc->sps;
} else if (env->mmu_model & POWERPC_MMU_64) { static void ppc_cpu_instance_finalize(Object *obj)
/* Use default sets of page sizes. We don't support MPSS */ {
static const struct ppc_segment_page_sizes defsps_4k = { PowerPCCPU *cpu = POWERPC_CPU(obj);
.sps = {
{ .page_shift = 12, /* 4K */ ppc_hash64_finalize(cpu);
.slb_enc = 0,
.enc = { { .page_shift = 12, .pte_enc = 0 } }
},
{ .page_shift = 24, /* 16M */
.slb_enc = 0x100,
.enc = { { .page_shift = 24, .pte_enc = 0 } }
},
},
};
static const struct ppc_segment_page_sizes defsps_64k = {
.sps = {
{ .page_shift = 12, /* 4K */
.slb_enc = 0,
.enc = { { .page_shift = 12, .pte_enc = 0 } }
},
{ .page_shift = 16, /* 64K */
.slb_enc = 0x110,
.enc = { { .page_shift = 16, .pte_enc = 1 } }
},
{ .page_shift = 24, /* 16M */
.slb_enc = 0x100,
.enc = { { .page_shift = 24, .pte_enc = 0 } }
},
},
};
env->sps = (env->mmu_model & POWERPC_MMU_64K) ? defsps_64k : defsps_4k;
}
#endif /* defined(TARGET_PPC64) */
} }
static bool ppc_pvr_match_default(PowerPCCPUClass *pcc, uint32_t pvr) static bool ppc_pvr_match_default(PowerPCCPUClass *pcc, uint32_t pvr)
@ -10552,6 +10470,8 @@ static Property ppc_cpu_properties[] = {
DEFINE_PROP_BOOL("pre-2.8-migration", PowerPCCPU, pre_2_8_migration, false), DEFINE_PROP_BOOL("pre-2.8-migration", PowerPCCPU, pre_2_8_migration, false),
DEFINE_PROP_BOOL("pre-2.10-migration", PowerPCCPU, pre_2_10_migration, DEFINE_PROP_BOOL("pre-2.10-migration", PowerPCCPU, pre_2_10_migration,
false), false),
DEFINE_PROP_BOOL("pre-2.13-migration", PowerPCCPU, pre_2_13_migration,
false),
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
}; };
@ -10561,9 +10481,9 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc); CPUClass *cc = CPU_CLASS(oc);
DeviceClass *dc = DEVICE_CLASS(oc); DeviceClass *dc = DEVICE_CLASS(oc);
device_class_set_parent_realize(dc, ppc_cpu_realizefn, device_class_set_parent_realize(dc, ppc_cpu_realize,
&pcc->parent_realize); &pcc->parent_realize);
device_class_set_parent_unrealize(dc, ppc_cpu_unrealizefn, device_class_set_parent_unrealize(dc, ppc_cpu_unrealize,
&pcc->parent_unrealize); &pcc->parent_unrealize);
pcc->pvr_match = ppc_pvr_match_default; pcc->pvr_match = ppc_pvr_match_default;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always; pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always;
@ -10623,7 +10543,8 @@ static const TypeInfo ppc_cpu_type_info = {
.name = TYPE_POWERPC_CPU, .name = TYPE_POWERPC_CPU,
.parent = TYPE_CPU, .parent = TYPE_CPU,
.instance_size = sizeof(PowerPCCPU), .instance_size = sizeof(PowerPCCPU),
.instance_init = ppc_cpu_initfn, .instance_init = ppc_cpu_instance_init,
.instance_finalize = ppc_cpu_instance_finalize,
.abstract = true, .abstract = true,
.class_size = sizeof(PowerPCCPUClass), .class_size = sizeof(PowerPCCPUClass),
.class_init = ppc_cpu_class_init, .class_init = ppc_cpu_class_init,

View File

@ -50,19 +50,21 @@ size_t qemu_mempath_getpagesize(const char *mem_path)
struct statfs fs; struct statfs fs;
int ret; int ret;
do { if (mem_path) {
ret = statfs(mem_path, &fs); do {
} while (ret != 0 && errno == EINTR); ret = statfs(mem_path, &fs);
} while (ret != 0 && errno == EINTR);
if (ret != 0) { if (ret != 0) {
fprintf(stderr, "Couldn't statfs() memory path: %s\n", fprintf(stderr, "Couldn't statfs() memory path: %s\n",
strerror(errno)); strerror(errno));
exit(1); exit(1);
} }
if (fs.f_type == HUGETLBFS_MAGIC) { if (fs.f_type == HUGETLBFS_MAGIC) {
/* It's hugepage, return the huge page size */ /* It's hugepage, return the huge page size */
return fs.f_bsize; return fs.f_bsize;
}
} }
#ifdef __sparc__ #ifdef __sparc__
/* SPARC Linux needs greater alignment than the pagesize */ /* SPARC Linux needs greater alignment than the pagesize */