Update ACCESSED bits in GDT/LDT descriptors (finally)

This commit is contained in:
Jeff Parsons 2015-05-11 13:11:30 -07:00 • committed by jeffpar
commit 5eed275008
7 changed files with 229 additions and 182 deletions

View file

@ -35,6 +35,7 @@
if (typeof module !== 'undefined') {
var str = require("../../shared/lib/strlib");
var Messages = require("./messages");
var Memory = require("./memory");
var X86 = require("./x86");
}
@ -308,6 +309,7 @@ X86Seg.prototype.checkReadProt = function checkReadProt(off, cb, fSuppress)
* it to an unsigned value using ">>>"; offMax was already converted at segment load time.
*/
if ((off >>> 0) + cb <= this.offMax) {
this.blockACC.adw[this.iACC] |= this.bitACC;
return (this.base + off)|0;
}
return this.checkReadProtDisallowed(off, cb, fSuppress);
@ -329,6 +331,7 @@ X86Seg.prototype.checkReadProtDown = function checkReadProtDown(off, cb, fSuppre
* it to an unsigned value using ">>>"; offMax was already converted at segment load time.
*/
if ((off >>> 0) + cb > this.offMax) {
this.blockACC.adw[this.iACC] |= this.bitACC;
return (this.base + off)|0;
}
return this.checkReadProtDisallowed(off, cb, fSuppress);
@ -367,6 +370,7 @@ X86Seg.prototype.checkWriteProt = function checkWriteProt(off, cb, fSuppress)
* it to an unsigned value using ">>>"; offMax was already converted at segment load time.
*/
if ((off >>> 0) + cb <= this.offMax) {
this.blockACC.adw[this.iACC] |= this.bitACC;
return (this.base + off)|0;
}
return this.checkWriteProtDisallowed(off, cb, fSuppress);
@ -388,6 +392,7 @@ X86Seg.prototype.checkWriteProtDown = function checkWriteProtDown(off, cb, fSupp
* it to an unsigned value using ">>>"; offMax was already converted at segment load time.
*/
if ((off >>> 0) + cb > this.offMax) {
this.blockACC.adw[this.iACC] |= this.bitACC;
return (this.base + off)|0;
}
return this.checkWriteProtDisallowed(off, cb, fSuppress);
@ -946,6 +951,46 @@ X86Seg.prototype.updateMode = function(fLoad, fProt)
this.fExpDown = true;
}
}
/*
* Here begins the four-step process of computing the block, index and bit mask required
* to update the descriptor's ACCESSED bit whenever the segment is accessed.
*
* Step 1: Compute address of the descriptor byte containing the ACCESSED bit (offset 0x5);
* note that it's perfectly normal for addrDesc to occasionally be invalid (eg, when the CPU
* is creating protected-mode-only segment registers like LDT and TSS, or when the CPU has
* transitioned from real-mode to protected-mode and new selector(s) have not been loaded yet).
*/
this.iACC = this.bitACC = 0;
if (this.addrDesc != X86.ADDR_INVALID) {
var addrAcc = this.addrDesc + X86.DESC.ACC.TYPE.OFFSET;
/*
* Step 2: Compute the logical block number containing that byte, and record the block.
*/
this.blockACC = this.cpu.aMemBlocks[(addrAcc & this.cpu.nMemMask) >>> this.cpu.nBlockShift];
this.cpu.assert(this.blockACC && this.blockACC.adw);
/*
* It's critical that we check fReadOnly, because ROMs often use GDTs that are also located
* in ROM, in which case the ACCESSED bit cannot be set (ie, we must ensure that blockACC is
* set to a dummy block).
*/
if (this.blockACC && !this.blockACC.fReadOnly && this.blockACC.adw) {
/*
* Step 3: Compute the index of the DWORD (adw entry) containing that byte.
*/
this.iACC = (addrAcc & this.cpu.nBlockLimit) >> 2;
/*
* Step 4: Compute the bit that must be OR'ed into that DWORD in order to set the ACCESSED bit;
* we right-shift the bit into byte 0, and then left-shift it into byte 0, 1, 2 or 3 as appropriate.
*/
this.bitACC = Memory.adjustEndian((X86.DESC.ACC.TYPE.ACCESSED >> 8) << ((addrAcc & 0x3) << 3));
}
}
if (!this.bitACC) {
if (!this.cpu.blockDummy) this.cpu.blockDummy = new Memory(0, 0, 4);
this.blockACC = this.cpu.blockDummy;
}
if (fLoad) {
/*
* Any update to the following properties must occur only on segment loads, not simply when