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-4.2-20191004' into staging
ppc patch queue 2019-10-04
Here's the next batch of ppc and spapr patches. Includes:
* Fist part of a large cleanup to irq infrastructure
* Recreate the full FDT at CAS time, instead of making a difficult
to follow set of updates. This will help us move towards
eliminating CAS reboots altogether
* No longer provide RTAS blob to SLOF - SLOF can include it just as
well itself, since guests will generally need to relocate it with
a call to instantiate-rtas
* A number of DFP fixes and cleanups from Mark Cave-Ayland
* Assorted bugfixes
* Several new small devices for powernv
# gpg: Signature made Fri 04 Oct 2019 10:35:57 BST
# 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/dgibson/tags/ppc-for-4.2-20191004: (53 commits)
ppc/pnv: Remove the XICSFabric Interface from the POWER9 machine
spapr: Eliminate SpaprIrq::init hook
spapr: Add return value to spapr_irq_check()
spapr: Use less cryptic representation of which irq backends are supported
xive: Improve irq claim/free path
spapr, xics, xive: Better use of assert()s on irq claim/free paths
spapr: Handle freeing of multiple irqs in frontend only
spapr: Remove unhelpful tracepoints from spapr_irq_free_xics()
spapr: Eliminate SpaprIrq:get_nodename method
spapr: Simplify spapr_qirq() handling
spapr: Fix indexing of XICS irqs
spapr: Eliminate nr_irqs parameter to SpaprIrq::init
spapr: Clarify and fix handling of nr_irqs
spapr: Replace spapr_vio_qirq() helper with spapr_vio_irq_pulse() helper
spapr: Fold spapr_phb_lsi_qirq() into its single caller
xics: Create sPAPR specific ICS subtype
xics: Merge TYPE_ICS_BASE and TYPE_ICS_SIMPLE classes
xics: Eliminate reset hook
xics: Rename misleading ics_simple_*() functions
xics: Eliminate 'reject', 'resend' and 'eoi' class hooks
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -1077,8 +1077,6 @@ F: hw/*/spapr*
|
||||
F: include/hw/*/spapr*
|
||||
F: hw/*/xics*
|
||||
F: include/hw/*/xics*
|
||||
F: pc-bios/spapr-rtas/*
|
||||
F: pc-bios/spapr-rtas.bin
|
||||
F: pc-bios/slof.bin
|
||||
F: docs/specs/ppc-spapr-hcalls.txt
|
||||
F: docs/specs/ppc-spapr-hotplug.txt
|
||||
|
||||
@@ -769,7 +769,7 @@ qemu-nsis.bmp \
|
||||
bamboo.dtb canyonlands.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
|
||||
multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin \
|
||||
s390-ccw.img s390-netboot.img \
|
||||
spapr-rtas.bin slof.bin skiboot.lid \
|
||||
slof.bin skiboot.lid \
|
||||
palcode-clipper \
|
||||
u-boot.e500 u-boot-sam460-20100605.bin \
|
||||
qemu_vga.ndrv \
|
||||
|
||||
@@ -6166,9 +6166,6 @@ if { test "$cpu" = "i386" || test "$cpu" = "x86_64"; } && \
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if test "$ARCH" = "ppc64" && test "$targetos" != "Darwin" ; then
|
||||
roms="$roms spapr-rtas"
|
||||
fi
|
||||
|
||||
# Only build s390-ccw bios if we're on s390x and the compiler has -march=z900
|
||||
if test "$cpu" = "s390x" ; then
|
||||
@@ -7800,13 +7797,12 @@ fi
|
||||
DIRS="tests tests/tcg tests/tcg/lm32 tests/libqos tests/qapi-schema tests/qemu-iotests tests/vm"
|
||||
DIRS="$DIRS tests/fp tests/qgraph"
|
||||
DIRS="$DIRS docs docs/interop fsdev scsi"
|
||||
DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw"
|
||||
DIRS="$DIRS pc-bios/optionrom pc-bios/s390-ccw"
|
||||
DIRS="$DIRS roms/seabios roms/vgabios"
|
||||
LINKS="Makefile"
|
||||
LINKS="$LINKS tests/tcg/lm32/Makefile po/Makefile"
|
||||
LINKS="$LINKS tests/tcg/Makefile.target tests/fp/Makefile"
|
||||
LINKS="$LINKS pc-bios/optionrom/Makefile pc-bios/keymaps"
|
||||
LINKS="$LINKS pc-bios/spapr-rtas/Makefile"
|
||||
LINKS="$LINKS pc-bios/s390-ccw/Makefile"
|
||||
LINKS="$LINKS roms/seabios/Makefile roms/vgabios/Makefile"
|
||||
LINKS="$LINKS pc-bios/qemu-icon.bmp"
|
||||
|
||||
+1
-2
@@ -5,7 +5,6 @@
|
||||
#include "cpu.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "chardev/char-fe.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/ppc/spapr.h"
|
||||
#include "hw/ppc/spapr_vio.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
@@ -37,7 +36,7 @@ static void vty_receive(void *opaque, const uint8_t *buf, int size)
|
||||
|
||||
if ((dev->in == dev->out) && size) {
|
||||
/* toggle line to simulate edge interrupt */
|
||||
qemu_irq_pulse(spapr_vio_qirq(&dev->sdev));
|
||||
spapr_vio_irq_pulse(&dev->sdev);
|
||||
}
|
||||
for (i = 0; i < size; i++) {
|
||||
if (dev->in - dev->out >= VTERM_BUFSIZE) {
|
||||
|
||||
+10
-16
@@ -528,12 +528,15 @@ static void spapr_xive_register_types(void)
|
||||
|
||||
type_init(spapr_xive_register_types)
|
||||
|
||||
bool spapr_xive_irq_claim(SpaprXive *xive, uint32_t lisn, bool lsi)
|
||||
int spapr_xive_irq_claim(SpaprXive *xive, int lisn, bool lsi, Error **errp)
|
||||
{
|
||||
XiveSource *xsrc = &xive->source;
|
||||
|
||||
if (lisn >= xive->nr_irqs) {
|
||||
return false;
|
||||
assert(lisn < xive->nr_irqs);
|
||||
|
||||
if (xive_eas_is_valid(&xive->eat[lisn])) {
|
||||
error_setg(errp, "IRQ %d is not free", lisn);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -545,26 +548,17 @@ bool spapr_xive_irq_claim(SpaprXive *xive, uint32_t lisn, bool lsi)
|
||||
}
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
kvmppc_xive_source_reset_one(xsrc, lisn, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return false;
|
||||
}
|
||||
return kvmppc_xive_source_reset_one(xsrc, lisn, errp);
|
||||
}
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool spapr_xive_irq_free(SpaprXive *xive, uint32_t lisn)
|
||||
void spapr_xive_irq_free(SpaprXive *xive, int lisn)
|
||||
{
|
||||
if (lisn >= xive->nr_irqs) {
|
||||
return false;
|
||||
}
|
||||
assert(lisn < xive->nr_irqs);
|
||||
|
||||
xive->eat[lisn].w &= cpu_to_be64(~EAS_VALID);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -232,14 +232,14 @@ void kvmppc_xive_sync_source(SpaprXive *xive, uint32_t lisn, Error **errp)
|
||||
* only need to inform the KVM XIVE device about their type: LSI or
|
||||
* MSI.
|
||||
*/
|
||||
void kvmppc_xive_source_reset_one(XiveSource *xsrc, int srcno, Error **errp)
|
||||
int kvmppc_xive_source_reset_one(XiveSource *xsrc, int srcno, Error **errp)
|
||||
{
|
||||
SpaprXive *xive = SPAPR_XIVE(xsrc->xive);
|
||||
uint64_t state = 0;
|
||||
|
||||
/* The KVM XIVE device is not in use */
|
||||
if (xive->fd == -1) {
|
||||
return;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (xive_source_irq_is_lsi(xsrc, srcno)) {
|
||||
@@ -249,17 +249,22 @@ void kvmppc_xive_source_reset_one(XiveSource *xsrc, int srcno, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_SOURCE, srcno, &state,
|
||||
true, errp);
|
||||
return kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_SOURCE, srcno, &state,
|
||||
true, errp);
|
||||
}
|
||||
|
||||
static void kvmppc_xive_source_reset(XiveSource *xsrc, Error **errp)
|
||||
{
|
||||
SpaprXive *xive = SPAPR_XIVE(xsrc->xive);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < xsrc->nr_irqs; i++) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (!xive_eas_is_valid(&xive->eat[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
kvmppc_xive_source_reset_one(xsrc, i, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
@@ -328,11 +333,18 @@ uint64_t kvmppc_xive_esb_rw(XiveSource *xsrc, int srcno, uint32_t offset,
|
||||
|
||||
static void kvmppc_xive_source_get_state(XiveSource *xsrc)
|
||||
{
|
||||
SpaprXive *xive = SPAPR_XIVE(xsrc->xive);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < xsrc->nr_irqs; i++) {
|
||||
uint8_t pq;
|
||||
|
||||
if (!xive_eas_is_valid(&xive->eat[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Perform a load without side effect to retrieve the PQ bits */
|
||||
uint8_t pq = xive_esb_read(xsrc, i, XIVE_ESB_GET);
|
||||
pq = xive_esb_read(xsrc, i, XIVE_ESB_GET);
|
||||
|
||||
/* and save PQ locally */
|
||||
xive_source_esb_set(xsrc, i, pq);
|
||||
@@ -521,9 +533,14 @@ static void kvmppc_xive_change_state_handler(void *opaque, int running,
|
||||
*/
|
||||
if (running) {
|
||||
for (i = 0; i < xsrc->nr_irqs; i++) {
|
||||
uint8_t pq = xive_source_esb_get(xsrc, i);
|
||||
uint8_t pq;
|
||||
uint8_t old_pq;
|
||||
|
||||
if (!xive_eas_is_valid(&xive->eat[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pq = xive_source_esb_get(xsrc, i);
|
||||
old_pq = xive_esb_read(xsrc, i, XIVE_ESB_SET_PQ_00 + (pq << 8));
|
||||
|
||||
/*
|
||||
@@ -545,7 +562,13 @@ static void kvmppc_xive_change_state_handler(void *opaque, int running,
|
||||
* migration is in progress.
|
||||
*/
|
||||
for (i = 0; i < xsrc->nr_irqs; i++) {
|
||||
uint8_t pq = xive_esb_read(xsrc, i, XIVE_ESB_GET);
|
||||
uint8_t pq;
|
||||
|
||||
if (!xive_eas_is_valid(&xive->eat[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pq = xive_esb_read(xsrc, i, XIVE_ESB_GET);
|
||||
|
||||
/*
|
||||
* PQ is set to PENDING to possibly catch a triggered
|
||||
@@ -655,6 +678,17 @@ int kvmppc_xive_post_load(SpaprXive *xive, int version_id)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* We can only restore the source config if the source has been
|
||||
* previously set in KVM. Since we don't do that for all interrupts
|
||||
* at reset time anymore, let's do it now.
|
||||
*/
|
||||
kvmppc_xive_source_reset_one(&xive->source, i, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
kvmppc_xive_set_source_config(xive, i, &xive->eat[i], &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
|
||||
@@ -66,12 +66,12 @@ xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR 0x%"PRIx
|
||||
xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server %d given XIRR 0x%"PRIx32" new XIRR 0x%"PRIx32
|
||||
xics_icp_irq(int server, int nr, uint8_t priority) "cpu %d trying to deliver irq 0x%"PRIx32" priority 0x%x"
|
||||
xics_icp_raise(uint32_t xirr, uint8_t pending_priority) "raising IRQ new XIRR=0x%x new pending priority=0x%x"
|
||||
xics_ics_simple_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq 0x%x]"
|
||||
xics_ics_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq 0x%x]"
|
||||
xics_masked_pending(void) "set_irq_msi: masked pending"
|
||||
xics_ics_simple_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq 0x%x]"
|
||||
xics_ics_simple_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq 0x%x [src %d] server 0x%x prio 0x%x"
|
||||
xics_ics_simple_reject(int nr, int srcno) "reject irq 0x%x [src %d]"
|
||||
xics_ics_simple_eoi(int nr) "ics_eoi: irq 0x%x"
|
||||
xics_ics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq 0x%x]"
|
||||
xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_xive: irq 0x%x [src %d] server 0x%x prio 0x%x"
|
||||
xics_ics_reject(int nr, int srcno) "reject irq 0x%x [src %d]"
|
||||
xics_ics_eoi(int nr) "ics_eoi: irq 0x%x"
|
||||
|
||||
# s390_flic_kvm.c
|
||||
flic_create_device(int err) "flic: create device failed %d"
|
||||
|
||||
+71
-141
@@ -98,32 +98,8 @@ void ics_pic_print_info(ICSState *ics, Monitor *mon)
|
||||
#define XISR(icp) (((icp)->xirr) & XISR_MASK)
|
||||
#define CPPR(icp) (((icp)->xirr) >> 24)
|
||||
|
||||
static void ics_reject(ICSState *ics, uint32_t nr)
|
||||
{
|
||||
ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
|
||||
|
||||
if (k->reject) {
|
||||
k->reject(ics, nr);
|
||||
}
|
||||
}
|
||||
|
||||
void ics_resend(ICSState *ics)
|
||||
{
|
||||
ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
|
||||
|
||||
if (k->resend) {
|
||||
k->resend(ics);
|
||||
}
|
||||
}
|
||||
|
||||
static void ics_eoi(ICSState *ics, int nr)
|
||||
{
|
||||
ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
|
||||
|
||||
if (k->eoi) {
|
||||
k->eoi(ics, nr);
|
||||
}
|
||||
}
|
||||
static void ics_reject(ICSState *ics, uint32_t nr);
|
||||
static void ics_eoi(ICSState *ics, uint32_t nr);
|
||||
|
||||
static void icp_check_ipi(ICPState *icp)
|
||||
{
|
||||
@@ -427,7 +403,7 @@ Object *icp_create(Object *cpu, const char *type, XICSFabric *xi, Error **errp)
|
||||
/*
|
||||
* ICS: Source layer
|
||||
*/
|
||||
static void ics_simple_resend_msi(ICSState *ics, int srcno)
|
||||
static void ics_resend_msi(ICSState *ics, int srcno)
|
||||
{
|
||||
ICSIRQState *irq = ics->irqs + srcno;
|
||||
|
||||
@@ -440,7 +416,7 @@ static void ics_simple_resend_msi(ICSState *ics, int srcno)
|
||||
}
|
||||
}
|
||||
|
||||
static void ics_simple_resend_lsi(ICSState *ics, int srcno)
|
||||
static void ics_resend_lsi(ICSState *ics, int srcno)
|
||||
{
|
||||
ICSIRQState *irq = ics->irqs + srcno;
|
||||
|
||||
@@ -452,11 +428,11 @@ static void ics_simple_resend_lsi(ICSState *ics, int srcno)
|
||||
}
|
||||
}
|
||||
|
||||
static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val)
|
||||
static void ics_set_irq_msi(ICSState *ics, int srcno, int val)
|
||||
{
|
||||
ICSIRQState *irq = ics->irqs + srcno;
|
||||
|
||||
trace_xics_ics_simple_set_irq_msi(srcno, srcno + ics->offset);
|
||||
trace_xics_ics_set_irq_msi(srcno, srcno + ics->offset);
|
||||
|
||||
if (val) {
|
||||
if (irq->priority == 0xff) {
|
||||
@@ -468,20 +444,20 @@ static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val)
|
||||
}
|
||||
}
|
||||
|
||||
static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val)
|
||||
static void ics_set_irq_lsi(ICSState *ics, int srcno, int val)
|
||||
{
|
||||
ICSIRQState *irq = ics->irqs + srcno;
|
||||
|
||||
trace_xics_ics_simple_set_irq_lsi(srcno, srcno + ics->offset);
|
||||
trace_xics_ics_set_irq_lsi(srcno, srcno + ics->offset);
|
||||
if (val) {
|
||||
irq->status |= XICS_STATUS_ASSERTED;
|
||||
} else {
|
||||
irq->status &= ~XICS_STATUS_ASSERTED;
|
||||
}
|
||||
ics_simple_resend_lsi(ics, srcno);
|
||||
ics_resend_lsi(ics, srcno);
|
||||
}
|
||||
|
||||
void ics_simple_set_irq(void *opaque, int srcno, int val)
|
||||
void ics_set_irq(void *opaque, int srcno, int val)
|
||||
{
|
||||
ICSState *ics = (ICSState *)opaque;
|
||||
|
||||
@@ -491,13 +467,13 @@ void ics_simple_set_irq(void *opaque, int srcno, int val)
|
||||
}
|
||||
|
||||
if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
|
||||
ics_simple_set_irq_lsi(ics, srcno, val);
|
||||
ics_set_irq_lsi(ics, srcno, val);
|
||||
} else {
|
||||
ics_simple_set_irq_msi(ics, srcno, val);
|
||||
ics_set_irq_msi(ics, srcno, val);
|
||||
}
|
||||
}
|
||||
|
||||
static void ics_simple_write_xive_msi(ICSState *ics, int srcno)
|
||||
static void ics_write_xive_msi(ICSState *ics, int srcno)
|
||||
{
|
||||
ICSIRQState *irq = ics->irqs + srcno;
|
||||
|
||||
@@ -510,13 +486,13 @@ static void ics_simple_write_xive_msi(ICSState *ics, int srcno)
|
||||
icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
|
||||
}
|
||||
|
||||
static void ics_simple_write_xive_lsi(ICSState *ics, int srcno)
|
||||
static void ics_write_xive_lsi(ICSState *ics, int srcno)
|
||||
{
|
||||
ics_simple_resend_lsi(ics, srcno);
|
||||
ics_resend_lsi(ics, srcno);
|
||||
}
|
||||
|
||||
void ics_simple_write_xive(ICSState *ics, int srcno, int server,
|
||||
uint8_t priority, uint8_t saved_priority)
|
||||
void ics_write_xive(ICSState *ics, int srcno, int server,
|
||||
uint8_t priority, uint8_t saved_priority)
|
||||
{
|
||||
ICSIRQState *irq = ics->irqs + srcno;
|
||||
|
||||
@@ -524,21 +500,20 @@ void ics_simple_write_xive(ICSState *ics, int srcno, int server,
|
||||
irq->priority = priority;
|
||||
irq->saved_priority = saved_priority;
|
||||
|
||||
trace_xics_ics_simple_write_xive(ics->offset + srcno, srcno, server,
|
||||
priority);
|
||||
trace_xics_ics_write_xive(ics->offset + srcno, srcno, server, priority);
|
||||
|
||||
if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
|
||||
ics_simple_write_xive_lsi(ics, srcno);
|
||||
ics_write_xive_lsi(ics, srcno);
|
||||
} else {
|
||||
ics_simple_write_xive_msi(ics, srcno);
|
||||
ics_write_xive_msi(ics, srcno);
|
||||
}
|
||||
}
|
||||
|
||||
static void ics_simple_reject(ICSState *ics, uint32_t nr)
|
||||
static void ics_reject(ICSState *ics, uint32_t nr)
|
||||
{
|
||||
ICSIRQState *irq = ics->irqs + nr - ics->offset;
|
||||
|
||||
trace_xics_ics_simple_reject(nr, nr - ics->offset);
|
||||
trace_xics_ics_reject(nr, nr - ics->offset);
|
||||
if (irq->flags & XICS_FLAGS_IRQ_MSI) {
|
||||
irq->status |= XICS_STATUS_REJECTED;
|
||||
} else if (irq->flags & XICS_FLAGS_IRQ_LSI) {
|
||||
@@ -546,100 +521,41 @@ static void ics_simple_reject(ICSState *ics, uint32_t nr)
|
||||
}
|
||||
}
|
||||
|
||||
static void ics_simple_resend(ICSState *ics)
|
||||
void ics_resend(ICSState *ics)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ics->nr_irqs; i++) {
|
||||
/* FIXME: filter by server#? */
|
||||
if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
|
||||
ics_simple_resend_lsi(ics, i);
|
||||
ics_resend_lsi(ics, i);
|
||||
} else {
|
||||
ics_simple_resend_msi(ics, i);
|
||||
ics_resend_msi(ics, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ics_simple_eoi(ICSState *ics, uint32_t nr)
|
||||
static void ics_eoi(ICSState *ics, uint32_t nr)
|
||||
{
|
||||
int srcno = nr - ics->offset;
|
||||
ICSIRQState *irq = ics->irqs + srcno;
|
||||
|
||||
trace_xics_ics_simple_eoi(nr);
|
||||
trace_xics_ics_eoi(nr);
|
||||
|
||||
if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
|
||||
irq->status &= ~XICS_STATUS_SENT;
|
||||
}
|
||||
}
|
||||
|
||||
static void ics_simple_reset(DeviceState *dev)
|
||||
{
|
||||
ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev);
|
||||
|
||||
icsc->parent_reset(dev);
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
ics_set_kvm_state(ICS_BASE(dev), &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ics_simple_reset_handler(void *dev)
|
||||
{
|
||||
ics_simple_reset(dev);
|
||||
}
|
||||
|
||||
static void ics_simple_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ICSState *ics = ICS_SIMPLE(dev);
|
||||
ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics);
|
||||
Error *local_err = NULL;
|
||||
|
||||
icsc->parent_realize(dev, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_register_reset(ics_simple_reset_handler, ics);
|
||||
}
|
||||
|
||||
static void ics_simple_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
ICSStateClass *isc = ICS_BASE_CLASS(klass);
|
||||
|
||||
device_class_set_parent_realize(dc, ics_simple_realize,
|
||||
&isc->parent_realize);
|
||||
device_class_set_parent_reset(dc, ics_simple_reset,
|
||||
&isc->parent_reset);
|
||||
|
||||
isc->reject = ics_simple_reject;
|
||||
isc->resend = ics_simple_resend;
|
||||
isc->eoi = ics_simple_eoi;
|
||||
}
|
||||
|
||||
static const TypeInfo ics_simple_info = {
|
||||
.name = TYPE_ICS_SIMPLE,
|
||||
.parent = TYPE_ICS_BASE,
|
||||
.instance_size = sizeof(ICSState),
|
||||
.class_init = ics_simple_class_init,
|
||||
.class_size = sizeof(ICSStateClass),
|
||||
};
|
||||
|
||||
static void ics_reset_irq(ICSIRQState *irq)
|
||||
{
|
||||
irq->priority = 0xff;
|
||||
irq->saved_priority = 0xff;
|
||||
}
|
||||
|
||||
static void ics_base_reset(DeviceState *dev)
|
||||
static void ics_reset(DeviceState *dev)
|
||||
{
|
||||
ICSState *ics = ICS_BASE(dev);
|
||||
ICSState *ics = ICS(dev);
|
||||
int i;
|
||||
uint8_t flags[ics->nr_irqs];
|
||||
|
||||
@@ -653,17 +569,31 @@ static void ics_base_reset(DeviceState *dev)
|
||||
ics_reset_irq(ics->irqs + i);
|
||||
ics->irqs[i].flags = flags[i];
|
||||
}
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
ics_set_kvm_state(ICS(dev), &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ics_base_realize(DeviceState *dev, Error **errp)
|
||||
static void ics_reset_handler(void *dev)
|
||||
{
|
||||
ICSState *ics = ICS_BASE(dev);
|
||||
Object *obj;
|
||||
Error *err = NULL;
|
||||
ics_reset(dev);
|
||||
}
|
||||
|
||||
obj = object_property_get_link(OBJECT(dev), ICS_PROP_XICS, &err);
|
||||
static void ics_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ICSState *ics = ICS(dev);
|
||||
Error *local_err = NULL;
|
||||
Object *obj;
|
||||
|
||||
obj = object_property_get_link(OBJECT(dev), ICS_PROP_XICS, &local_err);
|
||||
if (!obj) {
|
||||
error_propagate_prepend(errp, err,
|
||||
error_propagate_prepend(errp, local_err,
|
||||
"required link '" ICS_PROP_XICS
|
||||
"' not found: ");
|
||||
return;
|
||||
@@ -675,16 +605,18 @@ static void ics_base_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
|
||||
|
||||
qemu_register_reset(ics_reset_handler, ics);
|
||||
}
|
||||
|
||||
static void ics_base_instance_init(Object *obj)
|
||||
static void ics_instance_init(Object *obj)
|
||||
{
|
||||
ICSState *ics = ICS_BASE(obj);
|
||||
ICSState *ics = ICS(obj);
|
||||
|
||||
ics->offset = XICS_IRQ_BASE;
|
||||
}
|
||||
|
||||
static int ics_base_pre_save(void *opaque)
|
||||
static int ics_pre_save(void *opaque)
|
||||
{
|
||||
ICSState *ics = opaque;
|
||||
|
||||
@@ -695,7 +627,7 @@ static int ics_base_pre_save(void *opaque)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ics_base_post_load(void *opaque, int version_id)
|
||||
static int ics_post_load(void *opaque, int version_id)
|
||||
{
|
||||
ICSState *ics = opaque;
|
||||
|
||||
@@ -713,7 +645,7 @@ static int ics_base_post_load(void *opaque, int version_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_ics_base_irq = {
|
||||
static const VMStateDescription vmstate_ics_irq = {
|
||||
.name = "ics/irq",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 1,
|
||||
@@ -727,45 +659,44 @@ static const VMStateDescription vmstate_ics_base_irq = {
|
||||
},
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_ics_base = {
|
||||
static const VMStateDescription vmstate_ics = {
|
||||
.name = "ics",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.pre_save = ics_base_pre_save,
|
||||
.post_load = ics_base_post_load,
|
||||
.pre_save = ics_pre_save,
|
||||
.post_load = ics_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
/* Sanity check */
|
||||
VMSTATE_UINT32_EQUAL(nr_irqs, ICSState, NULL),
|
||||
|
||||
VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
|
||||
vmstate_ics_base_irq,
|
||||
vmstate_ics_irq,
|
||||
ICSIRQState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
};
|
||||
|
||||
static Property ics_base_properties[] = {
|
||||
static Property ics_properties[] = {
|
||||
DEFINE_PROP_UINT32("nr-irqs", ICSState, nr_irqs, 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void ics_base_class_init(ObjectClass *klass, void *data)
|
||||
static void ics_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = ics_base_realize;
|
||||
dc->props = ics_base_properties;
|
||||
dc->reset = ics_base_reset;
|
||||
dc->vmsd = &vmstate_ics_base;
|
||||
dc->realize = ics_realize;
|
||||
dc->props = ics_properties;
|
||||
dc->reset = ics_reset;
|
||||
dc->vmsd = &vmstate_ics;
|
||||
}
|
||||
|
||||
static const TypeInfo ics_base_info = {
|
||||
.name = TYPE_ICS_BASE,
|
||||
static const TypeInfo ics_info = {
|
||||
.name = TYPE_ICS,
|
||||
.parent = TYPE_DEVICE,
|
||||
.abstract = true,
|
||||
.instance_size = sizeof(ICSState),
|
||||
.instance_init = ics_base_instance_init,
|
||||
.class_init = ics_base_class_init,
|
||||
.instance_init = ics_instance_init,
|
||||
.class_init = ics_class_init,
|
||||
.class_size = sizeof(ICSStateClass),
|
||||
};
|
||||
|
||||
@@ -805,8 +736,7 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
|
||||
|
||||
static void xics_register_types(void)
|
||||
{
|
||||
type_register_static(&ics_simple_info);
|
||||
type_register_static(&ics_base_info);
|
||||
type_register_static(&ics_info);
|
||||
type_register_static(&icp_info);
|
||||
type_register_static(&xics_fabric_info);
|
||||
}
|
||||
|
||||
@@ -190,6 +190,10 @@ void ics_get_kvm_state(ICSState *ics)
|
||||
for (i = 0; i < ics->nr_irqs; i++) {
|
||||
ICSIRQState *irq = &ics->irqs[i];
|
||||
|
||||
if (ics_irq_free(ics, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
kvm_device_access(kernel_xics_fd, KVM_DEV_XICS_GRP_SOURCES,
|
||||
i + ics->offset, &state, false, &error_fatal);
|
||||
|
||||
@@ -301,6 +305,10 @@ int ics_set_kvm_state(ICSState *ics, Error **errp)
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
if (ics_irq_free(ics, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = ics_set_kvm_state_one(ics, i, &local_err);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
|
||||
+40
-8
@@ -179,7 +179,7 @@ static void rtas_set_xive(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
||||
}
|
||||
|
||||
srcno = nr - ics->offset;
|
||||
ics_simple_write_xive(ics, srcno, server, priority, priority);
|
||||
ics_write_xive(ics, srcno, server, priority, priority);
|
||||
|
||||
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
|
||||
}
|
||||
@@ -243,8 +243,8 @@ static void rtas_int_off(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
||||
}
|
||||
|
||||
srcno = nr - ics->offset;
|
||||
ics_simple_write_xive(ics, srcno, ics->irqs[srcno].server, 0xff,
|
||||
ics->irqs[srcno].priority);
|
||||
ics_write_xive(ics, srcno, ics->irqs[srcno].server, 0xff,
|
||||
ics->irqs[srcno].priority);
|
||||
|
||||
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
|
||||
}
|
||||
@@ -276,15 +276,25 @@ static void rtas_int_on(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
||||
}
|
||||
|
||||
srcno = nr - ics->offset;
|
||||
ics_simple_write_xive(ics, srcno, ics->irqs[srcno].server,
|
||||
ics->irqs[srcno].saved_priority,
|
||||
ics->irqs[srcno].saved_priority);
|
||||
ics_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);
|
||||
}
|
||||
|
||||
void xics_spapr_init(SpaprMachineState *spapr)
|
||||
static void ics_spapr_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ICSState *ics = ICS_SPAPR(dev);
|
||||
ICSStateClass *icsc = ICS_GET_CLASS(ics);
|
||||
Error *local_err = NULL;
|
||||
|
||||
icsc->parent_realize(dev, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
spapr_rtas_register(RTAS_IBM_SET_XIVE, "ibm,set-xive", rtas_set_xive);
|
||||
spapr_rtas_register(RTAS_IBM_GET_XIVE, "ibm,get-xive", rtas_get_xive);
|
||||
spapr_rtas_register(RTAS_IBM_INT_OFF, "ibm,int-off", rtas_int_off);
|
||||
@@ -306,7 +316,7 @@ void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
|
||||
};
|
||||
int node;
|
||||
|
||||
_FDT(node = fdt_add_subnode(fdt, 0, XICS_NODENAME));
|
||||
_FDT(node = fdt_add_subnode(fdt, 0, "interrupt-controller"));
|
||||
|
||||
_FDT(fdt_setprop_string(fdt, node, "device_type",
|
||||
"PowerPC-External-Interrupt-Presentation"));
|
||||
@@ -319,3 +329,25 @@ void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
|
||||
_FDT(fdt_setprop_cell(fdt, node, "linux,phandle", phandle));
|
||||
_FDT(fdt_setprop_cell(fdt, node, "phandle", phandle));
|
||||
}
|
||||
|
||||
static void ics_spapr_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
ICSStateClass *isc = ICS_CLASS(klass);
|
||||
|
||||
device_class_set_parent_realize(dc, ics_spapr_realize,
|
||||
&isc->parent_realize);
|
||||
}
|
||||
|
||||
static const TypeInfo ics_spapr_info = {
|
||||
.name = TYPE_ICS_SPAPR,
|
||||
.parent = TYPE_ICS,
|
||||
.class_init = ics_spapr_class_init,
|
||||
};
|
||||
|
||||
static void xics_spapr_register_types(void)
|
||||
{
|
||||
type_register_static(&ics_spapr_info);
|
||||
}
|
||||
|
||||
type_init(xics_spapr_register_types)
|
||||
|
||||
@@ -1396,6 +1396,14 @@ static bool xive_presenter_match(XiveRouter *xrtr, uint8_t format,
|
||||
XiveTCTX *tctx = xive_router_get_tctx(xrtr, cs);
|
||||
int ring;
|
||||
|
||||
/*
|
||||
* Skip partially initialized vCPUs. This can happen when
|
||||
* vCPUs are hotplugged.
|
||||
*/
|
||||
if (!tctx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* HW checks that the CPU is enabled in the Physical Thread
|
||||
* Enable Register (PTER).
|
||||
|
||||
+1
-2
@@ -27,7 +27,6 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "hw/irq.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/module.h"
|
||||
#include "net/net.h"
|
||||
@@ -267,7 +266,7 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
|
||||
}
|
||||
|
||||
if (sdev->signal_state & 1) {
|
||||
qemu_irq_pulse(spapr_vio_qirq(sdev));
|
||||
spapr_vio_irq_pulse(sdev);
|
||||
}
|
||||
|
||||
return size;
|
||||
|
||||
@@ -9,6 +9,7 @@ obj-$(CONFIG_PSERIES) += spapr_tpm_proxy.o
|
||||
obj-$(CONFIG_SPAPR_RNG) += spapr_rng.o
|
||||
# IBM PowerNV
|
||||
obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o pnv_core.o pnv_lpc.o pnv_psi.o pnv_occ.o pnv_bmc.o
|
||||
obj-$(CONFIG_POWERNV) += pnv_homer.o
|
||||
ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
|
||||
obj-y += spapr_pci_vfio.o spapr_pci_nvlink2.o
|
||||
endif
|
||||
|
||||
+84
-34
@@ -187,7 +187,8 @@ static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
|
||||
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size)));
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size",
|
||||
cpu->hash64_opts->slb_size)));
|
||||
_FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
|
||||
_FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
|
||||
|
||||
@@ -200,19 +201,23 @@ static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
|
||||
segs, sizeof(segs))));
|
||||
}
|
||||
|
||||
/* Advertise VMX/VSX (vector extensions) if available
|
||||
/*
|
||||
* Advertise VMX/VSX (vector extensions) if available
|
||||
* 0 / no property == no vector extensions
|
||||
* 1 == VMX / Altivec available
|
||||
* 2 == VSX available */
|
||||
* 2 == VSX available
|
||||
*/
|
||||
if (env->insns_flags & PPC_ALTIVEC) {
|
||||
uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
|
||||
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
|
||||
}
|
||||
|
||||
/* Advertise DFP (Decimal Floating Point) if available
|
||||
/*
|
||||
* Advertise DFP (Decimal Floating Point) if available
|
||||
* 0 / no property == no DFP
|
||||
* 1 == DFP available */
|
||||
* 1 == DFP available
|
||||
*/
|
||||
if (env->insns_flags2 & PPC2_DFP) {
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
|
||||
}
|
||||
@@ -424,7 +429,8 @@ static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The default LPC bus of a multichip system is on chip 0. It's
|
||||
/*
|
||||
* The default LPC bus of a multichip system is on chip 0. It's
|
||||
* recognized by the firmware (skiboot) using a "primary" property.
|
||||
*/
|
||||
static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
|
||||
@@ -442,8 +448,10 @@ static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
|
||||
assert(phandle > 0);
|
||||
_FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
|
||||
|
||||
/* ISA devices are not necessarily parented to the ISA bus so we
|
||||
* can not use object_child_foreach() */
|
||||
/*
|
||||
* ISA devices are not necessarily parented to the ISA bus so we
|
||||
* can not use object_child_foreach()
|
||||
*/
|
||||
qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
|
||||
&args);
|
||||
}
|
||||
@@ -545,7 +553,8 @@ static void pnv_reset(MachineState *machine)
|
||||
|
||||
qemu_devices_reset();
|
||||
|
||||
/* OpenPOWER systems have a BMC, which can be defined on the
|
||||
/*
|
||||
* OpenPOWER systems have a BMC, which can be defined on the
|
||||
* command line with:
|
||||
*
|
||||
* -device ipmi-bmc-sim,id=bmc0
|
||||
@@ -705,7 +714,8 @@ static void pnv_init(MachineState *machine)
|
||||
|
||||
pnv->chips[i] = PNV_CHIP(chip);
|
||||
|
||||
/* TODO: put all the memory in one node on chip 0 until we find a
|
||||
/*
|
||||
* TODO: put all the memory in one node on chip 0 until we find a
|
||||
* way to specify different ranges for each chip
|
||||
*/
|
||||
if (i == 0) {
|
||||
@@ -732,8 +742,10 @@ static void pnv_init(MachineState *machine)
|
||||
/* Create an RTC ISA device too */
|
||||
mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
|
||||
|
||||
/* OpenPOWER systems use a IPMI SEL Event message to notify the
|
||||
* host to powerdown */
|
||||
/*
|
||||
* OpenPOWER systems use a IPMI SEL Event message to notify the
|
||||
* host to powerdown
|
||||
*/
|
||||
pnv->powerdown_notifier.notify = pnv_powerdown_notify;
|
||||
qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
|
||||
}
|
||||
@@ -803,7 +815,8 @@ static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
|
||||
pnv_cpu->intc = obj;
|
||||
}
|
||||
|
||||
/* Allowed core identifiers on a POWER8 Processor Chip :
|
||||
/*
|
||||
* Allowed core identifiers on a POWER8 Processor Chip :
|
||||
*
|
||||
* <EX0 reserved>
|
||||
* EX1 - Venice only
|
||||
@@ -847,6 +860,11 @@ static void pnv_chip_power8_instance_init(Object *obj)
|
||||
TYPE_PNV8_OCC, &error_abort, NULL);
|
||||
object_property_add_const_link(OBJECT(&chip8->occ), "psi",
|
||||
OBJECT(&chip8->psi), &error_abort);
|
||||
|
||||
object_initialize_child(obj, "homer", &chip8->homer, sizeof(chip8->homer),
|
||||
TYPE_PNV8_HOMER, &error_abort, NULL);
|
||||
object_property_add_const_link(OBJECT(&chip8->homer), "chip", obj,
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
|
||||
@@ -923,8 +941,10 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
|
||||
(uint64_t) PNV_XSCOM_BASE(chip),
|
||||
PNV_XSCOM_LPC_BASE);
|
||||
|
||||
/* Interrupt Management Area. This is the memory region holding
|
||||
* all the Interrupt Control Presenter (ICP) registers */
|
||||
/*
|
||||
* Interrupt Management Area. This is the memory region holding
|
||||
* all the Interrupt Control Presenter (ICP) registers
|
||||
*/
|
||||
pnv_chip_icp_realize(chip8, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
@@ -938,6 +958,20 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
|
||||
|
||||
/* OCC SRAM model */
|
||||
memory_region_add_subregion(get_system_memory(), PNV_OCC_COMMON_AREA(chip),
|
||||
&chip8->occ.sram_regs);
|
||||
|
||||
/* HOMER */
|
||||
object_property_set_bool(OBJECT(&chip8->homer), true, "realized",
|
||||
&local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
|
||||
&chip8->homer.regs);
|
||||
}
|
||||
|
||||
static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
|
||||
@@ -1020,6 +1054,11 @@ static void pnv_chip_power9_instance_init(Object *obj)
|
||||
TYPE_PNV9_OCC, &error_abort, NULL);
|
||||
object_property_add_const_link(OBJECT(&chip9->occ), "psi",
|
||||
OBJECT(&chip9->psi), &error_abort);
|
||||
|
||||
object_initialize_child(obj, "homer", &chip9->homer, sizeof(chip9->homer),
|
||||
TYPE_PNV9_HOMER, &error_abort, NULL);
|
||||
object_property_add_const_link(OBJECT(&chip9->homer), "chip", obj,
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
|
||||
@@ -1126,6 +1165,20 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
|
||||
|
||||
/* OCC SRAM model */
|
||||
memory_region_add_subregion(get_system_memory(), PNV9_OCC_COMMON_AREA(chip),
|
||||
&chip9->occ.sram_regs);
|
||||
|
||||
/* HOMER */
|
||||
object_property_set_bool(OBJECT(&chip9->homer), true, "realized",
|
||||
&local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
|
||||
&chip9->homer.regs);
|
||||
}
|
||||
|
||||
static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
|
||||
@@ -1404,8 +1457,8 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->init = pnv_init;
|
||||
mc->reset = pnv_reset;
|
||||
mc->max_cpus = MAX_CPUS;
|
||||
mc->block_default_type = IF_IDE; /* Pnv provides a AHCI device for
|
||||
* storage */
|
||||
/* Pnv provides a AHCI device for storage */
|
||||
mc->block_default_type = IF_IDE;
|
||||
mc->no_parallel = 1;
|
||||
mc->default_boot_order = NULL;
|
||||
/*
|
||||
@@ -1432,23 +1485,21 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data)
|
||||
.parent = TYPE_PNV9_CHIP, \
|
||||
}
|
||||
|
||||
#define DEFINE_PNV_MACHINE_TYPE(cpu, class_initfn) \
|
||||
{ \
|
||||
.name = MACHINE_TYPE_NAME(cpu), \
|
||||
.parent = TYPE_PNV_MACHINE, \
|
||||
.instance_size = sizeof(PnvMachineState), \
|
||||
.instance_init = pnv_machine_instance_init, \
|
||||
.class_init = class_initfn, \
|
||||
.interfaces = (InterfaceInfo[]) { \
|
||||
{ TYPE_XICS_FABRIC }, \
|
||||
{ TYPE_INTERRUPT_STATS_PROVIDER }, \
|
||||
{ }, \
|
||||
}, \
|
||||
}
|
||||
|
||||
static const TypeInfo types[] = {
|
||||
DEFINE_PNV_MACHINE_TYPE("powernv8", pnv_machine_power8_class_init),
|
||||
DEFINE_PNV_MACHINE_TYPE("powernv9", pnv_machine_power9_class_init),
|
||||
{
|
||||
.name = MACHINE_TYPE_NAME("powernv9"),
|
||||
.parent = TYPE_PNV_MACHINE,
|
||||
.class_init = pnv_machine_power9_class_init,
|
||||
},
|
||||
{
|
||||
.name = MACHINE_TYPE_NAME("powernv8"),
|
||||
.parent = TYPE_PNV_MACHINE,
|
||||
.class_init = pnv_machine_power8_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_XICS_FABRIC },
|
||||
{ },
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = TYPE_PNV_MACHINE,
|
||||
.parent = TYPE_MACHINE,
|
||||
@@ -1457,7 +1508,6 @@ static const TypeInfo types[] = {
|
||||
.instance_init = pnv_machine_instance_init,
|
||||
.class_init = pnv_machine_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_XICS_FABRIC },
|
||||
{ TYPE_INTERRUPT_STATS_PROVIDER },
|
||||
{ },
|
||||
},
|
||||
|
||||
+1
-4
@@ -77,13 +77,10 @@ void pnv_dt_bmc_sensors(IPMIBmc *bmc, void *fdt)
|
||||
const struct ipmi_sdr_compact *sdr;
|
||||
uint16_t nextrec;
|
||||
|
||||
offset = fdt_add_subnode(fdt, 0, "/bmc");
|
||||
offset = fdt_add_subnode(fdt, 0, "bmc");
|
||||
_FDT(offset);
|
||||
|
||||
_FDT((fdt_setprop_string(fdt, offset, "name", "bmc")));
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0x1)));
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "#size-cells", 0x0)));
|
||||
|
||||
offset = fdt_add_subnode(fdt, offset, "sensors");
|
||||
_FDT(offset);
|
||||
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* QEMU PowerPC PowerNV Emulation of a few HOMER related registers
|
||||
*
|
||||
* Copyright (c) 2019, IBM Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "exec/hwaddr.h"
|
||||
#include "exec/memory.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "hw/qdev-core.h"
|
||||
#include "hw/ppc/pnv.h"
|
||||
#include "hw/ppc/pnv_homer.h"
|
||||
|
||||
|
||||
static bool core_max_array(PnvHomer *homer, hwaddr addr)
|
||||
{
|
||||
int i;
|
||||
PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
|
||||
|
||||
for (i = 0; i <= homer->chip->nr_cores; i++) {
|
||||
if (addr == (hmrc->core_max_base + i)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* P8 Pstate table */
|
||||
|
||||
#define PNV8_OCC_PSTATE_VERSION 0x1f8001
|
||||
#define PNV8_OCC_PSTATE_MIN 0x1f8003
|
||||
#define PNV8_OCC_PSTATE_VALID 0x1f8000
|
||||
#define PNV8_OCC_PSTATE_THROTTLE 0x1f8002
|
||||
#define PNV8_OCC_PSTATE_NOM 0x1f8004
|
||||
#define PNV8_OCC_PSTATE_TURBO 0x1f8005
|
||||
#define PNV8_OCC_PSTATE_ULTRA_TURBO 0x1f8006
|
||||
#define PNV8_OCC_PSTATE_DATA 0x1f8008
|
||||
#define PNV8_OCC_PSTATE_ID_ZERO 0x1f8010
|
||||
#define PNV8_OCC_PSTATE_ID_ONE 0x1f8018
|
||||
#define PNV8_OCC_PSTATE_ID_TWO 0x1f8020
|
||||
#define PNV8_OCC_VDD_VOLTAGE_IDENTIFIER 0x1f8012
|
||||
#define PNV8_OCC_VCS_VOLTAGE_IDENTIFIER 0x1f8013
|
||||
#define PNV8_OCC_PSTATE_ZERO_FREQUENCY 0x1f8014
|
||||
#define PNV8_OCC_PSTATE_ONE_FREQUENCY 0x1f801c
|
||||
#define PNV8_OCC_PSTATE_TWO_FREQUENCY 0x1f8024
|
||||
#define PNV8_CORE_MAX_BASE 0x1f8810
|
||||
|
||||
|
||||
static uint64_t pnv_power8_homer_read(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
{
|
||||
PnvHomer *homer = PNV_HOMER(opaque);
|
||||
|
||||
switch (addr) {
|
||||
case PNV8_OCC_PSTATE_VERSION:
|
||||
case PNV8_OCC_PSTATE_MIN:
|
||||
case PNV8_OCC_PSTATE_ID_ZERO:
|
||||
return 0;
|
||||
case PNV8_OCC_PSTATE_VALID:
|
||||
case PNV8_OCC_PSTATE_THROTTLE:
|
||||
case PNV8_OCC_PSTATE_NOM:
|
||||
case PNV8_OCC_PSTATE_TURBO:
|
||||
case PNV8_OCC_PSTATE_ID_ONE:
|
||||
case PNV8_OCC_VDD_VOLTAGE_IDENTIFIER:
|
||||
case PNV8_OCC_VCS_VOLTAGE_IDENTIFIER:
|
||||
return 1;
|
||||
case PNV8_OCC_PSTATE_ULTRA_TURBO:
|
||||
case PNV8_OCC_PSTATE_ID_TWO:
|
||||
return 2;
|
||||
case PNV8_OCC_PSTATE_DATA:
|
||||
return 0x1000000000000000;
|
||||
/* P8 frequency for 0, 1, and 2 pstates */
|
||||
case PNV8_OCC_PSTATE_ZERO_FREQUENCY:
|
||||
case PNV8_OCC_PSTATE_ONE_FREQUENCY:
|
||||
case PNV8_OCC_PSTATE_TWO_FREQUENCY:
|
||||
return 3000;
|
||||
}
|
||||
/* pstate table core max array */
|
||||
if (core_max_array(homer, addr)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pnv_power8_homer_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
/* callback function defined to homer write */
|
||||
return;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps pnv_power8_homer_ops = {
|
||||
.read = pnv_power8_homer_read,
|
||||
.write = pnv_power8_homer_write,
|
||||
.valid.min_access_size = 1,
|
||||
.valid.max_access_size = 8,
|
||||
.impl.min_access_size = 1,
|
||||
.impl.max_access_size = 8,
|
||||
.endianness = DEVICE_BIG_ENDIAN,
|
||||
};
|
||||
|
||||
static void pnv_homer_power8_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
|
||||
|
||||
homer->homer_size = PNV_HOMER_SIZE;
|
||||
homer->homer_ops = &pnv_power8_homer_ops;
|
||||
homer->core_max_base = PNV8_CORE_MAX_BASE;
|
||||
}
|
||||
|
||||
static const TypeInfo pnv_homer_power8_type_info = {
|
||||
.name = TYPE_PNV8_HOMER,
|
||||
.parent = TYPE_PNV_HOMER,
|
||||
.instance_size = sizeof(PnvHomer),
|
||||
.class_init = pnv_homer_power8_class_init,
|
||||
};
|
||||
|
||||
/* P9 Pstate table */
|
||||
|
||||
#define PNV9_OCC_PSTATE_ID_ZERO 0xe2018
|
||||
#define PNV9_OCC_PSTATE_ID_ONE 0xe2020
|
||||
#define PNV9_OCC_PSTATE_ID_TWO 0xe2028
|
||||
#define PNV9_OCC_PSTATE_DATA 0xe2000
|
||||
#define PNV9_OCC_PSTATE_DATA_AREA 0xe2008
|
||||
#define PNV9_OCC_PSTATE_MIN 0xe2003
|
||||
#define PNV9_OCC_PSTATE_NOM 0xe2004
|
||||
#define PNV9_OCC_PSTATE_TURBO 0xe2005
|
||||
#define PNV9_OCC_PSTATE_ULTRA_TURBO 0xe2818
|
||||
#define PNV9_OCC_MAX_PSTATE_ULTRA_TURBO 0xe2006
|
||||
#define PNV9_OCC_PSTATE_MAJOR_VERSION 0xe2001
|
||||
#define PNV9_OCC_OPAL_RUNTIME_DATA 0xe2b85
|
||||
#define PNV9_CHIP_HOMER_IMAGE_POINTER 0x200008
|
||||
#define PNV9_CHIP_HOMER_BASE 0x0
|
||||
#define PNV9_OCC_PSTATE_ZERO_FREQUENCY 0xe201c
|
||||
#define PNV9_OCC_PSTATE_ONE_FREQUENCY 0xe2024
|
||||
#define PNV9_OCC_PSTATE_TWO_FREQUENCY 0xe202c
|
||||
#define PNV9_OCC_ROLE_MASTER_OR_SLAVE 0xe2002
|
||||
#define PNV9_CORE_MAX_BASE 0xe2819
|
||||
|
||||
|
||||
static uint64_t pnv_power9_homer_read(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
{
|
||||
PnvHomer *homer = PNV_HOMER(opaque);
|
||||
|
||||
switch (addr) {
|
||||
case PNV9_OCC_MAX_PSTATE_ULTRA_TURBO:
|
||||
case PNV9_OCC_PSTATE_ID_ZERO:
|
||||
return 0;
|
||||
case PNV9_OCC_PSTATE_DATA:
|
||||
case PNV9_OCC_ROLE_MASTER_OR_SLAVE:
|
||||
case PNV9_OCC_PSTATE_NOM:
|
||||
case PNV9_OCC_PSTATE_TURBO:
|
||||
case PNV9_OCC_PSTATE_ID_ONE:
|
||||
case PNV9_OCC_PSTATE_ULTRA_TURBO:
|
||||
case PNV9_OCC_OPAL_RUNTIME_DATA:
|
||||
return 1;
|
||||
case PNV9_OCC_PSTATE_MIN:
|
||||
case PNV9_OCC_PSTATE_ID_TWO:
|
||||
return 2;
|
||||
|
||||
/* 3000 khz frequency for 0, 1, and 2 pstates */
|
||||
case PNV9_OCC_PSTATE_ZERO_FREQUENCY:
|
||||
case PNV9_OCC_PSTATE_ONE_FREQUENCY:
|
||||
case PNV9_OCC_PSTATE_TWO_FREQUENCY:
|
||||
return 3000;
|
||||
case PNV9_OCC_PSTATE_MAJOR_VERSION:
|
||||
return 0x90;
|
||||
case PNV9_CHIP_HOMER_BASE:
|
||||
case PNV9_OCC_PSTATE_DATA_AREA:
|
||||
case PNV9_CHIP_HOMER_IMAGE_POINTER:
|
||||
return 0x1000000000000000;
|
||||
}
|
||||
/* pstate table core max array */
|
||||
if (core_max_array(homer, addr)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pnv_power9_homer_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
/* callback function defined to homer write */
|
||||
return;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps pnv_power9_homer_ops = {
|
||||
.read = pnv_power9_homer_read,
|
||||
.write = pnv_power9_homer_write,
|
||||
.valid.min_access_size = 1,
|
||||
.valid.max_access_size = 8,
|
||||
.impl.min_access_size = 1,
|
||||
.impl.max_access_size = 8,
|
||||
.endianness = DEVICE_BIG_ENDIAN,
|
||||
};
|
||||
|
||||
static void pnv_homer_power9_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
|
||||
|
||||
homer->homer_size = PNV9_HOMER_SIZE;
|
||||
homer->homer_ops = &pnv_power9_homer_ops;
|
||||
homer->core_max_base = PNV9_CORE_MAX_BASE;
|
||||
}
|
||||
|
||||
static const TypeInfo pnv_homer_power9_type_info = {
|
||||
.name = TYPE_PNV9_HOMER,
|
||||
.parent = TYPE_PNV_HOMER,
|
||||
.instance_size = sizeof(PnvHomer),
|
||||
.class_init = pnv_homer_power9_class_init,
|
||||
};
|
||||
|
||||
static void pnv_homer_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PnvHomer *homer = PNV_HOMER(dev);
|
||||
PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
|
||||
Object *obj;
|
||||
Error *local_err = NULL;
|
||||
|
||||
obj = object_property_get_link(OBJECT(dev), "chip", &local_err);
|
||||
if (!obj) {
|
||||
error_propagate(errp, local_err);
|
||||
error_prepend(errp, "required link 'chip' not found: ");
|
||||
return;
|
||||
}
|
||||
homer->chip = PNV_CHIP(obj);
|
||||
/* homer region */
|
||||
memory_region_init_io(&homer->regs, OBJECT(dev),
|
||||
hmrc->homer_ops, homer, "homer-main-memory",
|
||||
hmrc->homer_size);
|
||||
}
|
||||
|
||||
static void pnv_homer_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = pnv_homer_realize;
|
||||
dc->desc = "PowerNV HOMER Memory";
|
||||
}
|
||||
|
||||
static const TypeInfo pnv_homer_type_info = {
|
||||
.name = TYPE_PNV_HOMER,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_size = sizeof(PnvHomer),
|
||||
.class_init = pnv_homer_class_init,
|
||||
.class_size = sizeof(PnvHomerClass),
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void pnv_homer_register_types(void)
|
||||
{
|
||||
type_register_static(&pnv_homer_type_info);
|
||||
type_register_static(&pnv_homer_power8_type_info);
|
||||
type_register_static(&pnv_homer_power9_type_info);
|
||||
}
|
||||
|
||||
type_init(pnv_homer_register_types);
|
||||
@@ -30,6 +30,24 @@
|
||||
#define OCB_OCI_OCCMISC_AND 0x4021
|
||||
#define OCB_OCI_OCCMISC_OR 0x4022
|
||||
|
||||
/* OCC sensors */
|
||||
#define OCC_SENSOR_DATA_BLOCK_OFFSET 0x580000
|
||||
#define OCC_SENSOR_DATA_VALID 0x580001
|
||||
#define OCC_SENSOR_DATA_VERSION 0x580002
|
||||
#define OCC_SENSOR_DATA_READING_VERSION 0x580004
|
||||
#define OCC_SENSOR_DATA_NR_SENSORS 0x580008
|
||||
#define OCC_SENSOR_DATA_NAMES_OFFSET 0x580010
|
||||
#define OCC_SENSOR_DATA_READING_PING_OFFSET 0x580014
|
||||
#define OCC_SENSOR_DATA_READING_PONG_OFFSET 0x58000c
|
||||
#define OCC_SENSOR_DATA_NAME_LENGTH 0x58000d
|
||||
#define OCC_SENSOR_NAME_STRUCTURE_TYPE 0x580023
|
||||
#define OCC_SENSOR_LOC_CORE 0x580022
|
||||
#define OCC_SENSOR_LOC_GPU 0x580020
|
||||
#define OCC_SENSOR_TYPE_POWER 0x580003
|
||||
#define OCC_SENSOR_NAME 0x580005
|
||||
#define HWMON_SENSORS_MASK 0x58001e
|
||||
#define SLW_IMAGE_BASE 0x0
|
||||
|
||||
static void pnv_occ_set_misc(PnvOCC *occ, uint64_t val)
|
||||
{
|
||||
bool irq_state;
|
||||
@@ -82,6 +100,48 @@ static void pnv_occ_power8_xscom_write(void *opaque, hwaddr addr,
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t pnv_occ_common_area_read(void *opaque, hwaddr addr,
|
||||
unsigned width)
|
||||
{
|
||||
switch (addr) {
|
||||
/*
|
||||
* occ-sensor sanity check that asserts the sensor
|
||||
* header block
|
||||
*/
|
||||
case OCC_SENSOR_DATA_BLOCK_OFFSET:
|
||||
case OCC_SENSOR_DATA_VALID:
|
||||
case OCC_SENSOR_DATA_VERSION:
|
||||
case OCC_SENSOR_DATA_READING_VERSION:
|
||||
case OCC_SENSOR_DATA_NR_SENSORS:
|
||||
case OCC_SENSOR_DATA_NAMES_OFFSET:
|
||||
case OCC_SENSOR_DATA_READING_PING_OFFSET:
|
||||
case OCC_SENSOR_DATA_READING_PONG_OFFSET:
|
||||
case OCC_SENSOR_NAME_STRUCTURE_TYPE:
|
||||
return 1;
|
||||
case OCC_SENSOR_DATA_NAME_LENGTH:
|
||||
return 0x30;
|
||||
case OCC_SENSOR_LOC_CORE:
|
||||
return 0x0040;
|
||||
case OCC_SENSOR_TYPE_POWER:
|
||||
return 0x0080;
|
||||
case OCC_SENSOR_NAME:
|
||||
return 0x1000;
|
||||
case HWMON_SENSORS_MASK:
|
||||
case OCC_SENSOR_LOC_GPU:
|
||||
return 0x8e00;
|
||||
case SLW_IMAGE_BASE:
|
||||
return 0x1000000000000000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pnv_occ_common_area_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned width)
|
||||
{
|
||||
/* callback function defined to occ common area write */
|
||||
return;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps pnv_occ_power8_xscom_ops = {
|
||||
.read = pnv_occ_power8_xscom_read,
|
||||
.write = pnv_occ_power8_xscom_write,
|
||||
@@ -92,12 +152,24 @@ static const MemoryRegionOps pnv_occ_power8_xscom_ops = {
|
||||
.endianness = DEVICE_BIG_ENDIAN,
|
||||
};
|
||||
|
||||
const MemoryRegionOps pnv_occ_sram_ops = {
|
||||
.read = pnv_occ_common_area_read,
|
||||
.write = pnv_occ_common_area_write,
|
||||
.valid.min_access_size = 1,
|
||||
.valid.max_access_size = 8,
|
||||
.impl.min_access_size = 1,
|
||||
.impl.max_access_size = 8,
|
||||
.endianness = DEVICE_BIG_ENDIAN,
|
||||
};
|
||||
|
||||
static void pnv_occ_power8_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PnvOCCClass *poc = PNV_OCC_CLASS(klass);
|
||||
|
||||
poc->xscom_size = PNV_XSCOM_OCC_SIZE;
|
||||
poc->sram_size = PNV_OCC_COMMON_AREA_SIZE;
|
||||
poc->xscom_ops = &pnv_occ_power8_xscom_ops;
|
||||
poc->sram_ops = &pnv_occ_sram_ops;
|
||||
poc->psi_irq = PSIHB_IRQ_OCC;
|
||||
}
|
||||
|
||||
@@ -168,7 +240,9 @@ static void pnv_occ_power9_class_init(ObjectClass *klass, void *data)
|
||||
PnvOCCClass *poc = PNV_OCC_CLASS(klass);
|
||||
|
||||
poc->xscom_size = PNV9_XSCOM_OCC_SIZE;
|
||||
poc->sram_size = PNV9_OCC_COMMON_AREA_SIZE;
|
||||
poc->xscom_ops = &pnv_occ_power9_xscom_ops;
|
||||
poc->sram_ops = &pnv_occ_sram_ops;
|
||||
poc->psi_irq = PSIHB9_IRQ_OCC;
|
||||
}
|
||||
|
||||
@@ -199,6 +273,10 @@ static void pnv_occ_realize(DeviceState *dev, Error **errp)
|
||||
/* XScom region for OCC registers */
|
||||
pnv_xscom_region_init(&occ->xscom_regs, OBJECT(dev), poc->xscom_ops,
|
||||
occ, "xscom-occ", poc->xscom_size);
|
||||
|
||||
/* XScom region for OCC SRAM registers */
|
||||
pnv_xscom_region_init(&occ->sram_regs, OBJECT(dev), poc->sram_ops,
|
||||
occ, "occ-common-area", poc->sram_size);
|
||||
}
|
||||
|
||||
static void pnv_occ_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
+3
-3
@@ -311,7 +311,7 @@ static void pnv_psi_set_xivr(PnvPsi *psi, uint32_t reg, uint64_t val)
|
||||
* do for now but a more accurate implementation would instead
|
||||
* use a fixed server/prio and a remapper of the generated irq.
|
||||
*/
|
||||
ics_simple_write_xive(ics, src, server, prio, prio);
|
||||
ics_write_xive(ics, src, server, prio, prio);
|
||||
}
|
||||
|
||||
static uint64_t pnv_psi_reg_read(PnvPsi *psi, uint32_t offset, bool mmio)
|
||||
@@ -469,7 +469,7 @@ static void pnv_psi_power8_instance_init(Object *obj)
|
||||
Pnv8Psi *psi8 = PNV8_PSI(obj);
|
||||
|
||||
object_initialize_child(obj, "ics-psi", &psi8->ics, sizeof(psi8->ics),
|
||||
TYPE_ICS_SIMPLE, &error_abort, NULL);
|
||||
TYPE_ICS, &error_abort, NULL);
|
||||
}
|
||||
|
||||
static const uint8_t irq_to_xivr[] = {
|
||||
@@ -514,7 +514,7 @@ static void pnv_psi_power8_realize(DeviceState *dev, Error **errp)
|
||||
ics_set_irq_type(ics, i, true);
|
||||
}
|
||||
|
||||
psi->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);
|
||||
psi->qirqs = qemu_allocate_irqs(ics_set_irq, ics, ics->nr_irqs);
|
||||
|
||||
/* XSCOM region for PSI registers */
|
||||
pnv_xscom_region_init(&psi->xscom_regs, OBJECT(dev), &pnv_psi_xscom_ops,
|
||||
|
||||
+30
-4
@@ -36,6 +36,16 @@
|
||||
#define PRD_P9_IPOLL_REG_MASK 0x000F0033
|
||||
#define PRD_P9_IPOLL_REG_STATUS 0x000F0034
|
||||
|
||||
/* PBA BARs */
|
||||
#define P8_PBA_BAR0 0x2013f00
|
||||
#define P8_PBA_BAR2 0x2013f02
|
||||
#define P8_PBA_BARMASK0 0x2013f04
|
||||
#define P8_PBA_BARMASK2 0x2013f06
|
||||
#define P9_PBA_BAR0 0x5012b00
|
||||
#define P9_PBA_BAR2 0x5012b02
|
||||
#define P9_PBA_BARMASK0 0x5012b04
|
||||
#define P9_PBA_BARMASK2 0x5012b06
|
||||
|
||||
static void xscom_complete(CPUState *cs, uint64_t hmer_bits)
|
||||
{
|
||||
/*
|
||||
@@ -74,6 +84,26 @@ static uint64_t xscom_read_default(PnvChip *chip, uint32_t pcba)
|
||||
case 0x18002: /* ECID2 */
|
||||
return 0;
|
||||
|
||||
case P9_PBA_BAR0:
|
||||
return PNV9_HOMER_BASE(chip);
|
||||
case P8_PBA_BAR0:
|
||||
return PNV_HOMER_BASE(chip);
|
||||
|
||||
case P9_PBA_BARMASK0: /* P9 homer region size */
|
||||
return PNV9_HOMER_SIZE;
|
||||
case P8_PBA_BARMASK0: /* P8 homer region size */
|
||||
return PNV_HOMER_SIZE;
|
||||
|
||||
case P9_PBA_BAR2: /* P9 occ common area */
|
||||
return PNV9_OCC_COMMON_AREA(chip);
|
||||
case P8_PBA_BAR2: /* P8 occ common area */
|
||||
return PNV_OCC_COMMON_AREA(chip);
|
||||
|
||||
case P9_PBA_BARMASK2: /* P9 occ common area size */
|
||||
return PNV9_OCC_COMMON_AREA_SIZE;
|
||||
case P8_PBA_BARMASK2: /* P8 occ common area size */
|
||||
return PNV_OCC_COMMON_AREA_SIZE;
|
||||
|
||||
case 0x1010c00: /* PIBAM FIR */
|
||||
case 0x1010c03: /* PIBAM FIR MASK */
|
||||
|
||||
@@ -93,13 +123,9 @@ static uint64_t xscom_read_default(PnvChip *chip, uint32_t pcba)
|
||||
case 0x2020009: /* ADU stuff, error register */
|
||||
case 0x202000f: /* ADU stuff, receive status register*/
|
||||
return 0;
|
||||
case 0x2013f00: /* PBA stuff */
|
||||
case 0x2013f01: /* PBA stuff */
|
||||
case 0x2013f02: /* PBA stuff */
|
||||
case 0x2013f03: /* PBA stuff */
|
||||
case 0x2013f04: /* PBA stuff */
|
||||
case 0x2013f05: /* PBA stuff */
|
||||
case 0x2013f06: /* PBA stuff */
|
||||
case 0x2013f07: /* PBA stuff */
|
||||
return 0;
|
||||
case 0x2013028: /* CAPP stuff */
|
||||
|
||||
+86
-133
@@ -81,6 +81,8 @@
|
||||
#include "hw/mem/memory-device.h"
|
||||
#include "hw/ppc/spapr_tpm_proxy.h"
|
||||
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
/* SLOF memory layout:
|
||||
@@ -94,7 +96,6 @@
|
||||
* We load our kernel at 4M, leaving space for SLOF initial image
|
||||
*/
|
||||
#define FDT_MAX_SIZE 0x100000
|
||||
#define RTAS_MAX_SIZE 0x10000
|
||||
#define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */
|
||||
#define FW_MAX_SIZE 0x400000
|
||||
#define FW_FILE_NAME "slof.bin"
|
||||
@@ -218,8 +219,7 @@ static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, PowerPCCPU *cpu)
|
||||
/* Populate the "ibm,pa-features" property */
|
||||
static void spapr_populate_pa_features(SpaprMachineState *spapr,
|
||||
PowerPCCPU *cpu,
|
||||
void *fdt, int offset,
|
||||
bool legacy_guest)
|
||||
void *fdt, int offset)
|
||||
{
|
||||
uint8_t pa_features_206[] = { 6, 0,
|
||||
0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 };
|
||||
@@ -285,7 +285,7 @@ static void spapr_populate_pa_features(SpaprMachineState *spapr,
|
||||
if ((spapr_get_cap(spapr, SPAPR_CAP_HTM) != 0) && pa_size > 24) {
|
||||
pa_features[24] |= 0x80; /* Transactional memory support */
|
||||
}
|
||||
if (legacy_guest && pa_size > 40) {
|
||||
if (spapr->cas_pre_isa3_guest && pa_size > 40) {
|
||||
/* Workaround for broken kernels that attempt (guest) radix
|
||||
* mode when they can't handle it, if they see the radix bit set
|
||||
* in pa-features. So hide it from them. */
|
||||
@@ -295,65 +295,6 @@ static void spapr_populate_pa_features(SpaprMachineState *spapr,
|
||||
_FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size)));
|
||||
}
|
||||
|
||||
static int spapr_fixup_cpu_dt(void *fdt, SpaprMachineState *spapr)
|
||||
{
|
||||
MachineState *ms = MACHINE(spapr);
|
||||
int ret = 0, offset, cpus_offset;
|
||||
CPUState *cs;
|
||||
char cpu_model[32];
|
||||
uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
|
||||
|
||||
CPU_FOREACH(cs) {
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
DeviceClass *dc = DEVICE_GET_CLASS(cs);
|
||||
int index = spapr_get_vcpu_id(cpu);
|
||||
int compat_smt = MIN(ms->smp.threads, ppc_compat_max_vthreads(cpu));
|
||||
|
||||
if (!spapr_is_thread0_in_vcore(spapr, cpu)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
snprintf(cpu_model, 32, "%s@%x", dc->fw_name, index);
|
||||
|
||||
cpus_offset = fdt_path_offset(fdt, "/cpus");
|
||||
if (cpus_offset < 0) {
|
||||
cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
|
||||
if (cpus_offset < 0) {
|
||||
return cpus_offset;
|
||||
}
|
||||
}
|
||||
offset = fdt_subnode_offset(fdt, cpus_offset, cpu_model);
|
||||
if (offset < 0) {
|
||||
offset = fdt_add_subnode(fdt, cpus_offset, cpu_model);
|
||||
if (offset < 0) {
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
|
||||
ret = fdt_setprop(fdt, offset, "ibm,pft-size",
|
||||
pft_size_prop, sizeof(pft_size_prop));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ms->numa_state->num_nodes > 1) {
|
||||
ret = spapr_fixup_cpu_numa_dt(fdt, offset, cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
spapr_populate_pa_features(spapr, cpu, fdt, offset,
|
||||
spapr->cas_legacy_guest_workaround);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static hwaddr spapr_node0_size(MachineState *machine)
|
||||
{
|
||||
if (machine->numa_state->num_nodes) {
|
||||
@@ -388,7 +329,7 @@ static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start,
|
||||
mem_reg_property[0] = cpu_to_be64(start);
|
||||
mem_reg_property[1] = cpu_to_be64(size);
|
||||
|
||||
sprintf(mem_name, "memory@" TARGET_FMT_lx, start);
|
||||
sprintf(mem_name, "memory@%" HWADDR_PRIx, start);
|
||||
off = fdt_add_subnode(fdt, 0, mem_name);
|
||||
_FDT(off);
|
||||
_FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
|
||||
@@ -551,7 +492,7 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
|
||||
page_sizes_prop, page_sizes_prop_size)));
|
||||
}
|
||||
|
||||
spapr_populate_pa_features(spapr, cpu, fdt, offset, false);
|
||||
spapr_populate_pa_features(spapr, cpu, fdt, offset);
|
||||
|
||||
_FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id",
|
||||
cs->cpu_index / vcpus_per_socket)));
|
||||
@@ -984,11 +925,13 @@ static bool spapr_hotplugged_dev_before_cas(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void *spapr_build_fdt(SpaprMachineState *spapr);
|
||||
|
||||
int spapr_h_cas_compose_response(SpaprMachineState *spapr,
|
||||
target_ulong addr, target_ulong size,
|
||||
SpaprOptionVector *ov5_updates)
|
||||
{
|
||||
void *fdt, *fdt_skel;
|
||||
void *fdt;
|
||||
SpaprDeviceTreeUpdateHeader hdr = { .version_id = 1 };
|
||||
|
||||
if (spapr_hotplugged_dev_before_cas()) {
|
||||
@@ -1004,28 +947,11 @@ int spapr_h_cas_compose_response(SpaprMachineState *spapr,
|
||||
|
||||
size -= sizeof(hdr);
|
||||
|
||||
/* Create skeleton */
|
||||
fdt_skel = g_malloc0(size);
|
||||
_FDT((fdt_create(fdt_skel, size)));
|
||||
_FDT((fdt_finish_reservemap(fdt_skel)));
|
||||
_FDT((fdt_begin_node(fdt_skel, "")));
|
||||
_FDT((fdt_end_node(fdt_skel)));
|
||||
_FDT((fdt_finish(fdt_skel)));
|
||||
fdt = g_malloc0(size);
|
||||
_FDT((fdt_open_into(fdt_skel, fdt, size)));
|
||||
g_free(fdt_skel);
|
||||
|
||||
/* Fixup cpu nodes */
|
||||
_FDT((spapr_fixup_cpu_dt(fdt, spapr)));
|
||||
|
||||
if (spapr_dt_cas_updates(spapr, fdt, ov5_updates)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Pack resulting tree */
|
||||
fdt = spapr_build_fdt(spapr);
|
||||
_FDT((fdt_pack(fdt)));
|
||||
|
||||
if (fdt_totalsize(fdt) + sizeof(hdr) > size) {
|
||||
g_free(fdt);
|
||||
trace_spapr_cas_failed(size);
|
||||
return -1;
|
||||
}
|
||||
@@ -1033,7 +959,11 @@ int spapr_h_cas_compose_response(SpaprMachineState *spapr,
|
||||
cpu_physical_memory_write(addr, &hdr, sizeof(hdr));
|
||||
cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt));
|
||||
trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr));
|
||||
g_free(fdt);
|
||||
|
||||
g_free(spapr->fdt_blob);
|
||||
spapr->fdt_size = fdt_totalsize(fdt);
|
||||
spapr->fdt_initial_size = spapr->fdt_size;
|
||||
spapr->fdt_blob = fdt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1136,19 +1066,28 @@ static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
|
||||
PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu);
|
||||
|
||||
char val[2 * 4] = {
|
||||
23, spapr->irq->ov5, /* Xive mode. */
|
||||
23, 0x00, /* XICS / XIVE mode */
|
||||
24, 0x00, /* Hash/Radix, filled in below. */
|
||||
25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */
|
||||
26, 0x40, /* Radix options: GTSE == yes. */
|
||||
};
|
||||
|
||||
if (spapr->irq->xics && spapr->irq->xive) {
|
||||
val[1] = SPAPR_OV5_XIVE_BOTH;
|
||||
} else if (spapr->irq->xive) {
|
||||
val[1] = SPAPR_OV5_XIVE_EXPLOIT;
|
||||
} else {
|
||||
assert(spapr->irq->xics);
|
||||
val[1] = SPAPR_OV5_XIVE_LEGACY;
|
||||
}
|
||||
|
||||
if (!ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0,
|
||||
first_ppc_cpu->compat_pvr)) {
|
||||
/*
|
||||
* If we're in a pre POWER9 compat mode then the guest should
|
||||
* do hash and use the legacy interrupt mode
|
||||
*/
|
||||
val[1] = 0x00; /* XICS */
|
||||
val[1] = SPAPR_OV5_XIVE_LEGACY; /* XICS */
|
||||
val[3] = 0x00; /* Hash */
|
||||
} else if (kvm_enabled()) {
|
||||
if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) {
|
||||
@@ -1178,11 +1117,16 @@ static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt)
|
||||
|
||||
_FDT(chosen = fdt_add_subnode(fdt, 0, "chosen"));
|
||||
|
||||
_FDT(fdt_setprop_string(fdt, chosen, "bootargs", machine->kernel_cmdline));
|
||||
_FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-start",
|
||||
spapr->initrd_base));
|
||||
_FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-end",
|
||||
spapr->initrd_base + spapr->initrd_size));
|
||||
if (machine->kernel_cmdline && machine->kernel_cmdline[0]) {
|
||||
_FDT(fdt_setprop_string(fdt, chosen, "bootargs",
|
||||
machine->kernel_cmdline));
|
||||
}
|
||||
if (spapr->initrd_size) {
|
||||
_FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-start",
|
||||
spapr->initrd_base));
|
||||
_FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-end",
|
||||
spapr->initrd_base + spapr->initrd_size));
|
||||
}
|
||||
|
||||
if (spapr->kernel_size) {
|
||||
uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
|
||||
@@ -1717,8 +1661,7 @@ static void spapr_machine_reset(MachineState *machine)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(machine);
|
||||
PowerPCCPU *first_ppc_cpu;
|
||||
uint32_t rtas_limit;
|
||||
hwaddr rtas_addr, fdt_addr;
|
||||
hwaddr fdt_addr;
|
||||
void *fdt;
|
||||
int rc;
|
||||
|
||||
@@ -1739,16 +1682,6 @@ static void spapr_machine_reset(MachineState *machine)
|
||||
spapr_setup_hpt_and_vrma(spapr);
|
||||
}
|
||||
|
||||
/*
|
||||
* NVLink2-connected GPU RAM needs to be placed on a separate NUMA node.
|
||||
* We assign a new numa ID per GPU in spapr_pci_collect_nvgpu() which is
|
||||
* called from vPHB reset handler so we initialize the counter here.
|
||||
* If no NUMA is configured from the QEMU side, we start from 1 as GPU RAM
|
||||
* must be equally distant from any other node.
|
||||
* The final value of spapr->gpu_numa_id is going to be written to
|
||||
* max-associativity-domains in spapr_build_fdt().
|
||||
*/
|
||||
spapr->gpu_numa_id = MAX(1, machine->numa_state->num_nodes);
|
||||
qemu_devices_reset();
|
||||
|
||||
/*
|
||||
@@ -1792,14 +1725,10 @@ static void spapr_machine_reset(MachineState *machine)
|
||||
* or just below 2GB, whichever is lower, so that it can be
|
||||
* processed with 32-bit real mode code if necessary
|
||||
*/
|
||||
rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR);
|
||||
rtas_addr = rtas_limit - RTAS_MAX_SIZE;
|
||||
fdt_addr = rtas_addr - FDT_MAX_SIZE;
|
||||
fdt_addr = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FDT_MAX_SIZE;
|
||||
|
||||
fdt = spapr_build_fdt(spapr);
|
||||
|
||||
spapr_load_rtas(spapr, fdt, rtas_addr);
|
||||
|
||||
rc = fdt_pack(fdt);
|
||||
|
||||
/* Should only fail if we've built a corrupted tree */
|
||||
@@ -2847,13 +2776,57 @@ static void spapr_machine_init(MachineState *machine)
|
||||
spapr_ovec_set(spapr->ov5, OV5_DRMEM_V2);
|
||||
|
||||
/* advertise XIVE on POWER9 machines */
|
||||
if (spapr->irq->ov5 & (SPAPR_OV5_XIVE_EXPLOIT | SPAPR_OV5_XIVE_BOTH)) {
|
||||
if (spapr->irq->xive) {
|
||||
spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
|
||||
}
|
||||
|
||||
/* init CPUs */
|
||||
spapr_init_cpus(spapr);
|
||||
|
||||
/*
|
||||
* check we don't have a memory-less/cpu-less NUMA node
|
||||
* Firmware relies on the existing memory/cpu topology to provide the
|
||||
* NUMA topology to the kernel.
|
||||
* And the linux kernel needs to know the NUMA topology at start
|
||||
* to be able to hotplug CPUs later.
|
||||
*/
|
||||
if (machine->numa_state->num_nodes) {
|
||||
for (i = 0; i < machine->numa_state->num_nodes; ++i) {
|
||||
/* check for memory-less node */
|
||||
if (machine->numa_state->nodes[i].node_mem == 0) {
|
||||
CPUState *cs;
|
||||
int found = 0;
|
||||
/* check for cpu-less node */
|
||||
CPU_FOREACH(cs) {
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
if (cpu->node_id == i) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* memory-less and cpu-less node */
|
||||
if (!found) {
|
||||
error_report(
|
||||
"Memory-less/cpu-less nodes are not supported (node %d)",
|
||||
i);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* NVLink2-connected GPU RAM needs to be placed on a separate NUMA node.
|
||||
* We assign a new numa ID per GPU in spapr_pci_collect_nvgpu() which is
|
||||
* called from vPHB reset handler so we initialize the counter here.
|
||||
* If no NUMA is configured from the QEMU side, we start from 1 as GPU RAM
|
||||
* must be equally distant from any other node.
|
||||
* The final value of spapr->gpu_numa_id is going to be written to
|
||||
* max-associativity-domains in spapr_build_fdt().
|
||||
*/
|
||||
spapr->gpu_numa_id = MAX(1, machine->numa_state->num_nodes);
|
||||
|
||||
if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) &&
|
||||
ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0,
|
||||
spapr->max_compat_pvr)) {
|
||||
@@ -2915,28 +2888,6 @@ static void spapr_machine_init(MachineState *machine)
|
||||
spapr_create_lmb_dr_connectors(spapr);
|
||||
}
|
||||
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
|
||||
if (!filename) {
|
||||
error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin");
|
||||
exit(1);
|
||||
}
|
||||
spapr->rtas_size = get_image_size(filename);
|
||||
if (spapr->rtas_size < 0) {
|
||||
error_report("Could not get size of LPAR rtas '%s'", filename);
|
||||
exit(1);
|
||||
}
|
||||
spapr->rtas_blob = g_malloc(spapr->rtas_size);
|
||||
if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) {
|
||||
error_report("Could not load LPAR rtas '%s'", filename);
|
||||
exit(1);
|
||||
}
|
||||
if (spapr->rtas_size > RTAS_MAX_SIZE) {
|
||||
error_report("RTAS too big ! 0x%zx bytes (max is 0x%x)",
|
||||
(size_t)spapr->rtas_size, RTAS_MAX_SIZE);
|
||||
exit(1);
|
||||
}
|
||||
g_free(filename);
|
||||
|
||||
/* Set up RTAS event infrastructure */
|
||||
spapr_events_init(spapr);
|
||||
|
||||
@@ -4321,6 +4272,8 @@ static void spapr_pic_print_info(InterruptStatsProvider *obj,
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(obj);
|
||||
|
||||
spapr->irq->print_info(spapr, mon);
|
||||
monitor_printf(mon, "irqchip: %s\n",
|
||||
kvm_irqchip_in_kernel() ? "in-kernel" : "emulated");
|
||||
}
|
||||
|
||||
int spapr_get_vcpu_id(PowerPCCPU *cpu)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user