aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/alpha/cpu.h2
-rw-r--r--target/alpha/gdbstub.c2
-rw-r--r--target/arm/cpu.c7
-rw-r--r--target/arm/cpu.h31
-rw-r--r--target/arm/gdbstub.c173
-rw-r--r--target/arm/gdbstub64.c2
-rw-r--r--target/arm/helper.c186
-rw-r--r--target/arm/monitor.c8
-rw-r--r--target/cris/cpu.h4
-rw-r--r--target/cris/gdbstub.c4
-rw-r--r--target/hppa/cpu.h2
-rw-r--r--target/hppa/gdbstub.c2
-rw-r--r--target/i386/cpu.h2
-rw-r--r--target/i386/gdbstub.c29
-rw-r--r--target/lm32/cpu.h2
-rw-r--r--target/lm32/gdbstub.c2
-rw-r--r--target/m68k/cpu.h2
-rw-r--r--target/m68k/gdbstub.c2
-rw-r--r--target/m68k/helper.c33
-rw-r--r--target/microblaze/cpu.h2
-rw-r--r--target/microblaze/gdbstub.c2
-rw-r--r--target/mips/gdbstub.c2
-rw-r--r--target/mips/internal.h2
-rw-r--r--target/nios2/cpu.c2
-rw-r--r--target/openrisc/cpu.h2
-rw-r--r--target/openrisc/gdbstub.c2
-rw-r--r--target/ppc/cpu-qom.h1
-rw-r--r--target/ppc/cpu.h32
-rw-r--r--target/ppc/excp_helper.c79
-rw-r--r--target/ppc/gdbstub.c48
-rw-r--r--target/ppc/kvm.c5
-rw-r--r--target/ppc/kvm_ppc.h7
-rw-r--r--target/ppc/mmu-hash64.c319
-rw-r--r--target/ppc/translate.c20
-rw-r--r--target/ppc/translate_init.inc.c170
-rw-r--r--target/riscv/cpu.h2
-rw-r--r--target/riscv/gdbstub.c20
-rw-r--r--target/s390x/gdbstub.c30
-rw-r--r--target/s390x/internal.h2
-rw-r--r--target/sh4/cpu.h2
-rw-r--r--target/sh4/gdbstub.c2
-rw-r--r--target/sparc/cpu.h2
-rw-r--r--target/sparc/gdbstub.c2
-rw-r--r--target/xtensa/cpu.h2
-rw-r--r--target/xtensa/gdbstub.c2
45 files changed, 724 insertions, 532 deletions
diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
index 3f782c0efe..be29bdd530 100644
--- a/target/alpha/cpu.h
+++ b/target/alpha/cpu.h
@@ -280,7 +280,7 @@ void alpha_cpu_do_interrupt(CPUState *cpu);
bool alpha_cpu_exec_interrupt(CPUState *cpu, int int_req);
void alpha_cpu_dump_state(CPUState *cs, FILE *f, int flags);
hwaddr alpha_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-int alpha_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int alpha_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int alpha_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void alpha_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
MMUAccessType access_type,
diff --git a/target/alpha/gdbstub.c b/target/alpha/gdbstub.c
index 7f9cc092a9..0cd76ddaa9 100644
--- a/target/alpha/gdbstub.c
+++ b/target/alpha/gdbstub.c
@@ -21,7 +21,7 @@
#include "cpu.h"
#include "exec/gdbstub.h"
-int alpha_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int alpha_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
AlphaCPU *cpu = ALPHA_CPU(cs);
CPUAlphaState *env = &cpu->env;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 8e5ba619a0..a79f233b17 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -195,9 +195,10 @@ static void arm_cpu_reset(DeviceState *dev)
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 20, 2, 3);
/* and to the SVE instructions */
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 16, 2, 3);
- /* with maximum vector length */
- env->vfp.zcr_el[1] = cpu_isar_feature(aa64_sve, cpu) ?
- cpu->sve_max_vq - 1 : 0;
+ /* with reasonable vector length */
+ if (cpu_isar_feature(aa64_sve, cpu)) {
+ env->vfp.zcr_el[1] = MIN(cpu->sve_max_vq - 1, 3);
+ }
/*
* Enable TBI0 and TBI1. While the real kernel only enables TBI0,
* turning on both here will produce smaller code and otherwise
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 4ffd991b6f..8b9f2961ba 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -128,14 +128,20 @@ enum {
/**
* DynamicGDBXMLInfo:
* @desc: Contains the XML descriptions.
- * @num_cpregs: Number of the Coprocessor registers seen by GDB.
- * @cpregs_keys: Array that contains the corresponding Key of
- * a given cpreg with the same order of the cpreg in the XML description.
+ * @num: Number of the registers in this XML seen by GDB.
+ * @data: A union with data specific to the set of registers
+ * @cpregs_keys: Array that contains the corresponding Key of
+ * a given cpreg with the same order of the cpreg
+ * in the XML description.
*/
typedef struct DynamicGDBXMLInfo {
char *desc;
- int num_cpregs;
- uint32_t *cpregs_keys;
+ int num;
+ union {
+ struct {
+ uint32_t *keys;
+ } cpregs;
+ } data;
} DynamicGDBXMLInfo;
/* CPU state for each instance of a generic timer (in cp15 c14) */
@@ -749,7 +755,8 @@ struct ARMCPU {
uint64_t *cpreg_vmstate_values;
int32_t cpreg_vmstate_array_len;
- DynamicGDBXMLInfo dyn_xml;
+ DynamicGDBXMLInfo dyn_sysreg_xml;
+ DynamicGDBXMLInfo dyn_svereg_xml;
/* Timers used by the generic (architected) timer */
QEMUTimer *gt_timer[NUM_GTIMERS];
@@ -968,13 +975,15 @@ bool arm_cpu_exec_interrupt(CPUState *cpu, int int_req);
hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
MemTxAttrs *attrs);
-int arm_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int arm_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int arm_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
-/* Dynamically generates for gdb stub an XML description of the sysregs from
- * the cp_regs hashtable. Returns the registered sysregs number.
+/*
+ * Helpers to dynamically generates XML descriptions of the sysregs
+ * and SVE registers. Returns the number of registers in each set.
*/
-int arm_gen_dynamic_xml(CPUState *cpu);
+int arm_gen_dynamic_sysreg_xml(CPUState *cpu, int base_reg);
+int arm_gen_dynamic_svereg_xml(CPUState *cpu, int base_reg);
/* Returns the dynamically generated XML for the gdb stub.
* Returns a pointer to the XML contents for the specified XML file or NULL
@@ -988,7 +997,7 @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
int cpuid, void *opaque);
#ifdef TARGET_AARCH64
-int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int aarch64_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq);
void aarch64_sve_change_el(CPUARMState *env, int old_el,
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index 1239abd984..d9ef7d2187 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -24,6 +24,7 @@
typedef struct RegisterSysregXmlParam {
CPUState *cs;
GString *s;
+ int n;
} RegisterSysregXmlParam;
/* Old gdb always expect FPA registers. Newer (xml-aware) gdb only expect
@@ -32,7 +33,7 @@ typedef struct RegisterSysregXmlParam {
We hack round this by giving the FPA regs zero size when talking to a
newer gdb. */
-int arm_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
@@ -106,15 +107,16 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
return 0;
}
-static void arm_gen_one_xml_reg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
- ARMCPRegInfo *ri, uint32_t ri_key,
- int bitsize)
+static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
+ ARMCPRegInfo *ri, uint32_t ri_key,
+ int bitsize, int regnum)
{
g_string_append_printf(s, "<reg name=\"%s\"", ri->name);
g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
+ g_string_append_printf(s, " regnum=\"%d\"", regnum);
g_string_append_printf(s, " group=\"cp_regs\"/>");
- dyn_xml->num_cpregs++;
- dyn_xml->cpregs_keys[dyn_xml->num_cpregs - 1] = ri_key;
+ dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key;
+ dyn_xml->num++;
}
static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
@@ -126,12 +128,13 @@ static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
GString *s = param->s;
ARMCPU *cpu = ARM_CPU(param->cs);
CPUARMState *env = &cpu->env;
- DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_xml;
+ DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_sysreg_xml;
if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) {
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
if (ri->state == ARM_CP_STATE_AA64) {
- arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 64);
+ arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
+ param->n++);
}
} else {
if (ri->state == ARM_CP_STATE_AA32) {
@@ -140,38 +143,174 @@ static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
return;
}
if (ri->type & ARM_CP_64BIT) {
- arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 64);
+ arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
+ param->n++);
} else {
- arm_gen_one_xml_reg_tag(s , dyn_xml, ri, ri_key, 32);
+ arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 32,
+ param->n++);
}
}
}
}
}
-int arm_gen_dynamic_xml(CPUState *cs)
+int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg)
{
ARMCPU *cpu = ARM_CPU(cs);
GString *s = g_string_new(NULL);
- RegisterSysregXmlParam param = {cs, s};
+ RegisterSysregXmlParam param = {cs, s, base_reg};
- cpu->dyn_xml.num_cpregs = 0;
- cpu->dyn_xml.cpregs_keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs));
+ cpu->dyn_sysreg_xml.num = 0;
+ cpu->dyn_sysreg_xml.data.cpregs.keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs));
g_string_printf(s, "<?xml version=\"1.0\"?>");
g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">");
g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, &param);
g_string_append_printf(s, "</feature>");
- cpu->dyn_xml.desc = g_string_free(s, false);
- return cpu->dyn_xml.num_cpregs;
+ cpu->dyn_sysreg_xml.desc = g_string_free(s, false);
+ return cpu->dyn_sysreg_xml.num;
}
+struct TypeSize {
+ const char *gdb_type;
+ int size;
+ const char sz, suffix;
+};
+
+static const struct TypeSize vec_lanes[] = {
+ /* quads */
+ { "uint128", 128, 'q', 'u' },
+ { "int128", 128, 'q', 's' },
+ /* 64 bit */
+ { "uint64", 64, 'd', 'u' },
+ { "int64", 64, 'd', 's' },
+ { "ieee_double", 64, 'd', 'f' },
+ /* 32 bit */
+ { "uint32", 32, 's', 'u' },
+ { "int32", 32, 's', 's' },
+ { "ieee_single", 32, 's', 'f' },
+ /* 16 bit */
+ { "uint16", 16, 'h', 'u' },
+ { "int16", 16, 'h', 's' },
+ { "ieee_half", 16, 'h', 'f' },
+ /* bytes */
+ { "uint8", 8, 'b', 'u' },
+ { "int8", 8, 'b', 's' },
+};
+
+
+int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ GString *s = g_string_new(NULL);
+ DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
+ g_autoptr(GString) ts = g_string_new("");
+ int i, bits, reg_width = (cpu->sve_max_vq * 128);
+ info->num = 0;
+ g_string_printf(s, "<?xml version=\"1.0\"?>");
+ g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
+ g_string_append_printf(s, "<feature name=\"org.qemu.gdb.aarch64.sve\">");
+
+ /* First define types and totals in a whole VL */
+ for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
+ int count = reg_width / vec_lanes[i].size;
+ g_string_printf(ts, "vq%d%c%c", count,
+ vec_lanes[i].sz, vec_lanes[i].suffix);
+ g_string_append_printf(s,
+ "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
+ ts->str, vec_lanes[i].gdb_type, count);
+ }
+ /*
+ * Now define a union for each size group containing unsigned and
+ * signed and potentially float versions of each size from 128 to
+ * 8 bits.
+ */
+ for (bits = 128; bits >= 8; bits /= 2) {
+ int count = reg_width / bits;
+ g_string_append_printf(s, "<union id=\"vq%dn\">", count);
+ for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
+ if (vec_lanes[i].size == bits) {
+ g_string_append_printf(s, "<field name=\"%c\" type=\"vq%d%c%c\"/>",
+ vec_lanes[i].suffix,
+ count,
+ vec_lanes[i].sz, vec_lanes[i].suffix);
+ }
+ }
+ g_string_append(s, "</union>");
+ }
+ /* And now the final union of unions */
+ g_string_append(s, "<union id=\"vq\">");
+ for (bits = 128; bits >= 8; bits /= 2) {
+ int count = reg_width / bits;
+ for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
+ if (vec_lanes[i].size == bits) {
+ g_string_append_printf(s, "<field name=\"%c\" type=\"vq%dn\"/>",
+ vec_lanes[i].sz, count);
+ break;
+ }
+ }
+ }
+ g_string_append(s, "</union>");
+
+ /* Then define each register in parts for each vq */
+ for (i = 0; i < 32; i++) {
+ g_string_append_printf(s,
+ "<reg name=\"z%d\" bitsize=\"%d\""
+ " regnum=\"%d\" group=\"vector\""
+ " type=\"vq\"/>",
+ i, reg_width, base_reg++);
+ info->num++;
+ }
+ /* fpscr & status registers */
+ g_string_append_printf(s, "<reg name=\"fpsr\" bitsize=\"32\""
+ " regnum=\"%d\" group=\"float\""
+ " type=\"int\"/>", base_reg++);
+ g_string_append_printf(s, "<reg name=\"fpcr\" bitsize=\"32\""
+ " regnum=\"%d\" group=\"float\""
+ " type=\"int\"/>", base_reg++);
+ info->num += 2;
+ /*
+ * Predicate registers aren't so big they are worth splitting up
+ * but we do need to define a type to hold the array of quad
+ * references.
+ */
+ g_string_append_printf(s,
+ "<vector id=\"vqp\" type=\"uint16\" count=\"%d\"/>",
+ cpu->sve_max_vq);
+ for (i = 0; i < 16; i++) {
+ g_string_append_printf(s,
+ "<reg name=\"p%d\" bitsize=\"%d\""
+ " regnum=\"%d\" group=\"vector\""
+ " type=\"vqp\"/>",
+ i, cpu->sve_max_vq * 16, base_reg++);
+ info->num++;
+ }
+ g_string_append_printf(s,
+ "<reg name=\"ffr\" bitsize=\"%d\""
+ " regnum=\"%d\" group=\"vector\""
+ " type=\"vqp\"/>",
+ cpu->sve_max_vq * 16, base_reg++);
+ g_string_append_printf(s,
+ "<reg name=\"vg\" bitsize=\"64\""
+ " regnum=\"%d\" group=\"vector\""
+ " type=\"uint32\"/>",
+ base_reg++);
+ info->num += 2;
+ g_string_append_printf(s, "</feature>");
+ cpu->dyn_svereg_xml.desc = g_string_free(s, false);
+
+ return cpu->dyn_svereg_xml.num;
+}
+
+
const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
{
ARMCPU *cpu = ARM_CPU(cs);
if (strcmp(xmlname, "system-registers.xml") == 0) {
- return cpu->dyn_xml.desc;
+ return cpu->dyn_sysreg_xml.desc;
+ } else if (strcmp(xmlname, "sve-registers.xml") == 0) {
+ return cpu->dyn_svereg_xml.desc;
}
return NULL;
}
diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index 665ebb3ef6..35d0b80c2d 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -20,7 +20,7 @@
#include "cpu.h"
#include "exec/gdbstub.h"
-int aarch64_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index b61ee73d18..d2ec2c5351 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -48,30 +48,27 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
static void switch_mode(CPUARMState *env, int mode);
-static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
+static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
{
ARMCPU *cpu = env_archcpu(env);
int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
/* VFP data registers are always little-endian. */
if (reg < nregs) {
- stq_le_p(buf, *aa32_vfp_dreg(env, reg));
- return 8;
+ return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg));
}
if (arm_feature(env, ARM_FEATURE_NEON)) {
/* Aliases for Q regs. */
nregs += 16;
if (reg < nregs) {
uint64_t *q = aa32_vfp_qreg(env, reg - 32);
- stq_le_p(buf, q[0]);
- stq_le_p(buf + 8, q[1]);
- return 16;
+ return gdb_get_reg128(buf, q[0], q[1]);
}
}
switch (reg - nregs) {
- case 0: stl_p(buf, env->vfp.xregs[ARM_VFP_FPSID]); return 4;
- case 1: stl_p(buf, vfp_get_fpscr(env)); return 4;
- case 2: stl_p(buf, env->vfp.xregs[ARM_VFP_FPEXC]); return 4;
+ case 0: return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]); break;
+ case 1: return gdb_get_reg32(buf, vfp_get_fpscr(env)); break;
+ case 2: return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]); break;
}
return 0;
}
@@ -102,25 +99,21 @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
return 0;
}
-static int aarch64_fpu_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
+static int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
{
switch (reg) {
case 0 ... 31:
- /* 128 bit FP register */
- {
- uint64_t *q = aa64_vfp_qreg(env, reg);
- stq_le_p(buf, q[0]);
- stq_le_p(buf + 8, q[1]);
- return 16;
- }
+ {
+ /* 128 bit FP register - quads are in LE order */
+ uint64_t *q = aa64_vfp_qreg(env, reg);
+ return gdb_get_reg128(buf, q[1], q[0]);
+ }
case 32:
/* FPSR */
- stl_p(buf, vfp_get_fpsr(env));
- return 4;
+ return gdb_get_reg32(buf, vfp_get_fpsr(env));
case 33:
/* FPCR */
- stl_p(buf, vfp_get_fpcr(env));
- return 4;
+ return gdb_get_reg32(buf,vfp_get_fpcr(env));
default:
return 0;
}
@@ -209,13 +202,22 @@ static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
}
}
-static int arm_gdb_get_sysreg(CPUARMState *env, uint8_t *buf, int reg)
+/**
+ * arm_get/set_gdb_*: get/set a gdb register
+ * @env: the CPU state
+ * @buf: a buffer to copy to/from
+ * @reg: register number (offset from start of group)
+ *
+ * We return the number of bytes copied
+ */
+
+static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
{
ARMCPU *cpu = env_archcpu(env);
const ARMCPRegInfo *ri;
uint32_t key;
- key = cpu->dyn_xml.cpregs_keys[reg];
+ key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
ri = get_arm_cp_reginfo(cpu->cp_regs, key);
if (ri) {
if (cpreg_field_is_64bit(ri)) {
@@ -232,6 +234,102 @@ static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
return 0;
}
+#ifdef TARGET_AARCH64
+static int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg)
+{
+ ARMCPU *cpu = env_archcpu(env);
+
+ switch (reg) {
+ /* The first 32 registers are the zregs */
+ case 0 ... 31:
+ {
+ int vq, len = 0;
+ for (vq = 0; vq < cpu->sve_max_vq; vq++) {
+ len += gdb_get_reg128(buf,
+ env->vfp.zregs[reg].d[vq * 2 + 1],
+ env->vfp.zregs[reg].d[vq * 2]);
+ }
+ return len;
+ }
+ case 32:
+ return gdb_get_reg32(buf, vfp_get_fpsr(env));
+ case 33:
+ return gdb_get_reg32(buf, vfp_get_fpcr(env));
+ /* then 16 predicates and the ffr */
+ case 34 ... 50:
+ {
+ int preg = reg - 34;
+ int vq, len = 0;
+ for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
+ len += gdb_get_reg64(buf, env->vfp.pregs[preg].p[vq / 4]);
+ }
+ return len;
+ }
+ case 51:
+ {
+ /*
+ * We report in Vector Granules (VG) which is 64bit in a Z reg
+ * while the ZCR works in Vector Quads (VQ) which is 128bit chunks.
+ */
+ int vq = sve_zcr_len_for_el(env, arm_current_el(env)) + 1;
+ return gdb_get_reg32(buf, vq * 2);
+ }
+ default:
+ /* gdbstub asked for something out our range */
+ qemu_log_mask(LOG_UNIMP, "%s: out of range register %d", __func__, reg);
+ break;
+ }
+
+ return 0;
+}
+
+static int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg)
+{
+ ARMCPU *cpu = env_archcpu(env);
+
+ /* The first 32 registers are the zregs */
+ switch (reg) {
+ /* The first 32 registers are the zregs */
+ case 0 ... 31:
+ {
+ int vq, len = 0;
+ uint64_t *p = (uint64_t *) buf;
+ for (vq = 0; vq < cpu->sve_max_vq; vq++) {
+ env->vfp.zregs[reg].d[vq * 2 + 1] = *p++;
+ env->vfp.zregs[reg].d[vq * 2] = *p++;
+ len += 16;
+ }
+ return len;
+ }
+ case 32:
+ vfp_set_fpsr(env, *(uint32_t *)buf);
+ return 4;
+ case 33:
+ vfp_set_fpcr(env, *(uint32_t *)buf);
+ return 4;
+ case 34 ... 50:
+ {
+ int preg = reg - 34;
+ int vq, len = 0;
+ uint64_t *p = (uint64_t *) buf;
+ for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
+ env->vfp.pregs[preg].p[vq / 4] = *p++;
+ len += 8;
+ }
+ return len;
+ }
+ case 51:
+ /* cannot set vg via gdbstub */
+ return 0;
+ default:
+ /* gdbstub asked for something out our range */
+ break;
+ }
+
+ return 0;
+}
+#endif /* TARGET_AARCH64 */
+
static bool raw_accessors_invalid(const ARMCPRegInfo *ri)
{
/* Return true if the regdef would cause an assertion if you called
@@ -6599,6 +6697,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri)
return pfr1;
}
+#ifndef CONFIG_USER_ONLY
static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
ARMCPU *cpu = env_archcpu(env);
@@ -6609,6 +6708,7 @@ static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri)
}
return pfr0;
}
+#endif
/* Shared logic between LORID and the rest of the LOR* registers.
* Secure state has already been delt with.
@@ -7182,16 +7282,24 @@ void register_cp_regs_for_features(ARMCPU *cpu)
* define new registers here.
*/
ARMCPRegInfo v8_idregs[] = {
- /* ID_AA64PFR0_EL1 is not a plain ARM_CP_CONST because we don't
- * know the right value for the GIC field until after we
- * define these regs.
+ /*
+ * ID_AA64PFR0_EL1 is not a plain ARM_CP_CONST in system
+ * emulation because we don't know the right value for the
+ * GIC field until after we define these regs.
*/
{ .name = "ID_AA64PFR0_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 0,
- .access = PL1_R, .type = ARM_CP_NO_RAW,
+ .access = PL1_R,
+#ifdef CONFIG_USER_ONLY
+ .type = ARM_CP_CONST,
+ .resetvalue = cpu->isar.id_aa64pfr0
+#else
+ .type = ARM_CP_NO_RAW,
.accessfn = access_aa64_tid3,
.readfn = id_aa64pfr0_read,
- .writefn = arm_cp_write_ignore },
+ .writefn = arm_cp_write_ignore
+#endif
+ },
{ .name = "ID_AA64PFR1_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 1,
.access = PL1_R, .type = ARM_CP_CONST,
@@ -7966,9 +8074,22 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
CPUARMState *env = &cpu->env;
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
- gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
- aarch64_fpu_gdb_set_reg,
- 34, "aarch64-fpu.xml", 0);
+ /*
+ * The lower part of each SVE register aliases to the FPU
+ * registers so we don't need to include both.
+ */
+#ifdef TARGET_AARCH64
+ if (isar_feature_aa64_sve(&cpu->isar)) {
+ gdb_register_coprocessor(cs, arm_gdb_get_svereg, arm_gdb_set_svereg,
+ arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs),
+ "sve-registers.xml", 0);
+ } else
+#endif
+ {
+ gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
+ aarch64_fpu_gdb_set_reg,
+ 34, "aarch64-fpu.xml", 0);
+ }
} else if (arm_feature(env, ARM_FEATURE_NEON)) {
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
51, "arm-neon.xml", 0);
@@ -7980,8 +8101,9 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
19, "arm-vfp.xml", 0);
}
gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
- arm_gen_dynamic_xml(cs),
+ arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
"system-registers.xml", 0);
+
}
/* Sort alphabetically by type name, except for "any". */
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
index c2dc7908de..ea6598c412 100644
--- a/target/arm/monitor.c
+++ b/target/arm/monitor.c
@@ -206,9 +206,7 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
return NULL;
}
} else {
- Error *err = NULL;
- arm_cpu_finalize_features(ARM_CPU(obj), &err);
- assert(err == NULL);
+ arm_cpu_finalize_features(ARM_CPU(obj), &error_abort);
}
expansion_info = g_new0(CpuModelExpansionInfo, 1);
@@ -221,12 +219,10 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
while ((name = cpu_model_advertised_features[i++]) != NULL) {
ObjectProperty *prop = object_property_find(obj, name, NULL);
if (prop) {
- Error *err = NULL;
QObject *value;
assert(prop->get);
- value = object_property_get_qobject(obj, name, &err);
- assert(!err);
+ value = object_property_get_qobject(obj, name, &error_abort);
qdict_put_obj(qdict_out, name, value);
}
diff --git a/target/cris/cpu.h b/target/cris/cpu.h
index ca240bc788..8f08d7628b 100644
--- a/target/cris/cpu.h
+++ b/target/cris/cpu.h
@@ -195,8 +195,8 @@ void cris_cpu_dump_state(CPUState *cs, FILE *f, int flags);
hwaddr cris_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-int crisv10_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
-int cris_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int crisv10_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
+int cris_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int cris_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
/* you can call this signal handler from your SIGBUS and SIGSEGV
diff --git a/target/cris/gdbstub.c b/target/cris/gdbstub.c
index a3d76d2e8c..b01b2aa081 100644
--- a/target/cris/gdbstub.c
+++ b/target/cris/gdbstub.c
@@ -21,7 +21,7 @@
#include "cpu.h"
#include "exec/gdbstub.h"
-int crisv10_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int crisv10_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
CRISCPU *cpu = CRIS_CPU(cs);
CPUCRISState *env = &cpu->env;
@@ -53,7 +53,7 @@ int crisv10_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
return 0;
}
-int cris_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int cris_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
CRISCPU *cpu = CRIS_CPU(cs);
CPUCRISState *env = &cpu->env;
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 6713d04f11..801a4fb1ba 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -321,7 +321,7 @@ void cpu_hppa_change_prot_id(CPUHPPAState *env);
int cpu_hppa_signal_handler(int host_signum, void *pinfo, void *puc);
hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr);
-int hppa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int hppa_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int hppa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void hppa_cpu_do_interrupt(CPUState *cpu);
bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req);
diff --git a/target/hppa/gdbstub.c b/target/hppa/gdbstub.c
index 341888a9da..a6428a2893 100644
--- a/target/hppa/gdbstub.c
+++ b/target/hppa/gdbstub.c
@@ -21,7 +21,7 @@
#include "cpu.h"
#include "exec/gdbstub.h"
-int hppa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int hppa_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
HPPACPU *cpu = HPPA_CPU(cs);
CPUHPPAState *env = &cpu->env;
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 7e9e963d78..60d797d594 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1769,7 +1769,7 @@ void x86_cpu_dump_state(CPUState *cs, FILE *f, int flags);
hwaddr x86_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
MemTxAttrs *attrs);
-int x86_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int x86_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int x86_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void x86_cpu_exec_enter(CPUState *cpu);
diff --git a/target/i386/gdbstub.c b/target/i386/gdbstub.c
index 572ead641c..f3d23b614e 100644
--- a/target/i386/gdbstub.c
+++ b/target/i386/gdbstub.c
@@ -79,7 +79,7 @@ static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
#endif
-int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int x86_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env;
@@ -98,26 +98,22 @@ int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
return gdb_get_reg64(mem_buf,
env->regs[gpr_map[n]] & 0xffffffffUL);
} else {
- memset(mem_buf, 0, sizeof(target_ulong));
- return sizeof(target_ulong);
+ return gdb_get_regl(mem_buf, 0);
}
} else {
return gdb_get_reg32(mem_buf, env->regs[gpr_map32[n]]);
}
} else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
-#ifdef USE_X86LDOUBLE
- /* FIXME: byteswap float values - after fixing fpregs layout. */
- memcpy(mem_buf, &env->fpregs[n - IDX_FP_REGS], 10);
-#else
- memset(mem_buf, 0, 10);
-#endif
- return 10;
+ floatx80 *fp = (floatx80 *) &env->fpregs[n - IDX_FP_REGS];
+ int len = gdb_get_reg64(mem_buf, cpu_to_le64(fp->low));
+ len += gdb_get_reg16(mem_buf + len, cpu_to_le16(fp->high));
+ return len;
} else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
n -= IDX_XMM_REGS;
if (n < CPU_NB_REGS32 || TARGET_LONG_BITS == 64) {
- stq_p(mem_buf, env->xmm_regs[n].ZMM_Q(0));
- stq_p(mem_buf + 8, env->xmm_regs[n].ZMM_Q(1));
- return 16;
+ return gdb_get_reg128(mem_buf,
+ env->xmm_regs[n].ZMM_Q(0),
+ env->xmm_regs[n].ZMM_Q(1));
}
} else {
switch (n) {
@@ -290,10 +286,9 @@ int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
return 4;
}
} else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
-#ifdef USE_X86LDOUBLE
- /* FIXME: byteswap float values - after fixing fpregs layout. */
- memcpy(&env->fpregs[n - IDX_FP_REGS], mem_buf, 10);
-#endif
+ floatx80 *fp = (floatx80 *) &env->fpregs[n - IDX_FP_REGS];
+ fp->low = le64_to_cpu(* (uint64_t *) mem_buf);
+ fp->high = le16_to_cpu(* (uint16_t *) (mem_buf + 8));
return 10;
} else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
n -= IDX_XMM_REGS;
diff --git a/target/lm32/cpu.h b/target/lm32/cpu.h
index 064c6b1267..01d408eb55 100644
--- a/target/lm32/cpu.h
+++ b/target/lm32/cpu.h
@@ -202,7 +202,7 @@ void lm32_cpu_do_interrupt(CPUState *cpu);
bool lm32_cpu_exec_interrupt(CPUState *cs, int int_req);
void lm32_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr lm32_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-int lm32_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int lm32_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int lm32_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
typedef enum {
diff --git a/target/lm32/gdbstub.c b/target/lm32/gdbstub.c
index 82ede436e1..b6fe12e1d6 100644
--- a/target/lm32/gdbstub.c
+++ b/target/lm32/gdbstub.c
@@ -22,7 +22,7 @@
#include "exec/gdbstub.h"
#include "hw/lm32/lm32_pic.h"
-int lm32_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int lm32_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
LM32CPU *cpu = LM32_CPU(cs);
CPULM32State *env = &cpu->env;
diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index 3de8e06dfe..521ac67cdd 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -168,7 +168,7 @@ void m68k_cpu_do_interrupt(CPUState *cpu);
bool m68k_cpu_exec_interrupt(CPUState *cpu, int int_req);
void m68k_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr m68k_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-int m68k_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int m68k_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int m68k_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void m68k_tcg_init(void);
diff --git a/target/m68k/gdbstub.c b/target/m68k/gdbstub.c
index fdc96f57ff..eb2d030e14 100644
--- a/target/m68k/gdbstub.c
+++ b/target/m68k/gdbstub.c
@@ -21,7 +21,7 @@
#include "cpu.h"
#include "exec/gdbstub.h"
-int m68k_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int m68k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
M68kCPU *cpu = M68K_CPU(cs);
CPUM68KState *env = &cpu->env;
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
index baf7729af0..014657c637 100644
--- a/target/m68k/helper.c
+++ b/target/m68k/helper.c
@@ -68,23 +68,19 @@ void m68k_cpu_list(void)
g_slist_free(list);
}
-static int cf_fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
+static int cf_fpu_gdb_get_reg(CPUM68KState *env, GByteArray *mem_buf, int n)
{
if (n < 8) {
float_status s;
- stfq_p(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
- return 8;
+ return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
}
switch (n) {
case 8: /* fpcontrol */
- stl_be_p(mem_buf, env->fpcr);
- return 4;
+ return gdb_get_reg32(mem_buf, env->fpcr);
case 9: /* fpstatus */
- stl_be_p(mem_buf, env->fpsr);
- return 4;
+ return gdb_get_reg32(mem_buf, env->fpsr);
case 10: /* fpiar, not implemented */
- memset(mem_buf, 0, 4);
- return 4;
+ return gdb_get_reg32(mem_buf, 0);
}
return 0;
}
@@ -109,24 +105,21 @@ static int cf_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
return 0;
}
-static int m68k_fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
+static int m68k_fpu_gdb_get_reg(CPUM68KState *env, GByteArray *mem_buf, int n)
{
if (n < 8) {
- stw_be_p(mem_buf, env->fregs[n].l.upper);
- memset(mem_buf + 2, 0, 2);
- stq_be_p(mem_buf + 4, env->fregs[n].l.lower);
- return 12;
+ int len = gdb_get_reg16(mem_buf, env->fregs[n].l.upper);
+ len += gdb_get_reg16(mem_buf + len, 0);
+ len += gdb_get_reg64(mem_buf + len, env->fregs[n].l.lower);
+ return len;
}
switch (n) {
case 8: /* fpcontrol */
- stl_be_p(mem_buf, env->fpcr);
- return 4;
+ return gdb_get_reg32(mem_buf, env->fpcr);
case 9: /* fpstatus */
- stl_be_p(mem_buf, env->fpsr);
- return 4;
+ return gdb_get_reg32(mem_buf, env->fpsr);
case 10: /* fpiar, not implemented */
- memset(mem_buf, 0, 4);
- return 4;
+ return gdb_get_reg32(mem_buf, 0);
}
return 0;
}
diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h
index 32522f606b..1a700a880c 100644
--- a/target/microblaze/cpu.h
+++ b/target/microblaze/cpu.h
@@ -313,7 +313,7 @@ void mb_cpu_do_interrupt(CPUState *cs);
bool mb_cpu_exec_interrupt(CPUState *cs, int int_req);
void mb_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr mb_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-int mb_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int mb_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int mb_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void mb_tcg_init(void);
diff --git a/target/microblaze/gdbstub.c b/target/microblaze/gdbstub.c
index 30677b6d1f..f41ebf1f33 100644
--- a/target/microblaze/gdbstub.c
+++ b/target/microblaze/gdbstub.c
@@ -21,7 +21,7 @@
#include "cpu.h"
#include "exec/gdbstub.h"
-int mb_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int mb_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
CPUMBState *env = &cpu->env;
diff --git a/target/mips/gdbstub.c b/target/mips/gdbstub.c
index bbb2544939..98f56e660d 100644
--- a/target/mips/gdbstub.c
+++ b/target/mips/gdbstub.c
@@ -22,7 +22,7 @@
#include "internal.h"
#include "exec/gdbstub.h"
-int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int mips_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
MIPSCPU *cpu = MIPS_CPU(cs);
CPUMIPSState *env = &cpu->env;
diff --git a/target/mips/internal.h b/target/mips/internal.h
index df55f845ba..1bf274b3ef 100644
--- a/target/mips/internal.h
+++ b/target/mips/internal.h
@@ -82,7 +82,7 @@ void mips_cpu_do_interrupt(CPUState *cpu);
bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
void mips_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr mips_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-int mips_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int mips_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
MMUAccessType access_type,
diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c
index 0a4075949e..8f7011fcb9 100644
--- a/target/nios2/cpu.c
+++ b/target/nios2/cpu.c
@@ -124,7 +124,7 @@ static void nios2_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
#endif
}
-static int nios2_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+static int nios2_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
Nios2CPU *cpu = NIOS2_CPU(cs);
CPUClass *cc = CPU_GET_CLASS(cs);
diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index e7fb06445e..f37a52e153 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -320,7 +320,7 @@ void openrisc_cpu_do_interrupt(CPUState *cpu);
bool openrisc_cpu_exec_interrupt(CPUState *cpu, int int_req);
void openrisc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-int openrisc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int openrisc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int openrisc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void openrisc_translate_init(void);
bool openrisc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
diff --git a/target/openrisc/gdbstub.c b/target/openrisc/gdbstub.c
index 0fcdb79668..095bf76c12 100644
--- a/target/openrisc/gdbstub.c
+++ b/target/openrisc/gdbstub.c
@@ -21,7 +21,7 @@
#include "cpu.h"
#include "exec/gdbstub.h"
-int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int openrisc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
OpenRISCCPU *cpu = OPENRISC_CPU(cs);
CPUOpenRISCState *env = &cpu->env;
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index b528131761..000c7d405b 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -177,6 +177,7 @@ typedef struct PowerPCCPUClass {
uint64_t insns_flags;
uint64_t insns_flags2;
uint64_t msr_mask;
+ uint64_t lpcr_mask; /* Available bits in the LPCR */
uint64_t lpcr_pm; /* Power-saving mode Exit Cause Enable bits */
powerpc_mmu_t mmu_model;
powerpc_excp_t excp_model;
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index b283042515..88d9449555 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -24,8 +24,6 @@
#include "exec/cpu-defs.h"
#include "cpu-qom.h"
-/* #define PPC_EMULATE_32BITS_HYPV */
-
#define TCG_GUEST_DEFAULT_MO 0
#define TARGET_PAGE_BITS_64K 16
@@ -300,13 +298,12 @@ typedef struct ppc_v3_pate_t {
#define MSR_SF 63 /* Sixty-four-bit mode hflags */
#define MSR_TAG 62 /* Tag-active mode (POWERx ?) */
#define MSR_ISF 61 /* Sixty-four-bit interrupt mode on 630 */
-#define MSR_SHV 60 /* hypervisor state hflags */
+#define MSR_HV 60 /* hypervisor state hflags */
#define MSR_TS0 34 /* Transactional state, 2 bits (Book3s) */
#define MSR_TS1 33
#define MSR_TM 32 /* Transactional Memory Available (Book3s) */
#define MSR_CM 31 /* Computation mode for BookE hflags */
#define MSR_ICM 30 /* Interrupt computation mode for BookE */
-#define MSR_THV 29 /* hypervisor state for 32 bits PowerPC hflags */
#define MSR_GS 28 /* guest state for BookE */
#define MSR_UCLE 26 /* User-mode cache lock enable for BookE */
#define MSR_VR 25 /* altivec available x hflags */
@@ -401,10 +398,13 @@ typedef struct ppc_v3_pate_t {
#define msr_sf ((env->msr >> MSR_SF) & 1)
#define msr_isf ((env->msr >> MSR_ISF) & 1)
-#define msr_shv ((env->msr >> MSR_SHV) & 1)
+#if defined(TARGET_PPC64)
+#define msr_hv ((env->msr >> MSR_HV) & 1)
+#else
+#define msr_hv (0)
+#endif
#define msr_cm ((env->msr >> MSR_CM) & 1)
#define msr_icm ((env->msr >> MSR_ICM) & 1)
-#define msr_thv ((env->msr >> MSR_THV) & 1)
#define msr_gs ((env->msr >> MSR_GS) & 1)
#define msr_ucle ((env->msr >> MSR_UCLE) & 1)
#define msr_vr ((env->msr >> MSR_VR) & 1)
@@ -449,16 +449,9 @@ typedef struct ppc_v3_pate_t {
/* Hypervisor bit is more specific */
#if defined(TARGET_PPC64)
-#define MSR_HVB (1ULL << MSR_SHV)
-#define msr_hv msr_shv
-#else
-#if defined(PPC_EMULATE_32BITS_HYPV)
-#define MSR_HVB (1ULL << MSR_THV)
-#define msr_hv msr_thv
+#define MSR_HVB (1ULL << MSR_HV)
#else
#define MSR_HVB (0ULL)
-#define msr_hv (0)
-#endif
#endif
/* DSISR */
@@ -1051,10 +1044,6 @@ struct CPUPPCState {
uint32_t flags;
uint64_t insns_flags;
uint64_t insns_flags2;
-#if defined(TARGET_PPC64)
- ppc_slb_t vrma_slb;
- target_ulong rmls;
-#endif
int error_code;
uint32_t pending_interrupts;
@@ -1218,8 +1207,8 @@ bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req);
void ppc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
void ppc_cpu_dump_statistics(CPUState *cpu, int flags);
hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-int ppc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
-int ppc_cpu_gdb_read_register_apple(CPUState *cpu, uint8_t *buf, int reg);
+int ppc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
+int ppc_cpu_gdb_read_register_apple(CPUState *cpu, GByteArray *buf, int reg);
int ppc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
int ppc_cpu_gdb_write_register_apple(CPUState *cpu, uint8_t *buf, int reg);
#ifndef CONFIG_USER_ONLY
@@ -1231,7 +1220,8 @@ int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
int cpuid, void *opaque);
#ifndef CONFIG_USER_ONLY
-void ppc_cpu_do_system_reset(CPUState *cs);
+void ppc_cpu_do_system_reset(CPUState *cs, target_ulong vector);
+void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector);
extern const VMStateDescription vmstate_ppc_cpu;
#endif
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 027f54c0ed..08bc885ca6 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -128,6 +128,37 @@ static uint64_t ppc_excp_vector_offset(CPUState *cs, int ail)
return offset;
}
+static inline void powerpc_set_excp_state(PowerPCCPU *cpu,
+ target_ulong vector, target_ulong msr)
+{
+ CPUState *cs = CPU(cpu);
+ CPUPPCState *env = &cpu->env;
+
+ /*
+ * We don't use hreg_store_msr here as already have treated any
+ * special case that could occur. Just store MSR and update hflags
+ *
+ * Note: We *MUST* not use hreg_store_msr() as-is anyway because it
+ * will prevent setting of the HV bit which some exceptions might need
+ * to do.
+ */
+ env->msr = msr & env->msr_mask;
+ hreg_compute_hflags(env);
+ env->nip = vector;
+ /* Reset exception state */
+ cs->exception_index = POWERPC_EXCP_NONE;
+ env->error_code = 0;
+
+ /* Reset the reservation */
+ env->reserve_addr = -1;
+
+ /*
+ * Any interrupt is context synchronizing, check if TCG TLB needs
+ * a delayed flush on ppc64
+ */
+ check_tlb_flush(env, false);
+}
+
/*
* Note that this function should be greatly optimized when called
* with a constant excp, from ppc_hw_interrupt
@@ -768,29 +799,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
}
}
#endif
- /*
- * We don't use hreg_store_msr here as already have treated any
- * special case that could occur. Just store MSR and update hflags
- *
- * Note: We *MUST* not use hreg_store_msr() as-is anyway because it
- * will prevent setting of the HV bit which some exceptions might need
- * to do.
- */
- env->msr = new_msr & env->msr_mask;
- hreg_compute_hflags(env);
- env->nip = vector;
- /* Reset exception state */
- cs->exception_index = POWERPC_EXCP_NONE;
- env->error_code = 0;
- /* Reset the reservation */
- env->reserve_addr = -1;
-
- /*
- * Any interrupt is context synchronizing, check if TCG TLB needs
- * a delayed flush on ppc64
- */
- check_tlb_flush(env, false);
+ powerpc_set_excp_state(cpu, vector, new_msr);
}
void ppc_cpu_do_interrupt(CPUState *cs)
@@ -951,12 +961,35 @@ static void ppc_hw_interrupt(CPUPPCState *env)
}
}
-void ppc_cpu_do_system_reset(CPUState *cs)
+void ppc_cpu_do_system_reset(CPUState *cs, target_ulong vector)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
+ if (vector != -1) {
+ env->nip = vector;
+ }
+}
+
+void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ target_ulong msr = 0;
+
+ /*
+ * Set MSR and NIP for the handler, SRR0/1, DAR and DSISR have already
+ * been set by KVM.
+ */
+ msr = (1ULL << MSR_ME);
+ msr |= env->msr & (1ULL << MSR_SF);
+ if (!(*pcc->interrupts_big_endian)(cpu)) {
+ msr |= (1ULL << MSR_LE);
+ }
+
+ powerpc_set_excp_state(cpu, vector, msr);
}
#endif /* !CONFIG_USER_ONLY */
diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index 823759c92e..eb362dd9ae 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -114,10 +114,11 @@ void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len)
* the FP regs zero size when talking to a newer gdb.
*/
-int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int ppc_cpu_gdb_read_register(CPUState *cs, GByteArray *buf, int n)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
+ uint8_t *mem_buf;
int r = ppc_gdb_register_len(n);
if (!r) {
@@ -126,17 +127,17 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
if (n < 32) {
/* gprs */
- gdb_get_regl(mem_buf, env->gpr[n]);
+ gdb_get_regl(buf, env->gpr[n]);
} else if (n < 64) {
/* fprs */
- stfq_p(mem_buf, *cpu_fpr_ptr(env, n - 32));
+ gdb_get_reg64(buf, *cpu_fpr_ptr(env, n - 32));
} else {
switch (n) {
case 64:
- gdb_get_regl(mem_buf, env->nip);
+ gdb_get_regl(buf, env->nip);
break;
case 65:
- gdb_get_regl(mem_buf, env->msr);
+ gdb_get_regl(buf, env->msr);
break;
case 66:
{
@@ -145,31 +146,33 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
for (i = 0; i < 8; i++) {
cr |= env->crf[i] << (32 - ((i + 1) * 4));
}
- gdb_get_reg32(mem_buf, cr);
+ gdb_get_reg32(buf, cr);
break;
}
case 67:
- gdb_get_regl(mem_buf, env->lr);
+ gdb_get_regl(buf, env->lr);
break;
case 68:
- gdb_get_regl(mem_buf, env->ctr);
+ gdb_get_regl(buf, env->ctr);
break;
case 69:
- gdb_get_reg32(mem_buf, env->xer);
+ gdb_get_reg32(buf, env->xer);
break;
case 70:
- gdb_get_reg32(mem_buf, env->fpscr);
+ gdb_get_reg32(buf, env->fpscr);
break;
}
}
+ mem_buf = buf->data + buf->len - r;
ppc_maybe_bswap_register(env, mem_buf, r);
return r;
}
-int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
+int ppc_cpu_gdb_read_register_apple(CPUState *cs, GByteArray *buf, int n)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
+ uint8_t *mem_buf;
int r = ppc_gdb_register_len_apple(n);
if (!r) {
@@ -178,21 +181,21 @@ int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
if (n < 32) {
/* gprs */
- gdb_get_reg64(mem_buf, env->gpr[n]);
+ gdb_get_reg64(buf, env->gpr[n]);
} else if (n < 64) {
/* fprs */
- stfq_p(mem_buf, *cpu_fpr_ptr(env, n - 32));
+ gdb_get_reg64(buf, *cpu_fpr_ptr(env, n - 32));
} else if (n < 96) {
/* Altivec */
- stq_p(mem_buf, n - 64);
- stq_p(mem_buf + 8, 0);
+ gdb_get_reg64(buf, n - 64);
+ gdb_get_reg64(buf, 0);
} else {
switch (n) {
case 64 + 32:
- gdb_get_reg64(mem_buf, env->nip);
+ gdb_get_reg64(buf, env->nip);
break;
case 65 + 32:
- gdb_get_reg64(mem_buf, env->msr);
+ gdb_get_reg64(buf, env->msr);
break;
case 66 + 32:
{
@@ -201,23 +204,24 @@ int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
for (i = 0; i < 8; i++) {
cr |= env->crf[i] << (32 - ((i + 1) * 4));
}
- gdb_get_reg32(mem_buf, cr);
+ gdb_get_reg32(buf, cr);
break;
}
case 67 + 32:
- gdb_get_reg64(mem_buf, env->lr);
+ gdb_get_reg64(buf, env->lr);
break;
case 68 + 32:
- gdb_get_reg64(mem_buf, env->ctr);
+ gdb_get_reg64(buf, env->ctr);
break;
case 69 + 32:
- gdb_get_reg32(mem_buf, env->xer);
+ gdb_get_reg32(buf, env->xer);
break;
case 70 + 32:
- gdb_get_reg64(mem_buf, env->fpscr);
+ gdb_get_reg64(buf, env->fpscr);
break;
}
}
+ mem_buf = buf->data + buf->len - r;
ppc_maybe_bswap_register(env, mem_buf, r);
return r;
}
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 7f44b1aa1a..597f72be1b 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2113,7 +2113,7 @@ void kvmppc_error_append_smt_possible_hint(Error *const *errp)
#ifdef TARGET_PPC64
-uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
+uint64_t kvmppc_vrma_limit(unsigned int hash_shift)
{
struct kvm_ppc_smmu_info info;
long rampagesize, best_page_shift;
@@ -2140,8 +2140,7 @@ uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
}
}
- return MIN(current_size,
- 1ULL << (best_page_shift + hash_shift - 7));
+ return 1ULL << (best_page_shift + hash_shift - 7);
}
#endif
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index 9e4f2357cc..332fa0aa1c 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -47,7 +47,7 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t page_shift,
int *pfd, bool need_vfio);
int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
int kvmppc_reset_htab(int shift_hint);
-uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift);
+uint64_t kvmppc_vrma_limit(unsigned int hash_shift);
bool kvmppc_has_cap_spapr_vfio(void);
#endif /* !CONFIG_USER_ONLY */
bool kvmppc_has_cap_epr(void);
@@ -255,10 +255,9 @@ static inline int kvmppc_reset_htab(int shift_hint)
return 0;
}
-static inline uint64_t kvmppc_rma_size(uint64_t current_size,
- unsigned int hash_shift)
+static inline uint64_t kvmppc_vrma_limit(unsigned int hash_shift)
{
- return ram_size;
+ g_assert_not_reached();
}
static inline bool kvmppc_hpt_needs_host_contiguous_pages(void)
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index da8966ccf5..34f6009b1e 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -18,6 +18,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
+#include "qemu/units.h"
#include "cpu.h"
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
@@ -668,6 +669,21 @@ unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu,
return 0;
}
+static bool ppc_hash64_use_vrma(CPUPPCState *env)
+{
+ switch (env->mmu_model) {
+ case POWERPC_MMU_3_00:
+ /*
+ * ISAv3.0 (POWER9) always uses VRMA, the VPM0 field and RMOR
+ * register no longer exist
+ */
+ return true;
+
+ default:
+ return !!(env->spr[SPR_LPCR] & LPCR_VPM0);
+ }
+}
+
static void ppc_hash64_set_isi(CPUState *cs, uint64_t error_code)
{
CPUPPCState *env = &POWERPC_CPU(cs)->env;
@@ -676,15 +692,7 @@ static void ppc_hash64_set_isi(CPUState *cs, uint64_t error_code)
if (msr_ir) {
vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM1);
} else {
- switch (env->mmu_model) {
- case POWERPC_MMU_3_00:
- /* Field deprecated in ISAv3.00 - interrupts always go to hyperv */
- vpm = true;
- break;
- default:
- vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM0);
- break;
- }
+ vpm = ppc_hash64_use_vrma(env);
}
if (vpm && !msr_hv) {
cs->exception_index = POWERPC_EXCP_HISI;
@@ -702,15 +710,7 @@ static void ppc_hash64_set_dsi(CPUState *cs, uint64_t dar, uint64_t dsisr)
if (msr_dr) {
vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM1);
} else {
- switch (env->mmu_model) {
- case POWERPC_MMU_3_00:
- /* Field deprecated in ISAv3.00 - interrupts always go to hyperv */
- vpm = true;
- break;
- default:
- vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM0);
- break;
- }
+ vpm = ppc_hash64_use_vrma(env);
}
if (vpm && !msr_hv) {
cs->exception_index = POWERPC_EXCP_HDSI;
@@ -758,11 +758,67 @@ static void ppc_hash64_set_c(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1)
stb_phys(CPU(cpu)->as, base + offset, (pte1 & 0xff) | 0x80);
}
+static target_ulong rmls_limit(PowerPCCPU *cpu)
+{
+ CPUPPCState *env = &cpu->env;
+ /*
+ * In theory the meanings of RMLS values are implementation
+ * dependent. In practice, this seems to have been the set from
+ * POWER4+..POWER8, and RMLS is no longer supported in POWER9.
+ *
+ * Unsupported values mean the OS has shot itself in the
+ * foot. Return a 0-sized RMA in this case, which we expect
+ * to trigger an immediate DSI or ISI
+ */
+ static const target_ulong rma_sizes[16] = {
+ [0] = 256 * GiB,
+ [1] = 16 * GiB,
+ [2] = 1 * GiB,
+ [3] = 64 * MiB,
+ [4] = 256 * MiB,
+ [7] = 128 * MiB,
+ [8] = 32 * MiB,
+ };
+ target_ulong rmls = (env->spr[SPR_LPCR] & LPCR_RMLS) >> LPCR_RMLS_SHIFT;
+
+ return rma_sizes[rmls];
+}
+
+static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t *slb)
+{
+ CPUPPCState *env = &cpu->env;
+ target_ulong lpcr = env->spr[SPR_LPCR];
+ uint32_t vrmasd = (lpcr & LPCR_VRMASD) >> LPCR_VRMASD_SHIFT;
+ target_ulong vsid = SLB_VSID_VRMA | ((vrmasd << 4) & SLB_VSID_LLP_MASK);
+ int i;
+
+ for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
+ const PPCHash64SegmentPageSizes *sps = &cpu->hash64_opts->sps[i];
+
+ if (!sps->page_shift) {
+ break;
+ }
+
+ if ((vsid & SLB_VSID_LLP_MASK) == sps->slb_enc) {
+ slb->esid = SLB_ESID_V;
+ slb->vsid = vsid;
+ slb->sps = sps;
+ return 0;
+ }
+ }
+
+ error_report("Bad page size encoding in LPCR[VRMASD]; LPCR=0x"
+ TARGET_FMT_lx"\n", lpcr);
+
+ return -1;
+}
+
int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
int rwx, int mmu_idx)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
+ ppc_slb_t vrma_slbe;
ppc_slb_t *slb;
unsigned apshift;
hwaddr ptex;
@@ -789,27 +845,32 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
*/
raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
- /* In HV mode, add HRMOR if top EA bit is clear */
- if (msr_hv || !env->has_hv_mode) {
+ if (cpu->vhyp) {
+ /*
+ * In virtual hypervisor mode, there's nothing to do:
+ * EA == GPA == qemu guest address
+ */
+ } else if (msr_hv || !env->has_hv_mode) {
+ /* In HV mode, add HRMOR if top EA bit is clear */
if (!(eaddr >> 63)) {
raddr |= env->spr[SPR_HRMOR];
}
- } else {
- /* Otherwise, check VPM for RMA vs VRMA */
- if (env->spr[SPR_LPCR] & LPCR_VPM0) {
- slb = &env->vrma_slb;
- if (slb->sps) {
- goto skip_slb_search;
- }
- /* Not much else to do here */
+ } else if (ppc_hash64_use_vrma(env)) {
+ /* Emulated VRMA mode */
+ slb = &vrma_slbe;
+ if (build_vrma_slbe(cpu, slb) != 0) {
+ /* Invalid VRMA setup, machine check */
cs->exception_index = POWERPC_EXCP_MCHECK;
env->error_code = 0;
return 1;
- } else if (raddr < env->rmls) {
- /* RMA. Check bounds in RMLS */
- raddr |= env->spr[SPR_RMOR];
- } else {
- /* The access failed, generate the approriate interrupt */
+ }
+
+ goto skip_slb_search;
+ } else {
+ target_ulong limit = rmls_limit(cpu);
+
+ /* Emulated old-style RMO mode, bounds check against RMLS */
+ if (raddr >= limit) {
if (rwx == 2) {
ppc_hash64_set_isi(cs, SRR1_PROTFAULT);
} else {
@@ -821,6 +882,8 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
}
return 1;
}
+
+ raddr |= env->spr[SPR_RMOR];
}
tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx,
@@ -943,6 +1006,7 @@ skip_slb_search:
hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr)
{
CPUPPCState *env = &cpu->env;
+ ppc_slb_t vrma_slbe;
ppc_slb_t *slb;
hwaddr ptex, raddr;
ppc_hash_pte64_t pte;
@@ -953,22 +1017,29 @@ hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr)
/* In real mode the top 4 effective address bits are ignored */
raddr = addr & 0x0FFFFFFFFFFFFFFFULL;
- /* In HV mode, add HRMOR if top EA bit is clear */
- if ((msr_hv || !env->has_hv_mode) && !(addr >> 63)) {
+ if (cpu->vhyp) {
+ /*
+ * In virtual hypervisor mode, there's nothing to do:
+ * EA == GPA == qemu guest address
+ */
+ return raddr;
+ } else if ((msr_hv || !env->has_hv_mode) && !(addr >> 63)) {
+ /* In HV mode, add HRMOR if top EA bit is clear */
return raddr | env->spr[SPR_HRMOR];
- }
+ } else if (ppc_hash64_use_vrma(env)) {
+ /* Emulated VRMA mode */
+ slb = &vrma_slbe;
+ if (build_vrma_slbe(cpu, slb) != 0) {
+ return -1;
+ }
+ } else {
+ target_ulong limit = rmls_limit(cpu);
- /* Otherwise, check VPM for RMA vs VRMA */
- if (env->spr[SPR_LPCR] & LPCR_VPM0) {
- slb = &env->vrma_slb;
- if (!slb->sps) {
+ /* Emulated old-style RMO mode, bounds check against RMLS */
+ if (raddr >= limit) {
return -1;
}
- } else if (raddr < env->rmls) {
- /* RMA. Check bounds in RMLS */
return raddr | env->spr[SPR_RMOR];
- } else {
- return -1;
}
} else {
slb = slb_lookup(cpu, addr);
@@ -997,168 +1068,12 @@ void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong ptex,
cpu->env.tlb_need_flush = TLB_NEED_GLOBAL_FLUSH | TLB_NEED_LOCAL_FLUSH;
}
-static void ppc_hash64_update_rmls(PowerPCCPU *cpu)
-{
- CPUPPCState *env = &cpu->env;
- uint64_t lpcr = env->spr[SPR_LPCR];
-
- /*
- * This is the full 4 bits encoding of POWER8. Previous
- * CPUs only support a subset of these but the filtering
- * is done when writing LPCR
- */
- switch ((lpcr & LPCR_RMLS) >> LPCR_RMLS_SHIFT) {
- case 0x8: /* 32MB */
- env->rmls = 0x2000000ull;
- break;
- case 0x3: /* 64MB */
- env->rmls = 0x4000000ull;
- break;
- case 0x7: /* 128MB */
- env->rmls = 0x8000000ull;
- break;
- case 0x4: /* 256MB */
- env->rmls = 0x10000000ull;
- break;
- case 0x2: /* 1GB */
- env->rmls = 0x40000000ull;
- break;
- case 0x1: /* 16GB */
- env->rmls = 0x400000000ull;
- break;
- default:
- /* What to do here ??? */
- env->rmls = 0;
- }
-}
-
-static void ppc_hash64_update_vrma(PowerPCCPU *cpu)
-{
- CPUPPCState *env = &cpu->env;
- const PPCHash64SegmentPageSizes *sps = NULL;
- target_ulong esid, vsid, lpcr;
- ppc_slb_t *slb = &env->vrma_slb;
- uint32_t vrmasd;
- int i;
-
- /* First clear it */
- slb->esid = slb->vsid = 0;
- slb->sps = NULL;
-
- /* Is VRMA enabled ? */
- lpcr = env->spr[SPR_LPCR];
- if (!(lpcr & LPCR_VPM0)) {
- return;
- }
-
- /*
- * Make one up. Mostly ignore the ESID which will not be needed
- * for translation
- */
- vsid = SLB_VSID_VRMA;
- vrmasd = (lpcr & LPCR_VRMASD) >> LPCR_VRMASD_SHIFT;
- vsid |= (vrmasd << 4) & (SLB_VSID_L | SLB_VSID_LP);
- esid = SLB_ESID_V;
-
- for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
- const PPCHash64SegmentPageSizes *sps1 = &cpu->hash64_opts->sps[i];
-
- if (!sps1->page_shift) {
- break;
- }
-
- if ((vsid & SLB_VSID_LLP_MASK) == sps1->slb_enc) {
- sps = sps1;
- break;
- }
- }
-
- if (!sps) {
- error_report("Bad page size encoding esid 0x"TARGET_FMT_lx
- " vsid 0x"TARGET_FMT_lx, esid, vsid);
- return;
- }
-
- slb->vsid = vsid;
- slb->esid = esid;
- slb->sps = sps;
-}
-
void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val)
{
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
CPUPPCState *env = &cpu->env;
- uint64_t lpcr = 0;
-
- /* Filter out bits */
- switch (env->mmu_model) {
- case POWERPC_MMU_64B: /* 970 */
- if (val & 0x40) {
- lpcr |= LPCR_LPES0;
- }
- if (val & 0x8000000000000000ull) {
- lpcr |= LPCR_LPES1;
- }
- if (val & 0x20) {
- lpcr |= (0x4ull << LPCR_RMLS_SHIFT);
- }
- if (val & 0x4000000000000000ull) {
- lpcr |= (0x2ull << LPCR_RMLS_SHIFT);
- }
- if (val & 0x2000000000000000ull) {
- lpcr |= (0x1ull << LPCR_RMLS_SHIFT);
- }
- env->spr[SPR_RMOR] = ((lpcr >> 41) & 0xffffull) << 26;
- /*
- * XXX We could also write LPID from HID4 here
- * but since we don't tag any translation on it
- * it doesn't actually matter
- *
- * XXX For proper emulation of 970 we also need
- * to dig HRMOR out of HID5
- */
- break;
- case POWERPC_MMU_2_03: /* P5p */
- lpcr = val & (LPCR_RMLS | LPCR_ILE |
- LPCR_LPES0 | LPCR_LPES1 |
- LPCR_RMI | LPCR_HDICE);
- break;
- case POWERPC_MMU_2_06: /* P7 */
- lpcr = val & (LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_DPFD |
- LPCR_VRMASD | LPCR_RMLS | LPCR_ILE |
- LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2 |
- LPCR_MER | LPCR_TC |
- LPCR_LPES0 | LPCR_LPES1 | LPCR_HDICE);
- break;
- case POWERPC_MMU_2_07: /* P8 */
- lpcr = val & (LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV |
- LPCR_DPFD | LPCR_VRMASD | LPCR_RMLS | LPCR_ILE |
- LPCR_AIL | LPCR_ONL | LPCR_P8_PECE0 | LPCR_P8_PECE1 |
- LPCR_P8_PECE2 | LPCR_P8_PECE3 | LPCR_P8_PECE4 |
- LPCR_MER | LPCR_TC | LPCR_LPES0 | LPCR_HDICE);
- break;
- case POWERPC_MMU_3_00: /* P9 */
- lpcr = val & (LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD |
- (LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL |
- LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD |
- (LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE |
- LPCR_DEE | LPCR_OEE)) | LPCR_MER | LPCR_GTSE | LPCR_TC |
- LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE);
- /*
- * If we have a virtual hypervisor, we need to bring back RMLS. It
- * doesn't exist on an actual P9 but that's all we know how to
- * configure with softmmu at the moment
- */
- if (cpu->vhyp) {
- lpcr |= (val & LPCR_RMLS);
- }
- break;
- default:
- ;
- }
- env->spr[SPR_LPCR] = lpcr;
- ppc_hash64_update_rmls(cpu);
- ppc_hash64_update_vrma(cpu);
+ env->spr[SPR_LPCR] = val & pcc->lpcr_mask;
}
void helper_store_lpcr(CPUPPCState *env, target_ulong val)
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 36fa27367c..127c82a24e 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1938,15 +1938,17 @@ static void gen_rlwinm(DisasContext *ctx)
me += 32;
#endif
mask = MASK(mb, me);
- if (sh == 0) {
- tcg_gen_andi_tl(t_ra, t_rs, mask);
- } else if (mask <= 0xffffffffu) {
- TCGv_i32 t0 = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(t0, t_rs);
- tcg_gen_rotli_i32(t0, t0, sh);
- tcg_gen_andi_i32(t0, t0, mask);
- tcg_gen_extu_i32_tl(t_ra, t0);
- tcg_temp_free_i32(t0);
+ if (mask <= 0xffffffffu) {
+ if (sh == 0) {
+ tcg_gen_andi_tl(t_ra, t_rs, mask);
+ } else {
+ TCGv_i32 t0 = tcg_temp_new_i32();
+ tcg_gen_trunc_tl_i32(t0, t_rs);
+ tcg_gen_rotli_i32(t0, t0, sh);
+ tcg_gen_andi_i32(t0, t0, mask);
+ tcg_gen_extu_i32_tl(t_ra, t0);
+ tcg_temp_free_i32(t0);
+ }
} else {
#if defined(TARGET_PPC64)
tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 7e9780e875..e853164a86 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -7895,25 +7895,21 @@ static void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn)
{
gen_helper_store_lpcr(cpu_env, cpu_gpr[gprn]);
}
-
-static void spr_write_970_hid4(DisasContext *ctx, int sprn, int gprn)
-{
-#if defined(TARGET_PPC64)
- spr_write_generic(ctx, sprn, gprn);
- gen_helper_store_lpcr(cpu_env, cpu_gpr[gprn]);
-#endif
-}
-
#endif /* !defined(CONFIG_USER_ONLY) */
static void gen_spr_970_lpar(CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
- /* Logical partitionning */
- /* PPC970: HID4 is effectively the LPCR */
+ /*
+ * PPC970: HID4 covers things later controlled by the LPCR and
+ * RMOR in later CPUs, but with a different encoding. We only
+ * support the 970 in "Apple mode" which has all hypervisor
+ * facilities disabled by strapping, so we can basically just
+ * ignore it
+ */
spr_register(env, SPR_970_HID4, "HID4",
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_970_hid4,
+ &spr_read_generic, &spr_write_generic,
0x00000000);
#endif
}
@@ -8019,12 +8015,16 @@ static void gen_spr_book3s_ids(CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
- spr_register_hv(env, SPR_RMOR, "RMOR",
+ spr_register_hv(env, SPR_HRMOR, "HRMOR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
- spr_register_hv(env, SPR_HRMOR, "HRMOR",
+}
+
+static void gen_spr_rmor(CPUPPCState *env)
+{
+ spr_register_hv(env, SPR_RMOR, "RMOR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
@@ -8476,6 +8476,8 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
(1ull << MSR_DR) |
(1ull << MSR_PMM) |
(1ull << MSR_RI);
+ pcc->lpcr_mask = LPCR_RMLS | LPCR_ILE | LPCR_LPES0 | LPCR_LPES1 |
+ LPCR_RMI | LPCR_HDICE;
pcc->mmu_model = POWERPC_MMU_2_03;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
@@ -8492,44 +8494,6 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
pcc->l1_icache_size = 0x10000;
}
-/*
- * The CPU used to have a "compat" property which set the
- * compatibility mode PVR. However, this was conceptually broken - it
- * only makes sense on the pseries machine type (otherwise the guest
- * owns the PCR and can control the compatibility mode itself). It's
- * been replaced with the 'max-cpu-compat' property on the pseries
- * machine type. For backwards compatibility, pseries specially
- * parses the -cpu parameter and converts old compat= parameters into
- * the appropriate machine parameters. This stub implementation of
- * the parameter catches any uses on explicitly created CPUs.
- */
-static void getset_compat_deprecated(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- QNull *null = NULL;
-
- if (!qtest_enabled()) {
- warn_report("CPU 'compat' property is deprecated and has no effect; "
- "use max-cpu-compat machine property instead");
- }
- visit_type_null(v, name, &null, NULL);
- qobject_unref(null);
-}
-
-static const PropertyInfo ppc_compat_deprecated_propinfo = {
- .name = "str",
- .description = "compatibility mode (deprecated)",
- .get = getset_compat_deprecated,
- .set = getset_compat_deprecated,
-};
-static Property powerpc_servercpu_properties[] = {
- {
- .name = "compat",
- .info = &ppc_compat_deprecated_propinfo,
- },
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void init_proc_POWER7(CPUPPCState *env)
{
/* Common Registers */
@@ -8539,6 +8503,7 @@ static void init_proc_POWER7(CPUPPCState *env)
/* POWER7 Specific Registers */
gen_spr_book3s_ids(env);
+ gen_spr_rmor(env);
gen_spr_amr(env);
gen_spr_book3s_purr(env);
gen_spr_power5p_common(env);
@@ -8611,7 +8576,6 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER7";
dc->desc = "POWER7";
- device_class_set_props(dc, powerpc_servercpu_properties);
pcc->pvr_match = ppc_pvr_match_power7;
pcc->pcr_mask = PCR_VEC_DIS | PCR_VSX_DIS | PCR_COMPAT_2_05;
pcc->pcr_supported = PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
@@ -8652,6 +8616,12 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
(1ull << MSR_PMM) |
(1ull << MSR_RI) |
(1ull << MSR_LE);
+ pcc->lpcr_mask = LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_DPFD |
+ LPCR_VRMASD | LPCR_RMLS | LPCR_ILE |
+ LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2 |
+ LPCR_MER | LPCR_TC |
+ LPCR_LPES0 | LPCR_LPES1 | LPCR_HDICE;
+ pcc->lpcr_pm = LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2;
pcc->mmu_model = POWERPC_MMU_2_06;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
@@ -8668,7 +8638,6 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
- pcc->lpcr_pm = LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2;
}
static void init_proc_POWER8(CPUPPCState *env)
@@ -8680,6 +8649,7 @@ static void init_proc_POWER8(CPUPPCState *env)
/* POWER8 Specific Registers */
gen_spr_book3s_ids(env);
+ gen_spr_rmor(env);
gen_spr_amr(env);
gen_spr_iamr(env);
gen_spr_book3s_purr(env);
@@ -8776,7 +8746,6 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER8";
dc->desc = "POWER8";
- device_class_set_props(dc, powerpc_servercpu_properties);
pcc->pvr_match = ppc_pvr_match_power8;
pcc->pcr_mask = PCR_TM_DIS | PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
pcc->pcr_supported = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
@@ -8804,7 +8773,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
PPC2_TM | PPC2_PM_ISA206;
pcc->msr_mask = (1ull << MSR_SF) |
- (1ull << MSR_SHV) |
+ (1ull << MSR_HV) |
(1ull << MSR_TM) |
(1ull << MSR_VR) |
(1ull << MSR_VSX) |
@@ -8823,6 +8792,13 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
(1ull << MSR_TS0) |
(1ull << MSR_TS1) |
(1ull << MSR_LE);
+ pcc->lpcr_mask = LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV |
+ LPCR_DPFD | LPCR_VRMASD | LPCR_RMLS | LPCR_ILE |
+ LPCR_AIL | LPCR_ONL | LPCR_P8_PECE0 | LPCR_P8_PECE1 |
+ LPCR_P8_PECE2 | LPCR_P8_PECE3 | LPCR_P8_PECE4 |
+ LPCR_MER | LPCR_TC | LPCR_LPES0 | LPCR_HDICE;
+ pcc->lpcr_pm = LPCR_P8_PECE0 | LPCR_P8_PECE1 | LPCR_P8_PECE2 |
+ LPCR_P8_PECE3 | LPCR_P8_PECE4;
pcc->mmu_model = POWERPC_MMU_2_07;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
@@ -8840,8 +8816,6 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
- pcc->lpcr_pm = LPCR_P8_PECE0 | LPCR_P8_PECE1 | LPCR_P8_PECE2 |
- LPCR_P8_PECE3 | LPCR_P8_PECE4;
}
#ifdef CONFIG_SOFTMMU
@@ -8988,7 +8962,6 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER9";
dc->desc = "POWER9";
- device_class_set_props(dc, powerpc_servercpu_properties);
pcc->pvr_match = ppc_pvr_match_power9;
pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07;
pcc->pcr_supported = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 |
@@ -9017,7 +8990,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL;
pcc->msr_mask = (1ull << MSR_SF) |
- (1ull << MSR_SHV) |
+ (1ull << MSR_HV) |
(1ull << MSR_TM) |
(1ull << MSR_VR) |
(1ull << MSR_VSX) |
@@ -9034,6 +9007,14 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
(1ull << MSR_PMM) |
(1ull << MSR_RI) |
(1ull << MSR_LE);
+ pcc->lpcr_mask = LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD |
+ (LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL |
+ LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD |
+ (LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE |
+ LPCR_DEE | LPCR_OEE))
+ | LPCR_MER | LPCR_GTSE | LPCR_TC |
+ LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE;
+ pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE;
pcc->mmu_model = POWERPC_MMU_3_00;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc64_v3_handle_mmu_fault;
@@ -9053,7 +9034,6 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
- pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE;
}
#ifdef CONFIG_SOFTMMU
@@ -9198,7 +9178,6 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER10";
dc->desc = "POWER10";
- device_class_set_props(dc, powerpc_servercpu_properties);
pcc->pvr_match = ppc_pvr_match_power10;
pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07 |
PCR_COMPAT_3_00;
@@ -9228,7 +9207,7 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL;
pcc->msr_mask = (1ull << MSR_SF) |
- (1ull << MSR_SHV) |
+ (1ull << MSR_HV) |
(1ull << MSR_TM) |
(1ull << MSR_VR) |
(1ull << MSR_VSX) |
@@ -9245,6 +9224,14 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
(1ull << MSR_PMM) |
(1ull << MSR_RI) |
(1ull << MSR_LE);
+ pcc->lpcr_mask = LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD |
+ (LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL |
+ LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD |
+ (LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE |
+ LPCR_DEE | LPCR_OEE))
+ | LPCR_MER | LPCR_GTSE | LPCR_TC |
+ LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE;
+ pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE;
pcc->mmu_model = POWERPC_MMU_3_00;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc64_v3_handle_mmu_fault;
@@ -9263,7 +9250,6 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
- pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE;
}
#if !defined(CONFIG_USER_ONLY)
@@ -9857,7 +9843,7 @@ static int gdb_find_spr_idx(CPUPPCState *env, int n)
return -1;
}
-static int gdb_get_spr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
+static int gdb_get_spr_reg(CPUPPCState *env, GByteArray *buf, int n)
{
int reg;
int len;
@@ -9868,8 +9854,8 @@ static int gdb_get_spr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
}
len = TARGET_LONG_SIZE;
- stn_p(mem_buf, len, env->spr[reg]);
- ppc_maybe_bswap_register(env, mem_buf, len);
+ gdb_get_regl(buf, env->spr[reg]);
+ ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, len), len);
return len;
}
@@ -9891,15 +9877,18 @@ static int gdb_set_spr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
}
#endif
-static int gdb_get_float_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
+static int gdb_get_float_reg(CPUPPCState *env, GByteArray *buf, int n)
{
+ uint8_t *mem_buf;
if (n < 32) {
- stfq_p(mem_buf, *cpu_fpr_ptr(env, n));
+ gdb_get_reg64(buf, *cpu_fpr_ptr(env, n));
+ mem_buf = gdb_get_reg_ptr(buf, 8);
ppc_maybe_bswap_register(env, mem_buf, 8);
return 8;
}
if (n == 32) {
- stl_p(mem_buf, env->fpscr);
+ gdb_get_reg32(buf, env->fpscr);
+ mem_buf = gdb_get_reg_ptr(buf, 4);
ppc_maybe_bswap_register(env, mem_buf, 4);
return 4;
}
@@ -9921,28 +9910,31 @@ static int gdb_set_float_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
return 0;
}
-static int gdb_get_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
+static int gdb_get_avr_reg(CPUPPCState *env, GByteArray *buf, int n)
{
+ uint8_t *mem_buf;
+
if (n < 32) {
ppc_avr_t *avr = cpu_avr_ptr(env, n);
if (!avr_need_swap(env)) {
- stq_p(mem_buf, avr->u64[0]);
- stq_p(mem_buf + 8, avr->u64[1]);
+ gdb_get_reg128(buf, avr->u64[0] , avr->u64[1]);
} else {
- stq_p(mem_buf, avr->u64[1]);
- stq_p(mem_buf + 8, avr->u64[0]);
+ gdb_get_reg128(buf, avr->u64[1] , avr->u64[0]);
}
+ mem_buf = gdb_get_reg_ptr(buf, 16);
ppc_maybe_bswap_register(env, mem_buf, 8);
ppc_maybe_bswap_register(env, mem_buf + 8, 8);
return 16;
}
if (n == 32) {
- stl_p(mem_buf, helper_mfvscr(env));
+ gdb_get_reg32(buf, helper_mfvscr(env));
+ mem_buf = gdb_get_reg_ptr(buf, 4);
ppc_maybe_bswap_register(env, mem_buf, 4);
return 4;
}
if (n == 33) {
- stl_p(mem_buf, (uint32_t)env->spr[SPR_VRSAVE]);
+ gdb_get_reg32(buf, (uint32_t)env->spr[SPR_VRSAVE]);
+ mem_buf = gdb_get_reg_ptr(buf, 4);
ppc_maybe_bswap_register(env, mem_buf, 4);
return 4;
}
@@ -9977,25 +9969,25 @@ static int gdb_set_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
return 0;
}
-static int gdb_get_spe_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
+static int gdb_get_spe_reg(CPUPPCState *env, GByteArray *buf, int n)
{
if (n < 32) {
#if defined(TARGET_PPC64)
- stl_p(mem_buf, env->gpr[n] >> 32);
- ppc_maybe_bswap_register(env, mem_buf, 4);
+ gdb_get_reg32(buf, env->gpr[n] >> 32);
+ ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 4), 4);
#else
- stl_p(mem_buf, env->gprh[n]);
+ gdb_get_reg32(buf, env->gprh[n]);
#endif
return 4;
}
if (n == 32) {
- stq_p(mem_buf, env->spe_acc);
- ppc_maybe_bswap_register(env, mem_buf, 8);
+ gdb_get_reg64(buf, env->spe_acc);
+ ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 8), 8);
return 8;
}
if (n == 33) {
- stl_p(mem_buf, env->spe_fscr);
- ppc_maybe_bswap_register(env, mem_buf, 4);
+ gdb_get_reg32(buf, env->spe_fscr);
+ ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 4), 4);
return 4;
}
return 0;
@@ -10030,11 +10022,11 @@ static int gdb_set_spe_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
return 0;
}
-static int gdb_get_vsx_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
+static int gdb_get_vsx_reg(CPUPPCState *env, GByteArray *buf, int n)
{
if (n < 32) {
- stq_p(mem_buf, *cpu_vsrl_ptr(env, n));
- ppc_maybe_bswap_register(env, mem_buf, 8);
+ gdb_get_reg64(buf, *cpu_vsrl_ptr(env, n));
+ ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 8), 8);
return 8;
}
return 0;
@@ -10486,6 +10478,8 @@ static void ppc_cpu_parse_featurestr(const char *type, char *features,
*s = '\0';
for (i = 0; inpieces[i]; i++) {
if (g_str_has_prefix(inpieces[i], "compat=")) {
+ warn_report_once("CPU 'compat' property is deprecated; "
+ "use max-cpu-compat machine property instead");
compat_str = inpieces[i];
continue;
}
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 078fc83959..7d21addbab 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -293,7 +293,7 @@ extern const char * const riscv_excp_names[];
extern const char * const riscv_intr_names[];
void riscv_cpu_do_interrupt(CPUState *cpu);
-int riscv_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
bool riscv_cpu_fp_enabled(CPURISCVState *env);
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 2f32750f2f..eba12a86f2 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -270,7 +270,7 @@ static int csr_register_map[] = {
CSR_MHCOUNTEREN,
};
-int riscv_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
@@ -301,14 +301,14 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
return 0;
}
-static int riscv_gdb_get_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
+static int riscv_gdb_get_fpu(CPURISCVState *env, GByteArray *buf, int n)
{
if (n < 32) {
if (env->misa & RVD) {
- return gdb_get_reg64(mem_buf, env->fpr[n]);
+ return gdb_get_reg64(buf, env->fpr[n]);
}
if (env->misa & RVF) {
- return gdb_get_reg32(mem_buf, env->fpr[n]);
+ return gdb_get_reg32(buf, env->fpr[n]);
}
/* there is hole between ft11 and fflags in fpu.xml */
} else if (n < 36 && n > 32) {
@@ -322,7 +322,7 @@ static int riscv_gdb_get_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
result = riscv_csrrw_debug(env, n - 33 + csr_register_map[8], &val,
0, 0);
if (result == 0) {
- return gdb_get_regl(mem_buf, val);
+ return gdb_get_regl(buf, val);
}
}
return 0;
@@ -351,7 +351,7 @@ static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
return 0;
}
-static int riscv_gdb_get_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
+static int riscv_gdb_get_csr(CPURISCVState *env, GByteArray *buf, int n)
{
if (n < ARRAY_SIZE(csr_register_map)) {
target_ulong val = 0;
@@ -359,7 +359,7 @@ static int riscv_gdb_get_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
result = riscv_csrrw_debug(env, csr_register_map[n], &val, 0, 0);
if (result == 0) {
- return gdb_get_regl(mem_buf, val);
+ return gdb_get_regl(buf, val);
}
}
return 0;
@@ -379,13 +379,13 @@ static int riscv_gdb_set_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
return 0;
}
-static int riscv_gdb_get_virtual(CPURISCVState *cs, uint8_t *mem_buf, int n)
+static int riscv_gdb_get_virtual(CPURISCVState *cs, GByteArray *buf, int n)
{
if (n == 0) {
#ifdef CONFIG_USER_ONLY
- return gdb_get_regl(mem_buf, 0);
+ return gdb_get_regl(buf, 0);
#else
- return gdb_get_regl(mem_buf, cs->priv);
+ return gdb_get_regl(buf, cs->priv);
#endif
}
return 0;
diff --git a/target/s390x/gdbstub.c b/target/s390x/gdbstub.c
index e24a49f4a9..d6fce5ff1e 100644
--- a/target/s390x/gdbstub.c
+++ b/target/s390x/gdbstub.c
@@ -27,7 +27,7 @@
#include "sysemu/hw_accel.h"
#include "sysemu/tcg.h"
-int s390_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int s390_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
S390CPU *cpu = S390_CPU(cs);
CPUS390XState *env = &cpu->env;
@@ -82,11 +82,11 @@ int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
/* total number of registers in s390-acr.xml */
#define S390_NUM_AC_REGS 16
-static int cpu_read_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
+static int cpu_read_ac_reg(CPUS390XState *env, GByteArray *buf, int n)
{
switch (n) {
case S390_A0_REGNUM ... S390_A15_REGNUM:
- return gdb_get_reg32(mem_buf, env->aregs[n]);
+ return gdb_get_reg32(buf, env->aregs[n]);
default:
return 0;
}
@@ -111,13 +111,13 @@ static int cpu_write_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
/* total number of registers in s390-fpr.xml */
#define S390_NUM_FP_REGS 17
-static int cpu_read_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
+static int cpu_read_fp_reg(CPUS390XState *env, GByteArray *buf, int n)
{
switch (n) {
case S390_FPC_REGNUM:
- return gdb_get_reg32(mem_buf, env->fpc);
+ return gdb_get_reg32(buf, env->fpc);
case S390_F0_REGNUM ... S390_F15_REGNUM:
- return gdb_get_reg64(mem_buf, *get_freg(env, n - S390_F0_REGNUM));
+ return gdb_get_reg64(buf, *get_freg(env, n - S390_F0_REGNUM));
default:
return 0;
}
@@ -145,17 +145,17 @@ static int cpu_write_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
/* total number of registers in s390-vx.xml */
#define S390_NUM_VREGS 32
-static int cpu_read_vreg(CPUS390XState *env, uint8_t *mem_buf, int n)
+static int cpu_read_vreg(CPUS390XState *env, GByteArray *buf, int n)
{
int ret;
switch (n) {
case S390_V0L_REGNUM ... S390_V15L_REGNUM:
- ret = gdb_get_reg64(mem_buf, env->vregs[n][1]);
+ ret = gdb_get_reg64(buf, env->vregs[n][1]);
break;
case S390_V16_REGNUM ... S390_V31_REGNUM:
- ret = gdb_get_reg64(mem_buf, env->vregs[n][0]);
- ret += gdb_get_reg64(mem_buf + 8, env->vregs[n][1]);
+ ret = gdb_get_reg64(buf, env->vregs[n][0]);
+ ret += gdb_get_reg64(buf, env->vregs[n][1]);
break;
default:
ret = 0;
@@ -186,11 +186,11 @@ static int cpu_write_vreg(CPUS390XState *env, uint8_t *mem_buf, int n)
#define S390_NUM_C_REGS 16
#ifndef CONFIG_USER_ONLY
-static int cpu_read_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
+static int cpu_read_c_reg(CPUS390XState *env, GByteArray *buf, int n)
{
switch (n) {
case S390_C0_REGNUM ... S390_C15_REGNUM:
- return gdb_get_regl(mem_buf, env->cregs[n]);
+ return gdb_get_regl(buf, env->cregs[n]);
default:
return 0;
}
@@ -223,7 +223,7 @@ static int cpu_write_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
/* total number of registers in s390-virt.xml */
#define S390_NUM_VIRT_REGS 8
-static int cpu_read_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
+static int cpu_read_virt_reg(CPUS390XState *env, GByteArray *mem_buf, int n)
{
switch (n) {
case S390_VIRT_CKC_REGNUM:
@@ -296,9 +296,9 @@ static int cpu_write_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
/* total number of registers in s390-gs.xml */
#define S390_NUM_GS_REGS 4
-static int cpu_read_gs_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
+static int cpu_read_gs_reg(CPUS390XState *env, GByteArray *buf, int n)
{
- return gdb_get_regl(mem_buf, env->gscb[n]);
+ return gdb_get_regl(buf, env->gscb[n]);
}
static int cpu_write_gs_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
diff --git a/target/s390x/internal.h b/target/s390x/internal.h
index d37816104d..8c95c734db 100644
--- a/target/s390x/internal.h
+++ b/target/s390x/internal.h
@@ -292,7 +292,7 @@ uint16_t float128_dcmask(CPUS390XState *env, float128 f1);
/* gdbstub.c */
-int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int s390_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void s390_cpu_gdb_init(CPUState *cs);
diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h
index 452a596e67..dbe58c7888 100644
--- a/target/sh4/cpu.h
+++ b/target/sh4/cpu.h
@@ -208,7 +208,7 @@ void superh_cpu_do_interrupt(CPUState *cpu);
bool superh_cpu_exec_interrupt(CPUState *cpu, int int_req);
void superh_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr superh_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-int superh_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int superh_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int superh_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void superh_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
MMUAccessType access_type,
diff --git a/target/sh4/gdbstub.c b/target/sh4/gdbstub.c
index 44c1679e9d..49fc4a0cc6 100644
--- a/target/sh4/gdbstub.c
+++ b/target/sh4/gdbstub.c
@@ -24,7 +24,7 @@
/* Hint: Use "set architecture sh4" in GDB to see fpu registers */
/* FIXME: We should use XML for this. */
-int superh_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int superh_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
SuperHCPU *cpu = SUPERH_CPU(cs);
CPUSH4State *env = &cpu->env;
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index ae97c7d9f7..b9369398f2 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -571,7 +571,7 @@ extern const VMStateDescription vmstate_sparc_cpu;
void sparc_cpu_do_interrupt(CPUState *cpu);
void sparc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr sparc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-int sparc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int sparc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int sparc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
MMUAccessType access_type,
diff --git a/target/sparc/gdbstub.c b/target/sparc/gdbstub.c
index 8be742b5a3..78dc8dcc98 100644
--- a/target/sparc/gdbstub.c
+++ b/target/sparc/gdbstub.c
@@ -27,7 +27,7 @@
#define gdb_get_rega(buf, val) gdb_get_regl(buf, val)
#endif
-int sparc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int sparc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
SPARCCPU *cpu = SPARC_CPU(cs);
CPUSPARCState *env = &cpu->env;
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 493f4fc80c..c0d69fad96 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -569,7 +569,7 @@ void xtensa_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
void xtensa_count_regs(const XtensaConfig *config,
unsigned *n_regs, unsigned *n_core_regs);
-int xtensa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int xtensa_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int xtensa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
MMUAccessType access_type,
diff --git a/target/xtensa/gdbstub.c b/target/xtensa/gdbstub.c
index 54727881f3..0ee3feabe5 100644
--- a/target/xtensa/gdbstub.c
+++ b/target/xtensa/gdbstub.c
@@ -63,7 +63,7 @@ void xtensa_count_regs(const XtensaConfig *config,
}
}
-int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+int xtensa_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
XtensaCPU *cpu = XTENSA_CPU(cs);
CPUXtensaState *env = &cpu->env;