avoid calling jit_dirty_page after page walk in jit mode

This commit is contained in:
Fabian 2022-11-05 19:45:18 -06:00
parent 9ecee545c8
commit 7fb9654920

View file

@ -1803,8 +1803,26 @@ pub unsafe fn translate_address_read_jit(address: i32) -> OrPageFault<u32> {
pub unsafe fn translate_address_write(address: i32) -> OrPageFault<u32> { pub unsafe fn translate_address_write(address: i32) -> OrPageFault<u32> {
translate_address(address, true, *cpl == 3, false, true) translate_address(address, true, *cpl == 3, false, true)
} }
pub unsafe fn translate_address_write_jit(address: i32) -> OrPageFault<u32> { pub unsafe fn translate_address_write_jit_and_can_skip_dirty(
translate_address(address, true, *cpl == 3, true, true) address: i32,
) -> OrPageFault<(u32, bool)> {
let entry = tlb_data[(address as u32 >> 12) as usize];
let user = *cpl == 3;
if entry & (TLB_VALID | if user { TLB_NO_USER } else { 0 } | TLB_READONLY) == TLB_VALID {
Ok((
(entry & !0xFFF ^ address) as u32 - memory::mem8 as u32,
entry & TLB_HAS_CODE == 0,
))
}
else {
match do_page_walk(address, true, user, true) {
Ok((phys_addr_high, skip)) => Ok((phys_addr_high | address as u32 & 0xFFF, skip)),
Err(pagefault) => {
trigger_pagefault_jit(pagefault);
Err(())
},
}
}
} }
pub unsafe fn translate_address_system_read(address: i32) -> OrPageFault<u32> { pub unsafe fn translate_address_system_read(address: i32) -> OrPageFault<u32> {
@ -1833,7 +1851,7 @@ pub unsafe fn translate_address(
} }
else { else {
match do_page_walk(address, for_writing, user, side_effects) { match do_page_walk(address, for_writing, user, side_effects) {
Ok(phys_addr_high) => Ok(phys_addr_high | address as u32 & 0xFFF), Ok((phys_addr_high, _)) => Ok(phys_addr_high | address as u32 & 0xFFF),
Err(pagefault) => { Err(pagefault) => {
if side_effects { if side_effects {
if jit { if jit {
@ -1860,7 +1878,7 @@ pub unsafe fn translate_address_write_and_can_skip_dirty(address: i32) -> OrPage
} }
else { else {
match do_page_walk(address, true, user, true) { match do_page_walk(address, true, user, true) {
Ok(phys_addr_high) => Ok((phys_addr_high | address as u32 & 0xFFF, false)), Ok((phys_addr_high, skip)) => Ok((phys_addr_high | address as u32 & 0xFFF, skip)),
Err(pagefault) => { Err(pagefault) => {
trigger_pagefault(pagefault); trigger_pagefault(pagefault);
Err(()) Err(())
@ -1893,7 +1911,7 @@ pub unsafe fn do_page_walk(
for_writing: bool, for_writing: bool,
user: bool, user: bool,
side_effects: bool, side_effects: bool,
) -> Result<u32, PageFault> { ) -> Result<(u32, bool), PageFault> {
let global; let global;
let mut allow_user: bool = true; let mut allow_user: bool = true;
let page = (addr as u32 >> 12) as i32; let page = (addr as u32 >> 12) as i32;
@ -2112,7 +2130,7 @@ pub unsafe fn do_page_walk(
jit::update_tlb_code(Page::page_of(addr as u32), Page::page_of(high)); jit::update_tlb_code(Page::page_of(addr as u32), Page::page_of(high));
} }
return Ok(high); return Ok((high, !has_code));
} }
#[no_mangle] #[no_mangle]
@ -3351,7 +3369,7 @@ pub unsafe fn safe_read_slow_jit(addr: i32, bitsize: i32, start_eip: i32, is_wri
} }
let crosses_page = (addr & 0xFFF) + bitsize / 8 > 0x1000; let crosses_page = (addr & 0xFFF) + bitsize / 8 > 0x1000;
let addr_low = match if is_write { let addr_low = match if is_write {
translate_address_write_jit(addr) translate_address_write_jit_and_can_skip_dirty(addr).map(|x| x.0)
} }
else { else {
translate_address_read_jit(addr) translate_address_read_jit(addr)
@ -3365,7 +3383,7 @@ pub unsafe fn safe_read_slow_jit(addr: i32, bitsize: i32, start_eip: i32, is_wri
if crosses_page { if crosses_page {
let boundary_addr = (addr | 0xFFF) + 1; let boundary_addr = (addr | 0xFFF) + 1;
let addr_high = match if is_write { let addr_high = match if is_write {
translate_address_write_jit(boundary_addr) translate_address_write_jit_and_can_skip_dirty(boundary_addr).map(|x| x.0)
} }
else { else {
translate_address_read_jit(boundary_addr) translate_address_read_jit(boundary_addr)
@ -3491,21 +3509,23 @@ pub unsafe fn safe_write_slow_jit(
); );
} }
let crosses_page = (addr & 0xFFF) + bitsize / 8 > 0x1000; let crosses_page = (addr & 0xFFF) + bitsize / 8 > 0x1000;
let addr_low = match translate_address_write_jit(addr) { let (addr_low, can_skip_dirty_page) = match translate_address_write_jit_and_can_skip_dirty(addr)
{
Err(()) => { Err(()) => {
*instruction_pointer = *instruction_pointer & !0xFFF | start_eip & 0xFFF; *instruction_pointer = *instruction_pointer & !0xFFF | start_eip & 0xFFF;
return 1; return 1;
}, },
Ok(addr) => addr, Ok(x) => x,
}; };
if crosses_page { if crosses_page {
let addr_high = match translate_address_write_jit((addr | 0xFFF) + 1) { let (addr_high, _) =
Err(()) => { match translate_address_write_jit_and_can_skip_dirty((addr | 0xFFF) + 1) {
*instruction_pointer = *instruction_pointer & !0xFFF | start_eip & 0xFFF; Err(()) => {
return 1; *instruction_pointer = *instruction_pointer & !0xFFF | start_eip & 0xFFF;
}, return 1;
Ok(addr) => addr, },
}; Ok(x) => x,
};
// TODO: Could check if virtual pages point to consecutive physical and go to fast path // TODO: Could check if virtual pages point to consecutive physical and go to fast path
// do write, return dummy pointer for fast path to write into // do write, return dummy pointer for fast path to write into
@ -3554,7 +3574,9 @@ pub unsafe fn safe_write_slow_jit(
((scratch as i32) ^ addr) & !0xFFF ((scratch as i32) ^ addr) & !0xFFF
} }
else { else {
jit::jit_dirty_page(jit::get_jit_state(), Page::page_of(addr_low)); if !can_skip_dirty_page {
jit::jit_dirty_page(jit::get_jit_state(), Page::page_of(addr_low));
}
((addr_low as i32 + memory::mem8 as i32) ^ addr) & !0xFFF ((addr_low as i32 + memory::mem8 as i32) ^ addr) & !0xFFF
} }
} }