On 02/02/2022 15:52, Nikolai Zhubr wrote:
https://github.com/ipxe/ipxe/commit/bc35b24e3

This was a fun problem to debug!

Oh, nice. The commit log was an entertaining reading!
I'll try to re-test it on some 486 as time permits later.

Now as the effect appeared to be still clearly algorythmic rather than some hidden timing/caching/pipelining mystery, it probably could be implemented in bochs so as emulated 486 also behaves the same way? For me it'd look quite usefull.

Go for it! It looks as though the relevant code in bochs is in handleCpuModeChange():

 // CS segment in real mode always allows full access
 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p        = 1;
 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment  = 1;
 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type =
       BX_DATA_READ_WRITE_ACCESSED;

To get behaviour roughly equivalent to what I observed (and what external articles such as http://www.rcollins.org/ddj/Aug98/Aug98.html suggest), you'd want to skip the setting of .cache.type (and possibly also .cache.p and .cache.segment) in that method, and add code in jmp_far16() and jmp_far32() to set .cache.type either before or after the call to load_seg_reg().

It should be possible to test by using the bochs magic breakpoint instruction ("xchgw %bx,%bx") to break into the bochs debugger immediately after the "Return to (flat) real mode" in iPXE's libprefix.S. With the changes outlined above, you should be able to observe in the debugger that you have a non-writable code segment (type BX_CODE_EXEC_READ_ACCESSED) after the "lret", which then becomes a writable segment (type BX_DATA_READ_WRITE_ACCESSED) after the "ljmp".

Michael
_______________________________________________
ipxe-devel mailing list
ipxe-devel@lists.ipxe.org
https://lists.ipxe.org/mailman/listinfo/ipxe-devel

Reply via email to