Open7

ゼロからのOS自作入門をやる

r_mutaxr_mutax

Vector2Dクラスの定義でミスしてた。
operator +=で受け取るVector2Dクラスが同じ型とは限らないので、別の型で定義しているところ、クラス自体と同じようにtemplate<typename T>って書いてしまっていた。

template<typename T>
struct Vector2D {
    T x, y;

    template<typename U>
    Vector2D<T>& operator += (const Vector2D<U>& rhs){
        x += rhs.x;
        y += rhs.y;
        return *this;
    }
};
r_mutaxr_mutax

変数にinlineがついているの初めてみた。

inline int hoge;

inline変数といってC++17から使える機能らしい。
inlineをつけた変数宣言をヘッダに書いた場合、変数の実体は単一になる。変数宣言だけ.cppソースに抜きだして…とかしなくていい。

r_mutaxr_mutax

7章に入った。

IDTはstd::arrayで割り込みベクタ定義して、ここに割り込み記述子登録しておく。
IDTのoffsetには割り込みハンドラのアドレスを設定する。

ゼロからのOS自作入門ではMSI割り込みの仕組みを使って割り込みを発生させる。
MSI割り込みでは特定のメモリアドレスへの書き込みで、割り込みを発生させる。割り込みが発生したら、割り込みベクタを見に行って対応する割り込みハンドラを探し、実行する。

r_mutaxr_mutax

割り込みの設定をしたあとは、Kernelのmain関数で無限ループで割り込み待ちをする。
インラインアセンブラでcli命令を実施し、割り込み許可フラグを落として割り込みを止める。
メッセージを受け取れたらsti命令で割り込み許可フラグを立て割り込みを許可する。

こうしている理由は、割り込みのメッセージを受け取ってる最中に新たなメッセージが積まれると厄介だから。割り込みに限らず、プロセス間通信とかでもよくやる。セマフォとかつかったり。

メッセージキューが空だったらhlt命令を使ってCPUを省電力モードにする。割り込みが起こるとhltから自動で復帰するらしい。

r_mutaxr_mutax

9章
プログラマからは隠蔽されたシャドウバッファを作って、描画時にはシャドウバッファからフレームバッファにmemcpyで書き込むようにした。
memcpyで書き込むことで高速化をしている?

サブのバッファを作って裏で書いておいて、描画時に一括でコピーする方式はダブルバッファリング方式とか言って、描画系の処理を書くとよく出てくる。

r_mutaxr_mutax

このスクラップすごい放ったらかしにしてましたが、裏でやってました。
今は19章 ページングをやっています。

↓はELFファイルを読み込んで、最初のロードセグメントを探しているところ。
Elf64_Phdr->e_phoffがElfの先頭からプログラムヘッダへのオフセットが入っているので、ehdrに足し合わせれば実際に置いてあるメモリがわかる。

プログラムヘッダは配列になっているので、Elf64_Ehdr->phnumだけ回してElf64_Phdr->p_typeを見ていけばLOADセグメントを探せる。
最初のLOADセグメントを返している。


    Elf64_Phdr* GetProgramHeader(Elf64_Ehdr* ehdr){
        return reinterpret_cast<Elf64_Phdr*>(
            reinterpret_cast<uintptr_t>(ehdr) + ehdr->e_phoff);
    }

    uintptr_t GetFirstLoadAddress(Elf64_Ehdr* ehdr){
        auto phdr = GetProgramHeader(ehdr);
        for(int i = 0; i < ehdr->e_phnum; ++i){
            if(phdr[i].p_type != PT_LOAD) continue;
            return phdr[i].p_vaddr;
        }
        return 0;
    }