Skip to content

Commit 0ff21ea

Browse files
committed
arch: add mips32 support
1 parent 8db5827 commit 0ff21ea

4 files changed

Lines changed: 258 additions & 10 deletions

File tree

.github/workflows/rust.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ jobs:
5252
# powerpc uses experimental asm features
5353
- target: powerpc-unknown-linux-gnu
5454
toolchain: nightly
55+
# mips is tier-3 and uses experimental asm features
56+
- target: mips-unknown-linux-gnu
57+
toolchain: nightly
58+
components: rust-src
59+
build_std: true
5560

5661
steps:
5762
- name: "Checkout"
@@ -77,7 +82,7 @@ jobs:
7782
target: ${{ matrix.target }}
7883

7984
- name: "Build"
80-
run: cargo build --verbose --target ${{ matrix.target }} ${{ matrix.build_std && '-Z build-std=core,alloc,panic_abort' || '' }}
85+
run: cargo build --verbose --target ${{ matrix.target }} ${{ matrix.build_std && '-Z build-std=core,alloc,panic_abort' || '' }} ${{ matrix.extra_args || '' }}
8186

8287
# tier-3 targets have no prebuilt std and tests are arch-agnostic, so
8388
# run them against the host toolchain instead of the cross target.

crates/asm/src/lib.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//!
88
//! Supports `x86_64`, `aarch64`, `riscv64`, `loongarch64`, `s390x`,
99
//! `powerpc64`, `arm` (armv7), `riscv32`, `sparc64`, `mips64`, `x86` (i686),
10-
//! `powerpc` (ppc32), and `sparc` (sparc32) architectures.
10+
//! `powerpc` (ppc32), `sparc` (sparc32), and `mips` (O32) architectures.
1111
1212
#![no_std]
1313
#![cfg_attr(
@@ -16,7 +16,8 @@
1616
target_arch = "powerpc",
1717
target_arch = "sparc64",
1818
target_arch = "sparc",
19-
target_arch = "mips64"
19+
target_arch = "mips64",
20+
target_arch = "mips"
2021
),
2122
feature(asm_experimental_arch)
2223
)]
@@ -35,12 +36,13 @@
3536
target_arch = "mips64",
3637
target_arch = "x86",
3738
target_arch = "powerpc",
38-
target_arch = "sparc"
39+
target_arch = "sparc",
40+
target_arch = "mips"
3941
)))]
4042
compile_error!(
4143
"Unsupported architecture: only x86_64, aarch64, riscv64, loongarch64, \
42-
s390x, powerpc64, arm, riscv32, sparc64, mips64, x86, powerpc, and sparc \
43-
are supported"
44+
s390x, powerpc64, arm, riscv32, sparc64, mips64, x86, powerpc, sparc, and \
45+
mips are supported"
4446
);
4547

4648
// Per-arch syscall implementations live in their own module files.
@@ -83,6 +85,9 @@ mod arch;
8385
#[cfg(target_arch = "sparc")]
8486
#[path = "sparc.rs"]
8587
mod arch;
88+
#[cfg(target_arch = "mips")]
89+
#[path = "mips.rs"]
90+
mod arch;
8691

