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

QOM CPUState refactorings

* Fix NULL pointer dereference in gdbstub
* Introduce vaddr type
* Introduce CPUClass::set_pc()
* Introduce CPUClass::synchronize_from_tb()
* Introduce CPUClass::get_phys_page_debug()
* Introduce CPUClass::memory_rw_debug()
* Move singlestep_enabled and gdb_regs fields out of CPU_COMMON
* Adopt CPUState in more APIs
* Propagate CPUState in gdbstub

# gpg: Signature made Mon 22 Jul 2013 07:50:17 PM CDT using RSA key ID 3E7E013F
# gpg: Can't check signature: public key not found

# By Andreas Färber (21) and others
# Via Andreas Färber
* afaerber/tags/qom-cpu-for-anthony: (24 commits)
  linux-user: Use X86CPU property to retrieve CPUID family
  gdbstub: Change gdb_register_coprocessor() argument to CPUState
  cpu: Move gdb_regs field from CPU_COMMON to CPUState
  gdbstub: Change GDBState::{c,g}_cpu and find_cpu() to CPUState
  cpu: Introduce CPUClass::memory_rw_debug() for target_memory_rw_debug()
  exec: Change cpu_memory_rw_debug() argument to CPUState
  cpu: Turn cpu_get_phys_page_debug() into a CPUClass hook
  gdbstub: Change gdb_{read,write}_register() argument to CPUState
  gdbstub: Change gdb_handlesig() argument to CPUState
  gdbstub: Change syscall callback argument to CPUState
  kvm: Change kvm_{insert,remove}_breakpoint() argument to CPUState
  cpu: Change cpu_single_step() argument to CPUState
  gdbstub: Update gdb_handlesig() and gdb_signalled() Coding Style
  cpu: Move singlestep_enabled field from CPU_COMMON to CPUState
  target-alpha: Copy implver to DisasContext
  target-alpha: Copy singlestep_enabled to DisasContext
  cpu: Introduce CPUClass::synchronize_from_tb() for cpu_pc_from_tb()
  target-unicore32: Implement CPUClass::set_pc()
  target-moxie: Implement CPUClass::set_pc()
  target-m68k: Implement CPUClass::set_pc()
  ...
