Skip to content

Commit a3b23da

Browse files
authored
aarch64: support runtime loading/linking of crates (theseus-os#940)
* Implemented all relocation types that appear in current aarch64 builds as well as the overflow checks for those relocation types. * Note that `loadable` mode fully works, but will hang due to a bug in the `multicore_bringup` logic on aarch64. If you modify the arm_board's QEMU configuration to use just a single CPU, that will bypass the bug and result in the system fully booting. * A PR to fix that is coming soon. * The following crates were modified to work on aarch64 loadable mode: * `panic_entry`, `panic_wrapper`: don't start unwinding, which isn't yet supported on aarch64. * `console`: undo arch-specific changes) * `first_application`: run a sample hello world app, as the full `shell` isn't yet supported on aarch64. * Split x86_64 and aarch64 relocations into separate functions. * Ensure `hull` is always built when the `console` is built, as the console directly spawns a new instance of it.
1 parent d91bb44 commit a3b23da

File tree

17 files changed

+440
-162
lines changed

17 files changed

+440
-162
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

applications/hello/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ authors = ["Kevin Boos <kevinaboos@gmail.com>"]
1010
version = "0.4.8"
1111

1212

13-
[dependencies.app_io]
14-
path = "../../kernel/app_io"
13+
# [dependencies.app_io]
14+
# path = "../../kernel/app_io"
1515

1616
# [dependencies.application_main_fn]
1717
# path = "../../compiler_plugins"

applications/hello/src/lib.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,11 @@
44

55

66
extern crate alloc;
7-
// #[macro_use] extern crate log;
8-
#[macro_use] extern crate app_io;
9-
10-
use alloc::vec::Vec;
11-
use alloc::string::String;
7+
// #[macro_use] extern crate app_io;
128

9+
use alloc::{string::String, vec::Vec};
1310

1411
pub fn main(_args: Vec<String>) -> isize {
15-
// info!("Hello, world! (from hello application)");
16-
println!("Hello, world! Args: {:?}", _args);
17-
12+
log::info!("Hello, world! Args: {:?}", _args);
1813
0
1914
}

cfg/aarch64-unknown-theseus.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
{
22
"abi": "softfloat",
33
"arch": "aarch64",
4+
"code-model": "large",
45
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
56
"disable-redzone": true,
7+
"executables": true,
68
"features": "+strict-align,-neon,-fp-armv8",
9+
"has-thread-local": true,
710
"linker": "rust-lld",
811
"linker-flavor": "ld.lld",
912
"llvm-target": "aarch64-unknown-none-elf",

kernel/captain/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ stack = { path = "../stack" }
2828
task = { path = "../task" }
2929
cpu = { path = "../cpu" }
3030
per_cpu = { path = "../per_cpu" }
31+
first_application = { path = "../first_application" }
3132

3233
[target.'cfg(target_arch = "x86_64")'.dependencies]
3334
window_manager = { path = "../window_manager" }
34-
first_application = { path = "../first_application" }
3535
exceptions_full = { path = "../exceptions_full" }
3636
multiple_heaps = { path = "../multiple_heaps" }
3737
tsc = { path = "../tsc" }

kernel/captain/src/lib.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,6 @@ pub fn init(
206206
console::start_connection_detection()?;
207207

208208
// 3. Start the first application(s).
209-
// arch-gate: many subsystems required by applications are missing
210-
// on aarch64: windowing, user input, app loading (relocation code
211-
// is x86_64-specific at the moment)
212-
#[cfg(target_arch = "x86_64")]
213209
first_application::start()?;
214210

215211
info!("captain::init(): initialization done! Spawning an idle task on BSP core {} and enabling interrupts...", bsp_id);

kernel/console/Cargo.toml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,21 @@ log = "0.4.8"
1010
irq_safety = { git = "https://github.com/theseus-os/irq_safety" }
1111
core2 = { version = "0.4.0", default-features = false, features = ["alloc", "nightly"] }
1212

13+
app_io = { path = "../app_io" }
1314
async_channel = { path = "../async_channel" }
15+
io = { path = "../io" }
16+
mod_mgmt = { path = "../mod_mgmt" }
17+
path = { path = "../path" }
1418
serial_port = { path = "../serial_port" }
15-
app_io = { path = "../app_io" }
1619
spawn = { path = "../spawn" }
1720
task = { path = "../task" }
1821
tty = { path = "../tty" }
19-
io = { path = "../io" }
2022

21-
[target.'cfg(target_arch = "x86_64")'.dependencies]
22-
path = { path = "../path" }
23-
mod_mgmt = { path = "../mod_mgmt" }
24-
25-
[target.'cfg(target_arch = "aarch64")'.dependencies]
23+
## In general, Theseus kernel crates *cannot* depend on application crates.
24+
## However, this crate loads and runs the `hull` shell application,
25+
## so it's best to ensure that the `hull` crate is always included in the build
26+
## by specifying it as a direct dependency here.
27+
##
28+
## Note that this does NOT result in a direct runtime dependency
29+
## from this crate to the `hull` crate; it merely guarantees it gets built.
2630
hull = { path = "../../applications/hull" }
27-
28-
[lib]
29-
crate-type = ["rlib"]

kernel/console/src/lib.rs

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -110,26 +110,17 @@ fn shell_loop(
110110
.spawn()?;
111111

112112

113-
let task;
114-
#[cfg(target_arch = "x86_64")] {
115-
let new_app_ns = mod_mgmt::create_application_namespace(None)?;
116-
117-
let (app_file, _ns) =
118-
mod_mgmt::CrateNamespace::get_crate_object_file_starting_with(&new_app_ns, "hull-")
119-
.expect("Couldn't find shell in default app namespace");
120-
121-
let path = path::Path::new(app_file.lock().get_absolute_path());
122-
task = spawn::new_application_task_builder(path, Some(new_app_ns))?
123-
.name(format!("{address:?}_shell"))
124-
.block()
125-
.spawn()?;
126-
}
127-
#[cfg(target_arch = "aarch64")] {
128-
task = spawn::new_task_builder(hull::main, alloc::vec::Vec::new())
129-
.name(alloc::format!("{address:?}_shell"))
130-
.block()
131-
.spawn()?;
132-
}
113+
let new_app_ns = mod_mgmt::create_application_namespace(None)?;
114+
115+
let (app_file, _ns) =
116+
mod_mgmt::CrateNamespace::get_crate_object_file_starting_with(&new_app_ns, "hull-")
117+
.expect("Couldn't find hull in default app namespace");
118+
119+
let path = path::Path::new(app_file.lock().get_absolute_path());
120+
let task = spawn::new_application_task_builder(path, Some(new_app_ns))?
121+
.name(format!("{address:?}_hull"))
122+
.block()
123+
.spawn()?;
133124

134125
let id = task.id;
135126
let stream = Arc::new(tty.slave());
@@ -143,7 +134,7 @@ fn shell_loop(
143134
},
144135
);
145136

146-
task.unblock().map_err(|_| "couldn't unblock shell task")?;
137+
task.unblock().map_err(|_| "couldn't unblock hull task")?;
147138
task.join()?;
148139

149140
reader_task.kill(KillReason::Requested).unwrap();

0 commit comments

Comments
 (0)