diff --git a/disks/pc/unix/microport/system-v/2.3/README.md b/disks/pc/unix/microport/system-v/2.3/README.md new file mode 100644 index 000000000..2257e41e9 --- /dev/null +++ b/disks/pc/unix/microport/system-v/2.3/README.md @@ -0,0 +1,36 @@ +Debugging Notes +--- + +The boot sector contains the following code: + +0000:7C3E B003 MOV AL,03 +0000:7C40 B200 MOV DL,00 +0000:7C42 B417 MOV AH,17 +0000:7C44 CD13 INT 13 +0000:7C46 72B8 JC 7C00 + +For BIOSes that don't support INT 0x13, AH function 0x17, patch the JC with two NOPs; eg: + + e 0:7c46 90 90 + +After booting, the following code is executed: + +12E8:01D3 52 PUSH DX ;history=5 +12E8:01D4 51 PUSH CX ;history=4 +12E8:01D5 2BC9 SUB CX,CX ;history=3 +12E8:01D7 BA6400 MOV DX,0064 ;history=2 +12E8:01DA ED IN AX,DX ;history=1 + +For virtual machines that don't support word I/O to port 0x64, patch IN AX,DX with IN AL,DX; eg: + + e 12e8:1da ec + +Here's where the first task switch (far jump using a TSS selector) occurs: + + AX=02F0 BX=0008 CX=0000 DX=0000 SP=037E BP=037E SI=1852 DI=0000 + SS=0044[001800,07FF] DS=0228[009E00,851B] ES=0220[001000,8DFB] A20=ON + CS=0200[012320,FFFD] LD=02E0[002000,01FF] GD=[001006,072F] ID=[0053E2,07FF] + TR=02D0 MS=FFF5 PS=0016 V0 D0 I0 T0 S0 Z0 A1 P1 C0 + 0200:016D FF6E06 JMP FAR [BP+06] + +The far address at [BP+6] is 02F0:0000. diff --git a/modules/pcjs/lib/x86seg.js b/modules/pcjs/lib/x86seg.js index d17f0a545..bafe0cc7e 100644 --- a/modules/pcjs/lib/x86seg.js +++ b/modules/pcjs/lib/x86seg.js @@ -555,11 +555,10 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress) fGate = false; } else if (type == X86.DESC.ACC.TYPE.TSS) { - if (!this.switchTSS(sel, true)) { + if (!this.switchTSS(sel, fCall)) { base = addrDesc = X86.ADDR_INVALID; break; } - if (DEBUG) cpu.stopCPU(); return this.base; } else if (type == X86.DESC.ACC.TYPE.GATE_CALL) { @@ -581,7 +580,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress) cpu.assert(!(acc & 0x1f)); } else if (type == X86.DESC.ACC.TYPE.GATE_TASK) { - if (!this.switchTSS(base & 0xffff, true)) { + if (!this.switchTSS(base & 0xffff, fCall)) { base = addrDesc = X86.ADDR_INVALID; break; } @@ -746,7 +745,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress) * * @this {X86Seg} * @param {number} selNew - * @param {boolean} fNest is true if nesting, false if un-nesting + * @param {boolean|null} [fNest] is true if nesting, false if un-nesting, null if neither * @return {boolean} true if successful, false if error */ X86Seg.prototype.switchTSS = function switchTSS(selNew, fNest) @@ -758,6 +757,9 @@ X86Seg.prototype.switchTSS = function switchTSS(selNew, fNest) var cplOld = this.cpl; var selOld = cpu.segTSS.sel; if (!fNest) { + /* + * TODO: Verify that it is (always) correct to require that the BUSY bit be currently set. + */ if (cpu.segTSS.type != X86.DESC.ACC.TYPE.TSS_BUSY) { X86.fnFault.call(cpu, X86.EXCEPTION.TS_FAULT, selNew, true); return false; @@ -771,7 +773,12 @@ X86Seg.prototype.switchTSS = function switchTSS(selNew, fNest) if (DEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Messages.TSS)) { this.dbg.message((fNest? "Task switch" : "Task return") + ": TR " + str.toHexWord(selOld) + " (%" + str.toHex(addrOld, 6) + "), new TR " + str.toHexWord(selNew) + " (%" + str.toHex(addrNew, 6) + ")"); } - if (fNest) { + if (fNest === false) { + if (cpu.segTSS.type != X86.DESC.ACC.TYPE.TSS_BUSY) { + X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, selNew, true); + return false; + } + } else { if (cpu.segTSS.type == X86.DESC.ACC.TYPE.TSS_BUSY) { X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, selNew, true); return false;