diff --git a/README.md b/README.md index fd24ec56f51f288af6c898b17ce0cae8e58116d2..deda2e75291ace343fc7ba89988cb37974ba33be 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,159 @@ OS的输出文件被é…置在了`debug/qemu.log`文件ä¸ï¼Œè€Œç»ˆç«¯ä¸çš„QEMU ## 模å—讲解 -### `mizu/kernel` +我们OSçš„å†…æ ¸æ€è¿è¡Œåœ¨å¼‚æ¥çš„æ— æ ˆå程上下文ä¸ã€‚TODO + +### `ksync(-core)` + +è¿™ä¸ªæ¨¡å—æä¾›äº†å„ç§åœ¨å¼‚æ¥ä¸Šä¸‹æ–‡ä¸åŒæ¥æºè¯ï¼Œè¿™äº›æ•°æ®ç»“æž„å‡å–自(`async-lock`)[https://github.com/smol-rs/async-lock] crate: + + - `mutex` äº’æ–¥é” + - `rw_lock` è¯»å†™é” + - `semaphore` ä¿¡å·é‡ + +æ¤å¤–,还有如下数æ®ç»“构: + + - `broadcast` 广æ’事件订阅 + - `mpmc` å¤šæ¶ˆè´¹è€…å¤šç”Ÿäº§è€…çš„é€šé“ + - `RCU` æ— é” Read Copy-Update 机制 + - `epoch` 多线程垃圾回收算法 + +在`core`ä¸ï¼Œå®žçŽ°äº†å•个CPUæ ¸å†…çš„ä¸´ç•ŒåŒºè®¿é—®æœºåˆ¶ï¼š`fn critial`,以用æ¥é…åˆ`spin` crate的自旋é”,防æ¢å¯èƒ½çš„䏿–é‡å…¥å¯¼è‡´é€’å½’é”。 + +独立出`core`çš„åŽŸå› æ˜¯ï¼Œç”±äºŽæ¨¡å—间有相互ä¾èµ–çš„å…³ç³»ï¼Œé€šè¿‡ç‹¬ç«‹å‡ºä¸€äº›å…±ç”¨çš„æŽ¥å£æˆ–æœåС就å¯ä»¥æ¥æ¶ˆé™¤æ¨¡å—ä¾èµ–图ä¸çš„环。 + +### `ktime(-core)` + +这个模å—主è¦å¤„ç†æ—¶é—´ç›¸å…³çš„æ•°æ®ç»“构。 + +- 在`core`䏿¨¡ä»¿æ ‡å‡†åº“定义了独立的`Instant`ï¼Œå¹¶åƒæ ‡å‡†åº“ä¸€æ ·å¯ä»¥ä¸Ž`core::time::Duration`进行互æ“作; +- 模仿(`async-io`)[https://doc.rs/async-io/latest/async_io/struct.Timer.html]实现了异æ¥å®šæ—¶å™¨åŠå…¶é˜Ÿåˆ—。 + +### `co-trap` + +这个模å—处ç†ç”¨æˆ·æ€ä¸Žå†…æ ¸æ€é€šè¿‡ä¸æ–机制相互切æ¢çš„æµç¨‹æŽ§åˆ¶å’Œå¯¹ç”¨æˆ·ä¸Šä¸‹æ–‡çš„ç³»ç»Ÿè°ƒç”¨å‚æ•°æŠ½è±¡ã€‚ + +ä¼ ç»Ÿçš„ä¸æ–处ç†ç¨‹åºé€šå¸¸ä¼šä»¥å‡½æ•°è°ƒç”¨çš„å½¢å¼ï¼Œä¼ªä»£ç 如下: + +1. ä¿å˜ç”¨æˆ·ä¸Šä¸‹æ–‡ï¼› +2. é€šè¿‡æ ‡å‡†çš„å‡½æ•°è°ƒç”¨å½¢å¼è·³è½¬åˆ°ä¸æ–处ç†ç¨‹åºï¼› +3. æ¢å¤ç”¨æˆ·ä¸Šä¸‹æ–‡å¹¶é€€å‡ºã€‚ + +è€Œè¿™é‡Œä½¿ç”¨ä¸€ç§æ–°çš„æ–¹å¼ï¼Œæ€æƒ³ä¸ŽåŽ»å¹´çš„ä¸€ç‰å¥–作å“FTL OSä¸è°‹è€Œåˆï¼Œå…¶ä¼ªä»£ç 分æˆä¸¤ä¸ªéƒ¨åˆ†ï¼Œè¿›å…¥ç”¨æˆ·å’Œè¿›å…¥å†…æ ¸ã€‚ + +è¿›å…¥å†…æ ¸æ—¶ï¼š + +1. ä¿å˜ç”¨æˆ·ä¸Šä¸‹æ–‡ï¼› +2. 通过sscratch切æ¢å¹¶åŠ è½½å†…æ ¸ä¸Šä¸‹æ–‡ï¼› +3. 退出函数调用(通过`ret`指令)。 + +进入用户时: + +1. ä¿å˜å†…æ ¸ä¸Šä¸‹æ–‡ï¼› +2. 通过a0切æ¢å¹¶åŠ è½½ç”¨æˆ·ä¸Šä¸‹æ–‡ï¼› +3. é€€å‡ºä¸æ–函数(通过`sret`指令)。 + +å¯ä»¥çœ‹å‡ºï¼Œè¿™ä¸¤æ®µä»£ç 是完全对å¶çš„,并ä¸è·Ÿä¼ 统方å¼ä¸€æ ·æ˜¯ä¸€ä¸ªå•独的函数调用过程。 + +å®žé™…ä¸Šè¿™å°±æ˜¯ä¸€ç§æœ‰æ ˆåç¨‹çš„ä¸Šä¸‹æ–‡åˆ‡æ¢æ–¹å¼ã€‚åœ¨ä¼ ç»Ÿä¸ä¾é æ— æ ˆåç¨‹çš„å†…æ ¸ä¸Šä¸‹æ–‡ä¸ï¼Œå†…æ ¸çº¿ç¨‹çš„ç›¸äº’åˆ‡æ¢ä¾¿æ˜¯é‡‡ç”¨çš„è¿™ç§æ–¹å¼ã€‚è¿™é‡Œå°†è¿™ç§æ–¹å¼è½¬ç§»åˆ°è¿™é‡Œï¼Œå¯ä»¥ä½¿å¾—用户代ç å’Œå†…æ ¸ä»£ç å˜æˆä¸¤ä¸ªç‹¬ç«‹çš„æŽ§åˆ¶æµã€‚è€Œä»Žå†…æ ¸æ€çš„视角æ¥çœ‹ï¼Œè¿›å…¥ç”¨æˆ·æ€ç›¸å½“于调用函数,而退出用户æ€ä¾¿æ˜¯è°ƒç”¨å‡½æ•°è¿”回。 + +```assembly +// a0 <- trap_frame: *mut TrapFrame +// a1 <- scratch register + +.global _return_to_user +.type _return_to_user, @function +_return_to_user: + xchg_sx // 交æ¢s系列寄å˜å™¨ + load_ux // åŠ è½½ä¸æ–寄å˜å™¨ï¼ˆsepcï¼‰ç‰ + load_tx // åŠ è½½aã€t系列和spã€tpç‰å¯„å˜å™¨ + load_scratch // åŠ è½½a1 + + csrw sscratch, a0 // a0å³ä¸ºè¯¥å‡½æ•°çš„傿•°ï¼Œä¿å˜ç”¨æˆ·ä¸Šä¸‹æ–‡çš„地å€ï¼›å°†å…¶å˜å…¥sscratchä¸ + ld a0, 16*8(a0) // åŠ è½½a0 + sret + +.global _user_entry +.type _user_entry, @function +.align 4 +_user_entry: + csrrw a0, sscratch, a0 // å–å‡ºç”¨æˆ·ä¸Šä¸‹æ–‡åœ°å€ + save_scratch + save_tx // ä¿å˜aã€t系列和spã€tpç‰å¯„å˜å™¨ + save_ux // ä¿å˜ä¸æ–寄å˜å™¨ï¼ˆsepcï¼‰ç‰ + csrr a1, sscratch // ä¿å˜a1 + xchg_sx // 交æ¢s系列寄å˜å™¨ + ret +``` + +è€Œå¯¹äºŽç”¨æˆ·ä¸Šä¸‹æ–‡çš„ç³»ç»Ÿè°ƒç”¨å‚æ•°æŠ½è±¡ï¼Œæˆ‘们定义了一个泛型包装结构,å¯ä»¥å¾ˆå®¹æ˜“地从泛型ä¸çš„函数ç¾å看出系统调用的函数原型ç¾å。在实现的时候使用了å®å±•å¼€æ¥ä¿è¯æ¯ä¸ªå‡½æ•°ç¾å的有效性。 + +```rust +pub struct UserCx<'a, A> { + tf: &'a mut TrapFrame, + _marker: PhantomData<A>, +} + +macro_rules! impl_arg { + ($($arg:ident),*) => { + impl<'a, $($arg: RawReg,)* T: RawReg> UserCx<'a, fn($($arg),*) -> T> { + #[allow(clippy::unused_unit)] + #[allow(non_snake_case)] + #[allow(unused_parens)] + /// Get the arguments with the same prototype as the parameters in the function prototype. + pub fn args(&self) -> ($($arg),*) { + $( + let $arg = self.tf.syscall_arg::<${index()}>(); + )* + ($(RawReg::from_raw($arg)),*) + } + + /// Gives the return value to the user context, consuming `self`. + pub fn ret(self, value: T) { + self.tf.set_syscall_ret(RawReg::into_raw(value)) + } + } + }; +} + +all_tuples!(impl_arg, 0, 7, P); +``` + +使用示例: + +```rust +let mut tf = Default::default(); + +let user: UserCx<'_, fn(u32, *const u8) -> usize> = + UserCx::from(&mut tf); + +let (a, b): (u32, *const u8) = user.args(); +user.ret(a as usize + b as usize); +``` + +### `art` + +### `ksc(-core, -macros)` + +### `umio`å’Œ`umifs` + +### `afat32` + +### `kmem`å’Œ`range-map` + +### `devices` + +### å…¶ä»–çš„ä¸€äº›æ¨¡å— + +- `kalloc` : å†…æ ¸å’ŒRustè¯è¨€è‡ªç”¨çš„å†…æ ¸å †åˆ†é…器; +- `klog` : 一些日志和输出的å®å’Œå‡½æ•°ï¼› +- `rv39-paging` : RISC-V çš„ Sv39 页表机制; +- `config` : ä¸€äº›å‚æ•°ï¼› +- `hart-id` : å˜å‚¨ hart-idï¼› +- `rand-riscv` : éšæœºæ•°ç”Ÿæˆå‡½æ•°ï¼› +- `sygnal` : å°šä¸å®Œå¤‡çš„ä¿¡å·å¤„ç†æœºåˆ¶ã€‚ + +### `kernel` è¿™æ˜¯å†…æ ¸ç¨‹åºçš„crate,也是å„ä¸ªæ¨¡å—æ•´åˆçš„终点。在这个crateä¸ï¼Œé€ä¸ªä»‹ç»ä¸€äº›æ¯”较é‡è¦çš„设计点。 @@ -267,7 +419,7 @@ pub unsafe fn init(fdt_base: *const ()) -> Result<(), FdtError> { 而对于文件系统,我们也直接建立了串å£ã€ç®¡é“ã€DevFSç‰å¯¹åº”的文件系统结构。其ä¸ä¸²å£æ–‡ä»¶ä½œä¸º`klog`模å—的简å•包装,管é“也仅是对`kmem::Phys`的简å•包装,而DevFS则是囊括了`umifs::misc`å’Œå—设备ä¸çš„æ‰€æœ‰æ–‡ä»¶èŠ‚ç‚¹ã€‚ -## 常è§é—®é¢˜ +## 常è§é—®é¢˜ä¸Žç»†èŠ‚ ### å¯åŠ¨æ—¶çš„åœ°å€è½¬æ¢ @@ -276,6 +428,10 @@ pub unsafe fn init(fdt_base: *const ()) -> Result<(), FdtError> { 1. 为了ä¿è¯é•¿è·³è½¬ä¸å‡ºé”™ï¼Œæˆ‘们使用一个å¯åŠ¨é¡µè¡¨ï¼ŒåŒæ—¶æ˜ 射低地å€å’Œé«˜åœ°å€ï¼Œå¹¶åœ¨å…¥å£å…ˆåŠ è½½è¯¥é¡µè¡¨ï¼Œè·³è½¬ä¹‹åŽå†æ¢æˆå…¶ä»–页表或者抹去低地å€çš„页表; 2. 为了ä¿è¯ç¬¦å·çš„ç»Ÿä¸€æ€§ï¼Œæˆ‘ä»¬å°†å†…æ ¸ç¼–è¯‘æˆé™æ€çš„PIE(Position-Independent Executable),å³ä¸ä¾èµ–ç»å¯¹åœ°å€çš„坿‰§è¡Œæ–‡ä»¶ã€‚è¿™æ ·å¯ä»¥å°†æ‰€æœ‰çš„å‡½æ•°è°ƒç”¨å’Œè·³è½¬è½¬æ¢æˆç›¸å¯¹PCçš„å¯»å€æ¨¡å¼ï¼Œå…·ä½“表现为汇编出包å«`auipc`指令的代ç 。并且如果ä¸èƒ½æŽ§åˆ¶GOT(全局å移表)的生æˆï¼Œæˆ‘们还需è¦åœ¨é“¾æŽ¥é€‰é¡¹ä¸æ·»åŠ è¯¸å¦‚`--apply-dynamic-relocs`å’Œ`-Ztls-model=local-exec`ç‰é€‰é¡¹ï¼Œå¹¶ä¸”在链接脚本ä¸åˆ¶å®šæœ€ç»ˆçš„åŠ è½½åœ°å€ï¼Œåœ¨é™æ€è¿žæŽ¥æ—¶å°±ç¡®å®šGOTä¸è¡¨é¡¹çš„值,从而é¿å…我们程åºè¿è¡Œæ—¶å†éº»çƒ¦åœ°åЍæ€è®¾ç½®ã€‚ +### æ¯ä¸ªæ¨¡å—内部的å•元测试 + +为了ä¸ä¾èµ–äºŽå†…æ ¸æ¥æµ‹è¯•å„个模å—,我们在一些模å—内部实现了å•元测试,直接è¿è¡Œåœ¨å®¿ä¸»æœºï¼ˆå·¥ä½œæœºå™¨ï¼‰å¹³å°ä¸‹ã€‚ + ### 第三方ä¾èµ–的自动下载 在æ¤ç›´æŽ¥å¥‰ä¸Šè‡ªåŠ¨ä¸‹è½½ç¬¬ä¸‰æ–¹ä¾èµ–项的脚本,帮助åŒå¦ä»¬é¿å‘ã€‚ä½¿ç”¨æ—¶æ³¨æ„æ›¿æ¢å…¶ä¸å¯èƒ½ä¸Žè‡ªå·±é¡¹ç›®ä¸ä¸€è‡´çš„内容。