task_struct is used to store the status of CPU and trap frame does the same thing so how they differ? And trap frame is a data struct or a just and concept?
The cpu state - is about context switch, while trapframe holds userspace state saved in tcb after exception or irq have arised.
My explanation will be based on self-written OS for raspberry pi 2 (ARMv7)
Here is task struct, which stores context and trap frame:
class task {
private:
public:
uint32_t pid;
pde_t *pgd;
tstate state;
uint32_t *kstack;
context *ctx;
trapframe *tf;
task() {};
void init_vm();
int load_binary(char *binary_obj);
};
the context is a set of callee-saved registers, which represents state of the task before it was preempted by other task (context switch)
struct context {
uint32_t r4;
uint32_t r5;
uint32_t r6;
uint32_t r7;
uint32_t r8;
uint32_t r9;
uint32_t r10;
uint32_t r11;
uint32_t r12;
uint32_t lr;
};
when the context switch in scheduler is occured, current task saves its registers to *ctx in class task
, and new set of registers are loaded from next task:
Note that R0 in below example is THIS pointer, because we call method of a particular object. So the arguments are R1 and R2
void scheduler::swtch(struct context **oldctx, struct context *newctx)
{
/* r0-r3 are not preserved during call, no need to save them */
asm volatile("push {r4-r12, lr}");
/* save current kernel thread sp to oldctx */
asm volatile("str r13, [r1]");
/* Load newctx (new sp) to sp register */
asm volatile("mov r13, r2");
/* Load all other registers from new ctx,
* refer struct context format for details */
asm volatile("pop {r4-r12, lr}");
}
Now about trapframe:
struct trapframe {
uint32_t sp_usr; // user mode sp
uint32_t lr_usr; // user mode lr
uint32_t sp_svc;
uint32_t lr_svc;
uint32_t spsr;
uint32_t r[N_GEN_REGS];
uint32_t pc; // (lr on entry) instruction to resume execution
};
Trapframe stores register set which was saved during exception have arised, so using trapframe we can return back and proceed execution (when exception or irq will be handled)