VOGONS


Reply 20 of 25, by superfury

User metadata
Rank l33t++
Rank
l33t++

Since paging is enabled in the faulting code, according to https://manybutfinite.com/post/kernel-boot-process/ , the main.c's start_kernel should have been reached at least?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 21 of 25, by superfury

User metadata
Rank l33t++
Rank
l33t++

I'm just thinking... Can I compile the linux source code on Windows 10 for a 80386 and use that one as a testcase for testing my emulator's 80386 emulation? So create the linux file on Windows(using the gcc compiler) and then boot it, and check how far it advances into the main kernel routine(start_kernel) using objdump etc.?

Edit: I found https://virtuallyfun.com/2016/10/04/cross-com … ed-linux-1-0-9/, which compiles fine(linux 1.0.9) on Windows 10(using the simple make command after running the env.bat file in a cmd.exe prompt).

I now have the zImage file, which should be a bootable floppy disk image or something like that? How do I get the raw addresses at which start_kernel is supposed to start from it?

Edit: Booting said kernel gives me this:

998-linux-1.0.9 giving up.jpg
Filename
998-linux-1.0.9 giving up.jpg
File size
60.68 KiB
Views
327 views
File comment
Linux gives up because no FPU is present and no emulation is provided?
File license
Fair use/fair dealing exception

Edit: Modifying the makefile to use the FPU emulation constant(set to 1) and compile in the software FPU emulation doesn't seem to have any effect(same result)?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 22 of 25, by superfury

User metadata
Rank l33t++
Rank
l33t++

Oddly enough, in the Debian stack trace, it shows lots of 00800000 on the stack dum it makes? So something's adding up on the stack over and over again, with value 0x800000?

Edit: Dumping the stack eventually page faults incorrectly at C0800000, PDE=00000000?

