Remove use of cpu exceptions for trigger_gp for instructions
This commit is contained in:
parent
33912bee28
commit
f43ab3387a
|
@ -124,7 +124,8 @@ const encodings = [
|
|||
{ opcode: 0x99, nonfaulting: 1, os: 1, },
|
||||
{ opcode: 0x9A, os: 1, imm1632: 1, extra_imm16: 1, skip: 1, block_boundary: 1, }, // callf
|
||||
{ opcode: 0x9B, skip: 1, },
|
||||
{ opcode: 0x9C, os: 1, },
|
||||
// pushf: block_boundary since it uses non-raising cpu exceptions
|
||||
{ opcode: 0x9C, os: 1, block_boundary: 1, },
|
||||
// popf: not a jump, but can cause an eip change due to updating the interrupt flag
|
||||
{ opcode: 0x9D, os: 1, block_boundary: 1, skip: 1, },
|
||||
{ opcode: 0x9E, },
|
||||
|
@ -248,7 +249,8 @@ const encodings = [
|
|||
|
||||
{ opcode: 0xF8, nonfaulting: 1, },
|
||||
{ opcode: 0xF9, nonfaulting: 1, },
|
||||
{ opcode: 0xFA, skip: 1, },
|
||||
// cli: block_boundary since it uses non-raising cpu exceptions
|
||||
{ opcode: 0xFA, block_boundary: 1, skip: 1, },
|
||||
// sti: not a jump, but can cause a change in eip
|
||||
{ opcode: 0xFB, block_boundary: 1, skip: 1, },
|
||||
{ opcode: 0xFC, nonfaulting: 1, },
|
||||
|
@ -264,29 +266,29 @@ const encodings = [
|
|||
{ opcode: 0xFF, os: 1, e: 1, fixed_g: 5, block_boundary: 1, no_next_instruction: 1, skip: 1, },
|
||||
{ opcode: 0xFF, custom: 1, os: 1, e: 1, fixed_g: 6, },
|
||||
|
||||
{ opcode: 0x0F00, fixed_g: 0, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F00, fixed_g: 1, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F00, fixed_g: 2, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F00, fixed_g: 3, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F00, fixed_g: 4, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F00, fixed_g: 5, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F00, fixed_g: 0, e: 1, skip: 1, block_boundary: 1, }, // sldt, ...
|
||||
{ opcode: 0x0F00, fixed_g: 1, e: 1, skip: 1, block_boundary: 1, },
|
||||
{ opcode: 0x0F00, fixed_g: 2, e: 1, skip: 1, block_boundary: 1, },
|
||||
{ opcode: 0x0F00, fixed_g: 3, e: 1, skip: 1, block_boundary: 1, },
|
||||
{ opcode: 0x0F00, fixed_g: 4, e: 1, skip: 1, block_boundary: 1, },
|
||||
{ opcode: 0x0F00, fixed_g: 5, e: 1, skip: 1, block_boundary: 1, },
|
||||
|
||||
{ opcode: 0x0F01, fixed_g: 0, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F01, fixed_g: 1, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F01, fixed_g: 2, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F01, fixed_g: 3, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F01, fixed_g: 4, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F01, fixed_g: 6, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F01, fixed_g: 7, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F01, fixed_g: 0, e: 1, skip: 1, block_boundary: 1, }, // sgdt, ...
|
||||
{ opcode: 0x0F01, fixed_g: 1, e: 1, skip: 1, block_boundary: 1, },
|
||||
{ opcode: 0x0F01, fixed_g: 2, e: 1, skip: 1, block_boundary: 1, },
|
||||
{ opcode: 0x0F01, fixed_g: 3, e: 1, skip: 1, block_boundary: 1, },
|
||||
{ opcode: 0x0F01, fixed_g: 4, e: 1, skip: 1, block_boundary: 1, },
|
||||
{ opcode: 0x0F01, fixed_g: 6, e: 1, skip: 1, block_boundary: 1, },
|
||||
{ opcode: 0x0F01, fixed_g: 7, e: 1, skip: 1, block_boundary: 1, },
|
||||
|
||||
{ opcode: 0x0F02, os: 1, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F03, os: 1, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F04, skip: 1 },
|
||||
{ opcode: 0x0F05, skip: 1 },
|
||||
{ opcode: 0x0F06, skip: 1 },
|
||||
{ opcode: 0x0F06, skip: 1, block_boundary: 1, }, // clts
|
||||
{ opcode: 0x0F07, skip: 1 },
|
||||
{ opcode: 0x0F08, skip: 1 },
|
||||
{ opcode: 0x0F09, skip: 1 },
|
||||
{ opcode: 0x0F09, skip: 1, block_boundary: 1, }, // wbinvd
|
||||
{ opcode: 0x0F0A, skip: 1 },
|
||||
// ud2
|
||||
// Technically has a next instruction, but Linux uses this for assertions
|
||||
|
@ -307,18 +309,18 @@ const encodings = [
|
|||
{ opcode: 0x0F1E, skip: 1 },
|
||||
{ opcode: 0x0F1F, custom: 1, e: 1, },
|
||||
|
||||
{ opcode: 0x0F20, ignore_mod: 1, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F21, ignore_mod: 1, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F22, ignore_mod: 1, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F23, ignore_mod: 1, e: 1, skip: 1 },
|
||||
{ opcode: 0x0F20, ignore_mod: 1, e: 1, skip: 1, block_boundary: 1, }, // mov reg, creg
|
||||
{ opcode: 0x0F21, ignore_mod: 1, e: 1, skip: 1, block_boundary: 1, }, // mov reg, dreg
|
||||
{ opcode: 0x0F22, ignore_mod: 1, e: 1, skip: 1, block_boundary: 1, }, // mov creg, reg
|
||||
{ opcode: 0x0F23, ignore_mod: 1, e: 1, skip: 1, block_boundary: 1, }, // mov dreg, reg
|
||||
{ opcode: 0x0F24, skip: 1 },
|
||||
{ opcode: 0x0F25, skip: 1 },
|
||||
{ opcode: 0x0F26, skip: 1 },
|
||||
{ opcode: 0x0F27, skip: 1 },
|
||||
|
||||
{ opcode: 0x0F30, skip: 1 },
|
||||
{ opcode: 0x0F31, skip: 1 },
|
||||
{ opcode: 0x0F32, skip: 1 },
|
||||
{ opcode: 0x0F30, skip: 1, block_boundary: 1, }, // wrmsr
|
||||
{ opcode: 0x0F31, skip: 1, block_boundary: 1, }, // rdtsc
|
||||
{ opcode: 0x0F32, skip: 1, block_boundary: 1, }, // rdmsr
|
||||
{ opcode: 0x0F33, skip: 1 },
|
||||
{ opcode: 0x0F34, skip: 1, block_boundary: 1, no_next_instruction: 1, }, // sysenter
|
||||
{ opcode: 0x0F35, skip: 1, block_boundary: 1, no_next_instruction: 1, }, // sysexit
|
||||
|
@ -415,10 +417,10 @@ const encodings = [
|
|||
|
||||
{ opcode: 0x0FAA, skip: 1 },
|
||||
|
||||
{ opcode: 0x0FAE, e: 1, fixed_g: 0, only_mem: 1, skip: 1, }, // fxsave, ...
|
||||
{ opcode: 0x0FAE, e: 1, fixed_g: 1, only_mem: 1, skip: 1, },
|
||||
{ opcode: 0x0FAE, e: 1, fixed_g: 2, only_mem: 1, skip: 1, },
|
||||
{ opcode: 0x0FAE, e: 1, fixed_g: 3, only_mem: 1, skip: 1, },
|
||||
{ opcode: 0x0FAE, e: 1, fixed_g: 0, only_mem: 1, skip: 1, }, // fxsave
|
||||
{ opcode: 0x0FAE, e: 1, fixed_g: 1, only_mem: 1, skip: 1, block_boundary: 1, }, // fxrstor: block_boundary since it uses non-raising cpu exceptions
|
||||
{ opcode: 0x0FAE, e: 1, fixed_g: 2, only_mem: 1, skip: 1, block_boundary: 1, }, // ldmxcsr
|
||||
{ opcode: 0x0FAE, e: 1, fixed_g: 3, only_mem: 1, skip: 1, block_boundary: 1, }, // stmxcsr
|
||||
{ opcode: 0x0FAE, e: 1, fixed_g: 4, only_mem: 1, skip: 1, },
|
||||
|
||||
{ opcode: 0x0FAE, e: 1, fixed_g: 5, only_reg: 1, skip: 1, }, // lfence (reg, only 0), xrstor (mem)
|
||||
|
|
|
@ -3329,7 +3329,7 @@ CPU.prototype.switch_seg = function(reg, selector)
|
|||
dbg_log("#GP for loading 0 in SS sel=" + h(selector, 4), LOG_CPU);
|
||||
dbg_trace(LOG_CPU);
|
||||
this.trigger_gp_non_raising(0);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!info.is_valid ||
|
||||
|
@ -3341,7 +3341,7 @@ CPU.prototype.switch_seg = function(reg, selector)
|
|||
dbg_log("#GP for loading invalid in SS sel=" + h(selector, 4), LOG_CPU);
|
||||
dbg_trace(LOG_CPU);
|
||||
this.trigger_gp_non_raising(selector & ~3);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!info.is_present)
|
||||
|
@ -3368,7 +3368,7 @@ CPU.prototype.switch_seg = function(reg, selector)
|
|||
//dbg_trace(LOG_CPU);
|
||||
this.sreg[reg] = selector;
|
||||
this.segment_is_null[reg] = 1;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!info.is_valid ||
|
||||
|
@ -3382,7 +3382,7 @@ CPU.prototype.switch_seg = function(reg, selector)
|
|||
this.debug.dump_regs();
|
||||
dbg_trace(LOG_CPU);
|
||||
this.trigger_gp_non_raising(selector & ~3);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!info.is_present)
|
||||
|
|
|
@ -849,8 +849,14 @@ void trigger_gp(int32_t code)
|
|||
__attribute__((noinline))
|
||||
void trigger_gp_non_raising(int32_t code)
|
||||
{
|
||||
#if DEBUG
|
||||
if(cpu_exception_hook(CPU_EXCEPTION_GP))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
*instruction_pointer = *previous_ip;
|
||||
raise_exception_with_code(CPU_EXCEPTION_GP, code);
|
||||
call_interrupt_vector(CPU_EXCEPTION_GP, false, true, code);
|
||||
}
|
||||
|
||||
int32_t virt_boundary_read16(int32_t low, int32_t high)
|
||||
|
|
|
@ -590,7 +590,7 @@ void instr16_9C() {
|
|||
{
|
||||
dbg_assert(*protected_mode);
|
||||
dbg_log("pushf #gp");
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -604,7 +604,7 @@ void instr32_9C() {
|
|||
// trap to virtual 8086 monitor
|
||||
dbg_assert(*protected_mode);
|
||||
dbg_log("pushf #gp");
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -617,7 +617,8 @@ void instr16_9D() {
|
|||
if((flags[0] & FLAG_VM) && getiopl() < 3)
|
||||
{
|
||||
dbg_log("popf #gp");
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
return;
|
||||
}
|
||||
|
||||
update_eflags((flags[0] & ~0xFFFF) | pop16());
|
||||
|
@ -641,7 +642,8 @@ void instr32_9D() {
|
|||
if((flags[0] & FLAG_VM) && getiopl() < 3)
|
||||
{
|
||||
dbg_log("popf #gp");
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
return;
|
||||
}
|
||||
|
||||
update_eflags(pop32s());
|
||||
|
@ -1493,7 +1495,7 @@ void instr_FA() {
|
|||
//else
|
||||
{
|
||||
dbg_log("cli #gp");
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1527,7 +1529,7 @@ void instr_FB() {
|
|||
//else
|
||||
{
|
||||
dbg_log("sti #gp");
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,23 +43,23 @@ void instr_0F00_1_reg(int32_t r) {
|
|||
void instr_0F00_2_mem(int32_t addr) {
|
||||
// lldt
|
||||
if(!protected_mode[0] || vm86_mode()) trigger_ud();
|
||||
if(cpl[0]) trigger_gp(0);
|
||||
if(cpl[0]) { trigger_gp_non_raising(0); return; }
|
||||
load_ldt(safe_read16(addr));
|
||||
}
|
||||
void instr_0F00_2_reg(int32_t r) {
|
||||
if(!protected_mode[0] || vm86_mode()) trigger_ud();
|
||||
if(cpl[0]) trigger_gp(0);
|
||||
if(cpl[0]) { trigger_gp_non_raising(0); return; }
|
||||
load_ldt(read_reg16(r));
|
||||
}
|
||||
void instr_0F00_3_mem(int32_t addr) {
|
||||
// ltr
|
||||
if(!protected_mode[0] || vm86_mode()) trigger_ud();
|
||||
if(cpl[0]) trigger_gp(0);
|
||||
if(cpl[0]) { trigger_gp_non_raising(0); return; }
|
||||
load_tr(safe_read16(addr));
|
||||
}
|
||||
void instr_0F00_3_reg(int32_t r) {
|
||||
if(!protected_mode[0] || vm86_mode()) trigger_ud();
|
||||
if(cpl[0]) trigger_gp(0);
|
||||
if(cpl[0]) { trigger_gp_non_raising(0); return; }
|
||||
load_tr(read_reg16(r));
|
||||
}
|
||||
void instr_0F00_4_mem(int32_t addr) {
|
||||
|
@ -99,7 +99,7 @@ void instr_0F01_1_mem(int32_t addr) {
|
|||
void instr_0F01_2_reg(int32_t r) { trigger_ud(); }
|
||||
void instr_0F01_2_mem(int32_t addr) {
|
||||
// lgdt
|
||||
if(cpl[0]) trigger_gp(0);
|
||||
if(cpl[0]) { trigger_gp_non_raising(0); return; }
|
||||
int32_t size = safe_read16(addr);
|
||||
int32_t offset = safe_read32s(addr + 2);
|
||||
int32_t mask = is_osize_32() ? -1 : 0x00FFFFFF;
|
||||
|
@ -109,7 +109,7 @@ void instr_0F01_2_mem(int32_t addr) {
|
|||
void instr_0F01_3_reg(int32_t r) { trigger_ud(); }
|
||||
void instr_0F01_3_mem(int32_t addr) {
|
||||
// lidt
|
||||
if(cpl[0]) trigger_gp(0);
|
||||
if(cpl[0]) { trigger_gp_non_raising(0); return; }
|
||||
int32_t size = safe_read16(addr);
|
||||
int32_t offset = safe_read32s(addr + 2);
|
||||
int32_t mask = is_osize_32() ? -1 : 0x00FFFFFF;
|
||||
|
@ -137,18 +137,18 @@ void lmsw(int32_t new_cr0) {
|
|||
set_cr0(new_cr0);
|
||||
}
|
||||
void instr_0F01_6_reg(int32_t r) {
|
||||
if(cpl[0]) trigger_gp(0);
|
||||
if(cpl[0]) { trigger_gp_non_raising(0); return; }
|
||||
lmsw(read_reg16(r));
|
||||
}
|
||||
void instr_0F01_6_mem(int32_t addr) {
|
||||
if(cpl[0]) trigger_gp(0);
|
||||
if(cpl[0]) { trigger_gp_non_raising(0); return; }
|
||||
lmsw(safe_read16(addr));
|
||||
}
|
||||
|
||||
void instr_0F01_7_reg(int32_t r) { trigger_ud(); }
|
||||
void instr_0F01_7_mem(int32_t addr) {
|
||||
// invlpg
|
||||
if(cpl[0]) trigger_gp(0);
|
||||
if(cpl[0]) { trigger_gp_non_raising(0); return; }
|
||||
invlpg(addr);
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ void instr_0F06() {
|
|||
if(cpl[0])
|
||||
{
|
||||
dbg_log("clts #gp");
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -185,9 +185,12 @@ void instr_0F09() {
|
|||
if(cpl[0])
|
||||
{
|
||||
dbg_log("wbinvd #gp");
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// wbinvd
|
||||
}
|
||||
// wbinvd
|
||||
}
|
||||
|
||||
|
||||
|
@ -450,7 +453,8 @@ void instr_0F20(int32_t r, int32_t creg) {
|
|||
|
||||
if(cpl[0])
|
||||
{
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(creg)
|
||||
|
@ -477,7 +481,8 @@ void instr_0F20(int32_t r, int32_t creg) {
|
|||
void instr_0F21(int32_t r, int32_t dreg_index) {
|
||||
if(cpl[0])
|
||||
{
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(dreg_index == 4 || dreg_index == 5)
|
||||
|
@ -503,7 +508,8 @@ void instr_0F22(int32_t r, int32_t creg) {
|
|||
|
||||
if(cpl[0])
|
||||
{
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t data = read_reg32(r);
|
||||
|
@ -537,7 +543,8 @@ void instr_0F22(int32_t r, int32_t creg) {
|
|||
if(data & (1 << 11 | 1 << 12 | 1 << 15 | 1 << 16 | 1 << 19 | 0xFFC00000))
|
||||
{
|
||||
dbg_log("trigger_gp: Invalid cr4 bit");
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if((cr[4] ^ data) & (CR4_PGE | CR4_PSE))
|
||||
|
@ -564,7 +571,8 @@ void instr_0F22(int32_t r, int32_t creg) {
|
|||
void instr_0F23(int32_t r, int32_t dreg_index) {
|
||||
if(cpl[0])
|
||||
{
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(dreg_index == 4 || dreg_index == 5)
|
||||
|
@ -687,7 +695,8 @@ void instr_0F30() {
|
|||
|
||||
if(cpl[0])
|
||||
{
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t index = reg32s[ECX];
|
||||
|
@ -766,7 +775,7 @@ void instr_0F31() {
|
|||
}
|
||||
else
|
||||
{
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -774,7 +783,8 @@ void instr_0F32() {
|
|||
// rdmsr - read maschine specific register
|
||||
if(cpl[0])
|
||||
{
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t index = reg32s[ECX];
|
||||
|
@ -869,7 +879,8 @@ void instr_0F34() {
|
|||
|
||||
if(!protected_mode[0] || seg == 0)
|
||||
{
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(CPU_LOG_VERBOSE)
|
||||
|
@ -907,7 +918,8 @@ void instr_0F35() {
|
|||
|
||||
if(!protected_mode[0] || cpl[0] || seg == 0)
|
||||
{
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(CPU_LOG_VERBOSE)
|
||||
|
@ -2066,7 +2078,8 @@ void instr_0FAE_2_mem(int32_t addr) {
|
|||
{
|
||||
dbg_log("Invalid mxcsr bits: %x", (new_mxcsr & ~MXCSR_MASK));
|
||||
assert(false);
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
return;
|
||||
}
|
||||
*mxcsr = new_mxcsr;
|
||||
}
|
||||
|
|
|
@ -389,7 +389,8 @@ void fxrstor(uint32_t addr)
|
|||
if(new_mxcsr & ~MXCSR_MASK)
|
||||
{
|
||||
dbg_log("#gp Invalid mxcsr bits");
|
||||
trigger_gp(0);
|
||||
trigger_gp_non_raising(0);
|
||||
return;
|
||||
}
|
||||
|
||||
*fpu_control_word = safe_read16(addr + 0);
|
||||
|
|
|
@ -14,6 +14,7 @@ align 0x10000
|
|||
; force a #gp if the code section is re-entered
|
||||
mov eax, -1
|
||||
mov cr4, eax
|
||||
hlt
|
||||
|
||||
ok:
|
||||
mov byte [re_entered], 1
|
||||
|
|
|
@ -14,6 +14,7 @@ align 0x10000
|
|||
; force a #gp if the code section is re-entered
|
||||
mov eax, -1
|
||||
mov cr4, eax
|
||||
hlt
|
||||
|
||||
ok:
|
||||
mov byte [re_entered], 1
|
||||
|
|
|
@ -277,8 +277,11 @@ else {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
if(exception === "DE")
|
||||
if(exception === "DE" || exception === "GP")
|
||||
{
|
||||
// XXX: On gdb execution is stopped at this point. On v86 we
|
||||
// currently don't have this ability, so we record the exception
|
||||
// and continue execution
|
||||
recorded_exceptions.push(exception);
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue