[BROKEN] 32-bit x86 (i386) support by sulix · Pull Request #966 · Rust-for-Linux/linux (original) (raw)

I've made a few attempts to get Rust-for-Linux going under 32-bit x86, and have hit some crashes (I think with printk) that I haven't been able to resolve. (Interestingly, it seems to work on 32-bit UML, so that's interesting…)

This currently consists of two patches:

I've not yet added either CI support or updated the arch-support.rst documentation.

At the moment, it's crashing in rust_fmt_argument whenever printk is called from Rust:

BUG: kernel NULL pointer dereference, address: 00000414
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
*pde = 00000000
Oops: 0000 [#1] PREEMPT
CPU: 0 PID: 66 Comm: kunit_try_catch Tainted: G                 N 6.1.0-rc1-63059-gc5878a6654a6-dirty #15
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552-rebuilt.opensuse.org 04/01/2014
EIP: rust_fmt_argument+0x1e/0x70
Code: 90 90 90 90 90 90 90 90 90 90 90 90 55 89 e5 83 ec 28 8b 45 10 8b 4d 0c 8b 55 08 89 55 f0 89 55 f4 89 4d f8 8d 4d f0 89 4d fc <8b> 48 14 89 4d ec 8b 48 10 89 4d e8 8b 48 0c 89 4d e4 8b 48 08 89
EAX: 00000400 EBX: ffff0a00 ECX: c1097cd8 EDX: c1097dd7
ESI: df11a6ae EDI: c1097e6c EBP: c1097ce8 ESP: c1097cc0
DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068 EFLAGS: 00000086
CR0: 80050033 CR2: 00000414 CR3: 1f2ca000 CR4: 00000690
Call Trace:
 ? console_emit_next_record+0x5e/0x410
 pointer+0x4f9/0x6a0
 vsnprintf+0x25d/0x5f0
 ? sched_clock_cpu+0x17/0x290
 vprintk_store+0x125/0x3f0
 ? vprintk_default+0x10/0x20
 vprintk_emit+0x5c/0x1e0
 vprintk_default+0x10/0x20
 vprintk+0x49/0x50
 _printk+0x1f/0x37
 rust_begin_unwind+0x4b/0x70
 ? <&u8 as core[b62776744ad43b56]::fmt::Debug>::fmt+0x60/0x60
 core[b62776744ad43b56]::panicking::panic_fmt+0x2f/0x40
 core[b62776744ad43b56]::result::unwrap_failed+0x6c/0x80
 ? krealloc+0x116/0x200
 ? __switch_to_asm+0xca/0xf0
 ? <&&str as core[b62776744ad43b56]::fmt::Display>::fmt+0x20/0x20
 ? <&[u8; 4: usize] as core[b62776744ad43b56]::fmt::Debug>::fmt+0xd0/0xd0
 rust_kernel_doctest_kasync_executor_workqueue_rs_174_0+0x71c/0x740
 ? __switch_to_asm+0x34/0xf0
 ? __switch_to_asm+0x2e/0xf0
 ? __switch_to_asm+0x28/0xf0
 ? __switch_to_asm+0x22/0xf0
 ? __schedule+0x335/0x3c0
 kunit_try_run_case+0x37/0x90
 kunit_generic_run_threadfn_adapter+0x11/0x20
 kthread+0xa6/0xc0
 ? kunit_try_catch_run+0x130/0x130
 ? kthread_unuse_mm+0x60/0x60
 ret_from_fork+0x1c/0x28
CR2: 0000000000000414
---[ end trace 0000000000000000 ]---

(Out of curiosity, is there a reason rust_fmt_argument is not declared extern "C"? Doing so doesn't fix this issue, but since it's called by the C printk code when %pA appears, I'd've thought it needed to use a C ABI?)

In any case, that issue doesn't seem to show up under UML, and all of the doctest KUnit tests pass:
# rust_kernel_doctests: pass:92 fail:0 skip:0 total:92

I'm testing this with KUnit's tooling, using the following commands:
QEMU/i386:
./tools/testing/kunit/kunit.py run --arch i386 --make_options LLVM=1 --kconfig_add CONFIG_RUST=y
UML/i386:
./tools/testing/kunit/kunit.py run --make_options LLVM=1 --kconfig_add CONFIG_RUST=y --kconfig_add CONFIG_64BIT=n

If anyone has any ideas what could be causing these problems, I'd love to hear them!