/*
* KQEMU
*
* Copyright (C) 2004-2007 Fabrice Bellard
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef __x86_64__
register unsigned long pc asm("%r12");
#else
register unsigned long pc asm("%esi");
#endif
#include "kqemu_int.h"
/*
* TODO:
* - do not use cs.base for CS64 code
* - test all segment limits in 16/32 bit mode
*/
//#define DEBUG_LRET
//#define DEBUG_INTERP
//#define DEBUG_SEG
#define ldq_kernel(addr) ldq_fast(s, addr, 0)
#define ldl_kernel(addr) ldl_fast(s, addr, 0)
#define lduw_kernel(addr) lduw_fast(s, addr, 0)
#define stq_kernel(addr, val) stq_fast(s, addr, val, 0)
#define stl_kernel(addr, val) stl_fast(s, addr, val, 0)
#define stw_kernel(addr, val) stw_fast(s, addr, val, 0)
#ifdef USE_HARD_MMU
#define ldub(s, addr) ldub_mem(s, addr)
#define lduw(s, addr) lduw_mem(s, addr)
#define ldl(s, addr) ldl_mem(s, addr)
#define ldq(s, addr) ldq_mem(s, addr)
#define stb(s, addr, val) stb_mem(s, addr, val)
#define stw(s, addr, val) stw_mem(s, addr, val)
#define stl(s, addr, val) stl_mem(s, addr, val)
#define stq(s, addr, val) stq_mem(s, addr, val)
#else
#define ldub(s, addr) ldub_fast(s, addr, (s->cpu_state.cpl == 3))
#define lduw(s, addr) lduw_fast(s, addr, (s->cpu_state.cpl == 3))
#define ldl(s, addr) ldl_fast(s, addr, (s->cpu_state.cpl == 3))
#define ldq(s, addr) ldq_fast(s, addr, (s->cpu_state.cpl == 3))
#define stb(s, addr, val) stb_fast(s, addr, val, (s->cpu_state.cpl == 3))
#define stw(s, addr, val) stw_fast(s, addr, val, (s->cpu_state.cpl == 3))
#define stl(s, addr, val) stl_fast(s, addr, val, (s->cpu_state.cpl == 3))
#define stq(s, addr, val) stq_fast(s, addr, val, (s->cpu_state.cpl == 3))
#endif
#ifdef __x86_64__
#define CODE64(s) ((s)->cpu_state.segs[R_CS].flags & DESC_L_MASK)
#define REX_R(s) ((s)->rex_r)
#define REX_X(s) ((s)->rex_x)
#define REX_B(s) ((s)->rex_b)
#else
#define CODE64(s) 0
#define REX_R(s) 0
#define REX_X(s) 0
#define REX_B(s) 0
#endif
#define PREFIX_REPZ 0x01
#define PREFIX_REPNZ 0x02
#define PREFIX_LOCK 0x04
#define PREFIX_REX 0x08
static inline unsigned int get_sp_mask(unsigned int e2)
{
if (e2 & DESC_B_MASK)
return 0xffffffff;
else
return 0xffff;
}
/* XXX: add a is_user flag to have proper security support */
#define PUSHW(ssp, sp, sp_mask, val)\
{\
sp -= 2;\
stw_kernel((ssp) + (sp & (sp_mask)), (val));\
}
#define PUSHL(ssp, sp, sp_mask, val)\
{\
sp -= 4;\
stl_kernel((ssp) + (sp & (sp_mask)), (val));\
}
#define POPW(ssp, sp, sp_mask, val)\
{\
val = lduw_kernel((ssp) + (sp & (sp_mask)));\
sp += 2;\
}
#define POPL(ssp, sp, sp_mask, val)\
{\
val = (uint32_t)ldl_kernel((ssp) + (sp & (sp_mask)));\
sp += 4;\
}
#define PUSHQ(sp, val)\
{\
sp -= 8;\
stq_kernel(sp, (val));\
}
#define POPQ(sp, val)\
{\
val = ldq_kernel(sp);\
sp += 8;\
}
#define ESP (s->regs1.esp)
#define EIP (s->regs1.eip)
static inline unsigned int get_seg_sel(struct kqemu_state *s, int seg_reg)
{
unsigned int val;
switch(seg_reg) {
case R_CS:
val = (s->regs1.cs_sel & ~3) | s->cpu_state.cpl;
break;
case R_SS:
val = (s->regs1.ss_sel & ~3) | s->cpu_state.cpl;
break;
#ifdef __x86_64__
case R_DS:
asm volatile ("mov %%ds, %0" : "=r" (val));
val &= 0xffff; /* XXX: see if it is really necessary */
break;
case R_ES:
asm volatile ("mov %%es, %0" : "=r" (val));
val &= 0xffff; /* XXX: see if it is really necessary */
break;
#else
case R_DS:
val = s->regs1.ds_sel;
break;
case R_ES:
val = s->regs1.es_sel;
break;
#endif
case R_FS:
asm volatile ("mov %%fs, %0" : "=r" (val));
val &= 0xffff; /* XXX: see if it is really necessary */
break;
default:
case R_GS:
asm volatile ("mov %%gs, %0" : "=r" (val));
val &= 0xffff; /* XXX: see if it is really necessary */
break;
}
return val;
}
#ifdef USE_SEG_GP
static inline void set_seg_desc_cache(struct kqemu_state *s,
int seg_reg)
{
struct kqemu_segment_cache *sc;
uint32_t e1, e2;
unsigned long base, limit;
sc = &s->cpu_state.segs[seg_reg];
limit = sc->limit;
base = sc->base;
e2 = (sc->flags & 0x0070ff00) | (3 << DESC_DPL_SHIFT) |
DESC_S_MASK | DESC_A_MASK;
if (limit > 0xfffff) {
limit >>= 12;
e2 |= DESC_G_MASK;
}
e1 = (base << 16) | (limit & 0xffff);
e2 |= ((base >> 16) & 0xff) | (base & 0xff000000) | (limit & 0x000f0000);
s->seg_desc_cache[seg_reg][0] = e1;
s->seg_desc_cache[seg_reg][1] = e2;
}
/* seg_reg must be R_CS or R_SS */
static inline void set_descriptor_entry(struct kqemu_state *s,
int seg_reg, int selector)
{
uint32_t sel;
uint8_t *ptr;
/* reset the previous one */
sel = s->seg_desc_entries[seg_reg - R_CS];
ptr = (uint8_t *)s->dt_table + sel;
*(uint64_t *)(ptr) = 0;
if ((selector & 0xfffc) != 0) {
sel = (selector & ~7) | ((selector & 4) << 14);
ptr = (uint8_t *)s->dt_table + sel;
*(uint32_t *)(ptr) = s->seg_desc_cache[seg_reg][0];
*(uint32_t *)(ptr + 4) = s->seg_desc_cache[seg_reg][1];
} else {
sel = 0;
}
s->seg_desc_entries[seg_reg - R_CS] = sel;
}
#endif
/* NOTE: in the interpreter we only need the base value and flags for
CS and SS. The selector is loaded at its real place (either real
segment or regs) */
static void cpu_x86_load_seg_cache(struct kqemu_state *s,
int seg_reg, unsigned int selector,
uint32_t base, unsigned int limit,
uint32_t e1, uint32_t e2)
{
struct kqemu_segment_cache *sc;
#if 0
monitor_log(s, "%08x: load_seg_cache seg_reg=%d sel=0x%04x e2=0x%08x\n",
s->regs1.eip, seg_reg, selector, e2);
#endif
sc = &s->cpu_state.segs[seg_reg];
sc->flags = e2;
sc->base = base;
sc->limit = limit;
/* update CPU state if needed */
#ifdef USE_SEG_GP
if (s->cpu_state.cpl != 3) {
switch(seg_reg) {
case R_CS:
s->regs1.cs_sel = selector | 3;
set_seg_desc_cache(s, R_CS);
set_descriptor_entry(s, R_CS, selector);
break;
case R_SS:
s->regs1.ss_sel = selector | 3;
set_seg_desc_cache(s, R_SS);
set_descriptor_entry(s, R_SS, selector);
break;
#ifdef __x86_64__
case R_DS:
set_seg_desc_cache(s, R_DS);
set_cpu_seg_cache(s, R_DS, selector);
break;
case R_ES:
set_seg_desc_cache(s, R_ES);
set_cpu_seg_cache(s, R_ES, selector);
break;
#else
case R_DS:
s->regs1.ds_sel = selector;
set_seg_desc_cache(s, R_DS);
break;
case R_ES:
s->regs1.es_sel = selector;
set_seg_desc_cache(s, R_ES);
break;
#endif
case R_FS:
set_seg_desc_cache(s, R_FS);
set_cpu_seg_cache(s, R_FS, selector);
break;
case R_GS:
set_seg_desc_cache(s, R_GS);
set_cpu_seg_cache(s, R_GS, selector);
break;
}
} else
#endif
{
switch(seg_reg) {
case R_CS:
s->regs1.cs_sel = selector | 3;
break;
case R_SS:
s->regs1.ss_sel = selector | 3;
没有合适的资源?快使用搜索试试~ 我知道了~
kqemu-1.3.0pre11
共48个文件
c:14个
s:9个
h:5个
需积分: 10 36 下载量 109 浏览量
2008-07-09
16:14:14
上传
评论
收藏 172KB RAR 举报
温馨提示
KQEMU[QEMU Accelerator]: QEMU加速器<br><br>KQEMU是一操作系统驱动开源软件,可以帮助QEMU PC仿真器运行更快. <br>QEMU可以在x86体系的主机上仿真PC.<br>KQEMU现可运行在基于x86或x86_64的Linux2.4或Linux 2.6主机上.<br>对FreBSD和Windows NT/2000/2003/XP的支持也在开发中.<br>
资源推荐
资源详情
资源评论
收起资源包目录
kqemu-1.3.0pre11.rar (48个子文件)
kqemu-1.3.0pre11
kqemu-1.3.0pre11
COPYING 18KB
kqemu-doc.html 8KB
Makefile.winnt 1KB
Changelog 2KB
tests
usertest.c 21KB
lib.c 5KB
entry-x86_64.S 4KB
entry-i386.S 2KB
kerneltest.c 8KB
kqemutest.h 4KB
head.S 144B
kqemutest.c 33KB
README 531B
Makefile 2KB
kqemu.h 5KB
kqemu-kernel.h 2KB
LICENSE 232B
kqemu.sys 121KB
configure 7KB
install.sh 287B
kqemu-tech.texi 18KB
kqemu-freebsd.c 12KB
common
genmon.c 1KB
monitor.c 63KB
common.c 23KB
interp.c 157KB
i386
nexus_asm.S 5KB
monitor.ld 393B
monitor_asm.S 10KB
kernel_asm.S 1KB
kernel.c 40KB
genoffsets.c 2KB
x86_64
nexus_asm.S 6KB
monitor.ld 426B
monitor_asm.S 9KB
kernel_asm.S 1KB
kqemu_int.h 37KB
Makefile 4KB
insn_table.h 8KB
monitor-utils.c 5KB
README 131B
kqemu-linux.c 10KB
Makefile 2KB
kqemu-doc.texi 6KB
kqemu-tech.html 21KB
Makefile.freebsd 184B
kqemu-win32.c 10KB
kqemu.inf 2KB
共 48 条
- 1
资源评论
lcw266
- 粉丝: 2
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功