Properly load pdptes when cr3 is loaded (fixes Ubuntu 16)
This commit is contained in:
parent
700225bb6b
commit
229310e686
|
@ -233,7 +233,7 @@
|
|||
use_parts: !ON_LOCALHOST,
|
||||
},
|
||||
memory_size: 512 * 1024 * 1024,
|
||||
state: { url: host + "serenity_state.bin.zst", },
|
||||
state: { url: host + "serenity_state-v2.bin.zst", },
|
||||
homepage: "https://serenityos.org/",
|
||||
},
|
||||
{
|
||||
|
|
|
@ -158,6 +158,8 @@ function CPU(bus, wm)
|
|||
// debug registers
|
||||
this.dreg = v86util.view(Int32Array, memory, 684, 8);
|
||||
|
||||
this.reg_pdpte = v86util.view(Int32Array, memory, 968, 8);
|
||||
|
||||
this.fw_value = [];
|
||||
this.fw_pointer = 0;
|
||||
this.option_roms = [];
|
||||
|
@ -341,6 +343,7 @@ CPU.prototype.get_state = function()
|
|||
state[39] = this.reg32;
|
||||
state[40] = this.sreg;
|
||||
state[41] = this.dreg;
|
||||
state[42] = this.reg_pdpte;
|
||||
|
||||
this.store_current_tsc();
|
||||
state[43] = this.current_tsc;
|
||||
|
@ -437,6 +440,7 @@ CPU.prototype.set_state = function(state)
|
|||
this.reg32.set(state[39]);
|
||||
this.sreg.set(state[40]);
|
||||
this.dreg.set(state[41]);
|
||||
state[42] && this.reg_pdpte.set(state[42]);
|
||||
|
||||
this.set_tsc(state[43][0], state[43][1]);
|
||||
|
||||
|
|
|
@ -165,6 +165,7 @@ pub const CR4_PAE: i32 = 1 << 5;
|
|||
pub const CR4_PGE: i32 = 1 << 7;
|
||||
pub const CR4_OSFXSR: i32 = 1 << 9;
|
||||
pub const CR4_OSXMMEXCPT: i32 = 1 << 10;
|
||||
pub const CR4_SMEP: i32 = 1 << 20;
|
||||
|
||||
pub const TSR_BACKLINK: i32 = 0x00;
|
||||
pub const TSR_CR3: i32 = 0x1C;
|
||||
|
@ -1695,9 +1696,7 @@ pub unsafe fn do_task_switch(selector: i32, error_code: Option<i32>) {
|
|||
*segment_limits.offset(TR as isize) = descriptor.effective_limit();
|
||||
*sreg.offset(TR as isize) = selector.raw;
|
||||
|
||||
*cr.offset(3) = new_cr3;
|
||||
dbg_assert!((*cr.offset(3) & 0xFFF) == 0);
|
||||
clear_tlb();
|
||||
set_cr3(new_cr3);
|
||||
|
||||
*cr.offset(0) |= CR0_TS;
|
||||
|
||||
|
@ -1831,9 +1830,7 @@ pub unsafe fn do_page_walk(
|
|||
let pae = cr4 & CR4_PAE != 0;
|
||||
|
||||
let (page_dir_addr, page_dir_entry) = if pae {
|
||||
// XXX: This should execute when cr3 is loaded
|
||||
let pdpt_addr = *cr.offset(3) as u32 + (((addr as u32) >> 30) << 3);
|
||||
let pdpt_entry = read64s(pdpt_addr);
|
||||
let pdpt_entry = *reg_pdpte.offset(((addr as u32) >> 30) as isize);
|
||||
if pdpt_entry as i32 & PAGE_TABLE_PRESENT_MASK == 0 {
|
||||
return Err(PageFault {
|
||||
addr,
|
||||
|
@ -1842,10 +1839,6 @@ pub unsafe fn do_page_walk(
|
|||
present: false,
|
||||
});
|
||||
}
|
||||
dbg_assert!(
|
||||
pdpt_entry as u64 & 0xFFFF_FFFF_0000_0000 == 0,
|
||||
"Unsupported: PDPT entry larger than 32 bits"
|
||||
);
|
||||
|
||||
let page_dir_addr =
|
||||
(pdpt_entry as u32 & 0xFFFFF000) + ((((addr as u32) >> 21) & 0x1FF) << 3);
|
||||
|
@ -2680,9 +2673,51 @@ pub unsafe fn set_cr0(cr0: i32) {
|
|||
full_clear_tlb();
|
||||
}
|
||||
|
||||
if *cr.offset(4) & CR4_PAE != 0
|
||||
&& old_cr0 & (CR0_CD | CR0_NW | CR0_PG) != cr0 & (CR0_CD | CR0_NW | CR0_PG)
|
||||
{
|
||||
load_pdpte(*cr.offset(3))
|
||||
}
|
||||
|
||||
*protected_mode = (*cr & CR0_PE) == CR0_PE;
|
||||
}
|
||||
|
||||
pub unsafe fn set_cr3(mut cr3: i32) {
|
||||
if false {
|
||||
dbg_log!("cr3 <- {:x}", cr3);
|
||||
}
|
||||
if *cr.offset(4) & CR4_PAE != 0 {
|
||||
cr3 &= !0b1111;
|
||||
load_pdpte(cr3);
|
||||
}
|
||||
else {
|
||||
cr3 &= !0b111111100111;
|
||||
dbg_assert!(cr3 & 0xFFF == 0, "TODO");
|
||||
}
|
||||
*cr.offset(3) = cr3;
|
||||
clear_tlb();
|
||||
}
|
||||
|
||||
pub unsafe fn load_pdpte(cr3: i32) {
|
||||
dbg_assert!(cr3 & 0b1111 == 0);
|
||||
for i in 0..4 {
|
||||
let mut pdpt_entry = read64s(cr3 as u32 + 8 * i as u32) as u64;
|
||||
pdpt_entry &= !0b1110_0000_0000;
|
||||
dbg_assert!(pdpt_entry & 0b11000 == 0, "TODO");
|
||||
dbg_assert!(
|
||||
pdpt_entry as u64 & 0xFFFF_FFFF_0000_0000 == 0,
|
||||
"Unsupported: PDPT entry larger than 32 bits"
|
||||
);
|
||||
if pdpt_entry as i32 & PAGE_TABLE_PRESENT_MASK != 0 {
|
||||
dbg_assert!(
|
||||
pdpt_entry & 0b1_1110_0110 == 0,
|
||||
"TODO: #gp reserved bit in pdpte"
|
||||
);
|
||||
}
|
||||
*reg_pdpte.offset(i) = pdpt_entry;
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn cpl_changed() { *last_virt_eip = -1; }
|
||||
|
||||
pub unsafe fn update_cs_size(new_size: bool) {
|
||||
|
@ -4144,6 +4179,10 @@ pub unsafe fn reset_cpu() {
|
|||
*fpu_st.offset(i) = ::softfloat::F80::ZERO;
|
||||
}
|
||||
|
||||
for i in 0..4 {
|
||||
*reg_pdpte.offset(i) = 0
|
||||
}
|
||||
|
||||
*fpu_stack_empty = 0xFF;
|
||||
*fpu_stack_ptr = 0;
|
||||
*fpu_control_word = 0x37F;
|
||||
|
|
|
@ -53,6 +53,8 @@ pub const mxcsr: *mut i32 = 824 as *mut i32;
|
|||
pub const reg_xmm: *mut reg128 = 832 as *mut reg128;
|
||||
pub const current_tsc: *mut u64 = 960 as *mut u64;
|
||||
|
||||
pub const reg_pdpte: *mut u64 = 968 as *mut u64; // 4 64-bit entries
|
||||
|
||||
pub const fpu_stack_ptr: *mut u8 = 1032 as *mut u8;
|
||||
pub const fpu_control_word: *mut u16 = 1036 as *mut u16;
|
||||
pub const fpu_status_word: *mut u16 = 1040 as *mut u16;
|
||||
|
|
|
@ -766,7 +766,7 @@ pub unsafe fn instr_0F22(r: i32, creg: i32) {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut data: i32 = read_reg32(r);
|
||||
let data = read_reg32(r);
|
||||
// mov cr, addr
|
||||
match creg {
|
||||
0 => {
|
||||
|
@ -779,17 +779,9 @@ pub unsafe fn instr_0F22(r: i32, creg: i32) {
|
|||
dbg_log!("cr2 <- {:x}", data);
|
||||
*cr.offset(2) = data
|
||||
},
|
||||
3 => {
|
||||
if false {
|
||||
dbg_log!("cr3 <- {:x}", data);
|
||||
}
|
||||
data &= !0b111111100111;
|
||||
dbg_assert!(data & 0xFFF == 0, "TODO");
|
||||
*cr.offset(3) = data;
|
||||
clear_tlb();
|
||||
},
|
||||
3 => set_cr3(data),
|
||||
4 => {
|
||||
dbg_log!("cr4 <- {:x}", *cr.offset(4));
|
||||
dbg_log!("cr4 <- {:x}", data);
|
||||
if 0 != data as u32
|
||||
& ((1 << 11 | 1 << 12 | 1 << 15 | 1 << 16 | 1 << 19) as u32 | 0xFFC00000)
|
||||
{
|
||||
|
@ -801,6 +793,11 @@ pub unsafe fn instr_0F22(r: i32, creg: i32) {
|
|||
if 0 != (*cr.offset(4) ^ data) & (CR4_PGE | CR4_PSE | CR4_PAE) {
|
||||
full_clear_tlb();
|
||||
}
|
||||
if data & CR4_PAE != 0
|
||||
&& 0 != (*cr.offset(4) ^ data) & (CR4_PGE | CR4_PSE | CR4_SMEP)
|
||||
{
|
||||
load_pdpte(*cr.offset(3));
|
||||
}
|
||||
*cr.offset(4) = data;
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue