---
# System prepended metadata

title: 2019q1 Homework2 (kcalc)
tags: [linux2019]

---

# 2019q1 Homework2 (kcalc)
contributed by: <`flawless0714`>

## 自我檢查清單

* 解釋浮點運算在 Linux 核心中為何需要特別對待，以及 context switch 的過程中，涉及到 FPU/SIMD context，該注意什麼？
    * 提示: 參照 [Lazy FP state restore](https://en.wikipedia.org/wiki/Lazy_FP_state_restore) 和上方參考資料
    * 應該撰寫對應包含浮點運算的 Linux 核心模組，實際編譯和測試
    - **回答**
        - 因為浮點運算使用的暫存器較其他暫存器大，所以相對的進行浮點運算時假如發生 context switch 則會需要不小的時間開銷來保存 FPU state，而 kernel 幾乎每分每秒都在進行 context switch (system call, interrupts,  switch between kernel threads)，假如每次 context switch 都要維護 FPU state 則會對 kernel 效能造成不小的衝擊，更何況浮點運算很少在 kernel 中用到，所以大部分 kernel 都選擇不在其中使用 FPU，但假如非要執行不可 Linux kernel 也有提供相關 API (`kernel_fpu_begin()`, `kernel_fpu_end()`)。而一般 kernel 中的浮點數運算都會由軟體做掉(fixed point, 用整數運算相關 ops 即可完成)，雖然效率沒有 FPU 好，但基於少用與省時(context switch)所以尚可接受。
        - 涉及到 FPU/SIMD 的 context switch 須注意到許多處理器有支援 `lazy state switching` 功能，這功能讓 OS 不用在每次 context switch 都須維護 FPU/SIMD state，此功能搭配 kernel 一起運作。發生 context switch 時，kernel 會先對 FPU/SIMD 做標記，假如在待會新的 context 都沒有用到 FPU/SIMD 相關運算則其 state 將持續保存上個 context 的內容，反之，則會在新的 context 進行相關 ops 前對 kernel 發 trap，以使其保存上個 context 的內容。有鑑於此特性，資訊安全人員發現其可能被濫用的缺陷。有心人士可於 user space 使用[一些嫖妓倆 (提及於 Mechanism)](https://en.wikipedia.org/wiki/Lazy_FP_state_restore)以存取到前個 process 的 FPU/SIMD state，這是非常嚴重的問題，因為 FPU/SIMD 相關暫存器不只保存浮點數運算相關資料，其也被用來暫存加密相關資料, e.g. [AES instruction set](https://en.wikipedia.org/wiki/AES_instruction_set)。 作業系統相關工程師為了修復此缺陷讓作業系統效能下降了不少(其中一個解決方法是每次 context switch 都強制 FPU/SIMD state 一起切換，進而增加不少切換時間開銷)，而麻省理工強者在去年(2019年)底研究出同時能解決此缺陷又不失效能的[方法](https://www.csail.mit.edu/news/better-approach-preventing-meltdownspectre-attacks)。
* 在給定的 `calc.c` 檔案中，和 [fibdrv](https://hackmd.io/s/SJ2DKLZ8E) 一樣有 character device，但註冊用的 kernel API 不同 (`register_chrdev` vs. `alloc_c⇚hrdev_region`)，能否解釋其差異和適用場合呢？
    - **回答**
        - 兩個 API 差別主要在於 `register_chrdev` 可自訂 driver 的 major number 與 minor number，而 `alloc_chrdev_region` 僅可自訂 major number。
        - `register_chrdev` (使用 0 作為 major number 參數時還是會動態分配 major number) 適合用於 common devices，他們經常會比你要載 driver 還早拿到你想要的 major number。除非你寫的 driver 有進到 mainline，否則強烈建議使用 `alloc_chrdev_region`，以減少註冊失敗的可能性。
* 在 `scripts/test.sh` 檔案中，有一道命令為 `sudo chmod 0666`，這個作用為何？對於我們測試有何幫助？能否對 [fibdrv](https://hackmd.io/s/SJ2DKLZ8E) 建立的 `/dev/fibonacci` device file 也套用類似修改呢？另外，請解釋 device file 在核心及使用者層級的功能
* 在 `calc.c` 檔案中，用到 `copy_to_user` 這個 kernel API，其作用為何？本例使用該 API 做了什麼事？若是資料量增長，是否會有效能的嚴重衝擊呢？
    - `copy_to_user()` 的用途為將 kernel space 的記憶體複製到 user space，更明確的說法為複製 kernel 中 stack (`copy_to_user()` 在複製前會驗證是否欲複製之記憶體區塊位於 stack 內)內的內容到 user space 。
* 找出至少 3 個 Linux 核心中使用定點數的案例，搭配程式碼解說
    * 提示: 參照 [Linux Kernel Load Average 計算分析
](http://brytonlee.github.io/blog/2014/05/07/linux-kernel-load-average-calc/), [What Every Computer Scientist Should Know About Floating-Point Arithmetic](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html), [Load average explained](https://wiki.nix-pro.com/view/Load_average_explained)
* 是否知曉 MathEx 如何解析給定字串，從而分離出變數和對應數學表示法呢？
* 如何對 `MathEx` 進行效能分析？能否找出相似的 math expression 來分析比較呢？
    * 提示: 參照 [muparserSSE - A Math Expression Compiler](http://beltoforion.de/article.php?a=muparsersse)
* 在 `MathEx` 原始程式碼的 `expression.[ch]` 裡頭 `vec` 相關的程式碼，主要做什麼事？有沒有發現類似 [list](https://hackmd.io/s/S12jCWKHN) 使用到的技巧呢？
    * 提示: 參照 `mathex/test-unit.c` 的測試項目
* 解釋 `MathEx` 一類的 math expression 在真實世界有哪些應用？甚至，是否在 Linux 核心就存在類似的程式碼？
    * 提示: 參照 [A thorough introduction to eBPF](https://lwn.net/Articles/740157/)
* 如果要將使用者層級的 C 語言程式，搬到 Linux 核心作為核心模組 (LKM)，該注意哪些議題呢？請舉例說明
    * 提示: 注意 `__KERNEL__` 巨集的定義, [kmalloc](https://www.kernel.org/doc/htmldocs/kernel-api/API-kmalloc.html) 的使用, [vmalloc](https://www.kernel.org/doc/htmldocs/kernel-api/API-vmalloc.html) 的使用 (以及後兩者的差異)
* [fixed point arithmetic for RT-Linux](http://netwinder.osuosl.org/pub/netwinder/docs/nw/rt_fixed/doc/html/rt_fix.html) 的運作原理為何？給定的程式碼已經存在超過 20 年，很多細節已有出入，可否嘗試移植到 Linux `v4.15+` 呢？

## 筆記
- MathEx
    - `expr_func()`
        用於檢驗輸入之函數 MathEx 中是否有提供實做，有則將該實做 assign 給 `struct expr` 中的 function pointer，`*f`，反之則以 `NULL` assign 給 `*f`;
## 參考資料
- [linux-kernel-and-floating-point](http://porterchen-note.blogspot.com/2011/03/linux-kernel-and-floating-point.html)
- [GFP flags](https://elixir.bootlin.com/linux/v4.15.18/source/include/linux/gfp.h#L211)

###### tags: `linux2019`