Would it be valid to add CR4 bit 4(PSE) only, CPUID bit 3(PSE) for identification and 4MB pages to the 80386 and/or 80486 emulation? I just added it to the 80486(even though it uses the same TLB as normal pages, although having an extra bit in the tag for seperating it from 4KB pages) in my emulator.
Well, there are 80486 CPUs with the CPUID instruction in later revisions, which isn't fully 80486(Documentation says Pentium and up)? So could there be a 80486 with PSE(seeing as the 80486 already has the CR4 register defined, as well as the Debugger Exceptions bit in the CR4 register)?
Could someone have theoretically made a 486 with PSE? Yes. Did anyone actually make a 486 with PSE? No. Ergo, if you are trying to emulate a 486 then you shouldn't emulate PSE. Because such a chip does not exist.
Just fixed a tiny bug in the PDE 4MB handling: when writing to such a page, it reads with D~1, but since it doesn't have a PTE, a junk PTE got written instead(this case being 0), thus causing an infinite loop trying to handle the dirty bit(it retries during execution phase(prefetching in this case, after the TLB is validly loaded(so it doesn't reload the TLB). Since the read and write to the TLB never match up(°read accesses any value of D, write only accepts reads from D~1 for proper dirty, rewalking the page table otherwise and rechecking when running the instruction until it's cached in the TLB again).mSince they never matched up, an infinite loop occurred(normally shouldn't happen, since it's cached once, it can be cached again in the same instruction executing).
Luckily the solution is simple: for 4MB PDE's, write the TLB as being dirty. Then everything runs as it should.
It's still 486-compatible, just with one Pentium extension(without Pentium instructions). The 486 still supports CPUID and CR4, which exist according to documentation(on the original and'or revisions of the chip).
Edit: Minix 3 crashes with a kernel panic(press any key to reboot) trying to execute #UD opcode 0F31 (Pentium instruction) on the 80486. But at least Paging and the 4MB handling doesn't page fault or hang anymore.
There's another open-source OS I've been following some OS development series on Youtube(OS Lectures Forall), which describes an OS(xv6), which is built for i386(although using 4MB pages as well for booting). Since it should have been compiled for i386(but with 4MB paging), it might be running fine on a 486 with PSE added?
Managed to compile xv6 using a Ubuntu virtual machine and adding the flags -m32 -march=i386 to the CFLAGS. Looking at bootblock.S, it returns from the bootmain function(which it shouldn't, according to documentaation, triggering a non-existent Bochs breakpoint(in UniPCemu at least), then performs an infinite JMP $-2 to effectively HLT the CPU.
Now, why does bootmain return? Hmmm...
Edit: Looks like the EKF header it read from disk had an invalid signature(0101457F instead of 464c457f)?
Edit: Looking at sector 1 of the disk image, it contains the valid signature. So something goes wrong during reading of sectors from disk into memory somewhere.
Edit: Found the bug: the boot sector code us using insl/outsl to transfer data of sectors. But, the hard disk only has a 16-bit data register at port 1f0. So it's reading 2 bytes of disk data and the next two ports(1f1 and 1f2) instead of 4 bytes of on-disk data. Thus reading the sector incorrectly.
Edit: Having implemented proper 32-bit disk access, it now reaches main.c's kinit1 call(at 0008:80102ac0). I don't see it returning to the address after said instruction, so it's going wrong somewhere in there.
kinit calls initlock at 0008:80102111. That one returns.
It then set kmem.use_lock(at 80111674) to 0.
It seems to call kfree at 0008:80102146?
Then at 0008:80102056 kfree() calls memset to fill the release block with ones(01h).
Edit: It seems to update it's bookkeeping of the free list:
It then restores EBX, cleans up the stack frame and returns to freerange at 0008:80102082.
The main kfree loop checks for it's next value to be within range at 0008:80102156. At 0008:80102158, the loops should have ended.
Edit: I don't see EBX reaching 400000, so it's still freeing the kernel memory for initial allocation(and I've stopped the debugger from continuing and logging it before it reached said point).
Edit: It seems to return to the main function, now to be working/hanging/crashing on the initialization of the page tables within kvmalloc()?