mirror of https://github.com/bochs-emu/Bochs
Removed patch which I committed to CVS.
This commit is contained in:
parent
3a5f338419
commit
944697affb
|
@ -1,644 +0,0 @@
|
||||||
----------------------------------------------------------------------
|
|
||||||
Patch name: patch.kpl-paging-cleanup
|
|
||||||
Author: Kevin Lawton
|
|
||||||
Date: Sat Aug 31 22:17:47 EDT 2002
|
|
||||||
|
|
||||||
Detailed description:
|
|
||||||
|
|
||||||
I rehashed dtranslate_linear() and itranslate_linear(), to behave
|
|
||||||
like a real CPU. There were several flaws and semantical differences
|
|
||||||
compared with how a real CPU behaves, which are fixed by this patch.
|
|
||||||
|
|
||||||
Additionally, a few things behave differently depending on the level
|
|
||||||
of CPU that is being emulated; notably from the P6 architecture on,
|
|
||||||
where the A/D bits is set is a little different. A couple new #ifdefs
|
|
||||||
take care of that.
|
|
||||||
|
|
||||||
Bochs was generating a fault if the current access was not matching
|
|
||||||
the TLB entry. Now, a table re-walk occurs to opt for updated info
|
|
||||||
in the memory image of the page tables, before an fault is invoked.
|
|
||||||
It is possible, the memory image contains access permissions which
|
|
||||||
are OK, and thus those are taken and re-cached rather than a
|
|
||||||
fault, when applicable.
|
|
||||||
|
|
||||||
Bochs was also storing the address of the PTE, in case the first
|
|
||||||
access seen was a read, and subsequently a write access necessitated
|
|
||||||
an update of the D bit. Ack!!! If the page tables were updated
|
|
||||||
after the 1st access, we were righting over some previous location!
|
|
||||||
|
|
||||||
Also, I made a new configure option '--enable-4meg-pages', and put
|
|
||||||
some conditional compilation code in bochs. For now, I made
|
|
||||||
disabling 4Meg page support, the default. I bracked the appropriate
|
|
||||||
code in CPUID, MOV_CdRd, and paging.cc. We were defaulting to
|
|
||||||
enabling 4Meg pages, but it is poorly supported. I'm going to
|
|
||||||
look into better support for it.
|
|
||||||
|
|
||||||
Many of these mods are a result of tests which I ran on machines,
|
|
||||||
and on bochs (before/after). I recommed integrating these,
|
|
||||||
because current bochs paging behavior is broken.
|
|
||||||
|
|
||||||
Please rerun 'autoconf'. I'm not big on diff'ing 'configure'.
|
|
||||||
|
|
||||||
|
|
||||||
Patch was created with:
|
|
||||||
cvs diff -u
|
|
||||||
Apply patch to what version:
|
|
||||||
cvs checked out on August 31, 2002
|
|
||||||
Instructions:
|
|
||||||
To patch, go to main bochs directory.
|
|
||||||
Type "patch -p0 < THIS_PATCH_FILE".
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
Index: config.h.in
|
|
||||||
===================================================================
|
|
||||||
RCS file: /cvsroot/bochs/bochs/config.h.in,v
|
|
||||||
retrieving revision 1.55
|
|
||||||
diff -u -r1.55 config.h.in
|
|
||||||
--- config.h.in 30 Aug 2002 06:47:21 -0000 1.55
|
|
||||||
+++ config.h.in 1 Sep 2002 03:16:27 -0000
|
|
||||||
@@ -559,6 +559,7 @@
|
|
||||||
|
|
||||||
#define BX_SUPPORT_FPU 0
|
|
||||||
#define BX_SUPPORT_MMX 0
|
|
||||||
+#define BX_SUPPORT_4MEG_PAGES 0
|
|
||||||
|
|
||||||
#define BX_HAVE_GETENV 0
|
|
||||||
#define BX_HAVE_SELECT 0
|
|
||||||
Index: configure.in
|
|
||||||
===================================================================
|
|
||||||
RCS file: /cvsroot/bochs/bochs/configure.in,v
|
|
||||||
retrieving revision 1.89
|
|
||||||
diff -u -r1.89 configure.in
|
|
||||||
--- configure.in 26 Aug 2002 19:06:59 -0000 1.89
|
|
||||||
+++ configure.in 1 Sep 2002 03:16:45 -0000
|
|
||||||
@@ -545,6 +545,24 @@
|
|
||||||
AC_SUBST(PCI_OBJ)
|
|
||||||
|
|
||||||
|
|
||||||
+AC_MSG_CHECKING(for 4Meg pages support)
|
|
||||||
+AC_ARG_ENABLE(4meg-pages,
|
|
||||||
+ [ --enable-4meg-pages support 4Megabyte pages extensions],
|
|
||||||
+ [if test "$enableval" = yes; then
|
|
||||||
+ AC_MSG_RESULT(yes)
|
|
||||||
+ AC_DEFINE(BX_SUPPORT_4MEG_PAGES, 1)
|
|
||||||
+ else
|
|
||||||
+ AC_MSG_RESULT(no)
|
|
||||||
+ AC_DEFINE(BX_SUPPORT_4MEG_PAGES, 0)
|
|
||||||
+ fi],
|
|
||||||
+ [
|
|
||||||
+ AC_MSG_RESULT(no)
|
|
||||||
+ AC_DEFINE(BX_SUPPORT_4MEG_PAGES, 0)
|
|
||||||
+ ]
|
|
||||||
+ )
|
|
||||||
+AC_SUBST(BX_SUPPORT_4MEG_PAGES)
|
|
||||||
+
|
|
||||||
+
|
|
||||||
AC_MSG_CHECKING(for port e9 hack)
|
|
||||||
AC_ARG_ENABLE(port-e9-hack,
|
|
||||||
[ --enable-port-e9-hack writes to port e9 go to console],
|
|
||||||
Index: cpu/cpu.h
|
|
||||||
===================================================================
|
|
||||||
RCS file: /cvsroot/bochs/bochs/cpu/cpu.h,v
|
|
||||||
retrieving revision 1.22
|
|
||||||
diff -u -r1.22 cpu.h
|
|
||||||
--- cpu/cpu.h 5 Jun 2002 21:51:30 -0000 1.22
|
|
||||||
+++ cpu/cpu.h 1 Sep 2002 03:16:52 -0000
|
|
||||||
@@ -519,7 +519,6 @@
|
|
||||||
typedef struct {
|
|
||||||
Bit32u lpf; // linear page frame
|
|
||||||
Bit32u ppf; // physical page frame
|
|
||||||
- Bit32u pte_addr; // Page Table Address for updating A & D bits
|
|
||||||
Bit32u combined_access;
|
|
||||||
} bx_TLB_entry;
|
|
||||||
#endif // #if BX_USE_TLB
|
|
||||||
Index: cpu/paging.cc
|
|
||||||
===================================================================
|
|
||||||
RCS file: /cvsroot/bochs/bochs/cpu/paging.cc,v
|
|
||||||
retrieving revision 1.9
|
|
||||||
diff -u -r1.9 paging.cc
|
|
||||||
--- cpu/paging.cc 19 Jun 2002 15:49:07 -0000 1.9
|
|
||||||
+++ cpu/paging.cc 1 Sep 2002 03:16:55 -0000
|
|
||||||
@@ -46,7 +46,6 @@
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-
|
|
||||||
#if 0
|
|
||||||
// X86 Registers Which Affect Paging:
|
|
||||||
// ==================================
|
|
||||||
@@ -465,9 +464,8 @@
|
|
||||||
{
|
|
||||||
Bit32u lpf, ppf, poffset, TLB_index, error_code, paddress;
|
|
||||||
Bit32u pde, pde_addr;
|
|
||||||
- Bit32u pte, pte_addr;
|
|
||||||
unsigned priv_index;
|
|
||||||
- Boolean is_rw;
|
|
||||||
+ Boolean isWrite;
|
|
||||||
Bit32u combined_access, new_combined_access;
|
|
||||||
|
|
||||||
lpf = laddress & 0xfffff000; // linear page frame
|
|
||||||
@@ -475,147 +473,173 @@
|
|
||||||
TLB_index = BX_TLB_INDEX_OF(lpf);
|
|
||||||
|
|
||||||
|
|
||||||
- is_rw = (rw>=BX_WRITE); // write or r-m-w
|
|
||||||
+ isWrite = (rw>=BX_WRITE); // write or r-m-w
|
|
||||||
|
|
||||||
if (BX_CPU_THIS_PTR TLB.entry[TLB_index].lpf == lpf) {
|
|
||||||
paddress = BX_CPU_THIS_PTR TLB.entry[TLB_index].ppf | poffset;
|
|
||||||
combined_access = BX_CPU_THIS_PTR TLB.entry[TLB_index].combined_access;
|
|
||||||
-priv_check:
|
|
||||||
priv_index =
|
|
||||||
#if BX_CPU_LEVEL >= 4
|
|
||||||
(BX_CPU_THIS_PTR cr0.wp<<4) | // bit 4
|
|
||||||
#endif
|
|
||||||
(pl<<3) | // bit 3
|
|
||||||
(combined_access & 0x06) | // bit 2,1
|
|
||||||
- is_rw; // bit 0
|
|
||||||
+ isWrite; // bit 0
|
|
||||||
|
|
||||||
if (priv_check[priv_index]) {
|
|
||||||
// Operation has proper privilege.
|
|
||||||
- // See if A/D bits need updating.
|
|
||||||
- //BW !! a read access does not do any updates, patched load
|
|
||||||
- new_combined_access = combined_access | is_rw;
|
|
||||||
+ // If our TLB entry has _not_ been used with a write before, we need
|
|
||||||
+ // to update the PDE.A/PTE.{A,D} fields with a re-walk.
|
|
||||||
+ new_combined_access = combined_access | isWrite;
|
|
||||||
if (new_combined_access == combined_access) {
|
|
||||||
// A/D bits already up-to-date
|
|
||||||
return(paddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
- // A/D bits need updating first
|
|
||||||
- BX_CPU_THIS_PTR TLB.entry[TLB_index].combined_access = new_combined_access;
|
|
||||||
- pte_addr = BX_CPU_THIS_PTR TLB.entry[TLB_index].pte_addr;
|
|
||||||
- BX_CPU_THIS_PTR mem->read_physical(this, pte_addr, 4, &pte); // get old 4kPTE/4mPDE
|
|
||||||
- pte |= 0x20 | (is_rw << 6);
|
|
||||||
- BX_CPU_THIS_PTR mem->write_physical(this, pte_addr, 4, &pte); // write updated 4kPTE/4mPDE
|
|
||||||
- return(paddress);
|
|
||||||
+ // If we have only seen reads for this TLB entry, but the
|
|
||||||
+ // permissions must be writeable, we must make sure the
|
|
||||||
+ // dirty bit (D) is set. To do this we must rewalk the page
|
|
||||||
+ // tables to find the PTE and to give a chance to pick up updated info.
|
|
||||||
+ goto pageTableWalk; // for clarity and in case of future mods
|
|
||||||
}
|
|
||||||
|
|
||||||
- // Protection violation
|
|
||||||
- error_code = 0xfffffff9; // RSVD=1, P=1
|
|
||||||
- goto page_fault_check;
|
|
||||||
+ // The current access does not have permission according to the info
|
|
||||||
+ // in our TLB cache entry. Re-walk the page tables, in case there is
|
|
||||||
+ // updated information in the memory image, and let the long path code
|
|
||||||
+ // generate an exception if one is warranted.
|
|
||||||
+ goto pageTableWalk; // for clarity and in case of future mods
|
|
||||||
}
|
|
||||||
|
|
||||||
+pageTableWalk:
|
|
||||||
+
|
|
||||||
// Get page dir entry
|
|
||||||
pde_addr = (BX_CPU_THIS_PTR cr3 & 0xfffff000) |
|
|
||||||
((laddress & 0xffc00000) >> 20);
|
|
||||||
BX_CPU_THIS_PTR mem->read_physical(this, pde_addr, 4, &pde);
|
|
||||||
if ( !(pde & 0x01) ) {
|
|
||||||
// Page Directory Entry NOT present
|
|
||||||
- error_code = 0xfffffff8; // RSVD=1, P=0
|
|
||||||
+ error_code = 0x00000000; // RSVD=0, P=0
|
|
||||||
goto page_fault_not_present;
|
|
||||||
}
|
|
||||||
|
|
||||||
- // check for 4Mbyte page
|
|
||||||
+#if BX_SUPPORT_4MEG_PAGES
|
|
||||||
+ // If 4M pages are enabled, and this is a 4Meg page
|
|
||||||
+ if ((pde & 0x80) && (BX_CPU_THIS_PTR cr4 & 0x10)) {
|
|
||||||
+ // Note: when the PSE and PAE flags in CR4 are set,
|
|
||||||
+ // the processor generates a PF if the reserved bits are not
|
|
||||||
+ // set to 0. (We don't handle PAE yet, just a note for
|
|
||||||
+ // the future).
|
|
||||||
|
|
||||||
- if ((pde & 0x80) && (BX_CPU_THIS_PTR cr4 & 0x10)) { // check for 4M page and make sure it's enabled
|
|
||||||
- combined_access = pde & 0x06; // combined access is just access from the pde
|
|
||||||
- ppf = (pde & 0xFFC00000) | (laddress & 0x003FF000); // make up the physical frame number
|
|
||||||
- pte_addr = pde_addr; // A/D bits in same place as a real pte
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- // normal 4Kbyte page
|
|
||||||
-
|
|
||||||
- else {
|
|
||||||
-
|
|
||||||
- // Get page table entry
|
|
||||||
- pte_addr = (pde & 0xfffff000) |
|
|
||||||
- ((laddress & 0x003ff000) >> 10);
|
|
||||||
- BX_CPU_THIS_PTR mem->read_physical(this, pte_addr, 4, &pte);
|
|
||||||
+ // Combined access is just access from the pde (no pte involved).
|
|
||||||
+ combined_access = pde & 0x06;
|
|
||||||
|
|
||||||
+ priv_index =
|
|
||||||
+#if BX_CPU_LEVEL >= 4
|
|
||||||
+ (BX_CPU_THIS_PTR cr0.wp<<4) | // bit 4
|
|
||||||
+#endif
|
|
||||||
+ (pl<<3) | // bit 3
|
|
||||||
+ (combined_access & 0x06) | // bit 2,1
|
|
||||||
+ isWrite; // bit 0
|
|
||||||
+
|
|
||||||
+ if (!priv_check[priv_index]) {
|
|
||||||
+ error_code = 0x00000001; // RSVD=0, P=1
|
|
||||||
+ goto page_fault_access;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // make up the physical frame number
|
|
||||||
+ ppf = (pde & 0xFFC00000) | (laddress & 0x003FF000);
|
|
||||||
+
|
|
||||||
+ // Update PDE if A/D bits if needed.
|
|
||||||
+ if ( ((pde & 0x20)==0) ||
|
|
||||||
+ (isWrite && ((pde&0x40)==0)) ) {
|
|
||||||
+ pde |= (0x20 | (isWrite<<6)); // Update A and possibly D bits
|
|
||||||
+ BX_CPU_THIS_PTR mem->write_physical(this, pde_addr, 4, &pde);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // Else normal 4Kbyte page...
|
|
||||||
+ else
|
|
||||||
+#endif
|
|
||||||
+ {
|
|
||||||
+ Bit32u pte, pte_addr;
|
|
||||||
+
|
|
||||||
+#if (BX_CPU_LEVEL < 6)
|
|
||||||
// update PDE if A bit was not set before
|
|
||||||
if ( !(pde & 0x20) ) {
|
|
||||||
pde |= 0x20;
|
|
||||||
BX_CPU_THIS_PTR mem->write_physical(this, pde_addr, 4, &pde);
|
|
||||||
}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
- if ( !(pte & 0x01) ) {
|
|
||||||
- // Page Table Entry NOT present
|
|
||||||
- error_code = 0xfffffff8; // RSVD=1, P=0
|
|
||||||
- goto page_fault_not_present;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- //BW added: update PTE if A bit was not set before
|
|
||||||
- if ( !(pte & 0x20) ) {
|
|
||||||
- pte |= 0x20;
|
|
||||||
- BX_CPU_THIS_PTR mem->write_physical(this, pte_addr, 4, &pte);
|
|
||||||
- }
|
|
||||||
+ // Get page table entry
|
|
||||||
+ pte_addr = (pde & 0xfffff000) |
|
|
||||||
+ ((laddress & 0x003ff000) >> 10);
|
|
||||||
+ BX_CPU_THIS_PTR mem->read_physical(this, pte_addr, 4, &pte);
|
|
||||||
+
|
|
||||||
+ if ( !(pte & 0x01) ) {
|
|
||||||
+ // Page Table Entry NOT present
|
|
||||||
+ error_code = 0x00000000; // RSVD=0, P=0
|
|
||||||
+ goto page_fault_not_present;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- // 386 and 486+ have different bahaviour for combining
|
|
||||||
- // privilege from PDE and PTE.
|
|
||||||
+ // 386 and 486+ have different bahaviour for combining
|
|
||||||
+ // privilege from PDE and PTE.
|
|
||||||
#if BX_CPU_LEVEL == 3
|
|
||||||
- combined_access = (pde | pte) & 0x04; // U/S
|
|
||||||
- combined_access |= (pde & pte) & 0x02; // R/W
|
|
||||||
+ combined_access = (pde | pte) & 0x04; // U/S
|
|
||||||
+ combined_access |= (pde & pte) & 0x02; // R/W
|
|
||||||
#else // 486+
|
|
||||||
- combined_access = (pde & pte) & 0x06; // U/S and R/W
|
|
||||||
+ combined_access = (pde & pte) & 0x06; // U/S and R/W
|
|
||||||
#endif
|
|
||||||
|
|
||||||
- ppf = pte & 0xfffff000;
|
|
||||||
- }
|
|
||||||
+ priv_index =
|
|
||||||
+#if BX_CPU_LEVEL >= 4
|
|
||||||
+ (BX_CPU_THIS_PTR cr0.wp<<4) | // bit 4
|
|
||||||
+#endif
|
|
||||||
+ (pl<<3) | // bit 3
|
|
||||||
+ (combined_access & 0x06) | // bit 2,1
|
|
||||||
+ isWrite; // bit 0
|
|
||||||
|
|
||||||
- // Calculate physical memory address and fill in TLB cache entry
|
|
||||||
+ if (!priv_check[priv_index]) {
|
|
||||||
+ error_code = 0x00000001; // RSVD=0, P=1
|
|
||||||
+ goto page_fault_access;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
+ ppf = pte & 0xfffff000;
|
|
||||||
+
|
|
||||||
+#if (BX_CPU_LEVEL >= 6)
|
|
||||||
+ // update PDE if A bit was not set before
|
|
||||||
+ if ( !(pde & 0x20) ) {
|
|
||||||
+ pde |= 0x20;
|
|
||||||
+ BX_CPU_THIS_PTR mem->write_physical(this, pde_addr, 4, &pde);
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ // Update PTE if A/D bits if needed.
|
|
||||||
+ if ( ((pte & 0x20)==0) ||
|
|
||||||
+ (isWrite && ((pte&0x40)==0)) ) {
|
|
||||||
+ pte |= (0x20 | (isWrite<<6)); // Update A and possibly D bits
|
|
||||||
+ BX_CPU_THIS_PTR mem->write_physical(this, pte_addr, 4, &pte);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ // Calculate physical memory address and fill in TLB cache entry
|
|
||||||
paddress = ppf | poffset;
|
|
||||||
|
|
||||||
BX_CPU_THIS_PTR TLB.entry[TLB_index].lpf = lpf;
|
|
||||||
BX_CPU_THIS_PTR TLB.entry[TLB_index].ppf = ppf;
|
|
||||||
- BX_CPU_THIS_PTR TLB.entry[TLB_index].pte_addr = pte_addr;
|
|
||||||
- BX_CPU_THIS_PTR TLB.entry[TLB_index].combined_access = combined_access;
|
|
||||||
+ BX_CPU_THIS_PTR TLB.entry[TLB_index].combined_access =
|
|
||||||
+ combined_access | isWrite;
|
|
||||||
|
|
||||||
- goto priv_check;
|
|
||||||
+ return(paddress);
|
|
||||||
|
|
||||||
|
|
||||||
-page_fault_check:
|
|
||||||
-// (mch) Define RMW_WRITES for old behavior
|
|
||||||
-#if !defined(RMW_WRITES)
|
|
||||||
- /* (mch) Ok, so we know it's a page fault. It the access is a
|
|
||||||
- read-modify-write access we check if the read faults, if it
|
|
||||||
- does then we (optionally) do not set the write bit */
|
|
||||||
- if (rw == BX_RW) {
|
|
||||||
- priv_index =
|
|
||||||
-#if BX_CPU_LEVEL >= 4
|
|
||||||
- (BX_CPU_THIS_PTR cr0.wp<<4) | // bit 4
|
|
||||||
-#endif
|
|
||||||
- (pl<<3) | // bit 3
|
|
||||||
- (combined_access & 0x06) | // bit 2,1
|
|
||||||
- 0; // bit 0 (read)
|
|
||||||
- if (!priv_check[priv_index]) {
|
|
||||||
- // Fault on read
|
|
||||||
- is_rw = 0;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-#endif /* RMW_WRITES */
|
|
||||||
- goto page_fault_proper;
|
|
||||||
-
|
|
||||||
+page_fault_access:
|
|
||||||
page_fault_not_present:
|
|
||||||
-#if !defined(RMW_WRITES)
|
|
||||||
- if (rw == BX_RW)
|
|
||||||
- is_rw = 0;
|
|
||||||
-#endif /* RMW_WRITES */
|
|
||||||
- goto page_fault_proper;
|
|
||||||
|
|
||||||
- page_fault_proper:
|
|
||||||
- error_code |= (pl << 2) | (is_rw << 1);
|
|
||||||
+ error_code |= (pl << 2) | (isWrite << 1);
|
|
||||||
BX_CPU_THIS_PTR cr2 = laddress;
|
|
||||||
- // invalidate entry - we can get away without maintaining A bit in PTE
|
|
||||||
- // if we don't maintain TLB entries without it set.
|
|
||||||
+ // Invalidate TLB entry.
|
|
||||||
BX_CPU_THIS_PTR TLB.entry[TLB_index].lpf = BX_INVALID_TLB_ENTRY;
|
|
||||||
exception(BX_PF_EXCEPTION, error_code, 0);
|
|
||||||
return(0); // keep compiler happy
|
|
||||||
@@ -630,7 +654,6 @@
|
|
||||||
{
|
|
||||||
Bit32u lpf, ppf, poffset, TLB_index, error_code, paddress;
|
|
||||||
Bit32u pde, pde_addr;
|
|
||||||
- Bit32u pte, pte_addr;
|
|
||||||
unsigned priv_index;
|
|
||||||
Bit32u combined_access;
|
|
||||||
|
|
||||||
@@ -642,7 +665,6 @@
|
|
||||||
if (BX_CPU_THIS_PTR TLB.entry[TLB_index].lpf == lpf) {
|
|
||||||
paddress = BX_CPU_THIS_PTR TLB.entry[TLB_index].ppf | poffset;
|
|
||||||
combined_access = BX_CPU_THIS_PTR TLB.entry[TLB_index].combined_access;
|
|
||||||
-priv_check:
|
|
||||||
priv_index =
|
|
||||||
#if BX_CPU_LEVEL >= 4
|
|
||||||
(BX_CPU_THIS_PTR cr0.wp<<4) | // bit 4
|
|
||||||
@@ -656,82 +678,134 @@
|
|
||||||
return(paddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
- // Protection violation
|
|
||||||
- error_code = 0xfffffff9; // RSVD=1, P=1
|
|
||||||
- goto page_fault;
|
|
||||||
+ // The current access does not have permission according to the info
|
|
||||||
+ // in our TLB cache entry. Re-walk the page tables, in case there is
|
|
||||||
+ // updated information in the memory image, and let the long path code
|
|
||||||
+ // generate an exception if one is warranted.
|
|
||||||
+ goto pageTableWalk; // for clarity and in case of future mods
|
|
||||||
}
|
|
||||||
|
|
||||||
+pageTableWalk:
|
|
||||||
+
|
|
||||||
// Get page dir entry
|
|
||||||
pde_addr = (BX_CPU_THIS_PTR cr3 & 0xfffff000) |
|
|
||||||
((laddress & 0xffc00000) >> 20);
|
|
||||||
BX_CPU_THIS_PTR mem->read_physical(this, pde_addr, 4, &pde);
|
|
||||||
if ( !(pde & 0x01) ) {
|
|
||||||
// Page Directory Entry NOT present
|
|
||||||
- error_code = 0xfffffff8; // RSVD=1, P=0
|
|
||||||
- goto page_fault;
|
|
||||||
+ error_code = 0x00000000; // RSVD=0, P=0
|
|
||||||
+ goto page_fault_not_present;
|
|
||||||
}
|
|
||||||
|
|
||||||
- // check for 4Mbyte page
|
|
||||||
+#if BX_SUPPORT_4MEG_PAGES
|
|
||||||
+ // If 4M pages are enabled, and this is a 4Meg page
|
|
||||||
+ if ((pde & 0x80) && (BX_CPU_THIS_PTR cr4 & 0x10)) {
|
|
||||||
+ // combined access is just access from the pde (no pte involved).
|
|
||||||
+ combined_access = pde & 0x06;
|
|
||||||
|
|
||||||
- if ((pde & 0x80) && (BX_CPU_THIS_PTR cr4 & 0x10)) { // check for 4M page and make sure it's enabled
|
|
||||||
- combined_access = pde & 0x06; // combined access is just access from the pde
|
|
||||||
- ppf = (pde & 0xFFC00000) | (laddress & 0x003FF000); // make up the physical frame number
|
|
||||||
- pte_addr = pde_addr; // A/D bits in same place as a real pte
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
-
|
|
||||||
- else {
|
|
||||||
- // normal 4Kbyte page
|
|
||||||
-
|
|
||||||
- // Get page table entry
|
|
||||||
- pte_addr = (pde & 0xfffff000) |
|
|
||||||
- ((laddress & 0x003ff000) >> 10);
|
|
||||||
- BX_CPU_THIS_PTR mem->read_physical(this, pte_addr, 4, &pte);
|
|
||||||
+ priv_index =
|
|
||||||
+#if BX_CPU_LEVEL >= 4
|
|
||||||
+ (BX_CPU_THIS_PTR cr0.wp<<4) | // bit 4
|
|
||||||
+#endif
|
|
||||||
+ (pl<<3) | // bit 3
|
|
||||||
+ (combined_access & 0x06); // bit 2,1
|
|
||||||
+ // bit 0 always 0 (fetch==read)
|
|
||||||
|
|
||||||
+ if (!priv_check[priv_index]) {
|
|
||||||
+ error_code = 0x00000001; // RSVD=0, P=1
|
|
||||||
+ goto page_fault_access;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // make up the physical frame number
|
|
||||||
+ ppf = (pde & 0xFFC00000) | (laddress & 0x003FF000);
|
|
||||||
+
|
|
||||||
+ // Update PDE if A/D bits if needed.
|
|
||||||
+ if ( (pde & 0x20)==0 ) {
|
|
||||||
+ pde |= 0x20; // Update A and possibly D bits
|
|
||||||
+ BX_CPU_THIS_PTR mem->write_physical(this, pde_addr, 4, &pde);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // Else normal 4Kbyte page...
|
|
||||||
+ else
|
|
||||||
+#endif
|
|
||||||
+ {
|
|
||||||
+ Bit32u pte, pte_addr;
|
|
||||||
+
|
|
||||||
+#if (BX_CPU_LEVEL < 6)
|
|
||||||
// update PDE if A bit was not set before
|
|
||||||
if ( !(pde & 0x20) ) {
|
|
||||||
pde |= 0x20;
|
|
||||||
BX_CPU_THIS_PTR mem->write_physical(this, pde_addr, 4, &pde);
|
|
||||||
}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
- if ( !(pte & 0x01) ) {
|
|
||||||
- // Page Table Entry NOT present
|
|
||||||
- error_code = 0xfffffff8; // RSVD=1, P=0
|
|
||||||
- goto page_fault;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- //BW added: update PTE if A bit was not set before
|
|
||||||
- if ( !(pte & 0x20) ) {
|
|
||||||
- pte |= 0x20;
|
|
||||||
- BX_CPU_THIS_PTR mem->write_physical(this, pte_addr, 4, &pte);
|
|
||||||
- }
|
|
||||||
+ // Get page table entry
|
|
||||||
+ pte_addr = (pde & 0xfffff000) |
|
|
||||||
+ ((laddress & 0x003ff000) >> 10);
|
|
||||||
+ BX_CPU_THIS_PTR mem->read_physical(this, pte_addr, 4, &pte);
|
|
||||||
+
|
|
||||||
+ if ( !(pte & 0x01) ) {
|
|
||||||
+ // Page Table Entry NOT present
|
|
||||||
+ error_code = 0x00000000; // RSVD=0, P=0
|
|
||||||
+ goto page_fault_not_present;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- // 386 and 486+ have different bahaviour for combining
|
|
||||||
- // privilege from PDE and PTE.
|
|
||||||
+ // 386 and 486+ have different bahaviour for combining
|
|
||||||
+ // privilege from PDE and PTE.
|
|
||||||
#if BX_CPU_LEVEL == 3
|
|
||||||
- combined_access = (pde | pte) & 0x04; // U/S
|
|
||||||
- combined_access |= (pde & pte) & 0x02; // R/W
|
|
||||||
+ combined_access = (pde | pte) & 0x04; // U/S
|
|
||||||
+ combined_access |= (pde & pte) & 0x02; // R/W
|
|
||||||
#else // 486+
|
|
||||||
- combined_access = (pde & pte) & 0x06; // U/S and R/W
|
|
||||||
+ combined_access = (pde & pte) & 0x06; // U/S and R/W
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ priv_index =
|
|
||||||
+#if BX_CPU_LEVEL >= 4
|
|
||||||
+ (BX_CPU_THIS_PTR cr0.wp<<4) | // bit 4
|
|
||||||
+#endif
|
|
||||||
+ (pl<<3) | // bit 3
|
|
||||||
+ (combined_access & 0x06); // bit 2,1
|
|
||||||
+ // bit 0 always 0 (fetch==read)
|
|
||||||
+
|
|
||||||
+ if (!priv_check[priv_index]) {
|
|
||||||
+ error_code = 0x00000001; // RSVD=0, P=1
|
|
||||||
+ goto page_fault_access;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ppf = pte & 0xfffff000;
|
|
||||||
+
|
|
||||||
+#if (BX_CPU_LEVEL >= 6)
|
|
||||||
+ // update PDE if A bit was not set before
|
|
||||||
+ if ( !(pde & 0x20) ) {
|
|
||||||
+ pde |= 0x20;
|
|
||||||
+ BX_CPU_THIS_PTR mem->write_physical(this, pde_addr, 4, &pde);
|
|
||||||
+ }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
- ppf = pte & 0xfffff000;
|
|
||||||
- }
|
|
||||||
+ // Update PTE if A/D bits if needed.
|
|
||||||
+ if ( (pte & 0x20)==0 ) {
|
|
||||||
+ pte |= 0x20; // Update A and possibly D bits
|
|
||||||
+ BX_CPU_THIS_PTR mem->write_physical(this, pte_addr, 4, &pte);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
|
|
||||||
+ // Calculate physical memory address and fill in TLB cache entry
|
|
||||||
paddress = ppf | poffset;
|
|
||||||
|
|
||||||
BX_CPU_THIS_PTR TLB.entry[TLB_index].lpf = lpf;
|
|
||||||
BX_CPU_THIS_PTR TLB.entry[TLB_index].ppf = ppf;
|
|
||||||
- BX_CPU_THIS_PTR TLB.entry[TLB_index].pte_addr = pte_addr;
|
|
||||||
BX_CPU_THIS_PTR TLB.entry[TLB_index].combined_access = combined_access;
|
|
||||||
- goto priv_check;
|
|
||||||
|
|
||||||
+ return(paddress);
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+page_fault_access:
|
|
||||||
+page_fault_not_present:
|
|
||||||
|
|
||||||
-page_fault:
|
|
||||||
error_code |= (pl << 2);
|
|
||||||
BX_CPU_THIS_PTR cr2 = laddress;
|
|
||||||
- // invalidate entry - we can get away without maintaining A bit in PTE
|
|
||||||
- // if we don't maintain TLB entries without it set.
|
|
||||||
+ // Invalidate TLB entry.
|
|
||||||
BX_CPU_THIS_PTR TLB.entry[TLB_index].lpf = BX_INVALID_TLB_ENTRY;
|
|
||||||
exception(BX_PF_EXCEPTION, error_code, 0);
|
|
||||||
return(0); // keep compiler happy
|
|
||||||
Index: cpu/proc_ctrl.cc
|
|
||||||
===================================================================
|
|
||||||
RCS file: /cvsroot/bochs/bochs/cpu/proc_ctrl.cc,v
|
|
||||||
retrieving revision 1.25
|
|
||||||
diff -u -r1.25 proc_ctrl.cc
|
|
||||||
--- cpu/proc_ctrl.cc 10 Aug 2002 12:06:26 -0000 1.25
|
|
||||||
+++ cpu/proc_ctrl.cc 1 Sep 2002 03:16:58 -0000
|
|
||||||
@@ -497,23 +497,29 @@
|
|
||||||
BX_INSTR_TLB_CNTRL(BX_INSTR_MOV_CR3, val_32);
|
|
||||||
break;
|
|
||||||
case 4: // CR4
|
|
||||||
+ {
|
|
||||||
#if BX_CPU_LEVEL == 3
|
|
||||||
BX_PANIC(("MOV_CdRd: write to CR4 of 0x%08x on 386",
|
|
||||||
val_32));
|
|
||||||
UndefinedOpcode(i);
|
|
||||||
#else
|
|
||||||
+ Bit32u allowMask = 0;
|
|
||||||
// Protected mode: #GP(0) if attempt to write a 1 to
|
|
||||||
// any reserved bit of CR4
|
|
||||||
|
|
||||||
- if (val_32 & ~ 0x10) { // support CR4<PSE> (to allow 4M pages)
|
|
||||||
+#if BX_SUPPORT_4MEG_PAGES
|
|
||||||
+ allowMask |= 0x00000010;
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ if (val_32 & ~allowMask) {
|
|
||||||
BX_INFO(("MOV_CdRd: (CR4) write of 0x%08x not supported!",
|
|
||||||
val_32));
|
|
||||||
}
|
|
||||||
- // Only allow writes of 0 to CR4 for now.
|
|
||||||
- // Writes to bits in CR4 should not be 1s as CPUID
|
|
||||||
- // returns not-supported for all of these features.
|
|
||||||
- BX_CPU_THIS_PTR cr4 = val_32 & 0x10;
|
|
||||||
+
|
|
||||||
+ val_32 = val_32 & allowMask; // Screen out unsupported bits.
|
|
||||||
+ BX_CPU_THIS_PTR cr4 = val_32;
|
|
||||||
#endif
|
|
||||||
+ }
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BX_PANIC(("MOV_CdRd: control register index out of range"));
|
|
||||||
@@ -1038,7 +1044,10 @@
|
|
||||||
#else
|
|
||||||
BX_PANIC(("CPUID: not implemented for > 6"));
|
|
||||||
#endif
|
|
||||||
+
|
|
||||||
+#if BX_SUPPORT_4MEG_PAGES
|
|
||||||
features |= 8; // support page-size extension (4m pages)
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
EAX = (family <<8) | (model<<4) | stepping;
|
|
||||||
EBX = ECX = 0; // reserved
|
|
Loading…
Reference in New Issue