Skip to content

Commit 89b6fa0

Browse files
FerralCoderrusty1968
authored andcommitted
add details on porting hubris to riscv
1 parent 9c66065 commit 89b6fa0

File tree

2 files changed

+131
-1
lines changed

2 files changed

+131
-1
lines changed

docs/src/design/hubris-riscv.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Porting Hubris OS to RISC-V
2+
3+
## Executive Summary
4+
5+
Porting Hubris OS to RISC-V would be **trivial** compared to porting most operating systems because Hubris was explicitly designed with architecture portability in mind. The documentation already includes RISC-V specifications, and the architecture-specific code is minimal and well-isolated.
6+
7+
## 🏗️ Architecture-Agnostic Design Philosophy
8+
9+
### Minimal Kernel Surface Area
10+
Hubris follows a **microkernel philosophy** where the kernel does as little as possible:
11+
12+
- **Small syscall set**: Only 14 syscalls total.
13+
- **Preemptive scheduling**: Simple priority-based scheduler.
14+
- **Statically allocated**: All resources determined at compile time
15+
- **Task isolation**: Memory protection via region-based MPU/PMP, not page tables
16+
17+
### Clean Architecture Abstraction
18+
19+
All architecture-specific code is isolated in a single module:
20+
21+
```rust
22+
// sys/kern/src/arch.rs - Current structure
23+
cfg_if::cfg_if! {
24+
if #[cfg(target_arch = "arm")] {
25+
pub mod arm_m;
26+
pub use arm_m::*;
27+
} else {
28+
compile_error!("support for this architecture not implemented");
29+
}
30+
}
31+
```
32+
33+
Adding RISC-V support requires only:
34+
35+
```rust
36+
// Proposed addition
37+
} else if #[cfg(target_arch = "riscv32")] {
38+
pub mod riscv;
39+
pub use riscv::*;
40+
} else {
41+
```
42+
43+
## What Already Exists for RISC-V
44+
45+
### Documentation References
46+
47+
The Hubris documentation **already includes RISC-V specifications**:
48+
49+
#### 1. **Syscall Interface** (syscalls.adoc:74-76)
50+
```
51+
=== RISC-V
52+
53+
Syscalls are invoked using the `ECALL` instruction. The rest is TBD.
54+
```
55+
56+
#### 2. **Timer System** (timers.adoc:6)
57+
```
58+
silicon vendors -- the `SysTick` on ARM, the `mtimer` on RISC-V. Hubris provides
59+
a multiplexer for this timer, so that each task appears to have its own.
60+
```
61+
62+
#### 3. **Interrupt Handling** (interrupts.adoc:5-11)
63+
```
64+
Hubris port, but these ideas are intended to translate to RISC-V systems using
65+
controllers like the PLIC.
66+
```
67+
68+
### Architecture Requirements Already Defined
69+
70+
The documentation specifies what any architecture port needs:
71+
72+
1. **32-bit registers**: ✅ RISC-V32 matches
73+
2. **Supervisor call instruction**: ✅ `ECALL` equivalent to ARM's `SVC`
74+
3. **Memory protection**: ✅ RISC-V PMP equivalent to ARM MPU
75+
4. **Standard timer**: ✅ `mtimer` equivalent to ARM `SysTick`
76+
5. **Interrupt controller**: ✅ PLIC equivalent to ARM NVIC
77+
78+
## 🔧 Implementation Requirements (Minimal)
79+
80+
### Architecture Module (~2000 lines total)
81+
82+
Based on the existing ARM implementation (`sys/kern/src/arch/arm_m.rs` - 1901 lines):
83+
84+
| Component | Estimated Lines | Complexity | ARM Equivalent |
85+
|-----------|----------------|------------|----------------|
86+
| **Context switching** | ~300 | Medium | Save/restore `x1-x31` vs `r0-r15` |
87+
| **Syscall entry** | ~200 | Low | `ECALL` handler vs `SVC` handler |
88+
| **Timer integration** | ~100 | Low | `mtimer` vs `SysTick` |
89+
| **Memory protection** | ~200 | Medium | PMP setup vs MPU setup |
90+
| **Interrupt routing** | ~200 | Low | PLIC vs NVIC |
91+
| **Task state management** | ~500 | Medium | TCB save/restore |
92+
| **Boot sequence** | ~100 | Low | Reset handler |
93+
| **Utilities/macros** | ~300 | Low | Architecture helpers |
94+
| **Total** | **~1900** | **Low-Medium** | **Direct translation** |
95+
96+
### Register Mapping (Trivial)
97+
98+
**Current ARM Syscall Convention:**
99+
- Arguments: `r4` through `r10` (7 args)
100+
- Syscall number: `r11`
101+
- Returns: `r4` through `r11` (8 returns)
102+
103+
**Proposed RISC-V Convention:**
104+
- Arguments: `x10-x16` (`a0-a6`) (7 args)
105+
- Syscall number: `x17` (`a7`)
106+
- Returns: `x10-x17` (`a0-a7`) (8 returns)
107+
108+
### Core Functions to Implement
109+
110+
```rust
111+
// Required architecture interface (based on ARM module)
112+
pub fn apply_memory_protection(task: &Task) -> Result<(), FaultInfo>;
113+
pub fn start_task(task: &Task) -> !;
114+
pub fn save_task_state(task: &mut Task);
115+
pub fn restore_task_state(task: &Task);
116+
pub fn current_task_ptr() -> *const Task;
117+
pub fn set_current_task_ptr(task: *const Task);
118+
pub fn usermode_entry_point() -> u32;
119+
pub fn get_task_dump_area() -> &'static mut [u8];
120+
```
121+
122+
### ✅ What Makes Hubris Easy to Port
123+
124+
1. **🎯 Narrow target scope**: Only 32-bit microcontrollers
125+
2. **📦 Rust ecosystem**: RISC-V already well-supported
126+
3. **🔒 Memory safety**: Rust prevents most porting bugs
127+
4. **⚡ Simple execution model**: Privileged kernel, unprivileged tasks
128+
5. **🛡️ Minimal assembly**: Most code is portable Rust
129+
6. **📚 Clear documentation**: Architecture requirements already specified
130+

