diff --git a/bochs/cpu/access.cc b/bochs/cpu/access.cc index 7f23e8c11..af95913e5 100644 --- a/bochs/cpu/access.cc +++ b/bochs/cpu/access.cc @@ -314,13 +314,15 @@ BX_CPU_C::system_read_word(bx_address laddr) } #if BX_SUPPORT_X86_64 - if (! IsCanonical(laddr) || ! IsCanonical(laddr+1)) { + if (! IsCanonical(laddr)) { BX_ERROR(("system_read_word(): canonical failure")); exception(BX_GP_EXCEPTION, 0); } #endif - access_read_linear(laddr, 2, 0, BX_READ, (void *) &data); + if (access_read_linear(laddr, 2, 0, BX_READ, (void *) &data) < 0) + exception(BX_GP_EXCEPTION, 0); + return data; } @@ -346,13 +348,15 @@ BX_CPU_C::system_read_dword(bx_address laddr) } #if BX_SUPPORT_X86_64 - if (! IsCanonical(laddr) || ! IsCanonical(laddr+3)) { + if (! IsCanonical(laddr)) { BX_ERROR(("system_read_dword(): canonical failure")); exception(BX_GP_EXCEPTION, 0); } #endif - access_read_linear(laddr, 4, 0, BX_READ, (void *) &data); + if (access_read_linear(laddr, 4, 0, BX_READ, (void *) &data) < 0) + exception(BX_GP_EXCEPTION, 0); + return data; } @@ -378,13 +382,15 @@ BX_CPU_C::system_read_qword(bx_address laddr) } #if BX_SUPPORT_X86_64 - if (! IsCanonical(laddr) || ! IsCanonical(laddr+7)) { + if (! IsCanonical(laddr)) { BX_ERROR(("system_read_qword(): canonical failure")); exception(BX_GP_EXCEPTION, 0); } #endif - access_read_linear(laddr, 8, 0, BX_READ, (void *) &data); + if (access_read_linear(laddr, 8, 0, BX_READ, (void *) &data) < 0) + exception(BX_GP_EXCEPTION, 0); + return data; } @@ -441,13 +447,14 @@ BX_CPU_C::system_write_word(bx_address laddr, Bit16u data) } #if BX_SUPPORT_X86_64 - if (! IsCanonical(laddr) || ! IsCanonical(laddr+1)) { + if (! IsCanonical(laddr)) { BX_ERROR(("system_write_word(): canonical failure")); exception(BX_GP_EXCEPTION, 0); } #endif - access_write_linear(laddr, 2, 0, (void *) &data); + if (access_write_linear(laddr, 2, 0, (void *) &data) < 0) + exception(BX_GP_EXCEPTION, 0); } void BX_CPP_AttrRegparmN(2) @@ -472,13 +479,14 @@ BX_CPU_C::system_write_dword(bx_address laddr, Bit32u data) } #if BX_SUPPORT_X86_64 - if (! IsCanonical(laddr) || ! IsCanonical(laddr+3)) { + if (! IsCanonical(laddr)) { BX_ERROR(("system_write_dword(): canonical failure")); exception(BX_GP_EXCEPTION, 0); } #endif - access_write_linear(laddr, 4, 0, (void *) &data); + if (access_write_linear(laddr, 4, 0, (void *) &data) < 0) + exception(BX_GP_EXCEPTION, 0); } Bit8u* BX_CPP_AttrRegparmN(2) diff --git a/bochs/cpu/access64.cc b/bochs/cpu/access64.cc index 81c7eb0df..ca0736bc9 100644 --- a/bochs/cpu/access64.cc +++ b/bochs/cpu/access64.cc @@ -102,12 +102,8 @@ BX_CPU_C::write_virtual_word_64(unsigned s, Bit64u offset, Bit16u data) } #endif - if (! IsCanonical(laddr+1)) { - BX_ERROR(("write_virtual_word_64(): canonical failure")); + if (access_write_linear(laddr, 2, CPL, (void *) &data) < 0) exception(int_number(s), 0); - } - - access_write_linear(laddr, 2, CPL, (void *) &data); } void BX_CPP_AttrRegparmN(3) @@ -152,12 +148,8 @@ BX_CPU_C::write_virtual_dword_64(unsigned s, Bit64u offset, Bit32u data) } #endif - if (! IsCanonical(laddr+3)) { - BX_ERROR(("write_virtual_dword_64(): canonical failure")); + if (access_write_linear(laddr, 4, CPL, (void *) &data) < 0) exception(int_number(s), 0); - } - - access_write_linear(laddr, 4, CPL, (void *) &data); } void BX_CPP_AttrRegparmN(3) @@ -202,12 +194,8 @@ BX_CPU_C::write_virtual_qword_64(unsigned s, Bit64u offset, Bit64u data) } #endif - if (! IsCanonical(laddr+7)) { - BX_ERROR(("write_virtual_qword_64(): canonical failure")); + if (access_write_linear(laddr, 8, CPL, (void *) &data) < 0) exception(int_number(s), 0); - } - - access_write_linear(laddr, 8, CPL, (void *) &data); } void BX_CPP_AttrRegparmN(3) @@ -235,12 +223,13 @@ BX_CPU_C::write_virtual_xmmword_64(unsigned s, Bit64u offset, const BxPackedXmmR } } - if (! IsCanonical(laddr) || ! IsCanonical(laddr+15)) { + if (! IsCanonical(laddr)) { BX_ERROR(("write_virtual_xmmword_64(): canonical failure")); exception(int_number(s), 0); } - access_write_linear(laddr, 16, CPL, (void *) data); + if (access_write_linear(laddr, 16, CPL, (void *) data) < 0) + exception(int_number(s), 0); } void BX_CPP_AttrRegparmN(3) @@ -308,12 +297,13 @@ void BX_CPU_C::write_virtual_ymmword_64(unsigned s, Bit64u offset, const BxPacke } } - if (! IsCanonical(laddr) || ! IsCanonical(laddr+31)) { + if (! IsCanonical(laddr)) { BX_ERROR(("write_virtual_ymmword_64(): canonical failure")); exception(int_number(s), 0); } - access_write_linear(laddr, 32, CPL, (void *) data); + if (access_write_linear(laddr, 32, CPL, (void *) data) < 0) + exception(int_number(s), 0); } void BX_CPU_C::write_virtual_ymmword_aligned_64(unsigned s, Bit64u offset, const BxPackedYmmRegister *data) @@ -388,7 +378,8 @@ void BX_CPU_C::write_virtual_zmmword_64(unsigned s, Bit64u offset, const BxPacke exception(int_number(s), 0); } - access_write_linear(laddr, 64, CPL, (void *) data); + if (access_write_linear(laddr, 64, CPL, (void *) data) < 0) + exception(int_number(s), 0); } void BX_CPU_C::write_virtual_zmmword_aligned_64(unsigned s, Bit64u offset, const BxPackedZmmRegister *data) @@ -504,12 +495,9 @@ BX_CPU_C::read_virtual_word_64(unsigned s, Bit64u offset) } #endif - if (! IsCanonical(laddr+1)) { - BX_ERROR(("read_virtual_word_64(): canonical failure")); + if (access_read_linear(laddr, 2, CPL, BX_READ, (void *) &data) < 0) exception(int_number(s), 0); - } - access_read_linear(laddr, 2, CPL, BX_READ, (void *) &data); return data; } @@ -554,12 +542,9 @@ BX_CPU_C::read_virtual_dword_64(unsigned s, Bit64u offset) } #endif - if (! IsCanonical(laddr+3)) { - BX_ERROR(("read_virtual_dword_64(): canonical failure")); + if (access_read_linear(laddr, 4, CPL, BX_READ, (void *) &data) < 0) exception(int_number(s), 0); - } - access_read_linear(laddr, 4, CPL, BX_READ, (void *) &data); return data; } @@ -604,12 +589,9 @@ BX_CPU_C::read_virtual_qword_64(unsigned s, Bit64u offset) } #endif - if (! IsCanonical(laddr+7)) { - BX_ERROR(("read_virtual_qword_64(): canonical failure")); + if (access_read_linear(laddr, 8, CPL, BX_READ, (void *) &data) < 0) exception(int_number(s), 0); - } - access_read_linear(laddr, 8, CPL, BX_READ, (void *) &data); return data; } @@ -636,12 +618,13 @@ BX_CPU_C::read_virtual_xmmword_64(unsigned s, Bit64u offset, BxPackedXmmRegister } } - if (! IsCanonical(laddr) || ! IsCanonical(laddr+15)) { + if (! IsCanonical(laddr)) { BX_ERROR(("read_virtual_xmmword_64(): canonical failure")); exception(int_number(s), 0); } - access_read_linear(laddr, 16, CPL, BX_READ, (void *) data); + if (access_read_linear(laddr, 16, CPL, BX_READ, (void *) &data) < 0) + exception(int_number(s), 0); } void BX_CPP_AttrRegparmN(3) @@ -705,12 +688,13 @@ void BX_CPU_C::read_virtual_ymmword_64(unsigned s, Bit64u offset, BxPackedYmmReg } } - if (! IsCanonical(laddr) || ! IsCanonical(laddr+31)) { + if (! IsCanonical(laddr)) { BX_ERROR(("read_virtual_ymmword_64(): canonical failure")); exception(int_number(s), 0); } - access_read_linear(laddr, 32, CPL, BX_READ, (void *) data); + if (access_read_linear(laddr, 32, CPL, BX_READ, (void *) &data) < 0) + exception(int_number(s), 0); } void BX_CPU_C::read_virtual_ymmword_aligned_64(unsigned s, Bit64u offset, BxPackedYmmRegister *data) @@ -776,12 +760,13 @@ void BX_CPU_C::read_virtual_zmmword_64(unsigned s, Bit64u offset, BxPackedZmmReg } } - if (! IsCanonical(laddr) || ! IsCanonical(laddr+63)) { + if (! IsCanonical(laddr)) { BX_ERROR(("read_virtual_ymmword_64(): canonical failure")); exception(int_number(s), 0); } - access_read_linear(laddr, 64, CPL, BX_READ, (void *) data); + if (access_read_linear(laddr, 64, CPL, BX_READ, (void *) &data) < 0) + exception(int_number(s), 0); } void BX_CPU_C::read_virtual_zmmword_aligned_64(unsigned s, Bit64u offset, BxPackedZmmRegister *data) @@ -908,12 +893,9 @@ BX_CPU_C::read_RMW_virtual_word_64(unsigned s, Bit64u offset) } #endif - if (! IsCanonical(laddr+1)) { - BX_ERROR(("read_RMW_virtual_word_64(): canonical failure")); + if (access_read_linear(laddr, 2, CPL, BX_RW, (void *) &data) < 0) exception(int_number(s), 0); - } - access_read_linear(laddr, 2, CPL, BX_RW, (void *) &data); return data; } @@ -962,12 +944,9 @@ BX_CPU_C::read_RMW_virtual_dword_64(unsigned s, Bit64u offset) } #endif - if (! IsCanonical(laddr+3)) { - BX_ERROR(("read_RMW_virtual_dword_64(): canonical failure")); + if (access_read_linear(laddr, 4, CPL, BX_RW, (void *) &data) < 0) exception(int_number(s), 0); - } - access_read_linear(laddr, 4, CPL, BX_RW, (void *) &data); return data; } @@ -1016,12 +995,9 @@ BX_CPU_C::read_RMW_virtual_qword_64(unsigned s, Bit64u offset) } #endif - if (! IsCanonical(laddr+7)) { - BX_ERROR(("read_RMW_virtual_qword_64(): canonical failure")); + if (access_read_linear(laddr, 8, CPL, BX_RW, (void *) &data) < 0) exception(int_number(s), 0); - } - access_read_linear(laddr, 8, CPL, BX_RW, (void *) &data); return data; } @@ -1121,12 +1097,8 @@ void BX_CPU_C::write_new_stack_word_64(Bit64u laddr, unsigned curr_pl, Bit16u da } #endif - if (! IsCanonical(laddr+1)) { - BX_ERROR(("write_new_stack_word_64(): canonical failure")); + if (access_write_linear(laddr, 2, curr_pl, (void *) &data) < 0) exception(BX_SS_EXCEPTION, 0); - } - - access_write_linear(laddr, 2, curr_pl, (void *) &data); } void BX_CPU_C::write_new_stack_dword_64(Bit64u laddr, unsigned curr_pl, Bit32u data) @@ -1168,12 +1140,8 @@ void BX_CPU_C::write_new_stack_dword_64(Bit64u laddr, unsigned curr_pl, Bit32u d } #endif - if (! IsCanonical(laddr+3)) { - BX_ERROR(("write_new_stack_dword_64(): canonical failure")); + if (access_write_linear(laddr, 4, curr_pl, (void *) &data) < 0) exception(BX_SS_EXCEPTION, 0); - } - - access_write_linear(laddr, 4, curr_pl, (void *) &data); } void BX_CPU_C::write_new_stack_qword_64(Bit64u laddr, unsigned curr_pl, Bit64u data) @@ -1215,12 +1183,8 @@ void BX_CPU_C::write_new_stack_qword_64(Bit64u laddr, unsigned curr_pl, Bit64u d } #endif - if (! IsCanonical(laddr+7)) { - BX_ERROR(("write_new_stack_qword_64(): canonical failure")); + if (access_write_linear(laddr, 8, curr_pl, (void *) &data) < 0) exception(BX_SS_EXCEPTION, 0); - } - - access_write_linear(laddr, 8, curr_pl, (void *) &data); } #endif diff --git a/bochs/cpu/cpu.h b/bochs/cpu/cpu.h index bece299bf..a42e231a8 100644 --- a/bochs/cpu/cpu.h +++ b/bochs/cpu/cpu.h @@ -4352,9 +4352,9 @@ public: // for now... BX_SMF void repeat_ZF(bxInstruction_c *i, BxRepIterationPtr_tR execute) BX_CPP_AttrRegparmN(2); // linear address for access_linear expected to be canonical ! - BX_SMF void access_read_linear(bx_address laddr, unsigned len, unsigned curr_pl, + BX_SMF int access_read_linear(bx_address laddr, unsigned len, unsigned curr_pl, unsigned rw, void *data); - BX_SMF void access_write_linear(bx_address laddr, unsigned len, unsigned curr_pl, + BX_SMF int access_write_linear(bx_address laddr, unsigned len, unsigned curr_pl, void *data); BX_SMF void page_fault(unsigned fault, bx_address laddr, unsigned user, unsigned rw); diff --git a/bochs/cpu/paging.cc b/bochs/cpu/paging.cc index 7ee003b9c..9bedc99be 100644 --- a/bochs/cpu/paging.cc +++ b/bochs/cpu/paging.cc @@ -1901,7 +1901,7 @@ page_fault: } #endif -void BX_CPU_C::access_write_linear(bx_address laddr, unsigned len, unsigned curr_pl, void *data) +int BX_CPU_C::access_write_linear(bx_address laddr, unsigned len, unsigned curr_pl, void *data) { Bit32u pageOffset = PAGE_OFFSET(laddr); @@ -1924,14 +1924,21 @@ void BX_CPU_C::access_write_linear(bx_address laddr, unsigned len, unsigned curr } else { // access across 2 pages - BX_CPU_THIS_PTR address_xlation.paddress1 = translate_linear(tlbEntry, laddr, (curr_pl == 3), BX_WRITE); BX_CPU_THIS_PTR address_xlation.len1 = 4096 - pageOffset; BX_CPU_THIS_PTR address_xlation.len2 = len - BX_CPU_THIS_PTR address_xlation.len1; BX_CPU_THIS_PTR address_xlation.pages = 2; bx_address laddr2 = laddr + BX_CPU_THIS_PTR address_xlation.len1; #if BX_SUPPORT_X86_64 if (! long64_mode()) laddr2 &= 0xffffffff; /* handle linear address wrap in legacy mode */ + else { + if (! IsCanonical(laddr2)) { + BX_ERROR(("access_write_linear(): canonical failure for second half of page split access")); + return -1; + } + } #endif + + BX_CPU_THIS_PTR address_xlation.paddress1 = translate_linear(tlbEntry, laddr, (curr_pl == 3), BX_WRITE); BX_CPU_THIS_PTR address_xlation.paddress2 = translate_linear(BX_TLB_ENTRY_OF(laddr2), laddr2, (curr_pl == 3), BX_WRITE); #ifdef BX_LITTLE_ENDIAN @@ -1965,9 +1972,11 @@ void BX_CPU_C::access_write_linear(bx_address laddr, unsigned len, unsigned curr hwbreakpoint_match(laddr2, BX_CPU_THIS_PTR address_xlation.len2, BX_WRITE); #endif } + + return 0; } -void BX_CPU_C::access_read_linear(bx_address laddr, unsigned len, unsigned curr_pl, unsigned xlate_rw, void *data) +int BX_CPU_C::access_read_linear(bx_address laddr, unsigned len, unsigned curr_pl, unsigned xlate_rw, void *data) { BX_ASSERT(xlate_rw == BX_READ || xlate_rw == BX_RW); @@ -1989,14 +1998,20 @@ void BX_CPU_C::access_read_linear(bx_address laddr, unsigned len, unsigned curr_ } else { // access across 2 pages - BX_CPU_THIS_PTR address_xlation.paddress1 = translate_linear(tlbEntry, laddr, (curr_pl == 3), xlate_rw); BX_CPU_THIS_PTR address_xlation.len1 = 4096 - pageOffset; BX_CPU_THIS_PTR address_xlation.len2 = len - BX_CPU_THIS_PTR address_xlation.len1; BX_CPU_THIS_PTR address_xlation.pages = 2; bx_address laddr2 = laddr + BX_CPU_THIS_PTR address_xlation.len1; #if BX_SUPPORT_X86_64 if (! long64_mode()) laddr2 &= 0xffffffff; /* handle linear address wrap in legacy mode */ + else { + if (! IsCanonical(laddr2)) { + BX_ERROR(("access_read_linear(): canonical failure for second half of page split access")); + return -1; + } + } #endif + BX_CPU_THIS_PTR address_xlation.paddress1 = translate_linear(tlbEntry, laddr, (curr_pl == 3), xlate_rw); BX_CPU_THIS_PTR address_xlation.paddress2 = translate_linear(BX_TLB_ENTRY_OF(laddr2), laddr2, (curr_pl == 3), xlate_rw); #ifdef BX_LITTLE_ENDIAN @@ -2030,6 +2045,8 @@ void BX_CPU_C::access_read_linear(bx_address laddr, unsigned len, unsigned curr_ hwbreakpoint_match(laddr2, BX_CPU_THIS_PTR address_xlation.len2, xlate_rw); #endif } + + return 0; } void BX_CPU_C::access_write_physical(bx_phy_address paddr, unsigned len, void *data)