8792
/// Copies `n` bytes from `src` to `dest`.
8893
///
@@ -323,7 +328,8 @@ pub unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
323328
target_arch = "x86",
324329
target_arch = "powerpc",
325330
target_arch = "sparc",
326-
target_arch = "mips64"
331+
target_arch = "mips64",
332+
target_arch = "mips"
327333
)))]
328334
pub struct StatfsBuf {
329335
pub f_type: i64,
@@ -389,6 +395,28 @@ pub struct StatfsBuf {
389395
pub _pad: [u32; 4],
390396
}
391397

398+
/// mips (O32) uses `compat_statfs64`, same reordering with 32-bit words; see
399+
/// https://github.com/torvalds/linux/blob/v6.19/arch/mips/include/uapi/asm/statfs.h
400+
#[repr(C)]
401+
#[cfg(target_arch = "mips")]
402+
pub struct StatfsBuf {
403+
pub f_type: u32,
404+
pub f_bsize: u32,
405+
pub f_frsize: u32,
406+
_pad: u32,
407+
pub f_blocks: u64,
408+
pub f_bfree: u64,
409+
pub f_files: u64,
410+
pub f_ffree: u64,
411+
pub f_bavail: u64,
412+
pub f_fsid: [i32; 2],
413+
pub f_namelen: u32,
414+
pub f_flags: u32,
415+
416+
#[allow(clippy::pub_underscore_fields, reason = "This is not a public API")]
417+
pub _pad2: [u32; 5],
418+
}
419+
392420
/// mips reorders fields; see
393421
/// https://github.com/torvalds/linux/blob/v6.19/arch/mips/include/uapi/asm/statfs.h
394422
#[repr(C)]
@@ -484,7 +512,8 @@ pub fn read_file_fast(path: &str, buffer: &mut [u8]) -> Result<usize, i32> {
484512
target_arch = "riscv32",
485513
target_arch = "x86",
486514
target_arch = "powerpc",
487-
target_arch = "sparc"
515+
target_arch = "sparc",
516+
target_arch = "mips"
488517
)))]
489518
pub struct SysInfo {
490519
pub uptime: i64,
@@ -514,7 +543,8 @@ pub struct SysInfo {
514543
target_arch = "riscv32",
515544
target_arch = "x86",
516545
target_arch = "powerpc",
517-
target_arch = "sparc"
546+
target_arch = "sparc",
547+
target_arch = "mips"
518548
))]
519549
pub struct SysInfo {
520550
pub uptime: i32,

crates/asm/src/mips.rs

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
//! Syscall implementations for `mips`.
2+
3+
use super::{StatfsBuf, SysInfo, UtsNameBuf};
4+
5+
pub(super) unsafe fn sys_open(path: *const u8, flags: i32) -> i32 {
6+
unsafe {
7+
let ret: i32;
8+
core::arch::asm!(
9+
"syscall",
10+
"beqz $7, 1f",
11+
"nop",
12+
"subu $2, $0, $2",
13+
"1:",
14+
inlateout("$2") 4000i32 + 5 => ret, // SYS_open
15+
in("$4") path,
16+
in("$5") flags,
17+
in("$6") 0i32, // mode
18+
lateout("$7") _,
19+
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
20+
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
21+
lateout("$24") _, lateout("$25") _,
22+
options(nostack)
23+
);
24+
ret
25+
}
26+
}
27+
28+
pub(super) unsafe fn sys_read(fd: i32, buf: *mut u8, count: usize) -> isize {
29+
unsafe {
30+
let ret: i32;
31+
core::arch::asm!(
32+
"syscall",
33+
"beqz $7, 1f",
34+
"nop",
35+
"subu $2, $0, $2",
36+
"1:",
37+
inlateout("$2") 4000i32 + 3 => ret, // SYS_read
38+
in("$4") fd,
39+
in("$5") buf,
40+
in("$6") count,
41+
lateout("$7") _,
42+
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
43+
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
44+
lateout("$24") _, lateout("$25") _,
45+
options(nostack)
46+
);
47+
ret as isize
48+
}
49+
}
50+
51+
pub(super) unsafe fn sys_write(fd: i32, buf: *const u8, count: usize) -> isize {
52+
unsafe {
53+
let ret: i32;
54+
core::arch::asm!(
55+
"syscall",
56+
"beqz $7, 1f",
57+
"nop",
58+
"subu $2, $0, $2",
59+
"1:",
60+
inlateout("$2") 4000i32 + 4 => ret, // SYS_write
61+
in("$4") fd,
62+
in("$5") buf,
63+
in("$6") count,
64+
lateout("$7") _,
65+
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
66+
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
67+
lateout("$24") _, lateout("$25") _,
68+
options(nostack)
69+
);
70+
ret as isize
71+
}
72+
}
73+
74+
pub(super) unsafe fn sys_close(fd: i32) -> i32 {
75+
unsafe {
76+
let ret: i32;
77+
core::arch::asm!(
78+
"syscall",
79+
"beqz $7, 1f",
80+
"nop",
81+
"subu $2, $0, $2",
82+
"1:",
83+
inlateout("$2") 4000i32 + 6 => ret, // SYS_close
84+
in("$4") fd,
85+
lateout("$7") _,
86+
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
87+
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
88+
lateout("$24") _, lateout("$25") _,
89+
options(nostack)
90+
);
91+
ret
92+
}
93+
}
94+
95+
pub(super) unsafe fn sys_uname(buf: *mut UtsNameBuf) -> i32 {
96+
unsafe {
97+
let ret: i32;
98+
core::arch::asm!(
99+
"syscall",
100+
"beqz $7, 1f",
101+
"nop",
102+
"subu $2, $0, $2",
103+
"1:",
104+
inlateout("$2") 4000i32 + 122 => ret, // SYS_newuname
105+
in("$4") buf,
106+
lateout("$7") _,
107+
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
108+
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
109+
lateout("$24") _, lateout("$25") _,
110+
options(nostack)
111+
);
112+
ret
113+
}
114+
}
115+
116+
pub(super) unsafe fn sys_statfs(path: *const u8, buf: *mut StatfsBuf) -> i32 {
117+
unsafe {
118+
let ret: i32;
119+
core::arch::asm!(
120+
"syscall",
121+
"beqz $7, 1f",
122+
"nop",
123+
"subu $2, $0, $2",
124+
"1:",
125+
inlateout("$2") 4000i32 + 255 => ret, // SYS_statfs64
126+
in("$4") path,
127+
in("$5") core::mem::size_of::<StatfsBuf>(),
128+
in("$6") buf,
129+
lateout("$7") _,
130+
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
131+
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
132+
lateout("$24") _, lateout("$25") _,
133+
options(nostack)
134+
);
135+
ret
136+
}
137+
}
138+
139+
pub(super) unsafe fn sys_sysinfo(info: *mut SysInfo) -> i64 {
140+
unsafe {
141+
let ret: i32;
142+
core::arch::asm!(
143+
"syscall",
144+
"beqz $7, 1f",
145+
"nop",
146+
"subu $2, $0, $2",
147+
"1:",
148+
inlateout("$2") 4000_i32 + 116 => ret, // __NR_sysinfo
149+
in("$4") info,
150+
lateout("$7") _,
151+
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
152+
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
153+
lateout("$24") _, lateout("$25") _,
154+
options(nostack)
155+
);
156+
i64::from(ret)
157+
}
158+
}
159+
160+
pub(super) unsafe fn sys_sched_getaffinity(
161+
pid: i32,
162+
mask_size: usize,
163+
mask: *mut u8,
164+
) -> i32 {
165+
unsafe {
166+
let ret: i32;
167+
core::arch::asm!(
168+
"syscall",
169+
"beqz $7, 1f",
170+
"nop",
171+
"subu $2, $0, $2",
172+
"1:",
173+
inlateout("$2") 4000i32 + 240 => ret, // __NR_sched_getaffinity
174+
in("$4") pid,
175+
in("$5") mask_size,
176+
in("$6") mask,
177+
lateout("$7") _,
178+
lateout("$8") _, lateout("$9") _, lateout("$10") _, lateout("$11") _,
179+
lateout("$12") _, lateout("$13") _, lateout("$14") _, lateout("$15") _,
180+
lateout("$24") _, lateout("$25") _,
181+
options(nostack)
182+
);
183+
ret
184+
}
185+
}
186+
187+
pub(super) unsafe fn sys_exit(code: i32) -> ! {
188+
unsafe {
189+
core::arch::asm!(
190+
"syscall",
191+
in("$2") 4000i32 + 1, // SYS_exit
192+
in("$4") code,
193+
options(noreturn, nostack)
194+
);
195+
}
196+
}

microfetch/src/main.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
target_arch = "powerpc",
77
target_arch = "sparc64",
88
target_arch = "sparc",
9-
target_arch = "mips64"
9+
target_arch = "mips64",
10+
target_arch = "mips"
1011
),
1112
feature(asm_experimental_arch)
1213
)]
@@ -280,6 +281,22 @@ extern "C" fn __atomic_store_1(ptr: *mut u8, val: u8, _order: i32) {
280281
unsafe { core::ptr::write_volatile(ptr, val) }
281282
}
282283

284+
#[cfg(target_arch = "mips")]
285+
#[unsafe(no_mangle)]
286+
#[unsafe(naked)]
287+
unsafe extern "C" fn _start() {
288+
naked_asm!(
289+
"move $a0, $sp", // first arg = original sp (argc/argv)
290+
"addiu $sp, $sp, -24", // reserve 16-byte O32 shadow space + align
291+
"jal {entry_rust}",
292+
"nop", // delay slot
293+
"move $a0, $v0", // exit code = entry_rust return value
294+
"li $v0, 4001", // SYS_exit (4000 + 1)
295+
"syscall",
296+
entry_rust = sym entry_rust,
297+
);
298+
}
299+
283300
// Global allocator
284301
#[global_allocator]
285302
static ALLOCATOR: BumpAllocator = BumpAllocator::new();

0 commit comments

Comments
 (0)