Skip to content

Commit

Permalink
ldd ch06: calling wait_for_completion generating panic
Browse files Browse the repository at this point in the history
I guess completion is not initialized correctly.
The completion is initialized by Default trait.
What to do more?

/ # mknod /dev/rust_ldd06 c 10 124
/ # cat /dev/rust_ldd06
[   38.598297] rust_completion: open is invoked
[   38.598899] rust_completion: read is invoked
[   38.599419] rust_completion: read:dummy=1
[   38.599927] BUG: kernel NULL pointer dereference, address: 0000000000000000
[   38.600741] #PF: supervisor write access in kernel mode
[   38.601348] #PF: error_code(0x0002) - not-present page
[   38.601948] PGD 41ac067 P4D 41ac067 PUD 42a2067 PMD 0
[   38.602542] Oops: 0002 [#1] PREEMPT SMP NOPTI
[   38.602880] CPU: 0 PID: 123 Comm: cat Tainted: G            E      6.6.0-rc4+ Rust-for-Linux#75
[   38.602880] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
[   38.602880] RIP: 0010:wait_for_common+0xb5/0x170
[   38.602880] Code: f6 81 19 0c 00 00 01 75 70 48 89 4d c0 48 8b 45 c8 4c 39 f8 75 17 48 8b 46 18 4c 89 7e 18 48 8b 7d b0 2
[   38.602880] RSP: 0018:ffffc9000059bd70 EFLAGS: 00010046
[   38.602880] RAX: 0000000000000000 RBX: ffff88800433d148 RCX: ffff88800438e000
[   38.602880] RDX: 0000000000000002 RSI: ffff88800433d148 RDI: ffff88800433d158
[   38.602880] RBP: ffffc9000059bdc8 R08: 0000000000000000 R09: 0000000000000000
[   38.602880] R10: ffffc9000059bca8 R11: 3fffffffffffffff R12: 00007ffe6e0671b8
[   38.602880] R13: 7fffffffffffffff R14: 0000000000000002 R15: ffffc9000059bd90
[   38.602880] FS:  00000000020243c0(0000) GS:ffff888007a00000(0000) knlGS:0000000000000000
[   38.602880] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   38.602880] CR2: 0000000000000000 CR3: 00000000042e6000 CR4: 00000000000006f0
[   38.602880] Call Trace:
[   38.602880]  <TASK>
[   38.602880]  ? __die_body+0x6b/0xb0
[   38.602880]  ? __die+0x9b/0xb0
[   38.602880]  ? page_fault_oops+0x24c/0x370
[   38.602880]  ? prb_read_valid+0x19/0x20
[   38.602880]  ? printk_get_next_message+0x72/0x320
[   38.602880]  ? kernelmode_fixup_or_oops+0xd7/0x100
[   38.602880]  ? __bad_area_nosemaphore+0x69/0x290
[   38.602880]  ? bad_area_nosemaphore+0x16/0x20
[   38.602880]  ? do_user_addr_fault+0x55a/0x620
[   38.602880]  ? exc_page_fault+0x7c/0xf0
[   38.602880]  ? asm_exc_page_fault+0x27/0x30
[   38.602880]  ? wait_for_common+0xb5/0x170
[   38.602880]  wait_for_completion+0x1d/0x20
[   38.602880]  _RNvMs3_NtCshlmskAEPslc_6kernel4fileINtB5_16OperationsVtableINtNtB7_7miscdev12RegistrationNtCs2Jef7UYeN6f_1]
[   38.602880]  ? _RNvXs4_NtNtNtCsaTHfZRq6xTQ_4core3fmt3num3impxNtB9_7Display3fmt+0x30/0x30
[   38.602880]  vfs_read+0xb4/0x280
[   38.602880]  ? do_sendfile+0x1cd/0x470
[   38.602880]  ksys_read+0x5f/0xb0
[   38.602880]  __x64_sys_read+0x1b/0x20
[   38.602880]  do_syscall_64+0x35/0x50
[   38.602880]  entry_SYSCALL_64_after_hwframe+0x63/0xcd
[   38.602880] RIP: 0033:0x4ad272
[   38.602880] Code: 31 c0 e9 b1 fe ff ff 50 48 8d 3d c1 80 17 00 e8 54 8e 00 00 0f 1f 40 00 f3 0f 1e fa 64 8b 04 25 18 00 4
[   38.602880] RSP: 002b:00007ffe6e067158 EFLAGS: 00000246 ORIG_RAX: 0000000000000000
[   38.602880] RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00000000004ad272
[   38.602880] RDX: 0000000000001000 RSI: 00007ffe6e0671b8 RDI: 0000000000000003
[   38.602880] RBP: 00007ffe6e0671b8 R08: 0000000000000001 R09: 0000000000000000
[   38.602880] R10: 0000000001000000 R11: 0000000000000246 R12: 0000000000001000
[   38.602880] R13: 00000000020243a0 R14: 0000000000000000 R15: 0000000000000001
[   38.602880]  </TASK>
[   38.602880] Modules linked in: rust_ldd06(E)
[   38.602880] CR2: 0000000000000000
[   38.602880] ---[ end trace 0000000000000000 ]---
[   38.602880] RIP: 0010:wait_for_common+0xb5/0x170
[   38.602880] Code: f6 81 19 0c 00 00 01 75 70 48 89 4d c0 48 8b 45 c8 4c 39 f8 75 17 48 8b 46 18 4c 89 7e 18 48 8b 7d b0 2
[   38.602880] RSP: 0018:ffffc9000059bd70 EFLAGS: 00010046
[   38.602880] RAX: 0000000000000000 RBX: ffff88800433d148 RCX: ffff88800438e000
[   38.602880] RDX: 0000000000000002 RSI: ffff88800433d148 RDI: ffff88800433d158
[   38.602880] RBP: ffffc9000059bdc8 R08: 0000000000000000 R09: 0000000000000000
[   38.602880] R10: ffffc9000059bca8 R11: 3fffffffffffffff R12: 00007ffe6e0671b8
[   38.602880] R13: 7fffffffffffffff R14: 0000000000000002 R15: ffffc9000059bd90
[   38.602880] FS:  00000000020243c0(0000) GS:ffff888007a00000(0000) knlGS:0000000000000000
[   38.602880] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   38.602880] CR2: 0000000000000000 CR3: 00000000042e6000 CR4: 00000000000006f0
[   38.602880] note: cat[123] exited with irqs disabled
[   38.652903] note: cat[123] exited with preempt_count 1
[   38.653512] rust_completion: release is invoked

