---
# System prepended metadata

title: Linmo 開發紀錄

---

# 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) 的測試不如預期（？