ppc patch queue 2018-05-04
Second patch of patches for qemu-2.13 (or whatever the version ends up being called). Highlights are: * Preliminary patches for POWER9 hash MMU support for powernv * A number of cleanups fo pseries startup and LPCR handling * Remove support for explicitly allocated RMAs (which require kernel support that's been gone for 3+ years) * Some mac_newworld cleanups * A few bugfixes -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAlrr6p8ACgkQbDjKyiDZ s5IxDQ/+NIZzD6xmMW0AtTes73Sn5uy3vB5utv/mgjbKuoovCE+FRtVXAPVlc41O q6Y8f0PWCfTbJb+G/XusSyQX9kc/anmmyQdrWuCbMFYJgwf9Fy3NVntx6HzppTub HEQJTdiPU3VCt3et1C4R9NqJmyG8n8qfyoa3oeEY+LTdIEQTRxgmzVfxMzfOddGQ jlvtwUqzGwSkXiJ/ZpKwFrn2XQiuvRdGeypMZWTk6ZsPAUHUpYvWO4LvhCmMsy1E PErwpHm8XCzOmkcdz2C6c7S9sfg1b8axllzwA5o6forfi9Hu8lk7EK08SRN0SUMf qjBA3upaQ4/HyKOuHMEAnVLErSerUOAM4hpkSt2ua9/KRR7zkx0pzqvAFPAKCuUv jXkYq/PlkbzxglkFiHaVyywAA7UBRPzTBn7NWhAf3XPtfcN5z/pU5qdeLAFRyw/U J77ET0Xq50po16uLIn8MVJY315C+kLvL8uz7IW6vN3koW4ZQeJ+v7s5S5ZZv20CY zLC5N/2loNyOVBvB3mTc+fa+HTDv8B9UBn+gLMHfzuCUbHiDC8BSKk/Z/FtpNCEG lW9whJ/prjZ+VTIiJxbSTg5o8UPl9RAAhDxi6g09BiJe9dBYWdYAe0EenSUllETy jfYeKbo0PG0NcbcsvxapCW1zvarMbczmpNWAe2w4MPuXUj+vfUc= =CAwC -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.13-20180504' into staging ppc patch queue 2018-05-04 Second patch of patches for qemu-2.13 (or whatever the version ends up being called). Highlights are: * Preliminary patches for POWER9 hash MMU support for powernv * A number of cleanups fo pseries startup and LPCR handling * Remove support for explicitly allocated RMAs (which require kernel support that's been gone for 3+ years) * Some mac_newworld cleanups * A few bugfixes # gpg: Signature made Fri 04 May 2018 06:07:43 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-20180504: spapr: don't advertise radix GTSE if max-compat-cpu < power9 spapr: don't migrate "spapr_option_vector_ov5_cas" to pre 2.8 machines target/ppc: always set PPC_MEM_TLBIE in pre 2.8 migration hack mac_newworld: move wiring of macio IRQs to macio_newworld_realize() mac_newworld: remove pics IRQ array and wire up macio to OpenPIC directly uninorth: create new uninorth device spapr: Clean up handling of LPCR power-saving exit bits spapr: Move PAPR mode cpu setup fully to spapr code target/ppc: Delay initialization of LPCR_UPRT for secondary cpus spapr: Clean up LPCR updates from hypercalls spapr: Make a helper to set up cpu entry point state spapr: Remove unhelpful helpers from rtas_start_cpu() spapr: Clean up rtas_start_cpu() & rtas_stop_self() target/ppc: Add ppc_store_lpcr() helper spapr: Remove support for explicitly allocated RMAs target/ppc: add basic support for PTCR on POWER9 target/ppc: return a nil HPT base address on sPAPR machines Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
2e4bd4a286
@ -279,11 +279,10 @@ static void macio_newworld_realize(PCIDevice *d, Error **errp)
|
||||
{
|
||||
MacIOState *s = MACIO(d);
|
||||
NewWorldMacIOState *ns = NEWWORLD_MACIO(d);
|
||||
DeviceState *pic_dev = DEVICE(ns->pic);
|
||||
Error *err = NULL;
|
||||
SysBusDevice *sysbus_dev;
|
||||
MemoryRegion *timer_memory = NULL;
|
||||
int i;
|
||||
int cur_irq = 0;
|
||||
|
||||
macio_common_realize(d, &err);
|
||||
if (err) {
|
||||
@ -292,11 +291,14 @@ static void macio_newworld_realize(PCIDevice *d, Error **errp)
|
||||
}
|
||||
|
||||
sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
|
||||
sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]);
|
||||
sysbus_connect_irq(sysbus_dev, 0, qdev_get_gpio_in(pic_dev,
|
||||
NEWWORLD_CUDA_IRQ));
|
||||
|
||||
sysbus_dev = SYS_BUS_DEVICE(&s->escc);
|
||||
sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]);
|
||||
sysbus_connect_irq(sysbus_dev, 1, ns->irqs[cur_irq++]);
|
||||
sysbus_connect_irq(sysbus_dev, 0, qdev_get_gpio_in(pic_dev,
|
||||
NEWWORLD_ESCCB_IRQ));
|
||||
sysbus_connect_irq(sysbus_dev, 1, qdev_get_gpio_in(pic_dev,
|
||||
NEWWORLD_ESCCA_IRQ));
|
||||
|
||||
/* OpenPIC */
|
||||
sysbus_dev = SYS_BUS_DEVICE(ns->pic);
|
||||
@ -304,15 +306,22 @@ static void macio_newworld_realize(PCIDevice *d, Error **errp)
|
||||
sysbus_mmio_get_region(sysbus_dev, 0));
|
||||
|
||||
/* IDE buses */
|
||||
for (i = 0; i < ARRAY_SIZE(ns->ide); i++) {
|
||||
qemu_irq irq0 = ns->irqs[cur_irq++];
|
||||
qemu_irq irq1 = ns->irqs[cur_irq++];
|
||||
macio_realize_ide(s, &ns->ide[0],
|
||||
qdev_get_gpio_in(pic_dev, NEWWORLD_IDE0_IRQ),
|
||||
qdev_get_gpio_in(pic_dev, NEWWORLD_IDE0_DMA_IRQ),
|
||||
0x16, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
macio_realize_ide(s, &ns->ide[i], irq0, irq1, 0x16 + (i * 4), &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
macio_realize_ide(s, &ns->ide[1],
|
||||
qdev_get_gpio_in(pic_dev, NEWWORLD_IDE1_IRQ),
|
||||
qdev_get_gpio_in(pic_dev, NEWWORLD_IDE1_DMA_IRQ),
|
||||
0x1a, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Timer */
|
||||
@ -328,8 +337,6 @@ static void macio_newworld_init(Object *obj)
|
||||
NewWorldMacIOState *ns = NEWWORLD_MACIO(obj);
|
||||
int i;
|
||||
|
||||
qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs));
|
||||
|
||||
object_property_add_link(obj, "pic", TYPE_OPENPIC,
|
||||
(Object **) &ns->pic,
|
||||
qdev_prop_allow_set_link_before_realize,
|
||||
|
@ -18,3 +18,5 @@ unin_set_irq(int irq_num, int level) "setting INT %d = %d"
|
||||
unin_get_config_reg(uint32_t reg, uint32_t addr, uint32_t retval) "converted config space accessor 0x%"PRIx32 "/0x%"PRIx32 " -> 0x%"PRIx32
|
||||
unin_data_write(uint64_t addr, unsigned len, uint64_t val) "write addr 0x%"PRIx64 " len %d val 0x%"PRIx64
|
||||
unin_data_read(uint64_t addr, unsigned len, uint64_t val) "read addr 0x%"PRIx64 " len %d val 0x%"PRIx64
|
||||
unin_write(uint64_t addr, uint64_t value) "addr=0x%" PRIx64 " val=0x%"PRIx64
|
||||
unin_read(uint64_t addr, uint64_t value) "addr=0x%" PRIx64 " val=0x%"PRIx64
|
||||
|
@ -519,6 +519,62 @@ static const TypeInfo pci_unin_internal_info = {
|
||||
.class_init = pci_unin_internal_class_init,
|
||||
};
|
||||
|
||||
/* UniN device */
|
||||
static void unin_write(void *opaque, hwaddr addr, uint64_t value,
|
||||
unsigned size)
|
||||
{
|
||||
trace_unin_write(addr, value);
|
||||
if (addr == 0x0) {
|
||||
*(int *)opaque = value;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t unin_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
value = 0;
|
||||
switch (addr) {
|
||||
case 0:
|
||||
value = *(int *)opaque;
|
||||
}
|
||||
|
||||
trace_unin_read(addr, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps unin_ops = {
|
||||
.read = unin_read,
|
||||
.write = unin_write,
|
||||
.endianness = DEVICE_BIG_ENDIAN,
|
||||
};
|
||||
|
||||
static void unin_init(Object *obj)
|
||||
{
|
||||
UNINState *s = UNI_NORTH(obj);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
|
||||
memory_region_init_io(&s->mem, obj, &unin_ops, &s->token, "unin", 0x1000);
|
||||
|
||||
sysbus_init_mmio(sbd, &s->mem);
|
||||
}
|
||||
|
||||
static void unin_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo unin_info = {
|
||||
.name = TYPE_UNI_NORTH,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(UNINState),
|
||||
.instance_init = unin_init,
|
||||
.class_init = unin_class_init,
|
||||
};
|
||||
|
||||
static void unin_register_types(void)
|
||||
{
|
||||
type_register_static(&unin_main_pci_host_info);
|
||||
@ -530,6 +586,8 @@ static void unin_register_types(void)
|
||||
type_register_static(&pci_u3_agp_info);
|
||||
type_register_static(&pci_unin_agp_info);
|
||||
type_register_static(&pci_unin_internal_info);
|
||||
|
||||
type_register_static(&unin_info);
|
||||
}
|
||||
|
||||
type_init(unin_register_types)
|
||||
|
@ -56,6 +56,15 @@
|
||||
#define OLDWORLD_IDE1_IRQ 0xe
|
||||
#define OLDWORLD_IDE1_DMA_IRQ 0x3
|
||||
|
||||
/* New World IRQs */
|
||||
#define NEWWORLD_CUDA_IRQ 0x19
|
||||
#define NEWWORLD_ESCCB_IRQ 0x24
|
||||
#define NEWWORLD_ESCCA_IRQ 0x25
|
||||
#define NEWWORLD_IDE0_IRQ 0xd
|
||||
#define NEWWORLD_IDE0_DMA_IRQ 0x2
|
||||
#define NEWWORLD_IDE1_IRQ 0xe
|
||||
#define NEWWORLD_IDE1_DMA_IRQ 0x3
|
||||
|
||||
/* MacIO */
|
||||
#define TYPE_MACIO_IDE "macio-ide"
|
||||
#define MACIO_IDE(obj) OBJECT_CHECK(MACIOIDEState, (obj), TYPE_MACIO_IDE)
|
||||
|
@ -82,36 +82,6 @@
|
||||
|
||||
#define NDRV_VGA_FILENAME "qemu_vga.ndrv"
|
||||
|
||||
/* UniN device */
|
||||
static void unin_write(void *opaque, hwaddr addr, uint64_t value,
|
||||
unsigned size)
|
||||
{
|
||||
trace_mac99_uninorth_write(addr, value);
|
||||
if (addr == 0x0) {
|
||||
*(int*)opaque = value;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t unin_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
value = 0;
|
||||
switch (addr) {
|
||||
case 0:
|
||||
value = *(int*)opaque;
|
||||
}
|
||||
|
||||
trace_mac99_uninorth_read(addr, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps unin_ops = {
|
||||
.read = unin_read,
|
||||
.write = unin_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void fw_cfg_boot_set(void *opaque, const char *boot_device,
|
||||
Error **errp)
|
||||
@ -144,8 +114,7 @@ static void ppc_core99_init(MachineState *machine)
|
||||
PowerPCCPU *cpu = NULL;
|
||||
CPUPPCState *env = NULL;
|
||||
char *filename;
|
||||
qemu_irq *pic, **openpic_irqs;
|
||||
MemoryRegion *unin_memory = g_new(MemoryRegion, 1);
|
||||
qemu_irq **openpic_irqs;
|
||||
int linux_boot, i, j, k;
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1), *bios = g_new(MemoryRegion, 1);
|
||||
hwaddr kernel_base, initrd_base, cmdline_base = 0;
|
||||
@ -164,7 +133,6 @@ static void ppc_core99_init(MachineState *machine)
|
||||
int machine_arch;
|
||||
SysBusDevice *s;
|
||||
DeviceState *dev, *pic_dev;
|
||||
int *token = g_new(int, 1);
|
||||
hwaddr nvram_addr = 0xFFF04000;
|
||||
uint64_t tbfreq;
|
||||
|
||||
@ -272,9 +240,12 @@ static void ppc_core99_init(MachineState *machine)
|
||||
}
|
||||
}
|
||||
|
||||
/* UniN init: XXX should be a real device */
|
||||
memory_region_init_io(unin_memory, NULL, &unin_ops, token, "unin", 0x1000);
|
||||
memory_region_add_subregion(get_system_memory(), 0xf8000000, unin_memory);
|
||||
/* UniN init */
|
||||
dev = qdev_create(NULL, TYPE_UNI_NORTH);
|
||||
qdev_init_nofail(dev);
|
||||
s = SYS_BUS_DEVICE(dev);
|
||||
memory_region_add_subregion(get_system_memory(), 0xf8000000,
|
||||
sysbus_mmio_get_region(s, 0));
|
||||
|
||||
openpic_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
|
||||
openpic_irqs[0] =
|
||||
@ -320,8 +291,6 @@ static void ppc_core99_init(MachineState *machine)
|
||||
}
|
||||
}
|
||||
|
||||
pic = g_new0(qemu_irq, 64);
|
||||
|
||||
pic_dev = qdev_create(NULL, TYPE_OPENPIC);
|
||||
qdev_prop_set_uint32(pic_dev, "model", OPENPIC_MODEL_KEYLARGO);
|
||||
qdev_init_nofail(pic_dev);
|
||||
@ -333,10 +302,6 @@ static void ppc_core99_init(MachineState *machine)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
pic[i] = qdev_get_gpio_in(pic_dev, i);
|
||||
}
|
||||
|
||||
if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {
|
||||
/* 970 gets a U3 bus */
|
||||
/* Uninorth AGP bus */
|
||||
@ -410,13 +375,6 @@ static void ppc_core99_init(MachineState *machine)
|
||||
/* MacIO */
|
||||
macio = NEWWORLD_MACIO(pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO));
|
||||
dev = DEVICE(macio);
|
||||
qdev_connect_gpio_out(dev, 0, pic[0x19]); /* CUDA */
|
||||
qdev_connect_gpio_out(dev, 1, pic[0x24]); /* ESCC-B */
|
||||
qdev_connect_gpio_out(dev, 2, pic[0x25]); /* ESCC-A */
|
||||
qdev_connect_gpio_out(dev, 3, pic[0x0d]); /* IDE */
|
||||
qdev_connect_gpio_out(dev, 4, pic[0x02]); /* IDE DMA */
|
||||
qdev_connect_gpio_out(dev, 5, pic[0x0e]); /* IDE */
|
||||
qdev_connect_gpio_out(dev, 6, pic[0x03]); /* IDE DMA */
|
||||
qdev_prop_set_uint64(dev, "frequency", tbfreq);
|
||||
object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic",
|
||||
&error_abort);
|
||||
|
@ -1668,10 +1668,8 @@ static void spapr_machine_reset(void)
|
||||
g_free(fdt);
|
||||
|
||||
/* Set up the entry state */
|
||||
first_ppc_cpu->env.gpr[3] = fdt_addr;
|
||||
spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, fdt_addr);
|
||||
first_ppc_cpu->env.gpr[5] = 0;
|
||||
first_cpu->halted = 0;
|
||||
first_ppc_cpu->env.nip = SPAPR_ENTRY_POINT;
|
||||
|
||||
spapr->cas_reboot = false;
|
||||
}
|
||||
@ -1851,10 +1849,12 @@ static bool spapr_ov5_cas_needed(void *opaque)
|
||||
*
|
||||
* Thus, for any cases where the set of available CAS-negotiatable
|
||||
* options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we
|
||||
* include the CAS-negotiated options in the migration stream.
|
||||
* include the CAS-negotiated options in the migration stream, unless
|
||||
* if they affect boot time behaviour only.
|
||||
*/
|
||||
spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY);
|
||||
spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY);
|
||||
spapr_ovec_set(ov5_mask, OV5_DRMEM_V2);
|
||||
|
||||
/* spapr_ovec_diff returns true if bits were removed. we avoid using
|
||||
* the mask itself since in the future it's possible "legacy" bits may be
|
||||
@ -2508,13 +2508,11 @@ static void spapr_machine_init(MachineState *machine)
|
||||
int i;
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *rma_region;
|
||||
void *rma = NULL;
|
||||
hwaddr rma_alloc_size;
|
||||
hwaddr node0_size = spapr_node0_size(machine);
|
||||
long load_limit, fw_size;
|
||||
char *filename;
|
||||
Error *resize_hpt_err = NULL;
|
||||
PowerPCCPU *first_ppc_cpu;
|
||||
|
||||
msi_nonbroken = true;
|
||||
|
||||
@ -2549,40 +2547,28 @@ static void spapr_machine_init(MachineState *machine)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Allocate RMA if necessary */
|
||||
rma_alloc_size = kvmppc_alloc_rma(&rma);
|
||||
spapr->rma_size = node0_size;
|
||||
|
||||
if (rma_alloc_size == -1) {
|
||||
error_report("Unable to create RMA");
|
||||
exit(1);
|
||||
/* With KVM, we don't actually know whether KVM supports an
|
||||
* unbounded RMA (PR KVM) or is limited by the hash table size
|
||||
* (HV KVM using VRMA), so we always assume the latter
|
||||
*
|
||||
* In that case, we also limit the initial allocations for RTAS
|
||||
* etc... to 256M since we have no way to know what the VRMA size
|
||||
* is going to be as it depends on the size of the hash table
|
||||
* which isn't determined yet.
|
||||
*/
|
||||
if (kvm_enabled()) {
|
||||
spapr->vrma_adjust = 1;
|
||||
spapr->rma_size = MIN(spapr->rma_size, 0x10000000);
|
||||
}
|
||||
|
||||
if (rma_alloc_size && (rma_alloc_size < node0_size)) {
|
||||
spapr->rma_size = rma_alloc_size;
|
||||
} else {
|
||||
spapr->rma_size = node0_size;
|
||||
|
||||
/* With KVM, we don't actually know whether KVM supports an
|
||||
* unbounded RMA (PR KVM) or is limited by the hash table size
|
||||
* (HV KVM using VRMA), so we always assume the latter
|
||||
*
|
||||
* In that case, we also limit the initial allocations for RTAS
|
||||
* etc... to 256M since we have no way to know what the VRMA size
|
||||
* is going to be as it depends on the size of the hash table
|
||||
* isn't determined yet.
|
||||
*/
|
||||
if (kvm_enabled()) {
|
||||
spapr->vrma_adjust = 1;
|
||||
spapr->rma_size = MIN(spapr->rma_size, 0x10000000);
|
||||
}
|
||||
|
||||
/* Actually we don't support unbounded RMA anymore since we
|
||||
* added proper emulation of HV mode. The max we can get is
|
||||
* 16G which also happens to be what we configure for PAPR
|
||||
* mode so make sure we don't do anything bigger than that
|
||||
*/
|
||||
spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull);
|
||||
}
|
||||
/* Actually we don't support unbounded RMA anymore since we added
|
||||
* proper emulation of HV mode. The max we can get is 16G which
|
||||
* also happens to be what we configure for PAPR mode so make sure
|
||||
* we don't do anything bigger than that
|
||||
*/
|
||||
spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull);
|
||||
|
||||
if (spapr->rma_size > node0_size) {
|
||||
error_report("Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")",
|
||||
@ -2607,11 +2593,6 @@ static void spapr_machine_init(MachineState *machine)
|
||||
}
|
||||
|
||||
spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY);
|
||||
if (!kvm_enabled() || kvmppc_has_cap_mmu_radix()) {
|
||||
/* KVM and TCG always allow GTSE with radix... */
|
||||
spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE);
|
||||
}
|
||||
/* ... but not with hash (currently). */
|
||||
|
||||
/* advertise support for dedicated HP event source to guests */
|
||||
if (spapr->use_hotplug_event_source) {
|
||||
@ -2629,6 +2610,15 @@ static void spapr_machine_init(MachineState *machine)
|
||||
/* init CPUs */
|
||||
spapr_init_cpus(spapr);
|
||||
|
||||
first_ppc_cpu = POWERPC_CPU(first_cpu);
|
||||
if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) &&
|
||||
ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0,
|
||||
spapr->max_compat_pvr)) {
|
||||
/* KVM and TCG always allow GTSE with radix... */
|
||||
spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE);
|
||||
}
|
||||
/* ... but not with hash (currently). */
|
||||
|
||||
if (kvm_enabled()) {
|
||||
/* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */
|
||||
kvmppc_enable_logical_ci_hcalls();
|
||||
@ -2643,14 +2633,6 @@ static void spapr_machine_init(MachineState *machine)
|
||||
machine->ram_size);
|
||||
memory_region_add_subregion(sysmem, 0, ram);
|
||||
|
||||
if (rma_alloc_size && rma) {
|
||||
rma_region = g_new(MemoryRegion, 1);
|
||||
memory_region_init_ram_ptr(rma_region, NULL, "ppc_spapr.rma",
|
||||
rma_alloc_size, rma);
|
||||
vmstate_register_ram_global(rma_region);
|
||||
memory_region_add_subregion(sysmem, 0, rma_region);
|
||||
}
|
||||
|
||||
/* initialize hotplug memory address space */
|
||||
if (machine->ram_size < machine->maxram_size) {
|
||||
ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size;
|
||||
|
@ -28,6 +28,7 @@ static void spapr_cpu_reset(void *opaque)
|
||||
CPUState *cs = CPU(cpu);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
|
||||
target_ulong lpcr;
|
||||
|
||||
cpu_reset(cs);
|
||||
|
||||
@ -43,13 +44,43 @@ static void spapr_cpu_reset(void *opaque)
|
||||
|
||||
env->spr[SPR_HIOR] = 0;
|
||||
|
||||
/* Disable Power-saving mode Exit Cause exceptions for the CPU.
|
||||
* This can cause issues when rebooting the guest if a secondary
|
||||
* is awaken */
|
||||
if (cs != first_cpu) {
|
||||
env->spr[SPR_LPCR] &= ~pcc->lpcr_pm;
|
||||
}
|
||||
lpcr = env->spr[SPR_LPCR];
|
||||
|
||||
/* Set emulated LPCR to not send interrupts to hypervisor. Note that
|
||||
* under KVM, the actual HW LPCR will be set differently by KVM itself,
|
||||
* the settings below ensure proper operations with TCG in absence of
|
||||
* a real hypervisor.
|
||||
*
|
||||
* Clearing VPM0 will also cause us to use RMOR in mmu-hash64.c for
|
||||
* real mode accesses, which thankfully defaults to 0 and isn't
|
||||
* accessible in guest mode.
|
||||
*
|
||||
* Disable Power-saving mode Exit Cause exceptions for the CPU, so
|
||||
* we don't get spurious wakups before an RTAS start-cpu call.
|
||||
*/
|
||||
lpcr &= ~(LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV | pcc->lpcr_pm);
|
||||
lpcr |= LPCR_LPES0 | LPCR_LPES1;
|
||||
|
||||
/* Set RMLS to the max (ie, 16G) */
|
||||
lpcr &= ~LPCR_RMLS;
|
||||
lpcr |= 1ull << LPCR_RMLS_SHIFT;
|
||||
|
||||
ppc_store_lpcr(cpu, lpcr);
|
||||
|
||||
/* Set a full AMOR so guest can use the AMR as it sees fit */
|
||||
env->spr[SPR_AMOR] = 0xffffffffffffffffull;
|
||||
}
|
||||
|
||||
void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip, target_ulong r3)
|
||||
{
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
env->nip = nip;
|
||||
env->gpr[3] = r3;
|
||||
CPU(cpu)->halted = 0;
|
||||
/* Enable Power-saving mode Exit Cause exceptions */
|
||||
ppc_store_lpcr(cpu, env->spr[SPR_LPCR] | pcc->lpcr_pm);
|
||||
}
|
||||
|
||||
static void spapr_cpu_destroy(PowerPCCPU *cpu)
|
||||
@ -65,8 +96,8 @@ static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
|
||||
/* Set time-base frequency to 512 MHz */
|
||||
cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);
|
||||
|
||||
/* Enable PAPR mode in TCG or KVM */
|
||||
cpu_ppc_set_papr(cpu, PPC_VIRTUAL_HYPERVISOR(spapr));
|
||||
cpu_ppc_set_vhyp(cpu, PPC_VIRTUAL_HYPERVISOR(spapr));
|
||||
kvmppc_set_papr(cpu);
|
||||
|
||||
qemu_register_reset(spapr_cpu_reset, cpu);
|
||||
spapr_cpu_reset(cpu);
|
||||
|
@ -15,32 +15,35 @@
|
||||
#include "hw/ppc/spapr_ovec.h"
|
||||
#include "mmu-book3s-v3.h"
|
||||
|
||||
struct SPRSyncState {
|
||||
int spr;
|
||||
struct LPCRSyncState {
|
||||
target_ulong value;
|
||||
target_ulong mask;
|
||||
};
|
||||
|
||||
static void do_spr_sync(CPUState *cs, run_on_cpu_data arg)
|
||||
static void do_lpcr_sync(CPUState *cs, run_on_cpu_data arg)
|
||||
{
|
||||
struct SPRSyncState *s = arg.host_ptr;
|
||||
struct LPCRSyncState *s = arg.host_ptr;
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
target_ulong lpcr;
|
||||
|
||||
cpu_synchronize_state(cs);
|
||||
env->spr[s->spr] &= ~s->mask;
|
||||
env->spr[s->spr] |= s->value;
|
||||
lpcr = env->spr[SPR_LPCR];
|
||||
lpcr &= ~s->mask;
|
||||
lpcr |= s->value;
|
||||
ppc_store_lpcr(cpu, lpcr);
|
||||
}
|
||||
|
||||
static void set_spr(CPUState *cs, int spr, target_ulong value,
|
||||
target_ulong mask)
|
||||
static void set_all_lpcrs(target_ulong value, target_ulong mask)
|
||||
{
|
||||
struct SPRSyncState s = {
|
||||
.spr = spr,
|
||||
CPUState *cs;
|
||||
struct LPCRSyncState s = {
|
||||
.value = value,
|
||||
.mask = mask
|
||||
};
|
||||
run_on_cpu(cs, do_spr_sync, RUN_ON_CPU_HOST_PTR(&s));
|
||||
CPU_FOREACH(cs) {
|
||||
run_on_cpu(cs, do_lpcr_sync, RUN_ON_CPU_HOST_PTR(&s));
|
||||
}
|
||||
}
|
||||
|
||||
static bool has_spr(PowerPCCPU *cpu, int spr)
|
||||
@ -1235,8 +1238,6 @@ static target_ulong h_set_mode_resource_le(PowerPCCPU *cpu,
|
||||
target_ulong value1,
|
||||
target_ulong value2)
|
||||
{
|
||||
CPUState *cs;
|
||||
|
||||
if (value1) {
|
||||
return H_P3;
|
||||
}
|
||||
@ -1246,16 +1247,12 @@ static target_ulong h_set_mode_resource_le(PowerPCCPU *cpu,
|
||||
|
||||
switch (mflags) {
|
||||
case H_SET_MODE_ENDIAN_BIG:
|
||||
CPU_FOREACH(cs) {
|
||||
set_spr(cs, SPR_LPCR, 0, LPCR_ILE);
|
||||
}
|
||||
set_all_lpcrs(0, LPCR_ILE);
|
||||
spapr_pci_switch_vga(true);
|
||||
return H_SUCCESS;
|
||||
|
||||
case H_SET_MODE_ENDIAN_LITTLE:
|
||||
CPU_FOREACH(cs) {
|
||||
set_spr(cs, SPR_LPCR, LPCR_ILE, LPCR_ILE);
|
||||
}
|
||||
set_all_lpcrs(LPCR_ILE, LPCR_ILE);
|
||||
spapr_pci_switch_vga(false);
|
||||
return H_SUCCESS;
|
||||
}
|
||||
@ -1268,7 +1265,6 @@ static target_ulong h_set_mode_resource_addr_trans_mode(PowerPCCPU *cpu,
|
||||
target_ulong value1,
|
||||
target_ulong value2)
|
||||
{
|
||||
CPUState *cs;
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
|
||||
|
||||
if (!(pcc->insns_flags2 & PPC2_ISA207S)) {
|
||||
@ -1285,9 +1281,7 @@ static target_ulong h_set_mode_resource_addr_trans_mode(PowerPCCPU *cpu,
|
||||
return H_UNSUPPORTED_FLAG;
|
||||
}
|
||||
|
||||
CPU_FOREACH(cs) {
|
||||
set_spr(cs, SPR_LPCR, mflags << LPCR_AIL_SHIFT, LPCR_AIL);
|
||||
}
|
||||
set_all_lpcrs(mflags << LPCR_AIL_SHIFT, LPCR_AIL);
|
||||
|
||||
return H_SUCCESS;
|
||||
}
|
||||
@ -1364,7 +1358,6 @@ static target_ulong h_register_process_table(PowerPCCPU *cpu,
|
||||
target_ulong opcode,
|
||||
target_ulong *args)
|
||||
{
|
||||
CPUState *cs;
|
||||
target_ulong flags = args[0];
|
||||
target_ulong proc_tbl = args[1];
|
||||
target_ulong page_size = args[2];
|
||||
@ -1422,12 +1415,9 @@ static target_ulong h_register_process_table(PowerPCCPU *cpu,
|
||||
spapr->patb_entry = cproc; /* Save new process table */
|
||||
|
||||
/* Update the UPRT and GTSE bits in the LPCR for all cpus */
|
||||
CPU_FOREACH(cs) {
|
||||
set_spr(cs, SPR_LPCR,
|
||||
((flags & (FLAG_RADIX | FLAG_HASH_PROC_TBL)) ? LPCR_UPRT : 0) |
|
||||
((flags & FLAG_GTSE) ? LPCR_GTSE : 0),
|
||||
LPCR_UPRT | LPCR_GTSE);
|
||||
}
|
||||
set_all_lpcrs(((flags & (FLAG_RADIX | FLAG_HASH_PROC_TBL)) ? LPCR_UPRT : 0) |
|
||||
((flags & FLAG_GTSE) ? LPCR_GTSE : 0),
|
||||
LPCR_UPRT | LPCR_GTSE);
|
||||
|
||||
if (kvm_enabled()) {
|
||||
return kvmppc_configure_v3_mmu(cpu, flags & FLAG_RADIX,
|
||||
|
@ -32,11 +32,12 @@
|
||||
#include "hw/qdev.h"
|
||||
#include "sysemu/device_tree.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
|
||||
#include "hw/ppc/spapr.h"
|
||||
#include "hw/ppc/spapr_vio.h"
|
||||
#include "hw/ppc/spapr_rtas.h"
|
||||
#include "hw/ppc/spapr_cpu_core.h"
|
||||
#include "hw/ppc/ppc.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
@ -45,6 +46,8 @@
|
||||
#include "qemu/cutils.h"
|
||||
#include "trace.h"
|
||||
#include "hw/ppc/fdt.h"
|
||||
#include "target/ppc/mmu-hash64.h"
|
||||
#include "target/ppc/mmu-book3s-v3.h"
|
||||
|
||||
static void rtas_display_character(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
uint32_t token, uint32_t nargs,
|
||||
@ -119,34 +122,16 @@ static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the timebase offset of the CPU to that of first CPU.
|
||||
* This helps hotplugged CPU to have the correct timebase offset.
|
||||
*/
|
||||
static void spapr_cpu_update_tb_offset(PowerPCCPU *cpu)
|
||||
{
|
||||
PowerPCCPU *fcpu = POWERPC_CPU(first_cpu);
|
||||
|
||||
cpu->env.tb_env->tb_offset = fcpu->env.tb_env->tb_offset;
|
||||
}
|
||||
|
||||
static void spapr_cpu_set_endianness(PowerPCCPU *cpu)
|
||||
{
|
||||
PowerPCCPU *fcpu = POWERPC_CPU(first_cpu);
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(fcpu);
|
||||
|
||||
if (!pcc->interrupts_big_endian(fcpu)) {
|
||||
cpu->env.spr[SPR_LPCR] |= LPCR_ILE;
|
||||
}
|
||||
}
|
||||
|
||||
static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPRMachineState *spapr,
|
||||
static void rtas_start_cpu(PowerPCCPU *callcpu, sPAPRMachineState *spapr,
|
||||
uint32_t token, uint32_t nargs,
|
||||
target_ulong args,
|
||||
uint32_t nret, target_ulong rets)
|
||||
{
|
||||
target_ulong id, start, r3;
|
||||
PowerPCCPU *cpu;
|
||||
PowerPCCPU *newcpu;
|
||||
CPUPPCState *env;
|
||||
PowerPCCPUClass *pcc;
|
||||
target_ulong lpcr;
|
||||
|
||||
if (nargs != 3 || nret != 1) {
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
@ -157,41 +142,55 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPRMachineState *spapr,
|
||||
start = rtas_ld(args, 1);
|
||||
r3 = rtas_ld(args, 2);
|
||||
|
||||
cpu = spapr_find_cpu(id);
|
||||
if (cpu != NULL) {
|
||||
CPUState *cs = CPU(cpu);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
|
||||
|
||||
if (!cs->halted) {
|
||||
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
/* This will make sure qemu state is up to date with kvm, and
|
||||
* mark it dirty so our changes get flushed back before the
|
||||
* new cpu enters */
|
||||
kvm_cpu_synchronize_state(cs);
|
||||
|
||||
env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
|
||||
|
||||
/* Enable Power-saving mode Exit Cause exceptions for the new CPU */
|
||||
env->spr[SPR_LPCR] |= pcc->lpcr_pm;
|
||||
|
||||
env->nip = start;
|
||||
env->gpr[3] = r3;
|
||||
cs->halted = 0;
|
||||
spapr_cpu_set_endianness(cpu);
|
||||
spapr_cpu_update_tb_offset(cpu);
|
||||
|
||||
qemu_cpu_kick(cs);
|
||||
|
||||
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
|
||||
newcpu = spapr_find_cpu(id);
|
||||
if (!newcpu) {
|
||||
/* Didn't find a matching cpu */
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Didn't find a matching cpu */
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
env = &newcpu->env;
|
||||
pcc = POWERPC_CPU_GET_CLASS(newcpu);
|
||||
|
||||
if (!CPU(newcpu)->halted) {
|
||||
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
cpu_synchronize_state(CPU(newcpu));
|
||||
|
||||
env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
|
||||
|
||||
/* Enable Power-saving mode Exit Cause exceptions for the new CPU */
|
||||
lpcr = env->spr[SPR_LPCR];
|
||||
if (!pcc->interrupts_big_endian(callcpu)) {
|
||||
lpcr |= LPCR_ILE;
|
||||
}
|
||||
if (env->mmu_model == POWERPC_MMU_3_00) {
|
||||
/*
|
||||
* New cpus are expected to start in the same radix/hash mode
|
||||
* as the existing CPUs
|
||||
*/
|
||||
if (ppc64_radix_guest(callcpu)) {
|
||||
lpcr |= LPCR_UPRT | LPCR_GTSE;
|
||||
} else {
|
||||
lpcr &= ~(LPCR_UPRT | LPCR_GTSE);
|
||||
}
|
||||
}
|
||||
ppc_store_lpcr(newcpu, lpcr);
|
||||
|
||||
/*
|
||||
* Set the timebase offset of the new CPU to that of the invoking
|
||||
* CPU. This helps hotplugged CPU to have the correct timebase
|
||||
* offset.
|
||||
*/
|
||||
newcpu->env.tb_env->tb_offset = callcpu->env.tb_env->tb_offset;
|
||||
|
||||
spapr_cpu_set_entry_state(newcpu, start, r3);
|
||||
|
||||
qemu_cpu_kick(CPU(newcpu));
|
||||
|
||||
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
|
||||
}
|
||||
|
||||
static void rtas_stop_self(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
@ -203,13 +202,12 @@ static void rtas_stop_self(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
CPUPPCState *env = &cpu->env;
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
|
||||
|
||||
cs->halted = 1;
|
||||
qemu_cpu_kick(cs);
|
||||
|
||||
/* Disable Power-saving mode Exit Cause exceptions for the CPU.
|
||||
* This could deliver an interrupt on a dying CPU and crash the
|
||||
* guest */
|
||||
env->spr[SPR_LPCR] &= ~pcc->lpcr_pm;
|
||||
ppc_store_lpcr(cpu, env->spr[SPR_LPCR] & ~pcc->lpcr_pm);
|
||||
cs->halted = 1;
|
||||
qemu_cpu_kick(cs);
|
||||
}
|
||||
|
||||
static inline int sysparm_st(target_ulong addr, target_ulong len,
|
||||
|
@ -92,10 +92,6 @@ rs6000mc_size_read(uint32_t addr, uint32_t val) "read addr=0x%x val=0x%x"
|
||||
rs6000mc_size_write(uint32_t addr, uint32_t val) "write addr=0x%x val=0x%x"
|
||||
rs6000mc_parity_read(uint32_t addr, uint32_t val) "read addr=0x%x val=0x%x"
|
||||
|
||||
# hw/ppc/mac_newworld.c
|
||||
mac99_uninorth_write(uint64_t addr, uint64_t value) "addr=0x%" PRIx64 " val=0x%"PRIx64
|
||||
mac99_uninorth_read(uint64_t addr, uint64_t value) "addr=0x%" PRIx64 " val=0x%"PRIx64
|
||||
|
||||
# hw/ppc/ppc4xx_pci.c
|
||||
ppc4xx_pci_map_irq(int32_t devfn, int irq_num, int slot) "devfn 0x%x irq %d -> %d"
|
||||
ppc4xx_pci_set_irq(int irq_num) "PCI irq %d"
|
||||
|
@ -71,7 +71,6 @@ typedef struct NewWorldMacIOState {
|
||||
/*< public >*/
|
||||
|
||||
OpenPICState *pic;
|
||||
qemu_irq irqs[7];
|
||||
MACIOIDEState ide[2];
|
||||
} NewWorldMacIOState;
|
||||
|
||||
|
@ -53,4 +53,15 @@ typedef struct UNINHostState {
|
||||
MemoryRegion pci_io;
|
||||
} UNINHostState;
|
||||
|
||||
typedef struct UNINState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion mem;
|
||||
int token[1];
|
||||
} UNINState;
|
||||
|
||||
#define TYPE_UNI_NORTH "uni-north"
|
||||
#define UNI_NORTH(obj) \
|
||||
OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH)
|
||||
|
||||
#endif /* UNINORTH_H */
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "hw/qdev.h"
|
||||
#include "hw/cpu/core.h"
|
||||
#include "target/ppc/cpu-qom.h"
|
||||
#include "target/ppc/cpu.h"
|
||||
|
||||
#define TYPE_SPAPR_CPU_CORE "spapr-cpu-core"
|
||||
#define SPAPR_CPU_CORE(obj) \
|
||||
@ -38,4 +39,6 @@ typedef struct sPAPRCPUCoreClass {
|
||||
} sPAPRCPUCoreClass;
|
||||
|
||||
const char *spapr_get_cpu_core_type(const char *cpu_type);
|
||||
void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip, target_ulong r3);
|
||||
|
||||
#endif
|
||||
|
@ -1295,6 +1295,7 @@ int ppc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
|
||||
void ppc_store_ptcr(CPUPPCState *env, target_ulong value);
|
||||
#endif /* !defined(CONFIG_USER_ONLY) */
|
||||
void ppc_store_msr (CPUPPCState *env, target_ulong value);
|
||||
|
||||
@ -1331,7 +1332,7 @@ void store_booke_tcr (CPUPPCState *env, target_ulong val);
|
||||
void store_booke_tsr (CPUPPCState *env, target_ulong val);
|
||||
void ppc_tlb_invalidate_all (CPUPPCState *env);
|
||||
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr);
|
||||
void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp);
|
||||
void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -1585,6 +1586,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
|
||||
#define SPR_BOOKE_GIVOR13 (0x1BC)
|
||||
#define SPR_BOOKE_GIVOR14 (0x1BD)
|
||||
#define SPR_TIR (0x1BE)
|
||||
#define SPR_PTCR (0x1D0)
|
||||
#define SPR_BOOKE_SPEFSCR (0x200)
|
||||
#define SPR_Exxx_BBEAR (0x201)
|
||||
#define SPR_Exxx_BBTAR (0x202)
|
||||
|
@ -709,6 +709,7 @@ DEF_HELPER_FLAGS_1(load_601_rtcu, TCG_CALL_NO_RWG, tl, env)
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#if defined(TARGET_PPC64)
|
||||
DEF_HELPER_FLAGS_1(load_purr, TCG_CALL_NO_RWG, tl, env)
|
||||
DEF_HELPER_2(store_ptcr, void, env, tl)
|
||||
#endif
|
||||
DEF_HELPER_2(store_sdr1, void, env, tl)
|
||||
DEF_HELPER_2(store_pidr, void, env, tl)
|
||||
|
@ -72,7 +72,6 @@ static int cap_segstate;
|
||||
static int cap_booke_sregs;
|
||||
static int cap_ppc_smt;
|
||||
static int cap_ppc_smt_possible;
|
||||
static int cap_ppc_rma;
|
||||
static int cap_spapr_tce;
|
||||
static int cap_spapr_tce_64;
|
||||
static int cap_spapr_multitce;
|
||||
@ -133,7 +132,6 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
cap_segstate = kvm_check_extension(s, KVM_CAP_PPC_SEGSTATE);
|
||||
cap_booke_sregs = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_SREGS);
|
||||
cap_ppc_smt_possible = kvm_vm_check_extension(s, KVM_CAP_PPC_SMT_POSSIBLE);
|
||||
cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA);
|
||||
cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
|
||||
cap_spapr_tce_64 = kvm_check_extension(s, KVM_CAP_SPAPR_TCE_64);
|
||||
cap_spapr_multitce = kvm_check_extension(s, KVM_CAP_SPAPR_MULTITCE);
|
||||
@ -2090,6 +2088,10 @@ void kvmppc_set_papr(PowerPCCPU *cpu)
|
||||
CPUState *cs = CPU(cpu);
|
||||
int ret;
|
||||
|
||||
if (!kvm_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_PAPR, 0);
|
||||
if (ret) {
|
||||
error_report("This vCPU type or KVM version does not support PAPR");
|
||||
@ -2159,52 +2161,12 @@ void kvmppc_hint_smt_possible(Error **errp)
|
||||
|
||||
|
||||
#ifdef TARGET_PPC64
|
||||
off_t kvmppc_alloc_rma(void **rma)
|
||||
{
|
||||
off_t size;
|
||||
int fd;
|
||||
struct kvm_allocate_rma ret;
|
||||
|
||||
/* If cap_ppc_rma == 0, contiguous RMA allocation is not supported
|
||||
* if cap_ppc_rma == 1, contiguous RMA allocation is supported, but
|
||||
* not necessary on this hardware
|
||||
* if cap_ppc_rma == 2, contiguous RMA allocation is needed on this hardware
|
||||
*
|
||||
* FIXME: We should allow the user to force contiguous RMA
|
||||
* allocation in the cap_ppc_rma==1 case.
|
||||
*/
|
||||
if (cap_ppc_rma < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = kvm_vm_ioctl(kvm_state, KVM_ALLOCATE_RMA, &ret);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "KVM: Error on KVM_ALLOCATE_RMA: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
size = MIN(ret.rma_size, 256ul << 20);
|
||||
|
||||
*rma = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (*rma == MAP_FAILED) {
|
||||
fprintf(stderr, "KVM: Error mapping RMA: %s\n", strerror(errno));
|
||||
return -1;
|
||||
};
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
|
||||
{
|
||||
struct kvm_ppc_smmu_info info;
|
||||
long rampagesize, best_page_shift;
|
||||
int i;
|
||||
|
||||
if (cap_ppc_rma >= 2) {
|
||||
return current_size;
|
||||
}
|
||||
|
||||
/* Find the largest hardware supported page size that's less than
|
||||
* or equal to the (logical) backing page size of guest RAM */
|
||||
kvm_get_smmu_info(POWERPC_CPU(first_cpu), &info);
|
||||
|
@ -37,7 +37,6 @@ target_ulong kvmppc_configure_v3_mmu(PowerPCCPU *cpu,
|
||||
bool radix, bool gtse,
|
||||
uint64_t proc_tbl);
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
off_t kvmppc_alloc_rma(void **rma);
|
||||
bool kvmppc_spapr_use_multitce(void);
|
||||
int kvmppc_spapr_enable_inkernel_multitce(void);
|
||||
void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t page_shift,
|
||||
@ -188,11 +187,6 @@ static inline target_ulong kvmppc_configure_v3_mmu(PowerPCCPU *cpu,
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static inline off_t kvmppc_alloc_rma(void **rma)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool kvmppc_spapr_use_multitce(void)
|
||||
{
|
||||
return false;
|
||||
|
@ -212,6 +212,11 @@ static int cpu_pre_save(void *opaque)
|
||||
;
|
||||
cpu->mig_msr_mask = env->msr_mask & ~metamask;
|
||||
cpu->mig_insns_flags = env->insns_flags & insns_compat_mask;
|
||||
/* CPU models supported by old machines all have PPC_MEM_TLBIE,
|
||||
* so we set it unconditionally to allow backward migration from
|
||||
* a POWER9 host to a POWER8 host.
|
||||
*/
|
||||
cpu->mig_insns_flags |= PPC_MEM_TLBIE;
|
||||
cpu->mig_insns_flags2 = env->insns_flags2 & insns_compat_mask2;
|
||||
cpu->mig_nb_BATs = env->nb_BATs;
|
||||
}
|
||||
|
@ -88,6 +88,18 @@ void helper_store_sdr1(CPUPPCState *env, target_ulong val)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
void helper_store_ptcr(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
|
||||
if (env->spr[SPR_PTCR] != val) {
|
||||
ppc_store_ptcr(env, val);
|
||||
tlb_flush(CPU(cpu));
|
||||
}
|
||||
}
|
||||
#endif /* defined(TARGET_PPC64) */
|
||||
|
||||
void helper_store_pidr(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
|
@ -22,6 +22,12 @@
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
/*
|
||||
* Partition table definitions
|
||||
*/
|
||||
#define PTCR_PATB 0x0FFFFFFFFFFFF000ULL /* Partition Table Base */
|
||||
#define PTCR_PATS 0x000000000000001FULL /* Partition Table Size */
|
||||
|
||||
/* Partition Table Entry Fields */
|
||||
#define PATBE1_GR 0x8000000000000000
|
||||
|
||||
|
@ -942,7 +942,7 @@ void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong ptex,
|
||||
cpu->env.tlb_need_flush = TLB_NEED_GLOBAL_FLUSH | TLB_NEED_LOCAL_FLUSH;
|
||||
}
|
||||
|
||||
void ppc_hash64_update_rmls(PowerPCCPU *cpu)
|
||||
static void ppc_hash64_update_rmls(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
uint64_t lpcr = env->spr[SPR_LPCR];
|
||||
@ -977,7 +977,7 @@ void ppc_hash64_update_rmls(PowerPCCPU *cpu)
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_hash64_update_vrma(PowerPCCPU *cpu)
|
||||
static void ppc_hash64_update_vrma(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
const PPCHash64SegmentPageSizes *sps = NULL;
|
||||
@ -1028,9 +1028,9 @@ void ppc_hash64_update_vrma(PowerPCCPU *cpu)
|
||||
slb->sps = sps;
|
||||
}
|
||||
|
||||
void helper_store_lpcr(CPUPPCState *env, target_ulong val)
|
||||
void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
uint64_t lpcr = 0;
|
||||
|
||||
/* Filter out bits */
|
||||
@ -1096,6 +1096,13 @@ void helper_store_lpcr(CPUPPCState *env, target_ulong val)
|
||||
ppc_hash64_update_vrma(cpu);
|
||||
}
|
||||
|
||||
void helper_store_lpcr(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
|
||||
ppc_store_lpcr(cpu, val);
|
||||
}
|
||||
|
||||
void ppc_hash64_init(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
@ -17,8 +17,7 @@ void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu,
|
||||
target_ulong pte0, target_ulong pte1);
|
||||
unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu,
|
||||
uint64_t pte0, uint64_t pte1);
|
||||
void ppc_hash64_update_vrma(PowerPCCPU *cpu);
|
||||
void ppc_hash64_update_rmls(PowerPCCPU *cpu);
|
||||
void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val);
|
||||
void ppc_hash64_init(PowerPCCPU *cpu);
|
||||
void ppc_hash64_finalize(PowerPCCPU *cpu);
|
||||
#endif
|
||||
@ -102,6 +101,9 @@ void ppc_hash64_finalize(PowerPCCPU *cpu);
|
||||
|
||||
static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu)
|
||||
{
|
||||
if (cpu->vhyp) {
|
||||
return 0;
|
||||
}
|
||||
return cpu->env.spr[SPR_SDR1] & SDR_64_HTABORG;
|
||||
}
|
||||
|
||||
|
@ -2028,6 +2028,35 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
|
||||
env->spr[SPR_SDR1] = value;
|
||||
}
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
void ppc_store_ptcr(CPUPPCState *env, target_ulong value)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
target_ulong ptcr_mask = PTCR_PATB | PTCR_PATS;
|
||||
target_ulong patbsize = value & PTCR_PATS;
|
||||
|
||||
qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
|
||||
|
||||
assert(!cpu->vhyp);
|
||||
assert(env->mmu_model & POWERPC_MMU_3_00);
|
||||
|
||||
if (value & ~ptcr_mask) {
|
||||
error_report("Invalid bits 0x"TARGET_FMT_lx" set in PTCR",
|
||||
value & ~ptcr_mask);
|
||||
value &= ptcr_mask;
|
||||
}
|
||||
|
||||
if (patbsize > 24) {
|
||||
error_report("Invalid Partition Table size 0x" TARGET_FMT_lx
|
||||
" stored in PTCR", patbsize);
|
||||
return;
|
||||
}
|
||||
|
||||
env->spr[SPR_PTCR] = value;
|
||||
}
|
||||
|
||||
#endif /* defined(TARGET_PPC64) */
|
||||
|
||||
/* Segment registers load and store */
|
||||
target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num)
|
||||
{
|
||||
|
@ -7136,6 +7136,9 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
|
||||
if (env->spr_cb[SPR_SDR1].name) { /* SDR1 Exists */
|
||||
cpu_fprintf(f, " SDR1 " TARGET_FMT_lx " ", env->spr[SPR_SDR1]);
|
||||
}
|
||||
if (env->spr_cb[SPR_PTCR].name) { /* PTCR Exists */
|
||||
cpu_fprintf(f, " PTCR " TARGET_FMT_lx " ", env->spr[SPR_PTCR]);
|
||||
}
|
||||
cpu_fprintf(f, " DAR " TARGET_FMT_lx " DSISR " TARGET_FMT_lx "\n",
|
||||
env->spr[SPR_DAR], env->spr[SPR_DSISR]);
|
||||
break;
|
||||
|
@ -420,6 +420,11 @@ static void spr_write_hior(DisasContext *ctx, int sprn, int gprn)
|
||||
tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, excp_prefix));
|
||||
tcg_temp_free(t0);
|
||||
}
|
||||
static void spr_write_ptcr(DisasContext *ctx, int sprn, int gprn)
|
||||
{
|
||||
gen_helper_store_ptcr(cpu_env, cpu_gpr[gprn]);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -8167,6 +8172,18 @@ static void gen_spr_power8_rpr(CPUPPCState *env)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gen_spr_power9_mmu(CPUPPCState *env)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* Partition Table Control */
|
||||
spr_register_hv(env, SPR_PTCR, "PTCR",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_ptcr,
|
||||
0x00000000);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void init_proc_book3s_common(CPUPPCState *env)
|
||||
{
|
||||
gen_spr_ne_601(env);
|
||||
@ -8719,6 +8736,7 @@ static void init_proc_POWER9(CPUPPCState *env)
|
||||
gen_spr_power8_ic(env);
|
||||
gen_spr_power8_book4(env);
|
||||
gen_spr_power8_rpr(env);
|
||||
gen_spr_power9_mmu(env);
|
||||
|
||||
/* POWER9 Specific registers */
|
||||
spr_register_kvm(env, SPR_TIDR, "TIDR", NULL, NULL,
|
||||
@ -8864,13 +8882,9 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
|
||||
void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
|
||||
{
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
ppc_spr_t *lpcr = &env->spr_cb[SPR_LPCR];
|
||||
ppc_spr_t *amor = &env->spr_cb[SPR_AMOR];
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
cpu->vhyp = vhyp;
|
||||
|
||||
@ -8879,62 +8893,6 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
|
||||
* hypervisor mode itself
|
||||
*/
|
||||
env->msr_mask &= ~MSR_HVB;
|
||||
|
||||
/* Set emulated LPCR to not send interrupts to hypervisor. Note that
|
||||
* under KVM, the actual HW LPCR will be set differently by KVM itself,
|
||||
* the settings below ensure proper operations with TCG in absence of
|
||||
* a real hypervisor.
|
||||
*
|
||||
* Clearing VPM0 will also cause us to use RMOR in mmu-hash64.c for
|
||||
* real mode accesses, which thankfully defaults to 0 and isn't
|
||||
* accessible in guest mode.
|
||||
*/
|
||||
lpcr->default_value &= ~(LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV);
|
||||
lpcr->default_value |= LPCR_LPES0 | LPCR_LPES1;
|
||||
|
||||
/* Set RMLS to the max (ie, 16G) */
|
||||
lpcr->default_value &= ~LPCR_RMLS;
|
||||
lpcr->default_value |= 1ull << LPCR_RMLS_SHIFT;
|
||||
|
||||
if (env->mmu_model == POWERPC_MMU_3_00) {
|
||||
/* By default we choose legacy mode and switch to new hash or radix
|
||||
* when a register process table hcall is made. So disable process
|
||||
* tables and guest translation shootdown by default
|
||||
*
|
||||
* Hot-plugged CPUs inherit from the guest radix setting under
|
||||
* KVM but not under TCG. Update the default LPCR to keep new
|
||||
* CPUs in sync when radix is enabled.
|
||||
*/
|
||||
if (ppc64_radix_guest(cpu)) {
|
||||
lpcr->default_value |= LPCR_UPRT | LPCR_GTSE;
|
||||
} else {
|
||||
lpcr->default_value &= ~(LPCR_UPRT | LPCR_GTSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Only enable Power-saving mode Exit Cause exceptions on the boot
|
||||
* CPU. The RTAS command start-cpu will enable them on secondaries.
|
||||
*/
|
||||
if (cs == first_cpu) {
|
||||
lpcr->default_value |= pcc->lpcr_pm;
|
||||
}
|
||||
|
||||
/* We should be followed by a CPU reset but update the active value
|
||||
* just in case...
|
||||
*/
|
||||
env->spr[SPR_LPCR] = lpcr->default_value;
|
||||
|
||||
/* Set a full AMOR so guest can use the AMR as it sees fit */
|
||||
env->spr[SPR_AMOR] = amor->default_value = 0xffffffffffffffffull;
|
||||
|
||||
/* Update some env bits based on new LPCR value */
|
||||
ppc_hash64_update_rmls(cpu);
|
||||
ppc_hash64_update_vrma(cpu);
|
||||
|
||||
/* Tell KVM that we're in PAPR mode */
|
||||
if (kvm_enabled()) {
|
||||
kvmppc_set_papr(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !defined(CONFIG_USER_ONLY) */
|
||||
|
Loading…
Reference in New Issue
Block a user