Remove use of cpu exceptions for trigger_gp for instructions

This commit is contained in:
Fabian 2018-07-21 15:52:30 -06:00
parent 33912bee28
commit f43ab3387a
9 changed files with 93 additions and 64 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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;
}