Skip to content

Commit e47fac7

Browse files
committed
Add charp and some prim params
1 parent f823a22 commit e47fac7

File tree

10 files changed

+248
-34
lines changed

10 files changed

+248
-34
lines changed

.github/workflows/ci.yaml

+10-5
Original file line numberDiff line numberDiff line change
@@ -153,18 +153,23 @@ jobs:
153153
# Run
154154
- run: ${{ env.BUILD_DIR }}usr/gen_init_cpio .github/workflows/qemu-initramfs.desc > qemu-initramfs.img
155155

156-
- run: qemu-system-${{ env.QEMU_ARCH }} -kernel ${{ env.BUILD_DIR }}${{ env.IMAGE_PATH }} -initrd qemu-initramfs.img -M ${{ env.QEMU_MACHINE }} -cpu ${{ env.QEMU_CPU }} -smp 2 -nographic -no-reboot -append '${{ env.QEMU_APPEND }} rust_example.my_i32=123321 rust_example_2.my_i32=234432' | tee qemu-stdout.log
156+
- run: qemu-system-${{ env.QEMU_ARCH }} -kernel ${{ env.BUILD_DIR }}${{ env.IMAGE_PATH }} -initrd qemu-initramfs.img -M ${{ env.QEMU_MACHINE }} -cpu ${{ env.QEMU_CPU }} -smp 2 -nographic -no-reboot -append '${{ env.QEMU_APPEND }} rust_example.my_i32=123321 rust_example.my_str=🦀mod rust_example.my_invbool=y rust_example_2.my_i32=234432' | tee qemu-stdout.log
157157

158158
# Check
159159
- run: grep -F '] Rust Example (init)' qemu-stdout.log
160160
- run: grep -F '] [2] Rust Example (init)' qemu-stdout.log
161161
- run: grep -F '] [3] Rust Example (init)' qemu-stdout.log
162162
- run: grep -F '] [4] Rust Example (init)' qemu-stdout.log
163163

164-
- run: "grep -F '] my_i32: 123321' qemu-stdout.log"
165-
- run: "grep -F '] [2] my_i32: 234432' qemu-stdout.log"
166-
- run: "grep -F '] [3] my_i32: 345543' qemu-stdout.log"
167-
- run: "grep -F '] [4] my_i32: 456654' qemu-stdout.log"
164+
- run: "grep -F '] my_i32: 123321' qemu-stdout.log"
165+
- run: "grep -F '] [2] my_i32: 234432' qemu-stdout.log"
166+
- run: "grep -F '] [3] my_i32: 345543' qemu-stdout.log"
167+
- run: "grep -F '] [4] my_i32: 456654' qemu-stdout.log"
168+
169+
- run: "grep '\\] my_str: 🦀mod\\s*$' qemu-stdout.log"
170+
- run: "grep '\\] \\[2\\] my_str: default str val\\s*$' qemu-stdout.log"
171+
- run: "grep '\\] \\[3\\] my_str: 🦀mod\\s*$' qemu-stdout.log"
172+
- run: "grep '\\] \\[4\\] my_str: default str val\\s*$' qemu-stdout.log"
168173

169174
- run: grep -F '] [3] Rust Example (exit)' qemu-stdout.log
170175
- run: grep -F '] [4] Rust Example (exit)' qemu-stdout.log

.github/workflows/qemu-init.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/sh
22

3-
busybox insmod rust_example_3.ko my_i32=345543
3+
busybox insmod rust_example_3.ko my_i32=345543 my_str=🦀mod
44
busybox insmod rust_example_4.ko my_i32=456654
55
busybox rmmod rust_example_3.ko
66
busybox rmmod rust_example_4.ko

drivers/char/rust_example.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ module! {
2626
permissions: 0o644,
2727
description: b"Example of i32",
2828
},
29+
my_str: str {
30+
default: b"default str val",
31+
permissions: 0o644,
32+
description: b"Example of a string param",
33+
},
2934
},
3035
}
3136

@@ -49,9 +54,16 @@ impl KernelModule for RustExample {
4954
fn init() -> KernelResult<Self> {
5055
println!("Rust Example (init)");
5156
println!("Am I built-in? {}", !cfg!(MODULE));
52-
println!("Parameters:");
53-
println!(" my_bool: {}", my_bool.read());
54-
println!(" my_i32: {}", my_i32.read());
57+
{
58+
let lock = THIS_MODULE.kernel_param_lock();
59+
println!("Parameters:");
60+
println!(" my_bool: {}", my_bool.read());
61+
println!(" my_i32: {}", my_i32.read(&lock));
62+
println!(
63+
" my_str: {}",
64+
core::str::from_utf8(my_str.read(&lock))?
65+
);
66+
}
5567

5668
// Including this large variable on the stack will trigger
5769
// stack probing on the supported archs.

drivers/char/rust_example_2.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ module! {
2323
permissions: 0o644,
2424
description: b"Example of i32",
2525
},
26+
my_str: str {
27+
default: b"default str val",
28+
permissions: 0o644,
29+
description: b"Example of a string param",
30+
},
2631
},
2732
}
2833

