Closed vilhelmgray closed 9 years ago
I think calling the command line is a very bad idea.
First of all, call
is meant for code that does actually return.
This does not return so we should probably use jmp
.
I will look into that.…
/os/cli.asm on line 78 call
s the program too.
So we need to ret
urn to that piece of code.
All we need to do that:
ret
statement thereThis is (or should be) what happens after the program finished execution.
The problem is that the program need not have finished executing, so we needed some sort of bootstrapping.
The easiest solution (and probably the most safe one) would be to reboot the whole operating system. Note that I am talking about the OS, not the computer. The OS would need to disable all processors, it's stack and a few other things and jmp
back to _kernelstart.
As mentioned above, we have multiple processors.
If we look at /os/kernel64.asm on line 72, we see this comment:
All cores start here on first start-up and after an exception
What does that mean?
We are working in a multithreaded environment, that means, if we call exit
we either want to stop the whole program (which, in a single-process OS would lead to, more or less, rebooting the OS so, see above) or we want to exit our current thread.
Exiting our thread works by simply resetting it's stack and waiting for a new workload. Unfortunately this is exactly what happens in _apclear (see the above links).
So in this scenario, the whole thread would just stop and opt out of existence.
Just blame the programmers if they forget to unlock
mutexes.
As far as I know, newlib is trying to provide the same functionality (or at least a subset) as the standard C library. Please correct me if I am wrong.
If, in C, the exit(0)
is called, it exit's the whole program.
To reproduce this the newlib would need to reset the whole OS (or at least some parts of it) as pointed out above. This would also fix #50.
Also it would be useful to have a syscall/function or something to exit the current thread (if that isn't yet implemented).
Agreed @benaryorg !
Calling the CLI again is not the proper method... especially if a multi-threaded process exits while other CPU cores are still executing code.
Looking into a fix for this that will involve resetting all CPU cores and restarting the CLI.
would the ret
assembly call do anything in this case?
It exit()
really resets all processors then the ret
will never get executed. It will only have an effect if your custom programs main function returns.
Well, could another possible solution be to call the kernel again? ie, jump to the start of the os and let everything re-initialize
Isn't the easiest thing to just jmp to reboot?
2015-07-08 16:09 GMT+02:00 Mason X notifications@github.com:
Well, could another possible solution be to call the kernel again? ie, jump to the start of the os and let everything re-initialize
— Reply to this email directly or view it on GitHub https://github.com/ReturnInfinity/BareMetal-OS/pull/83#issuecomment-119592112 .
but that's rebooting, which is different from resetting.
Also, please keep in mind that we have multiple processors (or at least threads) which are not just going to stop it one of them does.
One solution would be, to let them a l get an exception.
Then there would only be left the reset of the memory structures (e.g. memory allocations).
How about using paging to reset all threads? First emptying the smp-queue and then unmapping all memory allocated for the program and the user allocated memory would do the trick I think.
@benaryorg is correct.
The current plan is to add a system call (in b_system_misc) that does the following: -clear memory map -clear network and RTC callbacks -reset all CPU cores to jump to ap_clear in kernel64.asm (there is already an interrupt vector for this) -restart the CLI
Is it possible, and if yes, how, to send an interrupt to all processors?
loop through all processors?
Sorry, I wasn't clear enough.
What I meant was:
How would that look in Assembly code?
I quickly looked around the internet and found this Wikipedia Article but it is a bit short. It would be great if someone of you added some sample code for x86_64 there.
Here is how BareMetal inits the CPUs: https://github.com/ReturnInfinity/BareMetal-kernel/blob/master/src/x86-64/init/64.asm#L163
I just need to adjust the code for the new reset function. I don't want to reset the calling CPU core accidentally so will need to call os_smp_get_id first.
os_smp_reset: https://github.com/ReturnInfinity/BareMetal-OS/blob/master/os/syscalls/smp.asm#L19
That code send a message via the APIC to a specific CPU core telling it to execute interrupt 0x81 which is ap_clear in kernel64.asm
@benaryorg For IPI code you can take a look here: https://github.com/ReturnInfinity/Pure64/blob/master/src/init/smp.asm
That is the code for how Pure64 (The BareMetal bootloader) 'boots' up the other CPU cores.
@IanSeyler Thanks a lot!
You could, just to be sure to have everything cleaned up, do something like this then:
@benaryorg :+1:
This should be properly addressed in the last push: https://github.com/ReturnInfinity/BareMetal-OS/commit/59d15a4dcf39d77229e51fc4e261f0e437c0e9db
This should fix the infinite loop problem in issue #50 by calling the OS command line subroutine on a Newlib
_exit
function call.However, I have noticed a regression with this fix: upon executing the command line
exit
command after a program calls the Newlib_exit
function, a General Protection fault occurs. We should investigate the cause of this regression before closing issue #50.