mirror of https://gitee.com/openkylin/qemu.git
ppc patch queue 2021-01-06
First pull request for 2021, which has a bunch of things accumulated over the holidays. Includes: * A number of cleanups to sam460ex and ppc440 code from BALATON Zoltan * Several fixes for builds with --without-default-devices from Greg Kurz * Fixes for some DRC reset problems from Greg Kurz * QOM conversion of the PPC 4xx UIC devices from Peter Maydell * Some other assorted fixes and cleanups -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAl/1L38ACgkQbDjKyiDZ s5JmvQ//RddzvCrHewdtRys+XnLDsKbWng3rQGKh2rSpKMYM11ilmo7FOGoOMNwq aiZXm5z3t2lpSUTGZorVuPAnYKExzkuAQkPsFZ65uf9wfDhB2wg3BIr97GgZBF2S MvK9DlxhUNJI+1W8Y+hwj9xDMOX3oFqZp24g2i6EQPRcpqE7GtRpOzt6PdL15sNz KiJtIeyZ32uGDQaqNlWHJ/pBiYECEQTVpaZIztg2WLdfMICzgYMSCSZzbUrYXCii WPDJ9sr69sMFwX2oEAgmfmJeFaTOFMt/xTOwFvi2ex4Rd1Rzqb9XToZ+ihOeOAFr c4a7fpZzx0ePYLIAfOAZ2exV8Nh04dWjRyr2ykgo1ik3DaJ1Ck80O7jYyPQN1Dir wKpWW59a3pjdABa/ZAoMoFwJh1zPAwGuiN4Higy87Ux8X+JOlTzzkP9ja9v2fgRC DNb8VYvehUbY6bbHkqs57JcVyYLX56yphfq6Pr2D3DE6y1Ekph2G2vR8YXnqbRmY Pw5VJ9q1SdYypGVZdMmIXseM7XerFA9YlIfIAQ7DiEW5wH9sx5QjDxlSt07l56J0 TlK6m9Fgc3koLLtVqDlK0NPx39xqVa1JUkrvPeWNKqn1FG/0tfPU6oPVjdQx3ouk X2cv4A99MJsWSoyUMCH5r5+CHdMCscILOSOZ6OiWAHMEdqCxH0Q= =7Eiy -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/dg-gitlab/tags/ppc-for-6.0-20210106' into staging ppc patch queue 2021-01-06 First pull request for 2021, which has a bunch of things accumulated over the holidays. Includes: * A number of cleanups to sam460ex and ppc440 code from BALATON Zoltan * Several fixes for builds with --without-default-devices from Greg Kurz * Fixes for some DRC reset problems from Greg Kurz * QOM conversion of the PPC 4xx UIC devices from Peter Maydell * Some other assorted fixes and cleanups # gpg: Signature made Wed 06 Jan 2021 03:33:19 GMT # gpg: using RSA key 75F46586AE61A66CC44E87DC6C38CACA20D9B392 # gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" [full] # gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" [full] # gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" [full] # gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" [unknown] # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dg-gitlab/tags/ppc-for-6.0-20210106: (22 commits) ppc440_pcix: Fix up pci config access ppc440_pcix: Fix register write trace event ppc440_pcix: Improve comment for IRQ mapping sam460ex: Remove FDT_PPC dependency from KConfig ppc4xx: Move common dependency on serial to common option pnv: Fix reverse dependency on PCI express root ports ppc: Simplify reverse dependencies of POWERNV and PSERIES on XICS and XIVE ppc: Fix build with --without-default-devices spapr: Add drc_ prefix to the DRC realize and unrealize functions spapr: Use spapr_drc_reset_all() at machine reset spapr: Introduce spapr_drc_reset_all() spapr: Fix reset of transient DR connectors spapr: Call spapr_drc_reset() for all DRCs at CAS spapr: Fix buffer overflow in spapr_numa_associativity_init() spapr: Allow memory unplug to always succeed spapr: Fix DR properties of the root node spapr/xive: Make spapr_xive_pic_print_info() static spapr: DRC lookup cannot fail hw/ppc/ppc440_bamboo: Drop use of ppcuic_init() hw/ppc/virtex_ml507: Drop use of ppcuic_init() ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
7a5fd9343d
|
@ -1683,6 +1683,8 @@ F: hw/ppc/ppc4*.c
|
|||
F: hw/i2c/ppc4xx_i2c.c
|
||||
F: include/hw/ppc/ppc4xx.h
|
||||
F: include/hw/i2c/ppc4xx_i2c.h
|
||||
F: hw/intc/ppc-uic.c
|
||||
F: include/hw/intc/ppc-uic.h
|
||||
|
||||
Character devices
|
||||
M: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
|
|
|
@ -30,23 +30,11 @@ config ARM_GIC_KVM
|
|||
default y
|
||||
depends on ARM_GIC && KVM
|
||||
|
||||
config OPENPIC_KVM
|
||||
bool
|
||||
default y
|
||||
depends on OPENPIC && KVM
|
||||
|
||||
config XICS
|
||||
bool
|
||||
depends on POWERNV || PSERIES
|
||||
|
||||
config XICS_SPAPR
|
||||
config XIVE
|
||||
bool
|
||||
select XICS
|
||||
|
||||
config XICS_KVM
|
||||
bool
|
||||
default y
|
||||
depends on XICS && KVM
|
||||
|
||||
config ALLWINNER_A10_PIC
|
||||
bool
|
||||
|
@ -62,6 +50,9 @@ config S390_FLIC_KVM
|
|||
config OMPIC
|
||||
bool
|
||||
|
||||
config PPC_UIC
|
||||
bool
|
||||
|
||||
config RX_ICU
|
||||
bool
|
||||
|
||||
|
|
|
@ -39,8 +39,10 @@ specific_ss.add(when: 'CONFIG_LOONGSON_LIOINTC', if_true: files('loongson_lioint
|
|||
specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_gic.c'))
|
||||
specific_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_intc.c'))
|
||||
specific_ss.add(when: 'CONFIG_OMPIC', if_true: files('ompic.c'))
|
||||
specific_ss.add(when: 'CONFIG_OPENPIC_KVM', if_true: files('openpic_kvm.c'))
|
||||
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_OPENPIC'],
|
||||
if_true: files('openpic_kvm.c'))
|
||||
specific_ss.add(when: 'CONFIG_POWERNV', if_true: files('xics_pnv.c', 'pnv_xive.c'))
|
||||
specific_ss.add(when: 'CONFIG_PPC_UIC', if_true: files('ppc-uic.c'))
|
||||
specific_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_ic.c', 'bcm2836_control.c'))
|
||||
specific_ss.add(when: 'CONFIG_RX_ICU', if_true: files('rx_icu.c'))
|
||||
specific_ss.add(when: 'CONFIG_S390_FLIC', if_true: files('s390_flic.c'))
|
||||
|
@ -49,8 +51,9 @@ specific_ss.add(when: 'CONFIG_SH4', if_true: files('sh_intc.c'))
|
|||
specific_ss.add(when: 'CONFIG_SIFIVE_CLINT', if_true: files('sifive_clint.c'))
|
||||
specific_ss.add(when: 'CONFIG_SIFIVE_PLIC', if_true: files('sifive_plic.c'))
|
||||
specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c'))
|
||||
specific_ss.add(when: 'CONFIG_XICS_KVM', if_true: files('xics_kvm.c'))
|
||||
specific_ss.add(when: 'CONFIG_XICS_SPAPR', if_true: files('xics_spapr.c'))
|
||||
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XICS'],
|
||||
if_true: files('xics_kvm.c'))
|
||||
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('xics_spapr.c', 'spapr_xive.c'))
|
||||
specific_ss.add(when: 'CONFIG_XIVE', if_true: files('xive.c'))
|
||||
specific_ss.add(when: 'CONFIG_XIVE_KVM', if_true: files('spapr_xive_kvm.c'))
|
||||
specific_ss.add(when: 'CONFIG_XIVE_SPAPR', if_true: files('spapr_xive.c'))
|
||||
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XIVE'],
|
||||
if_true: files('spapr_xive_kvm.c'))
|
||||
|
|
|
@ -0,0 +1,321 @@
|
|||
/*
|
||||
* "Universal" Interrupt Controller for PowerPPC 4xx embedded processors
|
||||
*
|
||||
* Copyright (c) 2007 Jocelyn Mayer
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "include/hw/intc/ppc-uic.h"
|
||||
#include "hw/irq.h"
|
||||
#include "cpu.h"
|
||||
#include "hw/ppc/ppc.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
enum {
|
||||
DCR_UICSR = 0x000,
|
||||
DCR_UICSRS = 0x001,
|
||||
DCR_UICER = 0x002,
|
||||
DCR_UICCR = 0x003,
|
||||
DCR_UICPR = 0x004,
|
||||
DCR_UICTR = 0x005,
|
||||
DCR_UICMSR = 0x006,
|
||||
DCR_UICVR = 0x007,
|
||||
DCR_UICVCR = 0x008,
|
||||
DCR_UICMAX = 0x009,
|
||||
};
|
||||
|
||||
/*#define DEBUG_UIC*/
|
||||
|
||||
#ifdef DEBUG_UIC
|
||||
# define LOG_UIC(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
|
||||
#else
|
||||
# define LOG_UIC(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
static void ppcuic_trigger_irq(PPCUIC *uic)
|
||||
{
|
||||
uint32_t ir, cr;
|
||||
int start, end, inc, i;
|
||||
|
||||
/* Trigger interrupt if any is pending */
|
||||
ir = uic->uicsr & uic->uicer & (~uic->uiccr);
|
||||
cr = uic->uicsr & uic->uicer & uic->uiccr;
|
||||
LOG_UIC("%s: uicsr %08" PRIx32 " uicer %08" PRIx32
|
||||
" uiccr %08" PRIx32 "\n"
|
||||
" %08" PRIx32 " ir %08" PRIx32 " cr %08" PRIx32 "\n",
|
||||
__func__, uic->uicsr, uic->uicer, uic->uiccr,
|
||||
uic->uicsr & uic->uicer, ir, cr);
|
||||
if (ir != 0x0000000) {
|
||||
LOG_UIC("Raise UIC interrupt\n");
|
||||
qemu_irq_raise(uic->output_int);
|
||||
} else {
|
||||
LOG_UIC("Lower UIC interrupt\n");
|
||||
qemu_irq_lower(uic->output_int);
|
||||
}
|
||||
/* Trigger critical interrupt if any is pending and update vector */
|
||||
if (cr != 0x0000000) {
|
||||
qemu_irq_raise(uic->output_cint);
|
||||
if (uic->use_vectors) {
|
||||
/* Compute critical IRQ vector */
|
||||
if (uic->uicvcr & 1) {
|
||||
start = 31;
|
||||
end = 0;
|
||||
inc = -1;
|
||||
} else {
|
||||
start = 0;
|
||||
end = 31;
|
||||
inc = 1;
|
||||
}
|
||||
uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
|
||||
for (i = start; i <= end; i += inc) {
|
||||
if (cr & (1 << i)) {
|
||||
uic->uicvr += (i - start) * 512 * inc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_UIC("Raise UIC critical interrupt - "
|
||||
"vector %08" PRIx32 "\n", uic->uicvr);
|
||||
} else {
|
||||
LOG_UIC("Lower UIC critical interrupt\n");
|
||||
qemu_irq_lower(uic->output_cint);
|
||||
uic->uicvr = 0x00000000;
|
||||
}
|
||||
}
|
||||
|
||||
static void ppcuic_set_irq(void *opaque, int irq_num, int level)
|
||||
{
|
||||
PPCUIC *uic;
|
||||
uint32_t mask, sr;
|
||||
|
||||
uic = opaque;
|
||||
mask = 1U << (31 - irq_num);
|
||||
LOG_UIC("%s: irq %d level %d uicsr %08" PRIx32
|
||||
" mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
|
||||
__func__, irq_num, level,
|
||||
uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
|
||||
if (irq_num < 0 || irq_num > 31) {
|
||||
return;
|
||||
}
|
||||
sr = uic->uicsr;
|
||||
|
||||
/* Update status register */
|
||||
if (uic->uictr & mask) {
|
||||
/* Edge sensitive interrupt */
|
||||
if (level == 1) {
|
||||
uic->uicsr |= mask;
|
||||
}
|
||||
} else {
|
||||
/* Level sensitive interrupt */
|
||||
if (level == 1) {
|
||||
uic->uicsr |= mask;
|
||||
uic->level |= mask;
|
||||
} else {
|
||||
uic->uicsr &= ~mask;
|
||||
uic->level &= ~mask;
|
||||
}
|
||||
}
|
||||
LOG_UIC("%s: irq %d level %d sr %" PRIx32 " => "
|
||||
"%08" PRIx32 "\n", __func__, irq_num, level, uic->uicsr, sr);
|
||||
if (sr != uic->uicsr) {
|
||||
ppcuic_trigger_irq(uic);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t dcr_read_uic(void *opaque, int dcrn)
|
||||
{
|
||||
PPCUIC *uic;
|
||||
uint32_t ret;
|
||||
|
||||
uic = opaque;
|
||||
dcrn -= uic->dcr_base;
|
||||
switch (dcrn) {
|
||||
case DCR_UICSR:
|
||||
case DCR_UICSRS:
|
||||
ret = uic->uicsr;
|
||||
break;
|
||||
case DCR_UICER:
|
||||
ret = uic->uicer;
|
||||
break;
|
||||
case DCR_UICCR:
|
||||
ret = uic->uiccr;
|
||||
break;
|
||||
case DCR_UICPR:
|
||||
ret = uic->uicpr;
|
||||
break;
|
||||
case DCR_UICTR:
|
||||
ret = uic->uictr;
|
||||
break;
|
||||
case DCR_UICMSR:
|
||||
ret = uic->uicsr & uic->uicer;
|
||||
break;
|
||||
case DCR_UICVR:
|
||||
if (!uic->use_vectors) {
|
||||
goto no_read;
|
||||
}
|
||||
ret = uic->uicvr;
|
||||
break;
|
||||
case DCR_UICVCR:
|
||||
if (!uic->use_vectors) {
|
||||
goto no_read;
|
||||
}
|
||||
ret = uic->uicvcr;
|
||||
break;
|
||||
default:
|
||||
no_read:
|
||||
ret = 0x00000000;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dcr_write_uic(void *opaque, int dcrn, uint32_t val)
|
||||
{
|
||||
PPCUIC *uic;
|
||||
|
||||
uic = opaque;
|
||||
dcrn -= uic->dcr_base;
|
||||
LOG_UIC("%s: dcr %d val 0x%x\n", __func__, dcrn, val);
|
||||
switch (dcrn) {
|
||||
case DCR_UICSR:
|
||||
uic->uicsr &= ~val;
|
||||
uic->uicsr |= uic->level;
|
||||
ppcuic_trigger_irq(uic);
|
||||
break;
|
||||
case DCR_UICSRS:
|
||||
uic->uicsr |= val;
|
||||
ppcuic_trigger_irq(uic);
|
||||
break;
|
||||
case DCR_UICER:
|
||||
uic->uicer = val;
|
||||
ppcuic_trigger_irq(uic);
|
||||
break;
|
||||
case DCR_UICCR:
|
||||
uic->uiccr = val;
|
||||
ppcuic_trigger_irq(uic);
|
||||
break;
|
||||
case DCR_UICPR:
|
||||
uic->uicpr = val;
|
||||
break;
|
||||
case DCR_UICTR:
|
||||
uic->uictr = val;
|
||||
ppcuic_trigger_irq(uic);
|
||||
break;
|
||||
case DCR_UICMSR:
|
||||
break;
|
||||
case DCR_UICVR:
|
||||
break;
|
||||
case DCR_UICVCR:
|
||||
uic->uicvcr = val & 0xFFFFFFFD;
|
||||
ppcuic_trigger_irq(uic);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ppc_uic_reset(DeviceState *dev)
|
||||
{
|
||||
PPCUIC *uic = PPC_UIC(dev);
|
||||
|
||||
uic->uiccr = 0x00000000;
|
||||
uic->uicer = 0x00000000;
|
||||
uic->uicpr = 0x00000000;
|
||||
uic->uicsr = 0x00000000;
|
||||
uic->uictr = 0x00000000;
|
||||
if (uic->use_vectors) {
|
||||
uic->uicvcr = 0x00000000;
|
||||
uic->uicvr = 0x0000000;
|
||||
}
|
||||
}
|
||||
|
||||
static void ppc_uic_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PPCUIC *uic = PPC_UIC(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
PowerPCCPU *cpu;
|
||||
int i;
|
||||
|
||||
if (!uic->cpu) {
|
||||
/* This is a programming error in the code using this device */
|
||||
error_setg(errp, "ppc-uic 'cpu' link property was not set");
|
||||
return;
|
||||
}
|
||||
|
||||
cpu = POWERPC_CPU(uic->cpu);
|
||||
for (i = 0; i < DCR_UICMAX; i++) {
|
||||
ppc_dcr_register(&cpu->env, uic->dcr_base + i, uic,
|
||||
&dcr_read_uic, &dcr_write_uic);
|
||||
}
|
||||
|
||||
sysbus_init_irq(sbd, &uic->output_int);
|
||||
sysbus_init_irq(sbd, &uic->output_cint);
|
||||
qdev_init_gpio_in(dev, ppcuic_set_irq, UIC_MAX_IRQ);
|
||||
}
|
||||
|
||||
static Property ppc_uic_properties[] = {
|
||||
DEFINE_PROP_LINK("cpu", PPCUIC, cpu, TYPE_CPU, CPUState *),
|
||||
DEFINE_PROP_UINT32("dcr-base", PPCUIC, dcr_base, 0x30),
|
||||
DEFINE_PROP_BOOL("use-vectors", PPCUIC, use_vectors, true),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
static const VMStateDescription ppc_uic_vmstate = {
|
||||
.name = "ppc-uic",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(level, PPCUIC),
|
||||
VMSTATE_UINT32(uicsr, PPCUIC),
|
||||
VMSTATE_UINT32(uicer, PPCUIC),
|
||||
VMSTATE_UINT32(uiccr, PPCUIC),
|
||||
VMSTATE_UINT32(uicpr, PPCUIC),
|
||||
VMSTATE_UINT32(uictr, PPCUIC),
|
||||
VMSTATE_UINT32(uicvcr, PPCUIC),
|
||||
VMSTATE_UINT32(uicvr, PPCUIC),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
};
|
||||
|
||||
static void ppc_uic_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->reset = ppc_uic_reset;
|
||||
dc->realize = ppc_uic_realize;
|
||||
dc->vmsd = &ppc_uic_vmstate;
|
||||
device_class_set_props(dc, ppc_uic_properties);
|
||||
}
|
||||
|
||||
static const TypeInfo ppc_uic_info = {
|
||||
.name = TYPE_PPC_UIC,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(PPCUIC),
|
||||
.class_init = ppc_uic_class_init,
|
||||
};
|
||||
|
||||
static void ppc_uic_register_types(void)
|
||||
{
|
||||
type_register_static(&ppc_uic_info);
|
||||
}
|
||||
|
||||
type_init(ppc_uic_register_types);
|
|
@ -156,7 +156,7 @@ static void spapr_xive_end_pic_print_info(SpaprXive *xive, XiveEND *end,
|
|||
#define spapr_xive_in_kernel(xive) \
|
||||
(kvm_irqchip_in_kernel() && (xive)->fd != -1)
|
||||
|
||||
void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon)
|
||||
static void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon)
|
||||
{
|
||||
XiveSource *xsrc = &xive->source;
|
||||
int i;
|
||||
|
|
|
@ -60,3 +60,8 @@ config PCI_BONITO
|
|||
select PCI
|
||||
select UNIMP
|
||||
bool
|
||||
|
||||
config PCI_POWERNV
|
||||
select PCI_EXPRESS
|
||||
select MSI_NONBROKEN
|
||||
select PCIE_PORT
|
||||
|
|
|
@ -23,7 +23,7 @@ pci_ss.add(when: 'CONFIG_VERSATILE_PCI', if_true: files('versatile.c'))
|
|||
|
||||
softmmu_ss.add_all(when: 'CONFIG_PCI', if_true: pci_ss)
|
||||
|
||||
specific_ss.add(when: 'CONFIG_POWERNV', if_true: files(
|
||||
specific_ss.add(when: 'CONFIG_PCI_POWERNV', if_true: files(
|
||||
'pnv_phb3.c',
|
||||
'pnv_phb3_msi.c',
|
||||
'pnv_phb3_pbcq.c',
|
||||
|
|
|
@ -7,8 +7,8 @@ config PSERIES
|
|||
select PCI
|
||||
select SPAPR_VSCSI
|
||||
select VFIO if LINUX # needed by spapr_pci_vfio.c
|
||||
select XICS_SPAPR
|
||||
select XIVE_SPAPR
|
||||
select XICS
|
||||
select XIVE
|
||||
select MSI_NONBROKEN
|
||||
select FDT_PPC
|
||||
select CHRP_NVRAM
|
||||
|
@ -29,15 +29,13 @@ config POWERNV
|
|||
select XICS
|
||||
select XIVE
|
||||
select FDT_PPC
|
||||
select PCI_EXPRESS
|
||||
select MSI_NONBROKEN
|
||||
select PCI_POWERNV
|
||||
|
||||
config PPC405
|
||||
bool
|
||||
select M48T59
|
||||
select PFLASH_CFI02
|
||||
select PPC4XX
|
||||
select SERIAL
|
||||
|
||||
config PPC440
|
||||
bool
|
||||
|
@ -46,13 +44,14 @@ config PPC440
|
|||
imply E1000_PCI
|
||||
select PCI_EXPRESS
|
||||
select PPC4XX
|
||||
select SERIAL
|
||||
select FDT_PPC
|
||||
|
||||
config PPC4XX
|
||||
bool
|
||||
select BITBANG_I2C
|
||||
select PCI
|
||||
select PPC_UIC
|
||||
select SERIAL
|
||||
|
||||
config SAM460EX
|
||||
bool
|
||||
|
@ -61,12 +60,10 @@ config SAM460EX
|
|||
select IDE_SII3112
|
||||
select M41T80
|
||||
select PPC440
|
||||
select SERIAL
|
||||
select SM501
|
||||
select SMBUS_EEPROM
|
||||
select USB_EHCI_SYSBUS
|
||||
select USB_OHCI
|
||||
select FDT_PPC
|
||||
|
||||
config PREP
|
||||
bool
|
||||
|
@ -123,26 +120,10 @@ config VIRTEX
|
|||
bool
|
||||
select PPC4XX
|
||||
select PFLASH_CFI01
|
||||
select SERIAL
|
||||
select XILINX
|
||||
select XILINX_ETHLITE
|
||||
select FDT_PPC
|
||||
|
||||
config XIVE
|
||||
bool
|
||||
depends on POWERNV || PSERIES
|
||||
|
||||
config XIVE_SPAPR
|
||||
bool
|
||||
default y
|
||||
depends on PSERIES
|
||||
select XIVE
|
||||
|
||||
config XIVE_KVM
|
||||
bool
|
||||
default y
|
||||
depends on XIVE_SPAPR && KVM
|
||||
|
||||
# Only used by 64-bit targets
|
||||
config FW_CFG_PPC
|
||||
bool
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/intc/ppc-uic.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
|
||||
|
||||
|
@ -168,13 +171,13 @@ static void bamboo_init(MachineState *machine)
|
|||
MemoryRegion *ram_memories = g_new(MemoryRegion, PPC440EP_SDRAM_NR_BANKS);
|
||||
hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS];
|
||||
hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS];
|
||||
qemu_irq *pic;
|
||||
qemu_irq *irqs;
|
||||
PCIBus *pcibus;
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
target_long initrd_size = 0;
|
||||
DeviceState *dev;
|
||||
DeviceState *uicdev;
|
||||
SysBusDevice *uicsbd;
|
||||
int success;
|
||||
int i;
|
||||
|
||||
|
@ -192,10 +195,17 @@ static void bamboo_init(MachineState *machine)
|
|||
ppc_dcr_init(env, NULL, NULL);
|
||||
|
||||
/* interrupt controller */
|
||||
irqs = g_new0(qemu_irq, PPCUIC_OUTPUT_NB);
|
||||
irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
|
||||
irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
|
||||
pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
|
||||
uicdev = qdev_new(TYPE_PPC_UIC);
|
||||
uicsbd = SYS_BUS_DEVICE(uicdev);
|
||||
|
||||
object_property_set_link(OBJECT(uicdev), "cpu", OBJECT(cpu),
|
||||
&error_fatal);
|
||||
sysbus_realize_and_unref(uicsbd, &error_fatal);
|
||||
|
||||
sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_INT,
|
||||
((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT]);
|
||||
sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_CINT,
|
||||
((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT]);
|
||||
|
||||
/* SDRAM controller */
|
||||
memset(ram_bases, 0, sizeof(ram_bases));
|
||||
|
@ -203,14 +213,18 @@ static void bamboo_init(MachineState *machine)
|
|||
ppc4xx_sdram_banks(machine->ram, PPC440EP_SDRAM_NR_BANKS, ram_memories,
|
||||
ram_bases, ram_sizes, ppc440ep_sdram_bank_sizes);
|
||||
/* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
|
||||
ppc4xx_sdram_init(env, pic[14], PPC440EP_SDRAM_NR_BANKS, ram_memories,
|
||||
ppc4xx_sdram_init(env,
|
||||
qdev_get_gpio_in(uicdev, 14),
|
||||
PPC440EP_SDRAM_NR_BANKS, ram_memories,
|
||||
ram_bases, ram_sizes, 1);
|
||||
|
||||
/* PCI */
|
||||
dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE,
|
||||
PPC440EP_PCI_CONFIG,
|
||||
pic[pci_irq_nrs[0]], pic[pci_irq_nrs[1]],
|
||||
pic[pci_irq_nrs[2]], pic[pci_irq_nrs[3]],
|
||||
qdev_get_gpio_in(uicdev, pci_irq_nrs[0]),
|
||||
qdev_get_gpio_in(uicdev, pci_irq_nrs[1]),
|
||||
qdev_get_gpio_in(uicdev, pci_irq_nrs[2]),
|
||||
qdev_get_gpio_in(uicdev, pci_irq_nrs[3]),
|
||||
NULL);
|
||||
pcibus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
|
||||
if (!pcibus) {
|
||||
|
@ -223,12 +237,14 @@ static void bamboo_init(MachineState *machine)
|
|||
memory_region_add_subregion(get_system_memory(), PPC440EP_PCI_IO, isa);
|
||||
|
||||
if (serial_hd(0) != NULL) {
|
||||
serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
|
||||
serial_mm_init(address_space_mem, 0xef600300, 0,
|
||||
qdev_get_gpio_in(uicdev, 0),
|
||||
PPC_SERIAL_MM_BAUDBASE, serial_hd(0),
|
||||
DEVICE_BIG_ENDIAN);
|
||||
}
|
||||
if (serial_hd(1) != NULL) {
|
||||
serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
|
||||
serial_mm_init(address_space_mem, 0xef600400, 0,
|
||||
qdev_get_gpio_in(uicdev, 1),
|
||||
PPC_SERIAL_MM_BAUDBASE, serial_hd(1),
|
||||
DEVICE_BIG_ENDIAN);
|
||||
}
|
||||
|
|
|
@ -169,7 +169,7 @@ static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr,
|
|||
{
|
||||
struct PPC440PCIXState *s = opaque;
|
||||
|
||||
trace_ppc440_pcix_reg_read(addr, val);
|
||||
trace_ppc440_pcix_reg_write(addr, val, size);
|
||||
switch (addr) {
|
||||
case PCI_VENDOR_ID ... PCI_MAX_LAT:
|
||||
stl_le_p(s->dev->config + addr, val);
|
||||
|
@ -415,8 +415,15 @@ static void ppc440_pcix_reset(DeviceState *dev)
|
|||
s->sts = 0;
|
||||
}
|
||||
|
||||
/* All pins from each slot are tied to a single board IRQ.
|
||||
* This may need further refactoring for other boards. */
|
||||
/*
|
||||
* All four IRQ[ABCD] pins from all slots are tied to a single board
|
||||
* IRQ, so our mapping function here maps everything to IRQ 0.
|
||||
* The code in pci_change_irq_level() tracks the number of times
|
||||
* the mapped IRQ is asserted and deasserted, so if multiple devices
|
||||
* assert an IRQ at the same time the behaviour is correct.
|
||||
*
|
||||
* This may need further refactoring for boards that use multiple IRQ lines.
|
||||
*/
|
||||
static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num)
|
||||
{
|
||||
trace_ppc440_pcix_map_irq(pci_dev->devfn, irq_num, 0);
|
||||
|
@ -442,28 +449,35 @@ static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int devfn)
|
|||
return &s->bm_as;
|
||||
}
|
||||
|
||||
/* The default pci_host_data_{read,write} functions in pci/pci_host.c
|
||||
* deny access to registers without bit 31 set but our clients want
|
||||
* this to work so we have to override these here */
|
||||
static void pci_host_data_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned len)
|
||||
/*
|
||||
* Some guests on sam460ex write all kinds of garbage here such as
|
||||
* missing enable bit and low bits set and still expect this to work
|
||||
* (apparently it does on real hardware because these boot there) so
|
||||
* we have to override these ops here and fix it up
|
||||
*/
|
||||
static void pci_host_config_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned len)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
pci_data_write(s->bus, s->config_reg | (addr & 3), val, len);
|
||||
|
||||
if (addr != 0 || len != 4) {
|
||||
return;
|
||||
}
|
||||
s->config_reg = (val & 0xfffffffcULL) | (1UL << 31);
|
||||
}
|
||||
|
||||
static uint64_t pci_host_data_read(void *opaque,
|
||||
hwaddr addr, unsigned len)
|
||||
static uint64_t pci_host_config_read(void *opaque, hwaddr addr,
|
||||
unsigned len)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
uint32_t val;
|
||||
val = pci_data_read(s->bus, s->config_reg | (addr & 3), len);
|
||||
uint32_t val = s->config_reg;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
const MemoryRegionOps ppc440_pcix_host_data_ops = {
|
||||
.read = pci_host_data_read,
|
||||
.write = pci_host_data_write,
|
||||
const MemoryRegionOps ppc440_pcix_host_conf_ops = {
|
||||
.read = pci_host_config_read,
|
||||
.write = pci_host_config_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
|
@ -490,9 +504,9 @@ static void ppc440_pcix_realize(DeviceState *dev, Error **errp)
|
|||
pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s);
|
||||
|
||||
memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE);
|
||||
memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops,
|
||||
memory_region_init_io(&h->conf_mem, OBJECT(s), &ppc440_pcix_host_conf_ops,
|
||||
h, "pci-conf-idx", 4);
|
||||
memory_region_init_io(&h->data_mem, OBJECT(s), &ppc440_pcix_host_data_ops,
|
||||
memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops,
|
||||
h, "pci-conf-data", 4);
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s,
|
||||
"pci.reg", PPC440_REG_SIZE);
|
||||
|
|
|
@ -30,9 +30,12 @@
|
|||
#include "hw/ppc/ppc.h"
|
||||
#include "hw/ppc/ppc4xx.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/intc/ppc-uic.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "qemu/log.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
/*#define DEBUG_UIC*/
|
||||
|
||||
|
@ -76,245 +79,40 @@ PowerPCCPU *ppc4xx_init(const char *cpu_type,
|
|||
|
||||
/*****************************************************************************/
|
||||
/* "Universal" Interrupt controller */
|
||||
enum {
|
||||
DCR_UICSR = 0x000,
|
||||
DCR_UICSRS = 0x001,
|
||||
DCR_UICER = 0x002,
|
||||
DCR_UICCR = 0x003,
|
||||
DCR_UICPR = 0x004,
|
||||
DCR_UICTR = 0x005,
|
||||
DCR_UICMSR = 0x006,
|
||||
DCR_UICVR = 0x007,
|
||||
DCR_UICVCR = 0x008,
|
||||
DCR_UICMAX = 0x009,
|
||||
};
|
||||
|
||||
#define UIC_MAX_IRQ 32
|
||||
typedef struct ppcuic_t ppcuic_t;
|
||||
struct ppcuic_t {
|
||||
uint32_t dcr_base;
|
||||
int use_vectors;
|
||||
uint32_t level; /* Remembers the state of level-triggered interrupts. */
|
||||
uint32_t uicsr; /* Status register */
|
||||
uint32_t uicer; /* Enable register */
|
||||
uint32_t uiccr; /* Critical register */
|
||||
uint32_t uicpr; /* Polarity register */
|
||||
uint32_t uictr; /* Triggering register */
|
||||
uint32_t uicvcr; /* Vector configuration register */
|
||||
uint32_t uicvr;
|
||||
qemu_irq *irqs;
|
||||
};
|
||||
|
||||
static void ppcuic_trigger_irq (ppcuic_t *uic)
|
||||
{
|
||||
uint32_t ir, cr;
|
||||
int start, end, inc, i;
|
||||
|
||||
/* Trigger interrupt if any is pending */
|
||||
ir = uic->uicsr & uic->uicer & (~uic->uiccr);
|
||||
cr = uic->uicsr & uic->uicer & uic->uiccr;
|
||||
LOG_UIC("%s: uicsr %08" PRIx32 " uicer %08" PRIx32
|
||||
" uiccr %08" PRIx32 "\n"
|
||||
" %08" PRIx32 " ir %08" PRIx32 " cr %08" PRIx32 "\n",
|
||||
__func__, uic->uicsr, uic->uicer, uic->uiccr,
|
||||
uic->uicsr & uic->uicer, ir, cr);
|
||||
if (ir != 0x0000000) {
|
||||
LOG_UIC("Raise UIC interrupt\n");
|
||||
qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
|
||||
} else {
|
||||
LOG_UIC("Lower UIC interrupt\n");
|
||||
qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
|
||||
}
|
||||
/* Trigger critical interrupt if any is pending and update vector */
|
||||
if (cr != 0x0000000) {
|
||||
qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
|
||||
if (uic->use_vectors) {
|
||||
/* Compute critical IRQ vector */
|
||||
if (uic->uicvcr & 1) {
|
||||
start = 31;
|
||||
end = 0;
|
||||
inc = -1;
|
||||
} else {
|
||||
start = 0;
|
||||
end = 31;
|
||||
inc = 1;
|
||||
}
|
||||
uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
|
||||
for (i = start; i <= end; i += inc) {
|
||||
if (cr & (1 << i)) {
|
||||
uic->uicvr += (i - start) * 512 * inc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_UIC("Raise UIC critical interrupt - "
|
||||
"vector %08" PRIx32 "\n", uic->uicvr);
|
||||
} else {
|
||||
LOG_UIC("Lower UIC critical interrupt\n");
|
||||
qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
|
||||
uic->uicvr = 0x00000000;
|
||||
}
|
||||
}
|
||||
|
||||
static void ppcuic_set_irq (void *opaque, int irq_num, int level)
|
||||
{
|
||||
ppcuic_t *uic;
|
||||
uint32_t mask, sr;
|
||||
|
||||
uic = opaque;
|
||||
mask = 1U << (31-irq_num);
|
||||
LOG_UIC("%s: irq %d level %d uicsr %08" PRIx32
|
||||
" mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
|
||||
__func__, irq_num, level,
|
||||
uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
|
||||
if (irq_num < 0 || irq_num > 31)
|
||||
return;
|
||||
sr = uic->uicsr;
|
||||
|
||||
/* Update status register */
|
||||
if (uic->uictr & mask) {
|
||||
/* Edge sensitive interrupt */
|
||||
if (level == 1)
|
||||
uic->uicsr |= mask;
|
||||
} else {
|
||||
/* Level sensitive interrupt */
|
||||
if (level == 1) {
|
||||
uic->uicsr |= mask;
|
||||
uic->level |= mask;
|
||||
} else {
|
||||
uic->uicsr &= ~mask;
|
||||
uic->level &= ~mask;
|
||||
}
|
||||
}
|
||||
LOG_UIC("%s: irq %d level %d sr %" PRIx32 " => "
|
||||
"%08" PRIx32 "\n", __func__, irq_num, level, uic->uicsr, sr);
|
||||
if (sr != uic->uicsr)
|
||||
ppcuic_trigger_irq(uic);
|
||||
}
|
||||
|
||||
static uint32_t dcr_read_uic (void *opaque, int dcrn)
|
||||
{
|
||||
ppcuic_t *uic;
|
||||
uint32_t ret;
|
||||
|
||||
uic = opaque;
|
||||
dcrn -= uic->dcr_base;
|
||||
switch (dcrn) {
|
||||
case DCR_UICSR:
|
||||
case DCR_UICSRS:
|
||||
ret = uic->uicsr;
|
||||
break;
|
||||
case DCR_UICER:
|
||||
ret = uic->uicer;
|
||||
break;
|
||||
case DCR_UICCR:
|
||||
ret = uic->uiccr;
|
||||
break;
|
||||
case DCR_UICPR:
|
||||
ret = uic->uicpr;
|
||||
break;
|
||||
case DCR_UICTR:
|
||||
ret = uic->uictr;
|
||||
break;
|
||||
case DCR_UICMSR:
|
||||
ret = uic->uicsr & uic->uicer;
|
||||
break;
|
||||
case DCR_UICVR:
|
||||
if (!uic->use_vectors)
|
||||
goto no_read;
|
||||
ret = uic->uicvr;
|
||||
break;
|
||||
case DCR_UICVCR:
|
||||
if (!uic->use_vectors)
|
||||
goto no_read;
|
||||
ret = uic->uicvcr;
|
||||
break;
|
||||
default:
|
||||
no_read:
|
||||
ret = 0x00000000;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dcr_write_uic (void *opaque, int dcrn, uint32_t val)
|
||||
{
|
||||
ppcuic_t *uic;
|
||||
|
||||
uic = opaque;
|
||||
dcrn -= uic->dcr_base;
|
||||
LOG_UIC("%s: dcr %d val 0x%x\n", __func__, dcrn, val);
|
||||
switch (dcrn) {
|
||||
case DCR_UICSR:
|
||||
uic->uicsr &= ~val;
|
||||
uic->uicsr |= uic->level;
|
||||
ppcuic_trigger_irq(uic);
|
||||
break;
|
||||
case DCR_UICSRS:
|
||||
uic->uicsr |= val;
|
||||
ppcuic_trigger_irq(uic);
|
||||
break;
|
||||
case DCR_UICER:
|
||||
uic->uicer = val;
|
||||
ppcuic_trigger_irq(uic);
|
||||
break;
|
||||
case DCR_UICCR:
|
||||
uic->uiccr = val;
|
||||
ppcuic_trigger_irq(uic);
|
||||
break;
|
||||
case DCR_UICPR:
|
||||
uic->uicpr = val;
|
||||
break;
|
||||
case DCR_UICTR:
|
||||
uic->uictr = val;
|
||||
ppcuic_trigger_irq(uic);
|
||||
break;
|
||||
case DCR_UICMSR:
|
||||
break;
|
||||
case DCR_UICVR:
|
||||
break;
|
||||
case DCR_UICVCR:
|
||||
uic->uicvcr = val & 0xFFFFFFFD;
|
||||
ppcuic_trigger_irq(uic);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ppcuic_reset (void *opaque)
|
||||
{
|
||||
ppcuic_t *uic;
|
||||
|
||||
uic = opaque;
|
||||
uic->uiccr = 0x00000000;
|
||||
uic->uicer = 0x00000000;
|
||||
uic->uicpr = 0x00000000;
|
||||
uic->uicsr = 0x00000000;
|
||||
uic->uictr = 0x00000000;
|
||||
if (uic->use_vectors) {
|
||||
uic->uicvcr = 0x00000000;
|
||||
uic->uicvr = 0x0000000;
|
||||
}
|
||||
}
|
||||
|
||||
qemu_irq *ppcuic_init (CPUPPCState *env, qemu_irq *irqs,
|
||||
uint32_t dcr_base, int has_ssr, int has_vr)
|
||||
{
|
||||
ppcuic_t *uic;
|
||||
DeviceState *uicdev = qdev_new(TYPE_PPC_UIC);
|
||||
SysBusDevice *uicsbd = SYS_BUS_DEVICE(uicdev);
|
||||
qemu_irq *uic_irqs;
|
||||
int i;
|
||||
|
||||
uic = g_malloc0(sizeof(ppcuic_t));
|
||||
uic->dcr_base = dcr_base;
|
||||
uic->irqs = irqs;
|
||||
if (has_vr)
|
||||
uic->use_vectors = 1;
|
||||
for (i = 0; i < DCR_UICMAX; i++) {
|
||||
ppc_dcr_register(env, dcr_base + i, uic,
|
||||
&dcr_read_uic, &dcr_write_uic);
|
||||
}
|
||||
qemu_register_reset(ppcuic_reset, uic);
|
||||
qdev_prop_set_uint32(uicdev, "dcr-base", dcr_base);
|
||||
qdev_prop_set_bit(uicdev, "use-vectors", has_vr);
|
||||
object_property_set_link(OBJECT(uicdev), "cpu", OBJECT(env_cpu(env)),
|
||||
&error_fatal);
|
||||
sysbus_realize_and_unref(uicsbd, &error_fatal);
|
||||
|
||||
return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
|
||||
sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_INT, irqs[PPCUIC_OUTPUT_INT]);
|
||||
sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_CINT, irqs[PPCUIC_OUTPUT_CINT]);
|
||||
|
||||
/*
|
||||
* Return an allocated array of the UIC's input IRQ lines.
|
||||
* This is an ugly temporary API to retain compatibility with
|
||||
* the ppcuic_init() interface from the pre-QOM-conversion UIC.
|
||||
* None of the callers free this array, so it is leaked -- but
|
||||
* so was the array allocated by qemu_allocate_irqs() in the
|
||||
* old code.
|
||||
*
|
||||
* The callers should just instantiate the UIC and wire it up
|
||||
* themselves rather than passing qemu_irq* in and out of this function.
|
||||
*/
|
||||
uic_irqs = g_new0(qemu_irq, UIC_MAX_IRQ);
|
||||
for (i = 0; i < UIC_MAX_IRQ; i++) {
|
||||
uic_irqs[i] = qdev_get_gpio_in(uicdev, i);
|
||||
}
|
||||
return uic_irqs;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -1120,6 +1120,7 @@ void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space)
|
|||
MachineState *machine = MACHINE(spapr);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
|
||||
uint32_t root_drc_type_mask = 0;
|
||||
int ret;
|
||||
void *fdt;
|
||||
SpaprPhbState *phb;
|
||||
|
@ -1194,8 +1195,18 @@ void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space)
|
|||
|
||||
spapr_dt_cpus(fdt, spapr);
|
||||
|
||||
/* ibm,drc-indexes and friends */
|
||||
if (smc->dr_lmb_enabled) {
|
||||
_FDT(spapr_dt_drc(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB));
|
||||
root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_LMB;
|
||||
}
|
||||
if (smc->dr_phb_enabled) {
|
||||
root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_PHB;
|
||||
}
|
||||
if (mc->nvdimm_supported) {
|
||||
root_drc_type_mask |= SPAPR_DR_CONNECTOR_TYPE_PMEM;
|
||||
}
|
||||
if (root_drc_type_mask) {
|
||||
_FDT(spapr_dt_drc(fdt, 0, NULL, root_drc_type_mask));
|
||||
}
|
||||
|
||||
if (mc->has_hotpluggable_cpus) {
|
||||
|
@ -1233,14 +1244,6 @@ void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space)
|
|||
}
|
||||
}
|
||||
|
||||
if (smc->dr_phb_enabled) {
|
||||
ret = spapr_dt_drc(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_PHB);
|
||||
if (ret < 0) {
|
||||
error_report("Couldn't set up PHB DR device tree properties");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* NVDIMM devices */
|
||||
if (mc->nvdimm_supported) {
|
||||
spapr_dt_persistent_memory(spapr, fdt);
|
||||
|
@ -1563,19 +1566,6 @@ void spapr_setup_hpt(SpaprMachineState *spapr)
|
|||
}
|
||||
}
|
||||
|
||||
static int spapr_reset_drcs(Object *child, void *opaque)
|
||||
{
|
||||
SpaprDrc *drc =
|
||||
(SpaprDrc *) object_dynamic_cast(child,
|
||||
TYPE_SPAPR_DR_CONNECTOR);
|
||||
|
||||
if (drc) {
|
||||
spapr_drc_reset(drc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spapr_machine_reset(MachineState *machine)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(machine);
|
||||
|
@ -1630,7 +1620,7 @@ static void spapr_machine_reset(MachineState *machine)
|
|||
* will crash QEMU if the DIMM holding the vring goes away). To avoid such
|
||||
* situations, we reset DRCs after all devices have been reset.
|
||||
*/
|
||||
object_child_foreach_recursive(object_get_root(), spapr_reset_drcs, NULL);
|
||||
spapr_drc_reset_all(spapr);
|
||||
|
||||
spapr_clear_pending_events(spapr);
|
||||
|
||||
|
@ -3437,6 +3427,7 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
|
|||
if (dedicated_hp_event_source) {
|
||||
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
|
||||
addr_start / SPAPR_MEMORY_BLOCK_SIZE);
|
||||
g_assert(drc);
|
||||
spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB,
|
||||
nr_lmbs,
|
||||
spapr_drc_index(drc));
|
||||
|
@ -3677,6 +3668,7 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
|
|||
|
||||
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
|
||||
addr_start / SPAPR_MEMORY_BLOCK_SIZE);
|
||||
g_assert(drc);
|
||||
spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB,
|
||||
nr_lmbs, spapr_drc_index(drc));
|
||||
}
|
||||
|
@ -4064,7 +4056,8 @@ static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
|
|||
SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
||||
if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) {
|
||||
if (!smc->pre_6_0_memory_unplug ||
|
||||
spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) {
|
||||
spapr_memory_unplug_request(hotplug_dev, dev, errp);
|
||||
} else {
|
||||
/* NOTE: this means there is a window after guest reset, prior to
|
||||
|
@ -4550,8 +4543,11 @@ DEFINE_SPAPR_MACHINE(6_0, "6.0", true);
|
|||
*/
|
||||
static void spapr_machine_5_2_class_options(MachineClass *mc)
|
||||
{
|
||||
SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||
|
||||
spapr_machine_6_0_class_options(mc);
|
||||
compat_props_add(mc->compat_props, hw_compat_5_2, hw_compat_5_2_len);
|
||||
smc->pre_6_0_memory_unplug = true;
|
||||
}
|
||||
|
||||
DEFINE_SPAPR_MACHINE(5_2, "5.2", false);
|
||||
|
|
|
@ -417,9 +417,10 @@ void spapr_drc_detach(SpaprDrc *drc)
|
|||
spapr_drc_release(drc);
|
||||
}
|
||||
|
||||
void spapr_drc_reset(SpaprDrc *drc)
|
||||
bool spapr_drc_reset(SpaprDrc *drc)
|
||||
{
|
||||
SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
||||
bool unplug_completed = false;
|
||||
|
||||
trace_spapr_drc_reset(spapr_drc_index(drc));
|
||||
|
||||
|
@ -428,6 +429,7 @@ void spapr_drc_reset(SpaprDrc *drc)
|
|||
*/
|
||||
if (drc->unplug_requested) {
|
||||
spapr_drc_release(drc);
|
||||
unplug_completed = true;
|
||||
}
|
||||
|
||||
if (drc->dev) {
|
||||
|
@ -444,6 +446,8 @@ void spapr_drc_reset(SpaprDrc *drc)
|
|||
drc->ccs_offset = -1;
|
||||
drc->ccs_depth = -1;
|
||||
}
|
||||
|
||||
return unplug_completed;
|
||||
}
|
||||
|
||||
static bool spapr_drc_unplug_requested_needed(void *opaque)
|
||||
|
@ -462,8 +466,9 @@ static const VMStateDescription vmstate_spapr_drc_unplug_requested = {
|
|||
}
|
||||
};
|
||||
|
||||
bool spapr_drc_transient(SpaprDrc *drc)
|
||||
static bool spapr_drc_needed(void *opaque)
|
||||
{
|
||||
SpaprDrc *drc = opaque;
|
||||
SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
||||
|
||||
/*
|
||||
|
@ -483,11 +488,6 @@ bool spapr_drc_transient(SpaprDrc *drc)
|
|||
spapr_drc_unplug_requested(drc);
|
||||
}
|
||||
|
||||
static bool spapr_drc_needed(void *opaque)
|
||||
{
|
||||
return spapr_drc_transient(opaque);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_spapr_drc = {
|
||||
.name = "spapr_drc",
|
||||
.version_id = 1,
|
||||
|
@ -503,7 +503,7 @@ static const VMStateDescription vmstate_spapr_drc = {
|
|||
}
|
||||
};
|
||||
|
||||
static void realize(DeviceState *d, Error **errp)
|
||||
static void drc_realize(DeviceState *d, Error **errp)
|
||||
{
|
||||
SpaprDrc *drc = SPAPR_DR_CONNECTOR(d);
|
||||
Object *root_container;
|
||||
|
@ -530,7 +530,7 @@ static void realize(DeviceState *d, Error **errp)
|
|||
trace_spapr_drc_realize_complete(spapr_drc_index(drc));
|
||||
}
|
||||
|
||||
static void unrealize(DeviceState *d)
|
||||
static void drc_unrealize(DeviceState *d)
|
||||
{
|
||||
SpaprDrc *drc = SPAPR_DR_CONNECTOR(d);
|
||||
Object *root_container;
|
||||
|
@ -579,8 +579,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
|
|||
{
|
||||
DeviceClass *dk = DEVICE_CLASS(k);
|
||||
|
||||
dk->realize = realize;
|
||||
dk->unrealize = unrealize;
|
||||
dk->realize = drc_realize;
|
||||
dk->unrealize = drc_unrealize;
|
||||
/*
|
||||
* Reason: DR connector needs to be wired to either the machine or to a
|
||||
* PHB in spapr_dr_connector_new().
|
||||
|
@ -628,7 +628,7 @@ static void realize_physical(DeviceState *d, Error **errp)
|
|||
SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(d);
|
||||
Error *local_err = NULL;
|
||||
|
||||
realize(d, &local_err);
|
||||
drc_realize(d, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
|
@ -644,7 +644,7 @@ static void unrealize_physical(DeviceState *d)
|
|||
{
|
||||
SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(d);
|
||||
|
||||
unrealize(d);
|
||||
drc_unrealize(d);
|
||||
vmstate_unregister(VMSTATE_IF(drcp), &vmstate_spapr_drc_physical, drcp);
|
||||
qemu_unregister_reset(drc_physical_reset, drcp);
|
||||
}
|
||||
|
@ -832,6 +832,12 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask)
|
|||
GString *drc_names, *drc_types;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* This should really be only called once per node since it overwrites
|
||||
* the OF properties if they already exist.
|
||||
*/
|
||||
g_assert(!fdt_get_property(fdt, offset, "ibm,drc-indexes", NULL));
|
||||
|
||||
/* the first entry of each properties is a 32-bit integer encoding
|
||||
* the number of elements in the array. we won't know this until
|
||||
* we complete the iteration through all the matching DRCs, but
|
||||
|
@ -943,6 +949,37 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
void spapr_drc_reset_all(SpaprMachineState *spapr)
|
||||
{
|
||||
Object *drc_container;
|
||||
ObjectProperty *prop;
|
||||
ObjectPropertyIterator iter;
|
||||
|
||||
drc_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
|
||||
restart:
|
||||
object_property_iter_init(&iter, drc_container);
|
||||
while ((prop = object_property_iter_next(&iter))) {
|
||||
SpaprDrc *drc;
|
||||
|
||||
if (!strstart(prop->type, "link<", NULL)) {
|
||||
continue;
|
||||
}
|
||||
drc = SPAPR_DR_CONNECTOR(object_property_get_link(drc_container,
|
||||
prop->name,
|
||||
&error_abort));
|
||||
|
||||
/*
|
||||
* This will complete any pending plug/unplug requests.
|
||||
* In case of a unplugged PHB or PCI bridge, this will
|
||||
* cause some DRCs to be destroyed and thus potentially
|
||||
* invalidate the iterator.
|
||||
*/
|
||||
if (spapr_drc_reset(drc)) {
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* RTAS calls
|
||||
*/
|
||||
|
|
|
@ -658,7 +658,8 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
|
|||
/* we should not be using count_indexed value unless the guest
|
||||
* supports dedicated hotplug event source
|
||||
*/
|
||||
g_assert(spapr_ovec_test(spapr->ov5_cas, OV5_HP_EVT));
|
||||
g_assert(!SPAPR_MACHINE_GET_CLASS(spapr)->pre_6_0_memory_unplug ||
|
||||
spapr_ovec_test(spapr->ov5_cas, OV5_HP_EVT));
|
||||
hp->drc_id.count_indexed.count =
|
||||
cpu_to_be32(drc_id->count_indexed.count);
|
||||
hp->drc_id.count_indexed.index =
|
||||
|
|
|
@ -1632,32 +1632,6 @@ static uint32_t cas_check_pvr(PowerPCCPU *cpu, uint32_t max_compat,
|
|||
return best_compat;
|
||||
}
|
||||
|
||||
static void spapr_handle_transient_dev_before_cas(SpaprMachineState *spapr)
|
||||
{
|
||||
Object *drc_container;
|
||||
ObjectProperty *prop;
|
||||
ObjectPropertyIterator iter;
|
||||
|
||||
drc_container = container_get(object_get_root(), "/dr-connector");
|
||||
object_property_iter_init(&iter, drc_container);
|
||||
while ((prop = object_property_iter_next(&iter))) {
|
||||
SpaprDrc *drc;
|
||||
|
||||
if (!strstart(prop->type, "link<", NULL)) {
|
||||
continue;
|
||||
}
|
||||
drc = SPAPR_DR_CONNECTOR(object_property_get_link(drc_container,
|
||||
prop->name,
|
||||
&error_abort));
|
||||
|
||||
if (spapr_drc_transient(drc)) {
|
||||
spapr_drc_reset(drc);
|
||||
}
|
||||
}
|
||||
|
||||
spapr_clear_pending_hotplug_events(spapr);
|
||||
}
|
||||
|
||||
target_ulong do_client_architecture_support(PowerPCCPU *cpu,
|
||||
SpaprMachineState *spapr,
|
||||
target_ulong vec,
|
||||
|
@ -1815,7 +1789,12 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu,
|
|||
|
||||
spapr_irq_update_active_intc(spapr);
|
||||
|
||||
spapr_handle_transient_dev_before_cas(spapr);
|
||||
/*
|
||||
* Process all pending hot-plug/unplug requests now. An updated full
|
||||
* rendered FDT will be returned to the guest.
|
||||
*/
|
||||
spapr_drc_reset_all(spapr);
|
||||
spapr_clear_pending_hotplug_events(spapr);
|
||||
|
||||
/*
|
||||
* If spapr_machine_reset() did not set up a HPT but one is necessary
|
||||
|
|
|
@ -96,3 +96,4 @@ ppc440_pcix_set_irq(int irq_num) "PCI irq %d"
|
|||
ppc440_pcix_update_pim(int idx, uint64_t size, uint64_t la) "Added window %d of size=0x%" PRIx64 " to CPU=0x%" PRIx64
|
||||
ppc440_pcix_update_pom(int idx, uint32_t size, uint64_t la, uint64_t pcia) "Added window %d of size=0x%x from CPU=0x%" PRIx64 " to PCI=0x%" PRIx64
|
||||
ppc440_pcix_reg_read(uint64_t addr, uint32_t val) "addr 0x%" PRIx64 " = 0x%" PRIx32
|
||||
ppc440_pcix_reg_write(uint64_t addr, uint32_t val, uint32_t size) "addr 0x%" PRIx64 " = 0x%" PRIx32 " size 0x%" PRIx32
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "qemu/option.h"
|
||||
#include "exec/address-spaces.h"
|
||||
|
||||
#include "hw/intc/ppc-uic.h"
|
||||
#include "hw/ppc/ppc.h"
|
||||
#include "hw/ppc/ppc4xx.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
|
@ -95,7 +96,8 @@ static PowerPCCPU *ppc440_init_xilinx(const char *cpu_type, uint32_t sysclk)
|
|||
{
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
qemu_irq *irqs;
|
||||
DeviceState *uicdev;
|
||||
SysBusDevice *uicsbd;
|
||||
|
||||
cpu = POWERPC_CPU(cpu_create(cpu_type));
|
||||
env = &cpu->env;
|
||||
|
@ -105,10 +107,19 @@ static PowerPCCPU *ppc440_init_xilinx(const char *cpu_type, uint32_t sysclk)
|
|||
ppc_dcr_init(env, NULL, NULL);
|
||||
|
||||
/* interrupt controller */
|
||||
irqs = g_new0(qemu_irq, PPCUIC_OUTPUT_NB);
|
||||
irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
|
||||
irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
|
||||
ppcuic_init(env, irqs, 0x0C0, 0, 1);
|
||||
uicdev = qdev_new(TYPE_PPC_UIC);
|
||||
uicsbd = SYS_BUS_DEVICE(uicdev);
|
||||
|
||||
object_property_set_link(OBJECT(uicdev), "cpu", OBJECT(cpu),
|
||||
&error_fatal);
|
||||
sysbus_realize_and_unref(uicsbd, &error_fatal);
|
||||
|
||||
sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_INT,
|
||||
((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT]);
|
||||
sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_CINT,
|
||||
((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT]);
|
||||
|
||||
/* This board doesn't wire anything up to the inputs of the UIC. */
|
||||
return cpu;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* "Universal" Interrupt Controller for PowerPPC 4xx embedded processors
|
||||
*
|
||||
* Copyright (c) 2007 Jocelyn Mayer
|
||||
*
|
||||
* 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 HW_INTC_PPC_UIC_H
|
||||
#define HW_INTC_PPC_UIC_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_PPC_UIC "ppc-uic"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(PPCUIC, PPC_UIC)
|
||||
|
||||
/*
|
||||
* QEMU interface:
|
||||
* QOM property "cpu": link to the PPC CPU
|
||||
* (no default, must be set)
|
||||
* QOM property "dcr-base": base of the bank of DCR registers for the UIC
|
||||
* (default 0x30)
|
||||
* QOM property "use-vectors": true if the UIC has vector registers
|
||||
* (default true)
|
||||
* unnamed GPIO inputs 0..UIC_MAX_IRQ: input IRQ lines
|
||||
* sysbus IRQs:
|
||||
* 0 (PPCUIC_OUTPUT_INT): output INT line to the CPU
|
||||
* 1 (PPCUIC_OUTPUT_CINT): output CINT line to the CPU
|
||||
*/
|
||||
|
||||
#define UIC_MAX_IRQ 32
|
||||
|
||||
struct PPCUIC {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
qemu_irq output_int;
|
||||
qemu_irq output_cint;
|
||||
|
||||
/* properties */
|
||||
CPUState *cpu;
|
||||
uint32_t dcr_base;
|
||||
bool use_vectors;
|
||||
|
||||
uint32_t level; /* Remembers the state of level-triggered interrupts. */
|
||||
uint32_t uicsr; /* Status register */
|
||||
uint32_t uicer; /* Enable register */
|
||||
uint32_t uiccr; /* Critical register */
|
||||
uint32_t uicpr; /* Polarity register */
|
||||
uint32_t uictr; /* Triggering register */
|
||||
uint32_t uicvcr; /* Vector configuration register */
|
||||
uint32_t uicvr;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -115,8 +115,6 @@ struct SpaprPhbState {
|
|||
#define SPAPR_PCI_NV2RAM64_WIN_BASE SPAPR_PCI_LIMIT
|
||||
#define SPAPR_PCI_NV2RAM64_WIN_SIZE (2 * TiB) /* For up to 6 GPUs 256GB each */
|
||||
|
||||
/* Max number of these GPUsper a physical box */
|
||||
#define NVGPU_MAX_NUM 6
|
||||
/* Max number of NVLinks per GPU in any physical box */
|
||||
#define NVGPU_MAX_LINKS 3
|
||||
|
||||
|
|
|
@ -112,6 +112,9 @@ typedef enum {
|
|||
#define NUMA_ASSOC_SIZE (MAX_DISTANCE_REF_POINTS + 1)
|
||||
#define VCPU_ASSOC_SIZE (NUMA_ASSOC_SIZE + 1)
|
||||
|
||||
/* Max number of these GPUsper a physical box */
|
||||
#define NVGPU_MAX_NUM 6
|
||||
|
||||
typedef struct SpaprCapabilities SpaprCapabilities;
|
||||
struct SpaprCapabilities {
|
||||
uint8_t caps[SPAPR_CAP_NUM];
|
||||
|
@ -139,6 +142,7 @@ struct SpaprMachineClass {
|
|||
hwaddr rma_limit; /* clamp the RMA to this size */
|
||||
bool pre_5_1_assoc_refpoints;
|
||||
bool pre_5_2_numa_associativity;
|
||||
bool pre_6_0_memory_unplug;
|
||||
|
||||
bool (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
|
||||
uint64_t *buid, hwaddr *pio,
|
||||
|
@ -239,7 +243,7 @@ struct SpaprMachineState {
|
|||
unsigned gpu_numa_id;
|
||||
SpaprTpmProxy *tpm_proxy;
|
||||
|
||||
uint32_t numa_assoc_array[MAX_NODES][NUMA_ASSOC_SIZE];
|
||||
uint32_t numa_assoc_array[MAX_NODES + NVGPU_MAX_NUM][NUMA_ASSOC_SIZE];
|
||||
|
||||
Error *fwnmi_migration_blocker;
|
||||
};
|
||||
|
|
|
@ -224,7 +224,8 @@ static inline bool spapr_drc_hotplugged(DeviceState *dev)
|
|||
return dev->hotplugged && !runstate_check(RUN_STATE_INMIGRATE);
|
||||
}
|
||||
|
||||
void spapr_drc_reset(SpaprDrc *drc);
|
||||
/* Returns true if an unplug request completed */
|
||||
bool spapr_drc_reset(SpaprDrc *drc);
|
||||
|
||||
uint32_t spapr_drc_index(SpaprDrc *drc);
|
||||
SpaprDrcType spapr_drc_type(SpaprDrc *drc);
|
||||
|
@ -244,8 +245,11 @@ int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask);
|
|||
void spapr_drc_attach(SpaprDrc *drc, DeviceState *d);
|
||||
void spapr_drc_detach(SpaprDrc *drc);
|
||||
|
||||
/* Returns true if a hot plug/unplug request is pending */
|
||||
bool spapr_drc_transient(SpaprDrc *drc);
|
||||
/*
|
||||
* Reset all DRCs, causing pending hot-plug/unplug requests to complete.
|
||||
* Safely handles potential DRC removal (eg. PHBs or PCI bridges).
|
||||
*/
|
||||
void spapr_drc_reset_all(struct SpaprMachineState *spapr);
|
||||
|
||||
static inline bool spapr_drc_unplug_requested(SpaprDrc *drc)
|
||||
{
|
||||
|
|
|
@ -66,8 +66,6 @@ typedef struct SpaprXiveClass {
|
|||
*/
|
||||
#define SPAPR_XIVE_BLOCK_ID 0x0
|
||||
|
||||
void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon);
|
||||
|
||||
struct SpaprMachineState;
|
||||
void spapr_xive_hcall_init(struct SpaprMachineState *spapr);
|
||||
void spapr_xive_mmio_set_enabled(SpaprXive *xive, bool enable);
|
||||
|
|
Loading…
Reference in New Issue