1. ホーム
  2. linux

[解決済み] トラップフレームとは何ですか?また、トラップフレームとtask_structの違いは何ですか?

2022-03-01 20:18:02

質問

task_structはCPUの状態を保存するもので、trap frameは同じことをするものですが、どう違うのでしょうか?また、トラップフレームはデータ構造体なのか、それとも単なる概念なのでしょうか?

どのように解決するのですか?

CPUの状態はコンテキストスイッチに関するもので、trapframeは例外やirqが発生した後にtcbに保存されたユーザースペースの状態を保持します。

をベースに説明します。 ラズベリーパイ2(ARMv7)用自作OS

コンテキストとトラップフレームを格納するtask構造体です。

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);
};

コンテキストは、他のタスクにプリエンプトされる前のタスクの状態を表す、コールセーブされたレジスタのセットである(コンテキストスイッチ)。

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;
};

スケジューラでのコンテキストスイッチが発生すると、現在のタスクはそのレジスタを *ctx in class task そして、次のタスクから新しいレジスタがロードされます。

この例では、特定のオブジェクトのメソッドを呼び出しているので、R0はTHISポインタであることに注意してください。つまり、引数は R1 と 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}");
}

次に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
};

トラップフレームは、例外発生時に保存されたレジスタセットを保存するので、トラップフレームを使えば、(例外やirqが処理される時に)戻って実行を進めることができます。