Merge remote-tracking branch 'afaerber/tags/qom-cpu-for-anthony' into staging

QOM CPUState refactorings

* Fix cpu_memory_rw_debug() breakage in s390x KVM
* Replace final CPUArchState in sysemu/kvm.h
* Introduce model subclasses for XtensaCPU
* Introduce CPUClass::gdb_num[_core]_regs
* Introduce CPUClass::gdb_core_xml_file
* Introduce CPUClass::gdb_{read,write}_register()
* Propagate CPUState further in gdbstub

# gpg: Signature made Fri 26 Jul 2013 05:04:28 PM CDT using RSA key ID 3E7E013F
# gpg: Can't check signature: public key not found

# By Andreas Färber (23) and others
# Via Andreas Färber
* afaerber/tags/qom-cpu-for-anthony: (25 commits)
  cpu: Introduce CPUClass::gdb_core_xml_file for GDB_CORE_XML
  target-cris: Factor out CPUClass::gdb_read_register() hook for v10
  cpu: Introduce CPUClass::gdb_{read,write}_register()
  gdbstub: Replace GET_REG*() macros with gdb_get_reg*() functions
  target-xtensa: Move cpu_gdb_{read,write}_register()
  target-lm32: Move cpu_gdb_{read,write}_register()
  target-s390x: Move cpu_gdb_{read,write}_register()
  target-alpha: Move cpu_gdb_{read,write}_register()
  target-cris: Move cpu_gdb_{read,write}_register()
  target-microblaze: Move cpu_gdb_{read,write}_register()
  target-sh4: Move cpu_gdb_{read,write}_register()
  target-openrisc: Move cpu_gdb_{read,write}_register()
  target-mips: Move cpu_gdb_{read,write}_register()
  target-m68k: Move cpu_gdb_{read,write}_register()
  target-arm: Move cpu_gdb_{read,write}_register()
  target-sparc: Move cpu_gdb_{read,write}_register()
  target-ppc: Move cpu_gdb_{read,write}_register()
  target-i386: Move cpu_gdb_{read,write}_register()
  cpu: Introduce CPUState::gdb_num_regs and CPUClass::gdb_num_core_regs
  gdbstub: Drop dead code in cpu_gdb_{read,write}_register()
  ...
