Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optionalize target support #14

Merged
merged 6 commits into from
Oct 26, 2020
Merged

Optionalize target support #14

merged 6 commits into from
Oct 26, 2020

Conversation

mfld-fr
Copy link
Owner

@mfld-fr mfld-fr commented Oct 23, 2020

@ghaerr : this is a first draft to implement target option as discussed in issue #3.

@ghaerr
Copy link
Contributor

ghaerr commented Oct 23, 2020

@mfld-fr :

This is fine, but now there seems to be quite a bit of duplicated code, for much of the BIOS implementation. Keeping up two separate source files of many identical BIOS functions could end up being a lot of work, in the longer term.

I am wondering more precisely how you would like to use EMU86 as a tool for various porting projects. For instance, if one wanted to port ELKS to a smaller footprint embedded-like system (which is my goal), such as the Advantech, would one start with running int-elks.c to ensure it runs on a PC-like system, then build EMU86 with int-advtech.c to see if/how ELKS runs on that system? Or use a different approach?

My plan over at ELKS is to use EMU86 to identify (and mostly test) all outside services (exactly which INT calls and each subfunction used), as well as each external hardware device that may be required to boot and run. In order to do that, I was thinking along the lines of starting with a "fuller" BIOS implementation, then working to reduce ELKS' requirements of INT calls and subfunctions. For instance, the "headless" enhancement allows ELKS to run on INT 10's subfunction AH=0x0E ONLY. The idea is to use this approach of slimming down excess outside requirements to possibly entirely remove ELKS from requiring a BIOS and allowing it to run on (almost) bare metal.

In order to do this, I was thinking that perhaps an approach used in typical libc implementations might be useful: that of keeping all the routines in a single or multiple files (in this case in an int-bios.c file for PC BIOS functions) and using #define L_INT10_0E etc. (for example) in a separate Makefile. The Makefile would control exactly which functions were to be included in an emulated environment. In this approach, there isn't duplicated source code, and functions can be easily added or subtracted from the environment. Whether this makes much sense or not depends to me on how similar the Advantech and a typical PC BIOS are.

For those functions that are not typical BIOS functions, then, yes, they would be implemented only in an int-advantech.c (or other) file.

I am also working on getting ELKS source organized such that it won't be the semi-disaster of the #ifdef madness that was required for the now-defunct SIBO port. I am almost to the point of being able to separate each particular platform issues (PC, SIBO, Advantech, etc) out into mostly separate or at least only a few source files with little duplicated code, which should enable porting ELKS to different platforms much easier.

I'm interested in how you're thinking of porting MON86, SYS86 and/or ELKS to Advantech. From what I've seen here in EMU86 about Advantech, I'd say ELKS is pretty much ready to go for being able to run on it.

Separately, I am interested to learn more about what ethernet chip is used on the SNMP-1000, and whether we need to write a new driver for it, or whether its compatible with the WD/SMC or NE2K-style chip supported now on ELKS.

mfld-fr added a commit that referenced this pull request Oct 24, 2020
@mfld-fr
Copy link
Owner Author

mfld-fr commented Oct 24, 2020

@ghaerr : Got your concern about code duplication. So made a cleanup in Advantech BIOS emulation to show you how different the standard & Advantech BIOSes are.

@ghaerr
Copy link
Contributor

ghaerr commented Oct 24, 2020

Ok, I am starting to see bigger differences in the two platform's BIOS. After this commit, I will try playing around with running ELKS on the Advantech BIOS, to see which routines are implemented as well as how EMU86 handles emulation of non-existing entry points.

A couple other points, which may want to be tracked in seperate issues:

  • Unimplemented BIOS subfunctions are generally coded as an assert(0) under a default case. This would cause the emulator to exit. It would probably be more useful to return "err = -..." so that the trace stops and emulator is at command prompt.
  • I have been thinking about how ELKS could be traced through system calls using the FLAGS T-bit, which I think you stated previously might not be possible. I would like to have a technical discussion on that.
  • Can EMU86 currently run the MON86 program? MON86 supports master/slave by using the T-bit and INT 3, right?

@mfld-fr
Copy link
Owner Author

mfld-fr commented Oct 24, 2020

@ghaerr : After the BIOSes in previous step, also imported the 'sys86' branch with its deeper emulation of the Advantech target, to show you how basic devices (interrupt controller, timer and serial) are different.

@mfld-fr
Copy link
Owner Author

mfld-fr commented Oct 25, 2020