Signed-off-by: Gioh Kim <[email protected]>
  • Loading branch information
gurugio committed Oct 28, 2023
1 parent ae1271a commit f9655d7
Showing 1 changed file with 60 additions and 17 deletions.
77 changes: 60 additions & 17 deletions samples/rust/rust_ldd06.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@
//!
//! How to build only modules:
//! make LLVM=1 M=samples/rust
use core::marker::PhantomPinned;
//!
//! How to use:
//! / # insmod rust_ldd06.ko
//! / # mknod /dev/rust_ldd06 c 10 124
//! / # echo "hello" > /dev/rust_ldd06
//! / # cat /dev/rust_ldd06
use kernel::prelude::*;
use kernel::{
bindings,
file::{self, File},
fmt,
io_buffer::{IoBufferReader, IoBufferWriter},
miscdev, pin_init,
sync::{Arc, ArcBorrow},
types::Opaque,
miscdev, new_mutex, pin_init,
sync::{Arc, ArcBorrow, Mutex},
};

module! {
Expand All @@ -25,24 +29,40 @@ module! {
license: "GPL",
}

// Fist I made CompletionDev { completion: bindings::completion }.
// But it didn't work because we cannot get mutable reference to CompletionDev in read/write functions.
// The argument of read/write functions is ArcBorrow<'_, CompletionDev>.
// So it's not allowed to get the mutable reference to CompletionDev.
// The only way to mutate through ArcBorrow is to use Mutex/RwLock/Atomic types.
// (see doc.rust-lang.org/std/sync/struct.Mutex.html)
// Finally I makde CompletionInner struct and put it into Mutex.
struct CompletionInner {
completion: bindings::completion,
dummy: usize, // nothing but to check how to use Mutex
}

// internal info between file operations
#[pin_data]
struct CompletionDev {
pub completion: bindings::completion,

#[pin]
_pin: PhantomPinned,
inner: Mutex<CompletionInner>,
}

// TODO: impl CompletionDev::try_new
impl CompletionDev {
fn try_new() -> Result<Arc<Self>> {
pr_info!("completion_dev created\n");

Ok(Arc::try_new(Self {
_pin: PhantomPinned,
completion: bindings::completion::default(),
})?)
let dev = Arc::pin_init(pin_init!(Self {
completion: bindings::completion::default(), // Default trait is implmented by bindget. See rust/bindings/bindings_generates.rs
inner <- new_mutex!(CompletionInner {
completion: bindings::completion::default(),
dummy: 0,
}),
}))?;

Ok(dev)
}
}

Expand All @@ -66,29 +86,51 @@ impl file::Operations for RustFile {
fn read(
shared: ArcBorrow<'_, CompletionDev>,
_: &File,
data: &mut impl IoBufferWriter,
offset: u64,
_data: &mut impl IoBufferWriter,
_offset: u64,
) -> Result<usize> {
pr_info!("read is invoked\n");

let mut inner_guard = shared.inner.lock();
inner_guard.dummy += 1;
pr_info!("read:dummy={}\n", inner_guard.dummy);

unsafe {
bindings::wait_for_completion(&mut inner_guard.completion);
}

Ok(0)
}

fn write(
shared: ArcBorrow<'_, CompletionDev>,
_: &File,
data: &mut impl IoBufferReader,
offset: u64,
_offset: u64,
) -> Result<usize> {
pr_debug!("write is invoked\n");

let len: usize = data.len();
pr_info!("write: {} bytes\n", len);
Ok(len)
let mut inner_guard = shared.inner.lock();
pr_info!("write:dummy={}\n", inner_guard.dummy);
if inner_guard.dummy == 1 {
pr_info!("read() is waiting for completion\n");

unsafe {
bindings::complete(&mut inner_guard.completion);
}
} else if inner_guard.dummy == 0 {
pr_info!("read() is not waiting for completion\n");
} else {
pr_info!("Something went wrong\n");
}

// return non-zero value to avoid infinite re-try
Ok(data.len())
}

fn release(_data: Self::Data, _file: &File) {
fn release(data: Self::Data, _file: &File) {
pr_info!("release is invoked\n");
pr_info!("release:dummy={}\n", data.inner.lock().dummy);
}
}

Expand All @@ -101,6 +143,7 @@ impl kernel::Module for RustCompletion {
pr_info!("rust_ldd06 is loaded\n");

let dev: Arc<CompletionDev> = CompletionDev::try_new()?;

let reg = miscdev::Registration::new_pinned(fmt!("rust_ldd06"), dev)?;

Ok(RustCompletion { _dev: reg })
Expand Down

0 comments on commit f9655d7

Please sign in to comment.