1002-stackdump-pagefault.jpg
Filename
1002-stackdump-pagefault.jpg
File size
138.95 KiB
Views
314 views
File comment
Stack dump page faulting?
File license
Fair use/fair dealing exception

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 23 of 25, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just tried running Descent. It eventually crashes due to a stack fault on a POPA instruction(I see it's matching PUSHA in the function prologue, but ESP mismatches by a few bytes lower after the PUSHA. So somehow it's not pushing enough to be popped when crashing(it's a stack underflow) or pops too much?

Edit: Looking into the disassembly from the last PUSHA, I see the following:

3e58:00004c83 32 C9 xor cl,cl	RealRAM(p):000a94b0=b4(?); RAM(p):001094b0=b4(?); Physical(p):001094b0=b4(?); Paged(p):001094b0=b4(?); Normal(p):00004c90=b4(?); RealRAM(p):000a94b1=00( ); RAM(p):001094b1=00( ); Physical(p):001094b1=00( ); Paged(p):001094b1=00( ); Normal(p):00004c91=00( ); RealRAM(p):000a94b2=b0(?); RAM(p):001094b2=b0(?); Physical(p):001094b2=b0(?); Paged(p):001094b2=b0(?); Normal(p):00004c92=b0(?); RealRAM(p):000a94b3=0b(); RAM(p):001094b3=0b(); Physical(p):001094b3=0b(); Paged(p):001094b3=0b(); Normal(p):00004c93=0b()
Registers:
EAX: 00000270 EBX: 10111c08 ECX: 00000000 EDX: 00000002
ESP: 00000fe8 EBP: 00000fe8 ESI: 00000000 EDI: 000050c4
CS: 3e58 DS: 3e68 ES: 3e68 FS: 0000 GS: 0000 SS: 0250 TR: 0248 LDTR: 0000
EIP: 00004c83 EFLAGS: 00004012
CR0: 80000009 CR1: 00000000 CR2: 10111c08 CR3: 00145000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000001000103fff IDTR: 000000010ab007ff
FLAGSINFO: 00000000000000vr0N00oditsz0A0p1c
RealRAM(r):000e5003=00( ); RAM(r):00145003=00( ); Physical(r):00145003=00( ); RealRAM(r):000e5002=14(); RAM(r):00145002=14(); Physical(r):00145002=14(); RealRAM(r):000e5001=30(0); RAM(r):00145001=30(0); Physical(r):00145001=30(0); RealRAM(r):000e5000=27('); RAM(r):00145000=27('); Physical(r):00145000=27('); RealRAM(r):000e3447=00( ); RAM(r):00143447=00( ); Physical(r):00143447=00( ); RealRAM(r):000e3446=11(); RAM(r):00143446=11(); Physical(r):00143446=11(); RealRAM(r):000e3445=10(); RAM(r):00143445=10(); Physical(r):00143445=10(); RealRAM(r):000e3444=67(g); RAM(r):00143444=67(g); Physical(r):00143444=67(g); RealRAM(r):000b1362=01(); RAM(r):00111362=01(); Physical(r):00111362=01(); Paged(r):00111362=01()
RealRAM(p):000a94b4=ee(?); RAM(p):001094b4=ee(?); Physical(p):001094b4=ee(?); Paged(p):001094b4=ee(?); Normal(p):00004c94=ee(?); RealRAM(p):000a94b5=eb(?); RAM(p):001094b5=eb(?); Physical(p):001094b5=eb(?); Paged(p):001094b5=eb(?); Normal(p):00004c95=eb(?); RealRAM(p):000a94b6=00( ); RAM(p):001094b6=00( ); Physical(p):001094b6=00( ); Paged(p):001094b6=00( ); Normal(p):00004c96=00( ); RealRAM(p):000a94b7=eb(?); RAM(p):001094b7=eb(?); Physical(p):001094b7=eb(?); Paged(p):001094b7=eb(?); Normal(p):00004c97=eb(?)
3e58:00004c85 80 3E B2 00 01 cmp byte ds:[00b2],01
Registers:
EAX: 00000270 EBX: 10111c08 ECX: 00000000 EDX: 00000002
ESP: 00000fe8 EBP: 00000fe8 ESI: 00000000 EDI: 000050c4
CS: 3e58 DS: 3e68 ES: 3e68 FS: 0000 GS: 0000 SS: 0250 TR: 0248 LDTR: 0000
EIP: 00004c85 EFLAGS: 00004046
CR0: 80000009 CR1: 00000000 CR2: 10111c08 CR3: 00145000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000001000103fff IDTR: 000000010ab007ff
FLAGSINFO: 00000000000000vr0N00oditsZ0a0P1c
3e58:00004c8a 0F 85 1C 00 jnz 00004caa RealRAM(p):000a94b8=00( ); RAM(p):001094b8=00( ); Physical(p):001094b8=00( ); Paged(p):001094b8=00( ); Normal(p):00004c98=00( ); RealRAM(p):000a94b9=ec(?); RAM(p):001094b9=ec(?); Physical(p):001094b9=ec(?); Paged(p):001094b9=ec(?); Normal(p):00004c99=ec(?); RealRAM(p):000a94ba=22("); RAM(p):001094ba=22("); Physical(p):001094ba=22("); Paged(p):001094ba=22("); Normal(p):00004c9a=22("); RealRAM(p):000a94bb=06(); RAM(p):001094bb=06(); Physical(p):001094bb=06(); Paged(p):001094bb=06(); Normal(p):00004c9b=06()
Registers:
EAX: 00000270 EBX: 10111c08 ECX: 00000000 EDX: 00000002
ESP: 00000fe8 EBP: 00000fe8 ESI: 00000000 EDI: 000050c4
CS: 3e58 DS: 3e68 ES: 3e68 FS: 0000 GS: 0000 SS: 0250 TR: 0248 LDTR: 0000
EIP: 00004c8a EFLAGS: 00004046
CR0: 80000009 CR1: 00000000 CR2: 10111c08 CR3: 00145000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000001000103fff IDTR: 000000010ab007ff
FLAGSINFO: 00000000000000vr0N00oditsZ0a0P1c

That CMP is essentially a CMP 1400,01. So somehow, the EFLAGS isn't being updated there?

My notes on the stack being updated during the PUSHA until crash(#SS fault):

fee - PUSHA registers. After invalid CMP, here's POP AX, then another POP AX, then stack fault on POPA because of stack underflow.
fec - saved DS. Popped into DS after invalid CMP. See below ES comment on invalid POP cause.
fea - saved ES. Popped into ES at the end after invalid CMP and updating EFLAGS to set NT flag.
fe8 - saved BP <- current stack frame(EBP) <- ESP; popped into EBP after updating EFLAGS at the end after faulty CMP(opcode 80h).
(fe6 - 3e68 constant and pushed from DS after popping into DS(=DS when pushed again)). Then POPped into ES. Overwritten with EFLAGS copy for setting NT flag.

00141fb4 = CR2 saved value
00141fb8 = FFC constant

So the main issue seems to be the invalid CMP, that's all I see actually going wrong.
Edit: Oddly enough, Visual Studio doesn't tell me it's comparing 0 with 1. It's 1,1 each time, so the jump is always taken(at least up to the faulting point).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 24 of 25, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've found the source code for the loadlin.exe file(I'd assume the detection code shouldn't be changed).

It has the following CPU (mode) detection code:

cpu_86     equ   0
cpu_286 equ 2
cpu_386V86 equ 3 ; is >=386, but in virtual 86 mode
cpu_386GE equ 4 ; >=386
cpu_386GE_real_paging equ 5
cpu_type dw 0

cpu_check proc near
pushf
cmp option_force,0
jnz is_force_386GE
xor ax,ax ;0000 to ax
push ax
popf ; try to put that in flags
pushf
pop ax ; look at what really went into flags
and ah,0f0h ; mask off high flag bits
cmp ah,0f0h
je is_8086
mov ax,0f000h
push ax ; try to set the high bits
popf
pushf
pop ax ; look at actual flags
and ah,0f0h
je is_80286
; is x86, x >= 3
; check for V86 or real-paging -mode
mov ah,040h ; try to clear IOPL
push ax
popf
pushf
pop ax
and ah,030h
jne is_v86
cmp option_clone,0
jnz @@clone
.386p
mov eax,cr0 ; normally this would cause a GP(0)-exception
; (i386 Programmers Reference Guide, INTEL 1987)
; if in V86-mode, but most EMMXXXX drivers
; seem to intercept this exception and allow
; reading the CR0.
.386
or eax,eax
jz is_v86 ; not a valid CR0, reserved bits are allways set
; (this may be not true on a 486 clone such as
; the 486DLC, so if you have trouble with
; interpreting real mode as V86 use the -clone switch
;
test al,01h ; test PE -bit
jz is_greater_equal_80386
is_v86:
mov ax,cpu_386V86
cpu_check_exit:
mov cpu_type,ax
popf
ret
is_8086:
mov ax,cpu_86
Show last 15 lines
        jmp     cpu_check_exit
is_80286:
mov ax,cpu_286
jmp cpu_check_exit
is_greater_equal_80386:
test eax,eax ; test PG - bit
js is_386_real_pageing
mov ax,cpu_386GE
jmp cpu_check_exit
is_force_386GE:
mov ax,cpu_386GE
jmp cpu_check_exit
is_386_real_pageing:
mov ax,cpu_386GE_real_paging
jmp cpu_check_exit

Somehow, ax isn't cpu_386GE or higher when MS-DOS is executing on my 80386DX emulation, running MS-DOS with nothing more than HIMEM.SYS loaded? It tells me the CPU is in V86 mode, which it isn't(only sporadic protected mode without paging during HIMEM memory moves)?

Can anyone see why UniPCemu fails on the cpu_check function? Why would it tell me it's running in V86 mode(it should be running in (un)real mode)?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 25 of 25, by superfury

User metadata
Rank l33t++
Rank
l33t++

One interesting thing I notice about the Linux 2.0.33 kernel spewing out it's #GP(0) error message, is that pretty much all registers are reported incorrectly. All values are seemingly garbled up(all segments and data register but SS:ESP are reported with incorrect values. When the exception handler is thrown, most data registers have value 0x18 in them, CS 0x10, SS is correctly reported). Even CS:EIP is reported incorrectly(CS is definitely 0x10(:1E3439), while EIP is a completely different value, both being reported incorrectly).

Edit: Just found a bug that caused RET[D] to add the immediate number to the stack, even when a fault was raised(in the case of a fault, it would add to the exception handler's stack incorrectly, destroying anything pushed there(depending on the immediate value).

No effect on this, though, since RET has an (hardcoded) immediate of 0(since it doesn't add anything to the stack). But it still reports all registers incorrectly?

The location data pushed on the stack during the invalid RET:
205702=EFLAGS
CS=0010
EIP=1E3439

EIP of the error handler(#GP) becomes 10AA6C

The error code pushed is 0.

Edit: The RET seems to also be called a RETN instruction(opcode C3). The stack seems like it's loaded, but the value that's popped off is completely invalid(it's in user memory instead of kernel memory). Also, CS.base is C0000000 and limit 3FFFFFFF. So the return address must be 100% invalid.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io