This commit is contained in:
Anthony Liguori
2013-07-23 10:57:04 -05:00
104 changed files with 783 additions and 550 deletions
+17 -2
View File
@@ -40,8 +40,23 @@ speaking, the size of guest memory can always fit into ram_addr_t but
it would not be correct to store an actual guest physical address in a
ram_addr_t.
Use target_ulong (or abi_ulong) for CPU virtual addresses, however
devices should not need to use target_ulong.
For CPU virtual addresses there are several possible types.
vaddr is the best type to use to hold a CPU virtual address in
target-independent code. It is guaranteed to be large enough to hold a
virtual address for any target, and it does not change size from target
to target. It is always unsigned.
target_ulong is a type the size of a virtual address on the CPU; this means
it may be 32 or 64 bits depending on which target is being built. It should
therefore be used only in target-specific code, and in some
performance-critical built-per-target core code such as the TLB code.
There is also a signed version, target_long.
abi_ulong is for the *-user targets, and represents a type the size of
'void *' in that target's ABI. (This may not be the same as the size of a
full CPU virtual address in the case of target ABIs which use 32 bit pointers
on 64 bit CPUs, like sparc32plus.) Definitions of structures that must match
the target's ABI must use this type for anything that on the target is defined
to be an 'unsigned long' or a pointer type.
There is also a signed version, abi_long.
Of course, take all of the above with a grain of salt. If you're about
to use some system interface that requires a type like size_t, pid_t or
+6 -4
View File
@@ -643,7 +643,7 @@ void cpu_loop(CPUSPARCState *env)
{
int sig;
sig = gdb_handlesig (env, TARGET_SIGTRAP);
sig = gdb_handlesig(cs, TARGET_SIGTRAP);
#if 0
if (sig)
{
@@ -738,6 +738,7 @@ int main(int argc, char **argv)
struct image_info info1, *info = &info1;
TaskState ts1, *ts = &ts1;
CPUArchState *env;
CPUState *cpu;
int optind;
const char *r;
int gdbstub_port = 0;
@@ -912,10 +913,11 @@ int main(int argc, char **argv)
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
cpu = ENV_GET_CPU(env);
#if defined(TARGET_SPARC) || defined(TARGET_PPC)
cpu_reset(ENV_GET_CPU(env));
cpu_reset(cpu);
#endif
thread_cpu = ENV_GET_CPU(env);
thread_cpu = cpu;
if (getenv("QEMU_STRACE")) {
do_strace = 1;
@@ -1134,7 +1136,7 @@ int main(int argc, char **argv)
if (gdbstub_port) {
gdbserver_start (gdbstub_port);
gdb_handlesig(env, 0);
gdb_handlesig(cpu, 0);
}
cpu_loop(env);
/* never exits */
+8 -2
View File
@@ -59,8 +59,14 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr)
* counter hit zero); we must restore the guest PC to the address
* of the start of the TB.
*/
CPUClass *cc = CPU_GET_CLASS(cpu);
TranslationBlock *tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
cpu_pc_from_tb(env, tb);
if (cc->synchronize_from_tb) {
cc->synchronize_from_tb(cpu, tb);
} else {
assert(cc->set_pc);
cc->set_pc(cpu, tb->pc);
}
}
if ((next_tb & TB_EXIT_MASK) == TB_EXIT_REQUESTED) {
/* We were asked to stop executing TBs (probably a pending
@@ -291,7 +297,7 @@ int cpu_exec(CPUArchState *env)
for(;;) {
interrupt_request = cpu->interrupt_request;
if (unlikely(interrupt_request)) {
if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) {
/* Mask out external interrupts for this step. */
interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
}
+2 -4
View File
@@ -1186,7 +1186,7 @@ static void tcg_exec_all(void)
CPUArchState *env = cpu->env_ptr;
qemu_clock_enable(vm_clock,
(env->singlestep_enabled & SSTEP_NOTIMER) == 0);
(cpu->singlestep_enabled & SSTEP_NOTIMER) == 0);
if (cpu_can_run(cpu)) {
r = tcg_cpu_exec(env);
@@ -1285,7 +1285,6 @@ void qmp_memsave(int64_t addr, int64_t size, const char *filename,
{
FILE *f;
uint32_t l;
CPUArchState *env;
CPUState *cpu;
uint8_t buf[1024];
@@ -1299,7 +1298,6 @@ void qmp_memsave(int64_t addr, int64_t size, const char *filename,
"a CPU number");
return;
}
env = cpu->env_ptr;
f = fopen(filename, "wb");
if (!f) {
@@ -1311,7 +1309,7 @@ void qmp_memsave(int64_t addr, int64_t size, const char *filename,
l = sizeof(buf);
if (l > size)
l = size;
cpu_memory_rw_debug(env, addr, buf, l, 0);
cpu_memory_rw_debug(cpu, addr, buf, l, 0);
if (fwrite(buf, 1, l, f) != l) {
error_set(errp, QERR_IO_ERROR);
goto exit;
+2 -2
View File
@@ -39,7 +39,7 @@ target_read_memory (bfd_vma memaddr,
{
CPUDebug *s = container_of(info, CPUDebug, info);
cpu_memory_rw_debug(s->env, memaddr, myaddr, length, 0);
cpu_memory_rw_debug(ENV_GET_CPU(s->env), memaddr, myaddr, length, 0);
return 0;
}
@@ -392,7 +392,7 @@ monitor_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length,
if (monitor_disas_is_physical) {
cpu_physical_memory_read(memaddr, myaddr, length);
} else {
cpu_memory_rw_debug(s->env, memaddr,myaddr, length, 0);
cpu_memory_rw_debug(ENV_GET_CPU(s->env), memaddr, myaddr, length, 0);
}
return 0;
}
+20 -16
View File
@@ -415,14 +415,14 @@ void cpu_exec_init(CPUArchState *env)
#if defined(TARGET_HAS_ICE)
#if defined(CONFIG_USER_ONLY)
static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
{
tb_invalidate_phys_page_range(pc, pc + 1, 0);
}
#else
static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
{
tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc) |
tb_invalidate_phys_addr(cpu_get_phys_page_debug(cpu, pc) |
(pc & ~TARGET_PAGE_MASK));
}
#endif
@@ -525,15 +525,17 @@ int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
bp->flags = flags;
/* keep all GDB-injected breakpoints in front */
if (flags & BP_GDB)
if (flags & BP_GDB) {
QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
else
} else {
QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
}
breakpoint_invalidate(env, pc);
breakpoint_invalidate(ENV_GET_CPU(env), pc);
if (breakpoint)
if (breakpoint) {
*breakpoint = bp;
}
return 0;
#else
return -ENOSYS;
@@ -564,7 +566,7 @@ void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
#if defined(TARGET_HAS_ICE)
QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
breakpoint_invalidate(env, breakpoint->pc);
breakpoint_invalidate(ENV_GET_CPU(env), breakpoint->pc);
g_free(breakpoint);
#endif
@@ -585,14 +587,16 @@ void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
/* enable or disable single step mode. EXCP_DEBUG is returned by the
CPU loop after each instruction */
void cpu_single_step(CPUArchState *env, int enabled)
void cpu_single_step(CPUState *cpu, int enabled)
{
#if defined(TARGET_HAS_ICE)
if (env->singlestep_enabled != enabled) {
env->singlestep_enabled = enabled;
if (kvm_enabled())
CPUArchState *env = cpu->env_ptr;
if (cpu->singlestep_enabled != enabled) {
cpu->singlestep_enabled = enabled;
if (kvm_enabled()) {
kvm_update_guest_debug(env, 0);
else {
} else {
/* must flush all the translated code to avoid inconsistencies */
/* XXX: only flush what is necessary */
tb_flush(env);
@@ -1831,7 +1835,7 @@ MemoryRegion *get_system_io(void)
/* physical memory access (slow version, mainly for debug) */
#if defined(CONFIG_USER_ONLY)
int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
uint8_t *buf, int len, int is_write)
{
int l, flags;
@@ -2602,7 +2606,7 @@ void stq_be_phys(hwaddr addr, uint64_t val)
}
/* virtual memory access for debug (includes writing to ROM) */
int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
uint8_t *buf, int len, int is_write)
{
int l;
@@ -2611,7 +2615,7 @@ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
while (len > 0) {
page = addr & TARGET_PAGE_MASK;
phys_addr = cpu_get_phys_page_debug(env, page);
phys_addr = cpu_get_phys_page_debug(cpu, page);
/* if no physical page mapped, return an error */
if (phys_addr == -1)
return -1;
+125 -141
View File
File diff suppressed because it is too large Load Diff
+41 -37
View File
@@ -146,6 +146,7 @@ static void update_guest_rom_state(VAPICROMState *s)
static int find_real_tpr_addr(VAPICROMState *s, CPUX86State *env)
{
CPUState *cs = CPU(x86_env_get_cpu(env));
hwaddr paddr;
target_ulong addr;
@@ -158,7 +159,7 @@ static int find_real_tpr_addr(VAPICROMState *s, CPUX86State *env)
* virtual address space for the APIC mapping.
*/
for (addr = 0xfffff000; addr >= 0x80000000; addr -= TARGET_PAGE_SIZE) {
paddr = cpu_get_phys_page_debug(env, addr);
paddr = cpu_get_phys_page_debug(cs, addr);
if (paddr != APIC_DEFAULT_ADDRESS) {
continue;
}
@@ -187,9 +188,10 @@ static bool opcode_matches(uint8_t *opcode, const TPRInstruction *instr)
modrm_reg(opcode[1]) == instr->modrm_reg);
}
static int evaluate_tpr_instruction(VAPICROMState *s, CPUX86State *env,
static int evaluate_tpr_instruction(VAPICROMState *s, X86CPU *cpu,
target_ulong *pip, TPRAccess access)
{
CPUState *cs = CPU(cpu);
const TPRInstruction *instr;
target_ulong ip = *pip;
uint8_t opcode[2];
@@ -210,7 +212,7 @@ static int evaluate_tpr_instruction(VAPICROMState *s, CPUX86State *env,
* RSP, used by the patched instruction, is zero, so the guest gets a
* double fault and dies.
*/
if (env->regs[R_ESP] == 0) {
if (cpu->env.regs[R_ESP] == 0) {
return -1;
}
@@ -225,7 +227,7 @@ static int evaluate_tpr_instruction(VAPICROMState *s, CPUX86State *env,
if (instr->access != access) {
continue;
}
if (cpu_memory_rw_debug(env, ip - instr->length, opcode,
if (cpu_memory_rw_debug(cs, ip - instr->length, opcode,
sizeof(opcode), 0) < 0) {
return -1;
}
@@ -236,7 +238,7 @@ static int evaluate_tpr_instruction(VAPICROMState *s, CPUX86State *env,
}
return -1;
} else {
if (cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0) < 0) {
if (cpu_memory_rw_debug(cs, ip, opcode, sizeof(opcode), 0) < 0) {
return -1;
}
for (i = 0; i < ARRAY_SIZE(tpr_instr); i++) {
@@ -253,7 +255,7 @@ instruction_ok:
* Grab the virtual TPR address from the instruction
* and update the cached values.
*/
if (cpu_memory_rw_debug(env, ip + instr->addr_offset,
if (cpu_memory_rw_debug(cs, ip + instr->addr_offset,
(void *)&real_tpr_addr,
sizeof(real_tpr_addr), 0) < 0) {
return -1;
@@ -271,6 +273,7 @@ instruction_ok:
static int update_rom_mapping(VAPICROMState *s, CPUX86State *env, target_ulong ip)
{
CPUState *cs = CPU(x86_env_get_cpu(env));
hwaddr paddr;
uint32_t rom_state_vaddr;
uint32_t pos, patch, offset;
@@ -287,7 +290,7 @@ static int update_rom_mapping(VAPICROMState *s, CPUX86State *env, target_ulong i
/* find out virtual address of the ROM */
rom_state_vaddr = s->rom_state_paddr + (ip & 0xf0000000);
paddr = cpu_get_phys_page_debug(env, rom_state_vaddr);
paddr = cpu_get_phys_page_debug(cs, rom_state_vaddr);
if (paddr == -1) {
return -1;
}
@@ -332,8 +335,9 @@ static int update_rom_mapping(VAPICROMState *s, CPUX86State *env, target_ulong i
* cannot be accessed or is considered invalid. This also ensures that we are
* not patching the wrong guest.
*/
static int get_kpcr_number(CPUX86State *env)
static int get_kpcr_number(X86CPU *cpu)
{
CPUX86State *env = &cpu->env;
struct kpcr {
uint8_t fill1[0x1c];
uint32_t self;
@@ -341,7 +345,7 @@ static int get_kpcr_number(CPUX86State *env)
uint8_t number;
} QEMU_PACKED kpcr;
if (cpu_memory_rw_debug(env, env->segs[R_FS].base,
if (cpu_memory_rw_debug(CPU(cpu), env->segs[R_FS].base,
(void *)&kpcr, sizeof(kpcr), 0) < 0 ||
kpcr.self != env->segs[R_FS].base) {
return -1;
@@ -349,9 +353,9 @@ static int get_kpcr_number(CPUX86State *env)
return kpcr.number;
}
static int vapic_enable(VAPICROMState *s, CPUX86State *env)
static int vapic_enable(VAPICROMState *s, X86CPU *cpu)
{
int cpu_number = get_kpcr_number(env);
int cpu_number = get_kpcr_number(cpu);
hwaddr vapic_paddr;
static const uint8_t enabled = 1;
@@ -362,26 +366,26 @@ static int vapic_enable(VAPICROMState *s, CPUX86State *env)
(((hwaddr)cpu_number) << VAPIC_CPU_SHIFT);
cpu_physical_memory_rw(vapic_paddr + offsetof(VAPICState, enabled),
(void *)&enabled, sizeof(enabled), 1);
apic_enable_vapic(env->apic_state, vapic_paddr);
apic_enable_vapic(cpu->env.apic_state, vapic_paddr);
s->state = VAPIC_ACTIVE;
return 0;
}
static void patch_byte(CPUX86State *env, target_ulong addr, uint8_t byte)
static void patch_byte(X86CPU *cpu, target_ulong addr, uint8_t byte)
{
cpu_memory_rw_debug(env, addr, &byte, 1, 1);
cpu_memory_rw_debug(CPU(cpu), addr, &byte, 1, 1);
}
static void patch_call(VAPICROMState *s, CPUX86State *env, target_ulong ip,
static void patch_call(VAPICROMState *s, X86CPU *cpu, target_ulong ip,
uint32_t target)
{
uint32_t offset;
offset = cpu_to_le32(target - ip - 5);
patch_byte(env, ip, 0xe8); /* call near */
cpu_memory_rw_debug(env, ip + 1, (void *)&offset, sizeof(offset), 1);
patch_byte(cpu, ip, 0xe8); /* call near */
cpu_memory_rw_debug(CPU(cpu), ip + 1, (void *)&offset, sizeof(offset), 1);
}
static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
@@ -409,32 +413,32 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
pause_all_vcpus();
cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0);
cpu_memory_rw_debug(cs, ip, opcode, sizeof(opcode), 0);
switch (opcode[0]) {
case 0x89: /* mov r32 to r/m32 */
patch_byte(env, ip, 0x50 + modrm_reg(opcode[1])); /* push reg */
patch_call(s, env, ip + 1, handlers->set_tpr);
patch_byte(cpu, ip, 0x50 + modrm_reg(opcode[1])); /* push reg */
patch_call(s, cpu, ip + 1, handlers->set_tpr);
break;
case 0x8b: /* mov r/m32 to r32 */
patch_byte(env, ip, 0x90);
patch_call(s, env, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
patch_byte(cpu, ip, 0x90);
patch_call(s, cpu, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
break;
case 0xa1: /* mov abs to eax */
patch_call(s, env, ip, handlers->get_tpr[0]);
patch_call(s, cpu, ip, handlers->get_tpr[0]);
break;
case 0xa3: /* mov eax to abs */
patch_call(s, env, ip, handlers->set_tpr_eax);
patch_call(s, cpu, ip, handlers->set_tpr_eax);
break;
case 0xc7: /* mov imm32, r/m32 (c7/0) */
patch_byte(env, ip, 0x68); /* push imm32 */
cpu_memory_rw_debug(env, ip + 6, (void *)&imm32, sizeof(imm32), 0);
cpu_memory_rw_debug(env, ip + 1, (void *)&imm32, sizeof(imm32), 1);
patch_call(s, env, ip + 5, handlers->set_tpr);
patch_byte(cpu, ip, 0x68); /* push imm32 */
cpu_memory_rw_debug(cs, ip + 6, (void *)&imm32, sizeof(imm32), 0);
cpu_memory_rw_debug(cs, ip + 1, (void *)&imm32, sizeof(imm32), 1);
patch_call(s, cpu, ip + 5, handlers->set_tpr);
break;
case 0xff: /* push r/m32 */
patch_byte(env, ip, 0x50); /* push eax */
patch_call(s, env, ip + 1, handlers->get_tpr_stack);
patch_byte(cpu, ip, 0x50); /* push eax */
patch_call(s, cpu, ip + 1, handlers->get_tpr_stack);
break;
default:
abort();
@@ -458,16 +462,16 @@ void vapic_report_tpr_access(DeviceState *dev, CPUState *cs, target_ulong ip,
cpu_synchronize_state(cs);
if (evaluate_tpr_instruction(s, env, &ip, access) < 0) {
if (evaluate_tpr_instruction(s, cpu, &ip, access) < 0) {
if (s->state == VAPIC_ACTIVE) {
vapic_enable(s, env);
vapic_enable(s, cpu);
}
return;
}
if (update_rom_mapping(s, env, ip) < 0) {
return;
}
if (vapic_enable(s, env) < 0) {
if (vapic_enable(s, cpu) < 0) {
return;
}
patch_instruction(s, cpu, ip);
@@ -667,8 +671,8 @@ static void vapic_write(void *opaque, hwaddr addr, uint64_t data,
* accurate.
*/
pause_all_vcpus();
patch_byte(env, env->eip - 2, 0x66);
patch_byte(env, env->eip - 1, 0x90);
patch_byte(cpu, env->eip - 2, 0x66);
patch_byte(cpu, env->eip - 1, 0x90);
resume_all_vcpus();
}
@@ -681,7 +685,7 @@ static void vapic_write(void *opaque, hwaddr addr, uint64_t data,
if (find_real_tpr_addr(s, env) < 0) {
break;
}
vapic_enable(s, env);
vapic_enable(s, cpu);
break;
default:
case 4:
@@ -722,7 +726,7 @@ static void do_vapic_enable(void *data)
VAPICROMState *s = data;
X86CPU *cpu = X86_CPU(first_cpu);
vapic_enable(s, &cpu->env);
vapic_enable(s, cpu);
}
static int vapic_post_load(void *opaque, int version_id)
+5 -3
View File
@@ -144,9 +144,11 @@ static void lx60_net_init(MemoryRegion *address_space,
memory_region_add_subregion(address_space, buffers, ram);
}
static uint64_t translate_phys_addr(void *env, uint64_t addr)
static uint64_t translate_phys_addr(void *opaque, uint64_t addr)
{
return cpu_get_phys_page_debug(env, addr);
XtensaCPU *cpu = opaque;
return cpu_get_phys_page_debug(CPU(cpu), addr);
}
static void lx60_reset(void *opaque)
@@ -252,7 +254,7 @@ static void lx_init(const LxBoardDesc *board, QEMUMachineInitArgs *args)
}
uint64_t elf_entry;
uint64_t elf_lowaddr;
int success = load_elf(kernel_filename, translate_phys_addr, env,
int success = load_elf(kernel_filename, translate_phys_addr, cpu,
&elf_entry, &elf_lowaddr, NULL, be, ELF_MACHINE, 0);
if (success > 0) {
env->pc = elf_entry;
+6 -4
View File
@@ -32,9 +32,11 @@
#include "exec/memory.h"
#include "exec/address-spaces.h"
static uint64_t translate_phys_addr(void *env, uint64_t addr)
static uint64_t translate_phys_addr(void *opaque, uint64_t addr)
{
return cpu_get_phys_page_debug(env, addr);
XtensaCPU *cpu = opaque;
return cpu_get_phys_page_debug(CPU(cpu), addr);
}
static void sim_reset(void *opaque)
@@ -88,10 +90,10 @@ static void xtensa_sim_init(QEMUMachineInitArgs *args)
uint64_t elf_entry;
uint64_t elf_lowaddr;
#ifdef TARGET_WORDS_BIGENDIAN
int success = load_elf(kernel_filename, translate_phys_addr, env,
int success = load_elf(kernel_filename, translate_phys_addr, cpu,
&elf_entry, &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
#else
int success = load_elf(kernel_filename, translate_phys_addr, env,
int success = load_elf(kernel_filename, translate_phys_addr, cpu,
&elf_entry, &elf_lowaddr, NULL, 0, ELF_MACHINE, 0);
#endif
if (success > 0) {
+2 -12
View File
@@ -22,6 +22,7 @@
#include "qemu-common.h"
#include "exec/cpu-common.h"
#include "qemu/thread.h"
#include "qom/cpu.h"
/* some important defines:
*
@@ -428,19 +429,8 @@ int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr,
void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint);
void cpu_watchpoint_remove_all(CPUArchState *env, int mask);
#define SSTEP_ENABLE 0x1 /* Enable simulated HW single stepping */
#define SSTEP_NOIRQ 0x2 /* Do not use IRQ while single stepping */
#define SSTEP_NOTIMER 0x4 /* Do not Timers while single stepping */
void cpu_single_step(CPUArchState *env, int enabled);
#if !defined(CONFIG_USER_ONLY)
/* Return the physical page corresponding to a virtual one. Use it
only for debugging because no protection checks are done. Return -1
if no page found. */
hwaddr cpu_get_phys_page_debug(CPUArchState *env, target_ulong addr);
/* memory API */
extern ram_addr_t ram_size;
@@ -494,7 +484,7 @@ void qemu_mutex_lock_ramlist(void);
void qemu_mutex_unlock_ramlist(void);
#endif /* !CONFIG_USER_ONLY */
int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
uint8_t *buf, int len, int is_write);
#endif /* CPU_ALL_H */
-3
View File
@@ -170,13 +170,10 @@ typedef struct CPUWatchpoint {
/* from this point: preserved by CPU reset */ \
/* ice debug support */ \
QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints; \
int singlestep_enabled; \
\
QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints; \
CPUWatchpoint *watchpoint_hit; \
\
struct GDBRegisterState *gdb_regs; \
\
/* Core interrupt code */ \
sigjmp_buf jmp_env; \
int exception_index; \
+3 -3
View File
@@ -11,7 +11,7 @@
#define GDB_WATCHPOINT_ACCESS 4
#ifdef NEED_CPU_H
typedef void (*gdb_syscall_complete_cb)(CPUArchState *env,
typedef void (*gdb_syscall_complete_cb)(CPUState *cpu,
target_ulong ret, target_ulong err);
void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...);
@@ -20,13 +20,13 @@ void gdb_set_stop_cpu(CPUState *cpu);
void gdb_exit(CPUArchState *, int);
#ifdef CONFIG_USER_ONLY
int gdb_queuesig (void);
int gdb_handlesig (CPUArchState *, int);
int gdb_handlesig(CPUState *, int);
void gdb_signalled(CPUArchState *, int);
void gdbserver_fork(CPUArchState *);
#endif
/* Get or set a register. Returns the size of the register. */
typedef int (*gdb_reg_cb)(CPUArchState *env, uint8_t *buf, int reg);
void gdb_register_coprocessor(CPUArchState *env,
void gdb_register_coprocessor(CPUState *cpu,
gdb_reg_cb get_reg, gdb_reg_cb set_reg,
int num_regs, const char *xml, int g_pos);
+10 -8
View File
@@ -13,14 +13,14 @@ static inline uint32_t softmmu_tget32(CPUArchState *env, uint32_t addr)
{
uint32_t val;
cpu_memory_rw_debug(env, addr, (uint8_t *)&val, 4, 0);
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 4, 0);
return tswap32(val);
}
static inline uint32_t softmmu_tget8(CPUArchState *env, uint32_t addr)
{
uint8_t val;
cpu_memory_rw_debug(env, addr, &val, 1, 0);
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, &val, 1, 0);
return val;
}
@@ -31,7 +31,7 @@ static inline uint32_t softmmu_tget8(CPUArchState *env, uint32_t addr)
static inline void softmmu_tput32(CPUArchState *env, uint32_t addr, uint32_t val)
{
val = tswap32(val);
cpu_memory_rw_debug(env, addr, (uint8_t *)&val, 4, 1);
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 4, 1);
}
#define put_user_u32(arg, p) ({ softmmu_tput32(env, p, arg) ; 0; })
#define put_user_ual(arg, p) put_user_u32(arg, p)
@@ -42,8 +42,9 @@ static void *softmmu_lock_user(CPUArchState *env, uint32_t addr, uint32_t len,
uint8_t *p;
/* TODO: Make this something that isn't fixed size. */
p = malloc(len);
if (p && copy)
cpu_memory_rw_debug(env, addr, p, len, 0);
if (p && copy) {
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, p, len, 0);
}
return p;
}
#define lock_user(type, p, len, copy) softmmu_lock_user(env, p, len, copy)
@@ -58,7 +59,7 @@ static char *softmmu_lock_user_string(CPUArchState *env, uint32_t addr)
return NULL;
}
do {
cpu_memory_rw_debug(env, addr, &c, 1, 0);
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, &c, 1, 0);
addr++;
*(p++) = c;
} while (c);
@@ -68,8 +69,9 @@ static char *softmmu_lock_user_string(CPUArchState *env, uint32_t addr)
static void softmmu_unlock_user(CPUArchState *env, void *p, target_ulong addr,
target_ulong len)
{
if (len)
cpu_memory_rw_debug(env, addr, p, len, 1);
if (len) {
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, p, len, 1);
}
free(p);
}
#define unlock_user(s, args, len) softmmu_unlock_user(env, s, args, len)
+60 -53
View File
@@ -29,6 +29,18 @@
typedef int (*WriteCoreDumpFunction)(void *buf, size_t size, void *opaque);
/**
* vaddr:
* Type wide enough to contain any #target_ulong virtual address.
*/
typedef uint64_t vaddr;
#define VADDR_PRId PRId64
#define VADDR_PRIu PRIu64
#define VADDR_PRIo PRIo64
#define VADDR_PRIx PRIx64
#define VADDR_PRIX PRIX64
#define VADDR_MAX UINT64_MAX
/**
* SECTION:cpu
* @section_id: QEMU-cpu
@@ -48,6 +60,8 @@ typedef void (*CPUUnassignedAccess)(CPUState *cpu, hwaddr addr,
bool is_write, bool is_exec, int opaque,
unsigned size);
struct TranslationBlock;
/**
* CPUClass:
* @class_by_name: Callback to map -cpu command line model name to an
@@ -56,11 +70,16 @@ typedef void (*CPUUnassignedAccess)(CPUState *cpu, hwaddr addr,
* @reset_dump_flags: #CPUDumpFlags to use for reset logging.
* @do_interrupt: Callback for interrupt handling.
* @do_unassigned_access: Callback for unassigned access handling.
* @memory_rw_debug: Callback for GDB memory access.
* @dump_state: Callback for dumping state.
* @dump_statistics: Callback for dumping statistics.
* @get_arch_id: Callback for getting architecture-dependent CPU ID.
* @get_paging_enabled: Callback for inquiring whether paging is enabled.
* @get_memory_mapping: Callback for obtaining the memory mappings.
* @set_pc: Callback for setting the Program Counter register.
* @synchronize_from_tb: Callback for synchronizing state from a TCG
* #TranslationBlock.
* @get_phys_page_debug: Callback for obtaining a physical address.
* @vmsd: State description for migration.
*
* Represents a CPU family or model.
@@ -76,6 +95,8 @@ typedef struct CPUClass {
int reset_dump_flags;
void (*do_interrupt)(CPUState *cpu);
CPUUnassignedAccess do_unassigned_access;
int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
uint8_t *buf, int len, bool is_write);
void (*dump_state)(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
int flags);
void (*dump_statistics)(CPUState *cpu, FILE *f,
@@ -84,6 +105,9 @@ typedef struct CPUClass {
bool (*get_paging_enabled)(const CPUState *cpu);
void (*get_memory_mapping)(CPUState *cpu, MemoryMappingList *list,
Error **errp);
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);
const struct VMStateDescription *vmsd;
int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
@@ -114,8 +138,10 @@ struct kvm_run;
* @stopped: Indicates the CPU has been artificially stopped.
* @tcg_exit_req: Set to force TCG to stop executing linked TBs for this
* CPU and return to its top level loop.
* @singlestep_enabled: Flags for single-stepping.
* @env_ptr: Pointer to subclass-specific CPUArchState field.
* @current_tb: Currently executing TB.
* @gdb_regs: Additional GDB registers.
* @next_cpu: Next CPU sharing TB cache.
* @kvm_fd: vCPU file descriptor for KVM.
*
@@ -146,9 +172,11 @@ struct CPUState {
volatile sig_atomic_t exit_request;
volatile sig_atomic_t tcg_exit_req;
uint32_t interrupt_request;
int singlestep_enabled;
void *env_ptr; /* CPUArchState */
struct TranslationBlock *current_tb;
struct GDBRegisterState *gdb_regs;
CPUState *next_cpu;
int kvm_fd;
@@ -259,6 +287,25 @@ void cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
void cpu_dump_statistics(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
int flags);
#ifndef CONFIG_USER_ONLY
/**
* cpu_get_phys_page_debug:
* @cpu: The CPU to obtain the physical page address for.
* @addr: The virtual address.
*
* Obtains the physical page corresponding to a virtual one.
* Use it only for debugging because no protection checks are done.
*
* Returns: Corresponding physical page address or -1 if no page found.
*/
static inline hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
return cc->get_phys_page_debug(cpu, addr);
}
#endif
/**
* cpu_reset:
* @cpu: The CPU whose state is to be reset.
@@ -276,59 +323,6 @@ void cpu_reset(CPUState *cpu);
*/
ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model);
/**
* cpu_class_set_vmsd:
* @cc: CPU class
* @value: Value to set. Unused for %CONFIG_USER_ONLY.
*
* Sets #VMStateDescription for @cc.
*
* The @value argument is intentionally discarded for the non-softmmu targets
* to avoid linker errors or excessive preprocessor usage. If this behavior
* is undesired, you should assign #CPUClass.vmsd directly instead.
*/
#ifndef CONFIG_USER_ONLY
static inline void cpu_class_set_vmsd(CPUClass *cc,
const struct VMStateDescription *value)
{
cc->vmsd = value;
}
#else
#define cpu_class_set_vmsd(cc, value) ((cc)->vmsd = NULL)
#endif
#ifndef CONFIG_USER_ONLY
static inline void cpu_class_set_do_unassigned_access(CPUClass *cc,
CPUUnassignedAccess value)
{
cc->do_unassigned_access = value;
}
#else
#define cpu_class_set_do_unassigned_access(cc, value) \
((cc)->do_unassigned_access = NULL)
#endif
/**
* device_class_set_vmsd:
* @dc: Device class
* @value: Value to set. Unused for %CONFIG_USER_ONLY.
*
* Sets #VMStateDescription for @dc.
*
* The @value argument is intentionally discarded for the non-softmmu targets
* to avoid linker errors or excessive preprocessor usage. If this behavior
* is undesired, you should assign #DeviceClass.vmsd directly instead.
*/
#ifndef CONFIG_USER_ONLY
static inline void device_class_set_vmsd(DeviceClass *dc,
const struct VMStateDescription *value)
{
dc->vmsd = value;
}
#else
#define device_class_set_vmsd(dc, value) ((dc)->vmsd = NULL)
#endif
/**
* qemu_cpu_has_work:
* @cpu: The vCPU to check.
@@ -489,6 +483,19 @@ void cpu_resume(CPUState *cpu);
*/
void qemu_init_vcpu(CPUState *cpu);
#define SSTEP_ENABLE 0x1 /* Enable simulated HW single stepping */
#define SSTEP_NOIRQ 0x2 /* Do not use IRQ while single stepping */
#define SSTEP_NOTIMER 0x4 /* Do not Timers while single stepping */
/**
* cpu_single_step:
* @cpu: CPU to the flags for.
* @enabled: Flags to enable.
*
* Enables or disables single-stepping for @cpu.
*/
void cpu_single_step(CPUState *cpu, int enabled);
#ifdef CONFIG_SOFTMMU
extern const struct VMStateDescription vmstate_cpu_common;
#else
+2 -2
View File
@@ -169,9 +169,9 @@ void *kvm_arch_ram_alloc(ram_addr_t size);
void kvm_setup_guest_memory(void *start, size_t size);
void kvm_flush_coalesced_mmio_buffer(void);
int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr,
target_ulong len, int type);
int kvm_remove_breakpoint(CPUArchState *env, 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);
+5 -7
View File
@@ -1890,7 +1890,7 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
data.dbg.control = reinject_trap;
if (env->singlestep_enabled) {
if (cpu->singlestep_enabled) {
data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
}
kvm_arch_update_guest_debug(cpu, &data.dbg);
@@ -1900,10 +1900,9 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
return data.err;
}
int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr,
target_ulong len, int type)
{
CPUState *cpu = ENV_GET_CPU(env);
struct kvm_sw_breakpoint *bp;
int err;
@@ -1946,10 +1945,9 @@ int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
return 0;
}
int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr,
target_ulong len, int type)
{
CPUState *cpu = ENV_GET_CPU(env);
struct kvm_sw_breakpoint *bp;
int err;
@@ -2022,13 +2020,13 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
return -EINVAL;
}
int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr,
target_ulong len, int type)
{
return -EINVAL;
}
int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr,
target_ulong len, int type)
{
return -EINVAL;
+2 -2
View File
@@ -83,13 +83,13 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
return -ENOSYS;
}
int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr,
int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr,
target_ulong len, int type)
{
return -EINVAL;
}
int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr,
int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr,
target_ulong len, int type)
{
return -EINVAL;
+6 -4
View File
@@ -55,12 +55,14 @@ const char *cpu_to_uname_machine(void *cpu_env)
return "x86-64";
#elif defined(TARGET_I386)
/* see arch/x86/kernel/cpu/bugs.c: check_bugs(), 386, 486, 586, 686 */
uint32_t cpuid_version = ((CPUX86State *)cpu_env)->cpuid_version;
int family = ((cpuid_version >> 8) & 0x0f) + ((cpuid_version >> 20) & 0xff);
if (family == 4)
CPUState *cpu = ENV_GET_CPU((CPUX86State *)cpu_env);
int family = object_property_get_int(OBJECT(cpu), "family", NULL);
if (family == 4) {
return "i486";
if (family == 5)
}
if (family == 5) {
return "i586";
}
return "i686";
#else
/* default is #define-d in each arch/ subdir */
+19 -16
View File
@@ -312,6 +312,7 @@ static void set_idt(int n, unsigned int dpl)
void cpu_loop(CPUX86State *env)
{
CPUState *cs = CPU(x86_env_get_cpu(env));
int trapnr;
abi_ulong pc;
target_siginfo_t info;
@@ -443,7 +444,7 @@ void cpu_loop(CPUX86State *env)
{
int sig;
sig = gdb_handlesig (env, TARGET_SIGTRAP);
sig = gdb_handlesig(cs, TARGET_SIGTRAP);
if (sig)
{
info.si_signo = sig;
@@ -875,7 +876,7 @@ void cpu_loop(CPUARMState *env)
{
int sig;
sig = gdb_handlesig (env, TARGET_SIGTRAP);
sig = gdb_handlesig(cs, TARGET_SIGTRAP);
if (sig)
{
info.si_signo = sig;
@@ -966,7 +967,7 @@ void cpu_loop(CPUUniCore32State *env)
{
int sig;
sig = gdb_handlesig(env, TARGET_SIGTRAP);
sig = gdb_handlesig(cs, TARGET_SIGTRAP);
if (sig) {
info.si_signo = sig;
info.si_errno = 0;
@@ -1233,7 +1234,7 @@ void cpu_loop (CPUSPARCState *env)
{
int sig;
sig = gdb_handlesig (env, TARGET_SIGTRAP);
sig = gdb_handlesig(cs, TARGET_SIGTRAP);
if (sig)
{
info.si_signo = sig;
@@ -1764,7 +1765,7 @@ void cpu_loop(CPUPPCState *env)
{
int sig;
sig = gdb_handlesig(env, TARGET_SIGTRAP);
sig = gdb_handlesig(cs, TARGET_SIGTRAP);
if (sig) {
info.si_signo = sig;
info.si_errno = 0;
@@ -2315,7 +2316,7 @@ done_syscall:
{
int sig;
sig = gdb_handlesig (env, TARGET_SIGTRAP);
sig = gdb_handlesig(cs, TARGET_SIGTRAP);
if (sig)
{
info.si_signo = sig;
@@ -2475,7 +2476,7 @@ void cpu_loop(CPUOpenRISCState *env)
break;
}
if (gdbsig) {
gdb_handlesig(env, gdbsig);
gdb_handlesig(cs, gdbsig);
if (gdbsig != TARGET_SIGTRAP) {
exit(1);
}
@@ -2518,7 +2519,7 @@ void cpu_loop(CPUSH4State *env)
{
int sig;
sig = gdb_handlesig (env, TARGET_SIGTRAP);
sig = gdb_handlesig(cs, TARGET_SIGTRAP);
if (sig)
{
info.si_signo = sig;
@@ -2586,7 +2587,7 @@ void cpu_loop(CPUCRISState *env)
{
int sig;
sig = gdb_handlesig (env, TARGET_SIGTRAP);
sig = gdb_handlesig(cs, TARGET_SIGTRAP);
if (sig)
{
info.si_signo = sig;
@@ -2686,7 +2687,7 @@ void cpu_loop(CPUMBState *env)
{
int sig;
sig = gdb_handlesig (env, TARGET_SIGTRAP);
sig = gdb_handlesig(cs, TARGET_SIGTRAP);
if (sig)
{
info.si_signo = sig;
@@ -2779,7 +2780,7 @@ void cpu_loop(CPUM68KState *env)
{
int sig;
sig = gdb_handlesig (env, TARGET_SIGTRAP);
sig = gdb_handlesig(cs, TARGET_SIGTRAP);
if (sig)
{
info.si_signo = sig;
@@ -3006,7 +3007,7 @@ void cpu_loop(CPUAlphaState *env)
}
break;
case EXCP_DEBUG:
info.si_signo = gdb_handlesig (env, TARGET_SIGTRAP);
info.si_signo = gdb_handlesig(cs, TARGET_SIGTRAP);
if (info.si_signo) {
env->lock_addr = -1;
info.si_errno = 0;
@@ -3059,7 +3060,7 @@ void cpu_loop(CPUS390XState *env)
break;
case EXCP_DEBUG:
sig = gdb_handlesig(env, TARGET_SIGTRAP);
sig = gdb_handlesig(cs, TARGET_SIGTRAP);
if (sig) {
n = TARGET_TRAP_BRKPT;
goto do_signal_pc;
@@ -3541,6 +3542,7 @@ int main(int argc, char **argv, char **envp)
struct linux_binprm bprm;
TaskState *ts;
CPUArchState *env;
CPUState *cpu;
int optind;
char **target_environ, **wrk;
char **target_argv;
@@ -3637,11 +3639,12 @@ int main(int argc, char **argv, char **envp)
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
cpu = ENV_GET_CPU(env);
#if defined(TARGET_SPARC) || defined(TARGET_PPC)
cpu_reset(ENV_GET_CPU(env));
cpu_reset(cpu);
#endif
thread_cpu = ENV_GET_CPU(env);
thread_cpu = cpu;
if (getenv("QEMU_STRACE")) {
do_strace = 1;
@@ -4076,7 +4079,7 @@ int main(int argc, char **argv, char **envp)
gdbstub_port);
exit(1);
}
gdb_handlesig(env, 0);
gdb_handlesig(cpu, 0);
}
cpu_loop(env);
/* never exits */

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