diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-03-13 19:13:33 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-03-13 19:13:33 +0000 |
commit | bbbd67f0ccdba93702e58879997c1d2ca67311b1 (patch) | |
tree | d02c18e59ace36d7f8dcf01040b8f1218ad021b1 /include | |
parent | d7f0a59ff02affb8270ad9b6ee7e60974ac92df0 (diff) | |
parent | 2ef1f68d4f6630e6c77071d2dd979123d1b4d0ed (diff) | |
download | qemu-bbbd67f0ccdba93702e58879997c1d2ca67311b1.zip qemu-bbbd67f0ccdba93702e58879997c1d2ca67311b1.tar.gz qemu-bbbd67f0ccdba93702e58879997c1d2ca67311b1.tar.bz2 |
Merge remote-tracking branch 'remotes/afaerber/tags/qom-cpu-for-2.0' into staging
QOM CPUState refactorings / X86CPU
* Deadlock fix for exit requests around CPU reset
* X86CPU x2apic for KVM
* X86CPU model subclasses
* SPARCCPU preparations for model subclasses
* -cpu arguments for arm, cris, lm32, moxie, openrisc, ppc, sh4, uc32
* m68k assertion cleanups
* CPUClass hooks for cpu.h inline functions
* Field movements from CPU_COMMON to CPUState and follow-up cleanups
# gpg: Signature made Thu 13 Mar 2014 19:06:56 GMT using RSA key ID 3E7E013F
# gpg: Good signature from "Andreas Färber <afaerber@suse.de>"
# gpg: aka "Andreas Färber <afaerber@suse.com>"
* remotes/afaerber/tags/qom-cpu-for-2.0: (58 commits)
user-exec: Change exception_action() argument to CPUState
cputlb: Change tlb_set_page() argument to CPUState
cputlb: Change tlb_flush() argument to CPUState
cputlb: Change tlb_flush_page() argument to CPUState
target-microblaze: Replace DisasContext::env field with MicroBlazeCPU
target-cris: Replace DisasContext::env field with CRISCPU
exec: Change cpu_abort() argument to CPUState
exec: Change memory_region_section_get_iotlb() argument to CPUState
cputlb: Change tlb_unprotect_code_phys() argument to CPUState
cpu-exec: Change cpu_resume_from_signal() argument to CPUState
exec: Change cpu_breakpoint_{insert,remove{,_by_ref,_all}} argument
exec: Change cpu_watchpoint_{insert,remove{,_by_ref,_all}} argument
target-ppc: Use PowerPCCPU in PowerPCCPUClass::handle_mmu_fault hook
translate-all: Change tb_flush_jmp_cache() argument to CPUState
translate-all: Change tb_gen_code() argument to CPUState
translate-all: Change cpu_io_recompile() argument to CPUState
translate-all: Change tb_check_watchpoint() argument to CPUState
translate-all: Change cpu_restore_state_from_tb() argument to CPUState
translate-all: Change cpu_restore_state() argument to CPUState
cpu-exec: Change cpu_loop_exit() argument to CPUState
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/exec/cpu-all.h | 24 | ||||
-rw-r--r-- | include/exec/cpu-defs.h | 61 | ||||
-rw-r--r-- | include/exec/cputlb.h | 6 | ||||
-rw-r--r-- | include/exec/exec-all.h | 43 | ||||
-rw-r--r-- | include/exec/gen-icount.h | 10 | ||||
-rw-r--r-- | include/exec/softmmu_template.h | 24 | ||||
-rw-r--r-- | include/qom/cpu.h | 113 |
7 files changed, 156 insertions, 125 deletions
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 4cb4b4a..fb649a4 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -360,9 +360,6 @@ int page_check_range(target_ulong start, target_ulong len, int flags); CPUArchState *cpu_copy(CPUArchState *env); -void QEMU_NORETURN cpu_abort(CPUArchState *env, const char *fmt, ...) - GCC_FMT_ATTR(2, 3); - /* Flags for use in ENV->INTERRUPT_PENDING. The numbers assigned here are non-sequential in order to preserve @@ -413,27 +410,6 @@ void QEMU_NORETURN cpu_abort(CPUArchState *env, const char *fmt, ...) | CPU_INTERRUPT_TGT_EXT_3 \ | CPU_INTERRUPT_TGT_EXT_4) -/* Breakpoint/watchpoint flags */ -#define BP_MEM_READ 0x01 -#define BP_MEM_WRITE 0x02 -#define BP_MEM_ACCESS (BP_MEM_READ | BP_MEM_WRITE) -#define BP_STOP_BEFORE_ACCESS 0x04 -#define BP_WATCHPOINT_HIT 0x08 -#define BP_GDB 0x10 -#define BP_CPU 0x20 - -int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags, - CPUBreakpoint **breakpoint); -int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags); -void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint); -void cpu_breakpoint_remove_all(CPUArchState *env, int mask); -int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len, - int flags, CPUWatchpoint **watchpoint); -int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, - target_ulong len, int flags); -void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint); -void cpu_watchpoint_remove_all(CPUArchState *env, int mask); - #if !defined(CONFIG_USER_ONLY) /* memory API */ diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index 66a3d46..2dd6206 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -24,7 +24,6 @@ #endif #include "config.h" -#include <setjmp.h> #include <inttypes.h> #include "qemu/osdep.h" #include "qemu/queue.h" @@ -61,9 +60,6 @@ typedef uint64_t target_ulong; #define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */ #define EXCP_YIELD 0x10004 /* cpu wants to yield timeslice to another */ -#define TB_JMP_CACHE_BITS 12 -#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) - /* Only the bottom TB_JMP_PAGE_BITS of the jump cache hash bits vary for addresses on the same page. The top bits are the same. This allows TLB invalidation to quickly clear a subset of the hash table. */ @@ -118,66 +114,9 @@ QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS)); #endif -#ifdef HOST_WORDS_BIGENDIAN -typedef struct icount_decr_u16 { - uint16_t high; - uint16_t low; -} icount_decr_u16; -#else -typedef struct icount_decr_u16 { - uint16_t low; - uint16_t high; -} icount_decr_u16; -#endif - -typedef struct CPUBreakpoint { - target_ulong pc; - int flags; /* BP_* */ - QTAILQ_ENTRY(CPUBreakpoint) entry; -} CPUBreakpoint; - -typedef struct CPUWatchpoint { - target_ulong vaddr; - target_ulong len_mask; - int flags; /* BP_* */ - QTAILQ_ENTRY(CPUWatchpoint) entry; -} CPUWatchpoint; - #define CPU_TEMP_BUF_NLONGS 128 #define CPU_COMMON \ /* soft mmu support */ \ - /* in order to avoid passing too many arguments to the MMIO \ - helpers, we store some rarely used information in the CPU \ - context) */ \ - uintptr_t mem_io_pc; /* host pc at which the memory was \ - accessed */ \ - target_ulong mem_io_vaddr; /* target virtual addr at which the \ - memory was accessed */ \ CPU_COMMON_TLB \ - struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \ - \ - int64_t icount_extra; /* Instructions until next timer event. */ \ - /* Number of cycles left, with interrupt flag in high bit. \ - This allows a single read-compare-cbranch-write sequence to test \ - for both decrementer underflow and exceptions. */ \ - union { \ - uint32_t u32; \ - icount_decr_u16 u16; \ - } icount_decr; \ - uint32_t can_do_io; /* nonzero if memory mapped IO is safe. */ \ - \ - /* from this point: preserved by CPU reset */ \ - /* ice debug support */ \ - QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints; \ - \ - QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints; \ - CPUWatchpoint *watchpoint_hit; \ - \ - /* Core interrupt code */ \ - sigjmp_buf jmp_env; \ - int exception_index; \ - \ - /* user data */ \ - void *opaque; \ #endif diff --git a/include/exec/cputlb.h b/include/exec/cputlb.h index e21cb60..b8ecd6f 100644 --- a/include/exec/cputlb.h +++ b/include/exec/cputlb.h @@ -22,7 +22,7 @@ #if !defined(CONFIG_USER_ONLY) /* cputlb.c */ void tlb_protect_code(ram_addr_t ram_addr); -void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr, +void tlb_unprotect_code_phys(CPUState *cpu, ram_addr_t ram_addr, target_ulong vaddr); void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start, uintptr_t length); @@ -31,12 +31,12 @@ void tlb_set_dirty(CPUArchState *env, target_ulong vaddr); extern int tlb_flush_count; /* exec.c */ -void tb_flush_jmp_cache(CPUArchState *env, target_ulong addr); +void tb_flush_jmp_cache(CPUState *cpu, target_ulong addr); MemoryRegionSection * address_space_translate_for_iotlb(AddressSpace *as, hwaddr addr, hwaddr *xlat, hwaddr *plen); -hwaddr memory_region_section_get_iotlb(CPUArchState *env, +hwaddr memory_region_section_get_iotlb(CPUState *cpu, MemoryRegionSection *section, target_ulong vaddr, hwaddr paddr, hwaddr xlat, diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index a387922..502b7aa 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -80,16 +80,16 @@ void restore_state_to_opc(CPUArchState *env, struct TranslationBlock *tb, void cpu_gen_init(void); int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb, int *gen_code_size_ptr); -bool cpu_restore_state(CPUArchState *env, uintptr_t searched_pc); +bool cpu_restore_state(CPUState *cpu, uintptr_t searched_pc); void page_size_init(void); -void QEMU_NORETURN cpu_resume_from_signal(CPUArchState *env1, void *puc); -void QEMU_NORETURN cpu_io_recompile(CPUArchState *env, uintptr_t retaddr); -TranslationBlock *tb_gen_code(CPUArchState *env, +void QEMU_NORETURN cpu_resume_from_signal(CPUState *cpu, void *puc); +void QEMU_NORETURN cpu_io_recompile(CPUState *cpu, uintptr_t retaddr); +TranslationBlock *tb_gen_code(CPUState *cpu, target_ulong pc, target_ulong cs_base, int flags, int cflags); void cpu_exec_init(CPUArchState *env); -void QEMU_NORETURN cpu_loop_exit(CPUArchState *env1); +void QEMU_NORETURN cpu_loop_exit(CPUState *cpu); int page_unprotect(target_ulong address, uintptr_t pc, void *puc); void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, int is_cpu_write_access); @@ -98,18 +98,18 @@ void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end, #if !defined(CONFIG_USER_ONLY) void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as); /* cputlb.c */ -void tlb_flush_page(CPUArchState *env, target_ulong addr); -void tlb_flush(CPUArchState *env, int flush_global); -void tlb_set_page(CPUArchState *env, target_ulong vaddr, +void tlb_flush_page(CPUState *cpu, target_ulong addr); +void tlb_flush(CPUState *cpu, int flush_global); +void tlb_set_page(CPUState *cpu, target_ulong vaddr, hwaddr paddr, int prot, int mmu_idx, target_ulong size); void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr); #else -static inline void tlb_flush_page(CPUArchState *env, target_ulong addr) +static inline void tlb_flush_page(CPUState *cpu, target_ulong addr) { } -static inline void tlb_flush(CPUArchState *env, int flush_global) +static inline void tlb_flush(CPUState *cpu, int flush_global) { } #endif @@ -332,7 +332,7 @@ bool io_mem_read(struct MemoryRegion *mr, hwaddr addr, bool io_mem_write(struct MemoryRegion *mr, hwaddr addr, uint64_t value, unsigned size); -void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx, +void tlb_fill(CPUState *cpu, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr); uint8_t helper_ldb_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); @@ -380,20 +380,25 @@ extern int singlestep; /* cpu-exec.c */ extern volatile sig_atomic_t exit_request; -/* Deterministic execution requires that IO only be performed on the last - instruction of a TB so that interrupts take effect immediately. */ -static inline int can_do_io(CPUArchState *env) +/** + * cpu_can_do_io: + * @cpu: The CPU for which to check IO. + * + * Deterministic execution requires that IO only be performed on the last + * instruction of a TB so that interrupts take effect immediately. + * + * Returns: %true if memory-mapped IO is safe, %false otherwise. + */ +static inline bool cpu_can_do_io(CPUState *cpu) { - CPUState *cpu = ENV_GET_CPU(env); - if (!use_icount) { - return 1; + return true; } /* If not executing code then assume we are ok. */ if (cpu->current_tb == NULL) { - return 1; + return true; } - return env->can_do_io != 0; + return cpu->can_do_io != 0; } #endif diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h index 39a6b61..da53395 100644 --- a/include/exec/gen-icount.h +++ b/include/exec/gen-icount.h @@ -26,13 +26,15 @@ static inline void gen_tb_start(void) icount_label = gen_new_label(); count = tcg_temp_local_new_i32(); - tcg_gen_ld_i32(count, cpu_env, offsetof(CPUArchState, icount_decr.u32)); + tcg_gen_ld_i32(count, cpu_env, + -ENV_OFFSET + offsetof(CPUState, icount_decr.u32)); /* This is a horrid hack to allow fixing up the value later. */ icount_arg = tcg_ctx.gen_opparam_ptr + 1; tcg_gen_subi_i32(count, count, 0xdeadbeef); tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label); - tcg_gen_st16_i32(count, cpu_env, offsetof(CPUArchState, icount_decr.u16.low)); + tcg_gen_st16_i32(count, cpu_env, + -ENV_OFFSET + offsetof(CPUState, icount_decr.u16.low)); tcg_temp_free_i32(count); } @@ -51,14 +53,14 @@ static void gen_tb_end(TranslationBlock *tb, int num_insns) static inline void gen_io_start(void) { TCGv_i32 tmp = tcg_const_i32(1); - tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUArchState, can_do_io)); + tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io)); tcg_temp_free_i32(tmp); } static inline void gen_io_end(void) { TCGv_i32 tmp = tcg_const_i32(0); - tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUArchState, can_do_io)); + tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io)); tcg_temp_free_i32(tmp); } diff --git a/include/exec/softmmu_template.h b/include/exec/softmmu_template.h index c14a04d..73ed7cf 100644 --- a/include/exec/softmmu_template.h +++ b/include/exec/softmmu_template.h @@ -126,12 +126,12 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env, MemoryRegion *mr = iotlb_to_region(cpu->as, physaddr); physaddr = (physaddr & TARGET_PAGE_MASK) + addr; - env->mem_io_pc = retaddr; - if (mr != &io_mem_rom && mr != &io_mem_notdirty && !can_do_io(env)) { - cpu_io_recompile(env, retaddr); + cpu->mem_io_pc = retaddr; + if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu_can_do_io(cpu)) { + cpu_io_recompile(cpu, retaddr); } - env->mem_io_vaddr = addr; + cpu->mem_io_vaddr = addr; io_mem_read(mr, physaddr, &val, 1 << SHIFT); return val; } @@ -158,7 +158,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); } #endif - tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); + tlb_fill(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE, mmu_idx, retaddr); tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ; } @@ -240,7 +240,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); } #endif - tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); + tlb_fill(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE, mmu_idx, retaddr); tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ; } @@ -333,12 +333,12 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env, MemoryRegion *mr = iotlb_to_region(cpu->as, physaddr); physaddr = (physaddr & TARGET_PAGE_MASK) + addr; - if (mr != &io_mem_rom && mr != &io_mem_notdirty && !can_do_io(env)) { - cpu_io_recompile(env, retaddr); + if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu_can_do_io(cpu)) { + cpu_io_recompile(cpu, retaddr); } - env->mem_io_vaddr = addr; - env->mem_io_pc = retaddr; + cpu->mem_io_vaddr = addr; + cpu->mem_io_pc = retaddr; io_mem_write(mr, physaddr, val, 1 << SHIFT); } @@ -360,7 +360,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, do_unaligned_access(env, addr, 1, mmu_idx, retaddr); } #endif - tlb_fill(env, addr, 1, mmu_idx, retaddr); + tlb_fill(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr); tlb_addr = env->tlb_table[mmu_idx][index].addr_write; } @@ -436,7 +436,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, do_unaligned_access(env, addr, 1, mmu_idx, retaddr); } #endif - tlb_fill(env, addr, 1, mmu_idx, retaddr); + tlb_fill(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr); tlb_addr = env->tlb_table[mmu_idx][index].addr_write; } diff --git a/include/qom/cpu.h b/include/qom/cpu.h index d734be8..06ee263 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -21,6 +21,7 @@ #define QEMU_CPU_H #include <signal.h> +#include <setjmp.h> #include "hw/qdev-core.h" #include "exec/hwaddr.h" #include "qemu/queue.h" @@ -68,8 +69,10 @@ struct TranslationBlock; * CPUClass: * @class_by_name: Callback to map -cpu command line model name to an * instantiatable CPU type. + * @parse_features: Callback to parse command line arguments. * @reset: Callback to reset the #CPUState to its initial state. * @reset_dump_flags: #CPUDumpFlags to use for reset logging. + * @has_work: Callback for checking if there is work to do. * @do_interrupt: Callback for interrupt handling. * @do_unassigned_access: Callback for unassigned access handling. * @memory_rw_debug: Callback for GDB memory access. @@ -81,6 +84,7 @@ struct TranslationBlock; * @set_pc: Callback for setting the Program Counter register. * @synchronize_from_tb: Callback for synchronizing state from a TCG * #TranslationBlock. + * @handle_mmu_fault: Callback for handling an MMU fault. * @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. @@ -96,9 +100,11 @@ typedef struct CPUClass { /*< public >*/ ObjectClass *(*class_by_name)(const char *cpu_model); + void (*parse_features)(CPUState *cpu, char *str, Error **errp); void (*reset)(CPUState *cpu); int reset_dump_flags; + bool (*has_work)(CPUState *cpu); void (*do_interrupt)(CPUState *cpu); CPUUnassignedAccess do_unassigned_access; int (*memory_rw_debug)(CPUState *cpu, vaddr addr, @@ -113,6 +119,8 @@ typedef struct CPUClass { Error **errp); void (*set_pc)(CPUState *cpu, vaddr value); void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb); + int (*handle_mmu_fault)(CPUState *cpu, vaddr address, int rw, + int mmu_index); 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); @@ -131,9 +139,37 @@ typedef struct CPUClass { const char *gdb_core_xml_file; } CPUClass; +#ifdef HOST_WORDS_BIGENDIAN +typedef struct icount_decr_u16 { + uint16_t high; + uint16_t low; +} icount_decr_u16; +#else +typedef struct icount_decr_u16 { + uint16_t low; + uint16_t high; +} icount_decr_u16; +#endif + +typedef struct CPUBreakpoint { + vaddr pc; + int flags; /* BP_* */ + QTAILQ_ENTRY(CPUBreakpoint) entry; +} CPUBreakpoint; + +typedef struct CPUWatchpoint { + vaddr vaddr; + vaddr len_mask; + int flags; /* BP_* */ + QTAILQ_ENTRY(CPUWatchpoint) entry; +} CPUWatchpoint; + struct KVMState; struct kvm_run; +#define TB_JMP_CACHE_BITS 12 +#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) + /** * CPUState: * @cpu_index: CPU index (informative). @@ -150,12 +186,20 @@ struct kvm_run; * @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. + * @icount_extra: Instructions until next timer event. + * @icount_decr: Number of cycles left, with interrupt flag in high bit. + * This allows a single read-compare-cbranch-write sequence to test + * for both decrementer underflow and exceptions. + * @can_do_io: Nonzero if memory-mapped IO is safe. * @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. * @gdb_num_g_regs: Number of registers in GDB 'g' packets. * @next_cpu: Next CPU sharing TB cache. + * @opaque: User data. + * @mem_io_pc: Host Program Counter at which the memory was accessed. + * @mem_io_vaddr: Target virtual address at which the memory was accessed. * @kvm_fd: vCPU file descriptor for KVM. * * State of one CPU core or thread. @@ -186,17 +230,34 @@ struct CPUState { volatile sig_atomic_t tcg_exit_req; uint32_t interrupt_request; int singlestep_enabled; + int64_t icount_extra; + sigjmp_buf jmp_env; AddressSpace *as; MemoryListener *tcg_as_listener; void *env_ptr; /* CPUArchState */ struct TranslationBlock *current_tb; + struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; struct GDBRegisterState *gdb_regs; int gdb_num_regs; int gdb_num_g_regs; QTAILQ_ENTRY(CPUState) node; + /* ice debug support */ + QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints; + + QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints; + CPUWatchpoint *watchpoint_hit; + + void *opaque; + + /* In order to avoid passing too many arguments to the MMIO helpers, + * we store some rarely used information in the CPU context. + */ + uintptr_t mem_io_pc; + vaddr mem_io_vaddr; + int kvm_fd; bool kvm_vcpu_dirty; struct KVMState *kvm_state; @@ -205,6 +266,12 @@ struct CPUState { /* TODO Move common fields from CPUArchState here. */ int cpu_index; /* used by alpha TCG */ uint32_t halted; /* used by alpha, cris, ppc TCG */ + union { + uint32_t u32; + icount_decr_u16 u16; + } icount_decr; + uint32_t can_do_io; + int32_t exception_index; /* used by m68k TCG */ }; QTAILQ_HEAD(CPUTailQ, CPUState); @@ -348,14 +415,31 @@ void cpu_reset(CPUState *cpu); ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model); /** - * qemu_cpu_has_work: + * cpu_generic_init: + * @typename: The CPU base type. + * @cpu_model: The model string including optional parameters. + * + * Instantiates a CPU, processes optional parameters and realizes the CPU. + * + * Returns: A #CPUState or %NULL if an error occurred. + */ +CPUState *cpu_generic_init(const char *typename, const char *cpu_model); + +/** + * cpu_has_work: * @cpu: The vCPU to check. * * Checks whether the CPU has work to do. * * Returns: %true if the CPU has work, %false otherwise. */ -bool qemu_cpu_has_work(CPUState *cpu); +static inline bool cpu_has_work(CPUState *cpu) +{ + CPUClass *cc = CPU_GET_CLASS(cpu); + + g_assert(cc->has_work); + return cc->has_work(cpu); +} /** * qemu_cpu_is_self: @@ -511,6 +595,31 @@ void qemu_init_vcpu(CPUState *cpu); */ void cpu_single_step(CPUState *cpu, int enabled); +/* Breakpoint/watchpoint flags */ +#define BP_MEM_READ 0x01 +#define BP_MEM_WRITE 0x02 +#define BP_MEM_ACCESS (BP_MEM_READ | BP_MEM_WRITE) +#define BP_STOP_BEFORE_ACCESS 0x04 +#define BP_WATCHPOINT_HIT 0x08 +#define BP_GDB 0x10 +#define BP_CPU 0x20 + +int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, + CPUBreakpoint **breakpoint); +int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags); +void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint); +void cpu_breakpoint_remove_all(CPUState *cpu, int mask); + +int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, + int flags, CPUWatchpoint **watchpoint); +int cpu_watchpoint_remove(CPUState *cpu, vaddr addr, + vaddr len, int flags); +void cpu_watchpoint_remove_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint); +void cpu_watchpoint_remove_all(CPUState *cpu, int mask); + +void QEMU_NORETURN cpu_abort(CPUState *cpu, const char *fmt, ...) + GCC_FMT_ATTR(2, 3); + #ifdef CONFIG_SOFTMMU extern const struct VMStateDescription vmstate_cpu_common; #else |