VirtualBox

source: vbox/trunk/src/recompiler/exec-all.h@ 36170

Last change on this file since 36170 was 36170, checked in by vboxsync, 14 years ago

rem: synced up to svn://svn.savannah.nongnu.org/qemu/trunk@6686 (repo UUID c046a42c-6fe2-441c-8c8c-71466251a162).

  • Property svn:eol-style set to native
File size: 14.6 KB
Line 
1/*
2 * internal execution defines for qemu
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
19 */
20
21/*
22 * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
23 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
24 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
25 * a choice of LGPL license versions is made available with the language indicating
26 * that LGPLv2 or any later version may be used, or where a choice of which version
27 * of the LGPL is applied is otherwise unspecified.
28 */
29
30#ifndef _EXEC_ALL_H_
31#define _EXEC_ALL_H_
32
33#include "qemu-common.h"
34
35/* allow to see translation results - the slowdown should be negligible, so we leave it */
36#ifndef VBOX
37#define DEBUG_DISAS
38#endif
39
40#ifdef VBOX
41# include <VBox/vmm/tm.h>
42# include <VBox/vmm/pgm.h> /* PGM_DYNAMIC_RAM_ALLOC */
43# ifndef LOG_GROUP
44# define LOG_GROUP LOG_GROUP_REM
45# endif
46# include <VBox/log.h>
47# include "REMInternal.h"
48# include <VBox/vmm/vm.h>
49#endif /* VBOX */
50
51/* is_jmp field values */
52#define DISAS_NEXT 0 /* next instruction can be analyzed */
53#define DISAS_JUMP 1 /* only pc was modified dynamically */
54#define DISAS_UPDATE 2 /* cpu state was modified dynamically */
55#define DISAS_TB_JUMP 3 /* only pc was modified statically */
56
57typedef struct TranslationBlock TranslationBlock;
58
59/* XXX: make safe guess about sizes */
60#define MAX_OP_PER_INSTR 64
61/* A Call op needs up to 6 + 2N parameters (N = number of arguments). */
62#define MAX_OPC_PARAM 10
63#define OPC_BUF_SIZE 512
64#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
65
66/* Maximum size a TCG op can expand to. This is complicated because a
67 single op may require several host instructions and regirster reloads.
68 For now take a wild guess at 128 bytes, which should allow at least
69 a couple of fixup instructions per argument. */
70#define TCG_MAX_OP_SIZE 128
71
72#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * MAX_OPC_PARAM)
73
74extern target_ulong gen_opc_pc[OPC_BUF_SIZE];
75extern target_ulong gen_opc_npc[OPC_BUF_SIZE];
76extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
77extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
78extern uint16_t gen_opc_icount[OPC_BUF_SIZE];
79extern target_ulong gen_opc_jump_pc[2];
80extern uint32_t gen_opc_hflags[OPC_BUF_SIZE];
81
82#include "qemu-log.h"
83
84void gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
85void gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
86void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
87 unsigned long searched_pc, int pc_pos, void *puc);
88
89unsigned long code_gen_max_block_size(void);
90void cpu_gen_init(void);
91int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
92 int *gen_code_size_ptr);
93int cpu_restore_state(struct TranslationBlock *tb,
94 CPUState *env, unsigned long searched_pc,
95 void *puc);
96int cpu_restore_state_copy(struct TranslationBlock *tb,
97 CPUState *env, unsigned long searched_pc,
98 void *puc);
99void cpu_resume_from_signal(CPUState *env1, void *puc);
100void cpu_io_recompile(CPUState *env, void *retaddr);
101TranslationBlock *tb_gen_code(CPUState *env,
102 target_ulong pc, target_ulong cs_base, int flags,
103 int cflags);
104void cpu_exec_init(CPUState *env);
105void QEMU_NORETURN cpu_loop_exit(void);
106int page_unprotect(target_ulong address, unsigned long pc, void *puc);
107void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
108 int is_cpu_write_access);
109void tb_invalidate_page_range(target_ulong start, target_ulong end);
110void tlb_flush_page(CPUState *env, target_ulong addr);
111void tlb_flush(CPUState *env, int flush_global);
112int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
113 target_phys_addr_t paddr, int prot,
114 int mmu_idx, int is_softmmu);
115static inline int tlb_set_page(CPUState *env1, target_ulong vaddr,
116 target_phys_addr_t paddr, int prot,
117 int mmu_idx, int is_softmmu)
118{
119 if (prot & PAGE_READ)
120 prot |= PAGE_EXEC;
121 return tlb_set_page_exec(env1, vaddr, paddr, prot, mmu_idx, is_softmmu);
122}
123
124#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
125
126#define CODE_GEN_PHYS_HASH_BITS 15
127#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS)
128
129#define MIN_CODE_GEN_BUFFER_SIZE (1024 * 1024)
130
131/* estimated block size for TB allocation */
132/* XXX: use a per code average code fragment size and modulate it
133 according to the host CPU */
134#if defined(CONFIG_SOFTMMU)
135#define CODE_GEN_AVG_BLOCK_SIZE 128
136#else
137#define CODE_GEN_AVG_BLOCK_SIZE 64
138#endif
139
140#if defined(_ARCH_PPC) || defined(__x86_64__) || defined(__arm__)
141#define USE_DIRECT_JUMP
142#endif
143#if defined(__i386__) && !defined(_WIN32)
144#define USE_DIRECT_JUMP
145#endif
146
147#ifdef VBOX /* bird: not safe in next step because of threading & cpu_interrupt. */
148#undef USE_DIRECT_JUMP
149#endif /* VBOX */
150
151struct TranslationBlock {
152 target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
153 target_ulong cs_base; /* CS base for this block */
154 uint64_t flags; /* flags defining in which context the code was generated */
155 uint16_t size; /* size of target code for this block (1 <=
156 size <= TARGET_PAGE_SIZE) */
157 uint16_t cflags; /* compile flags */
158#define CF_COUNT_MASK 0x7fff
159#define CF_LAST_IO 0x8000 /* Last insn may be an IO access. */
160
161#ifdef VBOX
162#define CF_RAW_MODE 0x0010 /* block was generated in raw mode */
163#endif
164
165 uint8_t *tc_ptr; /* pointer to the translated code */
166 /* next matching tb for physical address. */
167 struct TranslationBlock *phys_hash_next;
168 /* first and second physical page containing code. The lower bit
169 of the pointer tells the index in page_next[] */
170 struct TranslationBlock *page_next[2];
171 target_ulong page_addr[2];
172
173 /* the following data are used to directly call another TB from
174 the code of this one. */
175 uint16_t tb_next_offset[2]; /* offset of original jump target */
176#ifdef USE_DIRECT_JUMP
177 uint16_t tb_jmp_offset[4]; /* offset of jump instruction */
178#else
179 unsigned long tb_next[2]; /* address of jump generated code */
180#endif
181 /* list of TBs jumping to this one. This is a circular list using
182 the two least significant bits of the pointers to tell what is
183 the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 =
184 jmp_first */
185 struct TranslationBlock *jmp_next[2];
186 struct TranslationBlock *jmp_first;
187 uint32_t icount;
188};
189
190static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc)
191{
192 target_ulong tmp;
193 tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
194 return (tmp >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)) & TB_JMP_PAGE_MASK;
195}
196
197static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc)
198{
199 target_ulong tmp;
200 tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
201 return (((tmp >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)) & TB_JMP_PAGE_MASK)
202 | (tmp & TB_JMP_ADDR_MASK));
203}
204
205static inline unsigned int tb_phys_hash_func(unsigned long pc)
206{
207 return pc & (CODE_GEN_PHYS_HASH_SIZE - 1);
208}
209
210TranslationBlock *tb_alloc(target_ulong pc);
211void tb_free(TranslationBlock *tb);
212void tb_flush(CPUState *env);
213void tb_link_phys(TranslationBlock *tb,
214 target_ulong phys_pc, target_ulong phys_page2);
215void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr);
216
217extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
218extern uint8_t *code_gen_ptr;
219extern int code_gen_max_blocks;
220
221#if defined(USE_DIRECT_JUMP)
222
223#if defined(_ARCH_PPC)
224extern void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr);
225#define tb_set_jmp_target1 ppc_tb_set_jmp_target
226#elif defined(__i386__) || defined(__x86_64__)
227static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
228{
229 /* patch the branch destination */
230 *(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
231 /* no need to flush icache explicitly */
232}
233#elif defined(__arm__)
234static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
235{
236#if QEMU_GNUC_PREREQ(4, 1)
237 void __clear_cache(char *beg, char *end);
238#else
239 register unsigned long _beg __asm ("a1");
240 register unsigned long _end __asm ("a2");
241 register unsigned long _flg __asm ("a3");
242#endif
243
244 /* we could use a ldr pc, [pc, #-4] kind of branch and avoid the flush */
245 *(uint32_t *)jmp_addr |= ((addr - (jmp_addr + 8)) >> 2) & 0xffffff;
246
247#if QEMU_GNUC_PREREQ(4, 1)
248 __clear_cache((char *) jmp_addr, (char *) jmp_addr + 4);
249#else
250 /* flush icache */
251 _beg = jmp_addr;
252 _end = jmp_addr + 4;
253 _flg = 0;
254 __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
255#endif
256}
257#endif
258
259static inline void tb_set_jmp_target(TranslationBlock *tb,
260 int n, unsigned long addr)
261{
262 unsigned long offset;
263
264 offset = tb->tb_jmp_offset[n];
265 tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
266 offset = tb->tb_jmp_offset[n + 2];
267 if (offset != 0xffff)
268 tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
269}
270
271#else
272
273/* set the jump target */
274static inline void tb_set_jmp_target(TranslationBlock *tb,
275 int n, unsigned long addr)
276{
277 tb->tb_next[n] = addr;
278}
279
280#endif
281
282static inline void tb_add_jump(TranslationBlock *tb, int n,
283 TranslationBlock *tb_next)
284{
285 /* NOTE: this test is only needed for thread safety */
286 if (!tb->jmp_next[n]) {
287 /* patch the native jump address */
288 tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr);
289
290 /* add in TB jmp circular list */
291 tb->jmp_next[n] = tb_next->jmp_first;
292 tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n));
293 }
294}
295
296TranslationBlock *tb_find_pc(unsigned long pc_ptr);
297
298extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
299extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
300extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
301
302#include "qemu-lock.h"
303
304extern spinlock_t tb_lock;
305
306extern int tb_invalidated_flag;
307
308#if !defined(CONFIG_USER_ONLY)
309
310void tlb_fill(target_ulong addr, int is_write, int mmu_idx,
311 void *retaddr);
312
313#include "softmmu_defs.h"
314
315#define ACCESS_TYPE (NB_MMU_MODES + 1)
316#define MEMSUFFIX _code
317#define env cpu_single_env
318
319#define DATA_SIZE 1
320#include "softmmu_header.h"
321
322#define DATA_SIZE 2
323#include "softmmu_header.h"
324
325#define DATA_SIZE 4
326#include "softmmu_header.h"
327
328#define DATA_SIZE 8
329#include "softmmu_header.h"
330
331#undef ACCESS_TYPE
332#undef MEMSUFFIX
333#undef env
334
335#endif
336
337#if defined(CONFIG_USER_ONLY)
338static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr)
339{
340 return addr;
341}
342#else
343# ifdef VBOX
344target_ulong remR3PhysGetPhysicalAddressCode(CPUState *env, target_ulong addr, CPUTLBEntry *pTLBEntry, target_phys_addr_t ioTLBEntry);
345# endif
346/* NOTE: this function can trigger an exception */
347/* NOTE2: the returned address is not exactly the physical address: it
348 is the offset relative to phys_ram_base */
349static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr)
350{
351 int mmu_idx, page_index, pd;
352
353 page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
354 mmu_idx = cpu_mmu_index(env1);
355 if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=
356 (addr & TARGET_PAGE_MASK))) {
357 ldub_code(addr);
358 }
359 pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK;
360 if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
361# ifdef VBOX
362 /* deal with non-MMIO access handlers. */
363 return remR3PhysGetPhysicalAddressCode(env1, addr,
364 &env1->tlb_table[mmu_idx][page_index],
365 env1->iotlb[mmu_idx][page_index]);
366# elif defined(TARGET_SPARC) || defined(TARGET_MIPS)
367 do_unassigned_access(addr, 0, 1, 0, 4);
368#else
369 cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
370#endif
371 }
372
373# if defined(VBOX) && defined(REM_PHYS_ADDR_IN_TLB)
374 return addr + env1->tlb_table[mmu_idx][page_index].addend;
375# elif defined(VBOX)
376 Assert(env1->phys_addends[mmu_idx][page_index] != -1);
377 return addr + env1->phys_addends[mmu_idx][page_index];
378# else
379 return addr + env1->tlb_table[mmu_idx][page_index].addend - (unsigned long)phys_ram_base;
380# endif
381}
382
383/* Deterministic execution requires that IO only be performed on the last
384 instruction of a TB so that interrupts take effect immediately. */
385static inline int can_do_io(CPUState *env)
386{
387 if (!use_icount)
388 return 1;
389
390 /* If not executing code then assume we are ok. */
391 if (!env->current_tb)
392 return 1;
393
394 return env->can_do_io != 0;
395}
396#endif
397
398#ifdef USE_KQEMU
399#define KQEMU_MODIFY_PAGE_MASK (0xff & ~(VGA_DIRTY_FLAG | CODE_DIRTY_FLAG))
400
401#define MSR_QPI_COMMBASE 0xfabe0010
402
403int kqemu_init(CPUState *env);
404int kqemu_cpu_exec(CPUState *env);
405void kqemu_flush_page(CPUState *env, target_ulong addr);
406void kqemu_flush(CPUState *env, int global);
407void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr);
408void kqemu_modify_page(CPUState *env, ram_addr_t ram_addr);
409void kqemu_set_phys_mem(uint64_t start_addr, ram_addr_t size,
410 ram_addr_t phys_offset);
411void kqemu_cpu_interrupt(CPUState *env);
412void kqemu_record_dump(void);
413
414extern uint32_t kqemu_comm_base;
415
416static inline int kqemu_is_ok(CPUState *env)
417{
418 return(env->kqemu_enabled &&
419 (env->cr[0] & CR0_PE_MASK) &&
420 !(env->hflags & HF_INHIBIT_IRQ_MASK) &&
421 (env->eflags & IF_MASK) &&
422 !(env->eflags & VM_MASK) &&
423 (env->kqemu_enabled == 2 ||
424 ((env->hflags & HF_CPL_MASK) == 3 &&
425 (env->eflags & IOPL_MASK) != IOPL_MASK)));
426}
427
428#endif
429
430typedef void (CPUDebugExcpHandler)(CPUState *env);
431
432CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler);
433#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette