mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.8-20161017' into staging
ppc patch queue 2016-10-17
Highlights:
* Significant rework of how PCI IO windows are placed for the
pseries machine type
* A number of extra tests added for ppc
* Other tests clean up / fixed
* Some cleanups to the XICS interrupt controller in preparation
for the 'powernv' machine type
A number of the test changes aren't strictly in ppc related code, but
are included via my tree because they're primarily focused on
improving test coverage for ppc.
# gpg: Signature made Mon 17 Oct 2016 03:42:41 BST
# gpg: using RSA key 0x6C38CACA20D9B392
# 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.8-20161017:
spapr: Improved placement of PCI host bridges in guest memory map
spapr_pci: Add a 64-bit MMIO window
spapr: Adjust placement of PCI host bridge to allow > 1TiB RAM
spapr_pci: Delegate placement of PCI host bridges to machine type
libqos: Limit spapr-pci to 32-bit MMIO for now
libqos: Correct error in PCI hole sizing for spapr
libqos: Isolate knowledge of spapr memory map to qpci_init_spapr()
ppc/xics: Split ICS into ics-base and ics class
ppc/xics: Make the ICSState a list
spapr: fix inheritance chain for default machine options
target-ppc: implement vexts[bh]2w and vexts[bhw]2d
tests/boot-sector: Increase time-out to 90 seconds
tests/boot-sector: Use mkstemp() to create a unique file name
tests/boot-sector: Use minimum length for the Forth boot script
qtest: ask endianness of the target in qtest_init()
tests: minor cleanups in usb-hcd-uhci-test
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -50,16 +50,17 @@ xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR %#"PRIx3
|
||||
xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server %d given XIRR %#"PRIx32" new XIRR %#"PRIx32
|
||||
xics_icp_irq(int server, int nr, uint8_t priority) "cpu %d trying to deliver irq %#"PRIx32" priority %#x"
|
||||
xics_icp_raise(uint32_t xirr, uint8_t pending_priority) "raising IRQ new XIRR=%#x new pending priority=%#x"
|
||||
xics_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
|
||||
xics_ics_simple_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq %#x]"
|
||||
xics_masked_pending(void) "set_irq_msi: masked pending"
|
||||
xics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
|
||||
xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
|
||||
xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
|
||||
xics_ics_eoi(int nr) "ics_eoi: irq %#x"
|
||||
xics_alloc(int src, int irq) "source#%d, irq %d"
|
||||
xics_alloc_block(int src, int first, int num, bool lsi, int align) "source#%d, first irq %d, %d irqs, lsi=%d, alignnum %d"
|
||||
xics_ics_simple_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq %#x]"
|
||||
xics_ics_simple_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq %#x [src %d] server %#x prio %#x"
|
||||
xics_ics_simple_reject(int nr, int srcno) "reject irq %#x [src %d]"
|
||||
xics_ics_simple_eoi(int nr) "ics_eoi: irq %#x"
|
||||
xics_alloc(int irq) "irq %d"
|
||||
xics_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d"
|
||||
xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
|
||||
xics_ics_free_warn(int src, int irq) "Source#%d, irq %d is already free"
|
||||
xics_icp_post_load(uint32_t server_no, uint32_t xirr, uint64_t addr, uint8_t pend) "server_no %d, xirr %#x, xirr_owner 0x%" PRIx64 ", pending %d"
|
||||
|
||||
# hw/intc/s390_flic_kvm.c
|
||||
flic_create_device(int err) "flic: create device failed %d"
|
||||
|
||||
+142
-91
File diff suppressed because it is too large
Load Diff
+24
-13
@@ -272,7 +272,7 @@ static void ics_kvm_set_irq(void *opaque, int srcno, int val)
|
||||
|
||||
static void ics_kvm_reset(DeviceState *dev)
|
||||
{
|
||||
ICSState *ics = ICS(dev);
|
||||
ICSState *ics = ICS_SIMPLE(dev);
|
||||
int i;
|
||||
uint8_t flags[ics->nr_irqs];
|
||||
|
||||
@@ -293,7 +293,7 @@ static void ics_kvm_reset(DeviceState *dev)
|
||||
|
||||
static void ics_kvm_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ICSState *ics = ICS(dev);
|
||||
ICSState *ics = ICS_SIMPLE(dev);
|
||||
|
||||
if (!ics->nr_irqs) {
|
||||
error_setg(errp, "Number of interrupts needs to be greater 0");
|
||||
@@ -306,7 +306,7 @@ static void ics_kvm_realize(DeviceState *dev, Error **errp)
|
||||
static void ics_kvm_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
ICSStateClass *icsc = ICS_CLASS(klass);
|
||||
ICSStateClass *icsc = ICS_BASE_CLASS(klass);
|
||||
|
||||
dc->realize = ics_kvm_realize;
|
||||
dc->reset = ics_kvm_reset;
|
||||
@@ -315,8 +315,8 @@ static void ics_kvm_class_init(ObjectClass *klass, void *data)
|
||||
}
|
||||
|
||||
static const TypeInfo ics_kvm_info = {
|
||||
.name = TYPE_KVM_ICS,
|
||||
.parent = TYPE_ICS,
|
||||
.name = TYPE_ICS_KVM,
|
||||
.parent = TYPE_ICS_SIMPLE,
|
||||
.instance_size = sizeof(ICSState),
|
||||
.class_init = ics_kvm_class_init,
|
||||
};
|
||||
@@ -361,7 +361,13 @@ static void xics_kvm_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
|
||||
static void xics_kvm_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
|
||||
Error **errp)
|
||||
{
|
||||
xics->nr_irqs = xics->ics->nr_irqs = nr_irqs;
|
||||
ICSState *ics = QLIST_FIRST(&xics->ics);
|
||||
|
||||
/* This needs to be deprecated ... */
|
||||
xics->nr_irqs = nr_irqs;
|
||||
if (ics) {
|
||||
ics->nr_irqs = nr_irqs;
|
||||
}
|
||||
}
|
||||
|
||||
static void xics_kvm_set_nr_servers(XICSState *xics, uint32_t nr_servers,
|
||||
@@ -394,6 +400,7 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
KVMXICSState *xicskvm = XICS_SPAPR_KVM(dev);
|
||||
XICSState *xics = XICS_COMMON(dev);
|
||||
ICSState *ics;
|
||||
int i, rc;
|
||||
Error *error = NULL;
|
||||
struct kvm_create_device xics_create_device = {
|
||||
@@ -445,10 +452,12 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
xicskvm->kernel_xics_fd = xics_create_device.fd;
|
||||
|
||||
object_property_set_bool(OBJECT(xics->ics), true, "realized", &error);
|
||||
if (error) {
|
||||
error_propagate(errp, error);
|
||||
goto fail;
|
||||
QLIST_FOREACH(ics, &xics->ics, list) {
|
||||
object_property_set_bool(OBJECT(ics), true, "realized", &error);
|
||||
if (error) {
|
||||
error_propagate(errp, error);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
assert(xics->nr_servers);
|
||||
@@ -477,10 +486,12 @@ fail:
|
||||
static void xics_kvm_initfn(Object *obj)
|
||||
{
|
||||
XICSState *xics = XICS_COMMON(obj);
|
||||
ICSState *ics;
|
||||
|
||||
xics->ics = ICS(object_new(TYPE_KVM_ICS));
|
||||
object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
|
||||
xics->ics->xics = xics;
|
||||
ics = ICS_SIMPLE(object_new(TYPE_ICS_KVM));
|
||||
object_property_add_child(obj, "ics", OBJECT(ics), NULL);
|
||||
ics->xics = xics;
|
||||
QLIST_INSERT_HEAD(&xics->ics, ics, list);
|
||||
}
|
||||
|
||||
static void xics_kvm_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
+73
-43
@@ -113,13 +113,17 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
uint32_t nargs, target_ulong args,
|
||||
uint32_t nret, target_ulong rets)
|
||||
{
|
||||
ICSState *ics = spapr->xics->ics;
|
||||
uint32_t nr, server, priority;
|
||||
ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
|
||||
uint32_t nr, srcno, server, priority;
|
||||
|
||||
if ((nargs != 3) || (nret != 1)) {
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
if (!ics) {
|
||||
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
nr = rtas_ld(args, 0);
|
||||
server = xics_get_cpu_index_by_dt_id(rtas_ld(args, 1));
|
||||
@@ -131,7 +135,8 @@ static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
return;
|
||||
}
|
||||
|
||||
ics_write_xive(ics, nr, server, priority, priority);
|
||||
srcno = nr - ics->offset;
|
||||
ics_simple_write_xive(ics, srcno, server, priority, priority);
|
||||
|
||||
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
|
||||
}
|
||||
@@ -141,13 +146,17 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
uint32_t nargs, target_ulong args,
|
||||
uint32_t nret, target_ulong rets)
|
||||
{
|
||||
ICSState *ics = spapr->xics->ics;
|
||||
uint32_t nr;
|
||||
ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
|
||||
uint32_t nr, srcno;
|
||||
|
||||
if ((nargs != 1) || (nret != 3)) {
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
if (!ics) {
|
||||
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
nr = rtas_ld(args, 0);
|
||||
|
||||
@@ -157,8 +166,9 @@ static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
}
|
||||
|
||||
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
|
||||
rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
|
||||
rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
|
||||
srcno = nr - ics->offset;
|
||||
rtas_st(rets, 1, ics->irqs[srcno].server);
|
||||
rtas_st(rets, 2, ics->irqs[srcno].priority);
|
||||
}
|
||||
|
||||
static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
@@ -166,13 +176,17 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
uint32_t nargs, target_ulong args,
|
||||
uint32_t nret, target_ulong rets)
|
||||
{
|
||||
ICSState *ics = spapr->xics->ics;
|
||||
uint32_t nr;
|
||||
ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
|
||||
uint32_t nr, srcno;
|
||||
|
||||
if ((nargs != 1) || (nret != 1)) {
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
if (!ics) {
|
||||
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
nr = rtas_ld(args, 0);
|
||||
|
||||
@@ -181,8 +195,9 @@ static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
return;
|
||||
}
|
||||
|
||||
ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
|
||||
ics->irqs[nr - ics->offset].priority);
|
||||
srcno = nr - ics->offset;
|
||||
ics_simple_write_xive(ics, srcno, ics->irqs[srcno].server, 0xff,
|
||||
ics->irqs[srcno].priority);
|
||||
|
||||
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
|
||||
}
|
||||
@@ -192,13 +207,17 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
uint32_t nargs, target_ulong args,
|
||||
uint32_t nret, target_ulong rets)
|
||||
{
|
||||
ICSState *ics = spapr->xics->ics;
|
||||
uint32_t nr;
|
||||
ICSState *ics = QLIST_FIRST(&spapr->xics->ics);
|
||||
uint32_t nr, srcno;
|
||||
|
||||
if ((nargs != 1) || (nret != 1)) {
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
if (!ics) {
|
||||
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
nr = rtas_ld(args, 0);
|
||||
|
||||
@@ -207,9 +226,10 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
return;
|
||||
}
|
||||
|
||||
ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
|
||||
ics->irqs[nr - ics->offset].saved_priority,
|
||||
ics->irqs[nr - ics->offset].saved_priority);
|
||||
srcno = nr - ics->offset;
|
||||
ics_simple_write_xive(ics, srcno, ics->irqs[srcno].server,
|
||||
ics->irqs[srcno].saved_priority,
|
||||
ics->irqs[srcno].saved_priority);
|
||||
|
||||
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
|
||||
}
|
||||
@@ -217,7 +237,13 @@ static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
static void xics_spapr_set_nr_irqs(XICSState *xics, uint32_t nr_irqs,
|
||||
Error **errp)
|
||||
{
|
||||
xics->nr_irqs = xics->ics->nr_irqs = nr_irqs;
|
||||
ICSState *ics = QLIST_FIRST(&xics->ics);
|
||||
|
||||
/* This needs to be deprecated ... */
|
||||
xics->nr_irqs = nr_irqs;
|
||||
if (ics) {
|
||||
ics->nr_irqs = nr_irqs;
|
||||
}
|
||||
}
|
||||
|
||||
static void xics_spapr_set_nr_servers(XICSState *xics, uint32_t nr_servers,
|
||||
@@ -240,6 +266,7 @@ static void xics_spapr_set_nr_servers(XICSState *xics, uint32_t nr_servers,
|
||||
static void xics_spapr_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
XICSState *xics = XICS_SPAPR(dev);
|
||||
ICSState *ics;
|
||||
Error *error = NULL;
|
||||
int i;
|
||||
|
||||
@@ -261,10 +288,12 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
|
||||
spapr_register_hypercall(H_EOI, h_eoi);
|
||||
spapr_register_hypercall(H_IPOLL, h_ipoll);
|
||||
|
||||
object_property_set_bool(OBJECT(xics->ics), true, "realized", &error);
|
||||
if (error) {
|
||||
error_propagate(errp, error);
|
||||
return;
|
||||
QLIST_FOREACH(ics, &xics->ics, list) {
|
||||
object_property_set_bool(OBJECT(ics), true, "realized", &error);
|
||||
if (error) {
|
||||
error_propagate(errp, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < xics->nr_servers; i++) {
|
||||
@@ -280,10 +309,12 @@ static void xics_spapr_realize(DeviceState *dev, Error **errp)
|
||||
static void xics_spapr_initfn(Object *obj)
|
||||
{
|
||||
XICSState *xics = XICS_SPAPR(obj);
|
||||
ICSState *ics;
|
||||
|
||||
xics->ics = ICS(object_new(TYPE_ICS));
|
||||
object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
|
||||
xics->ics->xics = xics;
|
||||
ics = ICS_SIMPLE(object_new(TYPE_ICS_SIMPLE));
|
||||
object_property_add_child(obj, "ics", OBJECT(ics), NULL);
|
||||
ics->xics = xics;
|
||||
QLIST_INSERT_HEAD(&xics->ics, ics, list);
|
||||
}
|
||||
|
||||
static void xics_spapr_class_init(ObjectClass *oc, void *data)
|
||||
@@ -329,14 +360,15 @@ static int ics_find_free_block(ICSState *ics, int num, int alignnum)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi,
|
||||
Error **errp)
|
||||
int xics_spapr_alloc(XICSState *xics, int irq_hint, bool lsi, Error **errp)
|
||||
{
|
||||
ICSState *ics = &xics->ics[src];
|
||||
ICSState *ics = QLIST_FIRST(&xics->ics);
|
||||
int irq;
|
||||
|
||||
if (!ics) {
|
||||
return -1;
|
||||
}
|
||||
if (irq_hint) {
|
||||
assert(src == xics_find_source(xics, irq_hint));
|
||||
if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) {
|
||||
error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint);
|
||||
return -1;
|
||||
@@ -352,7 +384,7 @@ int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi,
|
||||
}
|
||||
|
||||
ics_set_irq_type(ics, irq - ics->offset, lsi);
|
||||
trace_xics_alloc(src, irq);
|
||||
trace_xics_alloc(irq);
|
||||
|
||||
return irq;
|
||||
}
|
||||
@@ -361,13 +393,16 @@ int xics_spapr_alloc(XICSState *xics, int src, int irq_hint, bool lsi,
|
||||
* Allocate block of consecutive IRQs, and return the number of the first IRQ in
|
||||
* the block. If align==true, aligns the first IRQ number to num.
|
||||
*/
|
||||
int xics_spapr_alloc_block(XICSState *xics, int src, int num, bool lsi,
|
||||
bool align, Error **errp)
|
||||
int xics_spapr_alloc_block(XICSState *xics, int num, bool lsi, bool align,
|
||||
Error **errp)
|
||||
{
|
||||
ICSState *ics = QLIST_FIRST(&xics->ics);
|
||||
int i, first = -1;
|
||||
ICSState *ics = &xics->ics[src];
|
||||
|
||||
assert(src == 0);
|
||||
if (!ics) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* MSIMesage::data is used for storing VIRQ so
|
||||
* it has to be aligned to num to support multiple
|
||||
@@ -394,7 +429,7 @@ int xics_spapr_alloc_block(XICSState *xics, int src, int num, bool lsi,
|
||||
}
|
||||
first += ics->offset;
|
||||
|
||||
trace_xics_alloc_block(src, first, num, lsi, align);
|
||||
trace_xics_alloc_block(first, num, lsi, align);
|
||||
|
||||
return first;
|
||||
}
|
||||
@@ -405,7 +440,7 @@ static void ics_free(ICSState *ics, int srcno, int num)
|
||||
|
||||
for (i = srcno; i < srcno + num; ++i) {
|
||||
if (ICS_IRQ_FREE(ics, i)) {
|
||||
trace_xics_ics_free_warn(ics - ics->xics->ics, i + ics->offset);
|
||||
trace_xics_ics_free_warn(0, i + ics->offset);
|
||||
}
|
||||
memset(&ics->irqs[i], 0, sizeof(ICSIRQState));
|
||||
}
|
||||
@@ -413,15 +448,10 @@ static void ics_free(ICSState *ics, int srcno, int num)
|
||||
|
||||
void xics_spapr_free(XICSState *xics, int irq, int num)
|
||||
{
|
||||
int src = xics_find_source(xics, irq);
|
||||
ICSState *ics = xics_find_source(xics, irq);
|
||||
|
||||
if (src >= 0) {
|
||||
ICSState *ics = &xics->ics[src];
|
||||
|
||||
/* FIXME: implement multiple sources */
|
||||
assert(src == 0);
|
||||
|
||||
trace_xics_ics_free(ics - xics->ics, irq, num);
|
||||
if (ics) {
|
||||
trace_xics_ics_free(0, irq, num);
|
||||
ics_free(ics, irq - ics->offset, num);
|
||||
}
|
||||
}
|
||||
|
||||
+116
-2
@@ -2370,6 +2370,56 @@ static HotpluggableCPUList *spapr_query_hotpluggable_cpus(MachineState *machine)
|
||||
return head;
|
||||
}
|
||||
|
||||
static void spapr_phb_placement(sPAPRMachineState *spapr, uint32_t index,
|
||||
uint64_t *buid, hwaddr *pio,
|
||||
hwaddr *mmio32, hwaddr *mmio64,
|
||||
unsigned n_dma, uint32_t *liobns, Error **errp)
|
||||
{
|
||||
/*
|
||||
* New-style PHB window placement.
|
||||
*
|
||||
* Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window
|
||||
* for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO
|
||||
* windows.
|
||||
*
|
||||
* Some guest kernels can't work with MMIO windows above 1<<46
|
||||
* (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB
|
||||
*
|
||||
* 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each
|
||||
* PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the
|
||||
* 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the
|
||||
* 1TiB 64-bit MMIO windows for each PHB.
|
||||
*/
|
||||
const uint64_t base_buid = 0x800000020000000ULL;
|
||||
const int max_phbs =
|
||||
(SPAPR_PCI_LIMIT - SPAPR_PCI_BASE) / SPAPR_PCI_MEM64_WIN_SIZE - 1;
|
||||
int i;
|
||||
|
||||
/* Sanity check natural alignments */
|
||||
QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0);
|
||||
QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0);
|
||||
QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0);
|
||||
QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0);
|
||||
/* Sanity check bounds */
|
||||
QEMU_BUILD_BUG_ON((max_phbs * SPAPR_PCI_IO_WIN_SIZE) > SPAPR_PCI_MEM32_WIN_SIZE);
|
||||
QEMU_BUILD_BUG_ON((max_phbs * SPAPR_PCI_MEM32_WIN_SIZE) > SPAPR_PCI_MEM64_WIN_SIZE);
|
||||
|
||||
if (index >= max_phbs) {
|
||||
error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)",
|
||||
max_phbs - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
*buid = base_buid + index;
|
||||
for (i = 0; i < n_dma; ++i) {
|
||||
liobns[i] = SPAPR_PCI_LIOBN(index, i);
|
||||
}
|
||||
|
||||
*pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE;
|
||||
*mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE;
|
||||
*mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE;
|
||||
}
|
||||
|
||||
static void spapr_machine_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
@@ -2406,6 +2456,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->query_hotpluggable_cpus = spapr_query_hotpluggable_cpus;
|
||||
fwc->get_dev_path = spapr_get_fw_dev_path;
|
||||
nc->nmi_monitor_handler = spapr_nmi;
|
||||
smc->phb_placement = spapr_phb_placement;
|
||||
}
|
||||
|
||||
static const TypeInfo spapr_machine_info = {
|
||||
@@ -2470,11 +2521,71 @@ DEFINE_SPAPR_MACHINE(2_8, "2.8", true);
|
||||
/*
|
||||
* pseries-2.7
|
||||
*/
|
||||
#define SPAPR_COMPAT_2_7 \
|
||||
HW_COMPAT_2_7 \
|
||||
#define SPAPR_COMPAT_2_7 \
|
||||
HW_COMPAT_2_7 \
|
||||
{ \
|
||||
.driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \
|
||||
.property = "mem_win_size", \
|
||||
.value = stringify(SPAPR_PCI_2_7_MMIO_WIN_SIZE),\
|
||||
}, \
|
||||
{ \
|
||||
.driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \
|
||||
.property = "mem64_win_size", \
|
||||
.value = "0", \
|
||||
},
|
||||
|
||||
static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index,
|
||||
uint64_t *buid, hwaddr *pio,
|
||||
hwaddr *mmio32, hwaddr *mmio64,
|
||||
unsigned n_dma, uint32_t *liobns, Error **errp)
|
||||
{
|
||||
/* Legacy PHB placement for pseries-2.7 and earlier machine types */
|
||||
const uint64_t base_buid = 0x800000020000000ULL;
|
||||
const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */
|
||||
const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */
|
||||
const hwaddr pio_offset = 0x80000000; /* 2 GiB */
|
||||
const uint32_t max_index = 255;
|
||||
const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */
|
||||
|
||||
uint64_t ram_top = MACHINE(spapr)->ram_size;
|
||||
hwaddr phb0_base, phb_base;
|
||||
int i;
|
||||
|
||||
/* Do we have hotpluggable memory? */
|
||||
if (MACHINE(spapr)->maxram_size > ram_top) {
|
||||
/* Can't just use maxram_size, because there may be an
|
||||
* alignment gap between normal and hotpluggable memory
|
||||
* regions */
|
||||
ram_top = spapr->hotplug_memory.base +
|
||||
memory_region_size(&spapr->hotplug_memory.mr);
|
||||
}
|
||||
|
||||
phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment);
|
||||
|
||||
if (index > max_index) {
|
||||
error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)",
|
||||
max_index);
|
||||
return;
|
||||
}
|
||||
|
||||
*buid = base_buid + index;
|
||||
for (i = 0; i < n_dma; ++i) {
|
||||
liobns[i] = SPAPR_PCI_LIOBN(index, i);
|
||||
}
|
||||
|
||||
phb_base = phb0_base + index * phb_spacing;
|
||||
*pio = phb_base + pio_offset;
|
||||
*mmio32 = phb_base + mmio_offset;
|
||||
/*
|
||||
* We don't set the 64-bit MMIO window, relying on the PHB's
|
||||
* fallback behaviour of automatically splitting a large "32-bit"
|
||||
* window into contiguous 32-bit and 64-bit windows
|
||||
*/
|
||||
}
|
||||
|
||||
static void spapr_machine_2_7_instance_options(MachineState *machine)
|
||||
{
|
||||
spapr_machine_2_8_instance_options(machine);
|
||||
}
|
||||
|
||||
static void spapr_machine_2_7_class_options(MachineClass *mc)
|
||||
@@ -2484,6 +2595,7 @@ static void spapr_machine_2_7_class_options(MachineClass *mc)
|
||||
spapr_machine_2_8_class_options(mc);
|
||||
smc->tcg_default_cpu = "POWER7";
|
||||
SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_7);
|
||||
smc->phb_placement = phb_placement_2_7;
|
||||
}
|
||||
|
||||
DEFINE_SPAPR_MACHINE(2_7, "2.7", false);
|
||||
@@ -2501,6 +2613,7 @@ DEFINE_SPAPR_MACHINE(2_7, "2.7", false);
|
||||
|
||||
static void spapr_machine_2_6_instance_options(MachineState *machine)
|
||||
{
|
||||
spapr_machine_2_7_instance_options(machine);
|
||||
}
|
||||
|
||||
static void spapr_machine_2_6_class_options(MachineClass *mc)
|
||||
@@ -2525,6 +2638,7 @@ DEFINE_SPAPR_MACHINE(2_6, "2.6", false);
|
||||
|
||||
static void spapr_machine_2_5_instance_options(MachineState *machine)
|
||||
{
|
||||
spapr_machine_2_6_instance_options(machine);
|
||||
}
|
||||
|
||||
static void spapr_machine_2_5_class_options(MachineClass *mc)
|
||||
|
||||
@@ -594,7 +594,7 @@ out_no_events:
|
||||
void spapr_events_init(sPAPRMachineState *spapr)
|
||||
{
|
||||
QTAILQ_INIT(&spapr->pending_events);
|
||||
spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, 0, false,
|
||||
spapr->check_exception_irq = xics_spapr_alloc(spapr->xics, 0, false,
|
||||
&error_fatal);
|
||||
spapr->epow_notifier.notify = spapr_powerdown_req;
|
||||
qemu_register_powerdown_notifier(&spapr->epow_notifier);
|
||||
|
||||
+65
-30
@@ -363,7 +363,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
}
|
||||
|
||||
/* Allocate MSIs */
|
||||
irq = xics_spapr_alloc_block(spapr->xics, 0, req_num, false,
|
||||
irq = xics_spapr_alloc_block(spapr->xics, req_num, false,
|
||||
ret_intr_type == RTAS_TYPE_MSI, &err);
|
||||
if (err) {
|
||||
error_reportf_err(err, "Can't allocate MSIs for device %x: ",
|
||||
@@ -1311,32 +1311,27 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1;
|
||||
|
||||
if (sphb->index != (uint32_t)-1) {
|
||||
hwaddr windows_base;
|
||||
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
|
||||
Error *local_err = NULL;
|
||||
|
||||
if ((sphb->buid != (uint64_t)-1) || (sphb->dma_liobn[0] != (uint32_t)-1)
|
||||
|| (sphb->dma_liobn[1] != (uint32_t)-1 && windows_supported == 2)
|
||||
|| (sphb->mem_win_addr != (hwaddr)-1)
|
||||
|| (sphb->mem64_win_addr != (hwaddr)-1)
|
||||
|| (sphb->io_win_addr != (hwaddr)-1)) {
|
||||
error_setg(errp, "Either \"index\" or other parameters must"
|
||||
" be specified for PAPR PHB, not both");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sphb->index > SPAPR_PCI_MAX_INDEX) {
|
||||
error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)",
|
||||
SPAPR_PCI_MAX_INDEX);
|
||||
smc->phb_placement(spapr, sphb->index,
|
||||
&sphb->buid, &sphb->io_win_addr,
|
||||
&sphb->mem_win_addr, &sphb->mem64_win_addr,
|
||||
windows_supported, sphb->dma_liobn, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index;
|
||||
for (i = 0; i < windows_supported; ++i) {
|
||||
sphb->dma_liobn[i] = SPAPR_PCI_LIOBN(sphb->index, i);
|
||||
}
|
||||
|
||||
windows_base = SPAPR_PCI_WINDOW_BASE
|
||||
+ sphb->index * SPAPR_PCI_WINDOW_SPACING;
|
||||
sphb->mem_win_addr = windows_base + SPAPR_PCI_MMIO_WIN_OFF;
|
||||
sphb->io_win_addr = windows_base + SPAPR_PCI_IO_WIN_OFF;
|
||||
}
|
||||
|
||||
if (sphb->buid == (uint64_t)-1) {
|
||||
@@ -1360,6 +1355,38 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
if (sphb->mem64_win_size != 0) {
|
||||
if (sphb->mem64_win_addr == (hwaddr)-1) {
|
||||
error_setg(errp,
|
||||
"64-bit memory window address not specified for PHB");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sphb->mem_win_size > SPAPR_PCI_MEM32_WIN_SIZE) {
|
||||
error_setg(errp, "32-bit memory window of size 0x%"HWADDR_PRIx
|
||||
" (max 2 GiB)", sphb->mem_win_size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sphb->mem64_win_pciaddr == (hwaddr)-1) {
|
||||
/* 64-bit window defaults to identity mapping */
|
||||
sphb->mem64_win_pciaddr = sphb->mem64_win_addr;
|
||||
}
|
||||
} else if (sphb->mem_win_size > SPAPR_PCI_MEM32_WIN_SIZE) {
|
||||
/*
|
||||
* For compatibility with old configuration, if no 64-bit MMIO
|
||||
* window is specified, but the ordinary (32-bit) memory
|
||||
* window is specified as > 2GiB, we treat it as a 2GiB 32-bit
|
||||
* window, with a 64-bit MMIO window following on immediately
|
||||
* afterwards
|
||||
*/
|
||||
sphb->mem64_win_size = sphb->mem_win_size - SPAPR_PCI_MEM32_WIN_SIZE;
|
||||
sphb->mem64_win_addr = sphb->mem_win_addr + SPAPR_PCI_MEM32_WIN_SIZE;
|
||||
sphb->mem64_win_pciaddr =
|
||||
SPAPR_PCI_MEM_WIN_BUS_OFFSET + SPAPR_PCI_MEM32_WIN_SIZE;
|
||||
sphb->mem_win_size = SPAPR_PCI_MEM32_WIN_SIZE;
|
||||
}
|
||||
|
||||
if (spapr_pci_find_phb(spapr, sphb->buid)) {
|
||||
error_setg(errp, "PCI host bridges must have unique BUIDs");
|
||||
return;
|
||||
@@ -1373,12 +1400,19 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
sprintf(namebuf, "%s.mmio", sphb->dtbusname);
|
||||
memory_region_init(&sphb->memspace, OBJECT(sphb), namebuf, UINT64_MAX);
|
||||
|
||||
sprintf(namebuf, "%s.mmio-alias", sphb->dtbusname);
|
||||
memory_region_init_alias(&sphb->memwindow, OBJECT(sphb),
|
||||
sprintf(namebuf, "%s.mmio32-alias", sphb->dtbusname);
|
||||
memory_region_init_alias(&sphb->mem32window, OBJECT(sphb),
|
||||
namebuf, &sphb->memspace,
|
||||
SPAPR_PCI_MEM_WIN_BUS_OFFSET, sphb->mem_win_size);
|
||||
memory_region_add_subregion(get_system_memory(), sphb->mem_win_addr,
|
||||
&sphb->memwindow);
|
||||
&sphb->mem32window);
|
||||
|
||||
sprintf(namebuf, "%s.mmio64-alias", sphb->dtbusname);
|
||||
memory_region_init_alias(&sphb->mem64window, OBJECT(sphb),
|
||||
namebuf, &sphb->memspace,
|
||||
sphb->mem64_win_pciaddr, sphb->mem64_win_size);
|
||||
memory_region_add_subregion(get_system_memory(), sphb->mem64_win_addr,
|
||||
&sphb->mem64window);
|
||||
|
||||
/* Initialize IO regions */
|
||||
sprintf(namebuf, "%s.io", sphb->dtbusname);
|
||||
@@ -1445,8 +1479,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
uint32_t irq;
|
||||
Error *local_err = NULL;
|
||||
|
||||
irq = xics_spapr_alloc_block(spapr->xics, 0, 1, true, false,
|
||||
&local_err);
|
||||
irq = xics_spapr_alloc_block(spapr->xics, 1, true, false, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
error_prepend(errp, "can't allocate LSIs: ");
|
||||
@@ -1531,7 +1564,12 @@ static Property spapr_phb_properties[] = {
|
||||
DEFINE_PROP_UINT32("liobn64", sPAPRPHBState, dma_liobn[1], -1),
|
||||
DEFINE_PROP_UINT64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1),
|
||||
DEFINE_PROP_UINT64("mem_win_size", sPAPRPHBState, mem_win_size,
|
||||
SPAPR_PCI_MMIO_WIN_SIZE),
|
||||
SPAPR_PCI_MEM32_WIN_SIZE),
|
||||
DEFINE_PROP_UINT64("mem64_win_addr", sPAPRPHBState, mem64_win_addr, -1),
|
||||
DEFINE_PROP_UINT64("mem64_win_size", sPAPRPHBState, mem64_win_size,
|
||||
SPAPR_PCI_MEM64_WIN_SIZE),
|
||||
DEFINE_PROP_UINT64("mem64_win_pciaddr", sPAPRPHBState, mem64_win_pciaddr,
|
||||
-1),
|
||||
DEFINE_PROP_UINT64("io_win_addr", sPAPRPHBState, io_win_addr, -1),
|
||||
DEFINE_PROP_UINT64("io_win_size", sPAPRPHBState, io_win_size,
|
||||
SPAPR_PCI_IO_WIN_SIZE),
|
||||
@@ -1767,10 +1805,6 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
|
||||
int bus_off, i, j, ret;
|
||||
char nodename[FDT_NAME_MAX];
|
||||
uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) };
|
||||
const uint64_t mmiosize = memory_region_size(&phb->memwindow);
|
||||
const uint64_t w32max = (1ULL << 32) - SPAPR_PCI_MEM_WIN_BUS_OFFSET;
|
||||
const uint64_t w32size = MIN(w32max, mmiosize);
|
||||
const uint64_t w64size = (mmiosize > w32size) ? (mmiosize - w32size) : 0;
|
||||
struct {
|
||||
uint32_t hi;
|
||||
uint64_t child;
|
||||
@@ -1785,15 +1819,16 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
|
||||
{
|
||||
cpu_to_be32(b_ss(2)), cpu_to_be64(SPAPR_PCI_MEM_WIN_BUS_OFFSET),
|
||||
cpu_to_be64(phb->mem_win_addr),
|
||||
cpu_to_be64(w32size),
|
||||
cpu_to_be64(phb->mem_win_size),
|
||||
},
|
||||
{
|
||||
cpu_to_be32(b_ss(3)), cpu_to_be64(1ULL << 32),
|
||||
cpu_to_be64(phb->mem_win_addr + w32size),
|
||||
cpu_to_be64(w64size)
|
||||
cpu_to_be32(b_ss(3)), cpu_to_be64(phb->mem64_win_pciaddr),
|
||||
cpu_to_be64(phb->mem64_win_addr),
|
||||
cpu_to_be64(phb->mem64_win_size),
|
||||
},
|
||||
};
|
||||
const unsigned sizeof_ranges = (w64size ? 3 : 2) * sizeof(ranges[0]);
|
||||
const unsigned sizeof_ranges =
|
||||
(phb->mem64_win_size ? 3 : 2) * sizeof(ranges[0]);
|
||||
uint64_t bus_reg[] = { cpu_to_be64(phb->buid), 0 };
|
||||
uint32_t interrupt_map_mask[] = {
|
||||
cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, cpu_to_be32(-1)};
|
||||
|
||||
+1
-1
@@ -453,7 +453,7 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
|
||||
dev->qdev.id = id;
|
||||
}
|
||||
|
||||
dev->irq = xics_spapr_alloc(spapr->xics, 0, dev->irq, false, &local_err);
|
||||
dev->irq = xics_spapr_alloc(spapr->xics, dev->irq, false, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
|
||||
+13
-12
@@ -53,8 +53,10 @@ struct sPAPRPHBState {
|
||||
bool dr_enabled;
|
||||
|
||||
MemoryRegion memspace, iospace;
|
||||
hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size;
|
||||
MemoryRegion memwindow, iowindow, msiwindow;
|
||||
hwaddr mem_win_addr, mem_win_size, mem64_win_addr, mem64_win_size;
|
||||
uint64_t mem64_win_pciaddr;
|
||||
hwaddr io_win_addr, io_win_size;
|
||||
MemoryRegion mem32window, mem64window, iowindow, msiwindow;
|
||||
|
||||
uint32_t dma_liobn[SPAPR_PCI_DMA_MAX_WINDOWS];
|
||||
hwaddr dma_win_addr, dma_win_size;
|
||||
@@ -79,18 +81,17 @@ struct sPAPRPHBState {
|
||||
uint32_t numa_node;
|
||||
};
|
||||
|
||||
#define SPAPR_PCI_MAX_INDEX 255
|
||||
|
||||
#define SPAPR_PCI_BASE_BUID 0x800000020000000ULL
|
||||
|
||||
#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
|
||||
#define SPAPR_PCI_MEM32_WIN_SIZE \
|
||||
((1ULL << 32) - SPAPR_PCI_MEM_WIN_BUS_OFFSET)
|
||||
#define SPAPR_PCI_MEM64_WIN_SIZE 0x10000000000ULL /* 1 TiB */
|
||||
|
||||
#define SPAPR_PCI_WINDOW_BASE 0x10000000000ULL
|
||||
#define SPAPR_PCI_WINDOW_SPACING 0x1000000000ULL
|
||||
#define SPAPR_PCI_MMIO_WIN_OFF 0xA0000000
|
||||
#define SPAPR_PCI_MMIO_WIN_SIZE (SPAPR_PCI_WINDOW_SPACING - \
|
||||
SPAPR_PCI_MEM_WIN_BUS_OFFSET)
|
||||
#define SPAPR_PCI_IO_WIN_OFF 0x80000000
|
||||
/* Without manual configuration, all PCI outbound windows will be
|
||||
* within this range */
|
||||
#define SPAPR_PCI_BASE (1ULL << 45) /* 32 TiB */
|
||||
#define SPAPR_PCI_LIMIT (1ULL << 46) /* 64 TiB */
|
||||
|
||||
#define SPAPR_PCI_2_7_MMIO_WIN_SIZE 0xf80000000
|
||||
#define SPAPR_PCI_IO_WIN_SIZE 0x10000
|
||||
|
||||
#define SPAPR_PCI_MSI_WINDOW 0x40000000000ULL
|
||||
|
||||
@@ -40,6 +40,10 @@ struct sPAPRMachineClass {
|
||||
bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */
|
||||
bool use_ohci_by_default; /* use USB-OHCI instead of XHCI */
|
||||
const char *tcg_default_cpu; /* which (TCG) CPU to simulate by default */
|
||||
void (*phb_placement)(sPAPRMachineState *spapr, uint32_t index,
|
||||
uint64_t *buid, hwaddr *pio,
|
||||
hwaddr *mmio32, hwaddr *mmio64,
|
||||
unsigned n_dma, uint32_t *liobns, Error **errp);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+24
-16
@@ -85,7 +85,7 @@ struct XICSState {
|
||||
uint32_t nr_servers;
|
||||
uint32_t nr_irqs;
|
||||
ICPState *ss;
|
||||
ICSState *ics;
|
||||
QLIST_HEAD(, ICSState) ics;
|
||||
};
|
||||
|
||||
#define TYPE_ICP "icp"
|
||||
@@ -111,6 +111,7 @@ struct ICPState {
|
||||
DeviceState parent_obj;
|
||||
/*< public >*/
|
||||
CPUState *cs;
|
||||
ICSState *xirr_owner;
|
||||
uint32_t xirr;
|
||||
uint8_t pending_priority;
|
||||
uint8_t mfrr;
|
||||
@@ -118,22 +119,29 @@ struct ICPState {
|
||||
bool cap_irq_xics_enabled;
|
||||
};
|
||||
|
||||
#define TYPE_ICS "ics"
|
||||
#define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
|
||||
#define TYPE_ICS_BASE "ics-base"
|
||||
#define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_BASE)
|
||||
|
||||
#define TYPE_KVM_ICS "icskvm"
|
||||
#define KVM_ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_KVM_ICS)
|
||||
/* Retain ics for sPAPR for migration from existing sPAPR guests */
|
||||
#define TYPE_ICS_SIMPLE "ics"
|
||||
#define ICS_SIMPLE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SIMPLE)
|
||||
|
||||
#define ICS_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS)
|
||||
#define ICS_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS)
|
||||
#define TYPE_ICS_KVM "icskvm"
|
||||
#define ICS_KVM(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_KVM)
|
||||
|
||||
#define ICS_BASE_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(ICSStateClass, (klass), TYPE_ICS_BASE)
|
||||
#define ICS_BASE_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(ICSStateClass, (obj), TYPE_ICS_BASE)
|
||||
|
||||
struct ICSStateClass {
|
||||
DeviceClass parent_class;
|
||||
|
||||
void (*pre_save)(ICSState *s);
|
||||
int (*post_load)(ICSState *s, int version_id);
|
||||
void (*reject)(ICSState *s, uint32_t irq);
|
||||
void (*resend)(ICSState *s);
|
||||
void (*eoi)(ICSState *s, uint32_t irq);
|
||||
};
|
||||
|
||||
struct ICSState {
|
||||
@@ -145,6 +153,7 @@ struct ICSState {
|
||||
qemu_irq *qirqs;
|
||||
ICSIRQState *irqs;
|
||||
XICSState *xics;
|
||||
QLIST_ENTRY(ICSState) list;
|
||||
};
|
||||
|
||||
static inline bool ics_valid_irq(ICSState *ics, uint32_t nr)
|
||||
@@ -172,10 +181,9 @@ struct ICSIRQState {
|
||||
#define XICS_IRQS_SPAPR 1024
|
||||
|
||||
qemu_irq xics_get_qirq(XICSState *icp, int irq);
|
||||
int xics_spapr_alloc(XICSState *icp, int src, int irq_hint, bool lsi,
|
||||
Error **errp);
|
||||
int xics_spapr_alloc_block(XICSState *icp, int src, int num, bool lsi,
|
||||
bool align, Error **errp);
|
||||
int xics_spapr_alloc(XICSState *icp, int irq_hint, bool lsi, Error **errp);
|
||||
int xics_spapr_alloc_block(XICSState *icp, int num, bool lsi, bool align,
|
||||
Error **errp);
|
||||
void xics_spapr_free(XICSState *icp, int irq, int num);
|
||||
|
||||
void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
|
||||
@@ -190,11 +198,11 @@ uint32_t icp_accept(ICPState *ss);
|
||||
uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr);
|
||||
void icp_eoi(XICSState *icp, int server, uint32_t xirr);
|
||||
|
||||
void ics_write_xive(ICSState *ics, int nr, int server,
|
||||
uint8_t priority, uint8_t saved_priority);
|
||||
void ics_simple_write_xive(ICSState *ics, int nr, int server,
|
||||
uint8_t priority, uint8_t saved_priority);
|
||||
|
||||
void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
|
||||
|
||||
int xics_find_source(XICSState *icp, int irq);
|
||||
ICSState *xics_find_source(XICSState *icp, int irq);
|
||||
|
||||
#endif /* XICS_H */
|
||||
|
||||
@@ -537,6 +537,13 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
|
||||
|
||||
qtest_send_prefix(chr);
|
||||
qtest_send(chr, "OK\n");
|
||||
} else if (strcmp(words[0], "endianness") == 0) {
|
||||
qtest_send_prefix(chr);
|
||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||
qtest_sendf(chr, "OK big\n");
|
||||
#else
|
||||
qtest_sendf(chr, "OK little\n");
|
||||
#endif
|
||||
#ifdef TARGET_PPC64
|
||||
} else if (strcmp(words[0], "rtas") == 0) {
|
||||
uint64_t res, args, ret;
|
||||
|
||||
@@ -267,6 +267,11 @@ DEF_HELPER_3(vinsertb, void, avr, avr, i32)
|
||||
DEF_HELPER_3(vinserth, void, avr, avr, i32)
|
||||
DEF_HELPER_3(vinsertw, void, avr, avr, i32)
|
||||
DEF_HELPER_3(vinsertd, void, avr, avr, i32)
|
||||
DEF_HELPER_2(vextsb2w, void, avr, avr)
|
||||
DEF_HELPER_2(vextsh2w, void, avr, avr)
|
||||
DEF_HELPER_2(vextsb2d, void, avr, avr)
|
||||
DEF_HELPER_2(vextsh2d, void, avr, avr)
|
||||
DEF_HELPER_2(vextsw2d, void, avr, avr)
|
||||
DEF_HELPER_2(vupkhpx, void, avr, avr)
|
||||
DEF_HELPER_2(vupklpx, void, avr, avr)
|
||||
DEF_HELPER_2(vupkhsb, void, avr, avr)
|
||||
|
||||
@@ -1934,6 +1934,21 @@ VEXTRACT(uw, u32)
|
||||
VEXTRACT(d, u64)
|
||||
#undef VEXTRACT
|
||||
|
||||
#define VEXT_SIGNED(name, element, mask, cast, recast) \
|
||||
void helper_##name(ppc_avr_t *r, ppc_avr_t *b) \
|
||||
{ \
|
||||
int i; \
|
||||
VECTOR_FOR_INORDER_I(i, element) { \
|
||||
r->element[i] = (recast)((cast)(b->element[i] & mask)); \
|
||||
} \
|
||||
}
|
||||
VEXT_SIGNED(vextsb2w, s32, UINT8_MAX, int8_t, int32_t)
|
||||
VEXT_SIGNED(vextsb2d, s64, UINT8_MAX, int8_t, int64_t)
|
||||
VEXT_SIGNED(vextsh2w, s32, UINT16_MAX, int16_t, int32_t)
|
||||
VEXT_SIGNED(vextsh2d, s64, UINT16_MAX, int16_t, int64_t)
|
||||
VEXT_SIGNED(vextsw2d, s64, UINT32_MAX, int32_t, int64_t)
|
||||
#undef VEXT_SIGNED
|
||||
|
||||
#define VSPLTI(suffix, element, splat_type) \
|
||||
void helper_vspltis##suffix(ppc_avr_t *r, uint32_t splat) \
|
||||
{ \
|
||||
|
||||
@@ -815,6 +815,11 @@ GEN_VXFORM_NOA(vclzb, 1, 28)
|
||||
GEN_VXFORM_NOA(vclzh, 1, 29)
|
||||
GEN_VXFORM_NOA(vclzw, 1, 30)
|
||||
GEN_VXFORM_NOA(vclzd, 1, 31)
|
||||
GEN_VXFORM_NOA_2(vextsb2w, 1, 24, 16)
|
||||
GEN_VXFORM_NOA_2(vextsh2w, 1, 24, 17)
|
||||
GEN_VXFORM_NOA_2(vextsb2d, 1, 24, 24)
|
||||
GEN_VXFORM_NOA_2(vextsh2d, 1, 24, 25)
|
||||
GEN_VXFORM_NOA_2(vextsw2d, 1, 24, 26)
|
||||
GEN_VXFORM_NOA_2(vctzb, 1, 24, 28)
|
||||
GEN_VXFORM_NOA_2(vctzh, 1, 24, 29)
|
||||
GEN_VXFORM_NOA_2(vctzw, 1, 24, 30)
|
||||
|
||||
@@ -215,6 +215,11 @@ GEN_VXFORM_DUAL_INV(vspltish, vinserth, 6, 13, 0x00000000, 0x100000,
|
||||
GEN_VXFORM_DUAL_INV(vspltisw, vinsertw, 6, 14, 0x00000000, 0x100000,
|
||||
PPC_ALTIVEC),
|
||||
GEN_VXFORM_300_EXT(vinsertd, 6, 15, 0x100000),
|
||||
GEN_VXFORM_300_EO(vextsb2w, 0x01, 0x18, 0x10),
|
||||
GEN_VXFORM_300_EO(vextsh2w, 0x01, 0x18, 0x11),
|
||||
GEN_VXFORM_300_EO(vextsb2d, 0x01, 0x18, 0x18),
|
||||
GEN_VXFORM_300_EO(vextsh2d, 0x01, 0x18, 0x19),
|
||||
GEN_VXFORM_300_EO(vextsw2d, 0x01, 0x18, 0x1A),
|
||||
GEN_VXFORM_300_EO(vctzb, 0x01, 0x18, 0x1C),
|
||||
GEN_VXFORM_300_EO(vctzh, 0x01, 0x18, 0x1D),
|
||||
GEN_VXFORM_300_EO(vctzw, 0x01, 0x18, 0x1E),
|
||||
|
||||
@@ -112,7 +112,7 @@ typedef struct {
|
||||
g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
|
||||
} while (0)
|
||||
|
||||
static const char *disk = "tests/acpi-test-disk.raw";
|
||||
static char disk[] = "tests/acpi-test-disk-XXXXXX";
|
||||
static const char *data_dir = "tests/acpi-test-data";
|
||||
#ifdef CONFIG_IASL
|
||||
static const char *iasl = stringify(CONFIG_IASL);
|
||||
|
||||
+16
-9
@@ -69,25 +69,32 @@ static uint8_t boot_sector[0x7e000] = {
|
||||
};
|
||||
|
||||
/* Create boot disk file. */
|
||||
int boot_sector_init(const char *fname)
|
||||
int boot_sector_init(char *fname)
|
||||
{
|
||||
FILE *f = fopen(fname, "w");
|
||||
int fd, ret;
|
||||
size_t len = sizeof boot_sector;
|
||||
|
||||
if (!f) {
|
||||
fd = mkstemp(fname);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Couldn't open \"%s\": %s", fname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* For Open Firmware based system, we can use a Forth script instead */
|
||||
if (strcmp(qtest_get_arch(), "ppc64") == 0) {
|
||||
memset(boot_sector, ' ', sizeof boot_sector);
|
||||
sprintf((char *)boot_sector, "\\ Bootscript\n%x %x c! %x %x c!\n",
|
||||
len = sprintf((char *)boot_sector, "\\ Bootscript\n%x %x c! %x %x c!\n",
|
||||
LOW(SIGNATURE), BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET,
|
||||
HIGH(SIGNATURE), BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
|
||||
}
|
||||
|
||||
fwrite(boot_sector, 1, sizeof boot_sector, f);
|
||||
fclose(f);
|
||||
ret = write(fd, boot_sector, len);
|
||||
close(fd);
|
||||
|
||||
if (ret != len) {
|
||||
fprintf(stderr, "Could not write \"%s\"", fname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -99,9 +106,9 @@ void boot_sector_test(void)
|
||||
uint16_t signature;
|
||||
int i;
|
||||
|
||||
/* Wait at most 1 minute */
|
||||
/* Wait at most 90 seconds */
|
||||
#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
|
||||
#define TEST_CYCLES MAX((60 * G_USEC_PER_SEC / TEST_DELAY), 1)
|
||||
#define TEST_CYCLES MAX((90 * G_USEC_PER_SEC / TEST_DELAY), 1)
|
||||
|
||||
/* Poll until code has run and modified memory. Once it has we know BIOS
|
||||
* initialization is done. TODO: check that IP reached the halt
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@
|
||||
#ifndef TEST_BOOT_SECTOR_H
|
||||
#define TEST_BOOT_SECTOR_H
|
||||
|
||||
/* Create boot disk file. */
|
||||
int boot_sector_init(const char *fname);
|
||||
/* Create boot disk file. fname must be a suitable string for mkstemp() */
|
||||
int boot_sector_init(char *fname);
|
||||
|
||||
/* Loop until signature in memory is OK. */
|
||||
void boot_sector_test(void);
|
||||
|
||||
@@ -38,7 +38,8 @@ static const TestCase test_cases[] = {
|
||||
{ "ppc", "prep", 0x80000000, .bswap = true },
|
||||
{ "ppc", "bamboo", 0xe8000000, .bswap = true, .superio = "i82378" },
|
||||
{ "ppc64", "mac99", 0xf2000000, .bswap = true, .superio = "i82378" },
|
||||
{ "ppc64", "pseries", 0x10080000000ULL,
|
||||
{ "ppc64", "pseries", (1ULL << 45), .bswap = true, .superio = "i82378" },
|
||||
{ "ppc64", "pseries-2.7", 0x10080000000ULL,
|
||||
.bswap = true, .superio = "i82378" },
|
||||
{ "sh4", "r2d", 0xfe240000, .superio = "i82378" },
|
||||
{ "sh4eb", "r2d", 0xfe240000, .bswap = true, .superio = "i82378" },
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user