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-5.2-20200818' into staging
ppc patch queue 2020-08-18 Here's my first pull request for qemu-5.2, which has quite a few accumulated things. Highlights are: * Preliminary support for POWER10 (Power ISA 3.1) instruction emulation * Add documentation on the (very confusing) pseries NUMA configuration * Fix some bugs handling edge cases with XICS, XIVE and kernel_irqchip * Fix icount for a number of POWER registers * Many cleanups to error handling in XIVE code * Validate size of -prom-env data # gpg: Signature made Tue 18 Aug 2020 05:18:36 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-5.2-20200818: (40 commits) spapr/xive: Use xive_source_esb_len() nvram: Exit QEMU if NVRAM cannot contain all -prom-env data spapr/xive: Simplify error handling of kvmppc_xive_cpu_synchronize_state() ppc/xive: Simplify error handling in xive_tctx_realize() spapr/xive: Simplify error handling in kvmppc_xive_connect() ppc/xive: Fix error handling in vmstate_xive_tctx_*() callbacks spapr/xive: Fix error handling in kvmppc_xive_post_load() spapr/kvm: Fix error handling in kvmppc_xive_pre_save() spapr/xive: Rework error handling of kvmppc_xive_set_source_config() spapr/xive: Rework error handling in kvmppc_xive_get_queues() spapr/xive: Rework error handling of kvmppc_xive_[gs]et_queue_config() spapr/xive: Rework error handling of kvmppc_xive_cpu_[gs]et_state() spapr/xive: Rework error handling of kvmppc_xive_mmap() spapr/xive: Rework error handling of kvmppc_xive_source_reset() spapr/xive: Rework error handling of kvmppc_xive_cpu_connect() spapr: Simplify error handling in spapr_phb_realize() spapr/xive: Convert KVM device fd checks to assert() ppc/xive: Introduce dedicated kvm_irqchip_in_kernel() wrappers ppc/xive: Rework setup of XiveSource::esb_mmio target/ppc: Integrate icount to purr, vtb, and tbu40 ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -12,6 +12,7 @@ Contents:
|
||||
|
||||
ppc-xive
|
||||
ppc-spapr-xive
|
||||
ppc-spapr-numa
|
||||
acpi_hw_reduced_hotplug
|
||||
tpm
|
||||
acpi_hest_ghes
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
|
||||
NUMA mechanics for sPAPR (pseries machines)
|
||||
============================================
|
||||
|
||||
NUMA in sPAPR works different than the System Locality Distance
|
||||
Information Table (SLIT) in ACPI. The logic is explained in the LOPAPR
|
||||
1.1 chapter 15, "Non Uniform Memory Access (NUMA) Option". This
|
||||
document aims to complement this specification, providing details
|
||||
of the elements that impacts how QEMU views NUMA in pseries.
|
||||
|
||||
Associativity and ibm,associativity property
|
||||
--------------------------------------------
|
||||
|
||||
Associativity is defined as a group of platform resources that has
|
||||
similar mean performance (or in our context here, distance) relative to
|
||||
everyone else outside of the group.
|
||||
|
||||
The format of the ibm,associativity property varies with the value of
|
||||
bit 0 of byte 5 of the ibm,architecture-vec-5 property. The format with
|
||||
bit 0 equal to zero is deprecated. The current format, with the bit 0
|
||||
with the value of one, makes ibm,associativity property represent the
|
||||
physical hierarchy of the platform, as one or more lists that starts
|
||||
with the highest level grouping up to the smallest. Considering the
|
||||
following topology:
|
||||
|
||||
::
|
||||
|
||||
Mem M1 ---- Proc P1 |
|
||||
----------------- | Socket S1 ---|
|
||||
chip C1 | |
|
||||
| HW module 1 (MOD1)
|
||||
Mem M2 ---- Proc P2 | |
|
||||
----------------- | Socket S2 ---|
|
||||
chip C2 |
|
||||
|
||||
The ibm,associativity property for the processors would be:
|
||||
|
||||
* P1: {MOD1, S1, C1, P1}
|
||||
* P2: {MOD1, S2, C2, P2}
|
||||
|
||||
Each allocable resource has an ibm,associativity property. The LOPAPR
|
||||
specification allows multiple lists to be present in this property,
|
||||
considering that the same resource can have multiple connections to the
|
||||
platform.
|
||||
|
||||
Relative Performance Distance and ibm,associativity-reference-points
|
||||
--------------------------------------------------------------------
|
||||
|
||||
The ibm,associativity-reference-points property is an array that is used
|
||||
to define the relevant performance/distance related boundaries, defining
|
||||
the NUMA levels for the platform.
|
||||
|
||||
The definition of its elements also varies with the value of bit 0 of byte 5
|
||||
of the ibm,architecture-vec-5 property. The format with bit 0 equal to zero
|
||||
is also deprecated. With the current format, each integer of the
|
||||
ibm,associativity-reference-points represents an 1 based ordinal index (i.e.
|
||||
the first element is 1) of the ibm,associativity array. The first
|
||||
boundary is the most significant to application performance, followed by
|
||||
less significant boundaries. Allocated resources that belongs to the
|
||||
same performance boundaries are expected to have relative NUMA distance
|
||||
that matches the relevancy of the boundary itself. Resources that belongs
|
||||
to the same first boundary will have the shortest distance from each
|
||||
other. Subsequent boundaries represents greater distances and degraded
|
||||
performance.
|
||||
|
||||
Using the previous example, the following setting reference points defines
|
||||
three NUMA levels:
|
||||
|
||||
* ibm,associativity-reference-points = {0x3, 0x2, 0x1}
|
||||
|
||||
The first NUMA level (0x3) is interpreted as the third element of each
|
||||
ibm,associativity array, the second level is the second element and
|
||||
the third level is the first element. Let's also consider that elements
|
||||
belonging to the first NUMA level have distance equal to 10 from each
|
||||
other, and each NUMA level doubles the distance from the previous. This
|
||||
means that the second would be 20 and the third level 40. For the P1 and
|
||||
P2 processors, we would have the following NUMA levels:
|
||||
|
||||
::
|
||||
|
||||
* ibm,associativity-reference-points = {0x3, 0x2, 0x1}
|
||||
|
||||
* P1: associativity{MOD1, S1, C1, P1}
|
||||
|
||||
First NUMA level (0x3) => associativity[2] = C1
|
||||
Second NUMA level (0x2) => associativity[1] = S1
|
||||
Third NUMA level (0x1) => associativity[0] = MOD1
|
||||
|
||||
* P2: associativity{MOD1, S2, C2, P2}
|
||||
|
||||
First NUMA level (0x3) => associativity[2] = C2
|
||||
Second NUMA level (0x2) => associativity[1] = S2
|
||||
Third NUMA level (0x1) => associativity[0] = MOD1
|
||||
|
||||
P1 and P2 have the same third NUMA level, MOD1: Distance between them = 40
|
||||
|
||||
Changing the ibm,associativity-reference-points array changes the performance
|
||||
distance attributes for the same associativity arrays, as the following
|
||||
example illustrates:
|
||||
|
||||
::
|
||||
|
||||
* ibm,associativity-reference-points = {0x2}
|
||||
|
||||
* P1: associativity{MOD1, S1, C1, P1}
|
||||
|
||||
First NUMA level (0x2) => associativity[1] = S1
|
||||
|
||||
* P2: associativity{MOD1, S2, C2, P2}
|
||||
|
||||
First NUMA level (0x2) => associativity[1] = S2
|
||||
|
||||
P1 and P2 does not have a common performance boundary. Since this is a one level
|
||||
NUMA configuration, distance between them is one boundary above the first
|
||||
level, 20.
|
||||
|
||||
|
||||
In a hypothetical platform where all resources inside the same hardware module
|
||||
is considered to be on the same performance boundary:
|
||||
|
||||
::
|
||||
|
||||
* ibm,associativity-reference-points = {0x1}
|
||||
|
||||
* P1: associativity{MOD1, S1, C1, P1}
|
||||
|
||||
First NUMA level (0x1) => associativity[0] = MOD0
|
||||
|
||||
* P2: associativity{MOD1, S2, C2, P2}
|
||||
|
||||
First NUMA level (0x1) => associativity[0] = MOD0
|
||||
|
||||
P1 and P2 belongs to the same first order boundary. The distance between then
|
||||
is 10.
|
||||
|
||||
|
||||
How the pseries Linux guest calculates NUMA distances
|
||||
=====================================================
|
||||
|
||||
Another key difference between ACPI SLIT and the LOPAPR regarding NUMA is
|
||||
how the distances are expressed. The SLIT table provides the NUMA distance
|
||||
value between the relevant resources. LOPAPR does not provide a standard
|
||||
way to calculate it. We have the ibm,associativity for each resource, which
|
||||
provides a common-performance hierarchy, and the ibm,associativity-reference-points
|
||||
array that tells which level of associativity is considered to be relevant
|
||||
or not.
|
||||
|
||||
The result is that each OS is free to implement and to interpret the distance
|
||||
as it sees fit. For the pseries Linux guest, each level of NUMA duplicates
|
||||
the distance of the previous level, and the maximum amount of levels is
|
||||
limited to MAX_DISTANCE_REF_POINTS = 4 (from arch/powerpc/mm/numa.c in the
|
||||
kernel tree). This results in the following distances:
|
||||
|
||||
* both resources in the first NUMA level: 10
|
||||
* resources one NUMA level apart: 20
|
||||
* resources two NUMA levels apart: 40
|
||||
* resources three NUMA levels apart: 80
|
||||
* resources four NUMA levels apart: 160
|
||||
|
||||
|
||||
Consequences for QEMU NUMA tuning
|
||||
---------------------------------
|
||||
|
||||
The way the pseries Linux guest calculates NUMA distances has a direct effect
|
||||
on what QEMU users can expect when doing NUMA tuning. As of QEMU 5.1, this is
|
||||
the default ibm,associativity-reference-points being used in the pseries
|
||||
machine:
|
||||
|
||||
ibm,associativity-reference-points = {0x4, 0x4, 0x2}
|
||||
|
||||
The first and second level are equal, 0x4, and a third one was added in
|
||||
commit a6030d7e0b35 exclusively for NVLink GPUs support. This means that
|
||||
regardless of how the ibm,associativity properties are being created in
|
||||
the device tree, the pseries Linux guest will only recognize three scenarios
|
||||
as far as NUMA distance goes:
|
||||
|
||||
* if the resources belongs to the same first NUMA level = 10
|
||||
* second level is skipped since it's equal to the first
|
||||
* all resources that aren't a NVLink GPU, it is guaranteed that they will belong
|
||||
to the same third NUMA level, having distance = 40
|
||||
* for NVLink GPUs, distance = 80 from everything else
|
||||
|
||||
In short, we can summarize the NUMA distances seem in pseries Linux guests, using
|
||||
QEMU up to 5.1, as follows:
|
||||
|
||||
* local distance, i.e. the distance of the resource to its own NUMA node: 10
|
||||
* if it's a NVLink GPU device, distance: 80
|
||||
* every other resource, distance: 40
|
||||
|
||||
This also means that user input in QEMU command line does not change the
|
||||
NUMA distancing inside the guest for the pseries machine.
|
||||
@@ -61,6 +61,11 @@ depend on the XIVE KVM capability of the host. On older kernels
|
||||
without XIVE KVM support, QEMU will use the emulated XIVE device as a
|
||||
fallback and on newer kernels (>=5.2), the KVM XIVE device.
|
||||
|
||||
XIVE native exploitation mode is not supported for KVM nested guests,
|
||||
VMs running under a L1 hypervisor (KVM on pSeries). In that case, the
|
||||
hypervisor will not advertise the KVM capability and QEMU will use the
|
||||
emulated XIVE device, same as for older versions of KVM.
|
||||
|
||||
As a final refinement, the user can also switch the use of the KVM
|
||||
device with the machine option ``kernel_irqchip``.
|
||||
|
||||
@@ -121,6 +126,9 @@ xics XICS KVM XICS emul. XICS KVM
|
||||
|
||||
(1) QEMU warns with ``warning: kernel_irqchip requested but unavailable:
|
||||
IRQ_XIVE capability must be present for KVM``
|
||||
In some cases (old host kernels or KVM nested guests), one may hit a
|
||||
QEMU/KVM incompatibility due to device destruction in reset. QEMU fails
|
||||
with ``KVM is incompatible with ic-mode=dual,kernel-irqchip=on``
|
||||
(2) QEMU fails with ``kernel_irqchip requested but unavailable:
|
||||
IRQ_XIVE capability must be present for KVM``
|
||||
|
||||
@@ -143,7 +151,7 @@ xics XICS KVM XICS emul. XICS KVM
|
||||
mode (XICS), either don't set the ic-mode machine property or try
|
||||
ic-mode=xics or ic-mode=dual``
|
||||
(4) QEMU/KVM incompatibility due to device destruction in reset. QEMU fails
|
||||
with ``KVM is too old to support ic-mode=dual,kernel-irqchip=on``
|
||||
with ``KVM is incompatible with ic-mode=dual,kernel-irqchip=on``
|
||||
|
||||
|
||||
XIVE Device tree properties
|
||||
|
||||
+32
-15
@@ -148,12 +148,19 @@ static void spapr_xive_end_pic_print_info(SpaprXive *xive, XiveEND *end,
|
||||
xive_end_queue_pic_print_info(end, 6, mon);
|
||||
}
|
||||
|
||||
/*
|
||||
* kvm_irqchip_in_kernel() will cause the compiler to turn this
|
||||
* info a nop if CONFIG_KVM isn't defined.
|
||||
*/
|
||||
#define spapr_xive_in_kernel(xive) \
|
||||
(kvm_irqchip_in_kernel() && (xive)->fd != -1)
|
||||
|
||||
void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon)
|
||||
{
|
||||
XiveSource *xsrc = &xive->source;
|
||||
int i;
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
if (spapr_xive_in_kernel(xive)) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
kvmppc_xive_synchronize_state(xive, &local_err);
|
||||
@@ -329,7 +336,7 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp)
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(xive), &end_xsrc->esb_mmio);
|
||||
|
||||
/* Set the mapping address of the END ESB pages after the source ESBs */
|
||||
xive->end_base = xive->vc_base + (1ull << xsrc->esb_shift) * xsrc->nr_irqs;
|
||||
xive->end_base = xive->vc_base + xive_source_esb_len(xsrc);
|
||||
|
||||
/*
|
||||
* Allocate the routing tables
|
||||
@@ -507,8 +514,10 @@ static const VMStateDescription vmstate_spapr_xive_eas = {
|
||||
|
||||
static int vmstate_spapr_xive_pre_save(void *opaque)
|
||||
{
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
return kvmppc_xive_pre_save(SPAPR_XIVE(opaque));
|
||||
SpaprXive *xive = SPAPR_XIVE(opaque);
|
||||
|
||||
if (spapr_xive_in_kernel(xive)) {
|
||||
return kvmppc_xive_pre_save(xive);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -520,8 +529,10 @@ static int vmstate_spapr_xive_pre_save(void *opaque)
|
||||
*/
|
||||
static int spapr_xive_post_load(SpaprInterruptController *intc, int version_id)
|
||||
{
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
return kvmppc_xive_post_load(SPAPR_XIVE(intc), version_id);
|
||||
SpaprXive *xive = SPAPR_XIVE(intc);
|
||||
|
||||
if (spapr_xive_in_kernel(xive)) {
|
||||
return kvmppc_xive_post_load(xive, version_id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -564,7 +575,7 @@ static int spapr_xive_claim_irq(SpaprInterruptController *intc, int lisn,
|
||||
xive_source_irq_set_lsi(xsrc, lisn);
|
||||
}
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
if (spapr_xive_in_kernel(xive)) {
|
||||
return kvmppc_xive_source_reset_one(xsrc, lisn, errp);
|
||||
}
|
||||
|
||||
@@ -641,7 +652,7 @@ static void spapr_xive_set_irq(SpaprInterruptController *intc, int irq, int val)
|
||||
{
|
||||
SpaprXive *xive = SPAPR_XIVE(intc);
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
if (spapr_xive_in_kernel(xive)) {
|
||||
kvmppc_xive_source_set_irq(&xive->source, irq, val);
|
||||
} else {
|
||||
xive_source_set_irq(&xive->source, irq, val);
|
||||
@@ -749,11 +760,16 @@ static void spapr_xive_deactivate(SpaprInterruptController *intc)
|
||||
|
||||
spapr_xive_mmio_set_enabled(xive, false);
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
if (spapr_xive_in_kernel(xive)) {
|
||||
kvmppc_xive_disconnect(intc);
|
||||
}
|
||||
}
|
||||
|
||||
static bool spapr_xive_in_kernel_xptr(const XivePresenter *xptr)
|
||||
{
|
||||
return spapr_xive_in_kernel(SPAPR_XIVE(xptr));
|
||||
}
|
||||
|
||||
static void spapr_xive_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
@@ -788,6 +804,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data)
|
||||
sicc->post_load = spapr_xive_post_load;
|
||||
|
||||
xpc->match_nvt = spapr_xive_match_nvt;
|
||||
xpc->in_kernel = spapr_xive_in_kernel_xptr;
|
||||
}
|
||||
|
||||
static const TypeInfo spapr_xive_info = {
|
||||
@@ -1058,7 +1075,7 @@ static target_ulong h_int_set_source_config(PowerPCCPU *cpu,
|
||||
new_eas.w = xive_set_field64(EAS_END_DATA, new_eas.w, eisn);
|
||||
}
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
if (spapr_xive_in_kernel(xive)) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
kvmppc_xive_set_source_config(xive, lisn, &new_eas, &local_err);
|
||||
@@ -1379,7 +1396,7 @@ static target_ulong h_int_set_queue_config(PowerPCCPU *cpu,
|
||||
*/
|
||||
|
||||
out:
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
if (spapr_xive_in_kernel(xive)) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
kvmppc_xive_set_queue_config(xive, end_blk, end_idx, &end, &local_err);
|
||||
@@ -1480,7 +1497,7 @@ static target_ulong h_int_get_queue_config(PowerPCCPU *cpu,
|
||||
args[2] = 0;
|
||||
}
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
if (spapr_xive_in_kernel(xive)) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
kvmppc_xive_get_queue_config(xive, end_blk, end_idx, end, &local_err);
|
||||
@@ -1642,7 +1659,7 @@ static target_ulong h_int_esb(PowerPCCPU *cpu,
|
||||
return H_P3;
|
||||
}
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
if (spapr_xive_in_kernel(xive)) {
|
||||
args[0] = kvmppc_xive_esb_rw(xsrc, lisn, offset, data,
|
||||
flags & SPAPR_XIVE_ESB_STORE);
|
||||
} else {
|
||||
@@ -1717,7 +1734,7 @@ static target_ulong h_int_sync(PowerPCCPU *cpu,
|
||||
* under KVM
|
||||
*/
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
if (spapr_xive_in_kernel(xive)) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
kvmppc_xive_sync_source(xive, lisn, &local_err);
|
||||
@@ -1761,7 +1778,7 @@ static target_ulong h_int_reset(PowerPCCPU *cpu,
|
||||
|
||||
device_legacy_reset(DEVICE(xive));
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
if (spapr_xive_in_kernel(xive)) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
kvmppc_xive_reset(xive, &local_err);
|
||||
|
||||
+118
-139
File diff suppressed because it is too large
Load Diff
+35
-22
@@ -592,6 +592,17 @@ static const char * const xive_tctx_ring_names[] = {
|
||||
"USER", "OS", "POOL", "PHYS",
|
||||
};
|
||||
|
||||
/*
|
||||
* kvm_irqchip_in_kernel() will cause the compiler to turn this
|
||||
* info a nop if CONFIG_KVM isn't defined.
|
||||
*/
|
||||
#define xive_in_kernel(xptr) \
|
||||
(kvm_irqchip_in_kernel() && \
|
||||
({ \
|
||||
XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); \
|
||||
xpc->in_kernel ? xpc->in_kernel(xptr) : false; \
|
||||
}))
|
||||
|
||||
void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor *mon)
|
||||
{
|
||||
int cpu_index;
|
||||
@@ -606,7 +617,7 @@ void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor *mon)
|
||||
|
||||
cpu_index = tctx->cs ? tctx->cs->cpu_index : -1;
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
if (xive_in_kernel(tctx->xptr)) {
|
||||
Error *local_err = NULL;
|
||||
|
||||
kvmppc_xive_cpu_synchronize_state(tctx, &local_err);
|
||||
@@ -651,7 +662,6 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp)
|
||||
XiveTCTX *tctx = XIVE_TCTX(dev);
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
Error *local_err = NULL;
|
||||
|
||||
assert(tctx->cs);
|
||||
assert(tctx->xptr);
|
||||
@@ -671,10 +681,8 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
|
||||
/* Connect the presenter to the VCPU (required for CPU hotplug) */
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
kvmppc_xive_cpu_connect(tctx, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
if (xive_in_kernel(tctx->xptr)) {
|
||||
if (kvmppc_xive_cpu_connect(tctx, errp) < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -682,13 +690,15 @@ static void xive_tctx_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
static int vmstate_xive_tctx_pre_save(void *opaque)
|
||||
{
|
||||
XiveTCTX *tctx = XIVE_TCTX(opaque);
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
kvmppc_xive_cpu_get_state(XIVE_TCTX(opaque), &local_err);
|
||||
if (local_err) {
|
||||
if (xive_in_kernel(tctx->xptr)) {
|
||||
ret = kvmppc_xive_cpu_get_state(tctx, &local_err);
|
||||
if (ret < 0) {
|
||||
error_report_err(local_err);
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -697,17 +707,19 @@ static int vmstate_xive_tctx_pre_save(void *opaque)
|
||||
|
||||
static int vmstate_xive_tctx_post_load(void *opaque, int version_id)
|
||||
{
|
||||
XiveTCTX *tctx = XIVE_TCTX(opaque);
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
if (xive_in_kernel(tctx->xptr)) {
|
||||
/*
|
||||
* Required for hotplugged CPU, for which the state comes
|
||||
* after all states of the machine.
|
||||
*/
|
||||
kvmppc_xive_cpu_set_state(XIVE_TCTX(opaque), &local_err);
|
||||
if (local_err) {
|
||||
ret = kvmppc_xive_cpu_set_state(tctx, &local_err);
|
||||
if (ret < 0) {
|
||||
error_report_err(local_err);
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1128,6 +1140,7 @@ static void xive_source_reset(void *dev)
|
||||
static void xive_source_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
XiveSource *xsrc = XIVE_SOURCE(dev);
|
||||
size_t esb_len = xive_source_esb_len(xsrc);
|
||||
|
||||
assert(xsrc->xive);
|
||||
|
||||
@@ -1147,11 +1160,11 @@ static void xive_source_realize(DeviceState *dev, Error **errp)
|
||||
xsrc->status = g_malloc0(xsrc->nr_irqs);
|
||||
xsrc->lsi_map = bitmap_new(xsrc->nr_irqs);
|
||||
|
||||
if (!kvm_irqchip_in_kernel()) {
|
||||
memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc),
|
||||
&xive_source_esb_ops, xsrc, "xive.esb",
|
||||
(1ull << xsrc->esb_shift) * xsrc->nr_irqs);
|
||||
}
|
||||
memory_region_init(&xsrc->esb_mmio, OBJECT(xsrc), "xive.esb", esb_len);
|
||||
memory_region_init_io(&xsrc->esb_mmio_emulated, OBJECT(xsrc),
|
||||
&xive_source_esb_ops, xsrc, "xive.esb-emulated",
|
||||
esb_len);
|
||||
memory_region_add_subregion(&xsrc->esb_mmio, 0, &xsrc->esb_mmio_emulated);
|
||||
|
||||
qemu_register_reset(xive_source_reset, dev);
|
||||
}
|
||||
@@ -1502,7 +1515,7 @@ static bool xive_presenter_notify(XiveFabric *xfb, uint8_t format,
|
||||
|
||||
/*
|
||||
* Notification using the END ESe/ESn bit (Event State Buffer for
|
||||
* escalation and notification). Profide futher coalescing in the
|
||||
* escalation and notification). Provide further coalescing in the
|
||||
* Router.
|
||||
*/
|
||||
static bool xive_router_end_es_notify(XiveRouter *xrtr, uint8_t end_blk,
|
||||
@@ -1581,7 +1594,7 @@ static void xive_router_end_notify(XiveRouter *xrtr, uint8_t end_blk,
|
||||
|
||||
/*
|
||||
* Check the END ESn (Event State Buffer for notification) for
|
||||
* even futher coalescing in the Router
|
||||
* even further coalescing in the Router
|
||||
*/
|
||||
if (!xive_end_is_notify(&end)) {
|
||||
/* ESn[Q]=1 : end of notification */
|
||||
@@ -1660,7 +1673,7 @@ do_escalation:
|
||||
|
||||
/*
|
||||
* Check the END ESe (Event State Buffer for escalation) for even
|
||||
* futher coalescing in the Router
|
||||
* further coalescing in the Router
|
||||
*/
|
||||
if (!xive_end_is_uncond_escalation(&end)) {
|
||||
/* ESe[Q]=1 : end of notification */
|
||||
|
||||
+21
-3
@@ -21,14 +21,21 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/nvram/chrp_nvram.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
static int chrp_nvram_set_var(uint8_t *nvram, int addr, const char *str)
|
||||
static int chrp_nvram_set_var(uint8_t *nvram, int addr, const char *str,
|
||||
int max_len)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = strlen(str) + 1;
|
||||
|
||||
if (max_len < len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&nvram[addr], str, len);
|
||||
|
||||
return addr + len;
|
||||
@@ -38,19 +45,26 @@ static int chrp_nvram_set_var(uint8_t *nvram, int addr, const char *str)
|
||||
* Create a "system partition", used for the Open Firmware
|
||||
* environment variables.
|
||||
*/
|
||||
int chrp_nvram_create_system_partition(uint8_t *data, int min_len)
|
||||
int chrp_nvram_create_system_partition(uint8_t *data, int min_len, int max_len)
|
||||
{
|
||||
ChrpNvramPartHdr *part_header;
|
||||
unsigned int i;
|
||||
int end;
|
||||
|
||||
if (max_len < sizeof(*part_header)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
part_header = (ChrpNvramPartHdr *)data;
|
||||
part_header->signature = CHRP_NVPART_SYSTEM;
|
||||
pstrcpy(part_header->name, sizeof(part_header->name), "system");
|
||||
|
||||
end = sizeof(ChrpNvramPartHdr);
|
||||
for (i = 0; i < nb_prom_envs; i++) {
|
||||
end = chrp_nvram_set_var(data, end, prom_envs[i]);
|
||||
end = chrp_nvram_set_var(data, end, prom_envs[i], max_len - end);
|
||||
if (end == -1) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* End marker */
|
||||
@@ -65,6 +79,10 @@ int chrp_nvram_create_system_partition(uint8_t *data, int min_len)
|
||||
chrp_nvram_finish_partition(part_header, end);
|
||||
|
||||
return end;
|
||||
|
||||
fail:
|
||||
error_report("NVRAM is too small. Try to pass less data to -prom-env");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -141,7 +141,7 @@ static void pmac_format_nvram_partition_of(MacIONVRAMState *nvr, int off,
|
||||
|
||||
/* OpenBIOS nvram variables partition */
|
||||
sysp_end = chrp_nvram_create_system_partition(&nvr->data[off],
|
||||
DEF_SYSTEM_SIZE) + off;
|
||||
DEF_SYSTEM_SIZE, len) + off;
|
||||
|
||||
/* Free space partition */
|
||||
chrp_nvram_create_free_partition(&nvr->data[sysp_end], len - sysp_end);
|
||||
|
||||
@@ -188,7 +188,8 @@ static void spapr_nvram_realize(SpaprVioDevice *dev, Error **errp)
|
||||
}
|
||||
} else if (nb_prom_envs > 0) {
|
||||
/* Create a system partition to pass the -prom-env variables */
|
||||
chrp_nvram_create_system_partition(nvram->buf, MIN_NVRAM_SIZE / 4);
|
||||
chrp_nvram_create_system_partition(nvram->buf, MIN_NVRAM_SIZE / 4,
|
||||
nvram->size);
|
||||
chrp_nvram_create_free_partition(&nvram->buf[MIN_NVRAM_SIZE / 4],
|
||||
nvram->size - MIN_NVRAM_SIZE / 4);
|
||||
}
|
||||
|
||||
+4
-2
@@ -558,7 +558,8 @@ static int spapr_dt_dynamic_reconfiguration_memory(SpaprMachineState *spapr,
|
||||
int nb_numa_nodes = machine->numa_state->num_nodes;
|
||||
int ret, i, offset;
|
||||
uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
|
||||
uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)};
|
||||
uint32_t prop_lmb_size[] = {cpu_to_be32(lmb_size >> 32),
|
||||
cpu_to_be32(lmb_size & 0xffffffff)};
|
||||
uint32_t *int_buf, *cur_index, buf_len;
|
||||
int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1;
|
||||
MemoryDeviceInfoList *dimms = NULL;
|
||||
@@ -905,7 +906,8 @@ static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt)
|
||||
uint32_t lrdr_capacity[] = {
|
||||
cpu_to_be32(max_device_addr >> 32),
|
||||
cpu_to_be32(max_device_addr & 0xffffffff),
|
||||
0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE),
|
||||
cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE >> 32),
|
||||
cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE & 0xffffffff),
|
||||
cpu_to_be32(ms->smp.max_cpus / ms->smp.threads),
|
||||
};
|
||||
uint32_t maxdomain = cpu_to_be32(spapr->gpu_numa_id > 1 ? 1 : 0);
|
||||
|
||||
+60
-39
@@ -180,24 +180,24 @@ static void spapr_cap_set_pagesize(Object *obj, Visitor *v, const char *name,
|
||||
|
||||
static void cap_htm_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
if (!val) {
|
||||
/* TODO: We don't support disabling htm yet */
|
||||
return;
|
||||
}
|
||||
if (tcg_enabled()) {
|
||||
error_setg(errp,
|
||||
"No Transactional Memory support in TCG,"
|
||||
" try appending -machine cap-htm=off");
|
||||
error_setg(errp, "No Transactional Memory support in TCG");
|
||||
error_append_hint(errp, "Try appending -machine cap-htm=off\n");
|
||||
} else if (kvm_enabled() && !kvmppc_has_cap_htm()) {
|
||||
error_setg(errp,
|
||||
"KVM implementation does not support Transactional Memory,"
|
||||
" try appending -machine cap-htm=off"
|
||||
);
|
||||
"KVM implementation does not support Transactional Memory");
|
||||
error_append_hint(errp, "Try appending -machine cap-htm=off\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_vsx_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
@@ -209,13 +209,14 @@ static void cap_vsx_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
|
||||
* rid of anything that doesn't do VMX */
|
||||
g_assert(env->insns_flags & PPC_ALTIVEC);
|
||||
if (!(env->insns_flags2 & PPC2_VSX)) {
|
||||
error_setg(errp, "VSX support not available,"
|
||||
" try appending -machine cap-vsx=off");
|
||||
error_setg(errp, "VSX support not available");
|
||||
error_append_hint(errp, "Try appending -machine cap-vsx=off\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_dfp_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
@@ -224,8 +225,8 @@ static void cap_dfp_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
|
||||
return;
|
||||
}
|
||||
if (!(env->insns_flags2 & PPC2_DFP)) {
|
||||
error_setg(errp, "DFP support not available,"
|
||||
" try appending -machine cap-dfp=off");
|
||||
error_setg(errp, "DFP support not available");
|
||||
error_append_hint(errp, "Try appending -machine cap-dfp=off\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,6 +240,7 @@ SpaprCapPossible cap_cfpc_possible = {
|
||||
static void cap_safe_cache_apply(SpaprMachineState *spapr, uint8_t val,
|
||||
Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
uint8_t kvm_val = kvmppc_get_cap_safe_cache();
|
||||
|
||||
if (tcg_enabled() && val) {
|
||||
@@ -247,9 +249,9 @@ static void cap_safe_cache_apply(SpaprMachineState *spapr, uint8_t val,
|
||||
cap_cfpc_possible.vals[val]);
|
||||
} else if (kvm_enabled() && (val > kvm_val)) {
|
||||
error_setg(errp,
|
||||
"Requested safe cache capability level not supported by kvm,"
|
||||
" try appending -machine cap-cfpc=%s",
|
||||
cap_cfpc_possible.vals[kvm_val]);
|
||||
"Requested safe cache capability level not supported by KVM");
|
||||
error_append_hint(errp, "Try appending -machine cap-cfpc=%s\n",
|
||||
cap_cfpc_possible.vals[kvm_val]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,6 +265,7 @@ SpaprCapPossible cap_sbbc_possible = {
|
||||
static void cap_safe_bounds_check_apply(SpaprMachineState *spapr, uint8_t val,
|
||||
Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
uint8_t kvm_val = kvmppc_get_cap_safe_bounds_check();
|
||||
|
||||
if (tcg_enabled() && val) {
|
||||
@@ -271,9 +274,9 @@ static void cap_safe_bounds_check_apply(SpaprMachineState *spapr, uint8_t val,
|
||||
cap_sbbc_possible.vals[val]);
|
||||
} else if (kvm_enabled() && (val > kvm_val)) {
|
||||
error_setg(errp,
|
||||
"Requested safe bounds check capability level not supported by kvm,"
|
||||
" try appending -machine cap-sbbc=%s",
|
||||
cap_sbbc_possible.vals[kvm_val]);
|
||||
"Requested safe bounds check capability level not supported by KVM");
|
||||
error_append_hint(errp, "Try appending -machine cap-sbbc=%s\n",
|
||||
cap_sbbc_possible.vals[kvm_val]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,6 +293,7 @@ SpaprCapPossible cap_ibs_possible = {
|
||||
static void cap_safe_indirect_branch_apply(SpaprMachineState *spapr,
|
||||
uint8_t val, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
uint8_t kvm_val = kvmppc_get_cap_safe_indirect_branch();
|
||||
|
||||
if (tcg_enabled() && val) {
|
||||
@@ -298,9 +302,9 @@ static void cap_safe_indirect_branch_apply(SpaprMachineState *spapr,
|
||||
cap_ibs_possible.vals[val]);
|
||||
} else if (kvm_enabled() && (val > kvm_val)) {
|
||||
error_setg(errp,
|
||||
"Requested safe indirect branch capability level not supported by kvm,"
|
||||
" try appending -machine cap-ibs=%s",
|
||||
cap_ibs_possible.vals[kvm_val]);
|
||||
"Requested safe indirect branch capability level not supported by KVM");
|
||||
error_append_hint(errp, "Try appending -machine cap-ibs=%s\n",
|
||||
cap_ibs_possible.vals[kvm_val]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,23 +381,35 @@ static void cap_hpt_maxpagesize_cpu_apply(SpaprMachineState *spapr,
|
||||
static void cap_nested_kvm_hv_apply(SpaprMachineState *spapr,
|
||||
uint8_t val, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
|
||||
|
||||
if (!val) {
|
||||
/* capability disabled by default */
|
||||
return;
|
||||
}
|
||||
|
||||
if (tcg_enabled()) {
|
||||
error_setg(errp,
|
||||
"No Nested KVM-HV support in tcg,"
|
||||
" try appending -machine cap-nested-hv=off");
|
||||
error_setg(errp, "No Nested KVM-HV support in TCG");
|
||||
error_append_hint(errp, "Try appending -machine cap-nested-hv=off\n");
|
||||
} else if (kvm_enabled()) {
|
||||
if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0,
|
||||
spapr->max_compat_pvr)) {
|
||||
error_setg(errp, "Nested KVM-HV only supported on POWER9");
|
||||
error_append_hint(errp,
|
||||
"Try appending -machine max-cpu-compat=power9\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!kvmppc_has_cap_nested_kvm_hv()) {
|
||||
error_setg(errp,
|
||||
"KVM implementation does not support Nested KVM-HV,"
|
||||
" try appending -machine cap-nested-hv=off");
|
||||
"KVM implementation does not support Nested KVM-HV");
|
||||
error_append_hint(errp,
|
||||
"Try appending -machine cap-nested-hv=off\n");
|
||||
} else if (kvmppc_set_cap_nested_kvm_hv(val) < 0) {
|
||||
error_setg(errp,
|
||||
"Error enabling cap-nested-hv with KVM, try cap-nested-hv=off");
|
||||
error_setg(errp, "Error enabling cap-nested-hv with KVM");
|
||||
error_append_hint(errp,
|
||||
"Try appending -machine cap-nested-hv=off\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -401,6 +417,7 @@ static void cap_nested_kvm_hv_apply(SpaprMachineState *spapr,
|
||||
static void cap_large_decr_apply(SpaprMachineState *spapr,
|
||||
uint8_t val, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
|
||||
|
||||
@@ -411,22 +428,23 @@ static void cap_large_decr_apply(SpaprMachineState *spapr,
|
||||
if (tcg_enabled()) {
|
||||
if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0,
|
||||
spapr->max_compat_pvr)) {
|
||||
error_setg(errp,
|
||||
"Large decrementer only supported on POWER9, try -cpu POWER9");
|
||||
error_setg(errp, "Large decrementer only supported on POWER9");
|
||||
error_append_hint(errp, "Try -cpu POWER9\n");
|
||||
return;
|
||||
}
|
||||
} else if (kvm_enabled()) {
|
||||
int kvm_nr_bits = kvmppc_get_cap_large_decr();
|
||||
|
||||
if (!kvm_nr_bits) {
|
||||
error_setg(errp,
|
||||
"No large decrementer support,"
|
||||
" try appending -machine cap-large-decr=off");
|
||||
error_setg(errp, "No large decrementer support");
|
||||
error_append_hint(errp,
|
||||
"Try appending -machine cap-large-decr=off\n");
|
||||
} else if (pcc->lrg_decr_bits != kvm_nr_bits) {
|
||||
error_setg(errp,
|
||||
"KVM large decrementer size (%d) differs to model (%d),"
|
||||
" try appending -machine cap-large-decr=off",
|
||||
kvm_nr_bits, pcc->lrg_decr_bits);
|
||||
"KVM large decrementer size (%d) differs to model (%d)",
|
||||
kvm_nr_bits, pcc->lrg_decr_bits);
|
||||
error_append_hint(errp,
|
||||
"Try appending -machine cap-large-decr=off\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -435,14 +453,15 @@ static void cap_large_decr_cpu_apply(SpaprMachineState *spapr,
|
||||
PowerPCCPU *cpu,
|
||||
uint8_t val, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
CPUPPCState *env = &cpu->env;
|
||||
target_ulong lpcr = env->spr[SPR_LPCR];
|
||||
|
||||
if (kvm_enabled()) {
|
||||
if (kvmppc_enable_cap_large_decr(cpu, val)) {
|
||||
error_setg(errp,
|
||||
"No large decrementer support,"
|
||||
" try appending -machine cap-large-decr=off");
|
||||
error_setg(errp, "No large decrementer support");
|
||||
error_append_hint(errp,
|
||||
"Try appending -machine cap-large-decr=off\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,6 +476,7 @@ static void cap_large_decr_cpu_apply(SpaprMachineState *spapr,
|
||||
static void cap_ccf_assist_apply(SpaprMachineState *spapr, uint8_t val,
|
||||
Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
uint8_t kvm_val = kvmppc_get_cap_count_cache_flush_assist();
|
||||
|
||||
if (tcg_enabled() && val) {
|
||||
@@ -479,14 +499,15 @@ static void cap_ccf_assist_apply(SpaprMachineState *spapr, uint8_t val,
|
||||
return;
|
||||
}
|
||||
error_setg(errp,
|
||||
"Requested count cache flush assist capability level not supported by kvm,"
|
||||
" try appending -machine cap-ccf-assist=off");
|
||||
"Requested count cache flush assist capability level not supported by KVM");
|
||||
error_append_hint(errp, "Try appending -machine cap-ccf-assist=off\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_fwnmi_apply(SpaprMachineState *spapr, uint8_t val,
|
||||
Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
if (!val) {
|
||||
return; /* Disabled by default */
|
||||
}
|
||||
|
||||
+9
-3
@@ -139,6 +139,7 @@ SpaprIrq spapr_irq_dual = {
|
||||
|
||||
static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
MachineState *machine = MACHINE(spapr);
|
||||
|
||||
/*
|
||||
@@ -179,14 +180,19 @@ static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
|
||||
|
||||
/*
|
||||
* On a POWER9 host, some older KVM XICS devices cannot be destroyed and
|
||||
* re-created. Detect that early to avoid QEMU to exit later when the
|
||||
* guest reboots.
|
||||
* re-created. Same happens with KVM nested guests. Detect that early to
|
||||
* avoid QEMU to exit later when the guest reboots.
|
||||
*/
|
||||
if (kvm_enabled() &&
|
||||
spapr->irq == &spapr_irq_dual &&
|
||||
kvm_kernel_irqchip_required() &&
|
||||
xics_kvm_has_broken_disconnect(spapr)) {
|
||||
error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on");
|
||||
error_setg(errp,
|
||||
"KVM is incompatible with ic-mode=dual,kernel-irqchip=on");
|
||||
error_append_hint(errp,
|
||||
"This can happen with an old KVM or in a KVM nested guest.\n");
|
||||
error_append_hint(errp,
|
||||
"Try without kernel-irqchip or with kernel-irqchip=off.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
+7
-9
@@ -1796,6 +1796,7 @@ static void spapr_phb_destroy_msi(gpointer opaque)
|
||||
|
||||
static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
/* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
|
||||
* tries to add a sPAPR PHB to a non-pseries machine.
|
||||
*/
|
||||
@@ -1813,7 +1814,6 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
uint64_t msi_window_size = 4096;
|
||||
SpaprTceTable *tcet;
|
||||
const unsigned windows_supported = spapr_phb_windows_supported(sphb);
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (!spapr) {
|
||||
error_setg(errp, TYPE_SPAPR_PCI_HOST_BRIDGE " needs a pseries machine");
|
||||
@@ -1964,13 +1964,12 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
/* Initialize the LSI table */
|
||||
for (i = 0; i < PCI_NUM_PINS; i++) {
|
||||
uint32_t irq = SPAPR_IRQ_PCI_LSI + sphb->index * PCI_NUM_PINS + i;
|
||||
int irq = SPAPR_IRQ_PCI_LSI + sphb->index * PCI_NUM_PINS + i;
|
||||
|
||||
if (smc->legacy_irq_allocation) {
|
||||
irq = spapr_irq_findone(spapr, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate_prepend(errp, local_err,
|
||||
"can't allocate LSIs: ");
|
||||
irq = spapr_irq_findone(spapr, errp);
|
||||
if (irq < 0) {
|
||||
error_prepend(errp, "can't allocate LSIs: ");
|
||||
/*
|
||||
* Older machines will never support PHB hotplug, ie, this is an
|
||||
* init only path and QEMU will terminate. No need to rollback.
|
||||
@@ -1979,9 +1978,8 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
spapr_irq_claim(spapr, irq, true, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate_prepend(errp, local_err, "can't allocate LSIs: ");
|
||||
if (spapr_irq_claim(spapr, irq, true, errp) < 0) {
|
||||
error_prepend(errp, "can't allocate LSIs: ");
|
||||
goto unrealize;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -143,7 +143,7 @@ static void nvram_init(Nvram *nvram, uint8_t *macaddr,
|
||||
memset(image, '\0', sizeof(image));
|
||||
|
||||
/* OpenBIOS nvram variables partition */
|
||||
sysp_end = chrp_nvram_create_system_partition(image, 0);
|
||||
sysp_end = chrp_nvram_create_system_partition(image, 0, 0x1fd0);
|
||||
|
||||
/* Free space partition */
|
||||
chrp_nvram_create_free_partition(&image[sysp_end], 0x1fd0 - sysp_end);
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@ static int sun4u_NVRAM_set_params(Nvram *nvram, uint16_t NVRAM_size,
|
||||
memset(image, '\0', sizeof(image));
|
||||
|
||||
/* OpenBIOS nvram variables partition */
|
||||
sysp_end = chrp_nvram_create_system_partition(image, 0);
|
||||
sysp_end = chrp_nvram_create_system_partition(image, 0, 0x1fd0);
|
||||
|
||||
/* Free space partition */
|
||||
chrp_nvram_create_free_partition(&image[sysp_end], 0x1fd0 - sysp_end);
|
||||
|
||||
@@ -558,6 +558,7 @@ typedef struct {
|
||||
#define PPC_FEATURE2_HTM_NOSC 0x01000000
|
||||
#define PPC_FEATURE2_ARCH_3_00 0x00800000
|
||||
#define PPC_FEATURE2_HAS_IEEE128 0x00400000
|
||||
#define PPC_FEATURE2_ARCH_3_10 0x00040000
|
||||
|
||||
/* Bits present in AT_HWCAP for Sparc. */
|
||||
|
||||
|
||||
@@ -50,7 +50,8 @@ chrp_nvram_finish_partition(ChrpNvramPartHdr *header, uint32_t size)
|
||||
header->checksum = sum & 0xff;
|
||||
}
|
||||
|
||||
int chrp_nvram_create_system_partition(uint8_t *data, int min_len);
|
||||
/* chrp_nvram_create_system_partition() failure is fatal */
|
||||
int chrp_nvram_create_system_partition(uint8_t *data, int min_len, int max_len);
|
||||
int chrp_nvram_create_free_partition(uint8_t *data, int len);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -80,15 +80,15 @@ int kvmppc_xive_connect(SpaprInterruptController *intc, uint32_t nr_servers,
|
||||
Error **errp);
|
||||
void kvmppc_xive_disconnect(SpaprInterruptController *intc);
|
||||
void kvmppc_xive_reset(SpaprXive *xive, Error **errp);
|
||||
void kvmppc_xive_set_source_config(SpaprXive *xive, uint32_t lisn, XiveEAS *eas,
|
||||
Error **errp);
|
||||
int kvmppc_xive_set_source_config(SpaprXive *xive, uint32_t lisn, XiveEAS *eas,
|
||||
Error **errp);
|
||||
void kvmppc_xive_sync_source(SpaprXive *xive, uint32_t lisn, Error **errp);
|
||||
uint64_t kvmppc_xive_esb_rw(XiveSource *xsrc, int srcno, uint32_t offset,
|
||||
uint64_t data, bool write);
|
||||
void kvmppc_xive_set_queue_config(SpaprXive *xive, uint8_t end_blk,
|
||||
int kvmppc_xive_set_queue_config(SpaprXive *xive, uint8_t end_blk,
|
||||
uint32_t end_idx, XiveEND *end,
|
||||
Error **errp);
|
||||
void kvmppc_xive_get_queue_config(SpaprXive *xive, uint8_t end_blk,
|
||||
int kvmppc_xive_get_queue_config(SpaprXive *xive, uint8_t end_blk,
|
||||
uint32_t end_idx, XiveEND *end,
|
||||
Error **errp);
|
||||
void kvmppc_xive_synchronize_state(SpaprXive *xive, Error **errp);
|
||||
|
||||
+11
-4
@@ -191,6 +191,7 @@ typedef struct XiveSource {
|
||||
uint64_t esb_flags;
|
||||
uint32_t esb_shift;
|
||||
MemoryRegion esb_mmio;
|
||||
MemoryRegion esb_mmio_emulated;
|
||||
|
||||
/* KVM support */
|
||||
void *esb_mmap;
|
||||
@@ -215,6 +216,11 @@ static inline bool xive_source_esb_has_2page(XiveSource *xsrc)
|
||||
xsrc->esb_shift == XIVE_ESB_4K_2PAGE;
|
||||
}
|
||||
|
||||
static inline size_t xive_source_esb_len(XiveSource *xsrc)
|
||||
{
|
||||
return (1ull << xsrc->esb_shift) * xsrc->nr_irqs;
|
||||
}
|
||||
|
||||
/* The trigger page is always the first/even page */
|
||||
static inline hwaddr xive_source_esb_page(XiveSource *xsrc, uint32_t srcno)
|
||||
{
|
||||
@@ -396,6 +402,7 @@ typedef struct XivePresenterClass {
|
||||
uint8_t nvt_blk, uint32_t nvt_idx,
|
||||
bool cam_ignore, uint8_t priority,
|
||||
uint32_t logic_serv, XiveTCTXMatch *match);
|
||||
bool (*in_kernel)(const XivePresenter *xptr);
|
||||
} XivePresenterClass;
|
||||
|
||||
int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx,
|
||||
@@ -480,9 +487,9 @@ void xive_tctx_ipb_update(XiveTCTX *tctx, uint8_t ring, uint8_t ipb);
|
||||
|
||||
int kvmppc_xive_source_reset_one(XiveSource *xsrc, int srcno, Error **errp);
|
||||
void kvmppc_xive_source_set_irq(void *opaque, int srcno, int val);
|
||||
void kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp);
|
||||
void kvmppc_xive_cpu_synchronize_state(XiveTCTX *tctx, Error **errp);
|
||||
void kvmppc_xive_cpu_get_state(XiveTCTX *tctx, Error **errp);
|
||||
void kvmppc_xive_cpu_set_state(XiveTCTX *tctx, Error **errp);
|
||||
int kvmppc_xive_cpu_connect(XiveTCTX *tctx, Error **errp);
|
||||
int kvmppc_xive_cpu_synchronize_state(XiveTCTX *tctx, Error **errp);
|
||||
int kvmppc_xive_cpu_get_state(XiveTCTX *tctx, Error **errp);
|
||||
int kvmppc_xive_cpu_set_state(XiveTCTX *tctx, Error **errp);
|
||||
|
||||
#endif /* PPC_XIVE_H */
|
||||
|
||||
+3
-1
@@ -2191,6 +2191,8 @@ enum {
|
||||
PPC2_PM_ISA206 = 0x0000000000040000ULL,
|
||||
/* POWER ISA 3.0 */
|
||||
PPC2_ISA300 = 0x0000000000080000ULL,
|
||||
/* POWER ISA 3.1 */
|
||||
PPC2_ISA310 = 0x0000000000100000ULL,
|
||||
|
||||
#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_VSX | PPC2_PRCNTL | PPC2_DBRX | \
|
||||
PPC2_ISA205 | PPC2_VSX207 | PPC2_PERM_ISA206 | \
|
||||
@@ -2199,7 +2201,7 @@ enum {
|
||||
PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | \
|
||||
PPC2_ALTIVEC_207 | PPC2_ISA207S | PPC2_DFP | \
|
||||
PPC2_FP_CVT_S64 | PPC2_TM | PPC2_PM_ISA206 | \
|
||||
PPC2_ISA300)
|
||||
PPC2_ISA300 | PPC2_ISA310)
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user