docs/src/design/os-selection.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Complex embedded systems require robust debugging and monitoring capabilities th
4848
| **System Composition** | **Static**: All tasks defined at compile-time in app.toml configuration, cannot be created/destroyed at runtime. Build system validates all configurations with static assertions. Supports in-place task reinitialization for fault recovery - supervisor task can restart crashed tasks without system reboot. Design philosophy prioritizes eliminating functionality not essential for server management and platform security, resulting in a smaller, more focused codebase to audit and validate. | **Dynamic**: Tasks can be dynamically loaded and assigned. Offers flexibility for diverse application scenarios and runtime adaptation. | Static model with compile-time validation prevents entire classes of runtime failures. In-place restart capability enables component-level recovery, avoiding system-wide reboots for isolated faults. Dynamic models provide flexibility for applications requiring runtime component loading or updates. |
4949
| **Communication** | **Strictly Synchronous**: IPC blocks sender until reply received. Uses rendezvous mechanism inspired by L4 microkernel - kernel performs direct memory copy between tasks, extending Rust's ownership model across task boundaries through leasing. | **Asynchronous**: Callback-based notifications for applications. | Synchronous communication eliminates race conditions, enables precise fault isolation (REPLY_FAULT at error point), and simplifies kernel design by avoiding complex message queue management. |
5050
| **Fault Isolation** | **Disjoint Protection Domains**: Drivers and kernel in separate, MPU-enforced memory spaces. Failing driver cannot corrupt kernel. | **Shared Protection Domain**: Drivers run in same domain as kernel but are partitioned by Rust's type system and capsule architecture. Capsules are kernel modules that rely on Rust's memory safety (borrowing rules, lifetime management) and trait-based interfaces for isolation rather than hardware memory protection. | Hardware-enforced isolation provides robust defense against faults. Memory-safe languages alone don't prevent all failures in critical systems. |
51-
| **Embedded CPU Architecture Support** | **ARM Cortex-M:** Official native support included.<br> **RISC-V** Designed with RISC-V in mind, but currently only has unnofficial support from outside developers including OpenPRoT partners. | **ARM Cortex-M:** Official native support included.<br> **RISC-V** Official native support included.<br> **x86 (32bit):** Official native support included. | |
51+
| **Embedded CPU Architecture Support** | **ARM Cortex-M:** Official native support included.<br> **RISC-V** Designed with RISC-V in mind, but currently only has unnofficial support from outside developers including OpenPRoT partners. | **ARM Cortex-M:** Official native support included.<br> **RISC-V** Official native support included.<br> **x86 (32bit):** Official native support included. | While native support is desireable, Hubris is relatively trivial to port to additional architectures for these reasons:<br><br> 1. **🎯 Narrow target scope**: Only 32-bit microcontrollers<br> 2. **📦 Rust ecosystem**: RISC-V already well-supported<br> 3. **🔒 Memory safety**: Rust prevents most porting bugs<br> 4. **⚡ Simple execution model**: Privileged kernel, unprivileged tasks<br> 5. **🛡️ Minimal assembly**: Most code is portable Rust<br> 6. **📚 Clear documentation**: Architecture requirements already specified<br><br> [More details](./hubris-riscv.md) |
5252
| **Licensing** | **Mozilla Public License Version 2.0**: Commercial use allowed, May be combined with proprietary code, Modified MPL files must be shared and remain MPL, Explicit patent grant included, Must retain copyright notices | **Apache License 2.0**: Commercial use allowed without restrictions, May be combined with proprietary code, Must state significant changes but not required to share, Explicit patent grant included, Must retain copyright notices | Both licenses allow for commercial use and mixing files with other licenses (including proprietary code). The primary difference is that any MPL licensed files must remain under the MPL license, and any changes to those files must be shared publicly. |
5353

5454
### Resource & Memory Management

0 commit comments

Comments
 (0)