@@ -34,9 +39,16 @@ impl KernelModule for RustExample2 {
3439
fn init() -> KernelResult<Self> {
3540
println!("[2] Rust Example (init)");
3641
println!("[2] Am I built-in? {}", !cfg!(MODULE));
37-
println!("[2] Parameters:");
38-
println!("[2] my_bool: {}", my_bool.read());
39-
println!("[2] my_i32: {}", my_i32.read());
42+
{
43+
let lock = THIS_MODULE.kernel_param_lock();
44+
println!("[2] Parameters:");
45+
println!("[2] my_bool: {}", my_bool.read());
46+
println!("[2] my_i32: {}", my_i32.read(&lock));
47+
println!(
48+
"[2] my_str: {}",
49+
core::str::from_utf8(my_str.read(&lock))?
50+
);
51+
}
4052

4153
// Including this large variable on the stack will trigger
4254
// stack probing on the supported archs.

drivers/char/rust_example_3.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ module! {
2323
permissions: 0o644,
2424
description: b"Example of i32",
2525
},
26+
my_str: str {
27+
default: b"default str val",
28+
permissions: 0o644,
29+
description: b"Example of a string param",
30+
},
2631
},
2732
}
2833

@@ -34,9 +39,16 @@ impl KernelModule for RustExample3 {
3439
fn init() -> KernelResult<Self> {
3540
println!("[3] Rust Example (init)");
3641
println!("[3] Am I built-in? {}", !cfg!(MODULE));
37-
println!("[3] Parameters:");
38-
println!("[3] my_bool: {}", my_bool.read());
39-
println!("[3] my_i32: {}", my_i32.read());
42+
{
43+
let lock = THIS_MODULE.kernel_param_lock();
44+
println!("[3] Parameters:");
45+
println!("[3] my_bool: {}", my_bool.read());
46+
println!("[3] my_i32: {}", my_i32.read(&lock));
47+
println!(
48+
"[3] my_str: {}",
49+
core::str::from_utf8(my_str.read(&lock))?
50+
);
51+
}
4052

4153
// Including this large variable on the stack will trigger
4254
// stack probing on the supported archs.

drivers/char/rust_example_4.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ module! {
2323
permissions: 0o644,
2424
description: b"Example of i32",
2525
},
26+
my_str: str {
27+
default: b"default str val",
28+
permissions: 0o644,
29+
description: b"Example of a string param",
30+
},
2631
},
2732
}
2833

@@ -34,9 +39,16 @@ impl KernelModule for RustExample4 {
3439
fn init() -> KernelResult<Self> {
3540
println!("[4] Rust Example (init)");
3641
println!("[4] Am I built-in? {}", !cfg!(MODULE));
37-
println!("[4] Parameters:");
38-
println!("[4] my_bool: {}", my_bool.read());
39-
println!("[4] my_i32: {}", my_i32.read());
42+
{
43+
let lock = THIS_MODULE.kernel_param_lock();
44+
println!("[4] Parameters:");
45+
println!("[4] my_bool: {}", my_bool.read());
46+
println!("[4] my_i32: {}", my_i32.read(&lock));
47+
println!(
48+
"[4] my_str: {}",
49+
core::str::from_utf8(my_str.read(&lock))?
50+
);
51+
}
4052

4153
// Including this large variable on the stack will trigger
4254
// stack probing on the supported archs.

rust/kernel/c_types.rs

+11
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,14 @@ mod c {
5151
}
5252

5353
pub use c::*;
54+
55+
/// Reads string until null byte is reached and returns slice excluding the terminating null.
56+
///
57+
/// SAFETY: The data from the pointer until the null terminator must be valid for reads and
58+
/// not mutated for all of `'a`. The length of the string must also be less than `isize::MAX`.
59+
/// See the documentation on [`from_raw_parts`](https://doc.rust-lang.org/core/slice/fn.from_raw_parts.html)
60+
/// for further details on safety of converting a pointer to a slice.
61+
pub unsafe fn c_string_bytes<'a>(ptr: *const crate::c_types::c_char) -> &'a [u8] {
62+
let length = crate::bindings::strlen(ptr) as usize;
63+
&core::slice::from_raw_parts(ptr as *const u8, length)
64+
}

rust/kernel/error.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0
22

33
use core::num::TryFromIntError;
4+
use core::str::Utf8Error;
45

56
use alloc::alloc::AllocError;
67

@@ -31,6 +32,12 @@ impl From<TryFromIntError> for Error {
3132
}
3233
}
3334

35+
impl From<Utf8Error> for Error {
36+
fn from(_: Utf8Error) -> Error {
37+
Error::EINVAL
38+
}
39+
}
40+
3441
pub type KernelResult<T> = Result<T, Error>;
3542

3643
impl From<AllocError> for Error {

rust/kernel/lib.rs

+24
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,30 @@ impl ThisModule {
5454
pub const unsafe fn from_ptr(ptr: *mut bindings::module) -> ThisModule {
5555
ThisModule(ptr)
5656
}
57+
58+
pub fn kernel_param_lock(&self) -> KParamGuard<'_> {
59+
// SAFETY: `kernel_param_lock` will check if the pointer is null and use the built-in mutex
60+
// in that case.
61+
#[cfg(CONFIG_SYSFS)]
62+
unsafe { bindings::kernel_param_lock(self.0) }
63+
64+
KParamGuard { this_module: self }
65+
}
66+
}
67+
68+
/// Scoped lock on the kernel parameters of `ThisModule`. Lock will be released
69+
/// when this struct is dropped.
70+
pub struct KParamGuard<'a> {
71+
this_module: &'a ThisModule
72+
}
73+
74+
#[cfg(CONFIG_SYSFS)]
75+
impl<'a> Drop for KParamGuard<'a> {
76+
fn drop(&mut self) {
77+
// SAFETY: `kernel_param_lock` will check if the pointer is null and use the built-in mutex
78+
// in that case. The existance of `self` guarantees that the lock is held.
79+
unsafe { bindings::kernel_param_unlock(self.this_module.0) }
80+
}
5781
}
5882

5983
extern "C" {

0 commit comments

Comments
 (0)