Hi,
Prochamber wrote:Also I don't think my segment copying is going to drastically ruin performance, as I write this article my operating system is copying data to the video buffer in volumes hundreds of times larger than I would in my operating system and the CPU is reading hundreds of megabytes of memory every second and it still runs seamlessly.
Here I agree - the impact on performance caused by saving (up to) 640 KiB of RAM and then restoring (up to) 640 KiB of RAM during a task switch is likely to be negligible compared to the performance impact of "locking up" the CPU just so the BIOS can do nothing while waiting for hardware to do DMA/UDMA disk IO transfers.
Note that your video buffer example is probably not a good example. I don't know which OS you're currently using, but I'd still expect most of the data it needs is already in the video card's RAM (e.g. using hardware accelerated "video RAM to video RAM" bit blits to render windows), and anything that isn't already in the video card's RAM is being transferred via. bus mastering without consuming CPU time.
Prochamber wrote:Brendan wrote:The BIOS's code is in ROM and so it can't be corrupted to begin with (actually it can be - nothing prevents a real mode application from messing with the chipset, but that's a different matter). The BIOS Data Area could be copied somewhere else and then restored before the BIOS accesses it (which would protect the BIOS Data Area from being trashed), but huge unreal mode doesn't help this. Having multiple copies of the BIOS Data Area will break the BIOS (prevents the BIOS from correctly tracking the current state of various pieces of hardware).
Also don't forget that there's an EBDA (Extended BIOS Data Area) that is just as trashable as the BIOS Data Area, and that the firmware's SMM handler may rely on data stored in the EBDA (and the CPU can enter SMM at any time, even if IRQs are disabled).
Uh, yeah. I meant the BIOS Data Area and this scheme won't affect the EBDA.
I'll copy and restore:
- The interrupt vector table
- The BIOS data area
- Kernel Space
- Program Space
I've decided the system of copying data with Big (not huge) Unreal Mode will be the simplest idea to implement.
Ok, let's consider a simple scenario - an application is running and some IRQ occurs. The CPU uses your IVT to figure out how to transfer control to your interrupt handler; and your interrupt handler copies the BIOS' IVT and BDA from somewhere safe back to where it needs to be, then passes control to the BIOS's interrupt handler. When the BIOS interrupt handler has finished it returns to your interrupt handler which transfers the BIOS's IVT and BDA somewhere safe again. Then your interrupt handler returns to the application.
Now; the CPU has to be able to access your IVT and has to be able to execute your interrupt handler. If the CPU can access it then real mode software can access it. This means that instead of applications being able to trash the BIOS's IVT and BDA, the applications can just trash your IVT and your interrupt handlers. This doesn't sound like an improvement to me (roughly the same amount of "trash-able area" with nothing gained).
Prochamber wrote:You mentioned that there could be some problems, with having many separate copies of this data, so I've looked at the BIOS data area specifications and resolved a few paradoxes.
VideoBIOS - Screen settings are the only thing that is saved in the BDA. Programs won't need to change these.
You've got 123 different applications all writing to video display memory at the same time and screwing each other up and you're worried about the BDA? Obviously you're going to need some sort of abstraction (e.g. where applications draw their window's contents in buffers in RAM and a GUI copies the application's buffers to display memory). Once you realise this you'll also realise that the only thing that should be touching the Video BIOS is the GUI, and there's no point having multiple copies of the BDA for video.
Prochamber wrote:Disk Services - I'll make a wrapper to disable and re-enable multitasking.
Yes. Also add "write-through" disk IO caches to avoid painfully slow BIOS functions where possible. Sadly, the BIOS won't tell you when removable media has been removed and/or inserted, so for removable media you won't be able to keep your caches synchronised and it'd only be possible to (reliably) cache non-removable disks (e.g. hard drives).
Prochamber wrote:Serial Services - Unsure, maybe I'll lock it to one process.
Don't bother - nobody has ever used the BIOS's serial services because they need constant polling to avoid data loss. Serial ports (if they exist) are so easy that your applications will just use the IO ports directly, just like DOS applications did. Of course DOS was single-tasking so (excluding TSRs) the chance of 2 pieces of software trying to use the serial ports at the same time was zero. To avoid conflicts (and data loss) you'd probably want to provide your own serial port drivers and make sure only one application can use a serial port at a time. However you'd have to wonder why applications need to talk to devices attached to serial ports themselves (e.g. why the OS doesn't have drivers for devices attached via. serial).
Prochamber wrote:Keyboard Services - This will actually work to my advantage, because each process will have it's own queue and won't be able to 'steal' keypresses from others. I might write my own handler with a global API.
It won't work to your advantage. The user pushes down the shift key and the BIOS sets a flag in the BDA, the OS does a task switch and changes the BDA, the user presses the 'a' key (while the shift key is still held down) and the BIOS checks the BDA and sees that the flag is clear so the application gets a lower-case 'a' instead of an upper-case 'A'. Then the user releases the shift key and the BIOS clears a copy of the flag that was already clear anyway. Then the OS does a task switch and copies the first BDA back, the user presses the 'b' key and the BIOS checks the flag and sees that it's set (because the wrong copy of the flag was cleared), so it gives the application an upper case 'B' instead of a lower case 'b'. See how this is completely borked?
Also note that the application that should receive the keypress probably won't be the application that's currently running.
Your best option here might be for your "IRQ 1" handler to pass control to the BIOS's IRQ 1 handler, then when the BIOS's IRQ handler returns to your IRQ handler you can check the keyboard's queue and transfer any keypress to the correct application's queue yourself. However, in a well designed system it'd be the GUI's job to determine which application should receive the keypress (unless it's a global keypress like "alt+tab" that the GUI itself handles); and the kernel should just send all keypresses to the GUI to sort out.
Prochamber wrote:RTC Services - Copy the time to the next process upon exiting (if it is sane) this will work for PIT timer ticks as well.
RTC services are mostly broken (hint: there's no way to really tell if the RTC has been set to local time or UTC, or to handle daylight savings time properly). Even when they are made to work they're slow (BIOS uses lots IO port reads/writes to get/set the time instead of caching anything in the BDA). Basically; it's better to only use the RTC during boot and to keep track of time yourself after that.
Prochamber wrote:Can anyone see any other problems that I might face?
What I can't see is a sane reason to bother having multiple copies of the BDA.
Cheers,
Brendan