* [Qemu-devel] [PATCH v2 1/9] target-ppc: Add "compat" CPU option
2014-05-21 8:27 [Qemu-devel] [PATCH v2 0/9] spapr: Enable ibm, client-architecture-support Alexey Kardashevskiy
@ 2014-05-21 8:27 ` Alexey Kardashevskiy
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 2/9] spapr: Move SMT-related properties out of skeleton fdt Alexey Kardashevskiy
` (8 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-21 8:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
PowerISA defines a compatibility mode for server POWERPC CPUs which
is supported by the PCR special register which is hypervisor privileged.
To support this mode for guests, SPAPR defines a set of virtual PVRs,
one per PowerISA spec version. When a hypervisor needs a guest to work in
a compatibility mode, it puts a virtual PVR value into @cpu-version
property of a CPU node.
This introduces a "compat" CPU option which defines maximal compatibility
mode enabled. The supported modes are power6/power7/power8.
This does not change the existing behaviour, new property will be used
by next patches.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
target-ppc/cpu-models.h | 10 ++++++
target-ppc/cpu-qom.h | 2 ++
target-ppc/translate_init.c | 75 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 87 insertions(+)
diff --git a/target-ppc/cpu-models.h b/target-ppc/cpu-models.h
index 9a003b4..db75896 100644
--- a/target-ppc/cpu-models.h
+++ b/target-ppc/cpu-models.h
@@ -595,6 +595,16 @@ enum {
CPU_POWERPC_PA6T = 0x00900000,
};
+/* Logical PVR definitions for sPAPR */
+enum {
+ CPU_POWERPC_LOGICAL_2_04 = 0x0F000001,
+ CPU_POWERPC_LOGICAL_2_05 = 0x0F000002,
+ CPU_POWERPC_LOGICAL_2_06 = 0x0F000003,
+ CPU_POWERPC_LOGICAL_2_06_PLUS = 0x0F100003,
+ CPU_POWERPC_LOGICAL_2_07 = 0x0F000004,
+ CPU_POWERPC_LOGICAL_2_08 = 0x0F000005,
+};
+
/* System version register (used on MPC 8xxx) */
enum {
POWERPC_SVR_NONE = 0x00000000,
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 046ea0e..533de8f 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -83,6 +83,7 @@ typedef struct PowerPCCPUClass {
* PowerPCCPU:
* @env: #CPUPPCState
* @cpu_dt_id: CPU index used in the device tree. KVM uses this index too
+ * @max_compat: Maximal supported logical PVR from the command line
*
* A PowerPC CPU.
*/
@@ -93,6 +94,7 @@ struct PowerPCCPU {
CPUPPCState env;
int cpu_dt_id;
+ uint32_t max_compat;
};
static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 16ecada..2e273dc 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -28,6 +28,8 @@
#include "mmu-hash32.h"
#include "mmu-hash64.h"
#include "qemu/error-report.h"
+#include "qapi/visitor.h"
+#include "hw/qdev-properties.h"
//#define PPC_DUMP_CPU
//#define PPC_DEBUG_SPR
@@ -7680,6 +7682,76 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
pcc->l1_icache_size = 0x10000;
}
+static void powerpc_get_compat(Object *obj, Visitor *v,
+ void *opaque, const char *name, Error **errp)
+{
+ char *value = (char *)"";
+ Property *prop = opaque;
+ uint32_t *max_compat = qdev_get_prop_ptr(DEVICE(obj), prop);
+
+ switch (*max_compat) {
+ case CPU_POWERPC_LOGICAL_2_05:
+ value = (char *)"power6";
+ break;
+ case CPU_POWERPC_LOGICAL_2_06:
+ value = (char *)"power7";
+ break;
+ case CPU_POWERPC_LOGICAL_2_07:
+ value = (char *)"power8";
+ break;
+ case 0:
+ break;
+ default:
+ error_setg(errp, "Internal error: compat is set to %x",
+ max_compat ? *max_compat : -1);
+ break;
+ }
+
+ visit_type_str(v, &value, name, errp);
+}
+
+static void powerpc_set_compat(Object *obj, Visitor *v,
+ void *opaque, const char *name, Error **errp)
+{
+ Error *error = NULL;
+ char *value = NULL;
+ Property *prop = opaque;
+ uint32_t *max_compat = qdev_get_prop_ptr(DEVICE(obj), prop);
+
+ visit_type_str(v, &value, name, &error);
+ if (error) {
+ error_propagate(errp, error);
+ return;
+ }
+
+ if (strcmp(value, "power6") == 0) {
+ *max_compat = CPU_POWERPC_LOGICAL_2_05;
+ } else if (strcmp(value, "power7") == 0) {
+ *max_compat = CPU_POWERPC_LOGICAL_2_06;
+ } else if (strcmp(value, "power8") == 0) {
+ *max_compat = CPU_POWERPC_LOGICAL_2_07;
+ } else {
+ error_setg(errp, "Invalid compatibility mode \"%s\"", value);
+ }
+
+ g_free(value);
+}
+
+static PropertyInfo powerpc_compat_propinfo = {
+ .name = "str",
+ .legacy_name = "powerpc-server-compat",
+ .get = powerpc_get_compat,
+ .set = powerpc_set_compat,
+};
+
+#define DEFINE_PROP_POWERPC_COMPAT(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, powerpc_compat_propinfo, uint32_t)
+
+static Property powerpc_servercpu_properties[] = {
+ DEFINE_PROP_POWERPC_COMPAT("compat", PowerPCCPU, max_compat),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void init_proc_POWER7 (CPUPPCState *env)
{
gen_spr_ne_601(env);
@@ -7766,6 +7838,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER7";
dc->desc = "POWER7";
+ dc->props = powerpc_servercpu_properties;
pcc->pvr = CPU_POWERPC_POWER7_BASE;
pcc->pvr_mask = CPU_POWERPC_POWER7_MASK;
pcc->init_proc = init_proc_POWER7;
@@ -7825,6 +7898,7 @@ POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER7+";
dc->desc = "POWER7+";
+ dc->props = powerpc_servercpu_properties;
pcc->pvr = CPU_POWERPC_POWER7P_BASE;
pcc->pvr_mask = CPU_POWERPC_POWER7P_MASK;
pcc->init_proc = init_proc_POWER7;
@@ -7896,6 +7970,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER8";
dc->desc = "POWER8";
+ dc->props = powerpc_servercpu_properties;
pcc->pvr = CPU_POWERPC_POWER8_BASE;
pcc->pvr_mask = CPU_POWERPC_POWER8_MASK;
pcc->init_proc = init_proc_POWER8;
--
1.9.rc0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v2 2/9] spapr: Move SMT-related properties out of skeleton fdt
2014-05-21 8:27 [Qemu-devel] [PATCH v2 0/9] spapr: Enable ibm, client-architecture-support Alexey Kardashevskiy
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 1/9] target-ppc: Add "compat" CPU option Alexey Kardashevskiy
@ 2014-05-21 8:27 ` Alexey Kardashevskiy
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 3/9] target-ppc: Implement "compat" CPU option Alexey Kardashevskiy
` (7 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-21 8:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
The upcoming support of the "ibm,client-architecture-support"
reconfiguration call will be able to change dynamically the number
of threads per core (SMT mode). From the device tree prospective
this does not change the number of CPU nodes (as it is one node per
a CPU core) but affects content and size of the ibm,ppc-interrupt-server#s
and ibm,ppc-interrupt-gserver#s properties.
This moves ibm,ppc-interrupt-server#s and ibm,ppc-interrupt-gserver#s
out of the device tree skeleton.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr.c | 48 +++++++++++++++++++++++++++++++++---------------
1 file changed, 33 insertions(+), 15 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 0a61246..aa17cae 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -202,6 +202,32 @@ static XICSState *xics_system_init(int nr_servers, int nr_irqs)
return icp;
}
+static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu,
+ int smt_threads)
+{
+ int i, ret = 0;
+ uint32_t servers_prop[smt_threads];
+ uint32_t gservers_prop[smt_threads * 2];
+ int index = ppc_get_vcpu_dt_id(cpu);
+
+ /* Build interrupt servers and gservers properties */
+ for (i = 0; i < smt_threads; i++) {
+ servers_prop[i] = cpu_to_be32(index + i);
+ /* Hack, direct the group queues back to cpu 0 */
+ gservers_prop[i*2] = cpu_to_be32(index + i);
+ gservers_prop[i*2 + 1] = 0;
+ }
+ ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
+ servers_prop, sizeof(servers_prop));
+ if (ret < 0) {
+ return ret;
+ }
+ ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s",
+ gservers_prop, sizeof(gservers_prop));
+
+ return ret;
+}
+
static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
{
int ret = 0, offset;
@@ -245,6 +271,12 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
if (ret < 0) {
return ret;
}
+
+ ret = spapr_fixup_cpu_smt_dt(fdt, offset, POWERPC_CPU(cpu),
+ smp_threads);
+ if (ret < 0) {
+ return ret;
+ }
}
return ret;
}
@@ -311,7 +343,7 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
char qemu_hypertas_prop[] = "hcall-memop1";
uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
- int i, smt = kvmppc_smt_threads();
+ int smt = kvmppc_smt_threads();
unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
QemuOpts *opts = qemu_opts_find(qemu_find_opts("smp-opts"), NULL);
unsigned sockets = opts ? qemu_opt_get_number(opts, "sockets", 0) : 0;
@@ -378,8 +410,6 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
DeviceClass *dc = DEVICE_GET_CLASS(cs);
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
int index = ppc_get_vcpu_dt_id(cpu);
- uint32_t servers_prop[smp_threads];
- uint32_t gservers_prop[smp_threads * 2];
char *nodename;
uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
0xffffffff, 0xffffffff};
@@ -428,18 +458,6 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
_FDT((fdt_property_string(fdt, "status", "okay")));
_FDT((fdt_property(fdt, "64-bit", NULL, 0)));
- /* Build interrupt servers and gservers properties */
- for (i = 0; i < smp_threads; i++) {
- servers_prop[i] = cpu_to_be32(index + i);
- /* Hack, direct the group queues back to cpu 0 */
- gservers_prop[i*2] = cpu_to_be32(index + i);
- gservers_prop[i*2 + 1] = 0;
- }
- _FDT((fdt_property(fdt, "ibm,ppc-interrupt-server#s",
- servers_prop, sizeof(servers_prop))));
- _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
- gservers_prop, sizeof(gservers_prop))));
-
if (env->spr_cb[SPR_PURR].oea_read) {
_FDT((fdt_property(fdt, "ibm,purr", NULL, 0)));
}
--
1.9.rc0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v2 3/9] target-ppc: Implement "compat" CPU option
2014-05-21 8:27 [Qemu-devel] [PATCH v2 0/9] spapr: Enable ibm, client-architecture-support Alexey Kardashevskiy
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 1/9] target-ppc: Add "compat" CPU option Alexey Kardashevskiy
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 2/9] spapr: Move SMT-related properties out of skeleton fdt Alexey Kardashevskiy
@ 2014-05-21 8:27 ` Alexey Kardashevskiy
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 4/9] target-ppc: Define Processor Compatibility Masks Alexey Kardashevskiy
` (6 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-21 8:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
This adds basic support for the "compat" CPU option. By specifying
the compat property, the user can manually switch guest CPU mode from
"raw" to "architected".
This defines feature disable bits which are not used yet as, for example,
PowerISA 2.07 says if 2.06 mode is selected, the TM bit does not matter -
transactional memory (TM) will be disabled because 2.06 does not define
it at all. The same is true for VSX and 2.05 mode. So just setting a mode
must be ok.
This does not change the existing behavior as the actual compatibility
mode support is coming in next patches.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr.c | 14 ++++++++++++++
target-ppc/cpu-qom.h | 2 ++
target-ppc/cpu.h | 11 +++++++++++
target-ppc/translate_init.c | 34 ++++++++++++++++++++++++++++++++++
4 files changed, 61 insertions(+)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index aa17cae..5ea9640 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -210,6 +210,14 @@ static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu,
uint32_t gservers_prop[smt_threads * 2];
int index = ppc_get_vcpu_dt_id(cpu);
+ if (cpu->cpu_version) {
+ ret = fdt_setprop(fdt, offset, "cpu-version",
+ &cpu->cpu_version, sizeof(cpu->cpu_version));
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
/* Build interrupt servers and gservers properties */
for (i = 0; i < smt_threads; i++) {
servers_prop[i] = cpu_to_be32(index + i);
@@ -1289,6 +1297,12 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
kvmppc_set_papr(cpu);
}
+ if (cpu->max_compat) {
+ if (ppc_set_compat(cpu, cpu->max_compat) < 0) {
+ exit(1);
+ }
+ }
+
xics_cpu_setup(spapr->icp, cpu);
qemu_register_reset(spapr_cpu_reset, cpu);
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 533de8f..e88e1da 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -84,6 +84,7 @@ typedef struct PowerPCCPUClass {
* @env: #CPUPPCState
* @cpu_dt_id: CPU index used in the device tree. KVM uses this index too
* @max_compat: Maximal supported logical PVR from the command line
+ * @cpu_version: Current logical PVR, zero if in "raw" mode
*
* A PowerPC CPU.
*/
@@ -95,6 +96,7 @@ struct PowerPCCPU {
CPUPPCState env;
int cpu_dt_id;
uint32_t max_compat;
+ uint32_t cpu_version;
};
static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index b035e91..d3b8236 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1122,6 +1122,7 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
void ppc_store_msr (CPUPPCState *env, target_ulong value);
void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf);
+int ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version);
/* Time-base and decrementer management */
#ifndef NO_CPU_IO_DEFS
@@ -1338,6 +1339,7 @@ static inline int cpu_mmu_index (CPUPPCState *env)
#define SPR_LPCR (0x13E)
#define SPR_BOOKE_DVC2 (0x13F)
#define SPR_BOOKE_TSR (0x150)
+#define SPR_PCR (0x152)
#define SPR_BOOKE_TCR (0x154)
#define SPR_BOOKE_TLB0PS (0x158)
#define SPR_BOOKE_TLB1PS (0x159)
@@ -2061,6 +2063,15 @@ enum {
PPC_INTERRUPT_PERFM, /* Performance monitor interrupt */
};
+/* Processor Compatibility mask (PCR) */
+enum {
+ PCR_COMPAT_2_05 = 1ul << (63-62),
+ PCR_COMPAT_2_06 = 1ul << (63-61),
+ PCR_VEC_DIS = 1ul << (63-0), /* Vec. disable (bit NA since POWER8) */
+ PCR_VSX_DIS = 1ul << (63-1), /* VSX disable (bit NA since POWER8) */
+ PCR_TM_DIS = 1ul << (63-2), /* Trans. memory disable (POWER8) */
+};
+
/*****************************************************************************/
static inline target_ulong cpu_read_xer(CPUPPCState *env)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 2e273dc..41afc5e 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7829,6 +7829,15 @@ static void init_proc_POWER7 (CPUPPCState *env)
/* Can't find information on what this should be on reset. This
* value is the one used by 74xx processors. */
vscr_init(env, 0x00010000);
+
+ /*
+ * Register PCR to report POWERPC_EXCP_PRIV_REG instead of
+ * POWERPC_EXCP_INVAL_SPR.
+ */
+ spr_register(env, SPR_PCR, "PCR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ 0x00000000);
}
POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
@@ -8909,6 +8918,31 @@ static void ppc_cpu_unrealizefn(DeviceState *dev, Error **errp)
}
}
+int ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version)
+{
+ int ret = 0;
+ CPUPPCState *env = &cpu->env;
+
+ cpu->cpu_version = cpu_version;
+
+ switch (cpu_version) {
+ case CPU_POWERPC_LOGICAL_2_05:
+ env->spr[SPR_PCR] = PCR_COMPAT_2_05;
+ break;
+ case CPU_POWERPC_LOGICAL_2_06:
+ env->spr[SPR_PCR] = PCR_COMPAT_2_06;
+ break;
+ case CPU_POWERPC_LOGICAL_2_06_PLUS:
+ env->spr[SPR_PCR] = PCR_COMPAT_2_06;
+ break;
+ default:
+ env->spr[SPR_PCR] = 0;
+ break;
+ }
+
+ return ret;
+}
+
static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b)
{
ObjectClass *oc = (ObjectClass *)a;
--
1.9.rc0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v2 4/9] target-ppc: Define Processor Compatibility Masks
2014-05-21 8:27 [Qemu-devel] [PATCH v2 0/9] spapr: Enable ibm, client-architecture-support Alexey Kardashevskiy
` (2 preceding siblings ...)
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 3/9] target-ppc: Implement "compat" CPU option Alexey Kardashevskiy
@ 2014-05-21 8:27 ` Alexey Kardashevskiy
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 5/9] spapr: Add ibm, client-architecture-support call Alexey Kardashevskiy
` (5 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-21 8:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
This introduces PCR mask for supported compatibility modes.
This will be used later by the ibm,client-architecture-support call.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
target-ppc/cpu-qom.h | 1 +
target-ppc/translate_init.c | 3 +++
2 files changed, 4 insertions(+)
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index e88e1da..13c7031 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -57,6 +57,7 @@ typedef struct PowerPCCPUClass {
uint32_t pvr;
uint32_t pvr_mask;
+ uint64_t pcr_mask;
uint32_t svr;
uint64_t insns_flags;
uint64_t insns_flags2;
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 41afc5e..faac74a 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7850,6 +7850,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
dc->props = powerpc_servercpu_properties;
pcc->pvr = CPU_POWERPC_POWER7_BASE;
pcc->pvr_mask = CPU_POWERPC_POWER7_MASK;
+ pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06;
pcc->init_proc = init_proc_POWER7;
pcc->check_pow = check_pow_nocheck;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
@@ -7910,6 +7911,7 @@ POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data)
dc->props = powerpc_servercpu_properties;
pcc->pvr = CPU_POWERPC_POWER7P_BASE;
pcc->pvr_mask = CPU_POWERPC_POWER7P_MASK;
+ pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06;
pcc->init_proc = init_proc_POWER7;
pcc->check_pow = check_pow_nocheck;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
@@ -7982,6 +7984,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
dc->props = powerpc_servercpu_properties;
pcc->pvr = CPU_POWERPC_POWER8_BASE;
pcc->pvr_mask = CPU_POWERPC_POWER8_MASK;
+ pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06;
pcc->init_proc = init_proc_POWER8;
pcc->check_pow = check_pow_nocheck;
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
--
1.9.rc0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v2 5/9] spapr: Add ibm, client-architecture-support call
2014-05-21 8:27 [Qemu-devel] [PATCH v2 0/9] spapr: Enable ibm, client-architecture-support Alexey Kardashevskiy
` (3 preceding siblings ...)
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 4/9] target-ppc: Define Processor Compatibility Masks Alexey Kardashevskiy
@ 2014-05-21 8:27 ` Alexey Kardashevskiy
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 6/9] spapr: Rework spapr_fixup_cpu_dt() Alexey Kardashevskiy
` (4 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-21 8:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
The PAPR+ specification defines a ibm,client-architecture-support (CAS)
RTAS call which purpose is to provide a negotiation mechanism for
the guest and the hypervisor to work out the best compatibility parameters.
During the negotiation process, the guest provides an array of various
options and capabilities which it supports, the hypervisor adjusts
the device tree and (optionally) reboots the guest.
At the moment the Linux guest calls CAS method at early boot so SLOF
gets called. SLOF allocates a memory buffer for the device tree changes
and calls a custom KVMPPC_H_CAS hypercall. QEMU parses the options,
composes a diff for the device tree, copies it to the buffer provided
by SLOF and returns to SLOF. SLOF updates the device tree and returns
control to the guest kernel. Only then the Linux guest parses the device
tree so it is possible to avoid unnecessary reboot in most cases.
The device tree diff is a header with an update format version
(defined as 1 in this patch) followed by a device tree with the properties
which require update.
If QEMU detects that it has to reboot the guest, it silently does so
as the guest expects reboot to happen because this is usual pHyp firmware
behavior.
This defines custom KVMPPC_H_CAS hypercall. The current SLOF already
has support for it.
This implements stub which returns very basic tree (root node,
no properties) to the guest.
As the return buffer does not contain any change, no change in behavior is
expected.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr.c | 36 ++++++++++++++++++++++++++++++++++++
hw/ppc/spapr_hcall.c | 21 +++++++++++++++++++++
include/hw/ppc/spapr.h | 9 ++++++++-
trace-events | 4 ++++
4 files changed, 69 insertions(+), 1 deletion(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 5ea9640..400d0c7 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -53,6 +53,7 @@
#include "hw/usb.h"
#include "qemu/config-file.h"
#include "qemu/error-report.h"
+#include "trace.h"
#include <libfdt.h>
@@ -572,6 +573,41 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
return fdt;
}
+int spapr_h_cas_compose_response(target_ulong addr, target_ulong size)
+{
+ void *fdt, *fdt_skel;
+ sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 };
+
+ size -= sizeof(hdr);
+
+ /* Create sceleton */
+ fdt_skel = g_malloc0(size);
+ _FDT((fdt_create(fdt_skel, size)));
+ _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);
+
+ /* Place to make changes to the tree */
+
+ /* Pack resulting tree */
+ _FDT((fdt_pack(fdt)));
+
+ if (fdt_totalsize(fdt) + sizeof(hdr) > size) {
+ trace_spapr_cas_failed(size);
+ return -1;
+ }
+
+ 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);
+
+ return 0;
+}
+
static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
{
uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 0bae053..2f6aa5c 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -752,6 +752,24 @@ out:
return ret;
}
+static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
+ sPAPREnvironment *spapr,
+ target_ulong opcode,
+ target_ulong *args)
+{
+ target_ulong list = args[0];
+
+ if (!list) {
+ return H_SUCCESS;
+ }
+
+ if (spapr_h_cas_compose_response(args[1], args[2])) {
+ qemu_system_reset_request();
+ }
+
+ return H_SUCCESS;
+}
+
static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];
@@ -831,6 +849,9 @@ static void hypercall_register_types(void)
spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
spapr_register_hypercall(H_SET_MODE, h_set_mode);
+
+ /* ibm,client-architecture-support support */
+ spapr_register_hypercall(KVMPPC_H_CAS, h_client_architecture_support);
}
type_init(hypercall_register_types)
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 9f8bb89..b8c2ba4 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -303,10 +303,16 @@ typedef struct sPAPREnvironment {
#define KVMPPC_HCALL_BASE 0xf000
#define KVMPPC_H_RTAS (KVMPPC_HCALL_BASE + 0x0)
#define KVMPPC_H_LOGICAL_MEMOP (KVMPPC_HCALL_BASE + 0x1)
-#define KVMPPC_HCALL_MAX KVMPPC_H_LOGICAL_MEMOP
+/* Client Architecture support */
+#define KVMPPC_H_CAS (KVMPPC_HCALL_BASE + 0x2)
+#define KVMPPC_HCALL_MAX KVMPPC_H_CAS
extern sPAPREnvironment *spapr;
+typedef struct sPAPRDeviceTreeUpdateHeader {
+ uint32_t version_id;
+} sPAPRDeviceTreeUpdateHeader;
+
/*#define DEBUG_SPAPR_HCALLS*/
#ifdef DEBUG_SPAPR_HCALLS
@@ -402,6 +408,7 @@ struct sPAPRTCETable {
void spapr_events_init(sPAPREnvironment *spapr);
void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
+int spapr_h_cas_compose_response(target_ulong addr, target_ulong size);
sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
size_t window_size);
MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet);
diff --git a/trace-events b/trace-events
index 5997846..98d8e6a 100644
--- a/trace-events
+++ b/trace-events
@@ -1183,6 +1183,10 @@ xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_
xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]"
xics_ics_eoi(int nr) "ics_eoi: irq %#x"
+# hw/ppc/spapr.c
+spapr_cas_failed(unsigned long n) "DT diff buffer is too small: %ld bytes"
+spapr_cas_continue(unsigned long n) "Copy changes to the guest: %ld bytes"
+
# hw/ppc/spapr_iommu.c
spapr_iommu_put(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tce=0x%"PRIx64" ret=%"PRId64
spapr_iommu_get(uint64_t liobn, uint64_t ioba, uint64_t ret, uint64_t tce) "liobn=%"PRIx64" ioba=0x%"PRIx64" ret=%"PRId64" tce=0x%"PRIx64
--
1.9.rc0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v2 6/9] spapr: Rework spapr_fixup_cpu_dt()
2014-05-21 8:27 [Qemu-devel] [PATCH v2 0/9] spapr: Enable ibm, client-architecture-support Alexey Kardashevskiy
` (4 preceding siblings ...)
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 5/9] spapr: Add ibm, client-architecture-support call Alexey Kardashevskiy
@ 2014-05-21 8:27 ` Alexey Kardashevskiy
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 7/9] spapr: Limit threads per core according to current compatibility mode Alexey Kardashevskiy
` (3 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-21 8:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
In PPC code we usually use the "cs" name for a CPUState* variables
and "cpu" for PowerPCCPU. So let's change spapr_fixup_cpu_dt() to
use same rules as spapr_create_fdt_skel() does.
This adds missing nodes creation if they do not already exist in
the current device tree, this is going to be used from
the client-architecture-support handler.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr.c | 33 ++++++++++++++++++++++-----------
1 file changed, 22 insertions(+), 11 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 400d0c7..7082237 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -239,32 +239,43 @@ static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu,
static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
{
- int ret = 0, offset;
- CPUState *cpu;
+ int ret = 0, offset, cpus_offset;
+ CPUState *cs;
char cpu_model[32];
int smt = kvmppc_smt_threads();
uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
- CPU_FOREACH(cpu) {
- DeviceClass *dc = DEVICE_GET_CLASS(cpu);
- int index = ppc_get_vcpu_dt_id(POWERPC_CPU(cpu));
+ CPU_FOREACH(cs) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ DeviceClass *dc = DEVICE_GET_CLASS(cs);
+ int index = ppc_get_vcpu_dt_id(cpu);
uint32_t associativity[] = {cpu_to_be32(0x5),
cpu_to_be32(0x0),
cpu_to_be32(0x0),
cpu_to_be32(0x0),
- cpu_to_be32(cpu->numa_node),
+ cpu_to_be32(cs->numa_node),
cpu_to_be32(index)};
if ((index % smt) != 0) {
continue;
}
- snprintf(cpu_model, 32, "/cpus/%s@%x", dc->fw_name,
- index);
+ snprintf(cpu_model, 32, "%s@%x", dc->fw_name, index);
- offset = fdt_path_offset(fdt, cpu_model);
+ cpus_offset = fdt_path_offset(fdt, "/cpus");
+ if (cpus_offset < 0) {
+ cpus_offset = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
+ "cpus");
+ if (cpus_offset < 0) {
+ return cpus_offset;
+ }
+ }
+ offset = fdt_subnode_offset(fdt, cpus_offset, cpu_model);
if (offset < 0) {
- return offset;
+ offset = fdt_add_subnode(fdt, cpus_offset, cpu_model);
+ if (offset < 0) {
+ return offset;
+ }
}
if (nb_numa_nodes > 1) {
@@ -281,7 +292,7 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
return ret;
}
- ret = spapr_fixup_cpu_smt_dt(fdt, offset, POWERPC_CPU(cpu),
+ ret = spapr_fixup_cpu_smt_dt(fdt, offset, cpu,
smp_threads);
if (ret < 0) {
return ret;
--
1.9.rc0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v2 7/9] spapr: Limit threads per core according to current compatibility mode
2014-05-21 8:27 [Qemu-devel] [PATCH v2 0/9] spapr: Enable ibm, client-architecture-support Alexey Kardashevskiy
` (5 preceding siblings ...)
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 6/9] spapr: Rework spapr_fixup_cpu_dt() Alexey Kardashevskiy
@ 2014-05-21 8:27 ` Alexey Kardashevskiy
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 8/9] spapr: Implement processor compatibility in ibm, client-architecture-support Alexey Kardashevskiy
` (2 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-21 8:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
This puts a limit to the number of threads per core based on the current
compatibility mode. Although PowerISA specs do not specify the maximum
threads per core number, the linux guest still expects that
PowerISA2.05-compatible CPU supports only 2 threads per core as this
is what POWER6 (2.05 compliant CPU) implements, the same is for
POWER7 (2.06, 4 threads) and POWER8 (2.07, 8 threads).
This calls spapr_fixup_cpu_smt_dt() with the maximum allowed number of
threads which affects ibm,ppc-interrupt-server#s and
ibm,ppc-interrupt-gserver#s properties.
The number of CPU nodesremains unchanged.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr.c | 2 +-
target-ppc/cpu.h | 1 +
target-ppc/translate_init.c | 27 +++++++++++++++++++++++++++
3 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 7082237..14c72d9 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -293,7 +293,7 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
}
ret = spapr_fixup_cpu_smt_dt(fdt, offset, cpu,
- smp_threads);
+ ppc_get_compat_smt_threads(cpu));
if (ret < 0) {
return ret;
}
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index d3b8236..7b465b8 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1122,6 +1122,7 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
void ppc_store_msr (CPUPPCState *env, target_ulong value);
void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf);
+int ppc_get_compat_smt_threads(PowerPCCPU *cpu);
int ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version);
/* Time-base and decrementer management */
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index faac74a..56d3b97 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8921,6 +8921,33 @@ static void ppc_cpu_unrealizefn(DeviceState *dev, Error **errp)
}
}
+int ppc_get_compat_smt_threads(PowerPCCPU *cpu)
+{
+ int ret = smp_threads;
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+
+ switch (cpu->cpu_version) {
+ case CPU_POWERPC_LOGICAL_2_05:
+ ret = 2;
+ break;
+ case CPU_POWERPC_LOGICAL_2_06:
+ ret = 4;
+ break;
+ case CPU_POWERPC_LOGICAL_2_07:
+ ret = 8;
+ break;
+ default:
+ if (pcc->pcr_mask & PCR_COMPAT_2_06) {
+ ret = 4;
+ } else if (pcc->pcr_mask & PCR_COMPAT_2_05) {
+ ret = 2;
+ }
+ break;
+ }
+
+ return MIN(ret, smp_threads);
+}
+
int ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version)
{
int ret = 0;
--
1.9.rc0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v2 8/9] spapr: Implement processor compatibility in ibm, client-architecture-support
2014-05-21 8:27 [Qemu-devel] [PATCH v2 0/9] spapr: Enable ibm, client-architecture-support Alexey Kardashevskiy
` (6 preceding siblings ...)
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 7/9] spapr: Limit threads per core according to current compatibility mode Alexey Kardashevskiy
@ 2014-05-21 8:27 ` Alexey Kardashevskiy
2014-05-21 9:21 ` Alexander Graf
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 9/9] KVM: PPC: Enable compatibility mode Alexey Kardashevskiy
2014-05-21 8:44 ` [Qemu-devel] [PATCH v2 0/9] spapr: Enable ibm, client-architecture-support Alexander Graf
9 siblings, 1 reply; 14+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-21 8:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
Modern Linux kernels support last POWERPC CPUs so when a kernel boots,
in most cases it can find a matching cpu_spec in the kernel's cpu_specs
list. However if the kernel is quite old, it may be missing a definition
of the actual CPU. To provide an ability for old kernels to work on modern
hardware, a Processor Compatibility Mode has been introduced
by the PowerISA specification.
>From the hardware prospective, it is supported by the Processor
Compatibility Register (PCR) which is defined in PowerISA. The register
enables one of the compatibility modes (2.05/2.06/2.07).
Since PCR is a hypervisor privileged register and cannot be
directly accessed from the guest, the mode selection is done via
ibm,client-architecture-support (CAS) RTAS call using which the guest
specifies what "raw" and "architected" CPU versions it supports.
QEMU works out the best match, changes a "cpu-version" property of
every CPU and notifies the guest about the change by setting these
properties in the buffer passed as a response on a custom H_CAS hypercall.
This implements ibm,client-architecture-support parameters parsing
(now only for PVRs) and cooks the device tree diff with new values for
"cpu-version", "ibm,ppc-interrupt-server#s" and
"ibm,ppc-interrupt-server#s" properties.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr.c | 4 ++-
hw/ppc/spapr_hcall.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++
trace-events | 4 +++
3 files changed, 92 insertions(+), 1 deletion(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 14c72d9..020426a 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -34,6 +34,7 @@
#include "sysemu/kvm.h"
#include "kvm_ppc.h"
#include "mmu-hash64.h"
+#include "qom/cpu.h"
#include "hw/boards.h"
#include "hw/ppc/ppc.h"
@@ -601,7 +602,8 @@ int spapr_h_cas_compose_response(target_ulong addr, target_ulong size)
_FDT((fdt_open_into(fdt_skel, fdt, size)));
g_free(fdt_skel);
- /* Place to make changes to the tree */
+ /* Fix skeleton up */
+ _FDT((spapr_fixup_cpu_dt(fdt, spapr)));
/* Pack resulting tree */
_FDT((fdt_pack(fdt)));
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 2f6aa5c..2e0a49c 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -3,6 +3,9 @@
#include "helper_regs.h"
#include "hw/ppc/spapr.h"
#include "mmu-hash64.h"
+#include "cpu-models.h"
+#include "trace.h"
+#include "kvm_ppc.h"
struct SPRSyncState {
CPUState *cs;
@@ -752,12 +755,94 @@ out:
return ret;
}
+#define get_compat_level(cpuver) ( \
+ ((cpuver) == CPU_POWERPC_LOGICAL_2_05) ? 2050 : \
+ ((cpuver) == CPU_POWERPC_LOGICAL_2_06) ? 2060 : \
+ ((cpuver) == CPU_POWERPC_LOGICAL_2_06_PLUS) ? 2061 : \
+ ((cpuver) == CPU_POWERPC_LOGICAL_2_07) ? 2070 : 0)
+
static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
sPAPREnvironment *spapr,
target_ulong opcode,
target_ulong *args)
{
target_ulong list = args[0];
+ PowerPCCPUClass *pcc_ = POWERPC_CPU_GET_CLASS(cpu_);
+ CPUState *cs;
+ bool cpu_match = false;
+ unsigned old_cpu_version = cpu_->cpu_version;
+ unsigned compat_lvl = 0, cpu_version = 0;
+ unsigned max_lvl = get_compat_level(cpu_->max_compat);
+
+ /* Parse PVR list */
+ for ( ; ; ) {
+ uint32_t pvr, pvr_mask;
+
+ pvr_mask = rtas_ld(list, 0);
+ list += 4;
+ pvr = rtas_ld(list, 0);
+ list += 4;
+
+ trace_spapr_cas_pvr_try(pvr);
+ if (!max_lvl &&
+ ((cpu_->env.spr[SPR_PVR] & pvr_mask) == (pvr & pvr_mask))) {
+ cpu_match = true;
+ cpu_version = 0;
+ } else if (pvr == cpu_->cpu_version) {
+ cpu_match = true;
+ cpu_version = cpu_->cpu_version;
+ } else if (!cpu_match) {
+ /* If it is a logical PVR, try to determine the highest level */
+ unsigned lvl = get_compat_level(pvr);
+ if (lvl) {
+ bool is205 = (pcc_->pcr_mask & PCR_COMPAT_2_05) &&
+ (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05));
+ bool is206 = (pcc_->pcr_mask & PCR_COMPAT_2_06) &&
+ ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) ||
+ (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS)));
+
+ if (is205 || is206) {
+ if (!max_lvl) {
+ /* User did not set the level, choose the highest */
+ if (compat_lvl <= lvl) {
+ compat_lvl = lvl;
+ cpu_version = pvr;
+ }
+ } else if (max_lvl >= lvl) {
+ /* User chose the level, don't set higher than this */
+ compat_lvl = lvl;
+ cpu_version = pvr;
+ }
+ }
+ }
+ }
+ /* Terminator record */
+ if (~pvr_mask & pvr) {
+ break;
+ }
+ }
+
+ /* For the future use: here @list points to the first capability */
+
+ /* Parsing finished */
+ trace_spapr_cas_pvr(cpu_->cpu_version, cpu_match,
+ cpu_version, pcc_->pcr_mask);
+
+ /* Update CPUs */
+ if (old_cpu_version != cpu_version) {
+ CPU_FOREACH(cs) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+
+ if (ppc_set_compat(cpu, cpu_version) < 0) {
+ fprintf(stderr, "Unable to set compatibility mode\n");
+ return H_HARDWARE;
+ }
+ }
+ }
+
+ if (!cpu_version) {
+ return H_SUCCESS;
+ }
if (!list) {
return H_SUCCESS;
diff --git a/trace-events b/trace-events
index 98d8e6a..09f4b57 100644
--- a/trace-events
+++ b/trace-events
@@ -1187,6 +1187,10 @@ xics_ics_eoi(int nr) "ics_eoi: irq %#x"
spapr_cas_failed(unsigned long n) "DT diff buffer is too small: %ld bytes"
spapr_cas_continue(unsigned long n) "Copy changes to the guest: %ld bytes"
+# hw/ppc/spapr_hcall.c
+spapr_cas_pvr_try(uint32_t pvr) "%x"
+spapr_cas_pvr(uint32_t cur_pvr, bool cpu_match, uint32_t new_pvr, uint64_t pcr) "current=%x, cpu_match=%u, new=%x, compat flags=%"PRIx64
+
# hw/ppc/spapr_iommu.c
spapr_iommu_put(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tce=0x%"PRIx64" ret=%"PRId64
spapr_iommu_get(uint64_t liobn, uint64_t ioba, uint64_t ret, uint64_t tce) "liobn=%"PRIx64" ioba=0x%"PRIx64" ret=%"PRId64" tce=0x%"PRIx64
--
1.9.rc0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2 8/9] spapr: Implement processor compatibility in ibm, client-architecture-support
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 8/9] spapr: Implement processor compatibility in ibm, client-architecture-support Alexey Kardashevskiy
@ 2014-05-21 9:21 ` Alexander Graf
2014-05-21 9:36 ` Alexey Kardashevskiy
0 siblings, 1 reply; 14+ messages in thread
From: Alexander Graf @ 2014-05-21 9:21 UTC (permalink / raw)
To: Alexey Kardashevskiy, qemu-devel; +Cc: qemu-ppc
On 21.05.14 10:27, Alexey Kardashevskiy wrote:
> Modern Linux kernels support last POWERPC CPUs so when a kernel boots,
> in most cases it can find a matching cpu_spec in the kernel's cpu_specs
> list. However if the kernel is quite old, it may be missing a definition
> of the actual CPU. To provide an ability for old kernels to work on modern
> hardware, a Processor Compatibility Mode has been introduced
> by the PowerISA specification.
>
> From the hardware prospective, it is supported by the Processor
> Compatibility Register (PCR) which is defined in PowerISA. The register
> enables one of the compatibility modes (2.05/2.06/2.07).
> Since PCR is a hypervisor privileged register and cannot be
> directly accessed from the guest, the mode selection is done via
> ibm,client-architecture-support (CAS) RTAS call using which the guest
> specifies what "raw" and "architected" CPU versions it supports.
> QEMU works out the best match, changes a "cpu-version" property of
> every CPU and notifies the guest about the change by setting these
> properties in the buffer passed as a response on a custom H_CAS hypercall.
>
> This implements ibm,client-architecture-support parameters parsing
> (now only for PVRs) and cooks the device tree diff with new values for
> "cpu-version", "ibm,ppc-interrupt-server#s" and
> "ibm,ppc-interrupt-server#s" properties.
>
> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> ---
> hw/ppc/spapr.c | 4 ++-
> hw/ppc/spapr_hcall.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> trace-events | 4 +++
> 3 files changed, 92 insertions(+), 1 deletion(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 14c72d9..020426a 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -34,6 +34,7 @@
> #include "sysemu/kvm.h"
> #include "kvm_ppc.h"
> #include "mmu-hash64.h"
> +#include "qom/cpu.h"
>
> #include "hw/boards.h"
> #include "hw/ppc/ppc.h"
> @@ -601,7 +602,8 @@ int spapr_h_cas_compose_response(target_ulong addr, target_ulong size)
> _FDT((fdt_open_into(fdt_skel, fdt, size)));
> g_free(fdt_skel);
>
> - /* Place to make changes to the tree */
> + /* Fix skeleton up */
> + _FDT((spapr_fixup_cpu_dt(fdt, spapr)));
>
> /* Pack resulting tree */
> _FDT((fdt_pack(fdt)));
> diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> index 2f6aa5c..2e0a49c 100644
> --- a/hw/ppc/spapr_hcall.c
> +++ b/hw/ppc/spapr_hcall.c
> @@ -3,6 +3,9 @@
> #include "helper_regs.h"
> #include "hw/ppc/spapr.h"
> #include "mmu-hash64.h"
> +#include "cpu-models.h"
> +#include "trace.h"
> +#include "kvm_ppc.h"
>
> struct SPRSyncState {
> CPUState *cs;
> @@ -752,12 +755,94 @@ out:
> return ret;
> }
>
> +#define get_compat_level(cpuver) ( \
> + ((cpuver) == CPU_POWERPC_LOGICAL_2_05) ? 2050 : \
> + ((cpuver) == CPU_POWERPC_LOGICAL_2_06) ? 2060 : \
> + ((cpuver) == CPU_POWERPC_LOGICAL_2_06_PLUS) ? 2061 : \
> + ((cpuver) == CPU_POWERPC_LOGICAL_2_07) ? 2070 : 0)
> +
> static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
> sPAPREnvironment *spapr,
> target_ulong opcode,
> target_ulong *args)
> {
> target_ulong list = args[0];
> + PowerPCCPUClass *pcc_ = POWERPC_CPU_GET_CLASS(cpu_);
> + CPUState *cs;
> + bool cpu_match = false;
> + unsigned old_cpu_version = cpu_->cpu_version;
> + unsigned compat_lvl = 0, cpu_version = 0;
> + unsigned max_lvl = get_compat_level(cpu_->max_compat);
> +
> + /* Parse PVR list */
> + for ( ; ; ) {
> + uint32_t pvr, pvr_mask;
> +
> + pvr_mask = rtas_ld(list, 0);
> + list += 4;
> + pvr = rtas_ld(list, 0);
> + list += 4;
> +
> + trace_spapr_cas_pvr_try(pvr);
> + if (!max_lvl &&
> + ((cpu_->env.spr[SPR_PVR] & pvr_mask) == (pvr & pvr_mask))) {
> + cpu_match = true;
> + cpu_version = 0;
> + } else if (pvr == cpu_->cpu_version) {
> + cpu_match = true;
> + cpu_version = cpu_->cpu_version;
> + } else if (!cpu_match) {
> + /* If it is a logical PVR, try to determine the highest level */
> + unsigned lvl = get_compat_level(pvr);
> + if (lvl) {
> + bool is205 = (pcc_->pcr_mask & PCR_COMPAT_2_05) &&
> + (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05));
> + bool is206 = (pcc_->pcr_mask & PCR_COMPAT_2_06) &&
> + ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) ||
> + (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS)));
> +
> + if (is205 || is206) {
> + if (!max_lvl) {
> + /* User did not set the level, choose the highest */
> + if (compat_lvl <= lvl) {
> + compat_lvl = lvl;
> + cpu_version = pvr;
> + }
> + } else if (max_lvl >= lvl) {
> + /* User chose the level, don't set higher than this */
> + compat_lvl = lvl;
> + cpu_version = pvr;
> + }
> + }
> + }
> + }
> + /* Terminator record */
> + if (~pvr_mask & pvr) {
This loop can be used by the guest to stall QEMU for a long period of
time, no? Better add a safety net check somewhere to allow for early abort.
> + break;
> + }
> + }
> +
> + /* For the future use: here @list points to the first capability */
> +
> + /* Parsing finished */
> + trace_spapr_cas_pvr(cpu_->cpu_version, cpu_match,
> + cpu_version, pcc_->pcr_mask);
> +
> + /* Update CPUs */
> + if (old_cpu_version != cpu_version) {
> + CPU_FOREACH(cs) {
> + PowerPCCPU *cpu = POWERPC_CPU(cs);
> +
> + if (ppc_set_compat(cpu, cpu_version) < 0) {
Please run the updates on the vcpu threads themselves.
Alex
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2 8/9] spapr: Implement processor compatibility in ibm, client-architecture-support
2014-05-21 9:21 ` Alexander Graf
@ 2014-05-21 9:36 ` Alexey Kardashevskiy
2014-05-21 9:57 ` Alexander Graf
0 siblings, 1 reply; 14+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-21 9:36 UTC (permalink / raw)
To: Alexander Graf, qemu-devel; +Cc: qemu-ppc
On 05/21/2014 07:21 PM, Alexander Graf wrote:
>
> On 21.05.14 10:27, Alexey Kardashevskiy wrote:
>> Modern Linux kernels support last POWERPC CPUs so when a kernel boots,
>> in most cases it can find a matching cpu_spec in the kernel's cpu_specs
>> list. However if the kernel is quite old, it may be missing a definition
>> of the actual CPU. To provide an ability for old kernels to work on modern
>> hardware, a Processor Compatibility Mode has been introduced
>> by the PowerISA specification.
>>
>> From the hardware prospective, it is supported by the Processor
>> Compatibility Register (PCR) which is defined in PowerISA. The register
>> enables one of the compatibility modes (2.05/2.06/2.07).
>> Since PCR is a hypervisor privileged register and cannot be
>> directly accessed from the guest, the mode selection is done via
>> ibm,client-architecture-support (CAS) RTAS call using which the guest
>> specifies what "raw" and "architected" CPU versions it supports.
>> QEMU works out the best match, changes a "cpu-version" property of
>> every CPU and notifies the guest about the change by setting these
>> properties in the buffer passed as a response on a custom H_CAS hypercall.
>>
>> This implements ibm,client-architecture-support parameters parsing
>> (now only for PVRs) and cooks the device tree diff with new values for
>> "cpu-version", "ibm,ppc-interrupt-server#s" and
>> "ibm,ppc-interrupt-server#s" properties.
>>
>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>> ---
>> hw/ppc/spapr.c | 4 ++-
>> hw/ppc/spapr_hcall.c | 85
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>> trace-events | 4 +++
>> 3 files changed, 92 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
>> index 14c72d9..020426a 100644
>> --- a/hw/ppc/spapr.c
>> +++ b/hw/ppc/spapr.c
>> @@ -34,6 +34,7 @@
>> #include "sysemu/kvm.h"
>> #include "kvm_ppc.h"
>> #include "mmu-hash64.h"
>> +#include "qom/cpu.h"
>> #include "hw/boards.h"
>> #include "hw/ppc/ppc.h"
>> @@ -601,7 +602,8 @@ int spapr_h_cas_compose_response(target_ulong addr,
>> target_ulong size)
>> _FDT((fdt_open_into(fdt_skel, fdt, size)));
>> g_free(fdt_skel);
>> - /* Place to make changes to the tree */
>> + /* Fix skeleton up */
>> + _FDT((spapr_fixup_cpu_dt(fdt, spapr)));
>> /* Pack resulting tree */
>> _FDT((fdt_pack(fdt)));
>> diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
>> index 2f6aa5c..2e0a49c 100644
>> --- a/hw/ppc/spapr_hcall.c
>> +++ b/hw/ppc/spapr_hcall.c
>> @@ -3,6 +3,9 @@
>> #include "helper_regs.h"
>> #include "hw/ppc/spapr.h"
>> #include "mmu-hash64.h"
>> +#include "cpu-models.h"
>> +#include "trace.h"
>> +#include "kvm_ppc.h"
>> struct SPRSyncState {
>> CPUState *cs;
>> @@ -752,12 +755,94 @@ out:
>> return ret;
>> }
>> +#define get_compat_level(cpuver) ( \
>> + ((cpuver) == CPU_POWERPC_LOGICAL_2_05) ? 2050 : \
>> + ((cpuver) == CPU_POWERPC_LOGICAL_2_06) ? 2060 : \
>> + ((cpuver) == CPU_POWERPC_LOGICAL_2_06_PLUS) ? 2061 : \
>> + ((cpuver) == CPU_POWERPC_LOGICAL_2_07) ? 2070 : 0)
>> +
>> static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
>> sPAPREnvironment *spapr,
>> target_ulong opcode,
>> target_ulong *args)
>> {
>> target_ulong list = args[0];
>> + PowerPCCPUClass *pcc_ = POWERPC_CPU_GET_CLASS(cpu_);
>> + CPUState *cs;
>> + bool cpu_match = false;
>> + unsigned old_cpu_version = cpu_->cpu_version;
>> + unsigned compat_lvl = 0, cpu_version = 0;
>> + unsigned max_lvl = get_compat_level(cpu_->max_compat);
>> +
>> + /* Parse PVR list */
>> + for ( ; ; ) {
>> + uint32_t pvr, pvr_mask;
>> +
>> + pvr_mask = rtas_ld(list, 0);
>> + list += 4;
>> + pvr = rtas_ld(list, 0);
>> + list += 4;
>> +
>> + trace_spapr_cas_pvr_try(pvr);
>> + if (!max_lvl &&
>> + ((cpu_->env.spr[SPR_PVR] & pvr_mask) == (pvr & pvr_mask))) {
>> + cpu_match = true;
>> + cpu_version = 0;
>> + } else if (pvr == cpu_->cpu_version) {
>> + cpu_match = true;
>> + cpu_version = cpu_->cpu_version;
>> + } else if (!cpu_match) {
>> + /* If it is a logical PVR, try to determine the highest
>> level */
>> + unsigned lvl = get_compat_level(pvr);
>> + if (lvl) {
>> + bool is205 = (pcc_->pcr_mask & PCR_COMPAT_2_05) &&
>> + (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05));
>> + bool is206 = (pcc_->pcr_mask & PCR_COMPAT_2_06) &&
>> + ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) ||
>> + (lvl ==
>> get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS)));
>> +
>> + if (is205 || is206) {
>> + if (!max_lvl) {
>> + /* User did not set the level, choose the
>> highest */
>> + if (compat_lvl <= lvl) {
>> + compat_lvl = lvl;
>> + cpu_version = pvr;
>> + }
>> + } else if (max_lvl >= lvl) {
>> + /* User chose the level, don't set higher than
>> this */
>> + compat_lvl = lvl;
>> + cpu_version = pvr;
>> + }
>> + }
>> + }
>> + }
>> + /* Terminator record */
>> + if (~pvr_mask & pvr) {
>
> This loop can be used by the guest to stall QEMU for a long period of time,
> no? Better add a safety net check somewhere to allow for early abort.
Like what? No more than 64 PVRs would be enough?
>> + break;
>> + }
>> + }
>> +
>> + /* For the future use: here @list points to the first capability */
>> +
>> + /* Parsing finished */
>> + trace_spapr_cas_pvr(cpu_->cpu_version, cpu_match,
>> + cpu_version, pcc_->pcr_mask);
>> +
>> + /* Update CPUs */
>> + if (old_cpu_version != cpu_version) {
>> + CPU_FOREACH(cs) {
>> + PowerPCCPU *cpu = POWERPC_CPU(cs);
>> +
>> + if (ppc_set_compat(cpu, cpu_version) < 0) {
>
> Please run the updates on the vcpu threads themselves.
Ouch. Forgot. Sorry :(
--
Alexey
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2 8/9] spapr: Implement processor compatibility in ibm, client-architecture-support
2014-05-21 9:36 ` Alexey Kardashevskiy
@ 2014-05-21 9:57 ` Alexander Graf
0 siblings, 0 replies; 14+ messages in thread
From: Alexander Graf @ 2014-05-21 9:57 UTC (permalink / raw)
To: Alexey Kardashevskiy, qemu-devel; +Cc: qemu-ppc
On 21.05.14 11:36, Alexey Kardashevskiy wrote:
> On 05/21/2014 07:21 PM, Alexander Graf wrote:
>> On 21.05.14 10:27, Alexey Kardashevskiy wrote:
>>> Modern Linux kernels support last POWERPC CPUs so when a kernel boots,
>>> in most cases it can find a matching cpu_spec in the kernel's cpu_specs
>>> list. However if the kernel is quite old, it may be missing a definition
>>> of the actual CPU. To provide an ability for old kernels to work on modern
>>> hardware, a Processor Compatibility Mode has been introduced
>>> by the PowerISA specification.
>>>
>>> From the hardware prospective, it is supported by the Processor
>>> Compatibility Register (PCR) which is defined in PowerISA. The register
>>> enables one of the compatibility modes (2.05/2.06/2.07).
>>> Since PCR is a hypervisor privileged register and cannot be
>>> directly accessed from the guest, the mode selection is done via
>>> ibm,client-architecture-support (CAS) RTAS call using which the guest
>>> specifies what "raw" and "architected" CPU versions it supports.
>>> QEMU works out the best match, changes a "cpu-version" property of
>>> every CPU and notifies the guest about the change by setting these
>>> properties in the buffer passed as a response on a custom H_CAS hypercall.
>>>
>>> This implements ibm,client-architecture-support parameters parsing
>>> (now only for PVRs) and cooks the device tree diff with new values for
>>> "cpu-version", "ibm,ppc-interrupt-server#s" and
>>> "ibm,ppc-interrupt-server#s" properties.
>>>
>>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>>> ---
>>> hw/ppc/spapr.c | 4 ++-
>>> hw/ppc/spapr_hcall.c | 85
>>> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>> trace-events | 4 +++
>>> 3 files changed, 92 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
>>> index 14c72d9..020426a 100644
>>> --- a/hw/ppc/spapr.c
>>> +++ b/hw/ppc/spapr.c
>>> @@ -34,6 +34,7 @@
>>> #include "sysemu/kvm.h"
>>> #include "kvm_ppc.h"
>>> #include "mmu-hash64.h"
>>> +#include "qom/cpu.h"
>>> #include "hw/boards.h"
>>> #include "hw/ppc/ppc.h"
>>> @@ -601,7 +602,8 @@ int spapr_h_cas_compose_response(target_ulong addr,
>>> target_ulong size)
>>> _FDT((fdt_open_into(fdt_skel, fdt, size)));
>>> g_free(fdt_skel);
>>> - /* Place to make changes to the tree */
>>> + /* Fix skeleton up */
>>> + _FDT((spapr_fixup_cpu_dt(fdt, spapr)));
>>> /* Pack resulting tree */
>>> _FDT((fdt_pack(fdt)));
>>> diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
>>> index 2f6aa5c..2e0a49c 100644
>>> --- a/hw/ppc/spapr_hcall.c
>>> +++ b/hw/ppc/spapr_hcall.c
>>> @@ -3,6 +3,9 @@
>>> #include "helper_regs.h"
>>> #include "hw/ppc/spapr.h"
>>> #include "mmu-hash64.h"
>>> +#include "cpu-models.h"
>>> +#include "trace.h"
>>> +#include "kvm_ppc.h"
>>> struct SPRSyncState {
>>> CPUState *cs;
>>> @@ -752,12 +755,94 @@ out:
>>> return ret;
>>> }
>>> +#define get_compat_level(cpuver) ( \
>>> + ((cpuver) == CPU_POWERPC_LOGICAL_2_05) ? 2050 : \
>>> + ((cpuver) == CPU_POWERPC_LOGICAL_2_06) ? 2060 : \
>>> + ((cpuver) == CPU_POWERPC_LOGICAL_2_06_PLUS) ? 2061 : \
>>> + ((cpuver) == CPU_POWERPC_LOGICAL_2_07) ? 2070 : 0)
>>> +
>>> static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
>>> sPAPREnvironment *spapr,
>>> target_ulong opcode,
>>> target_ulong *args)
>>> {
>>> target_ulong list = args[0];
>>> + PowerPCCPUClass *pcc_ = POWERPC_CPU_GET_CLASS(cpu_);
>>> + CPUState *cs;
>>> + bool cpu_match = false;
>>> + unsigned old_cpu_version = cpu_->cpu_version;
>>> + unsigned compat_lvl = 0, cpu_version = 0;
>>> + unsigned max_lvl = get_compat_level(cpu_->max_compat);
>>> +
>>> + /* Parse PVR list */
>>> + for ( ; ; ) {
>>> + uint32_t pvr, pvr_mask;
>>> +
>>> + pvr_mask = rtas_ld(list, 0);
>>> + list += 4;
>>> + pvr = rtas_ld(list, 0);
>>> + list += 4;
>>> +
>>> + trace_spapr_cas_pvr_try(pvr);
>>> + if (!max_lvl &&
>>> + ((cpu_->env.spr[SPR_PVR] & pvr_mask) == (pvr & pvr_mask))) {
>>> + cpu_match = true;
>>> + cpu_version = 0;
>>> + } else if (pvr == cpu_->cpu_version) {
>>> + cpu_match = true;
>>> + cpu_version = cpu_->cpu_version;
>>> + } else if (!cpu_match) {
>>> + /* If it is a logical PVR, try to determine the highest
>>> level */
>>> + unsigned lvl = get_compat_level(pvr);
>>> + if (lvl) {
>>> + bool is205 = (pcc_->pcr_mask & PCR_COMPAT_2_05) &&
>>> + (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05));
>>> + bool is206 = (pcc_->pcr_mask & PCR_COMPAT_2_06) &&
>>> + ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) ||
>>> + (lvl ==
>>> get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS)));
>>> +
>>> + if (is205 || is206) {
>>> + if (!max_lvl) {
>>> + /* User did not set the level, choose the
>>> highest */
>>> + if (compat_lvl <= lvl) {
>>> + compat_lvl = lvl;
>>> + cpu_version = pvr;
>>> + }
>>> + } else if (max_lvl >= lvl) {
>>> + /* User chose the level, don't set higher than
>>> this */
>>> + compat_lvl = lvl;
>>> + cpu_version = pvr;
>>> + }
>>> + }
>>> + }
>>> + }
>>> + /* Terminator record */
>>> + if (~pvr_mask & pvr) {
>> This loop can be used by the guest to stall QEMU for a long period of time,
>> no? Better add a safety net check somewhere to allow for early abort.
> Like what? No more than 64 PVRs would be enough?
Yeah, choose a random (high) number. If you like make it 512 to be safe
for a few generations :).
Alex
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v2 9/9] KVM: PPC: Enable compatibility mode
2014-05-21 8:27 [Qemu-devel] [PATCH v2 0/9] spapr: Enable ibm, client-architecture-support Alexey Kardashevskiy
` (7 preceding siblings ...)
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 8/9] spapr: Implement processor compatibility in ibm, client-architecture-support Alexey Kardashevskiy
@ 2014-05-21 8:27 ` Alexey Kardashevskiy
2014-05-21 8:44 ` [Qemu-devel] [PATCH v2 0/9] spapr: Enable ibm, client-architecture-support Alexander Graf
9 siblings, 0 replies; 14+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-21 8:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
The host kernel implements a KVM_REG_PPC_ARCH_COMPAT register which
this uses to enable a compatibility mode if any chosen.
This sets the KVM_REG_PPC_ARCH_COMPAT register in KVM. ppc_set_compat()
signals the caller if the mode cannot be enabled by the host kernel.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
target-ppc/kvm.c | 5 +++++
target-ppc/kvm_ppc.h | 6 ++++++
target-ppc/translate_init.c | 5 +++++
3 files changed, 16 insertions(+)
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index ca31027..05952d0 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1514,6 +1514,11 @@ void kvmppc_set_papr(PowerPCCPU *cpu)
cap_papr = 1;
}
+int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version)
+{
+ return kvm_set_one_reg(CPU(cpu), KVM_REG_PPC_ARCH_COMPAT, &cpu_version);
+}
+
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
{
CPUState *cs = CPU(cpu);
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index ff077ec..716c33d 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -23,6 +23,7 @@ int kvmppc_get_hasidle(CPUPPCState *env);
int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len);
int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level);
void kvmppc_set_papr(PowerPCCPU *cpu);
+int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version);
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
int kvmppc_smt_threads(void);
int kvmppc_clear_tsr_bits(PowerPCCPU *cpu, uint32_t tsr_bits);
@@ -95,6 +96,11 @@ static inline void kvmppc_set_papr(PowerPCCPU *cpu)
{
}
+static inline int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version)
+{
+ return 0;
+}
+
static inline void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
{
}
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 56d3b97..ad5c27d 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8970,6 +8970,11 @@ int ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version)
break;
}
+ if (kvmppc_set_compat(cpu, cpu->max_compat) < 0) {
+ error_report("Unable to set compatibility mode in KVM");
+ ret = -1;
+ }
+
return ret;
}
--
1.9.rc0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2 0/9] spapr: Enable ibm, client-architecture-support
2014-05-21 8:27 [Qemu-devel] [PATCH v2 0/9] spapr: Enable ibm, client-architecture-support Alexey Kardashevskiy
` (8 preceding siblings ...)
2014-05-21 8:27 ` [Qemu-devel] [PATCH v2 9/9] KVM: PPC: Enable compatibility mode Alexey Kardashevskiy
@ 2014-05-21 8:44 ` Alexander Graf
9 siblings, 0 replies; 14+ messages in thread
From: Alexander Graf @ 2014-05-21 8:44 UTC (permalink / raw)
To: Alexey Kardashevskiy, qemu-devel; +Cc: qemu-ppc
On 21.05.14 10:27, Alexey Kardashevskiy wrote:
> This enables a ibm,client-architecture-support RTAS call.
>
> This allows older distros (such as SLES11 or RHEL6) to work on modern
> POWERPC hardware (such as POWER8) in "architected" mode.
>
> There is no change log as the changes are mostly about readbility, code
> design style and commit logs.
And these changes are not changes? Please *always* provide a full change
log of things that changed from version to version.
Alex
^ permalink raw reply [flat|nested] 14+ messages in thread