# Linmo 開發紀錄 contributed by < `HeatCrab` > > [GitHub](https://github.com/sysprog21/linmo) > [過往開發筆記](https://hackmd.io/@sysprog/HyIQvDYWll) ## Linmo 的事前準備 因為我將 Linux 系統重新安裝到了新的磁碟上,等同於重灌了整個 Linux 系統,所以要重啟 Linmo 專案也需要安裝相對應的套件。 參考 <[Operating System in 1,000 Lines](https://operating-system-in-1000-lines.vercel.app/en/01-setting-up-development-environment)> 教學文件,先安裝 QEMU: ```shell $ sudo apt update && sudo apt install -y clang llvm lld qemu-system-riscv32 curl ``` 接著安裝 [riscv-gnu-toolchain](https://github.com/riscv-collab/riscv-gnu-toolchain),先安裝必要套件: ```shell $ sudo apt-get install -y autoconf automake autotools-dev curl python3 python3-pip python3-tomli libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build git cmake libglib2.0-dev libslirp-dev ``` 接著將創建一個目錄並將檔案 clone 下來: ```shell $ mkdir -p ~/riscv-toolchain $ cd ~/riscv-toolchain $ git clone https://github.com/riscv-collab/riscv-gnu-toolchain $ cd riscv-gnu-toolchain ``` 最後設定安裝路徑之後開始編譯,過程會花一點時間大概 20 分鐘左右: ```shell $ ./configure --prefix=~/riscv --with-arch=rv32i --with-abi=ilp32 $ make -j$(nproc) ``` 最後一個步驟,驗證是否編譯成功: ```shell $ riscv-none-elf-gcc --version riscv-none-elf-gcc () 15.1.0 Copyright (C) 2025 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ``` 但是我的 toolchain 編譯後 none 是 unknown ,所以為了確定能正常編譯 Linmo 專案,我選擇針對我的 toolchain 建立 Symbolic Link: ```shell $ ln -s riscv32-unknown-elf-gcc riscv-none-elf-gcc $ ln -s riscv32-unknown-elf-ld riscv-none-elf-ld $ ln -s riscv32-unknown-elf-as riscv-none-elf-as $ ln -s riscv32-unknown-elf-objcopy riscv-none-elf-objcopy $ ln -s riscv32-unknown-elf-ar riscv-none-elf-ar $ ln -s riscv32-unknown-elf-objdump riscv-none-elf-objdump $ ln -s riscv32-unknown-elf-size riscv-none-elf-size ``` 最後根據 Linmo 專案中的 [README](https://github.com/sysprog21/linmo/blob/main/README.md),我們執行以下命令確認結果: ```shell $ make clean $ make $ make hello $ make run ``` 並預期得到以下的輸出結果: ```shell Ready to launch Linmo kernel + application. Linmo kernel is starting... Heap initialized, 130012136 bytes available task 1: entry=80000234 stack=80002c84 size=4096 task 2: entry=800001f4 stack=80003d34 size=4096 task 3: entry=80000184 stack=80004db0 size=4096 task0 has id 1 task1 has id 2 task2 has id 3 Scheduler mode: Preemptive [task 1 100000] [task 3 300000 - sys uptime: 0.013s] [task 1 100001] [task 3 300001 - sys uptime: 0.033s] [task 1 100002] [task 3 300002 - sys uptime: 0.053s] [task 1 100003] [task 3 300003 - sys uptime: 0.073s] [task 1 100004] [task 3 300004 - sys uptime: 0.093s] [task 1 100005] [task 2 200000] [task 3 300005 - sys uptime: 0.123s] [task 1 100006] ... ``` ## 關於 Linmo 的所見所聞所感 ### Dcoumentation 閱後筆記 **[Documentation/hal-riscv-context-switch.md](https://github.com/sysprog21/linmo/blob/main/Documentation/hal-riscv-context-switch.md)** : ## MMU 開發 ### 實作實體記憶體保護機制(PMP) :::warning 先閱讀 ISA-privilged 3.6 與 3.7 ::: 參考邱冠維學長之前為了修復 app 目錄下程式碼錯誤,實驗性地新增的 PMP 實作: ```c #define PMP_R 0x01 #define PMP_W 0x02 #define PMP_X 0x04 #define PMP_NAPOT 0x18 void setup_pmp(void) { // Set up a PMP to permit access to all of memory. // Ignore the illegal-instruction trap if PMPs aren't supported. unsigned long pmpc = PMP_NAPOT | PMP_R | PMP_W | PMP_X; asm volatile ("la t0, 1f\n\t" "csrrw t0, mtvec, t0\n\t" "csrw pmpaddr0, %1\n\t" "csrw pmpcfg0, %0\n\t" ".align 2\n\t" "1: csrw mtvec, t0" : : "r" (pmpc), "r" (-1UL) : "t0"); } ``` ## [app/rtsched.c](https://github.com/sysprog21/linmo/blob/main/app/rtsched.c) 的測試不如預期(?