This commit is contained in:
Anthony Liguori
2013-07-26 17:53:19 -05:00
70 changed files with 1993 additions and 1392 deletions
+2 -3
View File
@@ -590,15 +590,14 @@ void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
void cpu_single_step(CPUState *cpu, int enabled)
{
#if defined(TARGET_HAS_ICE)
CPUArchState *env = cpu->env_ptr;
if (cpu->singlestep_enabled != enabled) {
cpu->singlestep_enabled = enabled;
if (kvm_enabled()) {
kvm_update_guest_debug(env, 0);
kvm_update_guest_debug(cpu, 0);
} else {
/* must flush all the translated code to avoid inconsistencies */
/* XXX: only flush what is necessary */
CPUArchState *env = cpu->env_ptr;
tb_flush(env);
}
}
+30 -1352
View File
File diff suppressed because it is too large Load Diff
+45
View File
@@ -39,6 +39,43 @@ static inline int cpu_index(CPUState *cpu)
#endif
}
/* The GDB remote protocol transfers values in target byte order. This means
* we can use the raw memory access routines to access the value buffer.
* Conveniently, these also handle the case where the buffer is mis-aligned.
*/
static inline int gdb_get_reg8(uint8_t *mem_buf, uint8_t val)
{
stb_p(mem_buf, val);
return 1;
}
static inline int gdb_get_reg16(uint8_t *mem_buf, uint16_t val)
{
stw_p(mem_buf, val);
return 2;
}
static inline int gdb_get_reg32(uint8_t *mem_buf, uint32_t val)
{
stl_p(mem_buf, val);
return 4;
}
static inline int gdb_get_reg64(uint8_t *mem_buf, uint64_t val)
{
stq_p(mem_buf, val);
return 8;
}
#if TARGET_LONG_BITS == 64
#define gdb_get_regl(buf, val) gdb_get_reg64(buf, val)
#define ldtul_p(addr) ldq_p(addr)
#else
#define gdb_get_regl(buf, val) gdb_get_reg32(buf, val)
#define ldtul_p(addr) ldl_p(addr)
#endif
#endif
#ifdef CONFIG_USER_ONLY
@@ -47,6 +84,14 @@ int gdbserver_start(int);
int gdbserver_start(const char *port);
#endif
/**
* gdb_has_xml:
* This is an ugly hack to cope with both new and old gdb.
* If gdb sends qXfer:features:read then assume we're talking to a newish
* gdb that understands target descriptions.
*/
extern bool gdb_has_xml;
/* in gdbstub-xml.c, generated by scripts/feature_to_c.sh */
extern const char *const xml_builtin[][2];
+12 -1
View File
@@ -80,7 +80,11 @@ struct TranslationBlock;
* @synchronize_from_tb: Callback for synchronizing state from a TCG
* #TranslationBlock.
* @get_phys_page_debug: Callback for obtaining a physical address.
* @gdb_read_register: Callback for letting GDB read a register.
* @gdb_write_register: Callback for letting GDB write a register.
* @vmsd: State description for migration.
* @gdb_num_core_regs: Number of core registers accessible to GDB.
* @gdb_core_xml_file: File name for core registers GDB XML description.
*
* Represents a CPU family or model.
*/
@@ -108,8 +112,9 @@ typedef struct CPUClass {
void (*set_pc)(CPUState *cpu, vaddr value);
void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb);
hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr);
int (*gdb_read_register)(CPUState *cpu, uint8_t *buf, int reg);
int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
const struct VMStateDescription *vmsd;
int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
int cpuid, void *opaque);
int (*write_elf64_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
@@ -118,6 +123,10 @@ typedef struct CPUClass {
int cpuid, void *opaque);
int (*write_elf32_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
void *opaque);
const struct VMStateDescription *vmsd;
int gdb_num_core_regs;
const char *gdb_core_xml_file;
} CPUClass;
struct KVMState;
@@ -142,6 +151,7 @@ struct kvm_run;
* @env_ptr: Pointer to subclass-specific CPUArchState field.
* @current_tb: Currently executing TB.
* @gdb_regs: Additional GDB registers.
* @gdb_num_regs: Number of total registers accessible to GDB.
* @next_cpu: Next CPU sharing TB cache.
* @kvm_fd: vCPU file descriptor for KVM.
*
@@ -177,6 +187,7 @@ struct CPUState {
void *env_ptr; /* CPUArchState */
struct TranslationBlock *current_tb;
struct GDBRegisterState *gdb_regs;
int gdb_num_regs;
CPUState *next_cpu;
int kvm_fd;
+1 -1
View File
@@ -174,7 +174,7 @@ int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr,
int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr,
target_ulong len, int type);
void kvm_remove_all_breakpoints(CPUState *cpu);
int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap);
int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap);
#ifndef _WIN32
int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset);
#endif
+5 -12
View File
@@ -1883,9 +1883,8 @@ static void kvm_invoke_set_guest_debug(void *data)
&dbg_data->dbg);
}
int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap)
{
CPUState *cpu = ENV_GET_CPU(env);
struct kvm_set_guest_debug_data data;
data.dbg.control = reinject_trap;
@@ -1935,9 +1934,7 @@ int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr,
}
for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
CPUArchState *env = cpu->env_ptr;
err = kvm_update_guest_debug(env, 0);
err = kvm_update_guest_debug(cpu, 0);
if (err) {
return err;
}
@@ -1977,9 +1974,7 @@ int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr,
}
for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
CPUArchState *env = cpu->env_ptr;
err = kvm_update_guest_debug(env, 0);
err = kvm_update_guest_debug(cpu, 0);
if (err) {
return err;
}
@@ -2007,15 +2002,13 @@ void kvm_remove_all_breakpoints(CPUState *cpu)
kvm_arch_remove_all_hw_breakpoints();
for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
CPUArchState *env = cpu->env_ptr;
kvm_update_guest_debug(env, 0);
kvm_update_guest_debug(cpu, 0);
}
}
#else /* !KVM_CAP_SET_GUEST_DEBUG */
int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap)
{
return -EINVAL;
}
+1 -1
View File
@@ -78,7 +78,7 @@ void kvm_setup_guest_memory(void *start, size_t size)
{
}
int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap)
{
return -ENOSYS;
}
+1 -1
View File
@@ -3637,7 +3637,7 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
cpu = ENV_GET_CPU(env);
cpu_reset(ENV_GET_CPU(env));
cpu_reset(cpu);
thread_cpu = cpu;
+22
View File
@@ -157,6 +157,17 @@ static int cpu_common_write_elf64_note(WriteCoreDumpFunction f,
}
static int cpu_common_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg)
{
return 0;
}
static int cpu_common_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg)
{
return 0;
}
void cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
@@ -226,6 +237,14 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
}
}
static void cpu_common_initfn(Object *obj)
{
CPUState *cpu = CPU(obj);
CPUClass *cc = CPU_GET_CLASS(obj);
cpu->gdb_num_regs = cc->gdb_num_core_regs;
}
static int64_t cpu_common_get_arch_id(CPUState *cpu)
{
return cpu->cpu_index;
@@ -245,6 +264,8 @@ static void cpu_class_init(ObjectClass *klass, void *data)
k->write_elf32_note = cpu_common_write_elf32_note;
k->write_elf64_qemunote = cpu_common_write_elf64_qemunote;
k->write_elf64_note = cpu_common_write_elf64_note;
k->gdb_read_register = cpu_common_gdb_read_register;
k->gdb_write_register = cpu_common_gdb_write_register;
dc->realize = cpu_common_realizefn;
dc->no_user = 1;
}
@@ -253,6 +274,7 @@ static const TypeInfo cpu_type_info = {
.name = TYPE_CPU,
.parent = TYPE_DEVICE,
.instance_size = sizeof(CPUState),
.instance_init = cpu_common_initfn,
.abstract = true,
.class_size = sizeof(CPUClass),
.class_init = cpu_class_init,
+1
View File
@@ -7,6 +7,7 @@ stub-obj-y += fdset-add-fd.o
stub-obj-y += fdset-find-fd.o
stub-obj-y += fdset-get-fd.o
stub-obj-y += fdset-remove-fd.o
stub-obj-y += gdbstub.o
stub-obj-y += get-fd.o
stub-obj-y += get-vm-name.o
stub-obj-y += iothread-lock.o
+5
View File
@@ -0,0 +1,5 @@
#include "qemu-common.h"
const char *const xml_builtin[][2] = {
{ NULL, NULL }
};
+1
View File
@@ -1,3 +1,4 @@
obj-$(CONFIG_SOFTMMU) += machine.o
obj-y += translate.o helper.o cpu.o
obj-y += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
obj-y += gdbstub.o
+2
View File
@@ -82,5 +82,7 @@ void alpha_cpu_do_interrupt(CPUState *cpu);
void alpha_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
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_write_register(CPUState *cpu, uint8_t *buf, int reg);
#endif
+3
View File
@@ -271,11 +271,14 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
cc->do_interrupt = alpha_cpu_do_interrupt;
cc->dump_state = alpha_cpu_dump_state;
cc->set_pc = alpha_cpu_set_pc;
cc->gdb_read_register = alpha_cpu_gdb_read_register;
cc->gdb_write_register = alpha_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->do_unassigned_access = alpha_cpu_unassigned_access;
cc->get_phys_page_debug = alpha_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_alpha_cpu;
#endif
cc->gdb_num_core_regs = 67;
}
static const TypeInfo alpha_cpu_type_info = {
+93
View File
@@ -0,0 +1,93 @@
/*
* Alpha gdb server stub
*
* Copyright (c) 2003-2005 Fabrice Bellard
* Copyright (c) 2013 SUSE LINUX Products GmbH
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "qemu-common.h"
#include "exec/gdbstub.h"
int alpha_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
{
AlphaCPU *cpu = ALPHA_CPU(cs);
CPUAlphaState *env = &cpu->env;
uint64_t val;
CPU_DoubleU d;
switch (n) {
case 0 ... 30:
val = env->ir[n];
break;
case 32 ... 62:
d.d = env->fir[n - 32];
val = d.ll;
break;
case 63:
val = cpu_alpha_load_fpcr(env);
break;
case 64:
val = env->pc;
break;
case 66:
val = env->unique;
break;
case 31:
case 65:
/* 31 really is the zero register; 65 is unassigned in the
gdb protocol, but is still required to occupy 8 bytes. */
val = 0;
break;
default:
return 0;
}
return gdb_get_regl(mem_buf, val);
}
int alpha_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
AlphaCPU *cpu = ALPHA_CPU(cs);
CPUAlphaState *env = &cpu->env;
target_ulong tmp = ldtul_p(mem_buf);
CPU_DoubleU d;
switch (n) {
case 0 ... 30:
env->ir[n] = tmp;
break;
case 32 ... 62:
d.ll = tmp;
env->fir[n - 32] = d.d;
break;
case 63:
cpu_alpha_store_fpcr(env, tmp);
break;
case 64:
env->pc = tmp;
break;
case 66:
env->unique = tmp;
break;
case 31:
case 65:
/* 31 really is the zero register; 65 is unassigned in the
gdb protocol, but is still required to occupy 8 bytes. */
break;
default:
return 0;
}
return 8;
}
+1
View File
@@ -4,3 +4,4 @@ obj-$(CONFIG_KVM) += kvm.o
obj-$(CONFIG_NO_KVM) += kvm-stub.o
obj-y += translate.o op_helper.o helper.o cpu.o
obj-y += neon_helper.o iwmmxt_helper.o
obj-y += gdbstub.o
+3
View File
@@ -149,4 +149,7 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
hwaddr arm_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int arm_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int arm_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
#endif
+4
View File
@@ -824,10 +824,14 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
cc->do_interrupt = arm_cpu_do_interrupt;
cc->dump_state = arm_cpu_dump_state;
cc->set_pc = arm_cpu_set_pc;
cc->gdb_read_register = arm_cpu_gdb_read_register;
cc->gdb_write_register = arm_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = arm_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_arm_cpu;
#endif
cc->gdb_num_core_regs = 26;
cc->gdb_core_xml_file = "arm-core.xml";
}
static void cpu_register(const ARMCPUInfo *info)
+102
View File
@@ -0,0 +1,102 @@
/*
* ARM gdb server stub
*
* Copyright (c) 2003-2005 Fabrice Bellard
* Copyright (c) 2013 SUSE LINUX Products GmbH
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "qemu-common.h"
#include "exec/gdbstub.h"
/* Old gdb always expect FPA registers. Newer (xml-aware) gdb only expect
whatever the target description contains. Due to a historical mishap
the FPA registers appear in between core integer regs and the CPSR.
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)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
if (n < 16) {
/* Core integer register. */
return gdb_get_reg32(mem_buf, env->regs[n]);
}
if (n < 24) {
/* FPA registers. */
if (gdb_has_xml) {
return 0;
}
memset(mem_buf, 0, 12);
return 12;
}
switch (n) {
case 24:
/* FPA status register. */
if (gdb_has_xml) {
return 0;
}
return gdb_get_reg32(mem_buf, 0);
case 25:
/* CPSR */
return gdb_get_reg32(mem_buf, cpsr_read(env));
}
/* Unknown register. */
return 0;
}
int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
uint32_t tmp;
tmp = ldl_p(mem_buf);
/* Mask out low bit of PC to workaround gdb bugs. This will probably
cause problems if we ever implement the Jazelle DBX extensions. */
if (n == 15) {
tmp &= ~1;
}
if (n < 16) {
/* Core integer register. */
env->regs[n] = tmp;
return 4;
}
if (n < 24) { /* 16-23 */
/* FPA registers (ignored). */
if (gdb_has_xml) {
return 0;
}
return 12;
}
switch (n) {
case 24:
/* FPA status register (ignored). */
if (gdb_has_xml) {
return 0;
}
return 4;
case 25:
/* CPSR */
cpsr_write(env, tmp, 0xffffffff);
return 4;
}
/* Unknown register. */
return 0;
}
+1
View File
@@ -1,2 +1,3 @@
obj-y += translate.o op_helper.o helper.o cpu.o
obj-y += gdbstub.o
obj-$(CONFIG_SOFTMMU) += mmu.o machine.o

Some files were not shown because too many files have changed in this diff Show More