40 lines
1.3 KiB
C++
40 lines
1.3 KiB
C++
#include "context.h"
|
|
|
|
#include "../debug/assert.h"
|
|
#include "../debug/kernelpanic.h"
|
|
|
|
/*! \brief Panic function
|
|
*
|
|
* If the kickoff function (assigned in \ref prepareContext) *returns*, this
|
|
* parameterless function will be called -- and stop the execution.
|
|
*/
|
|
static void panic() {
|
|
// we should not come back here
|
|
kernelpanic("Application should not return from context_kickoff");
|
|
}
|
|
|
|
void prepareContext(void* tos, Context& context,
|
|
void (*kickoff)(uintptr_t, uintptr_t, uintptr_t),
|
|
uintptr_t param1, uintptr_t param2, uintptr_t param3) {
|
|
assert(tos != nullptr && "Top Of Stack must not be nullptr");
|
|
assert((uintptr_t)tos % 16 == 0 && "Top Of Stack be 16 byte aligned");
|
|
assert(kickoff != nullptr && "Kickoff function missing");
|
|
|
|
// XXX Double check alignment. This seems to work, but the stack pointer for
|
|
// `panic` should not be aligned to 16-bit?
|
|
void** sp = reinterpret_cast<void**>(tos);
|
|
*(--sp) = reinterpret_cast<void*>(panic); // return address
|
|
*(--sp) = reinterpret_cast<void*>(kickoff); // start the thread in C land
|
|
*(--sp) = reinterpret_cast<void*>(fake_systemv_abi); // pass via registers
|
|
|
|
context = {
|
|
.rbx = 0,
|
|
.rbp = 0,
|
|
.r12 = 0,
|
|
.r13 = param3,
|
|
.r14 = param2, // Second parameter to kickoff
|
|
.r15 = param1, // First parameter to kickoff
|
|
.rsp = reinterpret_cast<void*>(sp),
|
|
};
|
|
}
|