@ghaerr : for the remaining short questions :

  • Advantech Ethernet chip is a NE2K clone
  • Assertion in BIOS emulation : now tracked by No assertion in BIOS emulation #15
  • Trap flag (TF) is fully supported by EMU86
  • MON86 uses TF, INT1 and INT3 to control slave task
  • MON86 is fully tested in EMU86 and on SBC

@mfld-fr mfld-fr mentioned this pull request Oct 25, 2020
@ghaerr
Copy link
Contributor

ghaerr commented Oct 25, 2020

@mfld-fr : Thank you for your answers. I'm excited to learn the Advantach ethernet is NE2K compatible.

Trap flag (TF) is fully supported by EMU86

Regarding the TF flag and debugging of arbitrary OS code, including ELKS: My understanding of TF operation is that when the TF is set in the FLAGS register, after the next instruction executed (whatever it is), the CPU will push FLAGS, CS and IP, reset the TF flag, read the CS:IP for INT 1's vector, then jump to that address. The INT 1 handler routine will then run without the TF flag set. Upon returning from the INT 1 handler using IRET, the FLAGS register will be reloaded, the next instruction executed, and, if the TF flag is still set, the cycle repeats.

My question is whether this is handled different in real hardware when executing an INT instruction (say INT 80h) with the TF flag set: my understanding is the CPU executes the INT instruction, then executes a forced INT 1 as described above. That is, the TF flag is NOT reset as a result of the execution of INT 80h, it is only reset as part of the INT 1 handling. EMU86 does not work this way - it always resets TF when executing any INT instruction.

My other question is what the CPU does when a hardware interrupt occurs - is TF reset or not? That is, can TF be used to trace hardware interrupts?

Thank you!

@mfld-fr
Copy link
Owner Author

mfld-fr commented Oct 25, 2020

@ghaerr : On real HW, the processor resets both IF and TF upon an INT instruction (software or HW interrupt) just after pushing FLAGS on the stack.

Edit : this is why EMU86 is more powerful to debug an interrupt handler 😄

@ghaerr
Copy link
Contributor

ghaerr commented Oct 25, 2020

On real HW, the processor resets both IF and TF upon an INT instruction (software or HW interrupt) just after pushing FLAGS on the stack.

I see. In that case, we can still make things work by replacing the INT 80h vector with a patch that regains control, sets the TF bit, then jumps to the original entry point. Messy, but it would work. Not every vector would have to be patched, but patching INT 80 would allow at least tracing through ELKS syscalls. The timer interrupt could be left to run without tracing, at least initially.

this is why EMU86 is more powerful to debug an interrupt handler

Indeed, you have done a great job with it :) I am enjoying myself and learning a lot looking at your work.

At this point, I think with a few mods, we can get ELKS to be debuggable by MON86 without requiring kernel reentrancy. Of course, this means MON86 would run outside the kernel, instead of as a reentrant kernel process. By patching INT vectors, MON86 should be able to debug any 8086 OS. (And of course, so will EMU86 😄)!

@mfld-fr
Copy link
Owner Author

mfld-fr commented Oct 26, 2020

@ghaerr : is this PR now OK for your usage on ELKS ?

@mfld-fr mfld-fr self-assigned this Oct 26, 2020
@mfld-fr mfld-fr added enhancement New feature fix Defect correction improvement Product improvement and removed fix Defect correction labels Oct 26, 2020
@ghaerr
Copy link
Contributor

ghaerr commented Oct 26, 2020

@mfld-fr : I just pulled down the PR and compiled it. ELKS runs, comes to the shell prompt but then won't accept characters.

Do you suppose that's because we need an INT 8 timer? ELKS still needs the timer to poll for BIOS or headless operation.

@ghaerr
Copy link
Contributor

ghaerr commented Oct 26, 2020

Confirmed - adding back in the INT 8 hack in op_halt, and ELKS runs great:

	exec_int (8);  // TEMP HACK

@mfld-fr
Copy link
Owner Author

mfld-fr commented Oct 26, 2020

@ghaerr : yes, still have to complete with #16 after the merge.

@ghaerr
Copy link
Contributor

ghaerr commented Oct 26, 2020

In that case, yes, go ahead and merge. I can insert that line myself until #16 is done. Thanks!

@mfld-fr mfld-fr merged commit 546db71 into master Oct 26, 2020
@mfld-fr mfld-fr deleted the target branch October 26, 2020 21:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature improvement Product improvement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants