diff --git a/.gitignore b/.gitignore index ed6dc25c..b45e9406 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,9 @@ alien-* alien.bin rust -subsystems +tests/testsuits-for-oskernel -tests/testsuits-for-oskernel \ No newline at end of file +#subsystems/devices +#subsystems/drivers +#subsystems/vfs +#subsystems/timer \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 7f256a51..44607fa7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,6 +64,13 @@ dependencies = [ "nom 4.2.3", ] +[[package]] +name = "arch" +version = "0.1.0" +dependencies = [ + "riscv", +] + [[package]] name = "arrayref" version = "0.3.7" @@ -94,15 +101,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "atomic-polyfill" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" -dependencies = [ - "critical-section", -] - [[package]] name = "atomic-polyfill" version = "1.0.3" @@ -142,13 +140,6 @@ version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" -[[package]] -name = "basemachine" -version = "0.1.0" -dependencies = [ - "fdt", -] - [[package]] name = "bit-struct" version = "0.3.2" @@ -202,17 +193,6 @@ dependencies = [ "objc2-encode", ] -[[package]] -name = "boot" -version = "0.1.0" -dependencies = [ - "basemachine", - "cfg-if", - "kernel", - "preprint", - "riscv", -] - [[package]] name = "buddy_system_allocator" version = "0.9.0" @@ -379,6 +359,10 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "config" +version = "0.1.0" + [[package]] name = "const-field-offset" version = "0.1.3" @@ -400,6 +384,13 @@ dependencies = [ "syn 2.0.37", ] +[[package]] +name = "constants" +version = "0.1.0" +dependencies = [ + "pconst", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -638,6 +629,34 @@ dependencies = [ "vfscore", ] +[[package]] +name = "device_interface" +version = "0.1.0" +dependencies = [ + "constants", +] + +[[package]] +name = "devices" +version = "0.1.0" +dependencies = [ + "arch", + "config", + "constants", + "device_interface", + "drivers", + "fdt", + "interrupt", + "ksync", + "log", + "netcore", + "platform", + "smoltcp", + "spin", + "vfscore", + "virtio-drivers 0.5.0 (git+https://github.com/rcore-os/virtio-drivers?rev=de1c3b1)", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -668,6 +687,31 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +[[package]] +name = "drivers" +version = "0.1.0" +dependencies = [ + "config", + "constants", + "device_interface", + "downcast-rs", + "ksync", + "log", + "loopback", + "lru", + "mem", + "netcore", + "platform", + "rtc", + "spin", + "timer", + "uart16550", + "uart8250", + "virtio-drivers 0.5.0 (git+https://github.com/rcore-os/virtio-drivers?rev=de1c3b1)", + "virtio-net", + "visionfive2-sd", +] + [[package]] name = "drm" version = "0.9.0" @@ -852,9 +896,8 @@ dependencies = [ [[package]] name = "fdt" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67" +version = "0.2.0-alpha1" +source = "git+https://github.com/repnop/fdt#6fc87b53da0b46166f7bc5029982568e344cc338" [[package]] name = "field-offset" @@ -1111,11 +1154,11 @@ dependencies = [ [[package]] name = "heapless" -version = "0.7.16" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" dependencies = [ - "atomic-polyfill 0.1.11", + "atomic-polyfill", "hash32 0.2.1", "rustc_version", "spin", @@ -1354,6 +1397,19 @@ dependencies = [ "num-traits", ] +[[package]] +name = "interrupt" +version = "0.1.0" +dependencies = [ + "arch", + "config", + "device_interface", + "ksync", + "platform", + "plic", + "spin", +] + [[package]] name = "inventory" version = "0.3.12" @@ -1416,43 +1472,30 @@ dependencies = [ name = "kernel" version = "0.1.0" dependencies = [ - "basemachine", + "arch", "bit_field", "bitflags 1.3.2", - "buddy_system_allocator", - "cfg-if", - "devfs", - "downcast-rs", - "dynfs", - "fat-vfs", - "fdt", + "config", + "constants", + "devices", + "drivers", "gmanager", - "kernel-sync", + "interrupt", + "knet", + "ksync", "log", - "loopback", - "lru", + "mem", "netcore", "page-table", - "pager", - "pconst", - "plic", - "preprint", - "ramfs", + "platform", "riscv", - "rslab", - "rtc", - "smoltcp", "smpscheduler", "spin", "syscall-table", - "talc 1.0.0", - "tracer", - "uart16550", - "uart8250", + "timer", + "unwinder", + "vfs", "vfscore", - "virtio-drivers 0.5.0 (git+https://github.com/rcore-os/virtio-drivers?rev=de1c3b1)", - "virtio-net", - "visionfive2-sd", "xmas-elf", ] @@ -1465,6 +1508,27 @@ dependencies = [ "lock_api", ] +[[package]] +name = "knet" +version = "0.1.0" +dependencies = [ + "constants", + "ksync", + "log", + "netcore", + "vfs", + "vfscore", +] + +[[package]] +name = "ksync" +version = "0.1.0" +dependencies = [ + "arch", + "config", + "kernel-sync", +] + [[package]] name = "kurbo" version = "0.9.5" @@ -1639,6 +1703,23 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" +[[package]] +name = "mem" +version = "0.1.0" +dependencies = [ + "arch", + "buddy_system_allocator", + "config", + "ksync", + "log", + "page-table", + "pager", + "platform", + "rslab", + "spin", + "talc 1.0.0", +] + [[package]] name = "memchr" version = "2.3.4" @@ -1983,7 +2064,7 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" dependencies = [ - "atomic-polyfill 1.0.3", + "atomic-polyfill", "critical-section", ] @@ -2094,6 +2175,19 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "platform" +version = "0.1.0" +dependencies = [ + "arch", + "config", + "fdt", + "ksync", + "log", + "preprint", + "spin", +] + [[package]] name = "plic" version = "0.1.0" @@ -2623,7 +2717,7 @@ dependencies = [ "byteorder", "cfg-if", "defmt", - "heapless 0.7.16", + "heapless 0.7.17", "log", "managed", ] @@ -2895,6 +2989,17 @@ dependencies = [ "time-core", ] +[[package]] +name = "timer" +version = "0.1.0" +dependencies = [ + "arch", + "config", + "constants", + "platform", + "vfscore", +] + [[package]] name = "tiny-skia" version = "0.10.0" @@ -3132,6 +3237,15 @@ dependencies = [ "vfscore", ] +[[package]] +name = "unwinder" +version = "0.1.0" +dependencies = [ + "arch", + "platform", + "tracer", +] + [[package]] name = "url" version = "2.4.1" @@ -3222,6 +3336,26 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "vfs" +version = "0.1.0" +dependencies = [ + "arch", + "constants", + "devfs", + "devices", + "downcast-rs", + "dynfs", + "fat-vfs", + "interrupt", + "ksync", + "log", + "platform", + "ramfs", + "spin", + "vfscore", +] + [[package]] name = "vfscore" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 46501212..40d769f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,7 @@ resolver = "2" members = [ "kernel", "userlib", - "boot", - "dep/gmanager", - "dep/basemachine", + "subsystems/gmanager", "apps/slint-helper", "apps/cat", "apps/sleep", @@ -26,9 +24,27 @@ members = [ "apps/memory-game", "apps/print", "apps/final_test", -] + "subsystems/arch", + "subsystems/config", + "subsystems/ksync", + "subsystems/constants", + "subsystems/mem", + "subsystems/vfs", + "subsystems/devices", + "subsystems/drivers", + "subsystems/interrupt", + "subsystems/device_interface", + "subsystems/timer", + "kernel", + "subsystems/unwinder", + "subsystems/knet",] [profile.release] #lto = true #codegen-units = 1 + + + +[workspace.dependencies] +spin = "0" diff --git a/Makefile b/Makefile index a573294f..4d6793a3 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ TRACE_EXE := trace_exe TARGET := riscv64gc-unknown-none-elf -OUTPUT := target/$(TARGET)/release/ -KERNEL_FILE := $(OUTPUT)/boot +OUTPUT := target/$(TARGET)/release +KERNEL_FILE := $(OUTPUT)/kernel DEBUG_FILE ?= $(KERNEL_FILE) KERNEL_ENTRY_PA := 0x80200000 OBJDUMP := rust-objdump --arch-name=riscv64 @@ -41,9 +41,9 @@ endif ifeq ($(VF2),y) -FEATURES += vf2 ramfs +FEATURES += vf2 else ifeq ($(UNMATCHED),y) -FEATURES += hifive ramfs +FEATURES += hifive ramdisk else FEATURES += qemu endif @@ -76,7 +76,7 @@ define boot_qemu -serial mon:stdio endef -all:run +all: install: ifeq (, $(shell which $(TRACE_EXE))) @@ -86,25 +86,23 @@ else endif -build:install compile - +build:install compile compile: - cargo build --release -p boot --target $(TARGET) --features $(FEATURES) - @(nm -n ${KERNEL_FILE} | $(TRACE_EXE) > kernel/src/trace/kernel_symbol.S) + cargo build --release -p kernel --target $(TARGET) --features $(FEATURES) + (nm -n ${KERNEL_FILE} | $(TRACE_EXE) > subsystems/unwinder/src/kernel_symbol.S) @#call trace_info - cargo build --release -p boot --target $(TARGET) --features $(FEATURES) + cargo build --release -p kernel --target $(TARGET) --features $(FEATURES) @#$(OBJCOPY) $(KERNEL_FILE) --strip-all -O binary $(KERNEL_BIN) - @cp $(KERNEL_FILE) ./kernel-qemu + cp $(KERNEL_FILE) ./kernel-qemu trace_info: @(nm -n ${KERNEL_FILE} | $(TRACE_EXE) > kernel/src/trace/kernel_symbol.S) -sdcard:fat32 - @if [ -d "tests/testbin-second-stage" ]; then \ - sudo cp tests/testbin-second-stage/* /fat -r; \ - fi - @make -C apps +user: + @cd apps && make all + +sdcard:fat32 testelf user @sudo umount /fat run:sdcard install compile @@ -122,26 +120,21 @@ board:install compile @cp $(OUTPUT)/testos.bin /home/godones/projects/tftpboot/ @cp $(OUTPUT)/testos.bin ./alien.bin -qemu:install compile +qemu: + @rust-objcopy --strip-all $(OUTPUT)/boot -O binary $(OUTPUT)/testos.bin + @cp $(OUTPUT)/testos.bin /home/godones/projects/tftpboot/ + @cp $(OUTPUT)/testos.bin ./alien.bin vf2:board @mkimage -f ./tools/vf2.its ./alien-vf2.itb @rm ./kernel-qemu @cp ./alien-vf2.itb /home/godones/projects/tftpboot/ - @rm ./alien-vf2.itb -cv1811h:board - @mkimage -f ./tools/cv1811h.its ./alien-cv1811h.itb - @rm ./kernel-qemu - @cp ./alien-cv1811h.itb /home/godones/projects/tftpboot/ - @rm ./alien-cv1811h.itb - unmatched:board @mkimage -f ./tools/fu740.its ./alien-unmatched.itb @rm ./kernel-qemu @cp ./alien-unmatched.itb /home/godones/projects/tftpboot/ - @rm ./alien-unmatched.itb f_test: qemu-system-riscv64 \ @@ -154,6 +147,10 @@ f_test: -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 \ -device virtio-net-device,netdev=net -netdev user,id=net +testelf: + @if [ -d "tests/testbin-second-stage" ]; then \ + sudo cp tests/testbin-second-stage/* /fat -r; \ + fi dtb: $(call boot_qemu, -machine dumpdtb=riscv.dtb) @@ -168,7 +165,9 @@ SecondFile: #创建64MB大小空白文件 @dd if=/dev/zero of=$(IMG1) bs=1M count=64 - +ZeroFile: + #创建空白文件 + @dd if=/dev/zero of=$(IMG) bs=1M count=64 fat32: @-touch $(IMG) @@ -208,13 +207,12 @@ kernel_asm: @vim kernel.asm @rm kernel.asm - docs: cargo doc --open -p kernel --target riscv64gc-unknown-none-elf --features $(FEATURES) clean: @cargo clean - @rm kernel-qemu - @rm alien-* + @-rm kernel-qemu + @-rm alien-* check: diff --git a/boot/Cargo.toml b/boot/Cargo.toml deleted file mode 100644 index e6433c44..00000000 --- a/boot/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "boot" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -cfg-if = "1.0.0" -riscv = "0.10.0" -preprint = "0.1.0" -basemachine = { path = "../dep/basemachine" } -kernel = { version = "0.1.0", path = "../kernel" } - - -[features] -default = [] -vf2 = ["kernel/vf2"] -qemu = ["kernel/qemu"] -hifive = ["kernel/hifive"] - -slab = ["kernel/slab"] -talloc = ["kernel/talloc"] -buddy = ["kernel/buddy"] - -ramfs= ["kernel/ramfs"] - diff --git a/boot/build.rs b/boot/build.rs deleted file mode 100644 index 63c386fe..00000000 --- a/boot/build.rs +++ /dev/null @@ -1,32 +0,0 @@ -use std::fs::File; -use std::io::Write; -use std::path::Path; -use std::{env, fs}; - -fn main() { - // 指定target - let outdir = env::var("OUT_DIR").unwrap(); - let link_script = Path::new(&outdir).join("link.lds"); - let mut script = File::create(&link_script).unwrap(); - - let ld_path = Path::new("../tools/link.ld"); - let ld = fs::read_to_string(ld_path).unwrap(); - - #[cfg(not(feature = "vf2"))] - let base_addr = 0x80200000usize; - #[cfg(feature = "vf2")] - let base_addr: usize = 0x40200000; - let base_addr = format!("BASE_ADDRESS = {};", base_addr); - let mut new_config = String::new(); - for line in ld.lines() { - if line.starts_with("BASE_ADDRESS = ") { - new_config.push_str(base_addr.as_str()); - } else { - new_config.push_str(line); - new_config.push_str("\n"); - } - } - - script.write_all(new_config.as_bytes()).unwrap(); - println!("cargo:rustc-link-arg=-T{}", &link_script.display()); -} diff --git a/boot/src/entry.rs b/boot/src/entry.rs deleted file mode 100644 index 0e25fa1e..00000000 --- a/boot/src/entry.rs +++ /dev/null @@ -1,45 +0,0 @@ -//! 内核汇编入口 -use core::arch::asm; - -use kernel::config::{CPU_NUM, STACK_SIZE}; - -#[link_section = ".bss.stack"] -pub static mut STACK: [u8; STACK_SIZE * CPU_NUM] = [0; STACK_SIZE * CPU_NUM]; - -/// 内核入口 -/// -/// 用于初始化内核的栈空间,并关闭中断 -#[naked] -#[no_mangle] -#[link_section = ".text.entry"] -extern "C" fn _start() { - unsafe { - asm!("\ - mv tp, a0 - csrw sscratch, a1 - add t0, a0, 1 - slli t0, t0, 16 - la sp, {boot_stack} - add sp, sp, t0 - call main - ", - boot_stack = sym STACK, - options(noreturn) - ); - } -} - -/// 获取设备树地址 -/// 在开始阶段,内核会将设备树的地址保存在sscratch寄存器中 -#[allow(unused)] -#[inline] -pub fn device_tree_addr() -> usize { - let mut res: usize; - unsafe { - asm!( - " csrr {}, sscratch", - out(reg) res, - ) - } - res -} diff --git a/boot/src/main.rs b/boot/src/main.rs deleted file mode 100644 index 50337b23..00000000 --- a/boot/src/main.rs +++ /dev/null @@ -1,164 +0,0 @@ -//! 内核启动模块 -//! -//! 该模块主要完成以下功能: -//! 1. 初始化内核的栈空间 -//! 2. 清空.bss段 -//! 3. 从设备树中获取基本的信息 -//! 4. 初始化内存子系统 -//! 5. 初始化中断子系统 -//! 6. 初始化系统调用 -//! 7. 初始化进程子系统 -//! 8. 初始化文件系统 -//! 9. 初始化设备子系统 -//! 10. 主核唤醒其它核 - -#![no_std] -#![no_main] -#![feature(naked_functions)] -#![feature(asm_const)] -#![feature(stmt_expr_attributes)] -#![deny(missing_docs)] - -use core::hint::spin_loop; -use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; - -use cfg_if::cfg_if; -use kernel::init_init_array; - -use basemachine::machine_info_from_dtb; -use kernel::arch::hart_id; -#[cfg(not(feature = "qemu"))] -use kernel::board; -#[cfg(any( - feature = "vf2", - feature = "qemu", - feature = "hifive", - feature = "cv1811h" -))] -use kernel::board::init_dtb; -use kernel::config::CPU_NUM; -use kernel::device::init_device; -use kernel::fs::init_filesystem; -use kernel::interrupt::init_plic; -use kernel::memory::{init_memory_system, kernel_info}; -use kernel::print::init_print; -use kernel::sbi::hart_start; -use kernel::{config, init_machine_info, println, task, thread_local_init, timer, trap}; - -mod entry; - -/// 多核启动标志 -static STARTED: AtomicBool = AtomicBool::new(false); -/// cpu启动计数 -static CPUS: AtomicUsize = AtomicUsize::new(0); - -extern "C" { - fn _start(); - fn sbss(); - fn ebss(); -} - -/// 清空.bss段 -#[inline] -fn clear_bss() { - unsafe { - core::slice::from_raw_parts_mut(sbss as usize as *mut u8, ebss as usize - sbss as usize) - .fill(0); - } -} - -/// 内核位于高级语言的入口 -#[no_mangle] -pub fn main(_: usize, _: usize) -> ! { - if !STARTED.load(Ordering::Relaxed) { - clear_bss(); - println!("{}", config::FLAG); - cfg_if! { - if #[cfg(not(feature = "qemu"))] { - let device_tree_addr = board::FDT.as_ptr() as usize; - }else{ - use crate::entry::device_tree_addr; - let device_tree_addr = device_tree_addr(); - } - } - init_print(); - println!( - "boot hart id: {}, device tree addr: {:#x}", - hart_id(), - device_tree_addr - ); - let machine_info = machine_info_from_dtb(device_tree_addr); - println!("{:#x?}", machine_info); - init_machine_info(machine_info.clone()); - kernel_info(machine_info.memory.end); - init_memory_system(machine_info.memory.end, true); - thread_local_init(); - // init device tree - #[cfg(feature = "qemu")] - init_dtb(Some(device_tree_addr)); - #[cfg(any(feature = "hifive", feature = "vf2"))] - init_dtb(None); - // init plic associate board - init_plic(); - // init all device - init_device(); - trap::init_trap_subsystem(); - init_filesystem().expect("Init filesystem failed"); - task::init_process(); - CPUS.fetch_add(1, Ordering::Release); - STARTED.store(true, Ordering::Relaxed); - init_other_hart(hart_id()); - // register all syscall - init_init_array!(); - } else { - while !STARTED.load(Ordering::Relaxed) { - spin_loop(); - } - thread_local_init(); - println!("hart {:#x} start", hart_id()); - init_memory_system(0, false); - trap::init_trap_subsystem(); - CPUS.fetch_add(1, Ordering::Release); - } - timer::set_next_trigger(); - println!("Begin run task..."); - task::schedule::first_into_user(); -} - -/// 唤醒其它核 -/// -/// 对于qemu来说,只需要工具所有的核都是一样的,因此从严号核开始唤醒。 -/// 对于visionfive2/unmatched 来说,0号核只有M态,因此不进行唤醒 -fn init_other_hart(hart_id: usize) { - cfg_if! { - if #[cfg(any(feature="vf2",feature = "hifive"))]{ - let start_hart = 1; - }else { - let start_hart = 0; - } - } - for i in start_hart..CPU_NUM { - if i != hart_id { - let res = hart_start(i, _start as usize, 0); - assert_eq!(res.error, 0); - } - } - wait_all_cpu_start(); -} - -/// 等待其它cpu核启动 -/// -/// 对于visionfive2/unmatched 来说,我们使用make SMP=2 来进行单核启动,这里针对这个情况做了处理 -fn wait_all_cpu_start() { - cfg_if! { - if #[cfg(any(feature="vf2",feature = "hifive"))]{ - let cpu_num = CPU_NUM - 1; - }else { - let cpu_num = CPU_NUM; - } - } - while CPUS.load(Ordering::Acquire) < cpu_num { - spin_loop() - } - println!("All cpu start"); -} diff --git a/docs/assert/boot.drawio.png b/docs/assert/boot.drawio.png new file mode 100644 index 00000000..fa6edb72 Binary files /dev/null and b/docs/assert/boot.drawio.png differ diff --git "a/docs/doc/\347\263\273\347\273\237\346\236\266\346\236\204.md" "b/docs/doc/\347\263\273\347\273\237\346\236\266\346\236\204.md" index 619320f9..9d47c085 100644 --- "a/docs/doc/\347\263\273\347\273\237\346\236\266\346\236\204.md" +++ "b/docs/doc/\347\263\273\347\273\237\346\236\266\346\236\204.md" @@ -50,7 +50,7 @@ - [Godones/doubly-linked-list](https://github.com/Godones/doubly-linked-list) **侵入式双向链表** - [Godones/dbfs2](https://github.com/Godones/dbfs2) **高性能数据库文件系统** - [module/basemachine](../../dep/basemachine) **设备树机器基本信息** -- [module/gmanager](../../dep/gmanager) **最小索引分配管理** +- [module/gmanager](../../subsystems/gmanager) **最小索引分配管理** - [module/Input2event](../../dep/input2event) **virtio输入事件转换** - [module/pager](../modules/pager) **物理页管理** - [module/plic](../modules/plic) **riscv平台控制器驱动** diff --git a/docs/subsystem.md b/docs/subsystem.md new file mode 100644 index 00000000..cdce3ee6 --- /dev/null +++ b/docs/subsystem.md @@ -0,0 +1,98 @@ +# Subsystem + +这一阶段,我们将原来的内核划分为一些较为松耦合的子系统。子系统与我们之前的模块化工作有相似之处,但是目标不一样。简单来说,之前的模块化是将内核中可独立的部分脱离内核,从而可被其它内核使用,而现在我们将内核继续划分,这些划分的子系统有点类似linux中的各个子系统,比如内存管理子系统、平台相关子系统、任务子系统等,这些子系统只是对原来的内核的交互进行了梳理,使得各个子系统之间的依赖关系,信息交互更加合理,这些子系统与我们的内核紧密相关,因此大多数是不能被其它内核所使用。 + +目前系统被划分为几个简单的子系统: + +1. `config`:提供内核的相关配置,比如启动栈大小、用户程序栈大小,缓冲区大小等 +2. `arch` : 提供体系结构相关的功能,我们的内核目前只运行在riscv平台上,所以这里只是简单提供一下开关中断/激活页表的功能 +3. `platform` : 平台相关的部分,我们的内核可以跑在几个不同的开发板上,这部分主要负责系统的启动和初始输出初始化 +4. `constants`: 提供内核子系统直接都会使用的数据结构定义 +5. `device_interface`: 提供各种设备的接口定义,这在设备管理子系统和驱动子系统实现中被引用 +6. `devices`: 设备管理子系统,负责扫描、注册所有的设备,其会引用任务管理子系统的功能 +7. `drivers`: 驱动子系统,包含了支持的设备的驱动程序,这些驱动程序会引用任务管理子系统的功能 +8. `interrupt`: 负责管理和分发外部中断处理 +9. `ksync`: 只是对内核锁的简单封装 +10. `mem` : 建立内核的映射,并负责管理整个系统的内存分配 +11. `timer`: 负责获取时间 +12. `vfs`: 负责注册内核支持的文件系统,并建立文件系统树 +13. `unwinder`: 内核崩溃处理 +14. `kernel`: 这部分包含了内核的所有系统调用实现,负责进行进程/线程的管理,以及中断/异常处理,其会协调其它子系统的初始化,然后使用其它子系统的数据和功能 + + + +系统的启动流程大致如下所示 + +![boot.drawio](./assert/boot.drawio.png) + + + +这里我们对几个比较核心且未来可能作为隔离域存在的子系统进行讨论。 + +`drivers` 子系统是不同设备的驱动实现集合,目前我们将其放在一个`crate`中,在未来驱动被作为一个隔离域实现时,需要将其拆分出来形成不同的`crate`。 + +块设备驱动`GenericBlockDevice`: + +1. 如果是一个virtio 设备,其会需要依赖一块设备地址空间。 +2. 如果是一个sdio设备,其会需要依赖一块设备地址空间。 + +向上,块设备驱动使用一个接口暴露功能 + +```rust +pub trait BlockDevice: Send + Sync + DeviceBase { + fn read(&self, buf: &mut [u8], offset: usize) -> AlienResult; + fn write(&self, buf: &[u8], offset: usize) -> AlienResult; + fn size(&self) -> usize; + fn flush(&self) -> AlienResult<()>; +} +``` + +在设备管理子系统中,扫描程序会使用驱动程序实例化一个设备,并再次使用其提供的接口功能实现文件系统相关的接口。 + +因此,如果需要将其作为一个隔离域,这个隔离域向外暴露的功能就应该与其接口类似,而对于依赖,根据不同的设备,我们可能会传递一个`MmioTransport` 结构体或者 `SDIo`结构体。 + + + +串口设备驱动`Uart`: + +1. 其依赖由几个寄存器构成的设备地址空间 + +向上,其使用一个接口暴露功能: + +```rust +pub trait UartDevice: Send + Sync + DeviceBase { + fn put(&self, c: u8); + fn get(&self) -> Option; + fn put_bytes(&self, bytes: &[u8]); + fn have_data_to_get(&self) -> bool; + fn have_space_to_put(&self) -> bool; +} +``` + +如果将其作为一个隔离域,其可能的形式应该如下: + +```rust +pub struct Registers { + pub thr_rbr_dll: RwReg, + pub ier_dlh: RwReg, + pub iir_fcr: RwReg, + pub lcr: RwReg, + pub mcr: RwReg, + pub lsr: RoReg, + pub msr: RoReg, + pub scratch: RwReg, +} + +fn main(regs:Box)->Box{ + // +} + +pub trait UartDomain{ + fn put(&self, c: u8); + fn get(&self,[u8]) -> RpcResult<[u8]>; + fn put_bytes(&self, [u8;128]); + fn have_data_to_get(&self) -> RpcResult<()>; + fn have_space_to_put(&self) -> RpcResult<()>; +} +``` + diff --git a/kernel/.gitignore b/kernel/.gitignore deleted file mode 100644 index c7256db4..00000000 --- a/kernel/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.idea -src/trace/kernel_symbol.S \ No newline at end of file diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index e0b723b5..ce3684a5 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -2,91 +2,58 @@ name = "kernel" version = "0.1.0" edition = "2021" -authors = ["chen linfeng"] -[dependencies] -log = "0.4.14" -spin = "0.9.2" -riscv = "0.10.0" -bit_field = "0.10.1" -xmas-elf = "0.9.0" -bitflags = "1.3.2" -virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers",rev = "de1c3b1"} -fdt = "0.1.3" -rtc = { git = "https://github.com/os-module/rtc.git" } -lru = "0.10.0" - -cfg-if = "1.0.0" -page-table = { git = "https://github.com/os-module/page-table.git", branch = "dev" } - -visionfive2-sd = { git = "https://github.com/os-module/visionfive2-sd.git", optional = true } -tracer = { git = "https://github.com/os-module/tracer" } -preprint = "0.1.0" -rslab = { version = "0.2.1", optional = true } - -syscall-table = { git = "https://github.com/os-module/syscall-table.git" } -plic = { git = "https://github.com/os-module/plic" } -pager = { git = "https://github.com/os-module/pager", default-features = false, optional = true } -kernel-sync = { git = "https://github.com/os-module/kernel-sync.git"} -pconst = { git = "https://github.com/os-module/pconst.git", features = [ - "trick", -] } -gmanager = { path = "../dep/gmanager" } -basemachine = { path = "../dep/basemachine" } -uart16550 = { version = "0.0.1", optional = true } -uart8250 = { git = "https://github.com/os-module/uart-rs.git", optional = true } -smpscheduler = { git = "https://github.com/os-module/smpscheduler.git" } -talc = { version = "1.0", optional = true } -buddy_system_allocator = { version = "0.9.0", optional = true } - -downcast-rs = { version = "1.2.0", default-features = false } +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +arch = { path = "../subsystems/arch" } +platform = { path = "../subsystems/platform" } +mem = { path = "../subsystems/mem" } +interrupt = { path = "../subsystems/interrupt" } +devices = { path = "../subsystems/devices" } +drivers = { path = "../subsystems/drivers" } +unwinder = { path = "../subsystems/unwinder" } +constants = { path = "../subsystems/constants" } +config = { path = "../subsystems/config" } +vfs = { path = "../subsystems/vfs" } +timer = { path = "../subsystems/timer" } +ksync = { path = "../subsystems/ksync" } +knet = { path = "../subsystems/knet" } +gmanager = { path = "../subsystems/gmanager" } + + + + +riscv = "0.10" +bit_field = "0.10" +xmas-elf = "0.9" +bitflags = "1.3" +spin = "0" +log = "0" vfscore = { git = "https://github.com/os-module/rvfs.git", features = [ "linux_error", ] } -devfs = { git = "https://github.com/os-module/rvfs.git" } -dynfs = { git = "https://github.com/os-module/rvfs.git" } -ramfs = { git = "https://github.com/os-module/rvfs.git" } -fat-vfs = { git = "https://github.com/os-module/rvfs.git" } -loopback = {git = "https://github.com/os-module/simple-net",optional = true} -virtio-net = {git = "https://github.com/os-module/simple-net"} +syscall-table = { git = "https://github.com/os-module/syscall-table.git" } +smpscheduler = { git = "https://github.com/os-module/smpscheduler.git" } +page-table = { git = "https://github.com/os-module/page-table.git", branch = "dev" } netcore = {git = "https://github.com/os-module/simple-net"} -[dependencies.smoltcp] -git = "https://github.com/rcore-os/smoltcp.git" -rev = "2ade274" -default-features = false -features = [ - "alloc", - "log", # no std - "medium-ethernet", - "proto-ipv4", - "socket-raw", - "socket-icmp", - "socket-udp", - "socket-tcp", - "socket-dns", -] [features] -default = ["pager_bitmap","test",] -vf2 = ["visionfive2-sd", "uart8250"] -hifive = ["uart16550"] -qemu = ["uart16550"] - - -net_test = [] +default = ["smp","test"] +qemu = ["platform/qemu_riscv","interrupt/qemu"] +vf2 = ["platform/vf2","interrupt/vf2", "devices/vf2"] +hifive = ["platform/hifive","interrupt/hifive"] +smp = ["platform/smp"] -slab = ["rslab"] -talloc = ["talc"] -buddy = ["buddy_system_allocator"] -pager_buddy = ["pager/buddy"] -pager_bitmap = ["pager/bitmap"] +slab = [] +talloc = [] +buddy = [] -test = ["loopback"] +pager_buddy = ["mem/pager_buddy"] +pager_bitmap = ["mem/pager_bitmap"] -debug-eh-frame = [] -debug-frame-pointer = [] -ramfs = [] \ No newline at end of file +ramdisk = ["devices/ramdisk"] +test = ["devices/test"] \ No newline at end of file diff --git a/kernel/build.rs b/kernel/build.rs index 0449bc84..63c386fe 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -1,45 +1,32 @@ use std::fs::File; use std::io::Write; use std::path::Path; -use std::string::String; -use std::{format, fs}; +use std::{env, fs}; fn main() { - println!("cargo:rerun-if-changed={}", "src/"); - let path = Path::new("src/trace/kernel_symbol.S"); - if !path.exists() { - let mut file = File::create(path).unwrap(); - write!(file, ".section .rodata\n").unwrap(); - write!(file, ".align 3\n").unwrap(); - write!(file, ".global symbol_num\n").unwrap(); - write!(file, ".global symbol_address\n").unwrap(); - write!(file, ".global symbol_index\n").unwrap(); - write!(file, ".global symbol_name\n").unwrap(); - write!(file, "symbol_num:\n").unwrap(); - write!(file, ".quad {}\n", 0).unwrap(); - write!(file, "symbol_address:\n").unwrap(); - write!(file, "symbol_index:\n").unwrap(); - write!(file, "symbol_name:\n").unwrap(); - } - rewrite_config(); -} + // 指定target + let outdir = env::var("OUT_DIR").unwrap(); + let link_script = Path::new(&outdir).join("link.lds"); + let mut script = File::create(&link_script).unwrap(); -pub fn rewrite_config() { - let cpus = option_env!("SMP").unwrap_or("1"); - let cpus = cpus.parse::().unwrap(); - let config_file = Path::new("src/config.rs"); - let config = fs::read_to_string(config_file).unwrap(); - let cpus = format!("pub const CPU_NUM: usize = {};\n", cpus); - // let regex = regex::Regex::new(r"pub const CPU_NUM: usize = \d+;").unwrap(); - // config = regex.replace_all(&config, cpus.as_str()).to_string(); + let ld_path = Path::new("../tools/link.ld"); + let ld = fs::read_to_string(ld_path).unwrap(); + + #[cfg(not(feature = "vf2"))] + let base_addr = 0x80200000usize; + #[cfg(feature = "vf2")] + let base_addr: usize = 0x40200000; + let base_addr = format!("BASE_ADDRESS = {};", base_addr); let mut new_config = String::new(); - for line in config.lines() { - if line.starts_with("pub const CPU_NUM: usize = ") { - new_config.push_str(cpus.as_str()); + for line in ld.lines() { + if line.starts_with("BASE_ADDRESS = ") { + new_config.push_str(base_addr.as_str()); } else { new_config.push_str(line); new_config.push_str("\n"); } } - fs::write(config_file, new_config).unwrap(); + + script.write_all(new_config.as_bytes()).unwrap(); + println!("cargo:rustc-link-arg=-T{}", &link_script.display()); } diff --git a/kernel/src/arch/riscv.rs b/kernel/src/arch/riscv.rs deleted file mode 100644 index eee8ab02..00000000 --- a/kernel/src/arch/riscv.rs +++ /dev/null @@ -1,45 +0,0 @@ -pub use riscv::*; - -pub mod sstatus { - use core::arch::asm; - - use bit_field::BitField; - pub use riscv::register::sstatus::*; - - #[derive(Copy, Clone, Debug, Default)] - pub struct Sstatus(pub usize); - - impl Sstatus { - pub fn set_value(&mut self, val: usize) { - self.0 = val; - } - pub fn set_spp(&mut self, spp: SPP) { - self.0.set_bit(8, spp as usize != 0); - } - pub fn spp(&self) -> SPP { - let v = self.0.get_bit(8); - if v { - SPP::Supervisor - } else { - SPP::User - } - } - pub fn set_spie(&mut self) { - self.0.set_bit(5, true); - } - pub fn sie(&self) -> bool { - self.0.get_bit(1) - } - pub fn set_sie(&mut self, value: bool) { - self.0.set_bit(1, value); - } - } - - pub fn read() -> Sstatus { - let val: usize; - unsafe { - asm!("csrr {},sstatus", out(reg)val); - } - Sstatus(val) - } -} diff --git a/kernel/src/board/mod.rs b/kernel/src/board/mod.rs deleted file mode 100644 index 8b21a177..00000000 --- a/kernel/src/board/mod.rs +++ /dev/null @@ -1,104 +0,0 @@ -mod probe; - -use alloc::collections::BTreeMap; - -use cfg_if::cfg_if; - -use crate::ksync::Mutex; - -use crate::device::DeviceType; - -pub static BOARD_DEVICES: Mutex> = Mutex::new(BTreeMap::new()); - -pub fn get_rtc_info() -> Option { - BOARD_DEVICES - .lock() - .get(&DeviceType::Rtc) - .map(|rtc| rtc.clone()) -} - -pub fn get_uart_info() -> Option { - BOARD_DEVICES - .lock() - .get(&DeviceType::Uart) - .map(|uart| uart.clone()) -} - -pub fn get_gpu_info() -> Option { - BOARD_DEVICES - .lock() - .get(&DeviceType::GPU) - .map(|gpu| gpu.clone()) -} - -pub fn get_keyboard_info() -> Option { - BOARD_DEVICES - .lock() - .get(&DeviceType::KeyBoardInput) - .map(|keyboard| keyboard.clone()) -} - -pub fn get_mouse_info() -> Option { - BOARD_DEVICES - .lock() - .get(&DeviceType::MouseInput) - .map(|mouse| mouse.clone()) -} - -pub fn get_block_device_info() -> Option { - BOARD_DEVICES - .lock() - .get(&DeviceType::Block) - .map(|block| block.clone()) -} - -pub fn get_net_device_info() -> Option { - BOARD_DEVICES - .lock() - .get(&DeviceType::Network) - .map(|net| net.clone()) -} - -use crate::board::probe::DeviceInfo; -cfg_if! { - if #[cfg(feature="qemu")]{ - mod qemu; - pub use qemu::*; - }else if #[cfg(feature="hifive")]{ - mod unmatched; - pub use unmatched::*; - }else if #[cfg(feature="vf2")]{ - mod vf2; - pub use vf2::*; - } -} - -#[cfg(feature = "ramfs")] -core::arch::global_asm!( - r#" - .section .data - .global img_start - .global img_end - .align 12 - img_start: - .incbin "./tools/sdcard.img" - img_end: - "# -); - -#[cfg(feature = "ramfs")] -extern "C" { - pub fn img_start(); - pub fn img_end(); -} - -#[cfg(feature = "ramfs")] -pub fn checkout_fs_img() { - let img_start = img_start as usize; - let img_end = img_end as usize; - let img_size = img_end - img_start; - println!( - "img_start: {:#x}, img_end: {:#x}, img_size: {:#x}", - img_start, img_end, img_size - ); -} diff --git a/kernel/src/board/qemu.rs b/kernel/src/board/qemu.rs deleted file mode 100644 index 636de488..00000000 --- a/kernel/src/board/qemu.rs +++ /dev/null @@ -1,85 +0,0 @@ -use crate::board::probe::{DeviceInfo, Probe}; -use crate::board::BOARD_DEVICES; -use crate::device::DeviceType; -use core::ptr::NonNull; -use fdt::Fdt; -use spin::Once; -use virtio_drivers::transport::mmio::{MmioTransport, VirtIOHeader}; -use virtio_drivers::transport::Transport; - -pub static DTB: Once = Once::new(); - -pub fn init_dtb(dtb: Option) { - let fdt = if dtb.is_some() { - unsafe { Fdt::from_ptr(dtb.unwrap() as *const u8).unwrap() } - } else { - panic!("No dtb found") - }; - DTB.call_once(|| fdt); -} - -/// Get the base address and irq number of the uart device from the device tree. -pub fn probe_devices_from_dtb() { - let dtb = DTB.get().unwrap(); - if let Some(rtc) = dtb.probe_rtc() { - BOARD_DEVICES.lock().insert(DeviceType::Rtc, rtc); - } - if let Some(uart) = dtb.probe_uart() { - BOARD_DEVICES.lock().insert(DeviceType::Uart, uart); - } - if let Some(virtio_mmio) = dtb.probe_virtio() { - for virtio in virtio_mmio { - match virtio_mmio_type(&virtio) { - Some(ty) => { - BOARD_DEVICES.lock().insert(ty, virtio); - } - None => { - error!("Unknown virtio device type at {:#x}", virtio.base_addr); - } - } - } - } -} - -// keyboard -const VIRTIO5: usize = 0x10005000; -// mouse -const VIRTIO6: usize = 0x10006000; - -fn virtio_mmio_type(device_info: &DeviceInfo) -> Option { - let paddr = device_info.base_addr; - let header = NonNull::new(paddr as *mut VirtIOHeader).unwrap(); - info!("walk dt addr={:#x}", paddr); - info!( - "Device tree node {}: {:?}", - device_info.name, device_info.compatible - ); - match unsafe { MmioTransport::new(header) } { - Err(_) => None, - Ok(mut transport) => { - info!( - "Detected virtio MMIO device with vendor id {:#X}, device type {:?}, version {:?}, features:{:?}", - transport.vendor_id(), - transport.device_type(), - transport.version(), - transport.read_device_features(), - ); - info!("Probe virtio device: {:?}", transport.device_type()); - match transport.device_type() { - virtio_drivers::transport::DeviceType::Input => { - if paddr == VIRTIO5 { - Some(DeviceType::KeyBoardInput) - } else if paddr == VIRTIO6 { - Some(DeviceType::MouseInput) - } else { - None - } - } - virtio_drivers::transport::DeviceType::Block => Some(DeviceType::Block), - virtio_drivers::transport::DeviceType::GPU => Some(DeviceType::GPU), - virtio_drivers::transport::DeviceType::Network => Some(DeviceType::Network), - _ => None, - } - } - } -} diff --git a/kernel/src/board/unmatched.rs b/kernel/src/board/unmatched.rs deleted file mode 100644 index f913a5a2..00000000 --- a/kernel/src/board/unmatched.rs +++ /dev/null @@ -1,33 +0,0 @@ -use crate::board::probe::Probe; -use crate::board::BOARD_DEVICES; -use crate::device::DeviceType; -use fdt::Fdt; -use spin::Once; - -#[repr(align(4))] -struct Wrapper(T); - -pub const FDT: &[u8] = &Wrapper(*include_bytes!("../../../tools/hifive-unmatched-a00.dtb")).0; - -pub static DTB: Once = Once::new(); - -pub fn init_dtb(dtb: Option) { - let fdt = if dtb.is_some() { - assert_eq!(dtb.unwrap(), FDT.as_ptr() as usize); - unsafe { Fdt::from_ptr(dtb.unwrap() as *const u8).unwrap() } - } else { - unsafe { Fdt::from_ptr(FDT.as_ptr()).unwrap() } - }; - DTB.call_once(|| fdt); -} - -/// Get the base address and irq number of the uart device from the device tree. -pub fn probe_devices_from_dtb() { - let dtb = crate::board::DTB.get().unwrap(); - if let Some(rtc) = dtb.probe_rtc() { - BOARD_DEVICES.lock().insert(DeviceType::Rtc, rtc); - } - if let Some(uart) = dtb.probe_uart() { - BOARD_DEVICES.lock().insert(DeviceType::Uart, uart); - } -} diff --git a/kernel/src/board/vf2.rs b/kernel/src/board/vf2.rs deleted file mode 100644 index 24a44eb7..00000000 --- a/kernel/src/board/vf2.rs +++ /dev/null @@ -1,37 +0,0 @@ -use fdt::Fdt; -use spin::Once; - -use crate::board::probe::Probe; -use crate::board::BOARD_DEVICES; -use crate::device::DeviceType; - -#[repr(align(4))] -struct Wrapper(T); - -pub const FDT: &[u8] = &Wrapper(*include_bytes!("../../../tools/jh7110-visionfive-v2.dtb")).0; - -pub static DTB: Once = Once::new(); - -pub fn init_dtb(dtb: Option) { - let fdt = if dtb.is_some() { - assert_eq!(dtb.unwrap(), FDT.as_ptr() as usize); - unsafe { Fdt::from_ptr(dtb.unwrap() as *const u8).unwrap() } - } else { - unsafe { Fdt::from_ptr(FDT.as_ptr()).unwrap() } - }; - DTB.call_once(|| fdt); -} - -/// Get the base address and irq number of the uart device from the device tree. -pub fn probe_devices_from_dtb() { - let dtb = DTB.get().unwrap(); - if let Some(rtc) = dtb.probe_rtc() { - BOARD_DEVICES.lock().insert(DeviceType::Rtc, rtc); - } - if let Some(uart) = dtb.probe_uart() { - BOARD_DEVICES.lock().insert(DeviceType::Uart, uart); - } - if let Some(sdio) = dtb.probe_sdio() { - BOARD_DEVICES.lock().insert(DeviceType::Block, sdio); - } -} diff --git a/kernel/src/config.rs b/kernel/src/config.rs deleted file mode 100644 index 2edeeda9..00000000 --- a/kernel/src/config.rs +++ /dev/null @@ -1,194 +0,0 @@ -//! 配置文件 - -/// Alien os的标志 -pub const FLAG: &str = r" - _ _ _ - / \ | | (_) ___ _ __ - / _ \ | | | | / _ \ | '_ \ - / ___ \ | | | | | __/ | | | | - /_/ \_\ |_| |_| \___| |_| |_| -"; - -/// qemu时钟频率 -#[cfg(feature = "qemu")] -pub const CLOCK_FREQ: usize = 1250_0000; -/// vf2时钟频率 -#[cfg(feature = "vf2")] -pub const CLOCK_FREQ: usize = 400_0000; - -/// unmatched时钟频率 -#[cfg(feature = "hifive")] -pub const CLOCK_FREQ: usize = 100_0000; - -/// cv1811h时钟频率 -#[cfg(feature = "cv1811h")] -pub const CLOCK_FREQ: usize = 0x17d7840; - -/// 物理页大小 -pub const FRAME_SIZE: usize = 0x1000; -/// 物理页大小的位数 -pub const FRAME_BITS: usize = 12; -/// 内核启动栈大小 -pub const STACK_SIZE: usize = 1024 * 64; -/// 内核启动栈大小的位数 -pub const STACK_SIZE_BITS: usize = 16; - -/// equal to CLOCK_FREQ -pub const TIMER_FREQ: usize = CLOCK_FREQ; -/// 可配置的启动cpu数量 -pub const CPU_NUM: usize = 1; - -pub const AT_FDCWD: isize = -100isize; - -///qemu的设备地址空间 -#[cfg(feature = "qemu")] -pub const MMIO: &[(usize, usize)] = &[ - (0x0010_0000, 0x00_2000), // VIRT_TEST/RTC in virt machine - (0x2000000, 0x10000), - (0xc00_0000, 0x21_0000), // VIRT_PLIC in virt machine - (0x1000_0000, 0x9000), // VIRT_UART0 with GPU in virt machine - (0x3000_0000, 0x1000_0000), -]; - -/// vf2的设备地址空间 -#[cfg(feature = "vf2")] -pub const MMIO: &[(usize, usize)] = &[ - (0x17040000, 0x10000), // RTC - (0xc000000, 0x4000000), //PLIC - (0x00_1000_0000, 0x10000), // UART -]; - -/// hifive的设备地址空间 -#[cfg(feature = "hifive")] -pub const MMIO: &[(usize, usize)] = &[ - (0xc000000, 0x4000000), //PLIC -]; - -// todo!(if the app linker script changed, this should be changed too) -/// 进程的堆空间上限 -pub const PROCESS_HEAP_MAX: usize = u32::MAX as usize + 1; -/// 跳板页的虚拟地址 -pub const TRAMPOLINE: usize = usize::MAX - 2 * FRAME_SIZE + 1; -/// trap context的虚拟地址 -pub const TRAP_CONTEXT_BASE: usize = TRAMPOLINE - FRAME_SIZE; - -/// app内核栈大小 -pub const USER_KERNEL_STACK_SIZE: usize = 0x1000 * 2; -/// app用户栈大小 -pub const USER_STACK_SIZE: usize = 0x50_000; - -/// vf2/unmatched 的块缓存大小 -#[cfg(any(feature = "vf2", feature = "hifive"))] -pub const BLOCK_CACHE_FRAMES: usize = 1024 * 4 * 16; - -/// qemu 的块缓存大小 -#[cfg(feature = "qemu")] -pub const BLOCK_CACHE_FRAMES: usize = 1024 * 4 * 4; - -/// vf2/unmatched 的堆空间大小 -#[cfg(any(feature = "vf2", feature = "hifive"))] -pub const HEAP_SIZE: usize = 0x40_00000; - -/// qemu 的堆空间大小 -#[cfg(feature = "qemu")] -pub const HEAP_SIZE: usize = 0x26_00000; // (32+6)MB - -/// equal to HEAP_SIZe -#[cfg(any(feature = "talloc", feature = "buddy"))] -pub const KERNEL_HEAP_SIZE: usize = HEAP_SIZE; - -/// pipe缓冲区大小 -pub const PIPE_BUF: usize = 65536; - -/// 线程数量大小限制 -pub const MAX_THREAD_NUM: usize = 65536; -/// 描述符数量大小限制 -pub const MAX_FD_NUM: usize = 4096; - -/// 最大的输入事件数量 -pub const MAX_INPUT_EVENT_NUM: usize = 1024; - -/// 如果 elf 的 phdr 指示 base 是 0(如 libc-test 的 libc.so),则需要找一个非0的位置放置 -/// 我们将其从 0x4000_0000 开始放置。主要用于动态链接库使用 -pub const ELF_BASE_RELOCATE: usize = 0x400_0000; - -/// localtime文件中保存的内容 -pub const UTC: &[u8] = &[ - b'T', b'Z', b'i', b'f', b'2', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, - 0, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0x4, 0, 0, 0, 0, 0, 0, b'U', b'T', b'C', - 0, 0, 0, b'T', b'Z', b'i', b'f', b'2', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0x4, 0, 0, 0, 0, 0, 0, b'U', - b'T', b'C', 0, 0, 0, 0x0a, 0x55, 0x54, 0x43, 0x30, 0x0a, -]; - -/// rtc文件中保存的内容 -pub const RTC_TIME: &str = r" -rtc_time : 03:01:50 -rtc_date : 2023-07-11 -alrm_time : 13:03:24 -alrm_date : 2023-07-11 -alarm_IRQ : no -alrm_pending : no -update IRQ enabled : no -periodic IRQ enabled : no -periodic IRQ frequency : 1024 -max user IRQ frequency : 64 -24hr : yes -periodic_IRQ : no -update_IRQ : no -HPET_emulated : no -BCD : yes -DST_enable : no -periodic_freq : 1024 -batt_status : okay"; - -/// meminfo文件中保存的内容 -pub const MEMINFO: &str = r" -MemTotal: 944564 kB -MemFree: 835248 kB -MemAvailable: 873464 kB -Buffers: 6848 kB -Cached: 36684 kB -SwapCached: 0 kB -Active: 19032 kB -Inactive: 32676 kB -Active(anon): 128 kB -Inactive(anon): 8260 kB -Active(file): 18904 kB -Inactive(file): 24416 kB -Unevictable: 0 kB -Mlocked: 0 kB -SwapTotal: 0 kB -SwapFree: 0 kB -Dirty: 0 kB -Writeback: 0 kB -AnonPages: 8172 kB -Mapped: 16376 kB -Shmem: 216 kB -KReclaimable: 9960 kB -Slab: 17868 kB -SReclaimable: 9960 kB -SUnreclaim: 7908 kB -KernelStack: 1072 kB -PageTables: 600 kB -NFS_Unstable: 0 kB -Bounce: 0 kB -WritebackTmp: 0 kB -CommitLimit: 472280 kB -Committed_AS: 64684 kB -VmallocTotal: 67108863 kB -VmallocUsed: 15740 kB -VmallocChunk: 0 kB -Percpu: 496 kB -HugePages_Total: 0 -HugePages_Free: 0 -HugePages_Rsvd: 0 -HugePages_Surp: 0 -Hugepagesize: 2048 kB -Hugetlb: 0 kB -"; - -// QEMU user networking default IP -pub const QEMU_IP: &str = "10.0.2.15"; -// QEMU user networking gateway -pub const QEMU_GATEWAY: &str = "10.0.2.2"; diff --git a/kernel/src/device/mod.rs b/kernel/src/device/mod.rs deleted file mode 100644 index 89135523..00000000 --- a/kernel/src/device/mod.rs +++ /dev/null @@ -1,299 +0,0 @@ -pub use self::rtc::{get_rtc_time, RTCDevice, RtcDevice, RTC_DEVICE}; -pub use self::uart::{UARTDevice, UartDevice, UART_DEVICE}; -use crate::board::{get_rtc_info, probe_devices_from_dtb}; -use crate::driver::GenericBlockDevice; -use crate::interrupt::register_device_to_plic; -use crate::print::console::UART_FLAG; -use alloc::boxed::Box; -use alloc::sync::Arc; -pub use block::{BLKDevice, BlockDevice, BLOCK_DEVICE}; -pub use gpu::{GPUDevice, GpuDevice, GPU_DEVICE}; -pub use input::{ - sys_event_get, INPUTDevice, InputDevice, KEYBOARD_INPUT_DEVICE, MOUSE_INPUT_DEVICE, -}; -use smoltcp::wire::IpAddress; - -mod block; -mod gpu; -mod input; -mod net; -mod rtc; -mod uart; - -#[derive(Debug, Clone, Copy, PartialOrd, PartialEq, Hash, Ord, Eq)] -pub enum DeviceType { - Block, - GPU, - KeyBoardInput, - MouseInput, - Network, - Uart, - Rtc, -} -pub fn init_device() { - probe_devices_from_dtb(); - init_uart(); - init_gpu(); - init_keyboard_input_device(); - init_mouse_input_device(); - init_rtc(); - init_net(); - init_block_device(); - // init_pci(); -} - -fn init_rtc() { - let res = get_rtc_info(); - if res.is_none() { - println!("There is no rtc device"); - return; - } - let info = res.unwrap(); - let (base_addr, irq) = (info.base_addr, info.irq); - println!("Init rtc, base_addr:{:#x},irq:{}", base_addr, irq); - #[cfg(feature = "qemu")] - { - use crate::driver::rtc::GoldFishRtc; - use ::rtc::LowRtcDeviceExt; - let rtc = Arc::new(GoldFishRtc::new(base_addr)); - let current_time = rtc.read_time_fmt(); - rtc::init_rtc(rtc.clone()); - register_device_to_plic(irq, rtc.clone()); - println!("Init rtc success, current time: {:?}", current_time); - } - #[cfg(feature = "vf2")] - { - // rtc = todo!(); - println!("Don't support rtc on vf2"); - } -} - -fn init_uart() { - let res = crate::board::get_uart_info(); - if res.is_none() { - println!("There is no uart device"); - return; - } - let info = res.unwrap(); - let (base_addr, irq) = (info.base_addr, info.irq); - println!("Init uart, base_addr:{:#x},irq:{}", base_addr, irq); - #[cfg(feature = "qemu")] - { - use crate::driver::uart::{Uart, Uart16550}; - use core::sync::atomic::Ordering; - let uart = Uart16550::new(base_addr); - let uart = Uart::new(Box::new(uart)); - let uart = Arc::new(uart); - uart::init_uart(uart.clone()); - register_device_to_plic(irq, uart); - UART_FLAG.store(true, Ordering::Relaxed); - } - #[cfg(feature = "vf2")] - { - use crate::driver::uart::{Uart, Uart8250}; - use core::sync::atomic::Ordering; - let uart = Uart8250::new(base_addr); - let uart = Uart::new(Box::new(uart)); - let uart = Arc::new(uart); - uart::init_uart(uart.clone()); - register_device_to_plic(irq, uart); - UART_FLAG.store(true, Ordering::Relaxed); - } - - println!("Init uart success"); -} - -fn init_block_device() { - #[cfg(feature = "qemu")] - { - use crate::driver::VirtIOBlkWrapper; - let res = crate::board::get_block_device_info(); - if res.is_none() { - println!("There is no block device"); - return; - } - let info = res.unwrap(); - let (base_addr, irq) = (info.base_addr, info.irq); - println!("Init block device, base_addr:{:#x},irq:{}", base_addr, irq); - let block_device = VirtIOBlkWrapper::new(base_addr); - let block_device = GenericBlockDevice::new(Box::new(block_device)); - println!( - "Block Cache size: {}MB", - block_device.cache_max_size() / 1024 / 1024 - ); - let block_device = Arc::new(block_device); - block::init_block_device(block_device); - // register_device_to_plic(irq, block_device); - println!("Init block device success"); - } - - #[cfg(any(feature = "vf2", feature = "hifive"))] - { - #[cfg(not(feature = "ramfs"))] - { - use crate::config::CLOCK_FREQ; - use crate::driver::Vf2SdDriver; - use crate::timer::read_timer; - pub fn sleep(ms: usize) { - let start = read_timer(); - while read_timer() - start < ms * (CLOCK_FREQ / 1000) { - core::hint::spin_loop(); - } - } - let device = Vf2SdDriver::new(visionfive2_sd::Vf2SdDriver::new(sleep)); - device.init(); - let block_device = GenericBlockDevice::new(Box::new(device)); - println!( - "Block Cache size: {}MB", - block_device.cache_max_size() / 1024 / 1024 - ); - let block_device = Arc::new(block_device); - block::init_block_device(block_device); - println!("Init block device success"); - } - #[cfg(feature = "ramfs")] - { - use crate::board::checkout_fs_img; - checkout_fs_img(); - init_fake_disk(); - println!("Init fake disk success"); - } - } -} - -#[cfg(feature = "ramfs")] -fn init_fake_disk() { - use crate::board::{img_end, img_start}; - use crate::driver::MemoryFat32Img; - let data = unsafe { - core::slice::from_raw_parts_mut(img_start as *mut u8, img_end as usize - img_start as usize) - }; - let device = GenericBlockDevice::new(Box::new(MemoryFat32Img::new(data))); - println!( - "Block Cache size: {}MB", - device.cache_max_size() / 1024 / 1024 - ); - let device = Arc::new(device); - block::init_block_device(device); -} - -fn init_gpu() { - let res = crate::board::get_gpu_info(); - if res.is_none() { - println!("There is no gpu device"); - return; - } - let info = res.unwrap(); - let (base_addr, irq) = (info.base_addr, info.irq); - println!("Init gpu, base_addr:{:#x},irq:{}", base_addr, irq); - #[cfg(feature = "qemu")] - { - use crate::driver::gpu::VirtIOGpuWrapper; - let gpu = VirtIOGpuWrapper::new(base_addr); - let gpu = Arc::new(gpu); - gpu::init_gpu(gpu.clone()); - // let _ = register_device_to_plic(irq, gpu); - println!("Init gpu success"); - } -} - -fn init_keyboard_input_device() { - let res = crate::board::get_keyboard_info(); - if res.is_none() { - println!("There is no keyboard device"); - return; - } - let info = res.unwrap(); - let (base_addr, irq) = (info.base_addr, info.irq); - println!( - "Init keyboard input device, base_addr:{:#x},irq:{}", - base_addr, irq - ); - #[cfg(feature = "qemu")] - { - use crate::config::MAX_INPUT_EVENT_NUM; - use crate::driver::input::VirtIOInputDriver; - let input_device = VirtIOInputDriver::from_addr(base_addr, MAX_INPUT_EVENT_NUM as u32); - let input_device = Arc::new(input_device); - input::init_keyboard_input_device(input_device.clone()); - let _ = register_device_to_plic(irq, input_device); - println!("Init keyboard input device success"); - } -} - -fn init_mouse_input_device() { - let res = crate::board::get_mouse_info(); - if res.is_none() { - println!("There is no mouse device"); - return; - } - let info = res.unwrap(); - let (base_addr, irq) = (info.base_addr, info.irq); - println!( - "Init mouse input device, base_addr:{:#x},irq:{}", - base_addr, irq - ); - #[cfg(feature = "qemu")] - { - use crate::config::MAX_INPUT_EVENT_NUM; - use crate::driver::input::VirtIOInputDriver; - let input_device = VirtIOInputDriver::from_addr(base_addr, MAX_INPUT_EVENT_NUM as u32); - let input_device = Arc::new(input_device); - input::init_mouse_input_device(input_device.clone()); - let _ = register_device_to_plic(irq, input_device); - println!("Init mouse input device success"); - } -} - -fn init_net() { - // If we need run test, we should only init loop device because no we can't route packet - #[cfg(feature = "test")] - { - init_loop_device(); - } - #[cfg(not(feature = "test"))] - { - let res = crate::board::get_net_device_info(); - if res.is_none() { - println!("There is no net device"); - return; - } - let info = res.unwrap(); - let (base_addr, irq) = (info.base_addr, info.irq); - println!("Init net device, base_addr:{:#x},irq:{}", base_addr, irq); - - #[cfg(feature = "qemu")] - { - use crate::device::net::NetNeedFunc; - use crate::driver::net::make_virtio_net_device; - let virtio_net = make_virtio_net_device(base_addr); - use crate::config::{QEMU_GATEWAY, QEMU_IP}; - use core::str::FromStr; - let device = Box::new(virtio_net); - netcore::init_net( - device, - Arc::new(NetNeedFunc), - IpAddress::from_str(QEMU_IP).unwrap(), - IpAddress::from_str(QEMU_GATEWAY).unwrap(), - true, - ); - println!("Init net device success"); - #[cfg(feature = "net_test")] - { - println!("test echo-server"); - net::nettest::accept_loop(); - } - } - } -} -#[cfg(feature = "test")] -fn init_loop_device() { - use crate::device::net::NetNeedFunc; - use loopback::LoopbackDev; - // use default ip and gateway for qemu - let ip = IpAddress::v4(127, 0, 0, 1); - let gate_way = IpAddress::v4(127, 0, 0, 1); - let loopback = Box::new(LoopbackDev::new()); - netcore::init_net(loopback, Arc::new(NetNeedFunc), ip, gate_way, false); - println!("Init net device success"); -} diff --git a/kernel/src/driver/mod.rs b/kernel/src/driver/mod.rs deleted file mode 100644 index 5dc3e4d8..00000000 --- a/kernel/src/driver/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub use block_device::*; -mod block_device; -pub mod hal; - -pub mod gpu; -pub mod input; -pub mod net; -pub mod rtc; -pub mod uart; diff --git a/kernel/src/driver/net.rs b/kernel/src/driver/net.rs deleted file mode 100644 index a776a543..00000000 --- a/kernel/src/driver/net.rs +++ /dev/null @@ -1,18 +0,0 @@ -use core::ptr::NonNull; - -use virtio_drivers::transport::mmio::{MmioTransport, VirtIOHeader}; -use virtio_net::VirtIONetDeviceWrapper; - -use crate::driver::hal::HalImpl; - -pub const NET_BUFFER_LEN: usize = 4096; -pub const NET_QUEUE_SIZE: usize = 128; - -pub fn make_virtio_net_device( - addr: usize, -) -> VirtIONetDeviceWrapper { - let header = NonNull::new(addr as *mut VirtIOHeader).unwrap(); - let transport = unsafe { MmioTransport::new(header) }.unwrap(); - let device = VirtIONetDeviceWrapper::new(transport, NET_BUFFER_LEN); - device -} diff --git a/kernel/src/driver/rtc.rs b/kernel/src/driver/rtc.rs deleted file mode 100644 index 788480f6..00000000 --- a/kernel/src/driver/rtc.rs +++ /dev/null @@ -1,17 +0,0 @@ -pub use rtc::goldfish::GoldFishRtc; -use rtc::{LowRtcDevice, LowRtcDeviceExt}; - -use crate::device::RtcDevice; -use crate::interrupt::DeviceBase; - -impl DeviceBase for GoldFishRtc { - fn hand_irq(&self) { - let alarm = self.read_alarm_fmt(); - let time = self.read_time_fmt(); - println!("rtc interrupt, time: {:?}, alarm: {:?}", time, alarm); - self.clear_irq(); - self.set_alarm(self.read_time() + 1_000_000_000 * 5); - } -} - -impl RtcDevice for GoldFishRtc {} diff --git a/kernel/src/error.rs b/kernel/src/error.rs deleted file mode 100644 index b656d979..00000000 --- a/kernel/src/error.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! alien os中error定义 -//! -//! 后续需要将其与linux的error等价转换 -use pconst::LinuxErrno; - -pub type AlienError = LinuxErrno; -pub type AlienResult = Result; diff --git a/kernel/src/fs/basic.rs b/kernel/src/fs/basic.rs index 417e53a3..4f176597 100644 --- a/kernel/src/fs/basic.rs +++ b/kernel/src/fs/basic.rs @@ -1,19 +1,18 @@ use super::im2vim; -use crate::config::AT_FDCWD; -use crate::error::AlienResult; -use crate::fs::file::KernelFile; -use crate::fs::{syscontext_for_vfs, user_path_at, FS, SYSTEM_ROOT_FS}; +use crate::fs::{syscontext_for_vfs, user_path_at}; use crate::task::current_task; use alloc::sync::Arc; use alloc::vec; -use core::cmp::min; -use core::ops::Index; -use gmanager::ManagerError; -use pconst::io::{ +use constants::io::{ FileStat, FsStat, InodeMode, IoVec, MountFlags, OpenFlags, Renameat2Flags, SeekFrom, StatFlags, }; -use pconst::LinuxErrno; +use constants::LinuxErrno; +use constants::{AlienResult, AT_FDCWD}; +use core::cmp::min; +use gmanager::ManagerError; +use log::{info, warn}; use syscall_table::syscall_func; +use vfs::kfile::KernelFile; use vfscore::path::VfsPath; use vfscore::utils::{VfsFileStat, VfsFsStat, VfsNodeType, VfsRenameFlag}; @@ -36,16 +35,11 @@ pub fn sys_mount( "mount special:{:?},dir:{:?},fs_type:{:?},flags:{:?},data:{:?}", source, dir, fs_type, flags, data ); - let find = FS - .lock() - .iter() - .find(|(name, _)| name.eq(&&fs_type)) - .map(|(_, fs)| fs.clone()) - .ok_or(LinuxErrno::EINVAL)?; - let path = VfsPath::new(SYSTEM_ROOT_FS.get().unwrap().clone()); + let find = vfs::system_support_fs(&fs_type).ok_or(LinuxErrno::EINVAL)?; + let path = VfsPath::new(vfs::system_root_fs()); let fs_root = match find.fs_name() { name @ ("tmpfs" | "ramfs" | "fat32") => { - let fs = FS.lock().index(name).clone(); + let fs = vfs::system_support_fs(name).unwrap(); let dev = if name.eq("fat32") { let dev = path.join(source)?.open(None)?; Some(dev.inode()?) @@ -67,7 +61,7 @@ pub fn sys_umount(dir: *const u8) -> AlienResult { let process = current_task().unwrap(); let dir = process.transfer_str(dir); info!("umount dir:{:?}", dir); - let path = VfsPath::new(SYSTEM_ROOT_FS.get().unwrap().clone()); + let path = VfsPath::new(vfs::system_root_fs()); path.join(dir)?.umount()?; Ok(0) } diff --git a/kernel/src/fs/control.rs b/kernel/src/fs/control.rs index db28c4db..85ab8bbf 100644 --- a/kernel/src/fs/control.rs +++ b/kernel/src/fs/control.rs @@ -1,11 +1,11 @@ -use crate::config::AT_FDCWD; -use crate::error::AlienResult; use crate::fs::user_path_at; use crate::task::current_task; -use crate::timer::TimeSpec; -use pconst::io::{FaccessatFlags, FaccessatMode, Fcntl64Cmd, OpenFlags, TeletypeCommand}; -use pconst::LinuxErrno; +use constants::io::{FaccessatFlags, FaccessatMode, Fcntl64Cmd, OpenFlags, TeletypeCommand}; +use constants::LinuxErrno; +use constants::{AlienResult, AT_FDCWD}; +use log::{info, warn}; use syscall_table::syscall_func; +use timer::TimeSpec; use vfscore::utils::*; const FD_CLOEXEC: usize = 1; diff --git a/kernel/src/fs/ext.rs b/kernel/src/fs/ext.rs index a3ba61e9..601c1de6 100644 --- a/kernel/src/fs/ext.rs +++ b/kernel/src/fs/ext.rs @@ -1,9 +1,11 @@ +use crate::fs::user_path_at; +use crate::task::current_task; +use constants::AlienResult; +use constants::{LinuxErrno, AT_FDCWD}; use core::cmp::min; -use pconst::LinuxErrno; +use syscall_table::syscall_func; use vfscore::path::VfsPath; -use crate::{config::AT_FDCWD, error::AlienResult, fs::user_path_at, task::current_task}; - /// 一个系统调用,用于设置文件的 扩展属性(xattrs, Extended Attributes)。 /// /// 扩展属性(xattrs)提供了一个机制用来将一个(键, 值)对永久地关联到文件,让现有的文件系统得以支持在原始设计中未提供的功能。扩展属性是文件系统不可知论者, diff --git a/kernel/src/fs/file.rs b/kernel/src/fs/file.rs deleted file mode 100644 index ab0304a3..00000000 --- a/kernel/src/fs/file.rs +++ /dev/null @@ -1,278 +0,0 @@ -pub use kernel_file::{File, KernelFile}; -use pconst::io::DirentType; -use vfscore::utils::VfsNodeType; - -mod kernel_file { - use super::vfsnodetype2dirent64; - use crate::error::AlienResult; - use crate::ksync::Mutex; - use alloc::sync::Arc; - use core::fmt::{Debug, Formatter}; - use downcast_rs::{impl_downcast, DowncastSync}; - use pconst::io::{Dirent64, OpenFlags, PollEvents, SeekFrom}; - use pconst::LinuxErrno; - use vfscore::dentry::VfsDentry; - use vfscore::error::VfsError; - use vfscore::inode::VfsInode; - use vfscore::path::VfsPath; - use vfscore::utils::{VfsFileStat, VfsPollEvents}; - pub struct KernelFile { - pos: Mutex, - open_flag: Mutex, - dentry: Arc, - } - - impl Debug for KernelFile { - fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { - f.debug_struct("KernelFile") - .field("pos", &self.pos) - .field("open_flag", &self.open_flag) - .field("name", &self.dentry.name()) - .finish() - } - } - - impl KernelFile { - pub fn new(dentry: Arc, open_flag: OpenFlags) -> Self { - let pos = if open_flag.contains(OpenFlags::O_APPEND) { - dentry.inode().unwrap().get_attr().unwrap().st_size - } else { - 0 - }; - Self { - pos: Mutex::new(pos), - open_flag: Mutex::new(open_flag), - dentry, - } - } - } - - pub trait File: DowncastSync + Debug { - fn read(&self, buf: &mut [u8]) -> AlienResult; - fn write(&self, buf: &[u8]) -> AlienResult; - fn read_at(&self, _offset: u64, _buf: &mut [u8]) -> AlienResult { - Err(LinuxErrno::ENOSYS) - } - fn write_at(&self, _offset: u64, _buf: &[u8]) -> AlienResult { - Err(LinuxErrno::ENOSYS) - } - fn flush(&self) -> AlienResult<()> { - Ok(()) - } - fn fsync(&self) -> AlienResult<()> { - Ok(()) - } - fn seek(&self, pos: SeekFrom) -> AlienResult; - /// Gets the file attributes. - fn get_attr(&self) -> AlienResult; - fn ioctl(&self, _cmd: u32, _arg: usize) -> AlienResult { - Err(LinuxErrno::ENOSYS) - } - fn set_open_flag(&self, _flag: OpenFlags) {} - fn get_open_flag(&self) -> OpenFlags { - OpenFlags::O_RDONLY - } - fn dentry(&self) -> Arc; - fn inode(&self) -> Arc; - fn readdir(&self, _buf: &mut [u8]) -> AlienResult { - Err(LinuxErrno::ENOSYS) - } - fn truncate(&self, _len: u64) -> AlienResult<()> { - Err(LinuxErrno::ENOSYS) - } - fn is_readable(&self) -> bool; - fn is_writable(&self) -> bool; - fn is_append(&self) -> bool; - fn poll(&self, _event: PollEvents) -> AlienResult { - Err(LinuxErrno::ENOSYS) - } - } - - impl_downcast!(sync File); - - // todo! permission check - impl File for KernelFile { - fn read(&self, buf: &mut [u8]) -> AlienResult { - if buf.len() == 0 { - return Ok(0); - } - // warn!("[read] is_interrupt_enable:{}",is_interrupt_enable()); - let pos = *self.pos.lock(); - // warn!("[read] is_interrupt_enable:{}",is_interrupt_enable()); - let read = self.read_at(pos, buf)?; - *self.pos.lock() += read as u64; - Ok(read) - } - fn write(&self, buf: &[u8]) -> AlienResult { - if buf.len() == 0 { - return Ok(0); - } - let mut pos = self.pos.lock(); - let write = self.write_at(*pos, buf)?; - *pos += write as u64; - Ok(write) - } - fn read_at(&self, offset: u64, buf: &mut [u8]) -> AlienResult { - if buf.len() == 0 { - return Ok(0); - } - let open_flag = self.open_flag.lock(); - if !open_flag.contains(OpenFlags::O_RDONLY) && !open_flag.contains(OpenFlags::O_RDWR) { - return Err(LinuxErrno::EPERM); - } - drop(open_flag); - let inode = self.dentry.inode()?; - let read = inode.read_at(offset, buf)?; - Ok(read) - } - - fn write_at(&self, _offset: u64, buf: &[u8]) -> AlienResult { - if buf.len() == 0 { - return Ok(0); - } - let open_flag = self.open_flag.lock(); - if !open_flag.contains(OpenFlags::O_WRONLY) && !open_flag.contains(OpenFlags::O_RDWR) { - return Err(LinuxErrno::EPERM); - } - let inode = self.dentry.inode()?; - let write = inode.write_at(_offset, buf)?; - Ok(write) - } - - fn flush(&self) -> AlienResult<()> { - let open_flag = self.open_flag.lock(); - if !open_flag.contains(OpenFlags::O_WRONLY) & !open_flag.contains(OpenFlags::O_RDWR) { - return Err(LinuxErrno::EPERM); - } - let inode = self.dentry.inode()?; - inode.flush()?; - Ok(()) - } - - fn fsync(&self) -> AlienResult<()> { - let open_flag = self.open_flag.lock(); - if !open_flag.contains(OpenFlags::O_WRONLY) && !open_flag.contains(OpenFlags::O_RDWR) { - return Err(LinuxErrno::EPERM); - } - let inode = self.dentry.inode()?; - inode.fsync()?; - Ok(()) - } - - // check for special file - fn seek(&self, pos: SeekFrom) -> AlienResult { - let mut spos = self.pos.lock(); - let size = self.get_attr()?.st_size; - let new_offset = match pos { - SeekFrom::Start(pos) => Some(pos), - SeekFrom::Current(off) => spos.checked_add_signed(off), - SeekFrom::End(off) => size.checked_add_signed(off), - } - .ok_or_else(|| VfsError::Invalid)?; - *spos = new_offset; - Ok(new_offset) - } - - /// Gets the file attributes. - fn get_attr(&self) -> AlienResult { - self.dentry.inode()?.get_attr().map_err(Into::into) - } - - fn ioctl(&self, _cmd: u32, _arg: usize) -> AlienResult { - let inode = self.dentry.inode().unwrap(); - inode.ioctl(_cmd, _arg).map_err(Into::into) - } - - fn set_open_flag(&self, flag: OpenFlags) { - *self.open_flag.lock() = flag; - } - - fn get_open_flag(&self) -> OpenFlags { - *self.open_flag.lock() - } - fn dentry(&self) -> Arc { - self.dentry.clone() - } - fn inode(&self) -> Arc { - self.dentry.inode().unwrap() - } - fn readdir(&self, buf: &mut [u8]) -> AlienResult { - let inode = self.inode(); - let mut pos = self.pos.lock(); - let mut count = 0; - let mut ptr = buf.as_mut_ptr(); - loop { - let dirent = inode.readdir(*pos as usize).map_err(|e| { - *pos = 0; - e - })?; - match dirent { - Some(d) => { - let dirent64 = - Dirent64::new(&d.name, d.ino, *pos as i64, vfsnodetype2dirent64(d.ty)); - if count + dirent64.len() <= buf.len() { - let dirent_ptr = unsafe { &mut *(ptr as *mut Dirent64) }; - *dirent_ptr = dirent64; - let name_ptr = dirent_ptr.name.as_mut_ptr(); - unsafe { - let mut name = d.name.clone(); - name.push('\0'); - let len = name.len(); - name_ptr.copy_from(name.as_ptr(), len); - ptr = ptr.add(dirent_ptr.len()); - } - count += dirent_ptr.len(); - } else { - break; - } // Buf is small - } - None => { - break; - } // EOF - } - *pos += 1; - } - Ok(count) - } - fn truncate(&self, len: u64) -> AlienResult<()> { - let open_flag = self.open_flag.lock(); - if !open_flag.contains(OpenFlags::O_WRONLY) & !open_flag.contains(OpenFlags::O_RDWR) { - return Err(LinuxErrno::EINVAL); - } - let dt = self.dentry(); - VfsPath::new(dt).truncate(len).map_err(Into::into) - } - fn is_readable(&self) -> bool { - let open_flag = self.open_flag.lock(); - open_flag.contains(OpenFlags::O_RDONLY) | open_flag.contains(OpenFlags::O_RDWR) - } - fn is_writable(&self) -> bool { - let open_flag = self.open_flag.lock(); - open_flag.contains(OpenFlags::O_WRONLY) | open_flag.contains(OpenFlags::O_RDWR) - } - - fn is_append(&self) -> bool { - let open_flag = self.open_flag.lock(); - open_flag.contains(OpenFlags::O_APPEND) - } - - fn poll(&self, _event: PollEvents) -> AlienResult { - let inode = self.dentry.inode()?; - let res = inode - .poll(VfsPollEvents::from_bits_truncate(_event.bits())) - .map(|e| PollEvents::from_bits_truncate(e.bits())); - res.map_err(Into::into) - } - } -} - -fn vfsnodetype2dirent64(ty: VfsNodeType) -> DirentType { - DirentType::from_u8(ty as u8) -} - -impl Drop for KernelFile { - fn drop(&mut self) { - let _ = self.flush(); - let _ = self.fsync(); - } -} diff --git a/kernel/src/fs/link.rs b/kernel/src/fs/link.rs index 832f7534..7f45274e 100644 --- a/kernel/src/fs/link.rs +++ b/kernel/src/fs/link.rs @@ -1,9 +1,10 @@ use alloc::vec; -use pconst::io::{LinkFlags, UnlinkatFlags}; +use constants::io::{LinkFlags, UnlinkatFlags}; +use log::{info, warn}; use syscall_table::syscall_func; -use crate::{error::AlienResult, fs::user_path_at, task::current_task}; - +use crate::{fs::user_path_at, task::current_task}; +use constants::AlienResult; /// 一个系统调用,用于创建相对于一个目录某位置处的一个文件的(硬)链接。 /// /// 当传入的 `old_name` 是一个相对地址时,那么 `old_name` 会被解析成基于文件描述符 `old_fd` diff --git a/kernel/src/fs/mod.rs b/kernel/src/fs/mod.rs index 0b1dd25d..fdb5b8d4 100644 --- a/kernel/src/fs/mod.rs +++ b/kernel/src/fs/mod.rs @@ -1,154 +1,18 @@ -use crate::config::AT_FDCWD; -use crate::error::AlienResult; -use crate::fs::dev::{init_devfs, DevFsProviderImpl}; -use crate::fs::proc::init_procfs; -use crate::fs::ram::init_ramfs; -use crate::fs::sys::init_sysfs; -use crate::ipc::init_pipefs; -use crate::ksync::Mutex; -use crate::print::console::Stdout; -use crate::task::{current_task, FsContext}; -use alloc::collections::BTreeMap; -use alloc::string::{String, ToString}; -use alloc::sync::Arc; -use alloc::vec; -use alloc::vec::Vec; -pub use basic::*; -pub use control::*; -use core::ops::Index; -use dynfs::DynFsKernelProvider; -use fat_vfs::FatFsProvider; -use pconst::io::InodeMode; -use pconst::LinuxErrno; -pub use poll::*; -use riscv::register::sstatus::FS; -pub use select::*; -use spin::{Lazy, Once}; -pub use stdio::*; -use vfscore::dentry::VfsDentry; -use vfscore::fstype::VfsFsType; -use vfscore::path::{SysContext, VfsPath}; -use vfscore::utils::{VfsInodeMode, VfsNodeType, VfsTimeSpec}; - -pub mod stdio; - pub mod basic; pub mod control; -pub mod dev; pub mod ext; -pub mod file; pub mod link; pub mod poll; -pub mod proc; -pub mod ram; pub mod select; -pub mod sys; - -pub static FS: Lazy>>> = - Lazy::new(|| Mutex::new(BTreeMap::new())); - -pub static SYSTEM_ROOT_FS: Once> = Once::new(); - -type SysFs = dynfs::DynFs>; -type ProcFs = dynfs::DynFs>; -type RamFs = ramfs::RamFs>; -type DevFs = devfs::DevFs>; -type TmpFs = ramfs::RamFs>; -type PipeFs = dynfs::DynFs>; -type FatFs = fat_vfs::FatFs>; - -#[derive(Clone)] -pub struct CommonFsProviderImpl; - -impl DynFsKernelProvider for CommonFsProviderImpl { - fn current_time(&self) -> VfsTimeSpec { - VfsTimeSpec::new(0, 0) - } -} - -impl ramfs::RamFsProvider for CommonFsProviderImpl { - fn current_time(&self) -> VfsTimeSpec { - DynFsKernelProvider::current_time(self) - } -} - -impl FatFsProvider for CommonFsProviderImpl { - fn current_time(&self) -> VfsTimeSpec { - DynFsKernelProvider::current_time(self) - } -} - -fn register_all_fs() { - let procfs = Arc::new(ProcFs::new(CommonFsProviderImpl, "procfs")); - let sysfs = Arc::new(SysFs::new(CommonFsProviderImpl, "sysfs")); - let ramfs = Arc::new(RamFs::new(CommonFsProviderImpl)); - let devfs = Arc::new(DevFs::new(DevFsProviderImpl)); - let tmpfs = Arc::new(TmpFs::new(CommonFsProviderImpl)); - let pipefs = Arc::new(PipeFs::new(CommonFsProviderImpl, "pipefs")); - - let fatfs = Arc::new(FatFs::new(CommonFsProviderImpl)); - - FS.lock().insert("procfs".to_string(), procfs); - FS.lock().insert("sysfs".to_string(), sysfs); - FS.lock().insert("ramfs".to_string(), ramfs); - FS.lock().insert("devfs".to_string(), devfs); - FS.lock().insert("tmpfs".to_string(), tmpfs); - FS.lock().insert("pipefs".to_string(), pipefs); - FS.lock().insert("fatfs".to_string(), fatfs); - println!("register fs success"); -} - -/// Init the filesystem -pub fn init_filesystem() -> AlienResult<()> { - register_all_fs(); - let ramfs_root = init_ramfs(FS.lock().index("ramfs").clone()); - let procfs_root = init_procfs(FS.lock().index("procfs").clone()); - let devfs_root = init_devfs(FS.lock().index("devfs").clone()); - let sysfs_root = init_sysfs(FS.lock().index("sysfs").clone()); - let tmpfs_root = FS - .lock() - .index("tmpfs") - .clone() - .i_mount(0, "/tmp", None, &[])?; - - init_pipefs(FS.lock().index("pipefs").clone()); - - let path = VfsPath::new(ramfs_root.clone()); - path.join("proc")?.mount(procfs_root, 0)?; - path.join("sys")?.mount(sysfs_root, 0)?; - path.join("dev")?.mount(devfs_root, 0)?; - path.join("tmp")?.mount(tmpfs_root.clone(), 0)?; - - let shm_ramfs = FS - .lock() - .index("ramfs") - .clone() - .i_mount(0, "/dev/shm", None, &[])?; - path.join("dev/shm")?.mount(shm_ramfs, 0)?; - - let fatfs = FS.lock().index("fatfs").clone(); - let blk_inode = path - .join("/dev/sda")? - .open(None) - .expect("open /dev/sda failed") - .inode()?; - let fat32_root = fatfs.i_mount(0, "/bin", Some(blk_inode), &[])?; - path.join("bin")?.mount(fat32_root, 0)?; - - vfscore::path::print_fs_tree(&mut VfsOutPut, ramfs_root.clone(), "".to_string(), false) - .unwrap(); - SYSTEM_ROOT_FS.call_once(|| ramfs_root); - println!("Init filesystem success"); - Ok(()) -} +pub mod stdio; -struct VfsOutPut; -impl core::fmt::Write for VfsOutPut { - fn write_str(&mut self, s: &str) -> core::fmt::Result { - Stdout.write_str(s).unwrap(); - Ok(()) - } -} +use crate::task::{current_task, FsContext}; +use alloc::vec::Vec; +use constants::io::InodeMode; +use constants::{AlienResult, LinuxErrno, AT_FDCWD}; +use log::info; +use vfscore::path::{SysContext, VfsPath}; +use vfscore::utils::{VfsInodeMode, VfsNodeType}; /// 地址解析函数,通过 `fd` 所指向的一个目录文件 和 相对于该目录文件的路径或绝对路径 `path` 解析出某目标文件的绝对路径。 /// @@ -171,7 +35,7 @@ fn user_path_at(fd: isize, path: &str) -> AlienResult { VfsPath::new(file.dentry()).join(path) } } else { - VfsPath::new(SYSTEM_ROOT_FS.get().unwrap().clone()).join(path) + VfsPath::new(vfs::system_root_fs()).join(path) }; res.map_err(|e| e.into()) } @@ -181,12 +45,10 @@ pub fn read_all(file_name: &str, buf: &mut Vec) -> bool { // let cwd = if task.is_some() { // task.unwrap().access_inner().cwd().cwd // } else { - // SYSTEM_ROOT_FS.get().unwrap().clone() + // vfs::system_root_fs() // }; let path = if task.is_none() { - VfsPath::new(SYSTEM_ROOT_FS.get().unwrap().clone()) - .join(file_name) - .unwrap() + VfsPath::new(vfs::system_root_fs()).join(file_name).unwrap() } else { user_path_at(AT_FDCWD, file_name).unwrap() }; @@ -204,7 +66,7 @@ pub fn read_all(file_name: &str, buf: &mut Vec) -> bool { let size = dentry.inode().unwrap().get_attr().unwrap().st_size; let mut offset = 0; while offset < size { - let mut tmp = vec![0; 512usize]; + let mut tmp = [0; 512]; let res = dentry.inode().unwrap().read_at(offset, &mut tmp).unwrap(); offset += res as u64; buf.extend_from_slice(&tmp); diff --git a/kernel/src/fs/poll.rs b/kernel/src/fs/poll.rs index 213ba10c..3be2987d 100644 --- a/kernel/src/fs/poll.rs +++ b/kernel/src/fs/poll.rs @@ -1,10 +1,11 @@ -use crate::error::AlienResult; use crate::task::{current_task, do_suspend}; -use crate::timer::TimeSpec; use alloc::vec::Vec; -use pconst::io::{PollEvents, PollFd}; -use pconst::LinuxErrno; +use constants::io::{PollEvents, PollFd}; +use constants::AlienResult; +use constants::LinuxErrno; +use log::{info, warn}; use syscall_table::syscall_func; +use timer::TimeSpec; /// 一个系统调用,用于在一些文件描述符上等待事件。作用与 [`pselect6`] 相似。 /// @@ -54,18 +55,6 @@ pub fn ppoll(fds_ptr: usize, nfds: usize, time: usize, _mask: usize) -> AlienRes for pfd in fds.iter_mut() { if let Some(file) = task.get_file(pfd.fd as usize) { let event = file.poll(pfd.events)?; - // if file.in_exceptional_conditions() { - // event |= PollEvents::ERR; - // } - // if file.is_hang_up() { - // event |= PollEvents::HUP; - // } - // if pfd.events.contains(PollEvents::IN) && file.ready_to_read() { - // event |= PollEvents::IN; - // } - // if pfd.events.contains(PollEvents::OUT) && file.ready_to_write() { - // event |= PollEvents::OUT; - // } if !event.is_empty() { res += 1; } diff --git a/kernel/src/fs/proc/mem.rs b/kernel/src/fs/proc/mem.rs deleted file mode 100644 index 4a777ee6..00000000 --- a/kernel/src/fs/proc/mem.rs +++ /dev/null @@ -1,42 +0,0 @@ -use crate::config::MEMINFO; -use alloc::sync::Arc; -use core::cmp::min; -use vfscore::error::VfsError; -use vfscore::file::VfsFile; -use vfscore::inode::{InodeAttr, VfsInode}; -use vfscore::superblock::VfsSuperBlock; -use vfscore::utils::{VfsFileStat, VfsNodePerm, VfsNodeType}; -use vfscore::VfsResult; - -pub struct MemInfo; - -impl VfsFile for MemInfo { - fn read_at(&self, offset: u64, buf: &mut [u8]) -> VfsResult { - let min_len = min(buf.len(), MEMINFO.as_bytes().len() - offset as usize); - buf[..min_len].copy_from_slice(&MEMINFO.as_bytes()[..min_len]); - Ok(min_len) - } -} - -impl VfsInode for MemInfo { - fn get_super_block(&self) -> VfsResult> { - Err(VfsError::NoSys) - } - fn node_perm(&self) -> VfsNodePerm { - VfsNodePerm::empty() - } - fn set_attr(&self, _attr: InodeAttr) -> VfsResult<()> { - Ok(()) - } - - fn get_attr(&self) -> VfsResult { - Ok(VfsFileStat { - st_size: MEMINFO.as_bytes().len() as u64, - ..Default::default() - }) - } - - fn inode_type(&self) -> VfsNodeType { - VfsNodeType::File - } -} diff --git a/kernel/src/fs/proc/process.rs b/kernel/src/fs/proc/process.rs deleted file mode 100644 index 43e2033c..00000000 --- a/kernel/src/fs/proc/process.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::error::AlienResult; -use crate::task::current_task; -use crate::timer::TimeFromFreq; -use pconst::sys::{Rusage, RusageFlag, TimeVal}; -use pconst::LinuxErrno; - -/// (待完善)一个系统调用,用于获取对系统资源的使用量信息。获取的信息将保存到`usage`所指向的[`Rusage`]结构中。 -/// -/// 可以通过`who`修改获取信息的对象,包括: -/// + `RUSAGE_SELF`: 返回调用该函数进程的资源用量统计,会返回该进程下所有线程的资源用量之和; -/// + `RUSAGE_CHILDREN`: 返回调用该函数进程所有已终止且被回收子进程的资源用量统计. -/// + `RUSAGE_THREAD`: 返回调用该函数线程的资源用量统计。 -/// -/// 在Alien中,目前仅支持`RUSAGE_SELF`。且返回的信息目前仅有[`Rusage`]下的`ru_utime`和`ru_stime`字段。 -/// -/// 正确执行后返回0。 -#[syscall_func(165)] -pub fn getrusage(who: isize, usage: usize) -> AlienResult { - let who = RusageFlag::try_from(who).map_err(|_| LinuxErrno::EINVAL)?; - info!("getrusage: who: {:?}, usage: {}", who, usage); - let task = current_task().unwrap(); - let static_info = task.access_inner().statistical_data().clone(); - let mut task_usage = Rusage::new(); - task_usage.ru_utime = TimeVal::from_freq(static_info.tms_utime); - task_usage.ru_stime = TimeVal::from_freq(static_info.tms_stime); - task.access_inner() - .copy_to_user(&task_usage, usage as *mut Rusage); - Ok(0) -} diff --git a/kernel/src/fs/select.rs b/kernel/src/fs/select.rs index 4aff56a5..e2813a7d 100644 --- a/kernel/src/fs/select.rs +++ b/kernel/src/fs/select.rs @@ -1,14 +1,15 @@ -use crate::config::MAX_FD_NUM; -use crate::error::AlienResult; use crate::task::{current_task, do_suspend}; -use crate::timer::TimeSpec; use alloc::vec::Vec; use bit_field::BitField; +use config::MAX_FD_NUM; +use constants::io::PollEvents; +use constants::signal::{SignalNumber, SimpleBitSet}; +use constants::AlienResult; +use constants::LinuxErrno; use core::cmp::min; -use pconst::io::PollEvents; -use pconst::signal::{SignalNumber, SimpleBitSet}; -use pconst::LinuxErrno; +use log::{info, trace}; use syscall_table::syscall_func; +use timer::TimeSpec; /// 一个系统调用,实现 IO 端口的复用。一般用于用户程序的一段循环体中, /// 用于周期性检测一组关注的文件描述符集里是否有需要进行处理的IO事件发生。 diff --git a/kernel/src/fs/stdio.rs b/kernel/src/fs/stdio.rs index aa2a7ce0..ef4f1f9f 100644 --- a/kernel/src/fs/stdio.rs +++ b/kernel/src/fs/stdio.rs @@ -1,26 +1,21 @@ -use crate::fs::file::KernelFile; -use crate::fs::SYSTEM_ROOT_FS; use alloc::sync::Arc; -use pconst::io::OpenFlags; +use constants::io::OpenFlags; use spin::Lazy; +use vfs::kfile::KernelFile; use vfscore::path::VfsPath; type Stdin = KernelFile; type Stdout = KernelFile; pub static STDIN: Lazy> = Lazy::new(|| { - let path = VfsPath::new(SYSTEM_ROOT_FS.get().unwrap().clone()) - .join("dev/tty") - .unwrap(); + let path = VfsPath::new(vfs::system_root_fs()).join("dev/tty").unwrap(); let dentry = path.open(None).unwrap(); let file = KernelFile::new(dentry, OpenFlags::O_RDONLY); Arc::new(file) }); pub static STDOUT: Lazy> = Lazy::new(|| { - let path = VfsPath::new(SYSTEM_ROOT_FS.get().unwrap().clone()) - .join("dev/tty") - .unwrap(); + let path = VfsPath::new(vfs::system_root_fs()).join("dev/tty").unwrap(); let dentry = path.open(None).unwrap(); let file = KernelFile::new(dentry, OpenFlags::O_WRONLY); Arc::new(file) diff --git a/kernel/src/fs/sys/cpu.rs b/kernel/src/fs/sys/cpu.rs deleted file mode 100644 index 2ab92f03..00000000 --- a/kernel/src/fs/sys/cpu.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::task::current_task; - -/// (待实现)一个系统调用,设置进程调度的参数。目前直接返回0。 -#[syscall_func(118)] -pub fn sched_setparam() -> isize { - 0 -} - -/// (待实现)一个系统调用,获取进程调度的参数。目前直接返回0。 -#[syscall_func(121)] -pub fn sched_getparam() -> isize { - 0 -} - -/// (待实现)一个系统调用,设置进程CPU亲和力(位掩码),使进程绑定在某一个或几个CPU上运行,避免在CPU之间来回切换,从而提高该进程的实时性能。目前直接返回0。 -#[syscall_func(122)] -pub fn sched_setaffinity() -> isize { - 0 -} - -/// (待完善)一个系统调用,获取某进程对CPU的亲和力(位掩码)。当前进程的cpu亲和力将保存到`mask`所指向的位置。函数执行成功后返回8。 -#[syscall_func(123)] -pub fn sched_getaffinity(pid: usize, size: usize, mask: usize) -> isize { - warn!( - "sched_getaffinity: pid: {}, size: {}, mask: {}", - pid, size, mask - ); - assert_eq!(pid, 0); - let task = current_task().unwrap(); - let res = task.access_inner().cpu_affinity; - let mask = task.access_inner().transfer_raw_ptr_mut(mask as *mut usize); - *mask = res; - 8 -} - -/// (待实现)一个系统调用,用于获取当前CPU的调度策略。目前直接返回0。 -#[syscall_func(120)] -pub fn sched_getscheduler(pid: usize) -> isize { - assert_eq!(pid, 0); - // let task = current_task().unwrap(); - 0 -} - -/// (待实现)一个系统调用,用于设置当前CPU的调度策略。目前直接返回0。 -#[syscall_func(119)] -pub fn sched_setscheduler(_pid: usize, _policy: usize, _param: usize) -> isize { - 0 -} diff --git a/kernel/src/fs/sys/info.rs b/kernel/src/fs/sys/info.rs deleted file mode 100644 index 40acfcec..00000000 --- a/kernel/src/fs/sys/info.rs +++ /dev/null @@ -1,87 +0,0 @@ -use crate::task::current_task; -use crate::timer::get_time_ms; -use crate::MACHINE_INFO; -use core::cmp::min; -use pconst::sys::{Sysinfo, SyslogAction}; -use pconst::LinuxErrno; - -const LOG_BUF_LEN: usize = 4096; -const LOG: &str = r" -[ 0.000000] Linux version 5.10.0-7-riscv64 (debian-kernel@lists.debian.org) (gcc-10 (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for Debian) 2.35.2) #1 SMP Debian 5.10.40-1 (2021-05-28) -"; - -/// (待完善)一个系统调用函数,用于对内核消息环状缓冲区进行操作。 -/// -/// + `log_type`: 指明操作的类型,具体值可见[`SyslogAction`]; -/// + `buf`: 指明读取消息时,消息要保存到的位置; -/// + `len`: 指明具体操作时,对于消息读取的长度限制。真正的读取消息的长度将取决于就传入的`len`和`LOG_BUF_LEN`的最小值。 -/// -/// 当`log_type`为`READ`、`ReadAll`、`ReadClear`三种flag,正确执行后返回读取消息的长度; -/// 当`log_type`为`Unknown`时,会返回`EINVAL`;当`log_type`为`OPEN`或`CLOSE`时,函数不进行任何操作后返回0。 -/// 目前Alien仅支持上述`log_type`值,其余值都将不进行任何操作后返回0。 -/// -/// Reference: [syslog](https://man7.org/linux/man-pages/man2/syslog.2.html) -#[syscall_func(116)] -pub fn syslog(log_type: u32, buf: usize, len: usize) -> isize { - let log_type = SyslogAction::try_from(log_type); - if log_type.is_err() { - return LinuxErrno::EINVAL as isize; - } - match log_type.unwrap() { - SyslogAction::OPEN | SyslogAction::CLOSE => 0, - SyslogAction::READ | SyslogAction::ReadAll | SyslogAction::ReadClear => { - let min_len = min(len, LOG_BUF_LEN); - let task = current_task().unwrap(); - // the buf may be not valid, so we need to check it -- > sbrk heap - let mut buf = task.transfer_buffer(buf as *mut u8, min_len); - let log = LOG.as_bytes(); - let mut offset = 0; - buf.iter_mut().for_each(|buf| { - let copy_len = min(log.len() - offset, buf.len()); - buf[..copy_len].copy_from_slice(&log[offset..offset + copy_len]); - offset += copy_len; - }); - offset as isize - } - SyslogAction::Unknown => LinuxErrno::EINVAL as isize, - _ => 0, - } -} - -extern "C" { - fn ekernel(); -} - -/// 一个系统调用函数,用于获取系统相关信息。信息包括系统的自启动经过的时间、对于内存的使用情况、共享存储区的大小、 -/// 缓冲区与交换区的大小、当前进程数目等,具体可见[`Sysinfo`]。获取到的信息将保存到`dst_info`所指向的[`Sysinfo`]结构处。 -/// -/// 目前功能还有待完善。正确执行后返回0。 -#[syscall_func(179)] -pub fn sys_info(dst_info: usize) -> isize { - const LINUX_SYSINFO_LOADS_SCALE: usize = 65536; - let task = current_task().unwrap(); - // calculate the task number - let task_number = 10; // fake task number - let memory_info = MACHINE_INFO.get().as_ref().unwrap().memory.clone(); - let info = Sysinfo { - uptime: (get_time_ms() / 1000) as usize, - loads: [ - task_number * LINUX_SYSINFO_LOADS_SCALE / 60, - task_number * LINUX_SYSINFO_LOADS_SCALE / 300, - task_number * LINUX_SYSINFO_LOADS_SCALE / 900, - ], - totalram: memory_info.end - memory_info.start, - freeram: memory_info.end - ekernel as usize, - sharedram: 0, - bufferram: 0, - totalswap: 0, - freeswap: 0, - procs: task_number as u16, - totalhigh: 0, - freehigh: 0, - mem_unit: 1, - }; - task.access_inner() - .copy_to_user(&info, dst_info as *mut Sysinfo); - 0 -} diff --git a/kernel/src/gui.rs b/kernel/src/gui.rs index aa3e3b21..1ec22685 100644 --- a/kernel/src/gui.rs +++ b/kernel/src/gui.rs @@ -1,10 +1,8 @@ //! GUI 相关的系统调用 +use crate::task::current_task; use page_table::addr::{align_up_4k, PhysAddr, VirtAddr}; -use syscall_table::syscall_func; - -use crate::device::GPU_DEVICE; -use crate::task::current_task; +use devices::{GPU_DEVICE, KEYBOARD_INPUT_DEVICE, MOUSE_INPUT_DEVICE}; const FB_VADDR: usize = 0x1000_0000; @@ -33,3 +31,47 @@ pub fn sys_framebuffer_flush() -> isize { GPU_DEVICE.get().unwrap().flush(); 0 } + + +/// 一个系统调用函数,用于获取鼠标和键盘事件。 +/// +/// `sys_event_get`会将获取到的事件将保存在event_buf所指向的内存位置处, +/// 此次允许获取到的事件的最大值(即event_buf)的大小由len指出。 +/// +/// 函数将返回成功获取到的事件个数。 +/// +#[syscall_func(2002)] +pub fn sys_event_get(event_buf: *mut u64, len: usize) -> isize { + let task = current_task().unwrap(); + let user_buffer = task.transfer_buffer(event_buf, len); + let mut count = 0; + for buf in user_buffer { + let mut index = 0; + let len = buf.len(); + while index < len { + let event = read_event(); + if event == 0 { + break; + } + buf[index] = event; + index += 1; + count += 1; + } + } + count +} + +fn read_event() -> u64 { + let (keyboard, mouse) = { + let kb = KEYBOARD_INPUT_DEVICE.get().unwrap(); + let mouse = MOUSE_INPUT_DEVICE.get().unwrap(); + (kb, mouse) + }; + if !keyboard.is_empty() { + keyboard.read_event_with_block() + } else if !mouse.is_empty() { + mouse.read_event_with_block() + } else { + 0 + } +} diff --git a/kernel/src/interrupt/mod.rs b/kernel/src/interrupt/mod.rs deleted file mode 100644 index e5f58411..00000000 --- a/kernel/src/interrupt/mod.rs +++ /dev/null @@ -1,63 +0,0 @@ -use alloc::collections::BTreeMap; -use alloc::sync::Arc; -use cfg_if::cfg_if; -use spin::Once; - -use crate::ksync::Mutex; -pub use ext_interrupt::external_interrupt_handler; -use plic::{Mode, PLIC}; - -use crate::arch::hart_id; -use crate::config::CPU_NUM; -use crate::MACHINE_INFO; - -mod ext_interrupt; -pub mod record; -mod timer; - -pub static PLIC: Once> = Once::new(); - -pub static DEVICE_TABLE: Mutex>> = Mutex::new(BTreeMap::new()); - -pub trait DeviceBase: Sync + Send { - fn hand_irq(&self); -} - -pub fn init_plic() { - let machine = MACHINE_INFO.get().unwrap(); - let addr = machine.plic.start; - - cfg_if! { - if #[cfg(feature = "qemu")]{ - let privileges = [2;CPU_NUM]; - let plic = PLIC::new(addr, privileges); - PLIC.call_once(|| plic); - println!("Init qemu plic success"); - }else if #[cfg(any(feature = "vf2", feature = "hifive"))]{ - let mut privileges = [2u8;CPU_NUM]; - // core 0 don't have S mode - privileges[0] = 1; - println!("PLIC context: {:?}",privileges); - let plic = PLIC::new(addr, privileges); - PLIC.call_once(|| plic); - println!("Init hifive or vf2 plic success"); - } - } -} - -/// Register a device to PLIC. -pub fn register_device_to_plic(irq: usize, device: Arc) { - let mut table = DEVICE_TABLE.lock(); - table.insert(irq, device); - let hard_id = hart_id(); - println!( - "plic enable irq {} for hart {}, priority {}", - irq, hard_id, 1 - ); - let plic = PLIC.get().unwrap(); - plic.set_threshold(hard_id as u32, Mode::Machine, 1); - plic.set_threshold(hard_id as u32, Mode::Supervisor, 0); - plic.complete(hard_id as u32, Mode::Supervisor, irq as u32); - plic.set_priority(irq as u32, 1); - plic.enable(hard_id as u32, Mode::Supervisor, irq as u32); -} diff --git a/kernel/src/interrupt/timer.rs b/kernel/src/interrupt/timer.rs deleted file mode 100644 index 8b137891..00000000 --- a/kernel/src/interrupt/timer.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/kernel/src/ipc/futex.rs b/kernel/src/ipc/futex.rs index 095be7ac..9b4c2b95 100644 --- a/kernel/src/ipc/futex.rs +++ b/kernel/src/ipc/futex.rs @@ -18,12 +18,12 @@ use alloc::vec; use alloc::vec::Vec; use core::cmp::min; -use crate::ksync::Mutex; +use ksync::Mutex; use smpscheduler::FifoTask; -use crate::error::{AlienError, AlienResult}; use crate::task::{Task, GLOBAL_TASK_MANAGER}; -use crate::timer::read_timer; +use constants::{AlienError, AlienResult}; +use timer::read_timer; /// 用于记录一个进程等待一个 futex 的相关信息 pub struct FutexWaiter { diff --git a/kernel/src/ipc/mod.rs b/kernel/src/ipc/mod.rs index 31b9409f..b46b73f4 100644 --- a/kernel/src/ipc/mod.rs +++ b/kernel/src/ipc/mod.rs @@ -9,20 +9,18 @@ use alloc::sync::Arc; use core::sync::atomic::{AtomicI32, Ordering}; use spin::Lazy; -use crate::error::AlienResult; -use crate::ksync::Mutex; -use pconst::ipc::{FutexOp, RobustList}; -use pconst::LinuxErrno; -pub use pipe::*; -pub use shm::*; -pub use signal::*; -use syscall_table::syscall_func; - -use crate::fs::sys_close; +use crate::fs::basic::sys_close; use crate::ipc::futex::{FutexWaitManager, FutexWaiter}; use crate::task::schedule::schedule; use crate::task::{current_task, TaskState}; -use crate::timer::TimeSpec; +use constants::ipc::{FutexOp, RobustList}; +use constants::AlienResult; +use constants::LinuxErrno; +use ksync::Mutex; +pub use pipe::*; +pub use shm::*; +pub use signal::*; +use timer::TimeSpec; pub mod futex; mod pipe; diff --git a/kernel/src/ipc/pipe.rs b/kernel/src/ipc/pipe.rs index 3191f199..9a43b809 100644 --- a/kernel/src/ipc/pipe.rs +++ b/kernel/src/ipc/pipe.rs @@ -9,26 +9,22 @@ //! [`pipe_read_is_hang_up`]、[`pipe_write_is_hang_up`]、[`pipe_ready_to_read`] //! 、[`pipe_ready_to_write`] 几个操作函数,即可快速的创建管道文件,并将其放入进程的文件描述 //! 符表中。 - -use crate::config::PIPE_BUF; -use crate::error::AlienResult; -use crate::fs::file::File; -use crate::fs::CommonFsProviderImpl; -use crate::ksync::Mutex; use crate::task::{current_task, do_suspend}; use alloc::string::{String, ToString}; use alloc::sync::{Arc, Weak}; use alloc::vec::Vec; +use config::PIPE_BUF; +use constants::io::{OpenFlags, PollEvents, SeekFrom}; +use constants::AlienResult; +use constants::LinuxErrno; use core::fmt::{Debug, Formatter}; use core::sync::atomic::AtomicUsize; -use dynfs::DynFsDirInode; -use pconst::io::{MountFlags, OpenFlags, PollEvents, SeekFrom}; -use pconst::LinuxErrno; -use spin::Once; +use ksync::Mutex; +use vfs::kfile::File; +use vfs::pipefs::{PipeFsDirInodeImpl, PIPE_FS_ROOT}; use vfscore::dentry::VfsDentry; use vfscore::error::VfsError; use vfscore::file::VfsFile; -use vfscore::fstype::VfsFsType; use vfscore::impl_common_inode_default; use vfscore::inode::{InodeAttr, VfsInode}; use vfscore::superblock::VfsSuperBlock; @@ -36,9 +32,6 @@ use vfscore::utils::VfsPollEvents; use vfscore::utils::*; use vfscore::VfsResult; -type PipeFsDirInodeImpl = DynFsDirInode>; -static PIPE_FS_ROOT: Once> = Once::new(); - static PIPE: AtomicUsize = AtomicUsize::new(0); /// 管道文件 @@ -71,13 +64,6 @@ impl PipeFile { } } -pub fn init_pipefs(fs: Arc) { - let root = fs - .i_mount(MountFlags::empty().bits(), "", None, &[]) - .unwrap(); - PIPE_FS_ROOT.call_once(|| root); -} - /// create a pipe file pub fn make_pipe_file() -> VfsResult<(Arc, Arc)> { let root = PIPE_FS_ROOT.get().unwrap(); diff --git a/kernel/src/ipc/shm.rs b/kernel/src/ipc/shm.rs index 319a067c..af61c1e0 100644 --- a/kernel/src/ipc/shm.rs +++ b/kernel/src/ipc/shm.rs @@ -6,19 +6,15 @@ //! 最后封装成 [`ShmMemory`] 结构。 //! use alloc::collections::btree_map::BTreeMap; -use alloc::vec::Vec; - +use constants::ipc::{ShmAtFlags, ShmCtlCmd, ShmGetFlags, IPC_PRIVATE}; +use constants::{AlienResult, LinuxErrno}; +use ksync::{Mutex, MutexGuard}; use page_table::addr::{align_down_4k, PhysAddr, VirtAddr}; -use page_table::table::PageSize; - -use crate::ksync::{Mutex, MutexGuard}; -use pconst::ipc::{ShmAtFlags, ShmCtlCmd, ShmGetFlags, IPC_PRIVATE}; -use pconst::LinuxErrno; use syscall_table::syscall_func; -use crate::config::FRAME_SIZE; -use crate::memory::{frames_alloc, FrameTracker}; use crate::task::current_task; +use config::FRAME_SIZE; +use mem::{alloc_frame_trackers, FrameTracker}; /// 共享内存被 Mutex 封装后的结构 #[derive(Debug)] @@ -33,7 +29,7 @@ pub struct ShmMemoryInner { /// 引用计数器 ref_count: usize, /// 共享内存数据部分 - pub frames: Vec, + pub frames: FrameTracker, /// 共享内存的状态 state: ShmMemoryState, } @@ -56,7 +52,7 @@ impl ShmInfo { impl ShmMemory { /// 创建新的共享内存 - pub fn new(frames: Vec) -> Self { + pub fn new(frames: FrameTracker) -> Self { Self { inner: Mutex::new(ShmMemoryInner { ref_count: 0, @@ -73,7 +69,7 @@ impl ShmMemory { /// 返回共享内存数据区的长度(字节数) pub fn len(&self) -> usize { - self.access_inner().frames.len() * FRAME_SIZE + self.access_inner().frames.len() } /// 引用计数器加一 @@ -95,11 +91,6 @@ impl ShmMemory { pub fn is_deleted(&self) -> bool { self.access_inner().state == ShmMemoryState::Deleted } - - /// 引用计数器减一 - pub fn dec_ref(&self) { - self.access_inner().ref_count -= 1; - } } /// 记录共享内存当前状态的结构 @@ -127,7 +118,7 @@ pub static SHM_MEMORY: Mutex> = Mutex::new(BTreeMap:: /// Reference: [shmget](https://man7.org/linux/man-pages/man2/shmget.2.html) #[syscall_func(194)] pub fn shmget(key: usize, size: usize, shmflg: u32) -> isize { - warn!( + info!( "shmget key:{},size:{},shmflg:{:?}", key, size, @@ -147,13 +138,13 @@ pub fn shmget(key: usize, size: usize, shmflg: u32) -> isize { } let flag = ShmGetFlags::from_bits_truncate(shmflg as i32); if flag.contains(ShmGetFlags::IPC_CREAT) { - warn!("create new share memory {}", key); + info!("create new share memory {}", key); // alloc frames - let frames = frames_alloc(align_down_4k(size) / FRAME_SIZE); - if frames.is_none() { - return LinuxErrno::ENOMEM as isize; - } - let frames = frames.unwrap(); + let frames = alloc_frame_trackers(align_down_4k(size) / FRAME_SIZE); + // if frames.is_none() { + // return LinuxErrno::ENOMEM as isize; + // } + // let frames = frames.unwrap(); let share_mem = ShmMemory::new(frames); shm_memory.insert(key, share_mem); return key as isize; @@ -175,7 +166,7 @@ pub fn shmget(key: usize, size: usize, shmflg: u32) -> isize { /// /// Reference: [shmat](https://www.man7.org/linux/man-pages/man3/shmat.3p.html) #[syscall_func(196)] -pub fn shmat(shmid: usize, shmaddr: usize, shmflg: u32) -> isize { +pub fn shmat(shmid: usize, shmaddr: usize, shmflg: u32) -> AlienResult { warn!( "shmat shmid:{},shmaddr:{:#x},shmflg:{:?}", shmid, @@ -183,15 +174,12 @@ pub fn shmat(shmid: usize, shmaddr: usize, shmflg: u32) -> isize { ShmAtFlags::from_bits_truncate(shmflg as i32) ); let shm_memory = SHM_MEMORY.lock(); - let shm = shm_memory.get(&shmid); - if shm.is_none() { - return LinuxErrno::EINVAL as isize; - } - let shm = shm.unwrap(); + let shm = shm_memory.get(&shmid).ok_or(LinuxErrno::EINVAL)?; + let flag = ShmAtFlags::from_bits_truncate(shmflg as i32); assert!(flag.is_empty()); if flag.contains(ShmAtFlags::SHM_RDONLY) { - warn!("read only"); + info!("read only"); } assert_eq!(shmaddr, 0); // we must find a place to map @@ -203,26 +191,41 @@ pub fn shmat(shmid: usize, shmaddr: usize, shmflg: u32) -> isize { let mut task_inner = task.access_inner(); let mut address_space = task_inner.address_space.lock(); // let shm_inner = shm.access_inner(); - let mut virt_start = free_map.start; - shm.access_inner().frames.iter().for_each(|x| { - let phy_start = x.start(); - address_space - .map( - VirtAddr::from(virt_start), - PhysAddr::from(phy_start), - PageSize::Size4K, - "UVRWAD".into(), - ) - .unwrap(); - error!("map {:#x} to {:#x}", phy_start, virt_start); - virt_start += FRAME_SIZE; - }); + // let mut virt_start = free_map.start; + // shm.access_inner().frames.iter().for_each(|x| { + // let phy_start = x.start(); + // address_space + // .map( + // VirtAddr::from(virt_start), + // PhysAddr::from(phy_start), + // PageSize::Size4K, + // "UVRWAD".into(), + // ) + // .unwrap(); + // error!("map {:#x} to {:#x}", phy_start, virt_start); + // virt_start += FRAME_SIZE; + // }); + + let size = shm.len(); + let start_phy = shm.access_inner().frames.start(); + address_space + .map_region( + VirtAddr::from(free_map.start), + PhysAddr::from(start_phy), + size, + "UVRWAD".into(), + false, + ) + .unwrap(); + + info!("shm map range:{:#x?}", free_map); + drop(address_space); task_inner .shm .insert(shmid, ShmInfo::new(free_map.start, free_map.end)); shm.add_ref(); - free_map.start as isize + Ok(free_map.start as isize) } /// 一个系统调用,用于控制共享内存。 @@ -236,21 +239,13 @@ pub fn shmat(shmid: usize, shmaddr: usize, shmflg: u32) -> isize { /// /// Reference: [shmctl](https://man7.org/linux/man-pages/man2/shmctl.2.html) #[syscall_func(195)] -pub fn shmctl(shmid: usize, cmd: usize, _buf: usize) -> isize { - let cmd = ShmCtlCmd::try_from(cmd as u32); - if cmd.is_err() { - return LinuxErrno::EINVAL as isize; - } - let cmd = cmd.unwrap(); +pub fn shmctl(shmid: usize, cmd: usize, _buf: usize) -> AlienResult { + let cmd = ShmCtlCmd::try_from(cmd as u32).map_err(|_| LinuxErrno::EINVAL)?; match cmd { ShmCtlCmd::IpcRmid => { //delete let shm_memory = SHM_MEMORY.lock(); - let shm = shm_memory.get(&shmid); - if shm.is_none() { - return LinuxErrno::EINVAL as isize; - } - let shm = shm.unwrap(); + let shm = shm_memory.get(&shmid).ok_or(LinuxErrno::EINVAL)?; shm.delete(); let task = current_task().unwrap(); let task_inner = task.access_inner(); @@ -283,5 +278,5 @@ pub fn shmctl(shmid: usize, cmd: usize, _buf: usize) -> isize { panic!("not support") } } - 0 + Ok(0) } diff --git a/kernel/src/ipc/signal.rs b/kernel/src/ipc/signal.rs index 6478d87d..822bbadd 100644 --- a/kernel/src/ipc/signal.rs +++ b/kernel/src/ipc/signal.rs @@ -7,16 +7,16 @@ use alloc::sync::Arc; use alloc::vec::Vec; use core::mem::size_of; -use crate::ksync::Mutex; -use pconst::signal::{ +use constants::signal::{ SigAction, SigActionDefault, SigActionFlags, SigInfo, SigProcMaskHow, SignalNumber, SignalReceivers, SignalUserContext, SimpleBitSet, }; -use pconst::LinuxErrno; +use constants::LinuxErrno; +use ksync::Mutex; use syscall_table::syscall_func; use crate::task::{current_task, do_exit, do_suspend}; -use crate::timer::{read_timer, TimeSpec}; +use timer::{read_timer, TimeSpec}; /// 记录每个线程的信号量,从 tid 获取信号相关信息 static TID2SIGNALS: Mutex>>> = diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs deleted file mode 100644 index 3dd9f0ac..00000000 --- a/kernel/src/lib.rs +++ /dev/null @@ -1,64 +0,0 @@ -//! 内核的主要代码,包含各个子模块的实现。 -//! -//! 通过导出子模块,boot模块可以调用内核的各个子模块完成初始化工作 - -#![no_std] -#![feature(error_in_core)] -#![feature(panic_info_message)] -#![feature(atomic_from_mut)] -#![feature(ip_in_core)] -// #![deny(missing_docs)] - -extern crate alloc; -#[macro_use] -extern crate log; - -use spin::Once; - -use basemachine::MachineInfo; - -#[macro_use] -pub mod print; -pub mod arch; -pub mod board; -pub mod config; -pub mod device; -pub mod driver; -pub mod error; -pub mod fs; -pub mod gui; -pub mod interrupt; -pub mod ipc; -pub mod ksync; -pub mod memory; -pub mod net; -pub mod panic; -pub mod sbi; -pub mod system; -pub mod task; -pub mod timer; -pub mod trace; -pub mod trap; - -#[macro_use] -extern crate syscall_table; - -pub use syscall_table::*; - -/// 设备基本信息 -pub static MACHINE_INFO: Once = Once::new(); - -/// 初始化设备基本信息 -/// -/// 在后续的代码中,可以通过调用`MACHINE_INFO.get()`来获取设备基本信息 -pub fn init_machine_info(machine_info: MachineInfo) { - MACHINE_INFO.call_once(|| machine_info); -} - -/// 允许内核读写用户态内存。 -/// 取决于 CPU 的 RISC-V 规范版本就行处理 -pub fn thread_local_init() { - unsafe { - riscv::register::sstatus::set_sum(); - } -} diff --git a/kernel/src/main.rs b/kernel/src/main.rs new file mode 100644 index 00000000..feedf595 --- /dev/null +++ b/kernel/src/main.rs @@ -0,0 +1,73 @@ +#![feature(atomic_from_mut)] +#![feature(ip_in_core)] +#![no_std] +#![no_main] + +#[macro_use] +extern crate log; +#[macro_use] +extern crate syscall_table; +#[macro_use] +extern crate platform; +extern crate alloc; + +use alloc::boxed::Box; +pub use syscall_table::*; +mod fs; +mod gui; +mod ipc; +mod mm; +mod net; +mod system; +mod task; +mod time; +mod trap; + +use crate::task::DriverTaskImpl; +use core::hint::spin_loop; +use core::panic::PanicInfo; +use core::sync::atomic::{AtomicBool, Ordering}; +use platform::{platform_machine_info, system_shutdown}; + +/// 多核启动标志 +static STARTED: AtomicBool = AtomicBool::new(false); + +#[no_mangle] +fn main(hart_id: usize) { + if STARTED + .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) + .is_ok() + { + println!("Boot hart {}", hart_id); + let machine_info = platform_machine_info(); + println!("{:#?}", machine_info); + mem::init_memory_system(machine_info.memory.end, true); + interrupt::init_plic(machine_info.plic.start); + drivers::register_task_func(Box::new(DriverTaskImpl)); + devices::init_device(Box::new(DriverTaskImpl)); + vfs::init_filesystem().expect("init filesystem failed"); + trap::init_trap_subsystem(); + arch::allow_access_user_memory(); + task::init_process(); + // register all syscall + syscall_table::init_init_array!(); + STARTED.store(false, Ordering::Relaxed); + } else { + while STARTED.load(Ordering::Relaxed) { + spin_loop(); + } + mem::init_memory_system(0, false); + arch::allow_access_user_memory(); + trap::init_trap_subsystem(); + println!("hart {} start", arch::hart_id()); + } + time::set_next_trigger(); + println!("Begin run task..."); + task::schedule::run_task(); +} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + println!("{}", info); + system_shutdown() +} diff --git a/kernel/src/memory/frame.rs b/kernel/src/memory/frame.rs deleted file mode 100644 index f4b180c2..00000000 --- a/kernel/src/memory/frame.rs +++ /dev/null @@ -1,147 +0,0 @@ -use super::manager::FrameRefManager; -use crate::config::{FRAME_BITS, FRAME_SIZE}; -use crate::ksync::Mutex; -use alloc::format; -use alloc::vec::Vec; -use core::ops::{Deref, DerefMut}; -use pager::{PageAllocator, PageAllocatorExt}; -use spin::Lazy; - -#[cfg(feature = "pager_bitmap")] -pub static FRAME_ALLOCATOR: Mutex> = Mutex::new(pager::Bitmap::new()); -#[cfg(feature = "pager_buddy")] -pub static FRAME_ALLOCATOR: Mutex> = Mutex::new(pager::Zone::new()); - -pub static FRAME_REF_MANAGER: Lazy> = - Lazy::new(|| Mutex::new(FrameRefManager::new())); -extern "C" { - fn ekernel(); -} - -pub fn init_frame_allocator(memory_end: usize) { - let start = ekernel as usize; - let end = memory_end; - let page_start = start / FRAME_SIZE; - let page_end = end / FRAME_SIZE; - let page_count = page_end - page_start; - println!( - "page start:{:#x},end:{:#x},count:{:#x}", - page_start, page_end, page_count - ); - FRAME_ALLOCATOR.lock().init(start..end).unwrap(); -} - -#[derive(Debug)] -pub struct FrameTracker { - id: usize, -} - -pub fn addr_to_frame(addr: usize) -> FrameTracker { - assert_eq!(addr % FRAME_SIZE, 0); - FrameTracker::new(addr >> FRAME_BITS) -} - -impl FrameTracker { - pub fn new(id: usize) -> Self { - Self { id } - } - pub fn start(&self) -> usize { - self.id << FRAME_BITS - } - pub fn end(&self) -> usize { - self.start() + FRAME_SIZE - } - pub fn id(&self) -> usize { - self.id - } -} - -impl Drop for FrameTracker { - fn drop(&mut self) { - trace!("drop frame:{}", self.id); - let _id = FRAME_REF_MANAGER.lock().dec_ref(self.id); - } -} - -impl Deref for FrameTracker { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - unsafe { core::slice::from_raw_parts(self.start() as *const u8, FRAME_SIZE) } - } -} - -impl DerefMut for FrameTracker { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { core::slice::from_raw_parts_mut(self.start() as *mut u8, FRAME_SIZE) } - } -} - -/// 提供给slab分配器的接口 -/// 这些页面需要保持连续 -#[no_mangle] -pub fn alloc_frames(num: usize) -> *mut u8 { - assert_eq!(num.next_power_of_two(), num); - let start_page = FRAME_ALLOCATOR.lock().alloc_pages(num, FRAME_SIZE); - if start_page.is_err() { - panic!("alloc {} frame failed", num); - } - let start_page = start_page.unwrap(); - let start_addr = start_page << FRAME_BITS; - trace!("slab alloc frame {} start:{:#x}", num, start_addr); - start_addr as *mut u8 -} - -/// 提供给slab分配器的接口 -#[no_mangle] -pub fn free_frames(addr: *mut u8, num: usize) { - assert_eq!(num.next_power_of_two(), num); - let start = addr as usize >> FRAME_BITS; - trace!("slab free frame {} start:{:#x}", num, addr as usize); - // make sure the num is 2^n - // assert_eq!(num.count_ones(), 1); - FRAME_ALLOCATOR - .lock() - .free_pages(start, num) - .expect(format!("frame start:{:#x},num:{}", start, num).as_str()); -} - -pub fn frame_alloc() -> Option { - let frame = FRAME_ALLOCATOR.lock().alloc(0); - if frame.is_err() { - return None; - } - let frame = frame.unwrap(); - FRAME_REF_MANAGER.lock().add_ref(frame); - Some(FrameTracker::new(frame)) -} - -pub fn frames_alloc(count: usize) -> Option> { - let mut ans = Vec::new(); - for _ in 0..count { - let id = FRAME_ALLOCATOR.lock().alloc(0); - if id.is_err() { - return None; - } - let id = id.unwrap(); - FRAME_REF_MANAGER.lock().add_ref(id); - ans.push(FrameTracker::new(id)); - } - Some(ans) -} - -pub fn frame_alloc_contiguous(count: usize) -> *mut u8 { - let count = count.next_power_of_two(); - assert_ne!(count, 0); - let frame = FRAME_ALLOCATOR.lock().alloc_pages(count, FRAME_SIZE); - if frame.is_err() { - panic!("alloc {} frame failed, oom", count); - } - let frame = frame.unwrap(); - trace!("alloc frame {} start:{:#x}", count, frame); - for i in 0..count { - let refs = FRAME_REF_MANAGER.lock().add_ref(frame + i); - assert_eq!(refs, 1) - } - (frame << FRAME_BITS as u64) as *mut u8 -} diff --git a/kernel/src/memory/mod.rs b/kernel/src/memory/mod.rs deleted file mode 100644 index 13240c92..00000000 --- a/kernel/src/memory/mod.rs +++ /dev/null @@ -1,167 +0,0 @@ -use core::alloc::GlobalAlloc; - -#[cfg(feature = "buddy")] -use buddy_system_allocator::LockedHeap; -use cfg_if::cfg_if; -use riscv::asm::sfence_vma_all; -use riscv::register::satp; -#[cfg(feature = "talloc")] -use talc::{Talc, Talck}; - -use crate::ksync::Mutex; -pub use frame::*; -pub use map::*; -use syscall_table::syscall_func; -pub use vmm::*; - -use crate::arch::hart_id; -use crate::config::FRAME_SIZE; -#[cfg(any(feature = "talloc", feature = "buddy"))] -use crate::config::KERNEL_HEAP_SIZE; - -mod elf; -mod frame; -mod manager; -mod map; -mod vmm; - -#[global_allocator] -static HEAP_ALLOCATOR: HeapAllocator = HeapAllocator::new(); - -#[cfg(any(feature = "talloc", feature = "buddy"))] -static mut KERNEL_HEAP: [u8; KERNEL_HEAP_SIZE] = [0; KERNEL_HEAP_SIZE]; - -pub fn init_memory_system(memory_end: usize, is_first_cpu: bool) { - if is_first_cpu { - init_frame_allocator(memory_end); - println!("Frame allocator init success"); - cfg_if! { - if #[cfg(feature = "talloc")] { - init_talloc_system(); - println!("talloc allocator init success"); - } else if #[cfg(feature = "buddy")] { - init_buddy_system(); - println!("buddy allocator init success"); - } else if #[cfg(feature = "slab")] { - init_slab_system(FRAME_SIZE, 32); - println!("slab allocator init success"); - } - } - build_kernel_address_space(memory_end); - println!("build kernel address space success"); - activate_paging_mode(); - println!("activate paging mode success"); - } else { - activate_paging_mode(); - } -} - -/// 激活页表模式 -pub fn activate_paging_mode() { - // let ppn = KERNEL_SPACE.read().root_ppn().unwrap().0; - unsafe { - sfence_vma_all(); - satp::set( - satp::Mode::Sv39, - 0, - KERNEL_SPACE.read().root_paddr().as_usize() >> 12, - ); - sfence_vma_all(); - } -} - -struct HeapAllocator { - #[cfg(feature = "talloc")] - allocator: Mutex, - #[cfg(feature = "buddy")] - allocator: Mutex>, - #[cfg(feature = "slab")] - allocator: Mutex, -} - -unsafe impl GlobalAlloc for HeapAllocator { - unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 { - let need_page = if layout.size() % FRAME_SIZE == 0 { - layout.size() / FRAME_SIZE - } else { - layout.size() / FRAME_SIZE + 1 - }; - if layout.size() >= 5 * 1024 * 1024 { - trace!("alloc big page: {:#x}", layout.size()); - let frame = alloc_frames(need_page); - frame - } else { - let ptr = self.allocator.lock().alloc(layout); - assert!(!ptr.is_null()); - ptr - } - } - unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) { - let need_page = if layout.size() % FRAME_SIZE == 0 { - layout.size() / FRAME_SIZE - } else { - layout.size() / FRAME_SIZE + 1 - }; - if layout.size() >= 5 * 1024 * 1024 { - trace!("free big page: {:#x}", layout.size()); - free_frames(ptr, need_page); - } else { - assert_eq!(ptr.is_null(), false); - self.allocator.lock().dealloc(ptr, layout); - } - } -} - -impl HeapAllocator { - pub const fn new() -> Self { - Self { - #[cfg(feature = "talloc")] - allocator: Mutex::new(Talc::new().spin_lock()), - #[cfg(feature = "buddy")] - allocator: Mutex::new(LockedHeap::<32>::new()), - #[cfg(feature = "slab")] - allocator: Mutex::new(SlabAllocator), - } - } -} - -pub fn kernel_satp() -> usize { - 8usize << 60 | (KERNEL_SPACE.read().root_paddr().as_usize() >> 12) -} - -/// This function will be call in slab allocator -#[no_mangle] -fn current_cpu_id() -> usize { - hart_id() -} - -/// (待实现)在一组线程中,设置内存屏障,控制多核系统中的内存访问次序。目前直接返回0。 -/// -/// -#[syscall_func(283)] -pub fn membarrier() -> isize { - 0 -} - -#[cfg(feature = "talloc")] -fn init_talloc_system() { - unsafe { - HEAP_ALLOCATOR - .allocator - .lock() - .talc() - .init(KERNEL_HEAP.as_mut_slice().into()) - } -} - -#[cfg(feature = "buddy")] -fn init_buddy_system() { - unsafe { - HEAP_ALLOCATOR - .allocator - .lock() - .lock() - .init(KERNEL_HEAP.as_ptr() as usize, KERNEL_HEAP_SIZE); - println!("heap start: {:#x}", KERNEL_HEAP.as_ptr() as usize); - } -} diff --git a/kernel/src/memory/elf.rs b/kernel/src/mm/elf.rs similarity index 87% rename from kernel/src/memory/elf.rs rename to kernel/src/mm/elf.rs index eb430b00..b2d0b522 100644 --- a/kernel/src/memory/elf.rs +++ b/kernel/src/mm/elf.rs @@ -3,13 +3,13 @@ use alloc::vec; use alloc::vec::Vec; use core::fmt::{Debug, Formatter}; +use mem::VmmPageAllocator; use page_table::table::Sv39PageTable; use xmas_elf::sections::SectionData; use xmas_elf::symbol_table::Entry; use xmas_elf::ElfFile; -use crate::memory::PageAllocator; - +#[allow(unused)] #[derive(Debug)] pub enum ELFError { NotELF, @@ -34,7 +34,7 @@ impl Debug for ELFInfo { } pub struct ELFInfo { - pub address_space: Sv39PageTable, + pub address_space: Sv39PageTable, pub entry: usize, pub stack_top: usize, pub heap_bottom: usize, @@ -133,3 +133,18 @@ impl ELFReader for ElfFile<'_> { Ok(res) } } +// /* RISC-V relocations. */ +// #define R_RISCV_NONE 0 +// #define R_RISCV_32 1 +// #define R_RISCV_64 2 +// #define R_RISCV_RELATIVE 3 +// #define R_RISCV_COPY 4 +// #define R_RISCV_JUMP_SLOT 5 +// #define R_RISCV_TLS_DTPMOD32 6 +// #define R_RISCV_TLS_DTPMOD64 7 +// #define R_RISCV_TLS_DTPREL32 8 +// #define R_RISCV_TLS_DTPREL64 9 +// #define R_RISCV_TLS_TPREL32 10 +// #define R_RISCV_TLS_TPREL64 11 +// #define R_RISCV_BRANCH 16 +// #define R_RISCV_JAL 17 diff --git a/kernel/src/memory/vmm.rs b/kernel/src/mm/loader.rs similarity index 72% rename from kernel/src/memory/vmm.rs rename to kernel/src/mm/loader.rs index c74bb90b..4da73547 100644 --- a/kernel/src/memory/vmm.rs +++ b/kernel/src/mm/loader.rs @@ -1,147 +1,23 @@ -use crate::config::*; use crate::fs; use crate::ipc::ShmInfo; -use crate::ksync::RwLock; -use crate::memory::elf::{ELFError, ELFInfo, ELFReader}; -use crate::memory::frame::{addr_to_frame, frame_alloc}; -use crate::memory::{frame_alloc_contiguous, FRAME_REF_MANAGER}; +use crate::mm::elf::{ELFError, ELFInfo, ELFReader}; use crate::trap::TrapFrame; use alloc::collections::BTreeMap; use alloc::string::{String, ToString}; -use alloc::sync::Arc; use alloc::vec; use alloc::vec::Vec; +use config::*; use core::cmp::min; use core::fmt::Debug; -use core::mem::forget; +use mem::{VmmPageAllocator, FRAME_REF_MANAGER}; use page_table::addr::{align_up_4k, PhysAddr, VirtAddr}; use page_table::pte::MappingFlags; -use page_table::table::{PagingIf, Sv39PageTable}; -use spin::Lazy; +use page_table::table::Sv39PageTable; use xmas_elf::program::{SegmentData, Type}; -pub static KERNEL_SPACE: Lazy>>> = Lazy::new(|| { - Arc::new(RwLock::new( - Sv39PageTable::::try_new().unwrap(), - )) -}); - -#[allow(unused)] extern "C" { - fn stext(); - fn srodata(); - fn sdata(); - fn sbss(); - fn ekernel(); fn strampoline(); - fn sinit(); - fn einit(); - - // fn kernel_eh_frame(); - // fn kernel_eh_frame_end(); - // fn kernel_eh_frame_hdr(); - // fn kernel_eh_frame_hdr_end(); } - -pub fn kernel_info(memory_end: usize) { - println!( - "kernel text: {:#x}-{:#x}", - stext as usize, srodata as usize - ); - println!( - "kernel rodata: {:#x}-{:#x}", - srodata as usize, sdata as usize - ); - println!( - "kernel init_array: {:#x}-{:#x}", - sinit as usize, einit as usize - ); - println!( - "kernel data: {:#x}-{:#x}", - sdata as usize, sbss as usize - ); - println!( - "kernel bss: {:#x}-{:#x}", - sbss as usize, ekernel as usize - ); - // println!("kernel eh_frame: {:#x}-{:#x}", kernel_eh_frame as usize, kernel_eh_frame_end as usize); - // println!("kernel eh_frame_hdr: {:#x}-{:#x}", kernel_eh_frame_hdr as usize, kernel_eh_frame_hdr_end as usize); - println!( - "kernel heap: {:#x}-{:#x}", - ekernel as usize, memory_end - ); -} - -/// 建立内核页表 -pub fn build_kernel_address_space(memory_end: usize) { - let mut kernel_space = KERNEL_SPACE.write(); - kernel_space - .map_region( - VirtAddr::from(stext as usize), - PhysAddr::from(stext as usize), - srodata as usize - stext as usize, - "RXVAD".into(), - true, - ) - .unwrap(); - kernel_space - .map_region( - VirtAddr::from(srodata as usize), - PhysAddr::from(srodata as usize), - sdata as usize - srodata as usize, - "RVAD".into(), - true, - ) - .unwrap(); - kernel_space - .map_region( - VirtAddr::from(sdata as usize), - PhysAddr::from(sdata as usize), - sbss as usize - sdata as usize, - "RWVAD".into(), - true, - ) - .unwrap(); - kernel_space - .map_region( - VirtAddr::from(sbss as usize), - PhysAddr::from(sbss as usize), - ekernel as usize - sbss as usize, - "RWVAD".into(), - true, - ) - .unwrap(); - kernel_space - .map_region( - VirtAddr::from(ekernel as usize), - PhysAddr::from(ekernel as usize), - memory_end - ekernel as usize, - "RWVAD".into(), - true, - ) - .unwrap(); - kernel_space - .map_region( - VirtAddr::from(TRAMPOLINE), - PhysAddr::from(strampoline as usize), - FRAME_SIZE, - "RXVAD".into(), - true, - ) - .unwrap(); - for pair in MMIO { - kernel_space - .map_region( - VirtAddr::from(pair.0), - PhysAddr::from(pair.0), - pair.1, - "RWVAD".into(), - true, - ) - .unwrap(); - } -} - #[derive(Debug)] pub struct UserStack { pub virt_stack_top: usize, @@ -157,11 +33,6 @@ impl UserStack { stack_bottom: phy_stack_top - FRAME_SIZE, } } - - pub fn get_stack_top(&self) -> usize { - self.stack_top - } - pub fn push(&mut self, data: usize) -> Result { if self.stack_top - 8 < self.stack_bottom { return Err("Stack Overflow"); @@ -213,7 +84,7 @@ impl UserStack { } pub fn build_thread_address_space( - table: &mut Sv39PageTable, + table: &mut Sv39PageTable, thread_num_within: usize, ) -> &'static mut TrapFrame { let address = TRAP_CONTEXT_BASE - FRAME_SIZE * thread_num_within; @@ -242,10 +113,10 @@ pub fn build_thread_address_space( } pub fn build_cow_address_space( - p_table: &mut Sv39PageTable, + p_table: &mut Sv39PageTable, shm: BTreeMap, -) -> Sv39PageTable { - let mut address_space = Sv39PageTable::::try_new().unwrap(); +) -> Sv39PageTable { + let mut address_space = Sv39PageTable::::try_new().unwrap(); for (v_addr, target) in p_table.get_record().into_iter() { trace!("v_addr: {:?}, target: {}", v_addr, target); let (phy, flag, page_size) = p_table.query(v_addr).unwrap(); @@ -298,7 +169,7 @@ pub fn build_cow_address_space( if target { for i in 0..usize::from(page_size) / FRAME_SIZE { let page_number = (phy + FRAME_SIZE * i).as_usize() >> FRAME_BITS; - FRAME_REF_MANAGER.lock().get_ref(page_number); + // FRAME_REF_MANAGER.lock().get_ref(page_number); FRAME_REF_MANAGER.lock().add_ref(page_number); } address_space.get_record_mut().insert(v_addr, true); @@ -313,7 +184,7 @@ pub fn build_elf_address_space( args: &mut Vec, name: &str, ) -> Result { - let mut address_space = Sv39PageTable::::try_new().unwrap(); + let mut address_space = Sv39PageTable::::try_new().unwrap(); const ELF_MAGIC: [u8; 4] = [0x7f, b'E', b'L', b'F']; if elf[0..4] != ELF_MAGIC { return Err(ELFError::NotELF); @@ -381,8 +252,6 @@ pub fn build_elf_address_space( .for_each(|ph| { let start_addr = ph.virtual_addr() as usize + bias; let end_addr = start_addr + ph.mem_size() as usize; - // 记录程序地址空间的最大地址 - break_addr = end_addr; let mut permission: MappingFlags = "UVAD".into(); let ph_flags = ph.flags(); if ph_flags.is_read() { @@ -396,6 +265,8 @@ pub fn build_elf_address_space( } let vaddr = VirtAddr::from(start_addr).align_down_4k(); let end_vaddr = VirtAddr::from(end_addr).align_up_4k(); + // 记录程序地址空间的最大地址 + break_addr = end_addr; let len = end_vaddr.as_usize() - vaddr.as_usize(); warn!( "load segment: {:#x} - {:#x} -> {:#x}-{:#x}, permission: {:?}", @@ -412,17 +283,19 @@ pub fn build_elf_address_space( .unwrap(); // copy data let mut page_offset = start_addr & (FRAME_SIZE - 1); + let mut count = 0; map_info .into_iter() - .for_each(|(vir, phy, page_size)| unsafe { - trace!("{:#x} {:#x} {:#x?}", vir, phy, page_size); + .for_each(|(_vir, phy, page_size)| unsafe { let size: usize = page_size.into(); let min = min(size - page_offset, data.len()); let dst = (phy.as_usize() + page_offset) as *mut u8; core::ptr::copy(data.as_ptr(), dst, min); data = &data[min..]; - page_offset = (page_offset + min) & (FRAME_SIZE - 1); + count += min; + page_offset = 0; }); + assert_eq!(count, ph.file_size() as usize); }); // 地址向上取整对齐4 @@ -519,33 +392,3 @@ pub fn build_elf_address_space( name: name.to_string(), }) } - -pub struct PageAllocator; - -impl PagingIf for PageAllocator { - fn alloc_frame() -> Option { - frame_alloc().map(|frame| { - let start = frame.start(); - trace!("PageAllocator alloc frame{:?} start:{:#x}", frame, start); - forget(frame); - PhysAddr::from(start) - }) - } - - fn dealloc_frame(paddr: PhysAddr) { - let frame = addr_to_frame(paddr.as_usize()); - trace!("PageAllocator dealloc frame {:?}", frame); - } - - fn phys_to_virt(paddr: PhysAddr) -> VirtAddr { - VirtAddr::from(paddr.as_usize()) - } - - fn alloc_contiguous_frames(size: usize) -> Option { - let ptr = frame_alloc_contiguous(size); - if ptr.is_null() { - return None; - } - Some(PhysAddr::from(ptr as usize)) - } -} diff --git a/kernel/src/memory/map.rs b/kernel/src/mm/map.rs similarity index 98% rename from kernel/src/memory/map.rs rename to kernel/src/mm/map.rs index e64f0d4b..c79ffe91 100644 --- a/kernel/src/memory/map.rs +++ b/kernel/src/mm/map.rs @@ -6,14 +6,13 @@ use bitflags::bitflags; use page_table::addr::{align_up_4k, VirtAddr}; use page_table::pte::MappingFlags; -use pconst::io::MapFlags; -use pconst::LinuxErrno; -use syscall_table::syscall_func; - -use crate::config::{FRAME_SIZE, PROCESS_HEAP_MAX}; -use crate::error::AlienResult; -use crate::fs::file::File; use crate::task::current_task; +use config::{FRAME_SIZE, PROCESS_HEAP_MAX}; +use constants::io::MapFlags; +use constants::AlienResult; +use constants::LinuxErrno; +use syscall_table::syscall_func; +use vfs::kfile::File; bitflags! { pub struct ProtFlags: u32 { diff --git a/kernel/src/mm/mod.rs b/kernel/src/mm/mod.rs new file mode 100644 index 00000000..660a1c28 --- /dev/null +++ b/kernel/src/mm/mod.rs @@ -0,0 +1,19 @@ +use arch::hart_id; + +pub mod elf; +pub mod loader; +pub mod map; + +/// This function will be call in slab allocator +#[no_mangle] +fn current_cpu_id() -> usize { + hart_id() +} + +/// (待实现)在一组线程中,设置内存屏障,控制多核系统中的内存访问次序。目前直接返回0。 +/// +/// +#[syscall_func(283)] +pub fn membarrier() -> isize { + 0 +} diff --git a/kernel/src/net/addr.rs b/kernel/src/net/addr.rs index cde85cbb..421670ed 100644 --- a/kernel/src/net/addr.rs +++ b/kernel/src/net/addr.rs @@ -1,92 +1,10 @@ -//! 在 Alien 内核中使用的 socket 套接字地址结构。 -//! -//! Alien 中目前能够接收的套接字地址种类包括本地路径地址和网络套接字地址。 -//! 对于从用户端传来的套接字地址,类似于 `linux` 中 `socket.h` 的套接字地址。 -//! 大致结构如下: -//! + 2字节表明该套接字使用的地址协议族 -//! + 2字节表明该套接字的端口 -//! + 12字节的地址数据 -//! -//! Alien 将会首先对传入的套接字的协议族进行解析,然后根据不同的地址协议族将其解析成 [`SocketAddrExt`] 结构, -//! 向下层的具体套接字中传递相应地址时,传递的也是 [`SocketAddrExt`] 结构。 -//! +use crate::task::current_task; use alloc::string::{String, ToString}; use alloc::vec; -use core::fmt::Debug; +use constants::net::Domain; +use constants::{AlienResult, LinuxErrno}; use core::net::{IpAddr, Ipv4Addr, SocketAddr}; - -use crate::error::AlienResult; -use crate::task::current_task; -use pconst::net::Domain; -use pconst::LinuxErrno; - -/// 用于存储套接字通信地址的结构,分为本地路径地址和网络套接字地址。 -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] -pub enum SocketAddrExt { - LocalPath(String), - SocketAddr(SocketAddr), -} - -/// 用于存储一个Ipv4套接字相关信息的结构。对应 `linux` 中 `socket.h` 的 `sockaddr_in` 结构。 -/// -/// 在 socket 相关系统调用中,一般都先分析出套接字采用的地址协议族,如果是 `IPV4` 则会将传入的套接字相关信息解析成 `RawIpV4Addr`。 -/// 且 `Alien` 目前默认使用网络套接字时,即采用 `IPV4` 协议。 -#[repr(C)] -#[derive(Debug, Clone, Copy, Default)] -pub struct RawIpV4Addr { - /// 地址协议族 - pub family: u16, - /// Ipv4 的端口 - pub port: u16, - /// Ipv4 的地址 - pub addr: u32, - /// 零位,用于后续扩展 - pub zero: [u8; 8], -} - -impl SocketAddrExt { - /// 获取网络套接字地址。当本结构中存储的是本地路径地址时,将导致 panic。 - pub fn get_socketaddr(&self) -> SocketAddr { - match self { - SocketAddrExt::LocalPath(_) => { - panic!("Can't get socketaddr from local path") - } - SocketAddrExt::SocketAddr(addr) => *addr, - } - } - - /// 获取本地路径地址。当本结构中存储的是网络套接字地址时,将导致 panic。 - pub fn get_local_path(&self) -> String { - match self { - SocketAddrExt::LocalPath(path) => path.clone(), - SocketAddrExt::SocketAddr(_) => { - panic!("Can't get local path from socketaddr") - } - } - } -} - -impl From for RawIpV4Addr { - /// 用一个 [`SocketAddr`] 结构 初始化 `RawIpV4Addr ` - fn from(addr: SocketAddr) -> Self { - let ip = addr.ip(); - let port = addr.port(); - let ip = match ip { - IpAddr::V4(ip) => ip, - IpAddr::V6(_) => { - panic!("ipv6 is not supported") - } - }; - let ip = ip.octets(); - let ip = u32::from_le_bytes(ip); - Self { - family: Domain::AF_INET as u16, - port: port.to_be(), - addr: ip, - zero: [0u8; 8], - } - } -} +use knet::addr::{RawIpV4Addr, SocketAddrExt}; /// 地址解析,将根据`family_user_addr`的[`Domain`]类型分类进行解析。 /// diff --git a/kernel/src/net/mod.rs b/kernel/src/net/mod.rs index a49f96a8..a4de7c2c 100644 --- a/kernel/src/net/mod.rs +++ b/kernel/src/net/mod.rs @@ -5,23 +5,19 @@ //! [`socket`] 子模块指明了Alien 内核中使用的套接字。 //! [`unix`] 子模块指明了有关 Unix 协议族下的套接字结构。(目前有关的功能有待支持) //! -use crate::error::AlienResult; -use crate::fs::file::File; -use crate::net::addr::{socket_addr_resolution, RawIpV4Addr}; -use crate::net::socket::{SocketData, SocketFile, SocketFileExt}; +use crate::net::addr::socket_addr_resolution; use crate::task::{current_task, do_suspend}; use alloc::sync::Arc; use alloc::vec; use alloc::vec::Vec; -use pconst::io::OpenFlags; -use pconst::net::*; -use pconst::LinuxErrno; -use syscall_table::syscall_func; +use constants::io::OpenFlags; +use constants::net::*; +use constants::{AlienResult, LinuxErrno}; +use knet::addr::RawIpV4Addr; +use knet::socket::{SocketData, SocketFile, SocketFileExt}; +use vfs::kfile::File; pub mod addr; -pub mod port; -pub mod socket; -mod unix; /// 一个系统调用,用于创建一个未绑定的socket套接字。 /// diff --git a/kernel/src/print/console.rs b/kernel/src/print/console.rs deleted file mode 100644 index 4162923b..00000000 --- a/kernel/src/print/console.rs +++ /dev/null @@ -1,133 +0,0 @@ -use core::fmt::{Arguments, Result, Write}; -use core::sync::atomic::{AtomicBool, Ordering}; - -use preprint::Print; - -use crate::ksync::Mutex; - -use crate::device::UART_DEVICE; -use crate::sbi::console_putchar; - -#[macro_export] -macro_rules! print { - ($($arg:tt)*) => { - let hard_id = $crate::arch::hart_id(); - // [hart_id] xxx - $crate::print::console::__print(format_args!("[{}] {}", hard_id, format_args!($($arg)*))) - }; -} - -#[macro_export] -macro_rules! println { - () => ($crate::print!("\n")); - ($fmt:expr) => ($crate::print!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => ($crate::print!( - concat!($fmt, "\n"), $($arg)*)); -} - -#[macro_export] -macro_rules! eprint { - ($($arg:tt)*) => { - $crate::print::console::__print(format_args!("{}", format_args!($($arg)*))) - }; -} - -#[macro_export] -macro_rules! eprintln { - () => ($crate::eprint!("\n")); - ($fmt:expr) => ($crate::eprint!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => ($crate::eprint!( - concat!($fmt, "\n"), $($arg)*)); -} - -#[macro_export] -macro_rules! uprint { - ($($arg:tt)*) => { - $crate::print::console::__uprint(format_args!($($arg)*)) - }; -} - -#[macro_export] -macro_rules! uprintln { - () => ($crate::uprint!("\n")); - ($fmt:expr) => ($crate::uprint!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => ($crate::uprint!( - concat!($fmt, "\n"), $($arg)*)); -} - -pub struct Stdout; - -pub static STDOUT: Mutex = Mutex::new(Stdout); - -pub static UART_FLAG: AtomicBool = AtomicBool::new(false); - -/// 对`Stdout`实现输出的Trait -impl Write for Stdout { - fn write_str(&mut self, s: &str) -> Result { - if UART_FLAG.load(Ordering::Relaxed) { - let uart = UART_DEVICE.get().unwrap(); - uart.put_bytes(s.as_bytes()); - } else { - s.as_bytes().iter().for_each(|x| { - console_putchar(*x); - }); - } - Ok(()) - } -} - -struct MStdout; -impl Write for MStdout { - fn write_str(&mut self, s: &str) -> Result { - s.as_bytes().iter().for_each(|x| { - console_putchar(*x); - }); - Ok(()) - } -} - -pub fn __mprint(args: Arguments) { - MStdout.write_fmt(args).unwrap(); -} - -#[macro_export] -macro_rules! mprint { - ($($arg:tt)*) => { - let hard_id = $crate::arch::hart_id(); - // [hart_id] xxx - $crate::print::console::__mprint(format_args!("[{}] {}", hard_id, format_args!($($arg)*))) - }; -} - -#[macro_export] -macro_rules! mprintln { - () => ($crate::mprint!("\n")); - ($fmt:expr) => ($crate::mprint!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => ($crate::mprint!( - concat!($fmt, "\n"), $($arg)*)); -} - -/// 输出函数 -/// 对参数进行输出 主要使用在输出相关的宏中 如println -pub fn __print(args: Arguments) { - Stdout.write_fmt(args).unwrap(); -} - -pub fn __uprint(args: Arguments) { - Stdout.write_fmt(args).unwrap(); -} - -pub struct PrePrint; - -impl Print for PrePrint { - fn print(&self, args: Arguments) { - print!("{}", args); - } -} - -impl Write for PrePrint { - fn write_str(&mut self, s: &str) -> Result { - print!("{}", s); - Ok(()) - } -} diff --git a/kernel/src/print/mod.rs b/kernel/src/print/mod.rs deleted file mode 100644 index 7b25d2c0..00000000 --- a/kernel/src/print/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -use console::PrePrint; -use logging::init_logger; - -#[macro_use] -pub mod console; -mod logging; - -pub fn init_print() { - init_logger(); - preprint::init_print(&PrePrint); - println!("Print init success"); -} diff --git a/kernel/src/system.rs b/kernel/src/system.rs index 0de05c6b..77871740 100644 --- a/kernel/src/system.rs +++ b/kernel/src/system.rs @@ -1,5 +1,9 @@ //! uname系统调用实现 +use constants::sys::{Rusage, RusageFlag, Sysinfo, SyslogAction, TimeVal}; +use constants::{AlienResult, LinuxErrno}; +use core::cmp::min; use syscall_table::syscall_func; +use timer::{get_time_ms, TimeFromFreq}; use crate::task::current_task; @@ -56,3 +60,169 @@ pub fn uname(utsname: *const u8) -> isize { .copy_to_user(&system_info(), utsname as *mut Utsname); 0 } + +const LOG_BUF_LEN: usize = 4096; +const LOG: &str = r" +[ 0.000000] Linux version 5.10.0-7-riscv64 (debian-kernel@lists.debian.org) (gcc-10 (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for Debian) 2.35.2) #1 SMP Debian 5.10.40-1 (2021-05-28) +"; + +/// (待完善)一个系统调用函数,用于对内核消息环状缓冲区进行操作。 +/// +/// + `log_type`: 指明操作的类型,具体值可见[`SyslogAction`]; +/// + `buf`: 指明读取消息时,消息要保存到的位置; +/// + `len`: 指明具体操作时,对于消息读取的长度限制。真正的读取消息的长度将取决于就传入的`len`和`LOG_BUF_LEN`的最小值。 +/// +/// 当`log_type`为`READ`、`ReadAll`、`ReadClear`三种flag,正确执行后返回读取消息的长度; +/// 当`log_type`为`Unknown`时,会返回`EINVAL`;当`log_type`为`OPEN`或`CLOSE`时,函数不进行任何操作后返回0。 +/// 目前Alien仅支持上述`log_type`值,其余值都将不进行任何操作后返回0。 +/// +/// Reference: [syslog](https://man7.org/linux/man-pages/man2/syslog.2.html) +#[syscall_func(116)] +pub fn syslog(log_type: u32, buf: usize, len: usize) -> isize { + let log_type = SyslogAction::try_from(log_type); + if log_type.is_err() { + return LinuxErrno::EINVAL as isize; + } + match log_type.unwrap() { + SyslogAction::OPEN | SyslogAction::CLOSE => 0, + SyslogAction::READ | SyslogAction::ReadAll | SyslogAction::ReadClear => { + let min_len = min(len, LOG_BUF_LEN); + let task = current_task().unwrap(); + // the buf may be not valid, so we need to check it -- > sbrk heap + let mut buf = task.transfer_buffer(buf as *mut u8, min_len); + let log = LOG.as_bytes(); + let mut offset = 0; + buf.iter_mut().for_each(|buf| { + let copy_len = min(log.len() - offset, buf.len()); + buf[..copy_len].copy_from_slice(&log[offset..offset + copy_len]); + offset += copy_len; + }); + offset as isize + } + SyslogAction::Unknown => LinuxErrno::EINVAL as isize, + _ => 0, + } +} + +extern "C" { + fn ekernel(); +} + +/// 一个系统调用函数,用于获取系统相关信息。信息包括系统的自启动经过的时间、对于内存的使用情况、共享存储区的大小、 +/// 缓冲区与交换区的大小、当前进程数目等,具体可见[`Sysinfo`]。获取到的信息将保存到`dst_info`所指向的[`Sysinfo`]结构处。 +/// +/// 目前功能还有待完善。正确执行后返回0。 +#[syscall_func(179)] +pub fn sys_info(dst_info: usize) -> isize { + const LINUX_SYSINFO_LOADS_SCALE: usize = 65536; + let task = current_task().unwrap(); + // calculate the task number + let task_number = 10; // fake task number + let machine_info = platform::platform_machine_info(); + let memory_info = machine_info.memory.clone(); + let info = Sysinfo { + uptime: (get_time_ms() / 1000) as usize, + loads: [ + task_number * LINUX_SYSINFO_LOADS_SCALE / 60, + task_number * LINUX_SYSINFO_LOADS_SCALE / 300, + task_number * LINUX_SYSINFO_LOADS_SCALE / 900, + ], + totalram: memory_info.end - memory_info.start, + freeram: memory_info.end - ekernel as usize, + sharedram: 0, + bufferram: 0, + totalswap: 0, + freeswap: 0, + procs: task_number as u16, + totalhigh: 0, + freehigh: 0, + mem_unit: 1, + }; + task.access_inner() + .copy_to_user(&info, dst_info as *mut Sysinfo); + 0 +} + +/// (待实现)一个系统调用,设置进程调度的参数。目前直接返回0。 +#[syscall_func(118)] +pub fn sched_setparam() -> isize { + 0 +} + +/// (待实现)一个系统调用,获取进程调度的参数。目前直接返回0。 +#[syscall_func(121)] +pub fn sched_getparam() -> isize { + 0 +} + +/// (待实现)一个系统调用,设置进程CPU亲和力(位掩码),使进程绑定在某一个或几个CPU上运行,避免在CPU之间来回切换,从而提高该进程的实时性能。目前直接返回0。 +#[syscall_func(122)] +pub fn sched_setaffinity() -> isize { + 0 +} + +/// (待完善)一个系统调用,获取某进程对CPU的亲和力(位掩码)。当前进程的cpu亲和力将保存到`mask`所指向的位置。函数执行成功后返回8。 +#[syscall_func(123)] +pub fn sched_getaffinity(pid: usize, size: usize, mask: usize) -> isize { + warn!( + "sched_getaffinity: pid: {}, size: {}, mask: {}", + pid, size, mask + ); + assert_eq!(pid, 0); + let task = current_task().unwrap(); + let res = task.access_inner().cpu_affinity; + let mask = task.access_inner().transfer_raw_ptr_mut(mask as *mut usize); + *mask = res; + 8 +} + +/// (待实现)一个系统调用,用于获取当前CPU的调度策略。目前直接返回0。 +#[syscall_func(120)] +pub fn sched_getscheduler(pid: usize) -> isize { + assert_eq!(pid, 0); + // let task = current_task().unwrap(); + 0 +} + +/// (待实现)一个系统调用,用于设置当前CPU的调度策略。目前直接返回0。 +#[syscall_func(119)] +pub fn sched_setscheduler(_pid: usize, _policy: usize, _param: usize) -> isize { + 0 +} + +/// (待完善)一个系统调用,用于获取对系统资源的使用量信息。获取的信息将保存到`usage`所指向的[`Rusage`]结构中。 +/// +/// 可以通过`who`修改获取信息的对象,包括: +/// + `RUSAGE_SELF`: 返回调用该函数进程的资源用量统计,会返回该进程下所有线程的资源用量之和; +/// + `RUSAGE_CHILDREN`: 返回调用该函数进程所有已终止且被回收子进程的资源用量统计. +/// + `RUSAGE_THREAD`: 返回调用该函数线程的资源用量统计。 +/// +/// 在Alien中,目前仅支持`RUSAGE_SELF`。且返回的信息目前仅有[`Rusage`]下的`ru_utime`和`ru_stime`字段。 +/// +/// 正确执行后返回0。 +#[syscall_func(165)] +pub fn getrusage(who: isize, usage: usize) -> AlienResult { + let who = RusageFlag::try_from(who).map_err(|_| LinuxErrno::EINVAL)?; + info!("getrusage: who: {:?}, usage: {}", who, usage); + let task = current_task().unwrap(); + let static_info = task.access_inner().statistical_data().clone(); + let mut task_usage = Rusage::new(); + task_usage.ru_utime = TimeVal::from_freq(static_info.tms_utime); + task_usage.ru_stime = TimeVal::from_freq(static_info.tms_stime); + task.access_inner() + .copy_to_user(&task_usage, usage as *mut Rusage); + Ok(0) +} + + + + + + + +/// 一个系统调用,通过调用 SBI_SHUTDOWN 来关闭操作系统(直接退出 QEMU) +#[syscall_func(2003)] +pub fn system_shutdown() -> AlienResult { + println!("shutdown..."); + platform::system_shutdown(); +} \ No newline at end of file diff --git a/kernel/src/task/cpu.rs b/kernel/src/task/cpu.rs index 2628ab4d..0ea880f1 100644 --- a/kernel/src/task/cpu.rs +++ b/kernel/src/task/cpu.rs @@ -3,27 +3,28 @@ use alloc::string::{String, ToString}; use alloc::sync::Arc; use alloc::vec::Vec; use core::cell::UnsafeCell; +use log::{error, info, warn}; use smpscheduler::{FifoSmpScheduler, FifoTask, ScheduleHart}; use spin::Lazy; -use crate::error::{AlienError, AlienResult}; -use crate::ksync::Mutex; -use pconst::ipc::FutexOp; -use pconst::signal::SignalNumber; -use pconst::task::{CloneFlags, WaitOptions}; -use pconst::{PrLimit, PrLimitRes}; +use constants::ipc::FutexOp; +use constants::signal::SignalNumber; +use constants::task::{CloneFlags, WaitOptions}; +use constants::{AlienError, AlienResult}; +use constants::{PrLimit, PrLimitRes}; +use ksync::Mutex; use syscall_table::syscall_func; -use crate::arch::hart_id; -use crate::config::CPU_NUM; +use crate::fs; use crate::ipc::{futex, global_logoff_signals}; -use crate::sbi::system_shutdown; use crate::task::context::Context; use crate::task::schedule::schedule; use crate::task::task::{Task, TaskState}; use crate::task::INIT_PROCESS; use crate::trap::{check_task_timer_expired, TrapFrame}; -use crate::{arch, fs}; +use arch::hart_id; +use config::CPU_NUM; +use platform::system_shutdown; /// 记录当前 CPU 上正在执行的线程 和 线程上下文 #[derive(Debug, Clone)] @@ -43,11 +44,6 @@ impl CPU { } } - /// 获取 cpu 上的线程任务控制块(会直接获取该任务控制块的所有权) - pub fn take_process(&mut self) -> Option> { - self.task.take() - } - /// 获取线程上下文的一个 不可变引用 的指针 pub fn get_context_raw_ptr(&self) -> *const Context { &self.context as *const Context diff --git a/kernel/src/task/heap.rs b/kernel/src/task/heap.rs index 9243bc09..cbe663ae 100644 --- a/kernel/src/task/heap.rs +++ b/kernel/src/task/heap.rs @@ -33,6 +33,7 @@ impl HeapInfo { addr >= self.start && addr < self.end } + #[allow(unused)] /// 堆大小增加 size 个单位 pub fn increase(&mut self, size: usize) { self.end += size; @@ -44,6 +45,7 @@ impl HeapInfo { self.start = start; } + #[allow(unused)] /// 重新设置堆空间的尾 pub fn set_end(&mut self, end: usize) { self.end = end; diff --git a/kernel/src/task/mod.rs b/kernel/src/task/mod.rs index 37b2f6c7..dff74938 100644 --- a/kernel/src/task/mod.rs +++ b/kernel/src/task/mod.rs @@ -6,18 +6,17 @@ //! [`schedule`] 子模块指明了 Alien 中有关 CPU 调度的相关机制 //! [`stack`] 子模块定义了 Alien 中有关内核栈的相关结构。 //! [`task`] 子模块定义了 Alien 中有关进程控制块的定义。 +use crate::fs::read_all; +pub use crate::task::task::FsContext; use alloc::sync::Arc; use alloc::vec::Vec; +pub use cpu::*; +use devices::DeviceWithTask; +use drivers::{DriverTask, DriverWithTask}; use smpscheduler::FifoTask; - use spin::Lazy; - -pub use cpu::*; pub use task::{StatisticalData, Task, TaskState}; -use crate::fs::{read_all, SYSTEM_ROOT_FS}; -pub use crate::task::task::FsContext; - mod context; mod cpu; mod heap; @@ -29,7 +28,6 @@ mod task; pub static INIT_PROCESS: Lazy> = Lazy::new(|| { let mut data = Vec::new(); read_all("/bin/init", &mut data); - // let data = INIT; assert!(data.len() > 0); let task = Task::from_elf("/bin/init", data.as_slice()).unwrap(); Arc::new(task) @@ -38,11 +36,54 @@ pub static INIT_PROCESS: Lazy> = Lazy::new(|| { /// 将初始进程加入进程池中进行调度 pub fn init_process() { let task = INIT_PROCESS.clone(); - let cwd = SYSTEM_ROOT_FS.get().unwrap().clone(); + let cwd = vfs::system_root_fs(); let root = cwd.clone(); task.access_inner().fs_info = FsContext::new(root, cwd); GLOBAL_TASK_MANAGER.add_task(Arc::new(FifoTask::new(task))); println!("Init process success"); } + +impl DriverTask for Task { + fn to_wait(&self) { + self.update_state(TaskState::Waiting) + } + + fn to_wakeup(&self) { + self.update_state(TaskState::Ready) + } + + fn have_signal(&self) -> bool { + self.access_inner().signal_receivers.lock().have_signal() + } +} +pub struct DriverTaskImpl; +impl DriverWithTask for DriverTaskImpl { + fn get_task(&self) -> Arc { + let task = current_task().unwrap(); + task.clone() + } + + fn put_task(&self, task: Arc) { + let task = task.downcast_arc::().map_err(|_| ()).unwrap(); + GLOBAL_TASK_MANAGER.add_task(Arc::new(FifoTask::new(task))); + } + + fn suspend(&self) { + do_suspend(); + } +} + +impl DeviceWithTask for DriverTaskImpl { + fn transfer_ptr_raw(&self, ptr: usize) -> usize { + let task = current_task().unwrap(); + task.transfer_raw(ptr) + } + + fn transfer_buf_raw(&self, src: usize, size: usize) -> Vec<&mut [u8]> { + let task = current_task().unwrap(); + task.transfer_buffer(src as *const u8, size) + } +} + // online test has no sort.src // pub static SORT_SRC: &[u8] = include_bytes!("../../../sdcard/sort.src"); diff --git a/kernel/src/task/schedule.rs b/kernel/src/task/schedule.rs index 0bc67b99..7dfaf768 100644 --- a/kernel/src/task/schedule.rs +++ b/kernel/src/task/schedule.rs @@ -3,7 +3,7 @@ use alloc::sync::Arc; use core::arch::asm; use smpscheduler::FifoTask; -use pconst::signal::SignalNumber; +use constants::signal::SignalNumber; use crate::ipc::send_signal; use crate::task::context::switch; @@ -21,42 +21,33 @@ use crate::trap::check_timer_interrupt_pending; /// /// 之后如果在线程池中有任务需要调度,那么就把该任务的上下文切换到 CPU 上来运行; /// 否则该 CPU 将进入等待状态,等待其它核的中断信号。 -#[no_mangle] -pub fn first_into_user() -> ! { +pub fn run_task() -> ! { loop { - { - let cpu = current_cpu(); - if cpu.task.is_some() { - let task = cpu.task.take().unwrap(); - match task.state() { - TaskState::Sleeping | TaskState::Waiting => { - // drop(task); - } - TaskState::Zombie => { - // 退出时向父进程发送信号,其中选项可被 sys_clone 控制 - if task.send_sigchld_when_exit || task.pid == task.tid.0 { - let parent = task - .access_inner() - .parent - .clone() - .unwrap() - .upgrade() - .unwrap(); - send_signal(parent.pid, SignalNumber::SIGCHLD as usize); - } - // 通知全局表将 signals 删除 - task.terminate(); - } - _ => { - GLOBAL_TASK_MANAGER.add_task(Arc::new(FifoTask::new(task))); + let cpu = current_cpu(); + if cpu.task.is_some() { + let task = cpu.task.take().unwrap(); + match task.state() { + TaskState::Waiting => { + // drop(task); + } + TaskState::Zombie => { + // 退出时向父进程发送信号,其中选项可被 sys_clone 控制 + if task.send_sigchld_when_exit || task.pid == task.tid.0 { + let parent = task + .access_inner() + .parent.as_ref().unwrap().upgrade().unwrap(); + send_signal(parent.pid, SignalNumber::SIGCHLD as usize); } + task.terminate(); + } + _ => { + GLOBAL_TASK_MANAGER.add_task(Arc::new(FifoTask::new(task))); } } } - let cpu = current_cpu(); if let Some(task) = GLOBAL_TASK_MANAGER.pick_next_task() { // if process.get_tid() >= 1 { - // warn!("switch to task {}", process.get_tid()); + // warn!("switch to task {}", task.get_tid()); // } // update state to running task.inner().update_state(TaskState::Running); diff --git a/kernel/src/task/stack.rs b/kernel/src/task/stack.rs index 1ce8dee2..494ce871 100644 --- a/kernel/src/task/stack.rs +++ b/kernel/src/task/stack.rs @@ -1,40 +1,33 @@ //! 进程内核栈空间 -use alloc::vec::Vec; -use crate::ksync::Mutex; - -use crate::config::FRAME_BITS; -use crate::memory::{frame_alloc_contiguous, FrameTracker}; +use config::FRAME_SIZE; +use mem::{alloc_frames, free_frames}; /// 记录进程内核栈空间 #[derive(Debug)] pub struct Stack { /// 栈帧 - frames: Mutex>, + start_ptr: usize, + pages: usize, } impl Stack { /// 通过帧的个数创建一块新的 内核栈 pub fn new(pages: usize) -> Option { - let frames = frame_alloc_contiguous(pages) as usize >> FRAME_BITS; - let frames = (0..pages) - .into_iter() - .map(|i| FrameTracker::new(i + frames)) - .collect::>(); + let frames = alloc_frames(pages); Some(Stack { - frames: Mutex::new(frames), + start_ptr: frames as usize, + pages, }) } /// 获取帧顶指针 pub fn top(&self) -> usize { - let first = self.frames.lock().last().map(|frame| frame.end()); - first.unwrap() + self.start_ptr + self.pages * FRAME_SIZE } /// 回收内核栈空间。 pub fn release(&self) { - let mut frames = self.frames.lock(); - *frames = Vec::new(); + free_frames(self.start_ptr as _, self.pages) } } diff --git a/kernel/src/task/task.rs b/kernel/src/task/task.rs index ea46e10b..4ddd5a0f 100644 --- a/kernel/src/task/task.rs +++ b/kernel/src/task/task.rs @@ -3,17 +3,15 @@ //! Alien 中对于进程\线程的相关概念的设计与 Linux 类似,进程和线程共用一个控制块结构。 //! 使用 `clone` 创建新的进程(线程)时,会根据 flag 指明父子进程之间资源共享的程度。 //! tid 是标识不同任务的唯一标识。 -use crate::config::*; -use crate::error::{AlienError, AlienResult}; -use crate::fs::file::File; -use crate::fs::{STDIN, STDOUT, SYSTEM_ROOT_FS}; +use crate::fs::stdio::{STDIN, STDOUT}; use crate::ipc::{global_register_signals, ShmInfo}; -use crate::ksync::{Mutex, MutexGuard}; -use crate::memory::*; +use crate::mm::loader::{ + build_cow_address_space, build_elf_address_space, build_thread_address_space, UserStack, +}; +use crate::mm::map::{MMapInfo, MMapRegion, ProtFlags}; use crate::task::context::Context; use crate::task::heap::HeapInfo; use crate::task::stack::Stack; -use crate::timer::{read_timer, ITimerVal, TimeNow, ToClock}; use crate::trap::{trap_common_read_file, trap_return, user_trap_vector, TrapFrame}; use alloc::collections::BTreeMap; use alloc::string::{String, ToString}; @@ -21,21 +19,27 @@ use alloc::sync::{Arc, Weak}; use alloc::vec::Vec; use alloc::{format, vec}; use bit_field::BitField; +use config::*; +use constants::aux::*; +use constants::io::MapFlags; +use constants::ipc::RobustList; +use constants::signal::{SignalHandlers, SignalNumber, SignalReceivers, SignalUserContext}; +use constants::sys::TimeVal; +use constants::task::CloneFlags; +use constants::time::TimerType; +use constants::{AlienError, AlienResult}; +use constants::{LinuxErrno, PrLimit, PrLimitRes}; use core::fmt::{Debug, Formatter}; use core::ops::Range; use gmanager::MinimalManager; +use ksync::{Mutex, MutexGuard}; +use mem::{kernel_satp, VmmPageAllocator, FRAME_REF_MANAGER}; use page_table::addr::{align_down_4k, align_up_4k, VirtAddr}; use page_table::pte::MappingFlags; use page_table::table::Sv39PageTable; -use pconst::aux::*; -use pconst::io::MapFlags; -use pconst::ipc::RobustList; -use pconst::signal::{SignalHandlers, SignalNumber, SignalReceivers, SignalUserContext}; -use pconst::sys::TimeVal; -use pconst::task::CloneFlags; -use pconst::time::TimerType; -use pconst::{LinuxErrno, PrLimit, PrLimitRes}; use spin::Lazy; +use timer::{read_timer, ITimerVal, TimeNow, ToClock}; +use vfs::kfile::File; use vfscore::dentry::VfsDentry; type FdManager = MinimalManager>; @@ -91,7 +95,7 @@ pub struct TaskInner { /// 用于记录当前线程组中的线程个数 pub thread_number: usize, /// 地址空间 - pub address_space: Arc>>, + pub address_space: Arc>>, /// 线程状态 pub state: TaskState, /// 父亲任务控制块 @@ -165,10 +169,6 @@ pub struct TaskTimer { } impl TaskTimer { - /// 创建一个新的任务计数器 - pub fn new() -> Self { - Self::default() - } /// 清除当前的计数器信息,将 timer_remained 置为 0 pub fn clear(&mut self) { self.timer_type = TimerType::NONE; @@ -265,7 +265,7 @@ pub enum TaskState { /// 运行态 Running, /// 等待一段时间 - Sleeping, + // Sleeping, /// 等待一个事件 Waiting, /// 僵尸态,等待父进程回收资源 @@ -367,15 +367,6 @@ impl Task { &inner.context as *const Context } - pub fn get_context(&self) -> Context { - let inner = self.inner.lock(); - inner.context.clone() - } - - pub fn kstack_top(&self) -> usize { - self.kernel_stack.top() - } - /// 获取任务上下文的可变指针 pub fn get_context_mut_raw_ptr(&self) -> *mut Context { let mut inner = self.inner.lock(); @@ -449,25 +440,6 @@ impl Task { inner.exit_code } - /// 用于判断一个文件是否存在在该进程的文件描述符表中,如果存在返回该文件描述符 - pub fn file_existed(&self, file: Arc) -> Option> { - let inner = self.inner.lock(); - let fd_table = inner.fd_table.lock(); - let fds = fd_table.data(); - fds.iter().find_map(|f| { - if f.is_some() { - let f = f.as_ref().unwrap(); - if Arc::ptr_eq(f, &file) { - Some(f.clone()) - } else { - None - } - } else { - None - } - }) - } - /// 用于获取文件描述符id号为 fd 的 文件描述符 pub fn get_file(&self, fd: usize) -> Option> { let inner = self.inner.lock(); @@ -717,31 +689,6 @@ impl TaskInner { res } - /// 将虚拟地址空间中的一段缓冲区的首地址 `ptr` 和 缓冲区的长度 `len` 转换为 实地址下的一组页 - pub fn transfer_raw_buffer(&self, ptr: *const u8, len: usize) -> Vec<&'static mut [u8]> { - let address_space = &self.address_space.lock(); - let mut start = ptr as usize; - let end = start + len; - let mut v = Vec::new(); - while start < end { - let (start_phy, flag, _) = address_space.query(VirtAddr::from(start)).unwrap(); - assert!(flag.contains(MappingFlags::V)); - // start_phy向上取整到FRAME_SIZE - let bound = (start & !(FRAME_SIZE - 1)) + FRAME_SIZE; - let len = if bound > end { - end - start - } else { - bound - start - }; - unsafe { - let buf = core::slice::from_raw_parts_mut(start_phy.as_usize() as *mut u8, len); - v.push(buf); - } - start = bound; - } - v - } - /// 从物理地址的 `src` 处取一个长度为 `len` 类型为 T 的缓冲区 赋到 用户虚拟地址空间下的 `dst` 处 pub fn copy_to_user_buffer( &mut self, @@ -1020,6 +967,7 @@ impl TaskInner { self.heap.lock().clone() } + #[allow(unused)] /// (待实现)缩减堆空间 pub fn shrink_heap(_addr: usize) -> Result { todo!() @@ -1173,7 +1121,7 @@ impl TaskInner { // warn!("add mmap region:{:#x?}",region); self.mmap.add_region(region); let start = v_range.start; - let mut map_flags = prot.into(); // no V flag + let mut map_flags: MappingFlags = prot.into(); // no V flag map_flags |= "AD".into(); self.address_space .lock() @@ -1256,7 +1204,7 @@ impl TaskInner { let region = self.mmap.get_region(addr).ok_or(AlienError::EINVAL)?; // now we need make sure the start is equal to the start of the region, and the len is equal to the len of the region // update page table - let mut map_flags = region.prot.into(); + let mut map_flags: MappingFlags = region.prot.into(); map_flags |= "V".into(); let mut address_space = self.address_space.lock(); @@ -1301,7 +1249,7 @@ impl TaskInner { let region = is_mmap.unwrap(); // assert_eq!(addr % FRAME_SIZE, 0); // update page table - let mut map_flags = region.prot.into(); + let mut map_flags: MappingFlags = region.prot.into(); map_flags |= "VAD".into(); warn!( "invalid page fault at {:#x}, flag is :{:?}", @@ -1459,7 +1407,7 @@ impl Task { let k_stack = Stack::new(USER_KERNEL_STACK_SIZE / FRAME_SIZE)?; let k_stack_top = k_stack.top(); let stack_info = elf_info.stack_top - USER_STACK_SIZE..elf_info.stack_top; - let cwd = SYSTEM_ROOT_FS.get().unwrap().clone(); + let cwd = vfs::system_root_fs(); let process = Task { tid, @@ -1515,7 +1463,7 @@ impl Task { let argc_ptr = user_stack.push(0).unwrap(); let trap_frame = process.trap_frame(); - *trap_frame = TrapFrame::from_app_info( + *trap_frame = TrapFrame::init_for_task( elf_info.entry, argc_ptr, kernel_satp(), @@ -1853,7 +1801,7 @@ impl Task { .query(VirtAddr::from(TRAP_CONTEXT_BASE)) .unwrap(); let trap_frame = TrapFrame::from_raw_ptr(physical.as_usize() as *mut TrapFrame); - *trap_frame = TrapFrame::from_app_info( + *trap_frame = TrapFrame::init_for_task( elf_info.entry, user_sp, kernel_satp(), diff --git a/kernel/src/timer/mod.rs b/kernel/src/time.rs similarity index 61% rename from kernel/src/timer/mod.rs rename to kernel/src/time.rs index 0c5b05da..3c5098fe 100644 --- a/kernel/src/timer/mod.rs +++ b/kernel/src/time.rs @@ -10,174 +10,26 @@ //! 在任务控制块中记录相应数据的字段为 `timer`(结构为 `TaskTimer` )。 //! //! 对于时间片 (每次引发时钟中断的时间间隔) 大小的设计:目前 Alien 中用户态和内核态下采用相同的时间片间隔,1s 内触发 10 次时钟中断。 -use alloc::collections::BinaryHeap; -use alloc::sync::Arc; -use core::cmp::Ordering; - -use crate::ksync::Mutex; -use pconst::sys::TimeVal; -use pconst::time::{ClockId, TimerType}; -use pconst::LinuxErrno; -use smpscheduler::FifoTask; -use spin::Lazy; +use crate::task::{current_task, do_suspend, StatisticalData}; +use constants::sys::TimeVal; +use constants::time::{ClockId, TimerType}; +use constants::LinuxErrno; +use log::{info, warn}; +use platform::config::CLOCK_FREQ; +use platform::set_timer; use syscall_table::syscall_func; -use vfscore::utils::VfsTimeSpec; - -use crate::arch; -use crate::config::CLOCK_FREQ; -use crate::task::{current_task, do_suspend, StatisticalData, Task, GLOBAL_TASK_MANAGER}; +use timer::{read_timer, ITimerVal, TimeNow, TimeSpec, Times}; /// 每秒包含的 时间片 数,每隔一个时间片,就会产生一个时钟中断 const TICKS_PER_SEC: usize = 10; // const TICKS_PER_SEC_IN_KERNEL: usize = 1000; -/// 每秒包含的毫秒数 -const MSEC_PER_SEC: usize = 1000; - -/// 程序运行时间 -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Times { - /// the ticks of user mode - pub tms_utime: usize, - /// the ticks of kernel mode - pub tms_stime: usize, - /// the ticks of user mode of child process - pub tms_cutime: usize, - /// the ticks of kernel mode of child process - pub tms_cstime: usize, -} - -impl Times { - /// 创建一个各字段值都为 0 的新 `Times` 变量 - pub fn new() -> Self { - Self { - tms_utime: 0, - tms_stime: 0, - tms_cutime: 0, - tms_cstime: 0, - } - } - - /// 从一个 [`StatisticalData`] 结构 (一般为 task 的 statistical_data 字段) 得到一个 `Times` 变量 - pub fn from_process_data(data: &StatisticalData) -> Self { - Self { - tms_stime: data.tms_stime, - tms_utime: data.tms_utime, - tms_cstime: data.tms_cstime, - tms_cutime: data.tms_cutime, - } - } -} - -/// 实现 `TimeNow` 特征的时钟结构,能够通过调用 `now` 方法得出 表示当前的 cpu 时间的一个本类型时钟 -pub trait TimeNow { - fn now() -> Self; -} - -/// 实现 `ToClock` 特征的时钟结构,能够将所表示的时间间隔,转换为 cpu 时钟 -pub trait ToClock { - fn to_clock(&self) -> usize; -} - -/// 实现 `TimeFromFreq` 特征的时钟结构,能够实现从 cpu时钟跳变的次数 初始化一个本类型的时钟 -pub trait TimeFromFreq { - fn from_freq(freq: usize) -> Self; -} - -impl TimeNow for TimeVal { - fn now() -> Self { - let time = read_timer(); - Self { - tv_sec: time / CLOCK_FREQ, - tv_usec: (time % CLOCK_FREQ) * 1000000 / CLOCK_FREQ, - } - } -} - -impl ToClock for TimeVal { - fn to_clock(&self) -> usize { - self.tv_sec * CLOCK_FREQ + self.tv_usec * CLOCK_FREQ / 1000_000 - } -} - -impl TimeFromFreq for TimeVal { - fn from_freq(freq: usize) -> Self { - Self { - tv_sec: freq / CLOCK_FREQ, - tv_usec: (freq % CLOCK_FREQ) * 1000000 / CLOCK_FREQ, - } - } -} - -/// 更精细的时间,秒(s)+纳秒(ns) -#[repr(C)] -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub struct TimeSpec { - pub tv_sec: usize, - pub tv_nsec: usize, //0~999999999 -} - -impl TimeSpec { - /// 创建一个新的 [`TimeSpec`] 时钟 - pub fn new(sec: usize, ns: usize) -> Self { - Self { - tv_sec: sec, - tv_nsec: ns, - } - } - - /// 获取一个可以表示当前 cpu 时间的一个 [`TimeSpec`] 时钟 - pub fn now() -> Self { - let time = read_timer(); - Self { - tv_sec: time / CLOCK_FREQ, - tv_nsec: (time % CLOCK_FREQ) * 1000000000 / CLOCK_FREQ, - } - } - - /// 将本时钟所表示的时间间隔转化为 cpu 上时钟的跳变数 - pub fn to_clock(&self) -> usize { - self.tv_sec * CLOCK_FREQ + self.tv_nsec * CLOCK_FREQ / 1000_000_000 - } -} - -impl TimeFromFreq for TimeSpec { - fn from_freq(freq: usize) -> Self { - Self { - tv_sec: freq / CLOCK_FREQ, - tv_nsec: (freq % CLOCK_FREQ) * 1000000000 / CLOCK_FREQ, - } - } -} - -impl Into for TimeSpec { - fn into(self) -> VfsTimeSpec { - VfsTimeSpec::new(self.tv_sec as u64, self.tv_nsec as u64) - } -} -/// [`getitimer`] / [`setitimer`] 指定的类型,用户执行系统调用时获取和输入的计时器 -#[repr(C)] -#[derive(Debug, Copy, Clone, Default)] -pub struct ITimerVal { - /// 计时器超时间隔 - pub it_interval: TimeVal, - /// 计时器当前所剩时间 - pub it_value: TimeVal, -} - -/// 获取当前计时器的值 -#[inline] -pub fn read_timer() -> usize { - arch::read_timer() -} - /// 设置下一次时钟的中断 #[inline] pub fn set_next_trigger() { let next = read_timer() + CLOCK_FREQ / TICKS_PER_SEC; assert!(next > read_timer()); - crate::sbi::set_timer(next); + set_timer(next); } /// 设置内核态中下一次时钟的中断 @@ -187,13 +39,7 @@ pub fn set_next_trigger() { pub fn set_next_trigger_in_kernel() { let next = read_timer() + CLOCK_FREQ / TICKS_PER_SEC; assert!(next > read_timer()); - crate::sbi::set_timer(next); -} - -/// 获取当前时间,以 ms 为单位 -// #[syscall_func(169)] -pub fn get_time_ms() -> isize { - (read_timer() / (CLOCK_FREQ / MSEC_PER_SEC)) as isize + set_timer(next); } /// 一个系统调用函数,获取当前的时间,获取的时间将存储在`tv`所指向的[`TimeVal`]结构处。 @@ -217,11 +63,21 @@ pub fn get_time_of_day(tv: *mut u8) -> isize { pub fn times(tms: *mut u8) -> isize { let mut task = current_task().unwrap().access_inner(); let statistic_data = task.statistical_data(); - let time = Times::from_process_data(statistic_data); + let time = times_from_process_data(statistic_data); task.copy_to_user(&time, tms as *mut Times); 0 } +/// 从一个 [`StatisticalData`] 结构 (一般为 task 的 statistical_data 字段) 得到一个 `Times` 变量 +pub fn times_from_process_data(data: &StatisticalData) -> Times { + Times { + tms_stime: data.tms_stime, + tms_utime: data.tms_utime, + tms_cstime: data.tms_cstime, + tms_cutime: data.tms_cutime, + } +} + /// 一个系统调用函数,暂停本进程直到一段时间后结束,要暂停的时间将保存在`req`所指向的[`TimeSpec`]结构处。 /// 但在`nanosleep`执行过程中,本进程有可能被其他信号唤醒。 /// 函数若正常停止`req`时间则返回0;如果由于因为其他信号而被唤醒,此时函数返回-1(EINTR)。 @@ -247,7 +103,6 @@ pub fn nanosleep(req: *mut u8, _: *mut u8) -> isize { return LinuxErrno::EINTR as isize; } } - 0 } @@ -273,78 +128,11 @@ pub fn clock_get_time(clock_id: usize, tp: *mut u8) -> isize { 0 } -/// 实际放入计时器队列中的计时器结构。 -/// -/// 当发生时钟中断时,会检查所有计时器队列中的计时器是否超时,具体可见 [`check_timer_queue`] -#[derive(Debug)] -pub struct Timer { - /// 计时器超时时间 - end_time: usize, - /// 在该计时器上进行等待的进程 - process: Arc, -} - -impl Timer { - /// 通过传入的 超时时间 和 等待进程的控制块 创建一个新的 `Timer` 结构 - pub fn new(end_time: usize, process: Arc) -> Self { - Self { end_time, process } - } - - /// 获取等待在该计时器上的进程的控制块信息 - pub fn get_task(&self) -> &Arc { - &self.process - } -} - -impl PartialEq for Timer { - fn eq(&self, other: &Self) -> bool { - self.end_time == other.end_time - } -} - -impl Eq for Timer {} - -impl PartialOrd for Timer { - fn partial_cmp(&self, other: &Self) -> Option { - // reverse order - Some(other.end_time.cmp(&self.end_time)) - } -} - -impl Ord for Timer { - fn cmp(&self, other: &Self) -> Ordering { - // reverse order - other.end_time.cmp(&self.end_time) - } -} - -/// 存储所有当前处于等待状态的计时器,是一个二叉树结构。 -/// -/// 保证存储在该队列中的计时器,按照超时时间 由先到后 的次序排列。 -pub static TIMER_QUEUE: Lazy>> = - Lazy::new(|| Mutex::new(BinaryHeap::new())); - -/// 将一个需要等待在 超时时间为 `end_time` 的计数器上的进程记录到计数器列表中 -pub fn push_to_timer_queue(process: Arc, end_time: usize) { - TIMER_QUEUE.lock().push(Timer::new(end_time, process)); -} - /// 当发生时钟中断时,`trap_handler` 会调用该函数检查所有计时器队列中的计时器,并唤醒等待在这些计时器上的进程 /// /// 遍历所有计时器队列 [`TIMER_QUEUE`] 中的计时器,若计时器的超时时间在当前时间之前(即已超时),那么将该等待的进程加入 /// 线程池的首位,马上对其进行调度。 -pub fn check_timer_queue() { - let now = read_timer(); - let mut queue = TIMER_QUEUE.lock(); - while let Some(timer) = queue.peek() { - if timer.end_time <= now { - let timer = queue.pop().unwrap(); - GLOBAL_TASK_MANAGER.put_prev_task(Arc::new(FifoTask::new(timer.process)), true); - } else { - break; - } - } -} +pub fn check_timer_queue() {} /// 一个系统调用函数,用于获取当前进程的计时器,保存在`current_value`指向的[`ITimerVal`]结构处。 /// 由于Alien目前每个进程只支持一个计时器,原定于分辨计时器种类的`_which`在此处并没有派上用场。 @@ -376,7 +164,7 @@ pub fn getitimer(_which: usize, current_value: usize) -> isize { pub fn setitimer(which: usize, current_value: usize, old_value: usize) -> isize { let which = TimerType::try_from(which).unwrap(); assert_ne!(which, TimerType::NONE); - warn!( + info!( "setitimer: which {:?} ,curret_value {:#x}, old_value {:#x}", which, current_value, old_value ); @@ -394,7 +182,7 @@ pub fn setitimer(which: usize, current_value: usize, old_value: usize) -> isize let mut itimer = ITimerVal::default(); task.access_inner() .copy_from_user(current_value as *const ITimerVal, &mut itimer); - error!("setitimer: itimer {:x?}", itimer); + info!("setitimer: itimer {:x?}", itimer); task.access_inner().set_timer(itimer, which); 0 } @@ -406,7 +194,7 @@ pub fn setitimer(which: usize, current_value: usize, old_value: usize) -> isize #[syscall_func(114)] pub fn clock_getres(id: usize, res: usize) -> isize { let id = ClockId::from_raw(id).unwrap(); - warn!("clock_getres: id {:?} ,res {:#x}", id, res); + info!("clock_getres: id {:?} ,res {:#x}", id, res); let task = current_task().unwrap(); let time_res = match id { ClockId::Monotonic => { @@ -434,15 +222,15 @@ pub fn clock_getres(id: usize, res: usize) -> isize { pub fn clock_nanosleep(clock_id: usize, flags: usize, req: usize, remain: usize) -> isize { const TIMER_ABSTIME: usize = 1; let id = ClockId::from_raw(clock_id).unwrap(); - warn!( + info!( "clock_nanosleep: id {:?} ,flags {:#x}, req {:#x}, remain {:#x}", id, flags, req, remain ); - let task = current_task().unwrap().clone(); match id { ClockId::Monotonic => { assert_eq!(flags, TIMER_ABSTIME); let mut target_time = TimeSpec::new(0, 0); + let task = current_task().unwrap().clone(); task.access_inner() .copy_from_user(req as *const TimeSpec, &mut target_time); let end_time = target_time.to_clock(); diff --git a/kernel/src/trap/context.rs b/kernel/src/trap/context.rs index b56b2089..5cf2bb4d 100644 --- a/kernel/src/trap/context.rs +++ b/kernel/src/trap/context.rs @@ -1,7 +1,6 @@ //! Trap 上下文 (Trap帧) 的定义和相关操作 -use bit_field::BitField; - -use crate::arch::riscv::sstatus::{self, Sstatus, SPP}; +use arch::ExtSstatus; +use riscv::register::sstatus::SPP; #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -19,26 +18,13 @@ pub struct TrapFrame { /// 记录所在的核 hart_id: usize, /// 给出 Trap 发生之前 CPU 处在哪个特权级等信息 - sstatus: Sstatus, + sstatus: ExtSstatus, fg: [usize; 2], } impl TrapFrame { - pub fn empty() -> Self { - Self { - x: [0; 32], - sepc: 0, - k_satp: 0, - k_sp: 0, - trap_handler: 0, - hart_id: 0, - sstatus: Sstatus::default(), - fg: [0; 2], - } - } - /// 获取当前的 Trap 帧下的 sstatus 寄存器的值 - pub fn get_status(&self) -> Sstatus { + pub fn get_status(&self) -> ExtSstatus { self.sstatus } @@ -47,9 +33,8 @@ impl TrapFrame { self.sepc += 4; } - /// pub fn from_raw_ptr(ptr: *mut TrapFrame) -> &'static mut Self { - unsafe { &mut *(ptr as *mut Self) } + unsafe { &mut *(ptr) } } /// 更新 Trap 帧中的内核栈地址 @@ -68,16 +53,16 @@ impl TrapFrame { } /// 用一个从文件系统中读取到的相关app数据,初始化一个 Trap 帧,使通过其创建的进程在初次进入用户态时能正常运行 - pub fn from_app_info( + pub fn init_for_task( entry: usize, sp: usize, k_satp: usize, k_sp: usize, trap_handler: usize, ) -> Self { - let mut sstatus = sstatus::read(); + let mut sstatus = ExtSstatus::read(); sstatus.set_spie(); - assert!(sstatus.0.get_bit(5)); //spie == 1 + // assert!(sstatus.0.get_bit(5)); //spie == 1 sstatus.set_spp(SPP::User); sstatus.set_sie(false); let mut res = Self { diff --git a/kernel/src/trap/exception.rs b/kernel/src/trap/exception.rs index 06cfb348..2157327a 100644 --- a/kernel/src/trap/exception.rs +++ b/kernel/src/trap/exception.rs @@ -3,12 +3,12 @@ //! 目前包括系统调用异常处理 [`syscall_exception_handler`]、页错误异常处理 [`page_exception_handler`] (包括 //! 指令页错误异常处理 [`instruction_page_fault_exception_handler`]、 加载页错误异常处理[`load_page_fault_exception_handler`]、 //! 储存页错误异常处理 [`store_page_fault_exception_handler`]) 和 文件读入异常处理 [`trap_common_read_file`]。 -use crate::arch::interrupt_enable; -use crate::error::{AlienError, AlienResult}; -use crate::fs::file::File; use crate::task::{current_task, current_trap_frame}; use alloc::sync::Arc; +use arch::interrupt_enable; +use constants::{AlienError, AlienResult}; use riscv::register::scause::{Exception, Trap}; +use vfs::kfile::File; /// 系统调用异常处理 pub fn syscall_exception_handler() { @@ -19,11 +19,12 @@ pub fn syscall_exception_handler() { cx.update_sepc(); // get system call return value let parameters = cx.parameters(); - let syscall_name = pconst::syscall_name(parameters[0]); + let syscall_name = constants::syscall_name(parameters[0]); - let p_name = current_task().unwrap().get_name(); - let tid = current_task().unwrap().get_tid(); - let pid = current_task().unwrap().get_pid(); + let task = current_task().unwrap(); + let p_name = task.get_name(); + let tid = task.get_tid(); + let pid = task.get_pid(); if !p_name.contains("shell") && !p_name.contains("init") && !p_name.contains("ls") { // ignore shell and init info!( @@ -144,14 +145,13 @@ pub fn store_page_fault_exception_handler(addr: usize) -> AlienResult<()> { /// 文件读入异常处理 pub fn trap_common_read_file(file: Arc, buf: &mut [u8], offset: u64) { - error!( + info!( "trap_common_read_file buf.len: {}, offset:{:#x}", buf.len(), offset ); - // let r = vfs_read_file::(file.get_file(), buf, offset); let r = file.read_at(offset, buf); if r.is_err() { - error!("page fault: read file error"); + info!("page fault: read file error"); } } diff --git a/kernel/src/trap/interrupt.rs b/kernel/src/trap/interrupt.rs index 5b73a731..12daafdb 100644 --- a/kernel/src/trap/interrupt.rs +++ b/kernel/src/trap/interrupt.rs @@ -1,10 +1,10 @@ //! Alien 的外部中断处理 //! //! 目前仅有时钟中断处理函数。 -use crate::interrupt::record::write_irq_info; use crate::ipc::solve_futex_wait; use crate::task::do_suspend; -use crate::timer::{check_timer_queue, set_next_trigger}; +use crate::time::{check_timer_queue, set_next_trigger}; +use interrupt::record::write_irq_info; /// 时钟中断处理函数 pub fn timer_interrupt_handler() { diff --git a/kernel/src/trap/mod.rs b/kernel/src/trap/mod.rs index 8ba41551..528723e4 100644 --- a/kernel/src/trap/mod.rs +++ b/kernel/src/trap/mod.rs @@ -1,32 +1,27 @@ -use core::arch::{asm, global_asm}; - use bit_field::BitField; -use page_table::addr::VirtAddr; +use core::arch::{asm, global_asm}; use riscv::register::sstatus::SPP; -use riscv::register::{sepc, sscratch, stval}; +use riscv::register::{sepc, sscratch, sstatus, stval, stvec}; +use constants::signal::SignalNumber; +use constants::signal::SIGNAL_RETURN_TRAP; +use constants::time::TimerType; pub use context::TrapFrame; pub use exception::trap_common_read_file; -use pconst::signal::SignalNumber; -use pconst::signal::SIGNAL_RETURN_TRAP; -use pconst::time::TimerType; -use crate::arch::riscv::register::scause::{Exception, Interrupt, Trap}; -use crate::arch::riscv::register::stvec; -use crate::arch::riscv::register::stvec::TrapMode; -use crate::arch::riscv::sstatus; -use crate::arch::{ - external_interrupt_enable, hart_id, interrupt_disable, interrupt_enable, is_interrupt_enable, - timer_interrupt_enable, -}; -use crate::config::TRAMPOLINE; -use crate::error::AlienError; -use crate::interrupt::external_interrupt_handler; -use crate::interrupt::record::write_irq_info; use crate::ipc::{send_signal, signal_handler, signal_return, solve_futex_wait}; -use crate::memory::KERNEL_SPACE; use crate::task::{current_task, current_trap_frame, current_user_token, do_exit, do_suspend}; -use crate::timer::{check_timer_queue, set_next_trigger, set_next_trigger_in_kernel}; +use crate::time::{check_timer_queue, set_next_trigger, set_next_trigger_in_kernel}; +use ::interrupt::external_interrupt_handler; +use ::interrupt::record::write_irq_info; +use arch::{ + external_interrupt_enable, interrupt_disable, interrupt_enable, is_interrupt_enable, + timer_interrupt_enable, +}; +use config::TRAMPOLINE; +use constants::AlienError; +use riscv::register::scause::{Exception, Interrupt, Trap}; +use riscv::register::stvec::TrapMode; mod context; mod exception; @@ -56,7 +51,6 @@ pub fn trap_return() -> ! { let sie = sstatues.0.get_bit(1); assert!(enable); assert!(!sie); - let trap_cx_ptr = current_task().unwrap().trap_frame_ptr(); let user_satp = current_user_token(); let restore_va = user_r as usize - user_v as usize + TRAMPOLINE; @@ -211,8 +205,7 @@ impl TrapHandler for Trap { self, stval, sepc ); { - let kernel_space = KERNEL_SPACE.read(); - let phy = kernel_space.query(VirtAddr::from(stval)); + let phy = mem::query_kernel_space(stval); debug!("physical address: {:#x?}", phy); } } @@ -259,12 +252,7 @@ pub fn user_trap_vector() { panic!("user_trap_vector: spp == SPP::Supervisor"); } { - let task = current_task().unwrap_or_else(|| { - panic!( - "can't find task in hart {}, but it's in user mode", - hart_id() as usize - ) - }); + let task = current_task().expect("user_trap_vector: current_task is none"); // update process statistics task.access_inner().update_user_mode_time(); check_task_timer_expired(); @@ -273,12 +261,12 @@ pub fn user_trap_vector() { let cause = riscv::register::scause::read(); let cause = cause.cause(); cause.do_user_handle(); - let process = current_task().unwrap(); + let task = current_task().unwrap(); if cause != Trap::Interrupt(Interrupt::SupervisorTimer) { // update process statistics - process.access_inner().update_kernel_mode_time(); + task.access_inner().update_kernel_mode_time(); } - process.access_inner().update_timer(); + task.access_inner().update_timer(); check_task_timer_expired(); trap_return(); } diff --git a/subsystems/arch/Cargo.toml b/subsystems/arch/Cargo.toml new file mode 100644 index 00000000..23804066 --- /dev/null +++ b/subsystems/arch/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "arch" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +riscv = { version = "0.10" } \ No newline at end of file diff --git a/subsystems/arch/src/lib.rs b/subsystems/arch/src/lib.rs new file mode 100644 index 00000000..a4c2b0c8 --- /dev/null +++ b/subsystems/arch/src/lib.rs @@ -0,0 +1,5 @@ +#![no_std] + +mod riscv; + +pub use riscv::*; diff --git a/kernel/src/arch/mod.rs b/subsystems/arch/src/riscv/mod.rs similarity index 53% rename from kernel/src/arch/mod.rs rename to subsystems/arch/src/riscv/mod.rs index 5f2a2506..d91145d8 100644 --- a/kernel/src/arch/mod.rs +++ b/subsystems/arch/src/riscv/mod.rs @@ -1,9 +1,10 @@ -use core::arch::asm; +mod regs; -use self::riscv::register::sie; -use self::riscv::sstatus; +pub use regs::*; -pub mod riscv; +use core::arch::asm; +use riscv::asm::sfence_vma_all; +use riscv::register::satp; /// 获取当前的 hart id pub fn hart_id() -> usize { @@ -18,48 +19,48 @@ pub fn hart_id() -> usize { /// 检查全局中断是否开启 pub fn is_interrupt_enable() -> bool { - sstatus::read().sie() + riscv::register::sstatus::read().sie() } /// 关闭全局中断 pub fn interrupt_disable() { unsafe { - sstatus::clear_sie(); + riscv::register::sstatus::clear_sie(); } } /// 开启全局中断 pub fn interrupt_enable() { unsafe { - sstatus::set_sie(); + riscv::register::sstatus::set_sie(); } } /// 开启外部中断 pub fn external_interrupt_enable() { unsafe { - sie::set_sext(); + riscv::register::sie::set_sext(); } } /// 开启软件中断 pub fn software_interrupt_enable() { unsafe { - sie::set_ssoft(); + riscv::register::sie::set_ssoft(); } } /// 关闭外部中断 pub fn external_interrupt_disable() { unsafe { - sie::clear_sext(); + riscv::register::sie::clear_sext(); } } /// 开启时钟中断 pub fn timer_interrupt_enable() { unsafe { - sie::set_stimer(); + riscv::register::sie::set_stimer(); } } @@ -68,11 +69,18 @@ pub fn read_timer() -> usize { riscv::register::time::read() } -#[macro_export] -macro_rules! write_csr { - ($csr:ident, $val:expr) => { - unsafe { - asm!(concat!("csrw ", stringify!($csr), ", {}"), in(reg) $val); - } - }; +/// 激活页表模式 +pub fn activate_paging_mode(root_ppn: usize) { + unsafe { + sfence_vma_all(); + satp::set(satp::Mode::Sv39, 0, root_ppn); + sfence_vma_all(); + } +} + +/// Permit Supervisor User Memory access +pub fn allow_access_user_memory() { + unsafe { + riscv::register::sstatus::set_sum(); + } } diff --git a/subsystems/arch/src/riscv/regs.rs b/subsystems/arch/src/riscv/regs.rs new file mode 100644 index 00000000..ab3d9dc5 --- /dev/null +++ b/subsystems/arch/src/riscv/regs.rs @@ -0,0 +1,39 @@ +use core::arch::asm; +use riscv::register::sstatus::SPP; + +#[derive(Debug, Default, Copy, Clone)] +pub struct ExtSstatus(pub usize); + +impl ExtSstatus { + pub fn read() -> Self { + let val: usize; + unsafe { + asm!("csrr {},sstatus", out(reg)val); + } + ExtSstatus(val) + } + pub fn set_value(&mut self, val: usize) { + self.0 = val; + } + pub fn set_spp(&mut self, spp: SPP) { + // self.0.set_bit(8, spp as usize != 0); + self.0 = self.0 & !(1 << 8) | ((spp as usize) << 8); + } + pub fn spp(&self) -> SPP { + let v = (self.0 >> 8) & 1; + if v == 1 { + SPP::Supervisor + } else { + SPP::User + } + } + pub fn set_spie(&mut self) { + self.0 |= 1 << 5; + } + pub fn sie(&self) -> bool { + (self.0 & (1 << 1)) != 0 + } + pub fn set_sie(&mut self, value: bool) { + self.0 = self.0 & !(1 << 1) | ((value as usize) << 1); + } +} diff --git a/dep/basemachine/Cargo.toml b/subsystems/config/Cargo.toml similarity index 82% rename from dep/basemachine/Cargo.toml rename to subsystems/config/Cargo.toml index ce04ac4b..691bb071 100644 --- a/dep/basemachine/Cargo.toml +++ b/subsystems/config/Cargo.toml @@ -1,9 +1,10 @@ [package] -name = "basemachine" +name = "config" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -fdt = "0.1.5" \ No newline at end of file + + diff --git a/subsystems/config/build.rs b/subsystems/config/build.rs new file mode 100644 index 00000000..53e423ec --- /dev/null +++ b/subsystems/config/build.rs @@ -0,0 +1,21 @@ +use std::fs; +use std::path::Path; + +fn main() { + println!("cargo:rerun-if-changed={}", "src/lib.rs"); + let cpus = option_env!("SMP").unwrap_or("1"); + let cpus = cpus.parse::().unwrap(); + let config_file = Path::new("src/lib.rs"); + let config = fs::read_to_string(config_file).unwrap(); + let cpus = format!("pub const CPU_NUM: usize = {};\n", cpus); + let mut new_config = String::new(); + for line in config.lines() { + if line.starts_with("pub const CPU_NUM: usize = ") { + new_config.push_str(cpus.as_str()); + } else { + new_config.push_str(line); + new_config.push_str("\n"); + } + } + fs::write(config_file, new_config).unwrap(); +} diff --git a/subsystems/config/src/lib.rs b/subsystems/config/src/lib.rs new file mode 100644 index 00000000..560b48b1 --- /dev/null +++ b/subsystems/config/src/lib.rs @@ -0,0 +1,56 @@ +#![no_std] +//! 配置文件 + +/// Alien os的标志 +pub const FLAG: &str = r" + _ _ _ + / \ | | (_) ___ _ __ + / _ \ | | | | / _ \ | '_ \ + / ___ \ | | | | | __/ | | | | + /_/ \_\ |_| |_| \___| |_| |_| +"; + +/// 物理页大小 +pub const FRAME_SIZE: usize = 0x1000; +/// 物理页大小的位数 +pub const FRAME_BITS: usize = 12; +/// 内核启动栈大小 +pub const STACK_SIZE: usize = 1024 * 64; +/// 内核启动栈大小的位数 +pub const STACK_SIZE_BITS: usize = 16; + +/// 可配置的启动cpu数量 +pub const CPU_NUM: usize = 1; + +// todo!(if the app linker script changed, this should be changed too) +/// 进程的堆空间上限 +pub const PROCESS_HEAP_MAX: usize = u32::MAX as usize + 1; +/// 跳板页的虚拟地址 +pub const TRAMPOLINE: usize = usize::MAX - 2 * FRAME_SIZE + 1; +/// trap context的虚拟地址 +pub const TRAP_CONTEXT_BASE: usize = TRAMPOLINE - FRAME_SIZE; + +/// app内核栈大小 +pub const USER_KERNEL_STACK_SIZE: usize = 0x1000 * 2; +/// app用户栈大小 +pub const USER_STACK_SIZE: usize = 0x50_000; + +/// pipe缓冲区大小 +pub const PIPE_BUF: usize = 65536; + +/// 线程数量大小限制 +pub const MAX_THREAD_NUM: usize = 65536; +/// 描述符数量大小限制 +pub const MAX_FD_NUM: usize = 4096; + +/// 最大的输入事件数量 +pub const MAX_INPUT_EVENT_NUM: usize = 1024; + +/// 如果 elf 的 phdr 指示 base 是 0(如 libc-test 的 libc.so),则需要找一个非0的位置放置 +/// 我们将其从 0x4000_0000 开始放置。主要用于动态链接库使用 +pub const ELF_BASE_RELOCATE: usize = 0x400_0000; + +// QEMU user networking default IP +pub const QEMU_IP: &str = "10.0.2.15"; +// QEMU user networking gateway +pub const QEMU_GATEWAY: &str = "10.0.2.2"; diff --git a/subsystems/constants/Cargo.toml b/subsystems/constants/Cargo.toml new file mode 100644 index 00000000..1cd1d88b --- /dev/null +++ b/subsystems/constants/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "constants" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +pconst = { git = "https://github.com/os-module/pconst.git", features = ["trick"] } diff --git a/subsystems/constants/src/lib.rs b/subsystems/constants/src/lib.rs new file mode 100644 index 00000000..4797a30e --- /dev/null +++ b/subsystems/constants/src/lib.rs @@ -0,0 +1,38 @@ +#![no_std] +//! 导出 `pconst` 中的常量和数据结构, 定义Alien OS的错误类型 + +pub use pconst::*; +pub type AlienError = LinuxErrno; +pub type AlienResult = Result; + +#[derive(Copy, Clone, Debug, Eq, PartialOrd, PartialEq, Hash, Ord)] +pub struct DeviceId { + major: u32, + minor: u32, +} + +impl DeviceId { + pub fn new(major: u32, minor: u32) -> Self { + Self { major, minor } + } + pub fn major(&self) -> u32 { + self.major + } + pub fn minor(&self) -> u32 { + self.minor + } + pub fn id(&self) -> u64 { + ((self.major as u64) << 32) | (self.minor as u64) + } +} + +impl From for DeviceId { + fn from(id: u64) -> Self { + Self { + major: (id >> 32) as u32, + minor: (id & 0xffffffff) as u32, + } + } +} + +pub const AT_FDCWD: isize = -100isize; diff --git a/subsystems/device_interface/Cargo.toml b/subsystems/device_interface/Cargo.toml new file mode 100644 index 00000000..50e61212 --- /dev/null +++ b/subsystems/device_interface/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "device_interface" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +constants = { path = "../constants" } \ No newline at end of file diff --git a/subsystems/device_interface/src/lib.rs b/subsystems/device_interface/src/lib.rs new file mode 100644 index 00000000..aa50cced --- /dev/null +++ b/subsystems/device_interface/src/lib.rs @@ -0,0 +1,49 @@ +#![no_std] + +use constants::io::RtcTime; +use constants::AlienResult; +use core::any::Any; + +pub trait DeviceBase: Sync + Send { + fn hand_irq(&self); +} + +pub trait BlockDevice: Send + Sync + DeviceBase { + fn read(&self, buf: &mut [u8], offset: usize) -> AlienResult; + fn write(&self, buf: &[u8], offset: usize) -> AlienResult; + fn size(&self) -> usize; + fn flush(&self) -> AlienResult<()>; +} +pub trait LowBlockDevice { + fn read_block(&mut self, block_id: usize, buf: &mut [u8]) -> AlienResult<()>; + fn write_block(&mut self, block_id: usize, buf: &[u8]) -> AlienResult<()>; + fn capacity(&self) -> usize; + fn flush(&mut self) {} +} + +pub trait GpuDevice: Send + Sync + Any + DeviceBase { + fn update_cursor(&self); + fn get_framebuffer(&self) -> &mut [u8]; + fn flush(&self); + fn resolution(&self) -> (u32, u32); +} + +pub trait InputDevice: Send + Sync + DeviceBase { + fn is_empty(&self) -> bool; + fn read_event_with_block(&self) -> u64; + fn read_event_without_block(&self) -> Option; +} + +pub trait RtcDevice: Send + Sync + DeviceBase { + fn read_time(&self) -> RtcTime; +} + +pub trait UartDevice: Send + Sync + DeviceBase { + fn put(&self, c: u8); + fn get(&self) -> Option; + fn put_bytes(&self, bytes: &[u8]); + fn have_data_to_get(&self) -> bool; + fn have_space_to_put(&self) -> bool; +} + +pub trait NetDevice: DeviceBase {} diff --git a/subsystems/devices/Cargo.toml b/subsystems/devices/Cargo.toml new file mode 100644 index 00000000..91bf978b --- /dev/null +++ b/subsystems/devices/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "devices" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +arch = { path = "../arch" } +config = { path = "../config" } +platform = { path = "../platform" } +constants = { path = "../constants" } +ksync = { path = "../ksync" } +interrupt = { path = "../interrupt" } +drivers = { path = "../drivers" } +device_interface = { path = "../device_interface" } + +spin = "0" +fdt = { git = "https://github.com/repnop/fdt" } +log = "0" +vfscore = { git = "https://github.com/os-module/rvfs.git", features = [ + "linux_error", +] } + +virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers",rev = "de1c3b1"} +netcore = {git = "https://github.com/os-module/simple-net"} + + + +[dependencies.smoltcp] +git = "https://github.com/rcore-os/smoltcp.git" +rev = "2ade274" +default-features = false +features = [ + "alloc", + "log", # no std + "medium-ethernet", +] + + + +[features] +default = ["test"] +ramdisk = [] +test = [] +vf2 = [] # enable to probe vf2's sdcard diff --git a/kernel/src/device/block.rs b/subsystems/devices/src/block.rs similarity index 80% rename from kernel/src/device/block.rs rename to subsystems/devices/src/block.rs index e52b3c82..9bd70ec1 100644 --- a/kernel/src/device/block.rs +++ b/subsystems/devices/src/block.rs @@ -1,8 +1,6 @@ use alloc::sync::Arc; - -use crate::driver::GenericBlockDevice; -use crate::error::AlienResult; -use crate::fs::dev::DeviceId; +use constants::DeviceId; +use device_interface::BlockDevice; use spin::Once; use vfscore::error::VfsError; use vfscore::file::VfsFile; @@ -10,8 +8,7 @@ use vfscore::inode::{InodeAttr, VfsInode}; use vfscore::utils::{VfsFileStat, VfsNodeType, VfsPollEvents}; use vfscore::VfsResult; -use crate::interrupt::DeviceBase; - +use drivers::block_device::GenericBlockDevice; pub static BLOCK_DEVICE: Once> = Once::new(); pub fn init_block_device(block_device: Arc) { @@ -19,13 +16,6 @@ pub fn init_block_device(block_device: Arc) { BLOCK_DEVICE.call_once(|| block_device); } -pub trait BlockDevice: Send + Sync + DeviceBase { - fn read(&self, buf: &mut [u8], offset: usize) -> AlienResult; - fn write(&self, buf: &[u8], offset: usize) -> AlienResult; - fn size(&self) -> usize; - fn flush(&self) -> AlienResult<()>; -} - pub struct BLKDevice { device_id: DeviceId, device: Arc, @@ -52,10 +42,10 @@ impl VfsFile for BLKDevice { .map_err(|_| VfsError::IoError) } fn poll(&self, _event: VfsPollEvents) -> VfsResult { - todo!() + unimplemented!() } fn ioctl(&self, _cmd: u32, _arg: usize) -> VfsResult { - todo!() + unimplemented!() } fn flush(&self) -> VfsResult<()> { Ok(()) diff --git a/kernel/src/device/gpu.rs b/subsystems/devices/src/gpu.rs similarity index 87% rename from kernel/src/device/gpu.rs rename to subsystems/devices/src/gpu.rs index a2f9b5a5..e1bb8064 100644 --- a/kernel/src/device/gpu.rs +++ b/subsystems/devices/src/gpu.rs @@ -1,7 +1,5 @@ use alloc::sync::Arc; -use core::any::Any; - -use crate::fs::dev::DeviceId; +use constants::DeviceId; use spin::Once; use vfscore::error::VfsError; use vfscore::file::VfsFile; @@ -9,13 +7,7 @@ use vfscore::inode::{InodeAttr, VfsInode}; use vfscore::utils::{VfsFileStat, VfsNodeType}; use vfscore::VfsResult; -use crate::interrupt::DeviceBase; - -pub trait GpuDevice: Send + Sync + Any + DeviceBase { - fn update_cursor(&self); - fn get_framebuffer(&self) -> &mut [u8]; - fn flush(&self); -} +use device_interface::GpuDevice; pub static GPU_DEVICE: Once> = Once::new(); diff --git a/kernel/src/device/input.rs b/subsystems/devices/src/input.rs similarity index 59% rename from kernel/src/device/input.rs rename to subsystems/devices/src/input.rs index 2abcde11..27c43d4a 100644 --- a/kernel/src/device/input.rs +++ b/subsystems/devices/src/input.rs @@ -1,9 +1,8 @@ use alloc::sync::Arc; +use constants::DeviceId; +use device_interface::InputDevice; use spin::Once; - -use crate::fs::dev::DeviceId; -use syscall_table::syscall_func; use vfscore::error::VfsError; use vfscore::file::VfsFile; use vfscore::inode::{InodeAttr, VfsInode}; @@ -11,15 +10,6 @@ use vfscore::superblock::VfsSuperBlock; use vfscore::utils::{VfsFileStat, VfsNodeType, VfsPollEvents}; use vfscore::VfsResult; -use crate::interrupt::DeviceBase; -use crate::task::current_task; - -pub trait InputDevice: Send + Sync + DeviceBase { - fn is_empty(&self) -> bool; - fn read_event_with_block(&self) -> u64; - fn read_event_without_block(&self) -> Option; -} - pub struct INPUTDevice { device_id: DeviceId, device: Arc, @@ -85,54 +75,10 @@ impl VfsInode for INPUTDevice { pub static KEYBOARD_INPUT_DEVICE: Once> = Once::new(); pub static MOUSE_INPUT_DEVICE: Once> = Once::new(); -#[cfg(feature = "qemu")] pub fn init_keyboard_input_device(input_device: Arc) { KEYBOARD_INPUT_DEVICE.call_once(|| input_device); } -#[cfg(feature = "qemu")] + pub fn init_mouse_input_device(input_device: Arc) { MOUSE_INPUT_DEVICE.call_once(|| input_device); } - -/// 一个系统调用函数,用于获取鼠标和键盘事件。 -/// -/// `sys_event_get`会将获取到的事件将保存在event_buf所指向的内存位置处, -/// 此次允许获取到的事件的最大值(即event_buf)的大小由len指出。 -/// -/// 函数将返回成功获取到的事件个数。 -/// -#[syscall_func(2002)] -pub fn sys_event_get(event_buf: *mut u64, len: usize) -> isize { - let process = current_task().unwrap(); - let user_buffer = process.transfer_buffer(event_buf, len); - let mut count = 0; - for buf in user_buffer { - let mut index = 0; - let len = buf.len(); - while index < len { - let event = read_event(); - if event == 0 { - break; - } - buf[index] = event; - index += 1; - count += 1; - } - } - count -} - -fn read_event() -> u64 { - let (keyboard, mouse) = { - let kb = KEYBOARD_INPUT_DEVICE.get().unwrap(); - let mouse = MOUSE_INPUT_DEVICE.get().unwrap(); - (kb, mouse) - }; - if !keyboard.is_empty() { - keyboard.read_event_with_block() - } else if !mouse.is_empty() { - mouse.read_event_with_block() - } else { - 0 - } -} diff --git a/subsystems/devices/src/lib.rs b/subsystems/devices/src/lib.rs new file mode 100644 index 00000000..ebc47c8b --- /dev/null +++ b/subsystems/devices/src/lib.rs @@ -0,0 +1,432 @@ +#![no_std] + +mod block; +mod gpu; +mod input; +mod net; +mod prob; +mod rtc; +mod uart; + +extern crate alloc; + +use alloc::boxed::Box; +use alloc::sync::Arc; + +use crate::prob::Probe; +use alloc::vec::Vec; +use config::MAX_INPUT_EVENT_NUM; +use core::ptr::NonNull; +use device_interface::{DeviceBase, GpuDevice, LowBlockDevice}; +use drivers::rtc::GoldFishRtc; +use drivers::uart::{Uart, Uart16550, Uart8250}; +use fdt::Fdt; +use ksync::Mutex; +use log::info; +use platform::println; +use spin::{Lazy, Once}; +use virtio_drivers::transport::mmio::{MmioTransport, VirtIOHeader}; +use virtio_drivers::transport::{DeviceType, Transport}; +pub use block::{BLKDevice, BLOCK_DEVICE}; +use drivers::block_device::GenericBlockDevice; +pub use gpu::{GPUDevice, GPU_DEVICE}; +pub use input::{INPUTDevice, KEYBOARD_INPUT_DEVICE, MOUSE_INPUT_DEVICE}; +use interrupt::register_device_to_plic; +pub use rtc::{RTCDevice, RTC_DEVICE}; +pub use uart::{UARTDevice, UART_DEVICE}; + +pub struct DeviceInfo { + pub device: Arc, + pub irq: usize, + pub need_register: bool, +} + +pub static INITIALIZED_DEVICES: Lazy>> = Lazy::new(|| Mutex::new(Vec::new())); + +static TASK_FUNC: Once> = Once::new(); + +pub trait DeviceWithTask: Send + Sync { + fn transfer_ptr_raw(&self, ptr: usize) -> usize; + fn transfer_buf_raw(&self, src: usize, size: usize) -> Vec<&mut [u8]>; +} + +impl dyn DeviceWithTask { + fn copy_data_to_task(&self, src: *const T, dst: *mut T) { + let size = core::mem::size_of::(); + let bufs = self.transfer_buf_raw(dst as usize, size); + let src = unsafe { core::slice::from_raw_parts(src as *const u8, size) }; + let mut start = 0; + for buffer in bufs { + let len = if start + buffer.len() > size { + size - start + } else { + buffer.len() + }; + unsafe { + core::ptr::copy_nonoverlapping(src.as_ptr().add(start), buffer.as_mut_ptr(), len); + } + start += len; + } + } + fn copy_data_from_task(&self, src: *const T, dst: *mut T) { + let size = core::mem::size_of::(); + let bufs = self.transfer_buf_raw(src as usize, size); + let dst = unsafe { core::slice::from_raw_parts_mut(dst as *mut u8, size) }; + let mut start = 0; + for buffer in bufs { + let len = if start + buffer.len() > size { + size - start + } else { + buffer.len() + }; + unsafe { + core::ptr::copy_nonoverlapping(buffer.as_ptr(), dst.as_mut_ptr().add(start), len); + } + start += len; + } + } + fn transfer_ptr_mut(&self, ptr: *mut T) -> &'static mut T { + let ptr = ptr as usize; + let ptr = self.transfer_ptr_raw(ptr); + unsafe { &mut *(ptr as *mut T) } + } + fn transfer_ptr(&self, ptr: *const T) -> &'static T { + let ptr = ptr as usize; + let ptr = self.transfer_ptr_raw(ptr); + unsafe { &*(ptr as *const T) } + } +} + +/// Probe all devices from device tree and init them. +/// # Warning +/// Before init device, we should init platform first. +/// +/// todo!(The task_func should be replaced) +pub fn init_device(task_func: Box) { + TASK_FUNC.call_once(|| task_func); + + let dtb_ptr = platform::platform_dtb_ptr(); + + let dtb = unsafe { Fdt::from_ptr(dtb_ptr as *const u8).unwrap() }; + match dtb.probe_rtc() { + Some(rtc) => init_rtc(rtc), + None => { + println!("There is no rtc device"); + } + } + + match dtb.probe_uart() { + Some(uart) => init_uart(uart), + None => { + println!("There is no uart device"); + } + } + + match dtb.probe_virtio() { + Some(virtio_mmio_devices) => init_virtio_mmio(virtio_mmio_devices), + None => { + println!("There is no virtio-mmio device"); + } + } + + + +} + +fn init_rtc(rtc: prob::DeviceInfo) { + let info = rtc; + println!( + "Init rtc, base_addr:{:#x}, irq:{}", + info.base_addr, info.irq + ); + match info.compatible.as_str() { + "google,goldfish-rtc" => { + let rtc = Arc::new(GoldFishRtc::new(info.base_addr)); + let current_time = rtc.read_time_string(); + rtc::init_rtc(rtc.clone()); + register_device_to_plic(info.irq, rtc); + // INITIALIZED_DEVICES.lock().push(DeviceInfo { + // device: rtc, + // irq: info.irq, + // need_register: true, + // }); + println!("Init rtc success, current time: {:?}", current_time); + } + name => { + println!("Don't support rtc: {}", name); + } + } +} + +fn init_uart(uart: prob::DeviceInfo) { + let (base_addr, irq) = (uart.base_addr, uart.irq); + println!("Init uart, base_addr:{:#x},irq:{}", base_addr, irq); + match uart.compatible.as_str() { + "ns16550a" => { + // qemu + let uart = Uart16550::new(base_addr); + let uart = Arc::new(Uart::new(Box::new(uart))); + uart::init_uart(uart.clone()); + register_device_to_plic(irq, uart); + // INITIALIZED_DEVICES.lock().push(DeviceInfo { + // device: uart, + // irq, + // need_register: true, + // }); + } + "snps,dw-apb-uart" => { + // vf2 + let uart = Uart8250::new(base_addr); + let uart = Arc::new(Uart::new(Box::new(uart))); + uart::init_uart(uart.clone()); + register_device_to_plic(irq, uart); + // INITIALIZED_DEVICES.lock().push(DeviceInfo { + // device: uart, + // irq, + // need_register: true, + // }); + } + name => { + println!("Don't support uart: {}", name); + return; + } + } + println!("Init uart success"); +} + +// keyboard +const VIRTIO5: usize = 0x10005000; +// mouse +const VIRTIO6: usize = 0x10006000; + +pub fn init_virtio_mmio(devices: Vec) { + for device in devices { + let paddr = device.base_addr; + let header = NonNull::new(paddr as *mut VirtIOHeader).unwrap(); + match unsafe { MmioTransport::new(header) } { + Err(_) => {} + Ok(mut transport) => { + info!( + "Detected virtio MMIO device with vendor id {:#X}, device type {:?}, version {:?}, features:{:?}", + transport.vendor_id(), + transport.device_type(), + transport.version(), + transport.read_device_features(), + ); + info!("Probe virtio device: {:?}", transport.device_type()); + match transport.device_type() { + DeviceType::Input => { + if paddr == VIRTIO5 { + init_input_device(device, "keyboard"); + } else if paddr == VIRTIO6 { + init_input_device(device, "mouse"); + } + } + DeviceType::Block => init_block_device(device, Some(transport)), + DeviceType::GPU => init_gpu(device), + DeviceType::Network => init_net(device), + _ => {} + } + } + } + } +} + +#[cfg(feature = "ramdisk")] +core::arch::global_asm!( + r#" + .section .data + .global img_start + .global img_end + .align 12 + img_start: + .incbin "./tools/sdcard.img" + img_end: + "# +); + +#[cfg(feature = "ramdisk")] +extern "C" { + pub fn img_start(); + pub fn img_end(); +} +#[cfg(feature = "ramdisk")] +pub fn checkout_fs_img() { + let img_start = img_start as usize; + let img_end = img_end as usize; + let img_size = img_end - img_start; + println!( + "img_start: {:#x}, img_end: {:#x}, img_size: {:#x}", + img_start, img_end, img_size + ); +} + +fn init_block_device(blk: prob::DeviceInfo, mmio_transport: Option) { + use drivers::block_device::{VirtIOBlkWrapper}; + let (base_addr, irq) = (blk.base_addr, blk.irq); + match blk.compatible.as_str() { + "virtio,mmio" => { + // qemu + // let mut block_device = VirtIOBlkWrapper::new(blk.base_addr); + let block_device = VirtIOBlkWrapper::from_mmio(mmio_transport.unwrap()); + println!("Init block device, base_addr:{:#x},irq:{}", base_addr, irq); + let size = block_device.capacity(); + println!("Block device size is {}MB", size * 512 / 1024 / 1024); + let block_device = Arc::new(GenericBlockDevice::new(Box::new(block_device))); + block::init_block_device(block_device); + // register_device_to_plic(irq, block_device); + println!("Init block device success"); + } + "starfive,jh7110-sdio" => { + // visionfi ve2/starfive2 + #[cfg(not(feature = "ramdisk"))] + { + use arch::read_timer; + use platform::config::CLOCK_FREQ; + pub fn sleep(ms: usize) { + let start = read_timer(); + while read_timer() - start < ms * (CLOCK_FREQ / 1000) { + core::hint::spin_loop(); + } + } + use drivers::block_device::{Vf2SdDriver,VF2SDDriver}; + let block_device = VF2SDDriver::new(Vf2SdDriver::new(sleep)); + let size = block_device.capacity(); + println!("Block device size is {}MB", size * 512 / 1024 / 1024); + let block_device = Arc::new(GenericBlockDevice::new(Box::new(block_device))); + block::init_block_device(block_device); + // register_device_to_plic(irq, block_device); + println!("Init SDIO block device success"); + } + #[cfg(feature = "ramdisk")] + { + init_ramdisk(); + } + } + name => { + println!("Don't support block device: {}", name); + #[cfg(feature = "ramdisk")]{ + init_ramdisk(); + } + #[cfg(not(feature = "ramdisk"))] + panic!("System need block device, but there is no block device"); + } + } +} + +#[cfg(feature = "ramdisk")] +fn init_ramdisk() { + use drivers::block_device::MemoryFat32Img; + checkout_fs_img(); + let data = unsafe { + core::slice::from_raw_parts_mut( + img_start as *mut u8, + img_end as usize - img_start as usize, + ) + }; + let block_device = GenericBlockDevice::new(Box::new(MemoryFat32Img::new(data))); + let block_device = Arc::new(block_device); + block::init_block_device(block_device); + println!("Init fake block device success"); +} + + +fn init_gpu(gpu: prob::DeviceInfo) { + let (base_addr, irq) = (gpu.base_addr, gpu.irq); + println!("Init gpu, base_addr:{:#x},irq:{}", base_addr, irq); + match gpu.compatible.as_str() { + "virtio,mmio" => { + // qemu + use drivers::gpu::VirtIOGpuWrapper; + let gpu = VirtIOGpuWrapper::new(base_addr); + let resolution = gpu.resolution(); + println!("GPU resolution: {:?}", resolution); + let gpu = Arc::new(gpu); + gpu::init_gpu(gpu.clone()); + // let _ = register_device_to_plic(irq, gpu); + println!("Init gpu success"); + } + name => { + println!("Don't support gpu: {}", name); + } + } +} + +fn init_input_device(input: prob::DeviceInfo, name: &str) { + let (base_addr, irq) = (input.base_addr, input.irq); + println!( + "Init {} input device, base_addr:{:#x},irq:{}", + name, base_addr, irq + ); + match input.compatible.as_str() { + "virtio,mmio" => { + // qemu + use drivers::input::VirtIOInputDriver; + let input = VirtIOInputDriver::from_addr(base_addr, MAX_INPUT_EVENT_NUM as u32); + let input = Arc::new(input); + match name { + "mouse" => input::init_mouse_input_device(input.clone()), + "keyboard" => input::init_keyboard_input_device(input.clone()), + _ => panic!("Don't support {} input device", name), + } + let _ = register_device_to_plic(irq, input); + // INITIALIZED_DEVICES.lock().push(DeviceInfo { + // device: input, + // irq, + // need_register: true, + // }); + println!("Init keyboard input device success"); + } + name => { + println!("Don't support keyboard input device: {}", name); + } + } +} + +fn init_net(_nic: prob::DeviceInfo) { + // If we need run test, we should only init loop device because no we can't route packet + #[cfg(feature = "test")] + { + init_loop_device(); + } + #[cfg(not(feature = "test"))] + { + let (base_addr, irq) = (_nic.base_addr, _nic.irq); + println!("Init net device, base_addr:{:#x},irq:{}", base_addr, irq); + + match _nic.compatible.as_str() { + "virtio,mmio" => { + use config::{QEMU_GATEWAY, QEMU_IP}; + use core::str::FromStr; + use drivers::net::{NetNeedFunc, VirtIONetDriver}; + use smoltcp::wire::IpAddress; + let virtio_net = VirtIONetDriver::from_mmio(base_addr); + let device = Box::new(virtio_net); + netcore::init_net( + device, + Arc::new(NetNeedFunc), + IpAddress::from_str(QEMU_IP).unwrap(), + IpAddress::from_str(QEMU_GATEWAY).unwrap(), + true, + ); + println!("Init net device success"); + } + name => { + println!("Don't support net device: {}", name); + return; + } + } + } +} + +#[cfg(feature = "test")] +fn init_loop_device() { + use drivers::net::{LoopbackDev, NetNeedFunc}; + use smoltcp::wire::IpAddress; + // use default ip and gateway for qemu + let ip = IpAddress::v4(127, 0, 0, 1); + let gate_way = IpAddress::v4(127, 0, 0, 1); + let loopback = Box::new(LoopbackDev::new()); + netcore::init_net(loopback, Arc::new(NetNeedFunc), ip, gate_way, false); + println!("Init net device success"); +} diff --git a/kernel/src/device/net.rs b/subsystems/devices/src/net.rs similarity index 74% rename from kernel/src/device/net.rs rename to subsystems/devices/src/net.rs index 03076d7a..8c2039d0 100644 --- a/kernel/src/device/net.rs +++ b/subsystems/devices/src/net.rs @@ -1,16 +1,9 @@ -use netcore::{KernelNetFunc, NetInstant}; - -use crate::interrupt::DeviceBase; - -use crate::timer::TimeSpec; - -pub trait NetDevice: DeviceBase {} #[cfg(feature = "net_test")] pub mod nettest { - use crate::error::AlienResult; use crate::net::port::neterror2alien; use alloc::vec::Vec; + use constants::AlienResult; use core::net::{IpAddr, SocketAddr}; use netcore::tcp::TcpSocket; @@ -95,34 +88,4 @@ pub mod nettest { i += 1; } } -} - -#[derive(Debug, Default)] -pub struct NetNeedFunc; - -impl KernelNetFunc for NetNeedFunc { - fn now(&self) -> NetInstant { - let time_spec = TimeSpec::now(); - NetInstant { - micros: time_spec.tv_sec as i64 * 1000_000 + time_spec.tv_nsec as i64 / 1000, - } - } - #[cfg(feature = "net_test")] - fn yield_now(&self) { - // do_suspend(); - } - #[cfg(not(feature = "net_test"))] - fn yield_now(&self) -> bool { - use crate::task::current_task; - use crate::task::do_suspend; - do_suspend(); - // interrupt by signal - let task = current_task().unwrap(); - let task_inner = task.access_inner(); - let receiver = task_inner.signal_receivers.lock(); - if receiver.have_signal() { - return true; - } - false - } -} +} \ No newline at end of file diff --git a/subsystems/devices/src/prob.rs b/subsystems/devices/src/prob.rs new file mode 100644 index 00000000..7768d768 --- /dev/null +++ b/subsystems/devices/src/prob.rs @@ -0,0 +1,94 @@ +use alloc::string::{String, ToString}; + +use alloc::vec::Vec; +use core::ops::Range; +use fdt::standard_nodes::Compatible; +use fdt::Fdt; + +#[derive(Debug, Clone)] +pub struct DeviceInfo { + pub name: String, + pub base_addr: usize, + pub irq: usize, + pub compatible: String, +} + +impl DeviceInfo { + pub fn new(name: String, base_addr: usize, irq: usize, compatible: String) -> Self { + Self { + name, + base_addr, + irq, + compatible, + } + } +} + +pub trait Probe { + /// Get the base address and irq number of the uart device from the device tree. + fn probe_uart(&self) -> Option; + /// Get the base address and irq number of the rtc device from the device tree. + fn probe_rtc(&self) -> Option; + /// Get the base address and irq number of the virtio devices from the device tree. + fn probe_virtio(&self) -> Option>; + fn probe_common(&self, device_name: &str) -> Option; + #[cfg(feature = "vf2")] + fn probe_sdio(&self) -> Option { + self.probe_common("sdio1") + } +} + +impl Probe for Fdt<'_> { + fn probe_uart(&self) -> Option { + match self.probe_common("uart") { + Some(device_info) => Some(device_info), + None => self.probe_common("serial"), + } + } + + fn probe_rtc(&self) -> Option { + self.probe_common("rtc") + } + + fn probe_virtio(&self) -> Option> { + let mut virtio_devices = Vec::new(); + for node in self.all_nodes() { + if node.name.starts_with("virtio_mmio") { + let reg = node.reg()?.next()?; + let paddr = reg.starting_address as usize; + let irq = node.property("interrupts")?.value; + let irq = u32::from_be_bytes(irq[0..4].try_into().ok()?); + + let compatible = node.compatible().map(Compatible::first).unwrap(); + + virtio_devices.push(DeviceInfo::new( + String::from("virtio_mmio"), + paddr, + irq as usize, + compatible.to_string(), + )); + } + } + Some(virtio_devices) + } + + fn probe_common(&self, device_name: &str) -> Option { + let node = self + .all_nodes() + .find(|node| node.name.starts_with(device_name))?; + let reg = node.reg()?.next()?; + let range = Range { + start: reg.starting_address as usize, + end: reg.starting_address as usize + reg.size.unwrap(), + }; + let irq = node.property("interrupts").unwrap().value; + let irq = u32::from_be_bytes(irq[0..4].try_into().unwrap()); + let compatible = node.compatible().map(Compatible::first).unwrap(); + Some(DeviceInfo::new( + device_name.to_string(), + range.start, + irq as usize, + compatible.to_string(), + )) + } +} diff --git a/kernel/src/device/rtc.rs b/subsystems/devices/src/rtc.rs similarity index 75% rename from kernel/src/device/rtc.rs rename to subsystems/devices/src/rtc.rs index 44502492..955a5497 100644 --- a/kernel/src/device/rtc.rs +++ b/subsystems/devices/src/rtc.rs @@ -1,10 +1,10 @@ +use crate::TASK_FUNC; use alloc::format; use alloc::sync::Arc; +use constants::io::{RtcTime, TeletypeCommand}; +use constants::DeviceId; use core::cmp::min; -use pconst::io::TeletypeCommand; -use rtc::RtcTime; - -use crate::fs::dev::DeviceId; +use device_interface::RtcDevice; use spin::Once; use vfscore::error::VfsError; use vfscore::file::VfsFile; @@ -13,22 +13,17 @@ use vfscore::superblock::VfsSuperBlock; use vfscore::utils::{VfsFileStat, VfsNodeType}; use vfscore::VfsResult; -use crate::interrupt::DeviceBase; -use crate::task::current_task; - pub static RTC_DEVICE: Once> = Once::new(); +#[allow(unused)] pub fn get_rtc_time() -> Option { - RTC_DEVICE.get().map(|rtc| rtc.read_time_fmt()) + RTC_DEVICE.get().map(|rtc| rtc.read_time()) } -#[allow(unused)] pub fn init_rtc(rtc: Arc) { RTC_DEVICE.call_once(|| rtc); } -pub trait RtcDevice: Send + Sync + DeviceBase + rtc::LowRtcDevice + rtc::LowRtcDeviceExt {} - pub struct RTCDevice { device_id: DeviceId, device: Arc, @@ -45,7 +40,7 @@ impl RTCDevice { impl VfsFile for RTCDevice { fn read_at(&self, _offset: u64, buf: &mut [u8]) -> VfsResult { - let time = self.device.read_time_fmt(); + let time = self.device.read_time(); let str = format!("{:?}", time); let bytes = str.as_bytes(); let min_len = min(buf.len(), bytes.len()); @@ -56,24 +51,16 @@ impl VfsFile for RTCDevice { todo!() } fn ioctl(&self, cmd: u32, arg: usize) -> VfsResult { - let task = current_task().unwrap(); - let mut task_inner = task.access_inner(); + // let task = current_task().unwrap(); + // let mut task_inner = task.access_inner(); let cmd = TeletypeCommand::try_from(cmd).map_err(|_| VfsError::Invalid)?; match cmd { TeletypeCommand::RTC_RD_TIME => { - let time = self.device.read_time_fmt(); - let c_rtc_time = pconst::io::RtcTime { - sec: time.second as u32, - min: time.minute as u32, - hour: time.hour as u32, - mday: time.day as u32, - mon: time.month as u32, - year: time.year, - wday: 0, - yday: 0, - isdst: 0, - }; - task_inner.copy_to_user(&c_rtc_time, arg as *mut pconst::io::RtcTime); + let time = self.device.read_time(); + TASK_FUNC + .get() + .unwrap() + .copy_data_to_task(&time, arg as *mut RtcTime); } _ => return Err(VfsError::Invalid), } diff --git a/kernel/src/device/uart.rs b/subsystems/devices/src/uart.rs similarity index 72% rename from kernel/src/device/uart.rs rename to subsystems/devices/src/uart.rs index 5a8c552d..77a347cd 100644 --- a/kernel/src/device/uart.rs +++ b/subsystems/devices/src/uart.rs @@ -1,6 +1,9 @@ -use crate::fs::dev::DeviceId; +use crate::TASK_FUNC; use alloc::sync::Arc; -use pconst::io::{LocalModes, TeletypeCommand, Termios, WinSize}; +use constants::io::{LocalModes, TeletypeCommand, Termios, WinSize}; +use constants::DeviceId; +use device_interface::UartDevice; +use ksync::Mutex; use spin::Once; use vfscore::error::VfsError; use vfscore::file::VfsFile; @@ -9,18 +12,6 @@ use vfscore::superblock::VfsSuperBlock; use vfscore::utils::{VfsFileStat, VfsNodeType, VfsPollEvents}; use vfscore::VfsResult; -use crate::interrupt::DeviceBase; -use crate::ksync::Mutex; -use crate::task::current_task; - -pub trait UartDevice: Send + Sync + DeviceBase { - fn put(&self, c: u8); - fn get(&self) -> Option; - fn put_bytes(&self, bytes: &[u8]); - fn have_data_to_get(&self) -> bool; - fn have_space_to_put(&self) -> bool; -} - pub static UART_DEVICE: Once> = Once::new(); pub fn init_uart(uart: Arc) { @@ -104,33 +95,53 @@ impl VfsFile for UARTDevice { fn ioctl(&self, cmd: u32, arg: usize) -> VfsResult { let mut io = self.io.lock(); let cmd = TeletypeCommand::try_from(cmd).unwrap(); - let task = current_task().unwrap(); - let mut task_inner = task.access_inner(); + + // let task = current_task().unwrap(); + // let mut task_inner = task.access_inner(); + return match cmd { TeletypeCommand::TCGETS | TeletypeCommand::TCGETA => { - task_inner.copy_to_user(&io.termios, arg as *mut Termios); + // task_inner.copy_to_user(&io.termios, arg as *mut Termios); + TASK_FUNC + .get() + .unwrap() + .copy_data_to_task(&io.termios, arg as *mut Termios); Ok(0) } TeletypeCommand::TCSETS | TeletypeCommand::TCSETSW | TeletypeCommand::TCSETSF => { - task_inner.copy_from_user(arg as *const Termios, &mut io.termios); + // task_inner.copy_from_user(arg as *const Termios, &mut io.termios); + TASK_FUNC + .get() + .unwrap() + .copy_data_from_task(arg as *const Termios, &mut io.termios); Ok(0) } TeletypeCommand::TIOCGPGRP => { - let word = task_inner.transfer_raw_ptr_mut(arg as *mut u32); + // let word = task_inner.transfer_raw_ptr_mut(arg as *mut u32); + let word = TASK_FUNC.get().unwrap().transfer_ptr_mut(arg as *mut u32); *word = io.foreground_pgid; Ok(0) } TeletypeCommand::TIOCSPGRP => { - let word = task_inner.transfer_raw_ptr(arg as *const u32); + // let word = task_inner.transfer_raw_ptr(arg as *const u32); + let word = TASK_FUNC.get().unwrap().transfer_ptr(arg as *const u32); io.foreground_pgid = *word; Ok(0) } TeletypeCommand::TIOCGWINSZ => { - task_inner.copy_to_user(&io.winsize, arg as *mut WinSize); + // task_inner.copy_to_user(&io.winsize, arg as *mut WinSize); + TASK_FUNC + .get() + .unwrap() + .copy_data_to_task(&io.winsize, arg as *mut WinSize); Ok(0) } TeletypeCommand::TIOCSWINSZ => { - task_inner.copy_from_user(arg as *const WinSize, &mut io.winsize); + // task_inner.copy_from_user(arg as *const WinSize, &mut io.winsize); + TASK_FUNC + .get() + .unwrap() + .copy_data_from_task(arg as *const WinSize, &mut io.winsize); Ok(0) } _ => { diff --git a/subsystems/drivers/Cargo.toml b/subsystems/drivers/Cargo.toml new file mode 100644 index 00000000..dfa2bdb8 --- /dev/null +++ b/subsystems/drivers/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "drivers" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +constants = { path = "../constants" } +ksync = { path = "../ksync" } +config = { path = "../config" } +device_interface = { path = "../device_interface" } +mem = { path = "../mem" } +log = "0" +timer = { path = "../timer" } +platform = { path = "../platform" } +spin = "0" + +virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers",rev = "de1c3b1"} +rtc = { git = "https://github.com/os-module/rtc.git" } +lru = "0.10.0" + +# uart +uart16550 = { version = "0.0.1"} +uart8250 = { git = "https://github.com/os-module/uart-rs.git"} + + +# net +loopback = {git = "https://github.com/os-module/simple-net"} +virtio-net = {git = "https://github.com/os-module/simple-net"} +netcore = {git = "https://github.com/os-module/simple-net"} + +visionfive2-sd = { git = "https://github.com/os-module/visionfive2-sd.git"} +downcast-rs = { version = "1.2.0", default-features = false } + diff --git a/kernel/src/driver/block_device.rs b/subsystems/drivers/src/block_device.rs similarity index 81% rename from kernel/src/driver/block_device.rs rename to subsystems/drivers/src/block_device.rs index 895f13ff..3c0e485f 100644 --- a/kernel/src/driver/block_device.rs +++ b/subsystems/drivers/src/block_device.rs @@ -1,50 +1,77 @@ use alloc::boxed::Box; use alloc::vec::Vec; +use constants::LinuxErrno; use core::cmp::min; use core::fmt::{Debug, Formatter}; use core::num::NonZeroUsize; +use core::ops::{Deref, DerefMut}; use core::ptr::NonNull; -use pconst::LinuxErrno; - use lru::LruCache; use virtio_drivers::device::blk::VirtIOBlk; use virtio_drivers::transport::mmio::{MmioTransport, VirtIOHeader}; -use crate::error::AlienResult; -use crate::ksync::Mutex; +use constants::AlienResult; +use ksync::Mutex; -use crate::config::BLOCK_CACHE_FRAMES; -use crate::config::FRAME_SIZE; -use crate::device::BlockDevice; -use crate::driver::hal::HalImpl; -use crate::interrupt::DeviceBase; -use crate::memory::{frame_alloc, FrameTracker}; +use crate::hal::HalImpl; +use config::FRAME_SIZE; +use device_interface::{BlockDevice, DeviceBase, LowBlockDevice}; +use mem::{alloc_frames, free_frames}; +use platform::config::BLOCK_CACHE_FRAMES; const PAGE_CACHE_SIZE: usize = FRAME_SIZE; pub struct GenericBlockDevice { - pub device: Mutex>, + pub device: Mutex>, cache: Mutex>, dirty: Mutex>, } +#[derive(Debug)] +struct FrameTracker { + ptr: usize, +} + +impl FrameTracker { + pub fn new(ptr: usize) -> Self { + Self { ptr } + } +} + +impl Deref for FrameTracker { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + unsafe { core::slice::from_raw_parts(self.ptr as *const u8, FRAME_SIZE) } + } +} + +impl DerefMut for FrameTracker { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { core::slice::from_raw_parts_mut(self.ptr as *mut u8, FRAME_SIZE) } + } +} + +impl Drop for FrameTracker { + fn drop(&mut self) { + free_frames(self.ptr as *mut u8, 1); + } +} + unsafe impl Send for GenericBlockDevice {} unsafe impl Sync for GenericBlockDevice {} impl GenericBlockDevice { - pub fn new(device: Box) -> Self { + pub fn new(device: Box) -> Self { Self { device: Mutex::new(device), cache: Mutex::new(LruCache::new( NonZeroUsize::new(BLOCK_CACHE_FRAMES).unwrap(), - )), + )), // 4MB cache dirty: Mutex::new(Vec::new()), } } - pub fn cache_max_size(&self) -> usize { - PAGE_CACHE_SIZE * BLOCK_CACHE_FRAMES - } } impl DeviceBase for GenericBlockDevice { @@ -71,7 +98,8 @@ impl BlockDevice for GenericBlockDevice { while count < len { if !cache_lock.contains(&page_id) { let mut device = self.device.lock(); - let mut cache = frame_alloc().unwrap(); + let cache = alloc_frames(1); + let mut cache = FrameTracker::new(cache as usize); let start_block = page_id * PAGE_CACHE_SIZE / 512; let end_block = start_block + PAGE_CACHE_SIZE / 512; for i in start_block..end_block { @@ -110,7 +138,8 @@ impl BlockDevice for GenericBlockDevice { while count < len { if !cache_lock.contains(&page_id) { let mut device = self.device.lock(); - let mut cache = frame_alloc().unwrap(); + let cache = alloc_frames(1); + let mut cache = FrameTracker::new(cache as usize); let start_block = page_id * PAGE_CACHE_SIZE / 512; let end_block = start_block + PAGE_CACHE_SIZE / 512; for i in start_block..end_block { @@ -164,13 +193,6 @@ impl BlockDevice for GenericBlockDevice { } } -pub trait LowBlockDriver { - fn read_block(&mut self, block_id: usize, buf: &mut [u8]) -> AlienResult<()>; - fn write_block(&mut self, block_id: usize, buf: &[u8]) -> AlienResult<()>; - fn capacity(&self) -> usize; - fn flush(&mut self) {} -} - pub struct VirtIOBlkWrapper { device: VirtIOBlk, } @@ -181,13 +203,17 @@ impl VirtIOBlkWrapper { let transport = unsafe { MmioTransport::new(header) }.unwrap(); let blk = VirtIOBlk::::new(transport) .expect("failed to create blk driver"); - let size = blk.capacity(); - println!("Block device size is {}MB", size * 512 / 1024 / 1024); + Self { device: blk } + } + + pub fn from_mmio(mmio_transport: MmioTransport) -> Self { + let blk = VirtIOBlk::::new(mmio_transport) + .expect("failed to create blk driver"); Self { device: blk } } } -impl LowBlockDriver for VirtIOBlkWrapper { +impl LowBlockDevice for VirtIOBlkWrapper { fn read_block(&mut self, block_id: usize, buf: &mut [u8]) -> AlienResult<()> { let res = self .device @@ -210,7 +236,7 @@ pub struct MemoryFat32Img { data: &'static mut [u8], } -impl LowBlockDriver for MemoryFat32Img { +impl LowBlockDevice for MemoryFat32Img { fn read_block(&mut self, block_id: usize, buf: &mut [u8]) -> AlienResult<()> { let start = block_id * 512; let end = start + 512; @@ -235,14 +261,14 @@ impl MemoryFat32Img { } } -#[cfg(all(feature = "vf2", not(feature = "ramfs")))] -pub struct Vf2SdDriver { - driver: visionfive2_sd::Vf2SdDriver, + +pub use visionfive2_sd::Vf2SdDriver; +pub struct VF2SDDriver { + driver: Vf2SdDriver, } -#[cfg(all(feature = "vf2", not(feature = "ramfs")))] -impl Vf2SdDriver { - pub fn new(vf2sd_driver: visionfive2_sd::Vf2SdDriver) -> Self { +impl VF2SDDriver { + pub fn new(vf2sd_driver: Vf2SdDriver) -> Self { Self { driver: vf2sd_driver, } @@ -252,8 +278,7 @@ impl Vf2SdDriver { } } -#[cfg(all(feature = "vf2", not(feature = "ramfs")))] -impl LowBlockDriver for Vf2SdDriver { +impl LowBlockDevice for VF2SDDriver { fn read_block(&mut self, block_id: usize, buf: &mut [u8]) -> AlienResult<()> { self.driver.read_block(block_id, buf); Ok(()) @@ -269,4 +294,4 @@ impl LowBlockDriver for Vf2SdDriver { // 32GB 32 * 1024 * 1024 * 1024 / 512 } -} +} \ No newline at end of file diff --git a/kernel/src/driver/gpu.rs b/subsystems/drivers/src/gpu.rs similarity index 89% rename from kernel/src/driver/gpu.rs rename to subsystems/drivers/src/gpu.rs index 698410f1..008916cc 100644 --- a/kernel/src/driver/gpu.rs +++ b/subsystems/drivers/src/gpu.rs @@ -1,12 +1,10 @@ use core::ptr::NonNull; +use device_interface::{DeviceBase, GpuDevice}; use virtio_drivers::device::gpu::VirtIOGpu; use virtio_drivers::transport::mmio::{MmioTransport, VirtIOHeader}; -use crate::ksync::Mutex; - -use crate::device::GpuDevice; -use crate::driver::hal::HalImpl; -use crate::interrupt::DeviceBase; +use crate::hal::HalImpl; +use ksync::Mutex; pub struct VirtIOGpuWrapper { gpu: Mutex>, @@ -25,7 +23,6 @@ impl VirtIOGpuWrapper { let mmio = unsafe { MmioTransport::new(header) }.unwrap(); let mut gpu = VirtIOGpu::new(mmio).unwrap(); let resolution = gpu.resolution().unwrap(); - println!("GPU resolution: {:?}", resolution); unsafe { let fbuffer = gpu.setup_framebuffer().unwrap(); let len = fbuffer.len(); @@ -58,4 +55,7 @@ impl GpuDevice for VirtIOGpuWrapper { fn flush(&self) { self.gpu.lock().flush().unwrap(); } + fn resolution(&self) -> (u32, u32) { + self.resolution + } } diff --git a/kernel/src/driver/hal.rs b/subsystems/drivers/src/hal.rs similarity index 69% rename from kernel/src/driver/hal.rs rename to subsystems/drivers/src/hal.rs index 46a9147c..d203d96b 100644 --- a/kernel/src/driver/hal.rs +++ b/subsystems/drivers/src/hal.rs @@ -1,20 +1,17 @@ -use crate::memory::{addr_to_frame, frame_alloc_contiguous}; use core::ptr::NonNull; -use virtio_drivers::{BufferDirection, Hal, PhysAddr, PAGE_SIZE}; +use mem::{alloc_frames, free_frames}; +use virtio_drivers::{BufferDirection, Hal, PhysAddr}; pub struct HalImpl; unsafe impl Hal for HalImpl { fn dma_alloc(pages: usize, _direction: BufferDirection) -> (PhysAddr, NonNull) { - let start = frame_alloc_contiguous(pages); + let start = alloc_frames(pages); (start as usize, NonNull::new(start).unwrap()) } unsafe fn dma_dealloc(paddr: PhysAddr, _vaddr: NonNull, pages: usize) -> i32 { - for i in 0..pages { - let frame_tracker = addr_to_frame(paddr + i * PAGE_SIZE); - drop(frame_tracker); - } + free_frames(paddr as *mut u8, pages); 0 } diff --git a/kernel/src/driver/input.rs b/subsystems/drivers/src/input.rs similarity index 74% rename from kernel/src/driver/input.rs rename to subsystems/drivers/src/input.rs index a556a896..f24a4fb3 100644 --- a/kernel/src/driver/input.rs +++ b/subsystems/drivers/src/input.rs @@ -1,18 +1,15 @@ use alloc::collections::VecDeque; use alloc::sync::Arc; use core::ptr::NonNull; +use log::info; +use device_interface::{DeviceBase, InputDevice}; use virtio_drivers::device::input::VirtIOInput; use virtio_drivers::transport::mmio::{MmioTransport, VirtIOHeader}; -use crate::ksync::Mutex; -use smpscheduler::FifoTask; - -use crate::device::InputDevice; -use crate::driver::hal::HalImpl; -use crate::interrupt::DeviceBase; -use crate::task::schedule::schedule; -use crate::task::{current_task, Task, TaskState, GLOBAL_TASK_MANAGER}; +use crate::hal::HalImpl; +use crate::{DriverTask, DRIVER_TASK}; +use ksync::Mutex; pub struct VirtIOInputDriver { inner: Mutex, @@ -26,7 +23,7 @@ struct InputDriverInner { max_events: u32, driver: VirtIOInput, events: VecDeque, - wait_queue: VecDeque>, + wait_queue: VecDeque>, } impl VirtIOInputDriver { @@ -64,11 +61,15 @@ impl InputDevice for VirtIOInputDriver { if let Some(event) = inner.events.pop_front() { return event; } - let process = current_task().unwrap(); - process.update_state(TaskState::Waiting); - inner.wait_queue.push_back(process.clone()); + // let process = current_task().unwrap(); + // process.update_state(TaskState::Waiting); + // inner.wait_queue.push_back(process.clone()); + let task = DRIVER_TASK.get().unwrap().get_task(); + task.to_wait(); + inner.wait_queue.push_back(task); } // drop the lock - schedule(); + // schedule(); + DRIVER_TASK.get().unwrap().suspend(); } } @@ -95,9 +96,11 @@ impl DeviceBase for VirtIOInputDriver { count += 1; } while !inner.wait_queue.is_empty() && count > 0 { - let process = inner.wait_queue.pop_front().unwrap(); - process.update_state(TaskState::Ready); - GLOBAL_TASK_MANAGER.add_task(Arc::new(FifoTask::new(process))); + let task = inner.wait_queue.pop_front().unwrap(); + // process.update_state(TaskState::Ready); + // GLOBAL_TASK_MANAGER.add_task(Arc::new(FifoTask::new(process))); + task.to_wakeup(); + DRIVER_TASK.get().unwrap().put_task(task); count -= 1; } info!("read {} events", count); diff --git a/subsystems/drivers/src/lib.rs b/subsystems/drivers/src/lib.rs new file mode 100644 index 00000000..86d800c3 --- /dev/null +++ b/subsystems/drivers/src/lib.rs @@ -0,0 +1,35 @@ +#![no_std] +extern crate alloc; + +use alloc::boxed::Box; +use alloc::sync::Arc; +use downcast_rs::{impl_downcast, DowncastSync}; +use spin::Once; + +pub mod block_device; +pub mod gpu; +pub mod hal; +pub mod input; +pub mod net; +pub mod rtc; +pub mod uart; + +pub trait DriverTask: Send + Sync + DowncastSync { + fn to_wait(&self); + fn to_wakeup(&self); + fn have_signal(&self) -> bool; +} + +impl_downcast!(sync DriverTask); + +pub trait DriverWithTask: Send + Sync { + fn get_task(&self) -> Arc; + fn put_task(&self, task: Arc); + fn suspend(&self); +} + +static DRIVER_TASK: Once> = Once::new(); + +pub fn register_task_func(task_func: Box) { + DRIVER_TASK.call_once(|| task_func); +} diff --git a/subsystems/drivers/src/net.rs b/subsystems/drivers/src/net.rs new file mode 100644 index 00000000..68c4de4c --- /dev/null +++ b/subsystems/drivers/src/net.rs @@ -0,0 +1,68 @@ +use core::ptr::NonNull; + +use crate::hal::HalImpl; +use netcore::{KernelNetFunc, NetInstant}; +use timer::TimeSpec; +use virtio_drivers::transport::mmio::{MmioTransport, VirtIOHeader}; +use virtio_net::VirtIONetDeviceWrapper; + +use crate::DRIVER_TASK; +pub use loopback::LoopbackDev; + +pub const NET_BUFFER_LEN: usize = 4096; +pub const NET_QUEUE_SIZE: usize = 128; + +pub struct VirtIONetDriver; + +impl VirtIONetDriver { + pub fn from_mmio( + addr: usize, + ) -> VirtIONetDeviceWrapper { + let header = NonNull::new(addr as *mut VirtIOHeader).unwrap(); + let transport = unsafe { MmioTransport::new(header) }.unwrap(); + let device = VirtIONetDeviceWrapper::new(transport, NET_BUFFER_LEN); + device + } +} + +#[derive(Debug, Default)] +pub struct NetNeedFunc; +#[derive(Debug, Default)] +pub struct NetNeedFuncEmpty; + +impl KernelNetFunc for NetNeedFuncEmpty { + fn now(&self) -> NetInstant { + let time_spec = TimeSpec::now(); + NetInstant { + micros: time_spec.tv_sec as i64 * 1000_000 + time_spec.tv_nsec as i64 / 1000, + } + } + + fn yield_now(&self) -> bool { + false + } +} + +impl KernelNetFunc for NetNeedFunc { + fn now(&self) -> NetInstant { + let time_spec = TimeSpec::now(); + NetInstant { + micros: time_spec.tv_sec as i64 * 1000_000 + time_spec.tv_nsec as i64 / 1000, + } + } + fn yield_now(&self) -> bool { + // use crate::task::current_task; + // use crate::task::do_suspend; + // do_suspend(); + DRIVER_TASK.get().unwrap().suspend(); + // interrupt by signal + // let task = current_task().unwrap(); + // let task_inner = task.access_inner(); + // let receiver = task_inner.signal_receivers.lock(); + // if receiver.have_signal() { + // return true; + // } + let task = DRIVER_TASK.get().unwrap().get_task(); + task.have_signal() + } +} diff --git a/subsystems/drivers/src/rtc.rs b/subsystems/drivers/src/rtc.rs new file mode 100644 index 00000000..ba7d850d --- /dev/null +++ b/subsystems/drivers/src/rtc.rs @@ -0,0 +1,59 @@ +use alloc::format; +use alloc::string::String; +use constants::io::RtcTime; +use device_interface::{DeviceBase, RtcDevice}; +use log::trace; +use rtc::{LowRtcDevice, LowRtcDeviceExt}; + +type GFish = rtc::goldfish::GoldFishRtc; +pub struct GoldFishRtc { + gold_fish_rtc: GFish, +} + +impl GoldFishRtc { + pub fn read_time_u64(&self) -> u64 { + self.gold_fish_rtc.read_time() + } + pub fn read_time_string(&self) -> String { + let time = self.gold_fish_rtc.read_time_fmt(); + format!( + "{:04}-{:02}-{:02} {:02}:{:02}:{:02}", + time.year, time.month, time.day, time.hour, time.minute, time.second + ) + } +} + +impl DeviceBase for GoldFishRtc { + fn hand_irq(&self) { + let alarm = self.gold_fish_rtc.read_alarm_fmt(); + let time = self.gold_fish_rtc.read_time_fmt(); + trace!("rtc interrupt, time: {:?}, alarm: {:?}", time, alarm); + self.gold_fish_rtc.clear_irq(); + self.gold_fish_rtc + .set_alarm(self.read_time_u64() + 1_000_000_000 * 5); + } +} + +impl RtcDevice for GoldFishRtc { + fn read_time(&self) -> RtcTime { + let time = self.gold_fish_rtc.read_time_fmt(); + RtcTime { + year: time.year, + wday: 0, + yday: 0, + mon: time.month as u32, + mday: time.day as u32, + hour: time.hour as u32, + min: time.minute as u32, + sec: time.second as u32, + isdst: 0, + } + } +} + +impl GoldFishRtc { + pub fn new(base_addr: usize) -> Self { + let gold_fish_rtc = GFish::new(base_addr); + Self { gold_fish_rtc } + } +} diff --git a/kernel/src/driver/uart.rs b/subsystems/drivers/src/uart.rs similarity index 81% rename from kernel/src/driver/uart.rs rename to subsystems/drivers/src/uart.rs index 61971ef0..27511770 100644 --- a/kernel/src/driver/uart.rs +++ b/subsystems/drivers/src/uart.rs @@ -1,18 +1,11 @@ -use crate::ksync::Mutex; +pub use self::uart16550::Uart16550; +pub use self::uart8250::Uart8250; +use crate::{DriverTask, DRIVER_TASK}; use alloc::boxed::Box; use alloc::collections::VecDeque; use alloc::sync::Arc; -use smpscheduler::FifoTask; - -#[cfg(not(feature = "vf2"))] -pub use self::uart16550::Uart16550; -use crate::device::UartDevice; -use crate::interrupt::DeviceBase; -use crate::task::schedule::schedule; -use crate::task::{current_task, Task, TaskState, GLOBAL_TASK_MANAGER}; - -#[cfg(feature = "vf2")] -pub use self::uart8250::Uart8250; +use device_interface::{DeviceBase, UartDevice}; +use ksync::Mutex; pub trait LowUartDriver: Send + Sync { fn _init(&mut self); @@ -20,9 +13,8 @@ pub trait LowUartDriver: Send + Sync { fn _read(&mut self) -> Option; } -#[cfg(feature = "vf2")] mod uart8250 { - use crate::driver::uart::LowUartDriver; + use crate::uart::LowUartDriver; pub struct Uart8250 { uart_raw: uart8250::MmioUart8250<'static, u32>, @@ -58,9 +50,8 @@ mod uart8250 { } } -#[cfg(not(feature = "vf2"))] mod uart16550 { - use crate::driver::uart::LowUartDriver; + use crate::uart::LowUartDriver; pub struct Uart16550 { uart_raw: &'static mut uart16550::Uart16550, @@ -107,7 +98,7 @@ pub struct Uart { struct UartInner { rx_buf: VecDeque, - wait_queue: VecDeque>, + wait_queue: VecDeque>, } impl Uart { @@ -133,11 +124,13 @@ impl UartDevice for Uart { loop { let mut inner = self.inner.lock(); if inner.1.rx_buf.is_empty() { - let current_process = current_task().unwrap(); - current_process.update_state(TaskState::Waiting); - inner.1.wait_queue.push_back(current_process.clone()); + // let current_process = current_task().unwrap(); + // current_process.update_state(TaskState::Waiting); + let task = DRIVER_TASK.get().unwrap().get_task(); + task.to_wait(); + inner.1.wait_queue.push_back(task); drop(inner); - schedule(); + DRIVER_TASK.get().unwrap().suspend(); } else { return inner.1.rx_buf.pop_front(); } @@ -170,8 +163,10 @@ impl DeviceBase for Uart { inner.1.rx_buf.push_back(c); if !inner.1.wait_queue.is_empty() { let task = inner.1.wait_queue.pop_front().unwrap(); - task.update_state(TaskState::Ready); - GLOBAL_TASK_MANAGER.add_task(Arc::new(FifoTask::new(task))); + // task.update_state(TaskState::Ready); + // GLOBAL_TASK_MANAGER.add_task(Arc::new(FifoTask::new(task))); + task.to_wakeup(); + DRIVER_TASK.get().unwrap().put_task(task); } } else { break; diff --git a/dep/gmanager/Cargo.toml b/subsystems/gmanager/Cargo.toml similarity index 93% rename from dep/gmanager/Cargo.toml rename to subsystems/gmanager/Cargo.toml index adc2c57e..8cea643e 100644 --- a/dep/gmanager/Cargo.toml +++ b/subsystems/gmanager/Cargo.toml @@ -6,6 +6,3 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] - - -[features] \ No newline at end of file diff --git a/dep/gmanager/src/lib.rs b/subsystems/gmanager/src/lib.rs similarity index 91% rename from dep/gmanager/src/lib.rs rename to subsystems/gmanager/src/lib.rs index 5eb9a08b..028b23e9 100644 --- a/dep/gmanager/src/lib.rs +++ b/subsystems/gmanager/src/lib.rs @@ -63,10 +63,6 @@ impl MinimalManager { self.max } - /// get the data reference - pub fn data(&self) -> &Vec> { - &self.data - } /// insert a value pub fn insert(&mut self, val: T) -> Result { if self.usable == self.max { @@ -83,7 +79,7 @@ impl MinimalManager { } /// find the next usable index - pub fn find_next_index(&self) -> Option { + fn find_next_index(&self) -> Option { let data = self .data .iter() @@ -122,16 +118,6 @@ impl MinimalManager { Ok(val.clone()) } - #[allow(unused)] - /// check the index is usable - pub fn is_usable(&self, index: usize) -> Result { - if index > self.max { - return Err(ManagerError::IndexOver); - } - let val = self.data.get(index).unwrap(); - Ok(val.is_none()) - } - /// User should ensure that the index is valid pub fn insert_with_index(&mut self, index: usize, val: T) -> Result<(), ManagerError> { if index >= self.max { diff --git a/subsystems/interrupt/Cargo.toml b/subsystems/interrupt/Cargo.toml new file mode 100644 index 00000000..dfbebdfa --- /dev/null +++ b/subsystems/interrupt/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "interrupt" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +plic = { git = "https://github.com/os-module/plic" } +spin = "0" +ksync = { path = "../ksync" } +arch = { path = "../arch" } +config = { path = "../config" } +device_interface = { path = "../device_interface" } +platform = { path = "../platform"} + + +[features] +default = [ "qemu" ] + +vf2 = [] +hifive = [] +qemu = [] diff --git a/kernel/src/interrupt/ext_interrupt.rs b/subsystems/interrupt/src/ext_interrupt.rs similarity index 86% rename from kernel/src/interrupt/ext_interrupt.rs rename to subsystems/interrupt/src/ext_interrupt.rs index 7433e486..44541293 100644 --- a/kernel/src/interrupt/ext_interrupt.rs +++ b/subsystems/interrupt/src/ext_interrupt.rs @@ -1,7 +1,7 @@ use plic::Mode; -use crate::arch::hart_id; -use crate::interrupt::{DEVICE_TABLE, PLIC}; +use crate::{DEVICE_TABLE, PLIC}; +use arch::hart_id; pub fn external_interrupt_handler() { let plic = PLIC.get().unwrap(); diff --git a/subsystems/interrupt/src/lib.rs b/subsystems/interrupt/src/lib.rs new file mode 100644 index 00000000..dec7457d --- /dev/null +++ b/subsystems/interrupt/src/lib.rs @@ -0,0 +1,59 @@ +#![no_std] +extern crate alloc; + +use alloc::collections::BTreeMap; +use alloc::sync::Arc; +use spin::Once; + +pub use ext_interrupt::external_interrupt_handler; +use ksync::Mutex; +use plic::{Mode, PLIC}; + +use arch::hart_id; +use config::CPU_NUM; +use device_interface::DeviceBase; +use platform::println; + +mod ext_interrupt; +pub mod record; + +pub static PLIC: Once> = Once::new(); + +pub static DEVICE_TABLE: Mutex>> = Mutex::new(BTreeMap::new()); + +pub fn init_plic(plic_addr: usize) { + #[cfg(feature = "qemu")] + { + let privileges = [2; CPU_NUM]; + let plic = PLIC::new(plic_addr, privileges); + PLIC.call_once(|| plic); + println!("Init qemu plic success"); + } + #[cfg(any(feature = "vf2", feature = "hifive"))] + { + let mut privileges = [2; CPU_NUM]; + // core 0 don't have S mode + privileges[0] = 1; + println!("PLIC context: {:?}", privileges); + let plic = PLIC::new(plic_addr, privileges); + PLIC.call_once(|| plic); + println!("Init hifive or vf2 plic success"); + } +} + +/// Register a device to PLIC. +pub fn register_device_to_plic(irq: usize, device: Arc) { + let mut table = DEVICE_TABLE.lock(); + table.insert(irq, device); + let hard_id = hart_id(); + println!( + "PLIC enable irq {} for hart {}, priority {}", + irq, hard_id, 1 + ); + let plic = PLIC.get().unwrap(); + plic.set_threshold(hard_id as u32, Mode::Machine, 1); + plic.set_threshold(hard_id as u32, Mode::Supervisor, 0); + plic.complete(hard_id as u32, Mode::Supervisor, irq as u32); + plic.set_priority(irq as u32, 1); + plic.enable(hard_id as u32, Mode::Supervisor, irq as u32); +} diff --git a/kernel/src/interrupt/record.rs b/subsystems/interrupt/src/record.rs similarity index 97% rename from kernel/src/interrupt/record.rs rename to subsystems/interrupt/src/record.rs index bdfdbfba..5d576b92 100644 --- a/kernel/src/interrupt/record.rs +++ b/subsystems/interrupt/src/record.rs @@ -1,7 +1,7 @@ -use crate::ksync::Mutex; use alloc::collections::BTreeMap; use alloc::format; use alloc::string::String; +use ksync::Mutex; use spin::Lazy; /// Record the number of interrupts diff --git a/subsystems/knet/Cargo.toml b/subsystems/knet/Cargo.toml new file mode 100644 index 00000000..45117675 --- /dev/null +++ b/subsystems/knet/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "knet" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +constants = { path = "../constants" } +ksync = { path = "../ksync" } +netcore = {git = "https://github.com/os-module/simple-net"} +vfs = { path = "../vfs" } +vfscore = { git = "https://github.com/os-module/rvfs.git", features = [ + "linux_error", +] } + +log = "0" \ No newline at end of file diff --git a/subsystems/knet/src/addr.rs b/subsystems/knet/src/addr.rs new file mode 100644 index 00000000..9a118fc7 --- /dev/null +++ b/subsystems/knet/src/addr.rs @@ -0,0 +1,84 @@ +//! 在 Alien 内核中使用的 socket 套接字地址结构。 +//! +//! Alien 中目前能够接收的套接字地址种类包括本地路径地址和网络套接字地址。 +//! 对于从用户端传来的套接字地址,类似于 `linux` 中 `socket.h` 的套接字地址。 +//! 大致结构如下: +//! + 2字节表明该套接字使用的地址协议族 +//! + 2字节表明该套接字的端口 +//! + 12字节的地址数据 +//! +//! Alien 将会首先对传入的套接字的协议族进行解析,然后根据不同的地址协议族将其解析成 [`SocketAddrExt`] 结构, +//! 向下层的具体套接字中传递相应地址时,传递的也是 [`SocketAddrExt`] 结构。 +//! +use alloc::string::String; +use constants::net::Domain; +use core::fmt::Debug; +use core::net::{IpAddr, SocketAddr}; + +/// 用于存储套接字通信地址的结构,分为本地路径地址和网络套接字地址。 +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] +pub enum SocketAddrExt { + LocalPath(String), + SocketAddr(SocketAddr), +} + +/// 用于存储一个Ipv4套接字相关信息的结构。对应 `linux` 中 `socket.h` 的 `sockaddr_in` 结构。 +/// +/// 在 socket 相关系统调用中,一般都先分析出套接字采用的地址协议族,如果是 `IPV4` 则会将传入的套接字相关信息解析成 `RawIpV4Addr`。 +/// 且 `Alien` 目前默认使用网络套接字时,即采用 `IPV4` 协议。 +#[repr(C)] +#[derive(Debug, Clone, Copy, Default)] +pub struct RawIpV4Addr { + /// 地址协议族 + pub family: u16, + /// Ipv4 的端口 + pub port: u16, + /// Ipv4 的地址 + pub addr: u32, + /// 零位,用于后续扩展 + pub zero: [u8; 8], +} + +impl SocketAddrExt { + /// 获取网络套接字地址。当本结构中存储的是本地路径地址时,将导致 panic。 + pub fn get_socketaddr(&self) -> SocketAddr { + match self { + SocketAddrExt::LocalPath(_) => { + panic!("Can't get socketaddr from local path") + } + SocketAddrExt::SocketAddr(addr) => *addr, + } + } + + /// 获取本地路径地址。当本结构中存储的是网络套接字地址时,将导致 panic。 + pub fn get_local_path(&self) -> String { + match self { + SocketAddrExt::LocalPath(path) => path.clone(), + SocketAddrExt::SocketAddr(_) => { + panic!("Can't get local path from socketaddr") + } + } + } +} + +impl From for RawIpV4Addr { + /// 用一个 [`SocketAddr`] 结构 初始化 `RawIpV4Addr ` + fn from(addr: SocketAddr) -> Self { + let ip = addr.ip(); + let port = addr.port(); + let ip = match ip { + IpAddr::V4(ip) => ip, + IpAddr::V6(_) => { + panic!("ipv6 is not supported") + } + }; + let ip = ip.octets(); + let ip = u32::from_le_bytes(ip); + Self { + family: Domain::AF_INET as u16, + port: port.to_be(), + addr: ip, + zero: [0u8; 8], + } + } +} diff --git a/subsystems/knet/src/lib.rs b/subsystems/knet/src/lib.rs new file mode 100644 index 00000000..1a5f6af7 --- /dev/null +++ b/subsystems/knet/src/lib.rs @@ -0,0 +1,11 @@ +#![no_std] +#![feature(ip_in_core)] + +extern crate alloc; +#[macro_use] +extern crate log; + +pub mod addr; +pub mod port; +pub mod socket; +pub mod unix; diff --git a/kernel/src/net/port.rs b/subsystems/knet/src/port.rs similarity index 94% rename from kernel/src/net/port.rs rename to subsystems/knet/src/port.rs index 151c2f8f..3183d585 100644 --- a/kernel/src/net/port.rs +++ b/subsystems/knet/src/port.rs @@ -1,8 +1,8 @@ //! 现为将网络异常类型 [`NetError`] 转为 系统异常类型 [`LinuxErrno`]的模块。原为定义端口全局变量和操作的模块。 -use crate::error::AlienError; +use constants::AlienError; +use constants::LinuxErrno; use netcore::common::NetError; -use pconst::LinuxErrno; /// 现为将网络异常类型 [`NetError`] 转为 系统异常类型 [`LinuxErrno`]。 pub fn neterror2alien(error: NetError) -> AlienError { diff --git a/kernel/src/net/socket.rs b/subsystems/knet/src/socket.rs similarity index 96% rename from kernel/src/net/socket.rs rename to subsystems/knet/src/socket.rs index 9f2b785e..0b261a4d 100644 --- a/kernel/src/net/socket.rs +++ b/subsystems/knet/src/socket.rs @@ -7,28 +7,25 @@ //! 的规定,我们只需为套接字文件规定好 [`socket_file_release`]、[`socket_file_write`]、[`socket_file_read`]、 //! [`socket_ready_to_read`]、[`socket_ready_to_write`] 几个操作函数,即可快速的创建套接字文件,并将其放入进程的文件描述 //! 符表中,具体有关套接字文件的创建,可见 [`SocketData::new`] 的实现。 -use super::ShutdownFlag; -use crate::error::AlienResult; -use crate::fs::file::File; -use crate::ksync::{Mutex, MutexGuard}; -use crate::net::addr::SocketAddrExt; -use crate::net::port::neterror2alien; -use crate::net::unix::UnixSocket; -// use crate::task::do_suspend; +use crate::addr::SocketAddrExt; +use crate::port::neterror2alien; +use crate::unix::UnixSocket; use alloc::boxed::Box; use alloc::sync::Arc; +use constants::io::{OpenFlags, PollEvents, SeekFrom}; +use constants::net::{Domain, ShutdownFlag, SocketType}; +use constants::AlienResult; +use constants::LinuxErrno; use core::fmt::{Debug, Formatter}; use core::net::SocketAddr; +use ksync::{Mutex, MutexGuard}; use netcore::tcp::TcpSocket; use netcore::udp::UdpSocket; -use pconst::io::{OpenFlags, PollEvents, SeekFrom}; -use pconst::net::{Domain, SocketType}; -use pconst::LinuxErrno; +use vfs::kfile::File; use vfscore::dentry::VfsDentry; use vfscore::inode::VfsInode; use vfscore::utils::VfsFileStat; -// Only for simplify the modification of the old code pub trait SocketFileExt { fn get_socketdata(&self) -> AlienResult>>; } @@ -193,10 +190,6 @@ impl Debug for Socket { } impl SocketData { - pub fn from_ptr(ptr: *const u8) -> &'static mut Self { - unsafe { &mut *(ptr as *mut Self) } - } - /// 用于创建一个新的套接字数据 `SocketData` 结构,返回创建的文件描述符。一般被系统调用 [`socket`] 所调用。 /// /// 执行过程中会创建一个对应的套接字文件,打开后将对应的文件描述符放入进程的文件描述符表中, diff --git a/kernel/src/net/unix.rs b/subsystems/knet/src/unix.rs similarity index 90% rename from kernel/src/net/unix.rs rename to subsystems/knet/src/unix.rs index e1188c33..e9594c4e 100644 --- a/kernel/src/net/unix.rs +++ b/subsystems/knet/src/unix.rs @@ -1,10 +1,9 @@ //! 有关 Unix 协议族下的套接字结构。(目前有关的功能有待支持) use alloc::string::String; use alloc::sync::Arc; -use pconst::LinuxErrno; - -use crate::fs::file::File; -use crate::ksync::Mutex; +use constants::LinuxErrno; +use ksync::Mutex; +use vfs::kfile::File; /// Unix 协议族下的套接字结构 #[allow(unused)] diff --git a/subsystems/ksync/Cargo.toml b/subsystems/ksync/Cargo.toml new file mode 100644 index 00000000..6a9a9f08 --- /dev/null +++ b/subsystems/ksync/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "ksync" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +config = { path = "../config" } +arch = { path = "../arch" } +kernel-sync = { git = "https://github.com/os-module/kernel-sync.git" } diff --git a/kernel/src/ksync.rs b/subsystems/ksync/src/lib.rs similarity index 95% rename from kernel/src/ksync.rs rename to subsystems/ksync/src/lib.rs index b15cc9c4..464839b7 100644 --- a/kernel/src/ksync.rs +++ b/subsystems/ksync/src/lib.rs @@ -1,5 +1,7 @@ -use crate::arch::{hart_id, interrupt_disable, interrupt_enable, is_interrupt_enable}; -use crate::config::CPU_NUM; +#![no_std] + +use arch::{hart_id, interrupt_disable, interrupt_enable, is_interrupt_enable}; +use config::CPU_NUM; use core::cell::{RefCell, RefMut}; use kernel_sync::{ticket::TicketMutexGuard, LockAction}; diff --git a/subsystems/mem/Cargo.toml b/subsystems/mem/Cargo.toml new file mode 100644 index 00000000..207e1a37 --- /dev/null +++ b/subsystems/mem/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "mem" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +config = {path = "../config" } +arch = {path = "../arch" } +ksync = { path = "../ksync" } +pager = { git = "https://github.com/os-module/pager", default-features = false, optional = true } +platform = { path = "../platform" } +log = "0" +talc = { version = "1.0", optional = true } +buddy_system_allocator = { version = "0.9.0", optional = true } +rslab = { version = "0.2.1", optional = true } + +spin = "0" + +page-table = { git = "https://github.com/os-module/page-table.git", branch = "dev" } + +#page_table = { git = "https://github.com/rcore-os/arceos",rev = "7eeebc5" } +#memory_addr = { git = "https://github.com/rcore-os/arceos",rev = "7eeebc5" } + + + +[features] +default = ["pager_bitmap","talloc"] +pager_buddy = ["pager/buddy"] +pager_bitmap = ["pager/bitmap"] +slab = ["rslab"] +talloc = ["talc"] +buddy = ["buddy_system_allocator"] \ No newline at end of file diff --git a/subsystems/mem/src/frame.rs b/subsystems/mem/src/frame.rs new file mode 100644 index 00000000..378a86a0 --- /dev/null +++ b/subsystems/mem/src/frame.rs @@ -0,0 +1,138 @@ +use crate::manager::FRAME_REF_MANAGER; +use alloc::format; +use config::{FRAME_BITS, FRAME_SIZE}; +use core::mem::forget; +use core::ops::{Deref, DerefMut}; +use ksync::Mutex; +use log::trace; +use page_table::addr::{PhysAddr, VirtAddr}; +use page_table::table::PagingIf; +use pager::{PageAllocator, PageAllocatorExt}; +use platform::println; + +#[cfg(feature = "pager_bitmap")] +pub static FRAME_ALLOCATOR: Mutex> = Mutex::new(pager::Bitmap::new()); +#[cfg(feature = "pager_buddy")] +pub static FRAME_ALLOCATOR: Mutex> = Mutex::new(pager::Zone::new()); + +pub fn init_frame_allocator(start: usize, end: usize) { + let page_start = start / FRAME_SIZE; + let page_end = end / FRAME_SIZE; + let page_count = page_end - page_start; + println!( + "Page start:{:#x},end:{:#x},count:{:#x}", + page_start, page_end, page_count + ); + FRAME_ALLOCATOR + .lock() + .init(start..end) + .expect("init frame allocator failed"); +} + +#[no_mangle] +pub fn alloc_frames(num: usize) -> *mut u8 { + assert_eq!(num.next_power_of_two(), num); + let start_page = FRAME_ALLOCATOR + .lock() + .alloc_pages(num, FRAME_SIZE) + .expect(format!("alloc {} frame failed", num).as_str()); + let start_addr = start_page << FRAME_BITS; + start_addr as *mut u8 +} + +#[no_mangle] +pub fn free_frames(addr: *mut u8, num: usize) { + assert_eq!(num.next_power_of_two(), num); + let start = addr as usize >> FRAME_BITS; + FRAME_ALLOCATOR + .lock() + .free_pages(start, num) + .expect(format!("free frame start:{:#x},num:{} failed", start, num).as_str()); +} + +#[derive(Debug)] +pub struct FrameTracker { + start: usize, + size: usize, +} + +impl FrameTracker { + pub fn new(start: usize, size: usize) -> Self { + Self { start, size } + } + pub fn from_addr(addr: usize, size: usize) -> Self { + assert_eq!(addr % FRAME_SIZE, 0); + Self::new(addr >> FRAME_BITS, size) + } + pub fn start(&self) -> usize { + self.start << FRAME_BITS + } + pub fn end(&self) -> usize { + self.start() + FRAME_SIZE * self.size + } + pub fn as_ptr(&self) -> *mut u8 { + self.start() as *mut u8 + } +} + +impl Drop for FrameTracker { + fn drop(&mut self) { + trace!("drop frame tracker: {:#x?}", self); + let mut manager = FRAME_REF_MANAGER.lock(); + for i in 0..self.size { + let _id = manager.dec_ref(self.start + i); + } + } +} + +impl Deref for FrameTracker { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + unsafe { core::slice::from_raw_parts(self.start() as *const u8, FRAME_SIZE * self.size) } + } +} +impl DerefMut for FrameTracker { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { core::slice::from_raw_parts_mut(self.start() as *mut u8, FRAME_SIZE * self.size) } + } +} + +pub fn alloc_frame_trackers(count: usize) -> FrameTracker { + let frame = FRAME_ALLOCATOR + .lock() + .alloc_pages(count, FRAME_SIZE) + .expect(format!("alloc {} frame failed", count).as_str()); + trace!("alloc frame [{}] start page: {:#x}", count, frame); + for i in 0..count { + let refs = FRAME_REF_MANAGER.lock().add_ref(frame + i); + assert_eq!(refs, 1) + } + FrameTracker::new(frame, count) +} + +pub struct VmmPageAllocator; + +impl PagingIf for VmmPageAllocator { + fn alloc_frame() -> Option { + let frame = alloc_frame_trackers(1); + let start_addr = frame.start(); + forget(frame); + Some(PhysAddr::from(start_addr)) + } + + fn dealloc_frame(paddr: PhysAddr) { + FrameTracker::from_addr(paddr.as_usize(), 1); + } + + fn phys_to_virt(paddr: PhysAddr) -> VirtAddr { + VirtAddr::from(paddr.as_usize()) + } + + fn alloc_contiguous_frames(size: usize) -> Option { + let frames = alloc_frame_trackers(size); + let start_addr = frames.start(); + forget(frames); + Some(PhysAddr::from(start_addr)) + } +} diff --git a/subsystems/mem/src/heap.rs b/subsystems/mem/src/heap.rs new file mode 100644 index 00000000..bb004252 --- /dev/null +++ b/subsystems/mem/src/heap.rs @@ -0,0 +1,73 @@ +use crate::frame::{alloc_frames, free_frames}; +#[cfg(feature = "buddy")] +use buddy_system_allocator::LockedHeap; +use config::FRAME_SIZE; +use core::alloc::GlobalAlloc; +use ksync::Mutex; +use log::trace; +#[cfg(feature = "rslab")] +use rslab::{init_slab_system, SlabAllocator}; +#[cfg(feature = "talloc")] +use talc::{Talc, Talck}; + +pub struct HeapAllocator { + #[cfg(feature = "talloc")] + allocator: Mutex, + #[cfg(feature = "buddy")] + allocator: Mutex>, + #[cfg(feature = "slab")] + allocator: Mutex, +} + +unsafe impl GlobalAlloc for HeapAllocator { + unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 { + if layout.size() >= 5 * 1024 * 1024 { + let need_page = (layout.size() + FRAME_SIZE - 1) / FRAME_SIZE; + trace!("alloc big page: {:#x}", layout.size()); + alloc_frames(need_page) + } else { + self.allocator.lock().alloc(layout) + } + } + unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) { + if layout.size() >= 5 * 1024 * 1024 { + let need_page = (layout.size() + FRAME_SIZE - 1) / FRAME_SIZE; + trace!("free big page: {:#x}", layout.size()); + free_frames(ptr, need_page); + } else { + self.allocator.lock().dealloc(ptr, layout); + } + } +} + +impl HeapAllocator { + pub const fn new() -> Self { + Self { + #[cfg(feature = "talloc")] + allocator: Mutex::new(Talc::new().spin_lock()), + #[cfg(feature = "buddy")] + allocator: Mutex::new(LockedHeap::<32>::new()), + #[cfg(feature = "slab")] + allocator: Mutex::new(SlabAllocator), + } + } + pub fn init(&self, heap: &mut [u8]) { + #[cfg(feature = "talloc")] + unsafe { + self.allocator.lock().talc().init(heap.into()) + } + #[cfg(feature = "buddy")] + unsafe { + self.allocator + .lock() + .lock() + .init(heap.as_mut_ptr() as usize, heap.len()) + } + #[cfg(feature = "slab")] + unsafe { + init_slab_system(FRAME_SIZE, 64); + } + #[cfg(any(feature = "talc", feature = "buddy"))] + println!("Kernel Heap size: {:#x}MB", heap.len() / 1024 / 1024); + } +} diff --git a/subsystems/mem/src/lib.rs b/subsystems/mem/src/lib.rs new file mode 100644 index 00000000..9d665c89 --- /dev/null +++ b/subsystems/mem/src/lib.rs @@ -0,0 +1,55 @@ +#![no_std] + +extern crate alloc; +#[macro_use] +extern crate platform; +use arch::activate_paging_mode; +use config::FRAME_BITS; +use heap::HeapAllocator; +use platform::config::HEAP_SIZE; +mod frame; +mod heap; +mod manager; +mod vmm; + +pub use frame::{alloc_frame_trackers, alloc_frames, free_frames, FrameTracker, VmmPageAllocator}; + +pub use vmm::{kernel_pgd, kernel_satp, map_region_to_kernel, query_kernel_space}; + +pub use manager::FRAME_REF_MANAGER; +#[global_allocator] +static HEAP_ALLOCATOR: HeapAllocator = HeapAllocator::new(); + +#[cfg(any(feature = "talloc", feature = "buddy"))] +static mut KERNEL_HEAP: [u8; HEAP_SIZE] = [0; HEAP_SIZE]; + +extern "C" { + fn ekernel(); +} + +pub fn init_memory_system(memory_end: usize, is_first_cpu: bool) { + if is_first_cpu { + frame::init_frame_allocator(ekernel as usize, memory_end); + println!("Frame allocator init success"); + #[cfg(any(feature = "talloc", feature = "buddy"))] + HEAP_ALLOCATOR.init(unsafe { &mut KERNEL_HEAP }); + #[cfg(feature = "talloc")] + { + println!("Talloc allocator init success"); + } + #[cfg(feature = "slab")] + { + println!("Slab allocator init success"); + } + #[cfg(feature = "buddy")] + { + println!("Buddy allocator init success"); + } + vmm::build_kernel_address_space(memory_end); + println!("Build kernel address space success"); + activate_paging_mode(vmm::kernel_pgd() >> FRAME_BITS); + println!("Activate paging mode success"); + } else { + activate_paging_mode(vmm::kernel_pgd() >> FRAME_BITS); + } +} diff --git a/kernel/src/memory/manager.rs b/subsystems/mem/src/manager.rs similarity index 81% rename from kernel/src/memory/manager.rs rename to subsystems/mem/src/manager.rs index 779c091a..31b13124 100644 --- a/kernel/src/memory/manager.rs +++ b/subsystems/mem/src/manager.rs @@ -1,7 +1,12 @@ +use crate::frame::FRAME_ALLOCATOR; use alloc::collections::BTreeMap; +use ksync::Mutex; +use log::trace; use pager::PageAllocator; +use spin::Lazy; -use crate::memory::FRAME_ALLOCATOR; +pub static FRAME_REF_MANAGER: Lazy> = + Lazy::new(|| Mutex::new(FrameRefManager::new())); #[derive(Debug)] pub struct FrameRefManager { @@ -34,7 +39,7 @@ impl FrameRefManager { } return Some(now_count); } else { - panic!("dec {} ref error", id); + panic!("dec page {:#x?} ref error", id); } } pub fn get_ref(&self, id: usize) -> usize { diff --git a/subsystems/mem/src/vmm.rs b/subsystems/mem/src/vmm.rs new file mode 100644 index 00000000..b36977f3 --- /dev/null +++ b/subsystems/mem/src/vmm.rs @@ -0,0 +1,164 @@ +use crate::frame::VmmPageAllocator; +use alloc::sync::Arc; +use config::{FRAME_BITS, FRAME_SIZE, TRAMPOLINE}; +use ksync::RwLock; +use page_table::addr::{PhysAddr, VirtAddr}; +use page_table::pte::MappingFlags; +use page_table::table::Sv39PageTable; +use platform::config::MMIO; +use spin::Lazy; + +extern "C" { + fn stext(); + fn srodata(); + fn sdata(); + fn sbss(); + fn ekernel(); + fn strampoline(); + fn sinit(); + fn einit(); + // fn kernel_eh_frame(); + // fn kernel_eh_frame_end(); + // fn kernel_eh_frame_hdr(); + // fn kernel_eh_frame_hdr_end(); +} + +fn kernel_info(memory_end: usize) { + println!( + "kernel text: {:#x}-{:#x}", + stext as usize, srodata as usize + ); + println!( + "kernel rodata: {:#x}-{:#x}", + srodata as usize, sdata as usize + ); + println!( + "kernel init_array: {:#x}-{:#x}", + sinit as usize, einit as usize + ); + println!( + "kernel data: {:#x}-{:#x}", + sdata as usize, sbss as usize + ); + println!( + "kernel bss: {:#x}-{:#x}", + sbss as usize, ekernel as usize + ); + // println!("kernel eh_frame: {:#x}-{:#x}", kernel_eh_frame as usize, kernel_eh_frame_end as usize); + // println!("kernel eh_frame_hdr: {:#x}-{:#x}", kernel_eh_frame_hdr as usize, kernel_eh_frame_hdr_end as usize); + println!( + "kernel heap: {:#x}-{:#x}", + ekernel as usize, memory_end + ); +} + +pub static KERNEL_SPACE: Lazy>>> = Lazy::new(|| { + Arc::new(RwLock::new( + Sv39PageTable::::try_new().unwrap(), + )) +}); + +pub fn build_kernel_address_space(memory_end: usize) { + kernel_info(memory_end); + let mut kernel_space = KERNEL_SPACE.write(); + kernel_space + .map_region( + VirtAddr::from(stext as usize), + PhysAddr::from(stext as usize), + srodata as usize - stext as usize, + "RXVAD".into(), + true, + ) + .unwrap(); + kernel_space + .map_region( + VirtAddr::from(srodata as usize), + PhysAddr::from(srodata as usize), + sdata as usize - srodata as usize, + "RVAD".into(), + true, + ) + .unwrap(); + kernel_space + .map_region( + VirtAddr::from(sdata as usize), + PhysAddr::from(sdata as usize), + sbss as usize - sdata as usize, + "RWVAD".into(), + true, + ) + .unwrap(); + kernel_space + .map_region( + VirtAddr::from(sbss as usize), + PhysAddr::from(sbss as usize), + ekernel as usize - sbss as usize, + "RWVAD".into(), + true, + ) + .unwrap(); + kernel_space + .map_region( + VirtAddr::from(ekernel as usize), + PhysAddr::from(ekernel as usize), + memory_end - ekernel as usize, + "RWVAD".into(), + true, + ) + .unwrap(); + kernel_space + .map_region( + VirtAddr::from(TRAMPOLINE), + PhysAddr::from(strampoline as usize), + FRAME_SIZE, + "RXVAD".into(), + true, + ) + .unwrap(); + for pair in MMIO { + kernel_space + .map_region( + VirtAddr::from(pair.0), + PhysAddr::from(pair.0), + pair.1, + "RWVAD".into(), + true, + ) + .unwrap(); + println!("map mmio: {:#x?}-{:#x?}", pair.0, pair.0 + pair.1); + } +} + +// static KERNEL_MAP_MAX: AtomicUsize = AtomicUsize::new(0); +pub fn kernel_pgd() -> usize { + KERNEL_SPACE.read().root_paddr().as_usize() +} + +pub fn kernel_satp() -> usize { + 8usize << 60 | (KERNEL_SPACE.read().root_paddr().as_usize() >> FRAME_BITS) +} + +// pub fn alloc_kernel_free_region(size: usize) -> usize { +// assert!(size > 0 && size % FRAME_SIZE == 0); +// KERNEL_MAP_MAX.fetch_add(size, core::sync::atomic::Ordering::SeqCst) +// } + +pub fn map_region_to_kernel(addr: usize, size: usize, flags: MappingFlags) { + let mut kernel_space = KERNEL_SPACE.write(); + kernel_space + .map_region( + VirtAddr::from(addr), + PhysAddr::from(addr), + size, + flags, + true, + ) + .unwrap(); +} +pub fn query_kernel_space(addr: usize) -> Option { + let kernel_space = KERNEL_SPACE.read(); + kernel_space + .query(VirtAddr::from(addr)) + .ok() + .map(|(x, _, _)| x.as_usize()) +} diff --git a/subsystems/platform/Cargo.toml b/subsystems/platform/Cargo.toml new file mode 100644 index 00000000..6bc7c2bd --- /dev/null +++ b/subsystems/platform/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "platform" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +log = "0" +arch = { path = "../arch" } +config = { path = "../config" } +ksync = { path = "../ksync" } +spin = "0" + +preprint = "0.1.0" +fdt = { git = "https://github.com/repnop/fdt" } + +[features] +default = [] + +qemu_riscv = [] +vf2 = [] +hifive = [] +smp = [] \ No newline at end of file diff --git a/dep/basemachine/src/lib.rs b/subsystems/platform/src/basic.rs similarity index 58% rename from dep/basemachine/src/lib.rs rename to subsystems/platform/src/basic.rs index b46f2173..28583c84 100644 --- a/dep/basemachine/src/lib.rs +++ b/subsystems/platform/src/basic.rs @@ -1,172 +1,104 @@ -//! This crate provides a way to get machine information from a device-tree. -//! -//! # Example -//! ``` -//! use basemachine::machine_info_from_dtb; -//! let machine_info = machine_info_from_dtb(0x80700000); -//! ``` -#![no_std] -#![deny(missing_docs)] -use core::cmp::min; -use core::fmt::Debug; -use core::ops::Range; - -use fdt::Fdt; - -const MEMORY: &str = "memory"; -const SERIAL: &str = "serial"; -const UART: &str = "uart"; -const PLIC: &str = "plic"; -const CLINT: &str = "clint"; -const RTC: &str = "rtc"; - -/// Machine basic information -#[derive(Clone)] -pub struct MachineInfo { - /// Machine model - pub model: [u8; 32], - /// Number of CPUs - pub smp: usize, - /// Memory range - pub memory: Range, - /// UART information - pub uart: [UartInfo; 8], - /// PLIC information - pub plic: Range, - /// CLINT information - pub clint: Range, - /// RTC information - pub rtc: RtcInfo, - /// Number of UARTs - pub uart_count: usize, -} - -impl Debug for MachineInfo { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - let index = self.model.iter().position(|&x| x == 0).unwrap_or(32); - let model = core::str::from_utf8(&self.model[..index]).unwrap(); - write!( - f, - "This is a devicetree representation of a {} machine\n", - model - ) - .unwrap(); - write!(f, "SMP: {}\n", self.smp).unwrap(); - write!( - f, - "Memory: {:#x}..{:#x}\n", - self.memory.start, self.memory.end - ) - .unwrap(); - write!(f, "PLIC: {:#x}..{:#x}\n", self.plic.start, self.plic.end).unwrap(); - write!(f, "CLINT: {:#x}..{:#x}", self.clint.start, self.clint.end).unwrap(); - Ok(()) - } -} - -/// RTC information -#[derive(Debug, Default, Clone)] -pub struct RtcInfo { - /// mmio virtual address - pub range: Range, - /// interrupt number - pub irq: usize, -} - -/// UART information -#[derive(Debug, Default, Copy, Clone)] -#[allow(unused)] -pub struct UartInfo { - /// mmio virtual address - base: usize, - /// interrupt number - irq: usize, -} - -/// Get machine information from a device-tree -pub fn machine_info_from_dtb(ptr: usize) -> MachineInfo { - let fdt = unsafe { Fdt::from_ptr(ptr as *const u8).unwrap() }; - walk_dt(fdt) -} - -// Walk the device-tree and get machine information -fn walk_dt(fdt: Fdt) -> MachineInfo { - let mut machine = MachineInfo { - model: [0; 32], - smp: 0, - memory: 0..0, - uart: [UartInfo::default(); 8], - plic: 0..0, - clint: 0..0, - rtc: RtcInfo::default(), - uart_count: 0, - }; - let x = fdt.root(); - machine.smp = fdt.cpus().count(); - let model = x.model().as_bytes(); - let len = min(model.len(), machine.model.len()); - machine.model[0..len].copy_from_slice(&model[..len]); - - let mut uart_count = 0; - - for node in fdt.all_nodes() { - if node.name.starts_with(MEMORY) { - let reg = node.reg().unwrap(); - reg.for_each(|x| { - machine.memory = Range { - start: x.starting_address as usize, - end: x.starting_address as usize + x.size.unwrap(), - } - }) - } else if node.name.starts_with(SERIAL) || node.name.starts_with(UART) { - let reg = node.reg(); - if reg.is_none() { - continue; - } - let irq = node.property("interrupts").unwrap().value; - let irq = u32::from_be_bytes(irq.try_into().unwrap()); - - let reg = reg.unwrap(); - // let val = node.interrupts().unwrap().next().unwrap(); - let mut base = 0; - // let irq = val as u32; - reg.for_each(|x| { - base = x.starting_address as usize; - }); - machine.uart[uart_count] = UartInfo { - base, - irq: irq as usize, - }; - uart_count += 1; - } else if node.name.starts_with(PLIC) { - let reg = node.reg().unwrap(); - reg.for_each(|x| { - machine.plic = Range { - start: x.starting_address as usize, - end: x.starting_address as usize + x.size.unwrap(), - } - }) - } else if node.name.starts_with(CLINT) { - let reg = node.reg().unwrap(); - reg.for_each(|x| { - machine.clint = Range { - start: x.starting_address as usize, - end: x.starting_address as usize + x.size.unwrap(), - } - }) - } else if node.name.starts_with(RTC) { - let reg = node.reg().unwrap(); - let irq = 0xc; - let mut range = 0..0; - reg.for_each(|x| { - range = Range { - start: x.starting_address as usize, - end: x.starting_address as usize + x.size.unwrap(), - } - }); - machine.rtc = RtcInfo { range, irq } - } - } - machine.uart_count = uart_count; - machine -} +//! This crate provides a way to get machine information from a device-tree. +//! +//! # Example +//! ``` +//! let machine_info = machine_info_from_dtb(0x80700000); +//! ``` +use core::cmp::min; +use core::fmt::Debug; +use core::ops::Range; + +use fdt::Fdt; + +const MEMORY: &str = "memory"; +const PLIC: &str = "plic"; +const CLINT: &str = "clint"; + +/// Machine basic information +#[derive(Clone)] +pub struct MachineInfo { + /// Machine model + pub model: [u8; 32], + /// Number of CPUs + pub smp: usize, + /// Memory range + pub memory: Range, + /// PLIC information + pub plic: Range, + /// CLINT information + pub clint: Range, +} + +impl Debug for MachineInfo { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let index = self.model.iter().position(|&x| x == 0).unwrap_or(32); + let model = core::str::from_utf8(&self.model[..index]).unwrap(); + write!( + f, + "This is a device tree representation of a {} machine\n", + model + ) + .unwrap(); + write!(f, "SMP: {}\n", self.smp).unwrap(); + write!( + f, + "Memory: {:#x}..{:#x}\n", + self.memory.start, self.memory.end + ) + .unwrap(); + write!(f, "PLIC: {:#x}..{:#x}\n", self.plic.start, self.plic.end).unwrap(); + write!(f, "CLINT: {:#x}..{:#x}", self.clint.start, self.clint.end).unwrap(); + Ok(()) + } +} + +/// Get machine information from a device-tree +pub fn machine_info_from_dtb(ptr: usize) -> MachineInfo { + let fdt = unsafe { Fdt::from_ptr(ptr as *const u8).unwrap() }; + walk_dt(fdt) +} + +// Walk the device-tree and get machine information +fn walk_dt(fdt: Fdt) -> MachineInfo { + let mut machine = MachineInfo { + model: [0; 32], + smp: 0, + memory: 0..0, + plic: 0..0, + clint: 0..0, + }; + let x = fdt.root(); + machine.smp = fdt.cpus().count(); + let model = x.model().as_bytes(); + let len = min(model.len(), machine.model.len()); + machine.model[0..len].copy_from_slice(&model[..len]); + + for node in fdt.all_nodes() { + if node.name.starts_with(MEMORY) { + let reg = node.reg().unwrap(); + reg.for_each(|x| { + machine.memory = Range { + start: x.starting_address as usize, + end: x.starting_address as usize + x.size.unwrap(), + } + }) + } else if node.name.starts_with(PLIC) { + let reg = node.reg().unwrap(); + reg.for_each(|x| { + machine.plic = Range { + start: x.starting_address as usize, + end: x.starting_address as usize + x.size.unwrap(), + } + }) + } else if node.name.starts_with(CLINT) { + let reg = node.reg().unwrap(); + reg.for_each(|x| { + machine.clint = Range { + start: x.starting_address as usize, + end: x.starting_address as usize + x.size.unwrap(), + } + }) + } + } + machine +} diff --git a/subsystems/platform/src/common_riscv/boot.rs b/subsystems/platform/src/common_riscv/boot.rs new file mode 100644 index 00000000..49425086 --- /dev/null +++ b/subsystems/platform/src/common_riscv/boot.rs @@ -0,0 +1,69 @@ +use config::{CPU_NUM, STACK_SIZE, STACK_SIZE_BITS}; +use core::arch::asm; + +#[link_section = ".bss.stack"] +static mut STACK: [u8; STACK_SIZE * CPU_NUM] = [0; STACK_SIZE * CPU_NUM]; + +/// 内核入口 +/// +/// 用于初始化内核的栈空间,并关闭中断 +#[naked] +#[no_mangle] +#[link_section = ".text.entry"] +extern "C" fn _start() { + unsafe { + asm!("\ + mv tp, a0 + mv gp, a1 + add t0, a0, 1 + slli t0, t0, {stack_size_bits} + la sp, {boot_stack} + add sp, sp, t0 + call clear_bss + mv a0, tp + mv a1, gp + call {platform_init} + ", + stack_size_bits = const STACK_SIZE_BITS, + boot_stack = sym STACK, + platform_init = sym crate::platform_init, + options(noreturn) + ); + } +} + +#[naked] +#[no_mangle] +extern "C" fn _start_secondary() { + unsafe { + asm!("\ + mv tp, a0 + mv gp, a1 + add t0, a0, 1 + slli t0, t0, {stack_size_bits} + la sp, {boot_stack} + add sp, sp, t0 + mv a0, tp + mv a1, gp + call main + ", + stack_size_bits = const STACK_SIZE_BITS, + boot_stack = sym STACK, + options(noreturn) + ); + } +} + +extern "C" { + fn sbss(); + fn ebss(); +} + +/// 清空.bss段 +#[no_mangle] +fn clear_bss() { + unsafe { + core::slice::from_raw_parts_mut(sbss as usize as *mut u8, ebss as usize - sbss as usize) + .fill(0); + } +} diff --git a/subsystems/platform/src/common_riscv/mod.rs b/subsystems/platform/src/common_riscv/mod.rs new file mode 100644 index 00000000..6823140c --- /dev/null +++ b/subsystems/platform/src/common_riscv/mod.rs @@ -0,0 +1,2 @@ +pub mod boot; +pub mod sbi; diff --git a/kernel/src/sbi.rs b/subsystems/platform/src/common_riscv/sbi.rs similarity index 83% rename from kernel/src/sbi.rs rename to subsystems/platform/src/common_riscv/sbi.rs index 58a3d3cd..2712cca6 100644 --- a/kernel/src/sbi.rs +++ b/subsystems/platform/src/common_riscv/sbi.rs @@ -1,128 +1,124 @@ -//! SBI 调用接口 -use core::arch::asm; - -use syscall_table::syscall_func; - -/// 设置定时器 -const SBI_SET_TIMER: usize = 0; -/// 控制台输出 -const SBI_CONSOLE_PUT_CHAR: usize = 1; -/// 控制台输入 -const SBI_CONSOLE_GET_CHAR: usize = 2; -// const SBI_CLEAR_IPI: usize = 3; -/// 发送 IPI -const SBI_SEND_IPI: usize = 4; -// const SBI_REMOTE_FENCE_I: usize = 5; -// const SBI_REMOTE_SFENCE_VMA: usize = 6; -// const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7; -/// 关闭机器 -const SBI_SHUTDOWN: usize = 8; - -/// SBI 调用 -/// -/// sbi规范定义了调用的参数传递方法 -fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> i32 { - let mut ret; - unsafe { - asm!("ecall", - in("a7") which, - inlateout("a0") arg0 as i32 => ret, - in("a1") arg1, - in("a2") arg2); - } - ret -} - -/// 设置定时器 -pub fn set_timer(time: usize) { - sbi_call(SBI_SET_TIMER, time, 0, 0); -} - -/// 一个系统调用,通过调用 SBI_SHUTDOWN 来关闭操作系统(直接退出 QEMU) -#[syscall_func(2003)] -pub fn system_shutdown() -> isize { - mprintln!("shutdown..."); - sbi_call(SBI_SHUTDOWN, 0, 0, 0); - 0 -} - -/// Warp sbi SBI_CONSOLE_PUT_CHAR call -pub fn console_putchar(ch: u8) { - sbi_call(SBI_CONSOLE_PUT_CHAR, ch as usize, 0, 0); -} - -/// Warp sbi SBI_CONSOLE_GET_CHAR call -#[allow(unused)] -pub fn console_getchar() -> char { - sbi_call(SBI_CONSOLE_GET_CHAR, 0, 0, 0) as u8 as char -} - -/// sbi调用返回值 -#[repr(C)] -#[derive(Debug)] -pub struct SbiRet { - /// Error number - pub error: isize, - /// Result value - pub value: isize, -} - -/// SBI 基本扩展 -pub const EXTENSION_BASE: usize = 0x10; -/// SBI 时钟扩展 -pub const EXTENSION_TIMER: usize = 0x54494D45; -// pub const EXTENSION_IPI: usize = 0x735049; -// pub const EXTENSION_RFENCE: usize = 0x52464E43; -/// SBI HSM 扩展 -pub const EXTENSION_HSM: usize = 0x48534D; -// pub const EXTENSION_SRST: usize = 0x53525354; - -/// SBI HSM扩展的启动cpu功能 -const FUNCTION_HSM_HART_START: usize = 0x0; -// const FUNCTION_HSM_HART_STOP: usize = 0x1; -// const FUNCTION_HSM_HART_GET_STATUS: usize = 0x2; -// const FUNCTION_HSM_HART_SUSPEND: usize = 0x3; - -/// 第三种类型的SBI调用 -/// -/// 可以传递更多参数 -#[inline(always)] -fn sbi_call_3(extension: usize, function: usize, arg0: usize, arg1: usize, arg2: usize) -> SbiRet { - let (error, value); - unsafe { - asm!( - "ecall", - in("a0") arg0, in("a1") arg1, in("a2") arg2, - in("a6") function, in("a7") extension, - lateout("a0") error, lateout("a1") value, - ) - } - SbiRet { error, value } -} - -// pub fn hart_suspend(suspend_type: u32, resume_addr: usize, opaque: usize) -> SbiRet { -// sbi_call_3( -// EXTENSION_HSM, -// FUNCTION_HSM_HART_SUSPEND, -// suspend_type as usize, -// resume_addr, -// opaque, -// ) -// } - -/// wrap sbi FUNCTION_HSM_HART_START call -pub fn hart_start(hart_id: usize, start_addr: usize, opaque: usize) -> SbiRet { - sbi_call_3( - EXTENSION_HSM, - FUNCTION_HSM_HART_START, - hart_id, - start_addr, - opaque, - ) -} - -/// wrap sbi SBI_SEND_IPI call -#[allow(unused)] -pub fn send_ipi(ptr: usize) { - sbi_call(SBI_SEND_IPI, ptr, 0, 0); -} +#![allow(unused)] +//! SBI 调用接口 +use core::arch::asm; + +/// 设置定时器 +const SBI_SET_TIMER: usize = 0; +/// 控制台输出 +const SBI_CONSOLE_PUT_CHAR: usize = 1; +/// 控制台输入 +const SBI_CONSOLE_GET_CHAR: usize = 2; +// const SBI_CLEAR_IPI: usize = 3; +/// 发送 IPI +const SBI_SEND_IPI: usize = 4; +// const SBI_REMOTE_FENCE_I: usize = 5; +// const SBI_REMOTE_SFENCE_VMA: usize = 6; +// const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7; +/// 关闭机器 +const SBI_SHUTDOWN: usize = 8; + +/// SBI 调用 +/// +/// sbi规范定义了调用的参数传递方法 +fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> i32 { + let mut ret; + unsafe { + asm!("ecall", + in("a7") which, + inlateout("a0") arg0 as i32 => ret, + in("a1") arg1, + in("a2") arg2); + } + ret +} + +/// 设置定时器 +pub fn set_timer(time: usize) { + sbi_call(SBI_SET_TIMER, time, 0, 0); +} + +pub fn system_shutdown() -> ! { + sbi_call(SBI_SHUTDOWN, 0, 0, 0); + loop {} +} + +/// Warp sbi SBI_CONSOLE_PUT_CHAR call +pub fn console_putchar(ch: u8) { + sbi_call(SBI_CONSOLE_PUT_CHAR, ch as usize, 0, 0); +} + +/// Warp sbi SBI_CONSOLE_GET_CHAR call +#[allow(unused)] +pub fn console_getchar() -> char { + sbi_call(SBI_CONSOLE_GET_CHAR, 0, 0, 0) as u8 as char +} + +/// sbi调用返回值 +#[repr(C)] +#[derive(Debug)] +pub struct SbiRet { + /// Error number + pub error: isize, + /// Result value + pub value: isize, +} + +/// SBI 基本扩展 +pub const EXTENSION_BASE: usize = 0x10; +/// SBI 时钟扩展 +pub const EXTENSION_TIMER: usize = 0x54494D45; +// pub const EXTENSION_IPI: usize = 0x735049; +// pub const EXTENSION_RFENCE: usize = 0x52464E43; +/// SBI HSM 扩展 +pub const EXTENSION_HSM: usize = 0x48534D; +// pub const EXTENSION_SRST: usize = 0x53525354; + +/// SBI HSM扩展的启动cpu功能 +const FUNCTION_HSM_HART_START: usize = 0x0; +// const FUNCTION_HSM_HART_STOP: usize = 0x1; +// const FUNCTION_HSM_HART_GET_STATUS: usize = 0x2; +const FUNCTION_HSM_HART_SUSPEND: usize = 0x3; + +/// 第三种类型的SBI调用 +/// +/// 可以传递更多参数 +#[inline(always)] +fn sbi_call_3(extension: usize, function: usize, arg0: usize, arg1: usize, arg2: usize) -> SbiRet { + let (error, value); + unsafe { + asm!( + "ecall", + in("a0") arg0, in("a1") arg1, in("a2") arg2, + in("a6") function, in("a7") extension, + lateout("a0") error, lateout("a1") value, + ) + } + SbiRet { error, value } +} + +pub fn hart_suspend(suspend_type: u32, resume_addr: usize, opaque: usize) -> SbiRet { + sbi_call_3( + EXTENSION_HSM, + FUNCTION_HSM_HART_SUSPEND, + suspend_type as usize, + resume_addr, + opaque, + ) +} + +/// wrap sbi FUNCTION_HSM_HART_START call +pub fn hart_start(hart_id: usize, start_addr: usize, opaque: usize) -> SbiRet { + sbi_call_3( + EXTENSION_HSM, + FUNCTION_HSM_HART_START, + hart_id, + start_addr, + opaque, + ) +} + +/// wrap sbi SBI_SEND_IPI call +#[allow(unused)] +pub fn send_ipi(ptr: usize) { + sbi_call(SBI_SEND_IPI, ptr, 0, 0); +} diff --git a/subsystems/platform/src/console.rs b/subsystems/platform/src/console.rs new file mode 100644 index 00000000..22e491c0 --- /dev/null +++ b/subsystems/platform/src/console.rs @@ -0,0 +1,63 @@ +use core::fmt::{Arguments, Result, Write}; +use ksync::Mutex; +use preprint::Print; +/// 系统启动初期使用的输出函数 +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => { + let hard_id = arch::hart_id(); + $crate::console::__print(format_args!("[{}] {}", hard_id, format_args!($($arg)*))) + }; +} + +/// 系统启动初期使用的输出函数 +#[macro_export] +macro_rules! println { + () => ($crate::print!("\n")); + ($fmt:expr) => ($crate::print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => ($crate::print!( + concat!($fmt, "\n"), $($arg)*)); +} + +pub struct Stdout; + +/// 对`Stdout`实现输出的Trait +impl Write for Stdout { + fn write_str(&mut self, s: &str) -> Result { + s.as_bytes().iter().for_each(|x| { + crate::console_putchar(*x); + }); + Ok(()) + } +} + +static STDOUT: Mutex = Mutex::new(Stdout); + +/// 输出函数 +/// 对参数进行输出 主要使用在输出相关的宏中 如println +#[doc(hidden)] +pub fn __print(args: Arguments) { + STDOUT.lock().write_fmt(args).unwrap(); +} + +/// 系统启动初期使用的输出函数 +/// +/// 在riscv平台上,由于没有实现串口驱动,所以在系统启动初期使用SBI进行输出 +pub fn console_write(s: &str) { + Stdout.write_str(s).unwrap(); +} + +pub struct PrePrint; + +impl Print for PrePrint { + fn print(&self, args: Arguments) { + print!("{}", args); + } +} + +impl Write for PrePrint { + fn write_str(&mut self, s: &str) -> Result { + print!("{}", s); + Ok(()) + } +} diff --git a/subsystems/platform/src/hifive_riscv/config.rs b/subsystems/platform/src/hifive_riscv/config.rs new file mode 100644 index 00000000..5b99f7a2 --- /dev/null +++ b/subsystems/platform/src/hifive_riscv/config.rs @@ -0,0 +1,7 @@ +pub const CLOCK_FREQ: usize = 100_0000; +pub const BLOCK_CACHE_FRAMES: usize = 1024 * 4 * 4; +pub const HEAP_SIZE: usize = 0x40_00000; //64M + +pub const MMIO: &[(usize, usize)] = &[ + (0xc000000, 0x4000000), //PLIC +]; diff --git a/subsystems/platform/src/hifive_riscv/mod.rs b/subsystems/platform/src/hifive_riscv/mod.rs new file mode 100644 index 00000000..ea0f0a11 --- /dev/null +++ b/subsystems/platform/src/hifive_riscv/mod.rs @@ -0,0 +1,32 @@ +pub mod config; + +use spin::Once; + +const FDT: &[u8] = include_bytes!("../../../../tools/hifive-unmatched-a00.dtb"); + +pub static DTB: Once = Once::new(); + +pub fn init_dtb(dtb: Option) { + let dtb_ptr = dtb.unwrap_or(FDT.as_ptr() as usize); + DTB.call_once(|| dtb_ptr); +} + +/// 设置定时器 +pub fn set_timer(time: usize) { + crate::common_riscv::sbi::set_timer(time); +} + +pub fn system_shutdown() -> ! { + crate::common_riscv::sbi::system_shutdown(); +} + +/// Warp sbi SBI_CONSOLE_PUT_CHAR call +pub fn console_putchar(ch: u8) { + crate::common_riscv::sbi::console_putchar(ch); +} + +/// Warp sbi SBI_CONSOLE_GET_CHAR call +#[allow(unused)] +pub fn console_getchar() -> char { + crate::common_riscv::sbi::console_getchar() +} diff --git a/subsystems/platform/src/lib.rs b/subsystems/platform/src/lib.rs new file mode 100644 index 00000000..f46601aa --- /dev/null +++ b/subsystems/platform/src/lib.rs @@ -0,0 +1,95 @@ +#![no_std] +#![feature(naked_functions)] +#![feature(asm_const)] +extern crate alloc; + +#[macro_use] +pub mod console; +mod common_riscv; +#[cfg(feature = "hifive")] +mod hifive_riscv; + +use ::config::CPU_NUM; +pub use basic::MachineInfo as PlatformInfo; +use spin::Once; +mod basic; + +pub mod logging; +#[cfg(feature = "qemu_riscv")] +mod qemu_riscv; +#[cfg(feature = "vf2")] +mod starfive2_riscv; + +#[cfg(feature = "qemu_riscv")] +use qemu_riscv::console_putchar; +#[cfg(feature = "qemu_riscv")] +pub use qemu_riscv::{config, set_timer, system_shutdown}; + +#[cfg(feature = "vf2")] +use starfive2_riscv::console_putchar; +#[cfg(feature = "vf2")] +pub use starfive2_riscv::{config, set_timer, system_shutdown}; + +#[cfg(feature = "hifive")] +use hifive_riscv::console_putchar; + +use crate::common_riscv::sbi::hart_start; +use crate::console::PrePrint; +#[cfg(feature = "hifive")] +pub use hifive_riscv::{config, set_timer, system_shutdown}; + +#[no_mangle] +pub fn platform_init(hart_id: usize, dtb: usize) { + println!("{}", ::config::FLAG); + #[cfg(feature = "hifive")] + hifive_riscv::init_dtb(Some(dtb)); + #[cfg(feature = "vf2")] + starfive2_riscv::init_dtb(Some(dtb)); + #[cfg(feature = "qemu_riscv")] + qemu_riscv::init_dtb(Some(dtb)); + let machine_info = basic::machine_info_from_dtb(platform_dtb_ptr()); + MACHINE_INFO.call_once(|| machine_info); + logging::init_logger(); + preprint::init_print(&PrePrint); + #[cfg(feature = "smp")] + init_other_hart(hart_id); + unsafe { main(hart_id) } +} + +/// 唤醒其它核 +/// +/// 对于qemu来说,只需要工具所有的核都是一样的,因此从严号核开始唤醒。 +/// 对于visionfive2/unmatched 来说,0号核只有M态,因此不进行唤醒 +fn init_other_hart(hart_id: usize) { + let start_hart = if cfg!(any(feature = "vf2", feature = "hifive")) { + 1 + } else { + 0 + }; + for i in start_hart..CPU_NUM { + if i != hart_id { + let res = hart_start(i, _start_secondary as usize, 0); + assert_eq!(res.error, 0); + } + } +} + +extern "C" { + fn main(hart_id: usize); + fn _start_secondary(); +} + +pub fn platform_dtb_ptr() -> usize { + #[cfg(feature = "hifive")] + return *hifive_riscv::DTB.get().unwrap(); + #[cfg(feature = "vf2")] + return *starfive2_riscv::DTB.get().unwrap(); + #[cfg(feature = "qemu_riscv")] + return *qemu_riscv::DTB.get().unwrap(); +} + +static MACHINE_INFO: Once = Once::new(); + +pub fn platform_machine_info() -> PlatformInfo { + MACHINE_INFO.get().unwrap().clone() +} diff --git a/kernel/src/print/logging.rs b/subsystems/platform/src/logging.rs similarity index 100% rename from kernel/src/print/logging.rs rename to subsystems/platform/src/logging.rs diff --git a/subsystems/platform/src/qemu_riscv/config.rs b/subsystems/platform/src/qemu_riscv/config.rs new file mode 100644 index 00000000..79406337 --- /dev/null +++ b/subsystems/platform/src/qemu_riscv/config.rs @@ -0,0 +1,12 @@ +pub const CLOCK_FREQ: usize = 1250_0000; +pub const BLOCK_CACHE_FRAMES: usize = 1024 * 4 * 4; +pub const HEAP_SIZE: usize = 0x26_00000; // (32+6)MB + +/// qemu的设备地址空间 +pub const MMIO: &[(usize, usize)] = &[ + (0x0010_0000, 0x00_2000), // VIRT_TEST/RTC in virt machine + (0x2000000, 0x10000), + (0xc00_0000, 0x21_0000), // VIRT_PLIC in virt machine + (0x1000_0000, 0x9000), // VIRT_UART0 with GPU in virt machine + (0x3000_0000, 0x1000_0000), +]; diff --git a/subsystems/platform/src/qemu_riscv/mod.rs b/subsystems/platform/src/qemu_riscv/mod.rs new file mode 100644 index 00000000..3777ff4b --- /dev/null +++ b/subsystems/platform/src/qemu_riscv/mod.rs @@ -0,0 +1,30 @@ +pub mod config; + +use spin::Once; + +pub static DTB: Once = Once::new(); + +pub fn init_dtb(dtb: Option) { + let dtb_ptr = dtb.expect("No dtb found"); + DTB.call_once(|| dtb_ptr); +} + +/// 设置定时器 +pub fn set_timer(time: usize) { + crate::common_riscv::sbi::set_timer(time); +} + +pub fn system_shutdown() -> ! { + crate::common_riscv::sbi::system_shutdown(); +} + +/// Warp sbi SBI_CONSOLE_PUT_CHAR call +pub fn console_putchar(ch: u8) { + crate::common_riscv::sbi::console_putchar(ch); +} + +/// Warp sbi SBI_CONSOLE_GET_CHAR call +#[allow(unused)] +pub fn console_getchar() -> char { + crate::common_riscv::sbi::console_getchar() +} diff --git a/subsystems/platform/src/starfive2_riscv/config.rs b/subsystems/platform/src/starfive2_riscv/config.rs new file mode 100644 index 00000000..f4422f16 --- /dev/null +++ b/subsystems/platform/src/starfive2_riscv/config.rs @@ -0,0 +1,11 @@ +pub const CLOCK_FREQ: usize = 400_0000; +pub const BLOCK_CACHE_FRAMES: usize = 1024 * 4 * 4; +pub const HEAP_SIZE: usize = 0x40_00000; + +/// vf2的设备地址空间 + +pub const MMIO: &[(usize, usize)] = &[ + (0x17040000, 0x10000), // RTC + (0xc000000, 0x4000000), //PLIC + (0x00_1000_0000, 0x10000), // UART +]; diff --git a/subsystems/platform/src/starfive2_riscv/mod.rs b/subsystems/platform/src/starfive2_riscv/mod.rs new file mode 100644 index 00000000..46005a3f --- /dev/null +++ b/subsystems/platform/src/starfive2_riscv/mod.rs @@ -0,0 +1,32 @@ +pub mod config; + +use spin::Once; + +pub const FDT: &[u8] = include_bytes!("../../../../tools/jh7110-visionfive-v2.dtb"); + +pub static DTB: Once = Once::new(); + +pub fn init_dtb(dtb: Option) { + let dtb_ptr = dtb.unwrap_or(FDT.as_ptr() as usize); + DTB.call_once(|| dtb_ptr); +} + +/// 设置定时器 +pub fn set_timer(time: usize) { + crate::common_riscv::sbi::set_timer(time); +} + +pub fn system_shutdown() -> ! { + crate::common_riscv::sbi::system_shutdown(); +} + +/// Warp sbi SBI_CONSOLE_PUT_CHAR call +pub fn console_putchar(ch: u8) { + crate::common_riscv::sbi::console_putchar(ch); +} + +/// Warp sbi SBI_CONSOLE_GET_CHAR call +#[allow(unused)] +pub fn console_getchar() -> char { + crate::common_riscv::sbi::console_getchar() +} diff --git a/subsystems/timer/Cargo.toml b/subsystems/timer/Cargo.toml new file mode 100644 index 00000000..c220d29b --- /dev/null +++ b/subsystems/timer/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "timer" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +arch = { path = "../arch" } +config = { path = "../config" } +platform = { path = "../platform" } +constants = { path = "../constants" } +vfscore = { git = "https://github.com/os-module/rvfs.git", features = [ + "linux_error", +] } \ No newline at end of file diff --git a/subsystems/timer/src/lib.rs b/subsystems/timer/src/lib.rs new file mode 100644 index 00000000..888e0927 --- /dev/null +++ b/subsystems/timer/src/lib.rs @@ -0,0 +1,129 @@ +#![no_std] + +use constants::sys::TimeVal; +use platform::config::CLOCK_FREQ; +use vfscore::utils::VfsTimeSpec; +/// 每秒包含的毫秒数 +const MSEC_PER_SEC: usize = 1000; +/// 程序运行时间 +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Times { + /// the ticks of user mode + pub tms_utime: usize, + /// the ticks of kernel mode + pub tms_stime: usize, + /// the ticks of user mode of child process + pub tms_cutime: usize, + /// the ticks of kernel mode of child process + pub tms_cstime: usize, +} + +impl Times { + pub fn new() -> Self { + Self { + tms_utime: 0, + tms_stime: 0, + tms_cutime: 0, + tms_cstime: 0, + } + } +} + +/// 实现 `TimeNow` 特征的时钟结构,能够通过调用 `now` 方法得出 表示当前的 cpu 时间的一个本类型时钟 +pub trait TimeNow { + fn now() -> Self; +} + +/// 实现 `ToClock` 特征的时钟结构,能够将所表示的时间间隔,转换为 cpu 时钟 +pub trait ToClock { + fn to_clock(&self) -> usize; +} + +/// 实现 `TimeFromFreq` 特征的时钟结构,能够实现从 cpu时钟跳变的次数 初始化一个本类型的时钟 +pub trait TimeFromFreq { + fn from_freq(freq: usize) -> Self; +} + +impl TimeNow for TimeVal { + fn now() -> Self { + let time = read_timer(); + Self { + tv_sec: time / CLOCK_FREQ, + tv_usec: (time % CLOCK_FREQ) * 1000000 / CLOCK_FREQ, + } + } +} +impl ToClock for TimeVal { + fn to_clock(&self) -> usize { + self.tv_sec * CLOCK_FREQ + self.tv_usec * CLOCK_FREQ / 1000_000 + } +} + +impl TimeFromFreq for TimeVal { + fn from_freq(freq: usize) -> Self { + Self { + tv_sec: freq / CLOCK_FREQ, + tv_usec: (freq % CLOCK_FREQ) * 1000000 / CLOCK_FREQ, + } + } +} + +/// 更精细的时间,秒(s)+纳秒(ns) +#[repr(C)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct TimeSpec { + pub tv_sec: usize, + pub tv_nsec: usize, //0~999999999 +} + +impl TimeSpec { + /// 创建一个新的 [`TimeSpec`] 时钟 + pub fn new(sec: usize, ns: usize) -> Self { + Self { + tv_sec: sec, + tv_nsec: ns, + } + } + + /// 获取一个可以表示当前 cpu 时间的一个 [`TimeSpec`] 时钟 + pub fn now() -> Self { + let time = arch::read_timer(); + Self { + tv_sec: time / CLOCK_FREQ, + tv_nsec: (time % CLOCK_FREQ) * 1000000000 / CLOCK_FREQ, + } + } + + /// 将本时钟所表示的时间间隔转化为 cpu 上时钟的跳变数 + pub fn to_clock(&self) -> usize { + self.tv_sec * CLOCK_FREQ + self.tv_nsec * CLOCK_FREQ / 1000_000_000 + } +} + +impl Into for TimeSpec { + fn into(self) -> VfsTimeSpec { + VfsTimeSpec::new(self.tv_sec as u64, self.tv_nsec as u64) + } +} + +/// [`getitimer`] / [`setitimer`] 指定的类型,用户执行系统调用时获取和输入的计时器 +#[repr(C)] +#[derive(Debug, Copy, Clone, Default)] +pub struct ITimerVal { + /// 计时器超时间隔 + pub it_interval: TimeVal, + /// 计时器当前所剩时间 + pub it_value: TimeVal, +} + +/// 获取当前计时器的值 +#[inline] +pub fn read_timer() -> usize { + arch::read_timer() +} + +/// 获取当前时间,以 ms 为单位 +pub fn get_time_ms() -> isize { + (read_timer() / (CLOCK_FREQ / MSEC_PER_SEC)) as isize +} diff --git a/subsystems/unwinder/Cargo.toml b/subsystems/unwinder/Cargo.toml new file mode 100644 index 00000000..cc6f21ec --- /dev/null +++ b/subsystems/unwinder/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "unwinder" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +tracer = { git = "https://github.com/os-module/tracer" } +platform = { path = "../platform" } +arch = { path = "../arch" } + +[features] +debug-eh-frame = [] +debug-frame-pointer = [] \ No newline at end of file diff --git a/subsystems/unwinder/build.rs b/subsystems/unwinder/build.rs new file mode 100644 index 00000000..071afa14 --- /dev/null +++ b/subsystems/unwinder/build.rs @@ -0,0 +1,22 @@ +use std::fs::File; +use std::io::Write; +use std::path::Path; + +fn main() { + println!("cargo:rerun-if-changed={}", "src/"); + let path = Path::new("src/kernel_symbol.S"); + if !path.exists() { + let mut file = File::create(path).unwrap(); + write!(file, ".section .rodata\n").unwrap(); + write!(file, ".align 3\n").unwrap(); + write!(file, ".global symbol_num\n").unwrap(); + write!(file, ".global symbol_address\n").unwrap(); + write!(file, ".global symbol_index\n").unwrap(); + write!(file, ".global symbol_name\n").unwrap(); + write!(file, "symbol_num:\n").unwrap(); + write!(file, ".quad {}\n", 0).unwrap(); + write!(file, "symbol_address:\n").unwrap(); + write!(file, "symbol_index:\n").unwrap(); + write!(file, "symbol_name:\n").unwrap(); + } +} diff --git a/subsystems/unwinder/src/kernel_symbol.S b/subsystems/unwinder/src/kernel_symbol.S new file mode 100644 index 00000000..abee068b --- /dev/null +++ b/subsystems/unwinder/src/kernel_symbol.S @@ -0,0 +1,10796 @@ +.align 3 +.section .rodata +.globl symbol_num +symbol_num: + .quad 3595 +.globl symbol_address +symbol_address: + .quad 2149580800 + .quad 2149580800 + .quad 2149584896 + .quad 2149584896 + .quad 2149585004 + .quad 2149588992 + .quad 2149588992 + .quad 2149589008 + .quad 2149589024 + .quad 2149589040 + .quad 2149589056 + .quad 2149589072 + .quad 2149589088 + .quad 2149589104 + .quad 2149589120 + .quad 2149589136 + .quad 2149589152 + .quad 2149589168 + .quad 2149589184 + .quad 2149589200 + .quad 2149589216 + .quad 2149589232 + .quad 2149589248 + .quad 2149589264 + .quad 2149589280 + .quad 2149589296 + .quad 2149589312 + .quad 2149589328 + .quad 2149589344 + .quad 2149589360 + .quad 2149589376 + .quad 2149589392 + .quad 2149589408 + .quad 2149589424 + .quad 2149589440 + .quad 2149589456 + .quad 2149589472 + .quad 2149589488 + .quad 2149589504 + .quad 2149589520 + .quad 2149589536 + .quad 2149589552 + .quad 2149589568 + .quad 2149589584 + .quad 2149589600 + .quad 2149589616 + .quad 2149589632 + .quad 2149589648 + .quad 2149589664 + .quad 2149589680 + .quad 2149589696 + .quad 2149589712 + .quad 2149589728 + .quad 2149589744 + .quad 2149589760 + .quad 2149589776 + .quad 2149589792 + .quad 2149589808 + .quad 2149589824 + .quad 2149589840 + .quad 2149589856 + .quad 2149589872 + .quad 2149589888 + .quad 2149589904 + .quad 2149589920 + .quad 2149589936 + .quad 2149589952 + .quad 2149589968 + .quad 2149589984 + .quad 2149590000 + .quad 2149590016 + .quad 2149590032 + .quad 2149590048 + .quad 2149590064 + .quad 2149590080 + .quad 2149590096 + .quad 2149590112 + .quad 2149590128 + .quad 2149590144 + .quad 2149590160 + .quad 2149590176 + .quad 2149590192 + .quad 2149590208 + .quad 2149590224 + .quad 2149590240 + .quad 2149590256 + .quad 2149590272 + .quad 2149590288 + .quad 2149590304 + .quad 2149590320 + .quad 2149590336 + .quad 2149590352 + .quad 2149590368 + .quad 2149590384 + .quad 2149590400 + .quad 2149590416 + .quad 2149590432 + .quad 2149590448 + .quad 2149590464 + .quad 2149590480 + .quad 2149590496 + .quad 2149590512 + .quad 2149590528 + .quad 2149590544 + .quad 2149590560 + .quad 2149590576 + .quad 2149590592 + .quad 2149590608 + .quad 2149590624 + .quad 2149590640 + .quad 2149590656 + .quad 2149590672 + .quad 2149590688 + .quad 2149590704 + .quad 2149590720 + .quad 2149590736 + .quad 2149590752 + .quad 2149590768 + .quad 2149590784 + .quad 2149590800 + .quad 2149590816 + .quad 2149590832 + .quad 2149590848 + .quad 2149590864 + .quad 2149590880 + .quad 2149590896 + .quad 2149590912 + .quad 2149590928 + .quad 2149590944 + .quad 2149590960 + .quad 2149590976 + .quad 2149590992 + .quad 2149591008 + .quad 2149591024 + .quad 2149591040 + .quad 2149591056 + .quad 2149591072 + .quad 2149592718 + .quad 2149594566 + .quad 2149596592 + .quad 2149598310 + .quad 2149600028 + .quad 2149601656 + .quad 2149602124 + .quad 2149602602 + .quad 2149603130 + .quad 2149603586 + .quad 2149604114 + .quad 2149604618 + .quad 2149605182 + .quad 2149605694 + .quad 2149606204 + .quad 2149606698 + .quad 2149607238 + .quad 2149607758 + .quad 2149608208 + .quad 2149608642 + .quad 2149609114 + .quad 2149609542 + .quad 2149610186 + .quad 2149610866 + .quad 2149611554 + .quad 2149612204 + .quad 2149612418 + .quad 2149612618 + .quad 2149612860 + .quad 2149613050 + .quad 2149613050 + .quad 2149613256 + .quad 2149613462 + .quad 2149613664 + .quad 2149613682 + .quad 2149613692 + .quad 2149613702 + .quad 2149613712 + .quad 2149613722 + .quad 2149613762 + .quad 2149613792 + .quad 2149613794 + .quad 2149613794 + .quad 2149613796 + .quad 2149613856 + .quad 2149614094 + .quad 2149614740 + .quad 2149614822 + .quad 2149614920 + .quad 2149615010 + .quad 2149615234 + .quad 2149615568 + .quad 2149615948 + .quad 2149616130 + .quad 2149616338 + .quad 2149616552 + .quad 2149617024 + .quad 2149617024 + .quad 2149617024 + .quad 2149617404 + .quad 2149617784 + .quad 2149618164 + .quad 2149618544 + .quad 2149619810 + .quad 2149621222 + .quad 2149622156 + .quad 2149622450 + .quad 2149622712 + .quad 2149622920 + .quad 2149623752 + .quad 2149624304 + .quad 2149624304 + .quad 2149624606 + .quad 2149624908 + .quad 2149625210 + .quad 2149625512 + .quad 2149625814 + .quad 2149626116 + .quad 2149626574 + .quad 2149628658 + .quad 2149629106 + .quad 2149629446 + .quad 2149630828 + .quad 2149632854 + .quad 2149633318 + .quad 2149634416 + .quad 2149635054 + .quad 2149642810 + .quad 2149646754 + .quad 2149658048 + .quad 2149658130 + .quad 2149658210 + .quad 2149658382 + .quad 2149658426 + .quad 2149658518 + .quad 2149658606 + .quad 2149658816 + .quad 2149658922 + .quad 2149659200 + .quad 2149659220 + .quad 2149659332 + .quad 2149659440 + .quad 2149659628 + .quad 2149660074 + .quad 2149660082 + .quad 2149660194 + .quad 2149660194 + .quad 2149660194 + .quad 2149660194 + .quad 2149660194 + .quad 2149660194 + .quad 2149660194 + .quad 2149660194 + .quad 2149660194 + .quad 2149660194 + .quad 2149660194 + .quad 2149660194 + .quad 2149660194 + .quad 2149660198 + .quad 2149660306 + .quad 2149660574 + .quad 2149660998 + .quad 2149661110 + .quad 2149661362 + .quad 2149661474 + .quad 2149661898 + .quad 2149661986 + .quad 2149662140 + .quad 2149662246 + .quad 2149662542 + .quad 2149662774 + .quad 2149662952 + .quad 2149663146 + .quad 2149663258 + .quad 2149663366 + .quad 2149663526 + .quad 2149663714 + .quad 2149663862 + .quad 2149664026 + .quad 2149664114 + .quad 2149664350 + .quad 2149664442 + .quad 2149664550 + .quad 2149664682 + .quad 2149664758 + .quad 2149665070 + .quad 2149665400 + .quad 2149665760 + .quad 2149665868 + .quad 2149665982 + .quad 2149666232 + .quad 2149666338 + .quad 2149666492 + .quad 2149666912 + .quad 2149666920 + .quad 2149667032 + .quad 2149667144 + .quad 2149667388 + .quad 2149667692 + .quad 2149667802 + .quad 2149667908 + .quad 2149668072 + .quad 2149668180 + .quad 2149668188 + .quad 2149668608 + .quad 2149668792 + .quad 2149668912 + .quad 2149669144 + .quad 2149669370 + .quad 2149669476 + .quad 2149669640 + .quad 2149669660 + .quad 2149669974 + .quad 2149669974 + .quad 2149670070 + .quad 2149670264 + .quad 2149670380 + .quad 2149670456 + .quad 2149670562 + .quad 2149670670 + .quad 2149670782 + .quad 2149670930 + .quad 2149671162 + .quad 2149671300 + .quad 2149671600 + .quad 2149671708 + .quad 2149671708 + .quad 2149671798 + .quad 2149671906 + .quad 2149672018 + .quad 2149672336 + .quad 2149672496 + .quad 2149672604 + .quad 2149672716 + .quad 2149672826 + .quad 2149672932 + .quad 2149673352 + .quad 2149673472 + .quad 2149673580 + .quad 2149673694 + .quad 2149673926 + .quad 2149673926 + .quad 2149674106 + .quad 2149674364 + .quad 2149674452 + .quad 2149674708 + .quad 2149674814 + .quad 2149675046 + .quad 2149675154 + .quad 2149675282 + .quad 2149675446 + .quad 2149675528 + .quad 2149675536 + .quad 2149675768 + .quad 2149675922 + .quad 2149675930 + .quad 2149676036 + .quad 2149676144 + .quad 2149676250 + .quad 2149676410 + .quad 2149676518 + .quad 2149676610 + .quad 2149676798 + .quad 2149677186 + .quad 2149677202 + .quad 2149677286 + .quad 2149677392 + .quad 2149677494 + .quad 2149677594 + .quad 2149677772 + .quad 2149677930 + .quad 2149677952 + .quad 2149678102 + .quad 2149678124 + .quad 2149678140 + .quad 2149678164 + .quad 2149678284 + .quad 2149678306 + .quad 2149678328 + .quad 2149678510 + .quad 2149678532 + .quad 2149678810 + .quad 2149678910 + .quad 2149678910 + .quad 2149679000 + .quad 2149679022 + .quad 2149679124 + .quad 2149679146 + .quad 2149679146 + .quad 2149679146 + .quad 2149679146 + .quad 2149679146 + .quad 2149679146 + .quad 2149679146 + .quad 2149679146 + .quad 2149679146 + .quad 2149679146 + .quad 2149679146 + .quad 2149679146 + .quad 2149679146 + .quad 2149679150 + .quad 2149679272 + .quad 2149679428 + .quad 2149679514 + .quad 2149679614 + .quad 2149679720 + .quad 2149679822 + .quad 2149679980 + .quad 2149680084 + .quad 2149680186 + .quad 2149680208 + .quad 2149680230 + .quad 2149680252 + .quad 2149680252 + .quad 2149680450 + .quad 2149680472 + .quad 2149680494 + .quad 2149680594 + .quad 2149680696 + .quad 2149680878 + .quad 2149680986 + .quad 2149681008 + .quad 2149681030 + .quad 2149681158 + .quad 2149681234 + .quad 2149681460 + .quad 2149681608 + .quad 2149681616 + .quad 2149681700 + .quad 2149681722 + .quad 2149681828 + .quad 2149682008 + .quad 2149682166 + .quad 2149682268 + .quad 2149682374 + .quad 2149682476 + .quad 2149682558 + .quad 2149682714 + .quad 2149682896 + .quad 2149682996 + .quad 2149683098 + .quad 2149683204 + .quad 2149683314 + .quad 2149683614 + .quad 2149683636 + .quad 2149683722 + .quad 2149683744 + .quad 2149683820 + .quad 2149683958 + .quad 2149684060 + .quad 2149684082 + .quad 2149684104 + .quad 2149684210 + .quad 2149684312 + .quad 2149684542 + .quad 2149684626 + .quad 2149684726 + .quad 2149684748 + .quad 2149684770 + .quad 2149684902 + .quad 2149684922 + .quad 2149685008 + .quad 2149685120 + .quad 2149685238 + .quad 2149685254 + .quad 2149685276 + .quad 2149685378 + .quad 2149685536 + .quad 2149685684 + .quad 2149685786 + .quad 2149685808 + .quad 2149685830 + .quad 2149685852 + .quad 2149685972 + .quad 2149686128 + .quad 2149686128 + .quad 2149686224 + .quad 2149686330 + .quad 2149686430 + .quad 2149686530 + .quad 2149686636 + .quad 2149686658 + .quad 2149686742 + .quad 2149686846 + .quad 2149686968 + .quad 2149687070 + .quad 2149687092 + .quad 2149687210 + .quad 2149687312 + .quad 2149687334 + .quad 2149687592 + .quad 2149687896 + .quad 2149687918 + .quad 2149688048 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688154 + .quad 2149688156 + .quad 2149688174 + .quad 2149688194 + .quad 2149688404 + .quad 2149688604 + .quad 2149688898 + .quad 2149689192 + .quad 2149689464 + .quad 2149689736 + .quad 2149690094 + .quad 2149690438 + .quad 2149690678 + .quad 2149690686 + .quad 2149690696 + .quad 2149690706 + .quad 2149690716 + .quad 2149690726 + .quad 2149690748 + .quad 2149690788 + .quad 2149690828 + .quad 2149690830 + .quad 2149690890 + .quad 2149690910 + .quad 2149690930 + .quad 2149691524 + .quad 2149692540 + .quad 2149692908 + .quad 2149693458 + .quad 2149694326 + .quad 2149694894 + .quad 2149695058 + .quad 2149695342 + .quad 2149695908 + .quad 2149696514 + .quad 2149696808 + .quad 2149697054 + .quad 2149697572 + .quad 2149698240 + .quad 2149698960 + .quad 2149699480 + .quad 2149699886 + .quad 2149700200 + .quad 2149700966 + .quad 2149701730 + .quad 2149702802 + .quad 2149703604 + .quad 2149703918 + .quad 2149704788 + .quad 2149706380 + .quad 2149707352 + .quad 2149707542 + .quad 2149707584 + .quad 2149707626 + .quad 2149707668 + .quad 2149707688 + .quad 2149707698 + .quad 2149707698 + .quad 2149707708 + .quad 2149707718 + .quad 2149707728 + .quad 2149707748 + .quad 2149707758 + .quad 2149707798 + .quad 2149707934 + .quad 2149707936 + .quad 2149707936 + .quad 2149707946 + .quad 2149708426 + .quad 2149709080 + .quad 2149709362 + .quad 2149709696 + .quad 2149710158 + .quad 2149710966 + .quad 2149711402 + .quad 2149711972 + .quad 2149713026 + .quad 2149714556 + .quad 2149716050 + .quad 2149717142 + .quad 2149718758 + .quad 2149719308 + .quad 2149719312 + .quad 2149719316 + .quad 2149719490 + .quad 2149719756 + .quad 2149720208 + .quad 2149722306 + .quad 2149722324 + .quad 2149722324 + .quad 2149722324 + .quad 2149722328 + .quad 2149722330 + .quad 2149722342 + .quad 2149722354 + .quad 2149722366 + .quad 2149722372 + .quad 2149722384 + .quad 2149722394 + .quad 2149722394 + .quad 2149722404 + .quad 2149722414 + .quad 2149722424 + .quad 2149722464 + .quad 2149722504 + .quad 2149722544 + .quad 2149722562 + .quad 2149722564 + .quad 2149722566 + .quad 2149722566 + .quad 2149722568 + .quad 2149722666 + .quad 2149722686 + .quad 2149722890 + .quad 2149723334 + .quad 2149723528 + .quad 2149723730 + .quad 2149724104 + .quad 2149724338 + .quad 2149724870 + .quad 2149725254 + .quad 2149725480 + .quad 2149726528 + .quad 2149727008 + .quad 2149729442 + .quad 2149729528 + .quad 2149729610 + .quad 2149729690 + .quad 2149729918 + .quad 2149730152 + .quad 2149730162 + .quad 2149730174 + .quad 2149730178 + .quad 2149732340 + .quad 2149732380 + .quad 2149732382 + .quad 2149732384 + .quad 2149732386 + .quad 2149732640 + .quad 2149732640 + .quad 2149732894 + .quad 2149732894 + .quad 2149733126 + .quad 2149733370 + .quad 2149733632 + .quad 2149734134 + .quad 2149735794 + .quad 2149741068 + .quad 2149741696 + .quad 2149741782 + .quad 2149742174 + .quad 2149742972 + .quad 2149744052 + .quad 2149744396 + .quad 2149745206 + .quad 2149745606 + .quad 2149745840 + .quad 2149745858 + .quad 2149745868 + .quad 2149745878 + .quad 2149745888 + .quad 2149745898 + .quad 2149745908 + .quad 2149745918 + .quad 2149745928 + .quad 2149745938 + .quad 2149746086 + .quad 2149746184 + .quad 2149746186 + .quad 2149746188 + .quad 2149746542 + .quad 2149746712 + .quad 2149746888 + .quad 2149747068 + .quad 2149747236 + .quad 2149748154 + .quad 2149748498 + .quad 2149748566 + .quad 2149748634 + .quad 2149748706 + .quad 2149748774 + .quad 2149748846 + .quad 2149748914 + .quad 2149748986 + .quad 2149748994 + .quad 2149748998 + .quad 2149749010 + .quad 2149749022 + .quad 2149749038 + .quad 2149749050 + .quad 2149749068 + .quad 2149749072 + .quad 2149749086 + .quad 2149749180 + .quad 2149749252 + .quad 2149749306 + .quad 2149749312 + .quad 2149749326 + .quad 2149749344 + .quad 2149749358 + .quad 2149749568 + .quad 2149749580 + .quad 2149749584 + .quad 2149749588 + .quad 2149749638 + .quad 2149749684 + .quad 2149749688 + .quad 2149749702 + .quad 2149749714 + .quad 2149749718 + .quad 2149749934 + .quad 2149750776 + .quad 2149751522 + .quad 2149751954 + .quad 2149752926 + .quad 2149753694 + .quad 2149753930 + .quad 2149754162 + .quad 2149754388 + .quad 2149754620 + .quad 2149754870 + .quad 2149755090 + .quad 2149755092 + .quad 2149755094 + .quad 2149755114 + .quad 2149755354 + .quad 2149755650 + .quad 2149755896 + .quad 2149756160 + .quad 2149756444 + .quad 2149756802 + .quad 2149756822 + .quad 2149757172 + .quad 2149757606 + .quad 2149757834 + .quad 2149758700 + .quad 2149759352 + .quad 2149759992 + .quad 2149760618 + .quad 2149760924 + .quad 2149761278 + .quad 2149761538 + .quad 2149761788 + .quad 2149762846 + .quad 2149764446 + .quad 2149765504 + .quad 2149766538 + .quad 2149766540 + .quad 2149766542 + .quad 2149767172 + .quad 2149767550 + .quad 2149767570 + .quad 2149768226 + .quad 2149769654 + .quad 2149770282 + .quad 2149773238 + .quad 2149774600 + .quad 2149775636 + .quad 2149775978 + .quad 2149775988 + .quad 2149775998 + .quad 2149776008 + .quad 2149776018 + .quad 2149776020 + .quad 2149776142 + .quad 2149776232 + .quad 2149776232 + .quad 2149776232 + .quad 2149776232 + .quad 2149776364 + .quad 2149776364 + .quad 2149776364 + .quad 2149776364 + .quad 2149776496 + .quad 2149776638 + .quad 2149776638 + .quad 2149776770 + .quad 2149776920 + .quad 2149777060 + .quad 2149777060 + .quad 2149777198 + .quad 2149777340 + .quad 2149777340 + .quad 2149777474 + .quad 2149777614 + .quad 2149777694 + .quad 2149777774 + .quad 2149777854 + .quad 2149777934 + .quad 2149778014 + .quad 2149778094 + .quad 2149778174 + .quad 2149778254 + .quad 2149778334 + .quad 2149778414 + .quad 2149778494 + .quad 2149778574 + .quad 2149778654 + .quad 2149778734 + .quad 2149778814 + .quad 2149778894 + .quad 2149778974 + .quad 2149779054 + .quad 2149779134 + .quad 2149779214 + .quad 2149779294 + .quad 2149779374 + .quad 2149779454 + .quad 2149779534 + .quad 2149779614 + .quad 2149779694 + .quad 2149779774 + .quad 2149779854 + .quad 2149779934 + .quad 2149780014 + .quad 2149780094 + .quad 2149780174 + .quad 2149780254 + .quad 2149780334 + .quad 2149780414 + .quad 2149780494 + .quad 2149780574 + .quad 2149780654 + .quad 2149780734 + .quad 2149780814 + .quad 2149780894 + .quad 2149780974 + .quad 2149781054 + .quad 2149781134 + .quad 2149781214 + .quad 2149781294 + .quad 2149781374 + .quad 2149781454 + .quad 2149781534 + .quad 2149781614 + .quad 2149781694 + .quad 2149781774 + .quad 2149781854 + .quad 2149781934 + .quad 2149782014 + .quad 2149782094 + .quad 2149782174 + .quad 2149782254 + .quad 2149782334 + .quad 2149782414 + .quad 2149782494 + .quad 2149782574 + .quad 2149782654 + .quad 2149782734 + .quad 2149782814 + .quad 2149782894 + .quad 2149782974 + .quad 2149783054 + .quad 2149783134 + .quad 2149783214 + .quad 2149783294 + .quad 2149783374 + .quad 2149783454 + .quad 2149783534 + .quad 2149783614 + .quad 2149783694 + .quad 2149783774 + .quad 2149783856 + .quad 2149784016 + .quad 2149784034 + .quad 2149784042 + .quad 2149784052 + .quad 2149784062 + .quad 2149784072 + .quad 2149784090 + .quad 2149784110 + .quad 2149784112 + .quad 2149784132 + .quad 2149784200 + .quad 2149784556 + .quad 2149784624 + .quad 2149784784 + .quad 2149785054 + .quad 2149787518 + .quad 2149788578 + .quad 2149790026 + .quad 2149790514 + .quad 2149790548 + .quad 2149790596 + .quad 2149790834 + .quad 2149790908 + .quad 2149790996 + .quad 2149791288 + .quad 2149791476 + .quad 2149791706 + .quad 2149792430 + .quad 2149792840 + .quad 2149793028 + .quad 2149793108 + .quad 2149794442 + .quad 2149794758 + .quad 2149794776 + .quad 2149794786 + .quad 2149794796 + .quad 2149794806 + .quad 2149794816 + .quad 2149794826 + .quad 2149794836 + .quad 2149794846 + .quad 2149794856 + .quad 2149794878 + .quad 2149795400 + .quad 2149795650 + .quad 2149796176 + .quad 2149796206 + .quad 2149796342 + .quad 2149796344 + .quad 2149796346 + .quad 2149796888 + .quad 2149796890 + .quad 2149796890 + .quad 2149796890 + .quad 2149796946 + .quad 2149797010 + .quad 2149797010 + .quad 2149797010 + .quad 2149797010 + .quad 2149797010 + .quad 2149797010 + .quad 2149797126 + .quad 2149797174 + .quad 2149797272 + .quad 2149797350 + .quad 2149797536 + .quad 2149797582 + .quad 2149797628 + .quad 2149797744 + .quad 2149797916 + .quad 2149798108 + .quad 2149798254 + .quad 2149798442 + .quad 2149798608 + .quad 2149798782 + .quad 2149798828 + .quad 2149798892 + .quad 2149798920 + .quad 2149798992 + .quad 2149799236 + .quad 2149799322 + .quad 2149799408 + .quad 2149799494 + .quad 2149799576 + .quad 2149799662 + .quad 2149799748 + .quad 2149799836 + .quad 2149799908 + .quad 2149799962 + .quad 2149800322 + .quad 2149800406 + .quad 2149800452 + .quad 2149800456 + .quad 2149800460 + .quad 2149800514 + .quad 2149802098 + .quad 2149802288 + .quad 2149802878 + .quad 2149802952 + .quad 2149803412 + .quad 2149803420 + .quad 2149803562 + .quad 2149803648 + .quad 2149803870 + .quad 2149803950 + .quad 2149804030 + .quad 2149804110 + .quad 2149804190 + .quad 2149804270 + .quad 2149804350 + .quad 2149804430 + .quad 2149804510 + .quad 2149804590 + .quad 2149804670 + .quad 2149804750 + .quad 2149804830 + .quad 2149804910 + .quad 2149804990 + .quad 2149805070 + .quad 2149805150 + .quad 2149805230 + .quad 2149805310 + .quad 2149805390 + .quad 2149805470 + .quad 2149805550 + .quad 2149805630 + .quad 2149805710 + .quad 2149805790 + .quad 2149805870 + .quad 2149805950 + .quad 2149806030 + .quad 2149806110 + .quad 2149806190 + .quad 2149806270 + .quad 2149806536 + .quad 2149806546 + .quad 2149806546 + .quad 2149806546 + .quad 2149806548 + .quad 2149806582 + .quad 2149806616 + .quad 2149806650 + .quad 2149806684 + .quad 2149806778 + .quad 2149807048 + .quad 2149807048 + .quad 2149807332 + .quad 2149807418 + .quad 2149807510 + .quad 2149807598 + .quad 2149807842 + .quad 2149808304 + .quad 2149808662 + .quad 2149808846 + .quad 2149809370 + .quad 2149809800 + .quad 2149810046 + .quad 2149810350 + .quad 2149810440 + .quad 2149810582 + .quad 2149810886 + .quad 2149810992 + .quad 2149811330 + .quad 2149811668 + .quad 2149811686 + .quad 2149811704 + .quad 2149811722 + .quad 2149811732 + .quad 2149811752 + .quad 2149811762 + .quad 2149811772 + .quad 2149811782 + .quad 2149811792 + .quad 2149811832 + .quad 2149811854 + .quad 2149811884 + .quad 2149811886 + .quad 2149811888 + .quad 2149811906 + .quad 2149811908 + .quad 2149812036 + .quad 2149812056 + .quad 2149812318 + .quad 2149812400 + .quad 2149812470 + .quad 2149812880 + .quad 2149813454 + .quad 2149813454 + .quad 2149813570 + .quad 2149814180 + .quad 2149814328 + .quad 2149814530 + .quad 2149814530 + .quad 2149814656 + .quad 2149814918 + .quad 2149815080 + .quad 2149815452 + .quad 2149815456 + .quad 2149815468 + .quad 2149815484 + .quad 2149816178 + .quad 2149816692 + .quad 2149816846 + .quad 2149818184 + .quad 2149818366 + .quad 2149818548 + .quad 2149818570 + .quad 2149818658 + .quad 2149818746 + .quad 2149818836 + .quad 2149819002 + .quad 2149820148 + .quad 2149821242 + .quad 2149821620 + .quad 2149821634 + .quad 2149821638 + .quad 2149821650 + .quad 2149821656 + .quad 2149821668 + .quad 2149821682 + .quad 2149821686 + .quad 2149821692 + .quad 2149822588 + .quad 2149823068 + .quad 2149823732 + .quad 2149823746 + .quad 2149823800 + .quad 2149823814 + .quad 2149823828 + .quad 2149823834 + .quad 2149823840 + .quad 2149823886 + .quad 2149823890 + .quad 2149823902 + .quad 2149823914 + .quad 2149823926 + .quad 2149823932 + .quad 2149823944 + .quad 2149823954 + .quad 2149823964 + .quad 2149823974 + .quad 2149823984 + .quad 2149823994 + .quad 2149824004 + .quad 2149824014 + .quad 2149824054 + .quad 2149824084 + .quad 2149824210 + .quad 2149824212 + .quad 2149824222 + .quad 2149824226 + .quad 2149824236 + .quad 2149824248 + .quad 2149824252 + .quad 2149824552 + .quad 2149824828 + .quad 2149825796 + .quad 2149826436 + .quad 2149827278 + .quad 2149828120 + .quad 2149828618 + .quad 2149829224 + .quad 2149829442 + .quad 2149830498 + .quad 2149830986 + .quad 2149831694 + .quad 2149832830 + .quad 2149833148 + .quad 2149834794 + .quad 2149835704 + .quad 2149835784 + .quad 2149835864 + .quad 2149835944 + .quad 2149836024 + .quad 2149836104 + .quad 2149836184 + .quad 2149836264 + .quad 2149836344 + .quad 2149836424 + .quad 2149836504 + .quad 2149836584 + .quad 2149836664 + .quad 2149836744 + .quad 2149836824 + .quad 2149836904 + .quad 2149836984 + .quad 2149837064 + .quad 2149837144 + .quad 2149837224 + .quad 2149837304 + .quad 2149837384 + .quad 2149837392 + .quad 2149837402 + .quad 2149837442 + .quad 2149837568 + .quad 2149837568 + .quad 2149837568 + .quad 2149837568 + .quad 2149837570 + .quad 2149837674 + .quad 2149837752 + .quad 2149837834 + .quad 2149838210 + .quad 2149838568 + .quad 2149838644 + .quad 2149838722 + .quad 2149838772 + .quad 2149838822 + .quad 2149839068 + .quad 2149839212 + .quad 2149839800 + .quad 2149839878 + .quad 2149840420 + .quad 2149840670 + .quad 2149840722 + .quad 2149841276 + .quad 2149841632 + .quad 2149841912 + .quad 2149842032 + .quad 2149842210 + .quad 2149842418 + .quad 2149842710 + .quad 2149842720 + .quad 2149842730 + .quad 2149842750 + .quad 2149842760 + .quad 2149842802 + .quad 2149842812 + .quad 2149842814 + .quad 2149842930 + .quad 2149843002 + .quad 2149843080 + .quad 2149843324 + .quad 2149843690 + .quad 2149843792 + .quad 2149843870 + .quad 2149843890 + .quad 2149843932 + .quad 2149843932 + .quad 2149843932 + .quad 2149843932 + .quad 2149843932 + .quad 2149843932 + .quad 2149843934 + .quad 2149843968 + .quad 2149844216 + .quad 2149844396 + .quad 2149844734 + .quad 2149844970 + .quad 2149844980 + .quad 2149844982 + .quad 2149845380 + .quad 2149847420 + .quad 2149847640 + .quad 2149848128 + .quad 2149848548 + .quad 2149848634 + .quad 2149848898 + .quad 2149848936 + .quad 2149849442 + .quad 2149849616 + .quad 2149850122 + .quad 2149850284 + .quad 2149850308 + .quad 2149850310 + .quad 2149850490 + .quad 2149850508 + .quad 2149850526 + .quad 2149850536 + .quad 2149850546 + .quad 2149850556 + .quad 2149850566 + .quad 2149850576 + .quad 2149850586 + .quad 2149850596 + .quad 2149850606 + .quad 2149850616 + .quad 2149850626 + .quad 2149850636 + .quad 2149850646 + .quad 2149850656 + .quad 2149850666 + .quad 2149850676 + .quad 2149850686 + .quad 2149850696 + .quad 2149850706 + .quad 2149850716 + .quad 2149850726 + .quad 2149850736 + .quad 2149850746 + .quad 2149850756 + .quad 2149850766 + .quad 2149850776 + .quad 2149850786 + .quad 2149850796 + .quad 2149850806 + .quad 2149850816 + .quad 2149850826 + .quad 2149850836 + .quad 2149850846 + .quad 2149850856 + .quad 2149850866 + .quad 2149850876 + .quad 2149850886 + .quad 2149850896 + .quad 2149850906 + .quad 2149850916 + .quad 2149850926 + .quad 2149850944 + .quad 2149850962 + .quad 2149851098 + .quad 2149851134 + .quad 2149851282 + .quad 2149851312 + .quad 2149851342 + .quad 2149851344 + .quad 2149851374 + .quad 2149851404 + .quad 2149851406 + .quad 2149851436 + .quad 2149851438 + .quad 2149851700 + .quad 2149851782 + .quad 2149851816 + .quad 2149851850 + .quad 2149851862 + .quad 2149851866 + .quad 2149851870 + .quad 2149851932 + .quad 2149851936 + .quad 2149851950 + .quad 2149851954 + .quad 2149851958 + .quad 2149851970 + .quad 2149851974 + .quad 2149851988 + .quad 2149852050 + .quad 2149852054 + .quad 2149852116 + .quad 2149852980 + .quad 2149852984 + .quad 2149852992 + .quad 2149853000 + .quad 2149853008 + .quad 2149853016 + .quad 2149853024 + .quad 2149853028 + .quad 2149853040 + .quad 2149853052 + .quad 2149853064 + .quad 2149853076 + .quad 2149853092 + .quad 2149853108 + .quad 2149853124 + .quad 2149853136 + .quad 2149853150 + .quad 2149853164 + .quad 2149853178 + .quad 2149853184 + .quad 2149853190 + .quad 2149853196 + .quad 2149853202 + .quad 2149853208 + .quad 2149853214 + .quad 2149853228 + .quad 2149853242 + .quad 2149853256 + .quad 2149853270 + .quad 2149853284 + .quad 2149853298 + .quad 2149853312 + .quad 2149853326 + .quad 2149853340 + .quad 2149853352 + .quad 2149853364 + .quad 2149853376 + .quad 2149853382 + .quad 2149853388 + .quad 2149853394 + .quad 2149853398 + .quad 2149853402 + .quad 2149853728 + .quad 2149854042 + .quad 2149854356 + .quad 2149854700 + .quad 2149855052 + .quad 2149855404 + .quad 2149855600 + .quad 2149855672 + .quad 2149855726 + .quad 2149855972 + .quad 2149856000 + .quad 2149856084 + .quad 2149856130 + .quad 2149856134 + .quad 2149856146 + .quad 2149856150 + .quad 2149856154 + .quad 2149856162 + .quad 2149856176 + .quad 2149856180 + .quad 2149856184 + .quad 2149856246 + .quad 2149856250 + .quad 2149856520 + .quad 2149856860 + .quad 2149860892 + .quad 2149861148 + .quad 2149861348 + .quad 2149861412 + .quad 2149861614 + .quad 2149861614 + .quad 2149861614 + .quad 2149861614 + .quad 2149861614 + .quad 2149861614 + .quad 2149861614 + .quad 2149861614 + .quad 2149861614 + .quad 2149861730 + .quad 2149861730 + .quad 2149861868 + .quad 2149861868 + .quad 2149861912 + .quad 2149862084 + .quad 2149862248 + .quad 2149862248 + .quad 2149862440 + .quad 2149862628 + .quad 2149862674 + .quad 2149862784 + .quad 2149862988 + .quad 2149862988 + .quad 2149863088 + .quad 2149863410 + .quad 2149863590 + .quad 2149863882 + .quad 2149863982 + .quad 2149864184 + .quad 2149864354 + .quad 2149864432 + .quad 2149864530 + .quad 2149864594 + .quad 2149864622 + .quad 2149864622 + .quad 2149864854 + .quad 2149865074 + .quad 2149865092 + .quad 2149865102 + .quad 2149865112 + .quad 2149865122 + .quad 2149865132 + .quad 2149865142 + .quad 2149865152 + .quad 2149865162 + .quad 2149865172 + .quad 2149865182 + .quad 2149865192 + .quad 2149865202 + .quad 2149865212 + .quad 2149865242 + .quad 2149865244 + .quad 2149865246 + .quad 2149865246 + .quad 2149865246 + .quad 2149865434 + .quad 2149865864 + .quad 2149866128 + .quad 2149866368 + .quad 2149866798 + .quad 2149867102 + .quad 2149867532 + .quad 2149867940 + .quad 2149868188 + .quad 2149868428 + .quad 2149868754 + .quad 2149869084 + .quad 2149869270 + .quad 2149869278 + .quad 2149869282 + .quad 2149869294 + .quad 2149869310 + .quad 2149869322 + .quad 2149869336 + .quad 2149869342 + .quad 2149869396 + .quad 2149869402 + .quad 2149869416 + .quad 2149869430 + .quad 2149869444 + .quad 2149869456 + .quad 2149869462 + .quad 2149869508 + .quad 2149869844 + .quad 2149870198 + .quad 2149870504 + .quad 2149870814 + .quad 2149871176 + .quad 2149871530 + .quad 2149871558 + .quad 2149871568 + .quad 2149871582 + .quad 2149871586 + .quad 2149871590 + .quad 2149871654 + .quad 2149871658 + .quad 2149871722 + .quad 2149872970 + .quad 2149874750 + .quad 2149874750 + .quad 2149874750 + .quad 2149876660 + .quad 2149878288 + .quad 2149880006 + .quad 2149881660 + .quad 2149883546 + .quad 2149884066 + .quad 2149884522 + .quad 2149885000 + .quad 2149885516 + .quad 2149886044 + .quad 2149886602 + .quad 2149887166 + .quad 2149887670 + .quad 2149888164 + .quad 2149888684 + .quad 2149889220 + .quad 2149889746 + .quad 2149890206 + .quad 2149890666 + .quad 2149891094 + .quad 2149891544 + .quad 2149892194 + .quad 2149892888 + .quad 2149893574 + .quad 2149894254 + .quad 2149894514 + .quad 2149894728 + .quad 2149894918 + .quad 2149895166 + .quad 2149895166 + .quad 2149895372 + .quad 2149895574 + .quad 2149895780 + .quad 2149895986 + .quad 2149896192 + .quad 2149896210 + .quad 2149896228 + .quad 2149896246 + .quad 2149896264 + .quad 2149896282 + .quad 2149896292 + .quad 2149896302 + .quad 2149896312 + .quad 2149896322 + .quad 2149896322 + .quad 2149896332 + .quad 2149896342 + .quad 2149896352 + .quad 2149896362 + .quad 2149896372 + .quad 2149896382 + .quad 2149896392 + .quad 2149896402 + .quad 2149896538 + .quad 2149896686 + .quad 2149896784 + .quad 2149897794 + .quad 2149897794 + .quad 2149898342 + .quad 2149898342 + .quad 2149899060 + .quad 2149899060 + .quad 2149899060 + .quad 2149899144 + .quad 2149899144 + .quad 2149900690 + .quad 2149900698 + .quad 2149900710 + .quad 2149900722 + .quad 2149900738 + .quad 2149900750 + .quad 2149900804 + .quad 2149900858 + .quad 2149900912 + .quad 2149900966 + .quad 2149901012 + .quad 2149901058 + .quad 2149901104 + .quad 2149901150 + .quad 2149901168 + .quad 2149901172 + .quad 2149901186 + .quad 2149901316 + .quad 2149901388 + .quad 2149901442 + .quad 2149901448 + .quad 2149901462 + .quad 2149901480 + .quad 2149901494 + .quad 2149901726 + .quad 2149901738 + .quad 2149901742 + .quad 2149901746 + .quad 2149901792 + .quad 2149901796 + .quad 2149901810 + .quad 2149901822 + .quad 2149901826 + .quad 2149901830 + .quad 2149901834 + .quad 2149901878 + .quad 2149901896 + .quad 2149901914 + .quad 2149901932 + .quad 2149901942 + .quad 2149901952 + .quad 2149901962 + .quad 2149901972 + .quad 2149901982 + .quad 2149901992 + .quad 2149902002 + .quad 2149902012 + .quad 2149902022 + .quad 2149902032 + .quad 2149902042 + .quad 2149902052 + .quad 2149902082 + .quad 2149902330 + .quad 2149902476 + .quad 2149902486 + .quad 2149902488 + .quad 2149902610 + .quad 2149902700 + .quad 2149902838 + .quad 2149902970 + .quad 2149903102 + .quad 2149903236 + .quad 2149903376 + .quad 2149903518 + .quad 2149905318 + .quad 2149905322 + .quad 2149905334 + .quad 2149906002 + .quad 2149906762 + .quad 2149906770 + .quad 2149906774 + .quad 2149906786 + .quad 2149906798 + .quad 2149907046 + .quad 2149908090 + .quad 2149908298 + .quad 2149908438 + .quad 2149908784 + .quad 2149908970 + .quad 2149909314 + .quad 2149909406 + .quad 2149909502 + .quad 2149910170 + .quad 2149910306 + .quad 2149910450 + .quad 2149910462 + .quad 2149910466 + .quad 2149910480 + .quad 2149910494 + .quad 2149910506 + .quad 2149910510 + .quad 2149910514 + .quad 2149910656 + .quad 2149910738 + .quad 2149910876 + .quad 2149910944 + .quad 2149911796 + .quad 2149912332 + .quad 2149912710 + .quad 2149913060 + .quad 2149915030 + .quad 2149915458 + .quad 2149917282 + .quad 2149917908 + .quad 2149918100 + .quad 2149918292 + .quad 2149918574 + .quad 2149918840 + .quad 2149919318 + .quad 2149920352 + .quad 2149921212 + .quad 2149921230 + .quad 2149921248 + .quad 2149921266 + .quad 2149921284 + .quad 2149921352 + .quad 2149921362 + .quad 2149921372 + .quad 2149921382 + .quad 2149921382 + .quad 2149921392 + .quad 2149921402 + .quad 2149921412 + .quad 2149921422 + .quad 2149921432 + .quad 2149921442 + .quad 2149921452 + .quad 2149921462 + .quad 2149921472 + .quad 2149921502 + .quad 2149921750 + .quad 2149921786 + .quad 2149921934 + .quad 2149921936 + .quad 2149922226 + .quad 2149922748 + .quad 2149923232 + .quad 2149923406 + .quad 2149924064 + .quad 2149924558 + .quad 2149925250 + .quad 2149925380 + .quad 2149925452 + .quad 2149926436 + .quad 2149926440 + .quad 2149926448 + .quad 2149926942 + .quad 2149927292 + .quad 2149927300 + .quad 2149927304 + .quad 2149927316 + .quad 2149927328 + .quad 2149927340 + .quad 2149927532 + .quad 2149927586 + .quad 2149927640 + .quad 2149927686 + .quad 2149927732 + .quad 2149927736 + .quad 2149927750 + .quad 2149927764 + .quad 2149927776 + .quad 2149927780 + .quad 2149927784 + .quad 2149927908 + .quad 2149927990 + .quad 2149928070 + .quad 2149928088 + .quad 2149928106 + .quad 2149928116 + .quad 2149928126 + .quad 2149928136 + .quad 2149928146 + .quad 2149928156 + .quad 2149928166 + .quad 2149928176 + .quad 2149928186 + .quad 2149928196 + .quad 2149928206 + .quad 2149928216 + .quad 2149928226 + .quad 2149928236 + .quad 2149928246 + .quad 2149928256 + .quad 2149928266 + .quad 2149928276 + .quad 2149928286 + .quad 2149928296 + .quad 2149928306 + .quad 2149928336 + .quad 2149928382 + .quad 2149928530 + .quad 2149928676 + .quad 2149928762 + .quad 2149928770 + .quad 2149928778 + .quad 2149928782 + .quad 2149928794 + .quad 2149928806 + .quad 2149928822 + .quad 2149928834 + .quad 2149928852 + .quad 2149928858 + .quad 2149928872 + .quad 2149928878 + .quad 2149928892 + .quad 2149928906 + .quad 2149928920 + .quad 2149928932 + .quad 2149928938 + .quad 2149928942 + .quad 2149928942 + .quad 2149929072 + .quad 2149929072 + .quad 2149929144 + .quad 2149929198 + .quad 2149929206 + .quad 2149930252 + .quad 2149930270 + .quad 2149930770 + .quad 2149931008 + .quad 2149931020 + .quad 2149931024 + .quad 2149931028 + .quad 2149931028 + .quad 2149931112 + .quad 2149931404 + .quad 2149931422 + .quad 2149931554 + .quad 2149932390 + .quad 2149932398 + .quad 2149933574 + .quad 2149933592 + .quad 2149935194 + .quad 2149935340 + .quad 2149936306 + .quad 2149936544 + .quad 2149936652 + .quad 2149936944 + .quad 2149936956 + .quad 2149936960 + .quad 2149936964 + .quad 2149936982 + .quad 2149937000 + .quad 2149937018 + .quad 2149937036 + .quad 2149937046 + .quad 2149937056 + .quad 2149937066 + .quad 2149937076 + .quad 2149937212 + .quad 2149937404 + .quad 2149937496 + .quad 2149937586 + .quad 2149937856 + .quad 2149938732 + .quad 2149939682 + .quad 2149940772 + .quad 2149941046 + .quad 2149941046 + .quad 2149941100 + .quad 2149941100 + .quad 2149941146 + .quad 2149941400 + .quad 2149941486 + .quad 2149941572 + .quad 2149941658 + .quad 2149941740 + .quad 2149941826 + .quad 2149941912 + .quad 2149942000 + .quad 2149942072 + .quad 2149942072 + .quad 2149942126 + .quad 2149942486 + .quad 2149942486 + .quad 2149942570 + .quad 2149942570 + .quad 2149942616 + .quad 2149942620 + .quad 2149942624 + .quad 2149942652 + .quad 2149942868 + .quad 2149943170 + .quad 2149943302 + .quad 2149943498 + .quad 2149943588 + .quad 2149943896 + .quad 2149944004 + .quad 2149944204 + .quad 2149944296 + .quad 2149944388 + .quad 2149944398 + .quad 2149944648 + .quad 2149944650 + .quad 2149944650 + .quad 2149944732 + .quad 2149944732 + .quad 2149944986 + .quad 2149944986 + .quad 2149945216 + .quad 2149945470 + .quad 2149946598 + .quad 2149947694 + .quad 2149948292 + .quad 2149948672 + .quad 2149949516 + .quad 2149949700 + .quad 2149949760 + .quad 2149949812 + .quad 2149949938 + .quad 2149950010 + .quad 2149950248 + .quad 2149950486 + .quad 2149952558 + .quad 2149953480 + .quad 2149954814 + .quad 2149956572 + .quad 2149958150 + .quad 2149958278 + .quad 2149960962 + .quad 2149961972 + .quad 2149962882 + .quad 2149963796 + .quad 2149965478 + .quad 2149965488 + .quad 2149965670 + .quad 2149965846 + .quad 2149966014 + .quad 2149966016 + .quad 2149967546 + .quad 2149969444 + .quad 2149969810 + .quad 2149970212 + .quad 2149970338 + .quad 2149970524 + .quad 2149970710 + .quad 2149970996 + .quad 2149971284 + .quad 2149971528 + .quad 2149971546 + .quad 2149971564 + .quad 2149971574 + .quad 2149971584 + .quad 2149971594 + .quad 2149971604 + .quad 2149971614 + .quad 2149971624 + .quad 2149971634 + .quad 2149971644 + .quad 2149971654 + .quad 2149971664 + .quad 2149971674 + .quad 2149971684 + .quad 2149971714 + .quad 2149971980 + .quad 2149972126 + .quad 2149972284 + .quad 2149972286 + .quad 2149972288 + .quad 2149973602 + .quad 2149974478 + .quad 2149974486 + .quad 2149974490 + .quad 2149974502 + .quad 2149974518 + .quad 2149974530 + .quad 2149974542 + .quad 2149975078 + .quad 2149975082 + .quad 2149975096 + .quad 2149975228 + .quad 2149975318 + .quad 2149975372 + .quad 2149975382 + .quad 2149977030 + .quad 2149979422 + .quad 2149979432 + .quad 2149979446 + .quad 2149979624 + .quad 2149979636 + .quad 2149979640 + .quad 2149979644 + .quad 2149979728 + .quad 2149980604 + .quad 2149980828 + .quad 2149981056 + .quad 2149981390 + .quad 2149981394 + .quad 2149981484 + .quad 2149981490 + .quad 2149981504 + .quad 2149981518 + .quad 2149981770 + .quad 2149981782 + .quad 2149982004 + .quad 2149982050 + .quad 2149982068 + .quad 2149982078 + .quad 2149982088 + .quad 2149982098 + .quad 2149982108 + .quad 2149982118 + .quad 2149982128 + .quad 2149982138 + .quad 2149982148 + .quad 2149982158 + .quad 2149982168 + .quad 2149982178 + .quad 2149982188 + .quad 2149982198 + .quad 2149982208 + .quad 2149982218 + .quad 2149982228 + .quad 2149982238 + .quad 2149982248 + .quad 2149982258 + .quad 2149982268 + .quad 2149982278 + .quad 2149982288 + .quad 2149982298 + .quad 2149982308 + .quad 2149982490 + .quad 2149982512 + .quad 2149982530 + .quad 2149982560 + .quad 2149982808 + .quad 2149982844 + .quad 2149982960 + .quad 2149982970 + .quad 2149983116 + .quad 2149983118 + .quad 2149983186 + .quad 2149983188 + .quad 2149983240 + .quad 2149983244 + .quad 2149983252 + .quad 2149984282 + .quad 2149984294 + .quad 2149984918 + .quad 2149984922 + .quad 2149984934 + .quad 2149984942 + .quad 2149984946 + .quad 2149984958 + .quad 2149984970 + .quad 2149984982 + .quad 2149985274 + .quad 2149985278 + .quad 2149985290 + .quad 2149985294 + .quad 2149988014 + .quad 2149994638 + .quad 2149994662 + .quad 2149994680 + .quad 2149994698 + .quad 2149994716 + .quad 2149994726 + .quad 2149994768 + .quad 2149994810 + .quad 2149994820 + .quad 2149994842 + .quad 2149994852 + .quad 2149994862 + .quad 2149994872 + .quad 2149994882 + .quad 2149994902 + .quad 2149994912 + .quad 2149994914 + .quad 2149995050 + .quad 2149995068 + .quad 2149995070 + .quad 2149995090 + .quad 2149995184 + .quad 2149995438 + .quad 2149995438 + .quad 2149995492 + .quad 2149995492 + .quad 2149995538 + .quad 2149995542 + .quad 2149995546 + .quad 2149996210 + .quad 2149996546 + .quad 2149996678 + .quad 2149996874 + .quad 2149996964 + .quad 2149997018 + .quad 2149997326 + .quad 2149997454 + .quad 2149997562 + .quad 2149997646 + .quad 2149997692 + .quad 2149997876 + .quad 2149998142 + .quad 2149998358 + .quad 2149998516 + .quad 2149998786 + .quad 2149999074 + .quad 2149999310 + .quad 2149999546 + .quad 2149999754 + .quad 2149999916 + .quad 2150000110 + .quad 2150000196 + .quad 2150000278 + .quad 2150000300 + .quad 2150000388 + .quad 2150001376 + .quad 2150001596 + .quad 2150001676 + .quad 2150001764 + .quad 2150001852 + .quad 2150002018 + .quad 2150002050 + .quad 2150002588 + .quad 2150002708 + .quad 2150002800 + .quad 2150002920 + .quad 2150003012 + .quad 2150003014 + .quad 2150003016 + .quad 2150003056 + .quad 2150003058 + .quad 2150003346 + .quad 2150003582 + .quad 2150003584 + .quad 2150003586 + .quad 2150004166 + .quad 2150004824 + .quad 2150005032 + .quad 2150005052 + .quad 2150005060 + .quad 2150005064 + .quad 2150005068 + .quad 2150005072 + .quad 2150005146 + .quad 2150005150 + .quad 2150005162 + .quad 2150005164 + .quad 2150005172 + .quad 2150005178 + .quad 2150005184 + .quad 2150007014 + .quad 2150009658 + .quad 2150009698 + .quad 2150010514 + .quad 2150010554 + .quad 2150010556 + .quad 2150011180 + .quad 2150011180 + .quad 2150011180 + .quad 2150011180 + .quad 2150011296 + .quad 2150011466 + .quad 2150011582 + .quad 2150011958 + .quad 2150012008 + .quad 2150012102 + .quad 2150013126 + .quad 2150013726 + .quad 2150014076 + .quad 2150014218 + .quad 2150014248 + .quad 2150014278 + .quad 2150015106 + .quad 2150015904 + .quad 2150015904 + .quad 2150016134 + .quad 2150016364 + .quad 2150016594 + .quad 2150016868 + .quad 2150017098 + .quad 2150017322 + .quad 2150017340 + .quad 2150017382 + .quad 2150017424 + .quad 2150017444 + .quad 2150017446 + .quad 2150017480 + .quad 2150017568 + .quad 2150017628 + .quad 2150017688 + .quad 2150017716 + .quad 2150017744 + .quad 2150017836 + .quad 2150017906 + .quad 2150017944 + .quad 2150018094 + .quad 2150018122 + .quad 2150018414 + .quad 2150018536 + .quad 2150018668 + .quad 2150018678 + .quad 2150018746 + .quad 2150018930 + .quad 2150019192 + .quad 2150019704 + .quad 2150019952 + .quad 2150020330 + .quad 2150022048 + .quad 2150023676 + .quad 2150023792 + .quad 2150023916 + .quad 2150024056 + .quad 2150024280 + .quad 2150024522 + .quad 2150024630 + .quad 2150025656 + .quad 2150025660 + .quad 2150025664 + .quad 2150025938 + .quad 2150026068 + .quad 2150026198 + .quad 2150026316 + .quad 2150026432 + .quad 2150026442 + .quad 2150026464 + .quad 2150026474 + .quad 2150026492 + .quad 2150026508 + .quad 2150026940 + .quad 2150027062 + .quad 2150027194 + .quad 2150027332 + .quad 2150027464 + .quad 2150028622 + .quad 2150029770 + .quad 2150030390 + .quad 2150031804 + .quad 2150032522 + .quad 2150033526 + .quad 2150034056 + .quad 2150034248 + .quad 2150034438 + .quad 2150034650 + .quad 2150034970 + .quad 2150035856 + .quad 2150035856 + .quad 2150035858 + .quad 2150035892 + .quad 2150035926 + .quad 2150036106 + .quad 2150036186 + .quad 2150036274 + .quad 2150036628 + .quad 2150036844 + .quad 2150036926 + .quad 2150037236 + .quad 2150037334 + .quad 2150037336 + .quad 2150037338 + .quad 2150037696 + .quad 2150037780 + .quad 2150038162 + .quad 2150038300 + .quad 2150039004 + .quad 2150039020 + .quad 2150039040 + .quad 2150039054 + .quad 2150039056 + .quad 2150039068 + .quad 2150039152 + .quad 2150040886 + .quad 2150042692 + .quad 2150042784 + .quad 2150042884 + .quad 2150043050 + .quad 2150043216 + .quad 2150043236 + .quad 2150043256 + .quad 2150043430 + .quad 2150046370 + .quad 2150046370 + .quad 2150047046 + .quad 2150049304 + .quad 2150049834 + .quad 2150049876 + .quad 2150049918 + .quad 2150049920 + .quad 2150049922 + .quad 2150050762 + .quad 2150050850 + .quad 2150051002 + .quad 2150051384 + .quad 2150051782 + .quad 2150051974 + .quad 2150052364 + .quad 2150053832 + .quad 2150054414 + .quad 2150055162 + .quad 2150055176 + .quad 2150055184 + .quad 2150055198 + .quad 2150055210 + .quad 2150055316 + .quad 2150055410 + .quad 2150055450 + .quad 2150055452 + .quad 2150055606 + .quad 2150056248 + .quad 2150056740 + .quad 2150057000 + .quad 2150057020 + .quad 2150057030 + .quad 2150057050 + .quad 2150057128 + .quad 2150057528 + .quad 2150057538 + .quad 2150057560 + .quad 2150057580 + .quad 2150057628 + .quad 2150057646 + .quad 2150057664 + .quad 2150057800 + .quad 2150057922 + .quad 2150058062 + .quad 2150058080 + .quad 2150058126 + .quad 2150058334 + .quad 2150058492 + .quad 2150058624 + .quad 2150058632 + .quad 2150058636 + .quad 2150058678 + .quad 2150058688 + .quad 2150058728 + .quad 2150058730 + .quad 2150058812 + .quad 2150058894 + .quad 2150058934 + .quad 2150060464 + .quad 2150060890 + .quad 2150061300 + .quad 2150062186 + .quad 2150062740 + .quad 2150063312 + .quad 2150063884 + .quad 2150064268 + .quad 2150064502 + .quad 2150064600 + .quad 2150064982 + .quad 2150064984 + .quad 2150065208 + .quad 2150065556 + .quad 2150065888 + .quad 2150066310 + .quad 2150066560 + .quad 2150066836 + .quad 2150067322 + .quad 2150067664 + .quad 2150068122 + .quad 2150068324 + .quad 2150068782 + .quad 2150069350 + .quad 2150069672 + .quad 2150070198 + .quad 2150070848 + .quad 2150071256 + .quad 2150071258 + .quad 2150071592 + .quad 2150072278 + .quad 2150072874 + .quad 2150073392 + .quad 2150074026 + .quad 2150074564 + .quad 2150075578 + .quad 2150076048 + .quad 2150076332 + .quad 2150079300 + .quad 2150079534 + .quad 2150080758 + .quad 2150080992 + .quad 2150081226 + .quad 2150082400 + .quad 2150083866 + .quad 2150084116 + .quad 2150084380 + .quad 2150084470 + .quad 2150084604 + .quad 2150085242 + .quad 2150085492 + .quad 2150086060 + .quad 2150086452 + .quad 2150086586 + .quad 2150086776 + .quad 2150086918 + .quad 2150087576 + .quad 2150087808 + .quad 2150088052 + .quad 2150088052 + .quad 2150088126 + .quad 2150088524 + .quad 2150088760 + .quad 2150089204 + .quad 2150089842 + .quad 2150090626 + .quad 2150090856 + .quad 2150091090 + .quad 2150091344 + .quad 2150091694 + .quad 2150091696 + .quad 2150092682 + .quad 2150093464 + .quad 2150095078 + .quad 2150095086 + .quad 2150095096 + .quad 2150095138 + .quad 2150095158 + .quad 2150095160 + .quad 2150095162 + .quad 2150095278 + .quad 2150096200 + .quad 2150096606 + .quad 2150096648 + .quad 2150096730 + .quad 2150097132 + .quad 2150097196 + .quad 2150097950 + .quad 2150098206 + .quad 2150098424 + .quad 2150098658 + .quad 2150098780 + .quad 2150098912 + .quad 2150099054 + .quad 2150099064 + .quad 2150099556 + .quad 2150099862 + .quad 2150100368 + .quad 2150100378 + .quad 2150100380 + .quad 2150100414 + .quad 2150100448 + .quad 2150100578 + .quad 2150100866 + .quad 2150100888 + .quad 2150102148 + .quad 2150102274 + .quad 2150102314 + .quad 2150102354 + .quad 2150102684 + .quad 2150102748 + .quad 2150102886 + .quad 2150103184 + .quad 2150103490 + .quad 2150103862 + .quad 2150103920 + .quad 2150104062 + .quad 2150104186 + .quad 2150104382 + .quad 2150104922 + .quad 2150105084 + .quad 2150111644 + .quad 2150111962 + .quad 2150112050 + .quad 2150112104 + .quad 2150112146 + .quad 2150112186 + .quad 2150112198 + .quad 2150114422 + .quad 2150114866 + .quad 2150115098 + .quad 2150115108 + .quad 2150115110 + .quad 2150115358 + .quad 2150115420 + .quad 2150115480 + .quad 2150115540 + .quad 2150115598 + .quad 2150116206 + .quad 2150117020 + .quad 2150118202 + .quad 2150118284 + .quad 2150119324 + .quad 2150119826 + .quad 2150119870 + .quad 2150121064 + .quad 2150123708 + .quad 2150124614 + .quad 2150124614 + .quad 2150124636 + .quad 2150124794 + .quad 2150124990 + .quad 2150125252 + .quad 2150125982 + .quad 2150126186 + .quad 2150126574 + .quad 2150126580 + .quad 2150126678 + .quad 2150126722 + .quad 2150126722 + .quad 2150126722 + .quad 2150126722 + .quad 2150126722 + .quad 2150126722 + .quad 2150126722 + .quad 2150126722 + .quad 2150126722 + .quad 2150126722 + .quad 2150126722 + .quad 2150126722 + .quad 2150126724 + .quad 2150127530 + .quad 2150128184 + .quad 2150128248 + .quad 2150129560 + .quad 2150129782 + .quad 2150130006 + .quad 2150130312 + .quad 2150130402 + .quad 2150130404 + .quad 2150130688 + .quad 2150131074 + .quad 2150131114 + .quad 2150131164 + .quad 2150131550 + .quad 2150131640 + .quad 2150131684 + .quad 2150131758 + .quad 2150131892 + .quad 2150131994 + .quad 2150132094 + .quad 2150132116 + .quad 2150132160 + .quad 2150132204 + .quad 2150132550 + .quad 2150133030 + .quad 2150133536 + .quad 2150134052 + .quad 2150134384 + .quad 2150134618 + .quad 2150134966 + .quad 2150135286 + .quad 2150135656 + .quad 2150135700 + .quad 2150135744 + .quad 2150135826 + .quad 2150135828 + .quad 2150135830 + .quad 2150135886 + .quad 2150136002 + .quad 2150136374 + .quad 2150136858 + .quad 2150136922 + .quad 2150136966 + .quad 2150137008 + .quad 2150137130 + .quad 2150137218 + .quad 2150137260 + .quad 2150137346 + .quad 2150137388 + .quad 2150137640 + .quad 2150137660 + .quad 2150137826 + .quad 2150138402 + .quad 2150138474 + .quad 2150138726 + .quad 2150138908 + .quad 2150139216 + .quad 2150139488 + .quad 2150139802 + .quad 2150139944 + .quad 2150139984 + .quad 2150139986 + .quad 2150139988 + .quad 2150139990 + .quad 2150140038 + .quad 2150140268 + .quad 2150140462 + .quad 2150140838 + .quad 2150140932 + .quad 2150141088 + .quad 2150141202 + .quad 2150141212 + .quad 2150141400 + .quad 2150141712 + .quad 2150142244 + .quad 2150142600 + .quad 2150143230 + .quad 2150143288 + .quad 2150143668 + .quad 2150143896 + .quad 2150143896 + .quad 2150143918 + .quad 2150144340 + .quad 2150144348 + .quad 2150144370 + .quad 2150144410 + .quad 2150144412 + .quad 2150146600 + .quad 2150146858 + .quad 2150147116 + .quad 2150147118 + .quad 2150148210 + .quad 2150148210 + .quad 2150148210 + .quad 2150148210 + .quad 2150148210 + .quad 2150148210 + .quad 2150148210 + .quad 2150148210 + .quad 2150148210 + .quad 2150148210 + .quad 2150148210 + .quad 2150148210 + .quad 2150148210 + .quad 2150148216 + .quad 2150149054 + .quad 2150149644 + .quad 2150149686 + .quad 2150149708 + .quad 2150149710 + .quad 2150149712 + .quad 2150149746 + .quad 2150150120 + .quad 2150150478 + .quad 2150150520 + .quad 2150150520 + .quad 2150150520 + .quad 2150150520 + .quad 2150150520 + .quad 2150150520 + .quad 2150150520 + .quad 2150150520 + .quad 2150150520 + .quad 2150150520 + .quad 2150150520 + .quad 2150150520 + .quad 2150150520 + .quad 2150150520 + .quad 2150150578 + .quad 2150150590 + .quad 2150150602 + .quad 2150150642 + .quad 2150150644 + .quad 2150150726 + .quad 2150151200 + .quad 2150151610 + .quad 2150152174 + .quad 2150152454 + .quad 2150153102 + .quad 2150153128 + .quad 2150153200 + .quad 2150153224 + .quad 2150153464 + .quad 2150153724 + .quad 2150153966 + .quad 2150154006 + .quad 2150154024 + .quad 2150154026 + .quad 2150154230 + .quad 2150154362 + .quad 2150154488 + .quad 2150155002 + .quad 2150155042 + .quad 2150155214 + .quad 2150155216 + .quad 2150157522 + .quad 2150157700 + .quad 2150157998 + .quad 2150159296 + .quad 2150159306 + .quad 2150159348 + .quad 2150159350 + .quad 2150159384 + .quad 2150159388 + .quad 2150159716 + .quad 2150160040 + .quad 2150160352 + .quad 2150160966 + .quad 2150160988 + .quad 2150161012 + .quad 2150161118 + .quad 2150161176 + .quad 2150162842 + .quad 2150164520 + .quad 2150164976 + .quad 2150165480 + .quad 2150165982 + .quad 2150166418 + .quad 2150167068 + .quad 2150167258 + .quad 2150167490 + .quad 2150167744 + .quad 2150168184 + .quad 2150169656 + .quad 2150170546 + .quad 2150170988 + .quad 2150171028 + .quad 2150171096 + .quad 2150171164 + .quad 2150171206 + .quad 2150171208 + .quad 2150171380 + .quad 2150171380 + .quad 2150171466 + .quad 2150171466 + .quad 2150171552 + .quad 2150171792 + .quad 2150171792 + .quad 2150172476 + .quad 2150172518 + .quad 2150172590 + .quad 2150172592 + .quad 2150172662 + .quad 2150172668 + .quad 2150172700 + .quad 2150172722 + .quad 2150172740 + .quad 2150172752 + .quad 2150172762 + .quad 2150172768 + .quad 2150172782 + .quad 2150173006 + .quad 2150173082 + .quad 2150173116 + .quad 2150173130 + .quad 2150173138 + .quad 2150173184 + .quad 2150173288 + .quad 2150173408 + .quad 2150173410 + .quad 2150173454 + .quad 2150174308 + .quad 2150174960 + .quad 2150175610 + .quad 2150175652 + .quad 2150175694 + .quad 2150175736 + .quad 2150175746 + .quad 2150175786 + .quad 2150175788 + .quad 2150175790 + .quad 2150175894 + .quad 2150176192 + .quad 2150176312 + .quad 2150176352 + .quad 2150176392 + .quad 2150176394 + .quad 2150176396 + .quad 2150176440 + .quad 2150176484 + .quad 2150176646 + .quad 2150176772 + .quad 2150176914 + .quad 2150177034 + .quad 2150177044 + .quad 2150177084 + .quad 2150177086 + .quad 2150177120 + .quad 2150177194 + .quad 2150177278 + .quad 2150177322 + .quad 2150177706 + .quad 2150177748 + .quad 2150177750 + .quad 2150177818 + .quad 2150177854 + .quad 2150177922 + .quad 2150178064 + .quad 2150178390 + .quad 2150178554 + .quad 2150178910 + .quad 2150179564 + .quad 2150179898 + .quad 2150179940 + .quad 2150180302 + .quad 2150180368 + .quad 2150180920 + .quad 2150181440 + .quad 2150181888 + .quad 2150182516 + .quad 2150182598 + .quad 2150182640 + .quad 2150182682 + .quad 2150182724 + .quad 2150182734 + .quad 2150182744 + .quad 2150182746 + .quad 2150183008 + .quad 2150183170 + .quad 2150183312 + .quad 2150183434 + .quad 2150183568 + .quad 2150183852 + .quad 2150183970 + .quad 2150184290 + .quad 2150184340 + .quad 2150184416 + .quad 2150184542 + .quad 2150184594 + .quad 2150184634 + .quad 2150184816 + .quad 2150184974 + .quad 2150185014 + .quad 2150185054 + .quad 2150185094 + .quad 2150185096 + .quad 2150185098 + .quad 2150185100 + .quad 2150185102 + .quad 2150185422 + .quad 2150185458 + .quad 2150185520 + .quad 2150185602 + .quad 2150186298 + .quad 2150186462 + .quad 2150187018 + .quad 2150187200 + .quad 2150187276 + .quad 2150187390 + .quad 2150187422 + .quad 2150187424 + .quad 2150187492 + .quad 2150187494 + .quad 2150187584 + .quad 2150187586 + .quad 2150187986 + .quad 2150188000 + .quad 2150188004 + .quad 2150188008 + .quad 2150188010 + .quad 2150188012 + .quad 2150188058 + .quad 2150188078 + .quad 2150188090 + .quad 2150188152 + .quad 2150188170 + .quad 2150188328 + .quad 2150189090 + .quad 2150189484 + .quad 2150189736 + .quad 2150191056 + .quad 2150191300 + .quad 2150191710 + .quad 2150192328 + .quad 2150192638 + .quad 2150193122 + .quad 2150194116 + .quad 2150194732 + .quad 2150195364 + .quad 2150198326 + .quad 2150198354 + .quad 2150198382 + .quad 2150198490 + .quad 2150198878 + .quad 2150199094 + .quad 2150199246 + .quad 2150202318 + .quad 2150202358 + .quad 2150202398 + .quad 2150202438 + .quad 2150202440 + .quad 2150202442 + .quad 2150202630 + .quad 2150202732 + .quad 2150204396 + .quad 2150204438 + .quad 2150204620 + .quad 2150204662 + .quad 2150204784 + .quad 2150204826 + .quad 2150204868 + .quad 2150204888 + .quad 2150204892 + .quad 2150204910 + .quad 2150205034 + .quad 2150205174 + .quad 2150205742 + .quad 2150205786 + .quad 2150205786 + .quad 2150205788 + .quad 2150205818 + .quad 2150205900 + .quad 2150205904 + .quad 2150205922 + .quad 2150205956 + .quad 2150205956 + .quad 2150205956 + .quad 2150206072 + .quad 2150206110 + .quad 2150206144 + .quad 2150206186 + .quad 2150206244 + .quad 2150206278 + .quad 2150206288 + .quad 2150206328 + .quad 2150206368 + .quad 2150206408 + .quad 2150206410 + .quad 2150206412 + .quad 2150206414 + .quad 2150207028 + .quad 2150207450 + .quad 2150207692 + .quad 2150208110 + .quad 2150208222 + .quad 2150208526 + .quad 2150208748 + .quad 2150208908 + .quad 2150209142 + .quad 2150209474 + .quad 2150211016 + .quad 2150213186 + .quad 2150214850 + .quad 2150215146 + .quad 2150215450 + .quad 2150215584 + .quad 2150215624 + .quad 2150215626 + .quad 2150216994 + .quad 2150217032 + .quad 2150217034 + .quad 2150217976 + .quad 2150218058 + .quad 2150218100 + .quad 2150218142 + .quad 2150218184 + .quad 2150218224 + .quad 2150218224 + .quad 2150218224 + .quad 2150218224 + .quad 2150218224 + .quad 2150218226 + .quad 2150218308 + .quad 2150218350 + .quad 2150220122 + .quad 2150220162 + .quad 2150220164 + .quad 2150220266 + .quad 2150220404 + .quad 2150220420 + .quad 2150220554 + .quad 2150221186 + .quad 2150221228 + .quad 2150221272 + .quad 2150221274 + .quad 2150221540 + .quad 2150221608 + .quad 2150221678 + .quad 2150221746 + .quad 2150221822 + .quad 2150221838 + .quad 2150221892 + .quad 2150222024 + .quad 2150222488 + .quad 2150222978 + .quad 2150223340 + .quad 2150223386 + .quad 2150223578 + .quad 2150223618 + .quad 2150223684 + .quad 2150223726 + .quad 2150223820 + .quad 2150223862 + .quad 2150223902 + .quad 2150223988 + .quad 2150224008 + .quad 2150224050 + .quad 2150224060 + .quad 2150224080 + .quad 2150224270 + .quad 2150224292 + .quad 2150224294 + .quad 2150224296 + .quad 2150224346 + .quad 2150224532 + .quad 2150224778 + .quad 2150224844 + .quad 2150224874 + .quad 2150225024 + .quad 2150225052 + .quad 2150225250 + .quad 2150225284 + .quad 2150225316 + .quad 2150225320 + .quad 2150225670 + .quad 2150225672 + .quad 2150225956 + .quad 2150226404 + .quad 2150226460 + .quad 2150226582 + .quad 2150226584 + .quad 2150226586 + .quad 2150226588 + .quad 2150227618 + .quad 2150230056 + .quad 2150230496 + .quad 2150230752 + .quad 2150231076 + .quad 2150231314 + .quad 2150231806 + .quad 2150232988 + .quad 2150233784 + .quad 2150234244 + .quad 2150234292 + .quad 2150234812 + .quad 2150235194 + .quad 2150235290 + .quad 2150235542 + .quad 2150235706 + .quad 2150235894 + .quad 2150235936 + .quad 2150236332 + .quad 2150236686 + .quad 2150236796 + .quad 2150236838 + .quad 2150236840 + .quad 2150236874 + .quad 2150236900 + .quad 2150236938 + .quad 2150236998 + .quad 2150237174 + .quad 2150237216 + .quad 2150237268 + .quad 2150237270 + .quad 2150237272 + .quad 2150237294 + .quad 2150237390 + .quad 2150237550 + .quad 2150237606 + .quad 2150237650 + .quad 2150237694 + .quad 2150237696 + .quad 2150237768 + .quad 2150237776 + .quad 2150237882 + .quad 2150237988 + .quad 2150238094 + .quad 2150238200 + .quad 2150238306 + .quad 2150238328 + .quad 2150238350 + .quad 2150238352 + .quad 2150238370 + .quad 2150238510 + .quad 2150238648 + .quad 2150238772 + .quad 2150238824 + .quad 2150238844 + .quad 2150238974 + .quad 2150239202 + .quad 2150239644 + .quad 2150239902 + .quad 2150240018 + .quad 2150240100 + .quad 2150240120 + .quad 2150240186 + .quad 2150240208 + .quad 2150240210 + .quad 2150240212 + .quad 2150240242 + .quad 2150240246 + .quad 2150240248 + .quad 2150240250 + .quad 2150240348 + .quad 2150240536 + .quad 2150240580 + .quad 2150240584 + .quad 2150240586 + .quad 2150240588 + .quad 2150241012 + .quad 2150241112 + .quad 2150241130 + .quad 2150241130 + .quad 2150241130 + .quad 2150241192 + .quad 2150241210 + .quad 2150241228 + .quad 2150241284 + .quad 2150241340 + .quad 2150242110 + .quad 2150242178 + .quad 2150242246 + .quad 2150242314 + .quad 2150242382 + .quad 2150242690 + .quad 2150244388 + .quad 2150244414 + .quad 2150244440 + .quad 2150244716 + .quad 2150245186 + .quad 2150245244 + .quad 2150245526 + .quad 2150245572 + .quad 2150245620 + .quad 2150245664 + .quad 2150245728 + .quad 2150245772 + .quad 2150245998 + .quad 2150246074 + .quad 2150246550 + .quad 2150246646 + .quad 2150247024 + .quad 2150247116 + .quad 2150247364 + .quad 2150247498 + .quad 2150247756 + .quad 2150247756 + .quad 2150247782 + .quad 2150247812 + .quad 2150248048 + .quad 2150248284 + .quad 2150248520 + .quad 2150248756 + .quad 2150248778 + .quad 2150248800 + .quad 2150248822 + .quad 2150248844 + .quad 2150248866 + .quad 2150248884 + .quad 2150249266 + .quad 2150249790 + .quad 2150249876 + .quad 2150250434 + .quad 2150250434 + .quad 2150250442 + .quad 2150250442 + .quad 2150250462 + .quad 2150250508 + .quad 2150250696 + .quad 2150250922 + .quad 2150251182 + .quad 2150251476 + .quad 2150251670 + .quad 2150251730 + .quad 2150251892 + .quad 2150252082 + .quad 2150252134 + .quad 2150252178 + .quad 2150252924 + .quad 2150252940 + .quad 2150253232 + .quad 2150253428 + .quad 2150253614 + .quad 2150253814 + .quad 2150254090 + .quad 2150254154 + .quad 2150254218 + .quad 2150254282 + .quad 2150254348 + .quad 2150254878 + .quad 2150255278 + .quad 2150255392 + .quad 2150256324 + .quad 2150256856 + .quad 2150256870 + .quad 2150257580 + .quad 2150257848 + .quad 2150258146 + .quad 2150258154 + .quad 2150258154 + .quad 2150258272 + .quad 2150258272 + .quad 2150258390 + .quad 2150258390 + .quad 2150258508 + .quad 2150258508 + .quad 2150258626 + .quad 2150258626 + .quad 2150258742 + .quad 2150258742 + .quad 2150258858 + .quad 2150258858 + .quad 2150258858 + .quad 2150258858 + .quad 2150258956 + .quad 2150258956 + .quad 2150258956 + .quad 2150258956 + .quad 2150259070 + .quad 2150259070 + .quad 2150259070 + .quad 2150259070 + .quad 2150259184 + .quad 2150259432 + .quad 2150259670 + .quad 2150260026 + .quad 2150260042 + .quad 2150260058 + .quad 2150260098 + .quad 2150260114 + .quad 2150260114 + .quad 2150260148 + .quad 2150260148 + .quad 2150260162 + .quad 2150260180 + .quad 2150260190 + .quad 2150260388 + .quad 2150260398 + .quad 2150260406 + .quad 2150260416 + .quad 2150260432 + .quad 2150260442 + .quad 2150260562 + .quad 2150260742 + .quad 2150261024 + .quad 2150261200 + .quad 2150261592 + .quad 2150261694 + .quad 2150261726 + .quad 2150261734 + .quad 2150261840 + .quad 2150263272 + .quad 2150263280 + .quad 2150263288 + .quad 2150264832 + .quad 2150264832 + .quad 2150339232 + .quad 2150375984 + .quad 2150396304 + .quad 2150416352 + .quad 2150416448 + .quad 2150417600 + .quad 2150447192 + .quad 2150452896 + .quad 2150453028 + .quad 2150457344 + .quad 2150461440 + .quad 2150461440 + .quad 2150461440 + .quad 2150461448 + .quad 2150461456 + .quad 2150461464 + .quad 2150461472 + .quad 2150461480 + .quad 2150461488 + .quad 2150461496 + .quad 2150461504 + .quad 2150461512 + .quad 2150461520 + .quad 2150461528 + .quad 2150461536 + .quad 2150461544 + .quad 2150461552 + .quad 2150461560 + .quad 2150461568 + .quad 2150461576 + .quad 2150461584 + .quad 2150461592 + .quad 2150461600 + .quad 2150461608 + .quad 2150461616 + .quad 2150461624 + .quad 2150461632 + .quad 2150461640 + .quad 2150461648 + .quad 2150461656 + .quad 2150461664 + .quad 2150461672 + .quad 2150461680 + .quad 2150461688 + .quad 2150461696 + .quad 2150461704 + .quad 2150461712 + .quad 2150461720 + .quad 2150461728 + .quad 2150461736 + .quad 2150461744 + .quad 2150461752 + .quad 2150461760 + .quad 2150461768 + .quad 2150461776 + .quad 2150461784 + .quad 2150461792 + .quad 2150461800 + .quad 2150461808 + .quad 2150461816 + .quad 2150461824 + .quad 2150461832 + .quad 2150461840 + .quad 2150461848 + .quad 2150461856 + .quad 2150461864 + .quad 2150461872 + .quad 2150461880 + .quad 2150461888 + .quad 2150461896 + .quad 2150461904 + .quad 2150461912 + .quad 2150461920 + .quad 2150461928 + .quad 2150461936 + .quad 2150461944 + .quad 2150461952 + .quad 2150461960 + .quad 2150461968 + .quad 2150461976 + .quad 2150461984 + .quad 2150461992 + .quad 2150462000 + .quad 2150462008 + .quad 2150462016 + .quad 2150462024 + .quad 2150462032 + .quad 2150462040 + .quad 2150462048 + .quad 2150462056 + .quad 2150462064 + .quad 2150462072 + .quad 2150462080 + .quad 2150462088 + .quad 2150462096 + .quad 2150462104 + .quad 2150462112 + .quad 2150462120 + .quad 2150462128 + .quad 2150462136 + .quad 2150462144 + .quad 2150462152 + .quad 2150462160 + .quad 2150462168 + .quad 2150462176 + .quad 2150462184 + .quad 2150462192 + .quad 2150462200 + .quad 2150462208 + .quad 2150462216 + .quad 2150462224 + .quad 2150462232 + .quad 2150462240 + .quad 2150462248 + .quad 2150462256 + .quad 2150462264 + .quad 2150462272 + .quad 2150462280 + .quad 2150462288 + .quad 2150462296 + .quad 2150462304 + .quad 2150462312 + .quad 2150462320 + .quad 2150462328 + .quad 2150462336 + .quad 2150462344 + .quad 2150462352 + .quad 2150462360 + .quad 2150462368 + .quad 2150462376 + .quad 2150462384 + .quad 2150462392 + .quad 2150462400 + .quad 2150462408 + .quad 2150462416 + .quad 2150462424 + .quad 2150462432 + .quad 2150462440 + .quad 2150462448 + .quad 2150462456 + .quad 2150462464 + .quad 2150462472 + .quad 2150462480 + .quad 2150462480 + .quad 2150462552 + .quad 2150462608 + .quad 2150462632 + .quad 2150462656 + .quad 2150462680 + .quad 2150462704 + .quad 2150462728 + .quad 2150462752 + .quad 2150462776 + .quad 2150462800 + .quad 2150462824 + .quad 2150462848 + .quad 2150462872 + .quad 2150462896 + .quad 2150462920 + .quad 2150462944 + .quad 2150462968 + .quad 2150462992 + .quad 2150463016 + .quad 2150463040 + .quad 2150463064 + .quad 2150463088 + .quad 2150463112 + .quad 2150463136 + .quad 2150463160 + .quad 2150463184 + .quad 2150463208 + .quad 2150463232 + .quad 2150463256 + .quad 2150463280 + .quad 2150463304 + .quad 2150463328 + .quad 2150463352 + .quad 2150463376 + .quad 2150463400 + .quad 2150463424 + .quad 2150463448 + .quad 2150463472 + .quad 2150463496 + .quad 2150463520 + .quad 2150463544 + .quad 2150463568 + .quad 2150463592 + .quad 2150463616 + .quad 2150463640 + .quad 2150463664 + .quad 2150463688 + .quad 2150463712 + .quad 2150463736 + .quad 2150463760 + .quad 2150463784 + .quad 2150463808 + .quad 2150463832 + .quad 2150463856 + .quad 2150463880 + .quad 2150463904 + .quad 2150463928 + .quad 2150463952 + .quad 2150463976 + .quad 2150464000 + .quad 2150464024 + .quad 2150464048 + .quad 2150464072 + .quad 2150464096 + .quad 2150464120 + .quad 2150464144 + .quad 2150464168 + .quad 2150464192 + .quad 2150464216 + .quad 2150464240 + .quad 2150464264 + .quad 2150464288 + .quad 2150464312 + .quad 2150464336 + .quad 2150464360 + .quad 2150464384 + .quad 2150464408 + .quad 2150464432 + .quad 2150464456 + .quad 2150464480 + .quad 2150464504 + .quad 2150464544 + .quad 2150464568 + .quad 2150464592 + .quad 2150464616 + .quad 2150464640 + .quad 2150464664 + .quad 2150464688 + .quad 2150464712 + .quad 2150464736 + .quad 2150464760 + .quad 2150464784 + .quad 2150464808 + .quad 2150464832 + .quad 2150464856 + .quad 2150464880 + .quad 2150464904 + .quad 2150464928 + .quad 2150464952 + .quad 2150464976 + .quad 2150465000 + .quad 2150465024 + .quad 2150465048 + .quad 2150465072 + .quad 2150465096 + .quad 2150465120 + .quad 2150465144 + .quad 2150465168 + .quad 2150465192 + .quad 2150465216 + .quad 2150465240 + .quad 2150465264 + .quad 2150465288 + .quad 2150465312 + .quad 2150465336 + .quad 2150465360 + .quad 2150465384 + .quad 2150465408 + .quad 2150465432 + .quad 2150465456 + .quad 2150465480 + .quad 2150465504 + .quad 2150465528 + .quad 2150465552 + .quad 2150465576 + .quad 2150465600 + .quad 2150465624 + .quad 2150465648 + .quad 2150465672 + .quad 2150465696 + .quad 2150465720 + .quad 2150465744 + .quad 2150465768 + .quad 2150465792 + .quad 2150465816 + .quad 2150465840 + .quad 2150465896 + .quad 2150465952 + .quad 2150466008 + .quad 2150466064 + .quad 2150466088 + .quad 2150466112 + .quad 2150466168 + .quad 2150466200 + .quad 2150466256 + .quad 2150466280 + .quad 2150467392 + .quad 2150469488 + .quad 2150469496 + .quad 2150473728 + .quad 2150473728 + .quad 2150539264 + .quad 2150539264 + .quad 2150539304 + .quad 2150539328 + .quad 2150539368 + .quad 2150539488 + .quad 2150539512 + .quad 2150539536 + .quad 2150539560 + .quad 2150539584 + .quad 2150539608 + .quad 2150539624 + .quad 2150539648 + .quad 2150539672 + .quad 2150539696 + .quad 2150539720 + .quad 2150539760 + .quad 2150539784 + .quad 2150539808 + .quad 2150540208 + .quad 2150540264 + .quad 2190386152 + .quad 2190386168 + .quad 2190386208 + .quad 2190386304 + .quad 2190386432 + .quad 2190386440 + .quad 2190386448 + .quad 2190386449 + .quad 2190386456 + .quad 2190386464 + .quad 2190386472 + .quad 2190389248 + .quad 2190389248 +.globl symbol_index +symbol_index: + .quad 0 + .quad 8 + .quad 14 + .quad 26 + .quad 33 + .quad 40 + .quad 79 + .quad 91 + .quad 130 + .quad 169 + .quad 208 + .quad 247 + .quad 286 + .quad 325 + .quad 369 + .quad 413 + .quad 457 + .quad 501 + .quad 545 + .quad 589 + .quad 633 + .quad 677 + .quad 721 + .quad 765 + .quad 809 + .quad 852 + .quad 894 + .quad 935 + .quad 976 + .quad 1017 + .quad 1058 + .quad 1099 + .quad 1137 + .quad 1175 + .quad 1213 + .quad 1251 + .quad 1289 + .quad 1331 + .quad 1373 + .quad 1415 + .quad 1452 + .quad 1489 + .quad 1535 + .quad 1581 + .quad 1627 + .quad 1673 + .quad 1719 + .quad 1765 + .quad 1808 + .quad 1847 + .quad 1891 + .quad 1933 + .quad 1975 + .quad 2016 + .quad 2057 + .quad 2098 + .quad 2138 + .quad 2178 + .quad 2218 + .quad 2264 + .quad 2309 + .quad 2354 + .quad 2399 + .quad 2444 + .quad 2489 + .quad 2534 + .quad 2579 + .quad 2622 + .quad 2665 + .quad 2708 + .quad 2752 + .quad 2795 + .quad 2838 + .quad 2881 + .quad 2924 + .quad 2967 + .quad 3010 + .quad 3053 + .quad 3096 + .quad 3139 + .quad 3182 + .quad 3225 + .quad 3268 + .quad 3311 + .quad 3354 + .quad 3392 + .quad 3431 + .quad 3474 + .quad 3518 + .quad 3562 + .quad 3603 + .quad 3644 + .quad 3685 + .quad 3723 + .quad 3761 + .quad 3799 + .quad 3837 + .quad 3875 + .quad 3912 + .quad 3954 + .quad 4000 + .quad 4043 + .quad 4082 + .quad 4121 + .quad 4163 + .quad 4205 + .quad 4246 + .quad 4287 + .quad 4331 + .quad 4374 + .quad 4417 + .quad 4460 + .quad 4503 + .quad 4546 + .quad 4589 + .quad 4632 + .quad 4676 + .quad 4720 + .quad 4764 + .quad 4807 + .quad 4848 + .quad 4889 + .quad 4927 + .quad 4965 + .quad 5003 + .quad 5045 + .quad 5082 + .quad 5119 + .quad 5156 + .quad 5199 + .quad 5241 + .quad 5282 + .quad 5323 + .quad 5363 + .quad 5403 + .quad 5446 + .quad 5489 + .quad 5731 + .quad 5973 + .quad 6215 + .quad 6457 + .quad 6699 + .quad 6941 + .quad 7013 + .quad 7085 + .quad 7157 + .quad 7229 + .quad 7302 + .quad 7375 + .quad 7448 + .quad 7521 + .quad 7603 + .quad 7685 + .quad 7767 + .quad 7849 + .quad 7914 + .quad 7979 + .quad 8044 + .quad 8109 + .quad 8389 + .quad 8669 + .quad 8949 + .quad 9229 + .quad 9523 + .quad 9817 + .quad 10111 + .quad 10405 + .quad 10704 + .quad 11003 + .quad 11302 + .quad 11601 + .quad 11632 + .quad 11673 + .quad 11715 + .quad 11752 + .quad 11791 + .quad 11846 + .quad 11885 + .quad 11916 + .quad 11965 + .quad 12022 + .quad 12071 + .quad 12134 + .quad 12170 + .quad 12209 + .quad 12246 + .quad 12287 + .quad 12322 + .quad 12360 + .quad 12400 + .quad 12440 + .quad 12475 + .quad 12510 + .quad 12548 + .quad 12591 + .quad 12634 + .quad 12677 + .quad 12720 + .quad 12763 + .quad 12806 + .quad 12845 + .quad 12887 + .quad 12929 + .quad 12972 + .quad 13014 + .quad 13061 + .quad 13105 + .quad 13152 + .quad 13204 + .quad 13256 + .quad 13308 + .quad 13356 + .quad 13404 + .quad 13452 + .quad 13500 + .quad 13543 + .quad 13583 + .quad 13620 + .quad 13663 + .quad 13713 + .quad 13764 + .quad 13821 + .quad 13872 + .quad 13910 + .quad 13945 + .quad 13979 + .quad 14010 + .quad 14089 + .quad 14170 + .quad 14253 + .quad 14310 + .quad 14356 + .quad 14402 + .quad 14448 + .quad 14494 + .quad 14540 + .quad 14586 + .quad 14632 + .quad 14678 + .quad 14724 + .quad 14770 + .quad 14816 + .quad 14862 + .quad 14908 + .quad 14954 + .quad 15000 + .quad 15046 + .quad 15092 + .quad 15138 + .quad 15184 + .quad 15230 + .quad 15276 + .quad 15322 + .quad 15368 + .quad 15414 + .quad 15460 + .quad 15506 + .quad 15552 + .quad 15598 + .quad 15644 + .quad 15690 + .quad 15736 + .quad 15782 + .quad 15828 + .quad 15874 + .quad 15920 + .quad 15966 + .quad 16012 + .quad 16058 + .quad 16104 + .quad 16150 + .quad 16196 + .quad 16242 + .quad 16288 + .quad 16334 + .quad 16380 + .quad 16426 + .quad 16472 + .quad 16518 + .quad 16564 + .quad 16610 + .quad 16656 + .quad 16702 + .quad 16748 + .quad 16794 + .quad 16840 + .quad 16886 + .quad 16932 + .quad 16978 + .quad 17024 + .quad 17070 + .quad 17116 + .quad 17162 + .quad 17208 + .quad 17254 + .quad 17300 + .quad 17346 + .quad 17392 + .quad 17438 + .quad 17484 + .quad 17530 + .quad 17576 + .quad 17622 + .quad 17668 + .quad 17714 + .quad 17760 + .quad 17806 + .quad 17852 + .quad 17898 + .quad 17944 + .quad 17990 + .quad 18036 + .quad 18082 + .quad 18128 + .quad 18174 + .quad 18220 + .quad 18266 + .quad 18312 + .quad 18358 + .quad 18404 + .quad 18450 + .quad 18496 + .quad 18542 + .quad 18588 + .quad 18634 + .quad 18680 + .quad 18726 + .quad 18772 + .quad 18818 + .quad 18864 + .quad 18910 + .quad 18956 + .quad 19002 + .quad 19048 + .quad 19094 + .quad 19140 + .quad 19186 + .quad 19232 + .quad 19278 + .quad 19324 + .quad 19370 + .quad 19416 + .quad 19462 + .quad 19508 + .quad 19554 + .quad 19600 + .quad 19646 + .quad 19692 + .quad 19738 + .quad 19784 + .quad 19830 + .quad 19876 + .quad 19922 + .quad 19968 + .quad 20014 + .quad 20060 + .quad 20106 + .quad 20152 + .quad 20198 + .quad 20244 + .quad 20290 + .quad 20327 + .quad 20377 + .quad 20427 + .quad 20477 + .quad 20527 + .quad 20577 + .quad 20627 + .quad 20677 + .quad 20727 + .quad 20777 + .quad 20827 + .quad 20877 + .quad 20927 + .quad 20977 + .quad 21027 + .quad 21077 + .quad 21127 + .quad 21177 + .quad 21227 + .quad 21277 + .quad 21327 + .quad 21377 + .quad 21427 + .quad 21477 + .quad 21527 + .quad 21577 + .quad 21627 + .quad 21677 + .quad 21727 + .quad 21777 + .quad 21827 + .quad 21877 + .quad 21927 + .quad 21977 + .quad 22027 + .quad 22077 + .quad 22127 + .quad 22177 + .quad 22227 + .quad 22277 + .quad 22327 + .quad 22377 + .quad 22427 + .quad 22477 + .quad 22527 + .quad 22577 + .quad 22627 + .quad 22677 + .quad 22727 + .quad 22777 + .quad 22827 + .quad 22877 + .quad 22927 + .quad 22977 + .quad 23027 + .quad 23077 + .quad 23127 + .quad 23177 + .quad 23227 + .quad 23277 + .quad 23327 + .quad 23377 + .quad 23427 + .quad 23477 + .quad 23527 + .quad 23577 + .quad 23627 + .quad 23677 + .quad 23727 + .quad 23777 + .quad 23827 + .quad 23877 + .quad 23927 + .quad 23977 + .quad 24027 + .quad 24077 + .quad 24127 + .quad 24177 + .quad 24227 + .quad 24277 + .quad 24327 + .quad 24377 + .quad 24427 + .quad 24477 + .quad 24527 + .quad 24577 + .quad 24627 + .quad 24677 + .quad 24727 + .quad 24777 + .quad 24827 + .quad 24877 + .quad 24927 + .quad 24977 + .quad 25027 + .quad 25077 + .quad 25127 + .quad 25177 + .quad 25227 + .quad 25277 + .quad 25327 + .quad 25377 + .quad 25427 + .quad 25477 + .quad 25527 + .quad 25577 + .quad 25627 + .quad 25677 + .quad 25727 + .quad 25777 + .quad 25827 + .quad 25877 + .quad 25927 + .quad 25977 + .quad 26027 + .quad 26077 + .quad 26127 + .quad 26177 + .quad 26227 + .quad 26277 + .quad 26327 + .quad 26377 + .quad 26427 + .quad 26477 + .quad 26527 + .quad 26577 + .quad 26627 + .quad 26677 + .quad 26727 + .quad 26777 + .quad 26827 + .quad 26932 + .quad 27038 + .quad 27146 + .quad 27254 + .quad 27363 + .quad 27472 + .quad 27581 + .quad 27690 + .quad 27799 + .quad 27909 + .quad 28019 + .quad 28129 + .quad 28239 + .quad 28350 + .quad 28462 + .quad 28575 + .quad 28688 + .quad 28802 + .quad 28915 + .quad 29028 + .quad 29144 + .quad 29258 + .quad 29375 + .quad 29492 + .quad 29608 + .quad 29724 + .quad 29841 + .quad 29951 + .quad 30070 + .quad 30190 + .quad 30310 + .quad 30430 + .quad 30550 + .quad 30664 + .quad 30786 + .quad 30906 + .quad 31029 + .quad 31152 + .quad 31274 + .quad 31396 + .quad 31519 + .quad 31643 + .quad 31763 + .quad 31886 + .quad 32014 + .quad 32138 + .quad 32263 + .quad 32393 + .quad 32525 + .quad 32658 + .quad 32779 + .quad 32913 + .quad 33047 + .quad 33177 + .quad 33312 + .quad 33450 + .quad 33586 + .quad 33721 + .quad 33861 + .quad 34019 + .quad 34182 + .quad 34344 + .quad 34509 + .quad 34675 + .quad 34842 + .quad 35003 + .quad 35169 + .quad 35337 + .quad 35505 + .quad 35673 + .quad 35842 + .quad 36012 + .quad 36182 + .quad 36347 + .quad 36521 + .quad 36696 + .quad 36869 + .quad 37042 + .quad 37212 + .quad 37387 + .quad 37562 + .quad 37737 + .quad 37912 + .quad 38083 + .quad 38260 + .quad 38437 + .quad 38610 + .quad 38788 + .quad 38963 + .quad 39141 + .quad 39320 + .quad 39501 + .quad 39683 + .quad 39866 + .quad 40044 + .quad 40224 + .quad 40406 + .quad 40585 + .quad 40770 + .quad 40951 + .quad 41132 + .quad 41316 + .quad 41498 + .quad 41681 + .quad 41865 + .quad 42045 + .quad 42232 + .quad 42418 + .quad 42601 + .quad 42785 + .quad 42972 + .quad 43167 + .quad 43355 + .quad 43543 + .quad 43733 + .quad 43923 + .quad 44124 + .quad 44316 + .quad 44509 + .quad 44702 + .quad 44895 + .quad 45089 + .quad 45286 + .quad 45485 + .quad 45684 + .quad 45880 + .quad 46077 + .quad 46279 + .quad 46482 + .quad 46687 + .quad 46735 + .quad 46784 + .quad 46830 + .quad 46876 + .quad 46925 + .quad 46974 + .quad 47023 + .quad 47072 + .quad 47124 + .quad 47176 + .quad 47199 + .quad 47231 + .quad 47272 + .quad 47314 + .quad 47351 + .quad 47390 + .quad 47420 + .quad 47475 + .quad 47530 + .quad 47559 + .quad 47608 + .quad 47657 + .quad 47708 + .quad 47753 + .quad 47798 + .quad 47843 + .quad 47888 + .quad 47935 + .quad 47982 + .quad 48029 + .quad 48076 + .quad 48123 + .quad 48170 + .quad 48220 + .quad 48270 + .quad 48320 + .quad 48370 + .quad 48420 + .quad 48470 + .quad 48520 + .quad 48573 + .quad 48626 + .quad 48679 + .quad 48732 + .quad 48785 + .quad 48838 + .quad 48894 + .quad 48950 + .quad 49009 + .quad 49060 + .quad 49090 + .quad 49120 + .quad 49150 + .quad 49180 + .quad 49221 + .quad 49263 + .quad 49310 + .quad 49347 + .quad 49386 + .quad 49418 + .quad 49450 + .quad 49505 + .quad 49616 + .quad 49648 + .quad 49682 + .quad 49718 + .quad 49759 + .quad 49801 + .quad 49843 + .quad 49888 + .quad 49935 + .quad 49982 + .quad 50029 + .quad 50076 + .quad 50126 + .quad 50176 + .quad 50226 + .quad 50279 + .quad 50332 + .quad 50385 + .quad 50463 + .quad 50538 + .quad 50583 + .quad 50626 + .quad 50659 + .quad 50695 + .quad 50726 + .quad 50758 + .quad 50782 + .quad 50806 + .quad 50838 + .quad 50862 + .quad 50888 + .quad 50914 + .quad 50941 + .quad 50968 + .quad 51009 + .quad 51051 + .quad 51098 + .quad 51135 + .quad 51174 + .quad 51227 + .quad 51282 + .quad 51337 + .quad 51376 + .quad 51406 + .quad 51438 + .quad 51487 + .quad 51544 + .quad 51598 + .quad 51647 + .quad 51687 + .quad 51729 + .quad 51774 + .quad 51819 + .quad 51866 + .quad 51913 + .quad 51963 + .quad 52013 + .quad 52063 + .quad 52113 + .quad 52166 + .quad 52219 + .quad 52297 + .quad 52372 + .quad 52447 + .quad 52494 + .quad 52530 + .quad 52586 + .quad 52646 + .quad 52707 + .quad 52726 + .quad 52781 + .quad 52812 + .quad 52867 + .quad 52924 + .quad 52966 + .quad 53008 + .quad 53050 + .quad 53092 + .quad 53134 + .quad 53176 + .quad 53218 + .quad 53265 + .quad 53309 + .quad 53353 + .quad 53358 + .quad 53376 + .quad 53458 + .quad 53519 + .quad 53582 + .quad 53649 + .quad 53720 + .quad 53794 + .quad 53848 + .quad 53879 + .quad 53920 + .quad 53961 + .quad 54003 + .quad 54045 + .quad 54082 + .quad 54119 + .quad 54158 + .quad 54197 + .quad 54337 + .quad 54479 + .quad 54512 + .quad 54569 + .quad 54632 + .quad 54703 + .quad 54774 + .quad 54845 + .quad 54916 + .quad 54961 + .quad 55009 + .quad 55060 + .quad 55111 + .quad 55162 + .quad 55213 + .quad 55264 + .quad 55315 + .quad 55366 + .quad 55395 + .quad 55425 + .quad 55455 + .quad 55487 + .quad 55519 + .quad 55552 + .quad 55620 + .quad 55693 + .quad 55766 + .quad 55840 + .quad 55918 + .quad 55985 + .quad 56053 + .quad 56122 + .quad 56191 + .quad 56261 + .quad 56332 + .quad 56403 + .quad 56474 + .quad 56545 + .quad 56617 + .quad 56689 + .quad 56764 + .quad 56835 + .quad 56908 + .quad 56981 + .quad 57030 + .quad 57084 + .quad 57139 + .quad 57198 + .quad 57241 + .quad 57287 + .quad 57379 + .quad 57471 + .quad 57563 + .quad 57658 + .quad 57756 + .quad 57868 + .quad 57919 + .quad 57972 + .quad 58021 + .quad 58077 + .quad 58133 + .quad 58189 + .quad 58245 + .quad 58301 + .quad 58357 + .quad 58408 + .quad 58458 + .quad 58508 + .quad 58537 + .quad 58590 + .quad 58646 + .quad 58740 + .quad 58834 + .quad 58915 + .quad 58996 + .quad 59077 + .quad 59158 + .quad 59183 + .quad 59204 + .quad 59264 + .quad 59306 + .quad 59359 + .quad 59416 + .quad 59457 + .quad 59512 + .quad 59563 + .quad 59613 + .quad 59663 + .quad 59713 + .quad 59772 + .quad 59823 + .quad 59871 + .quad 59918 + .quad 59948 + .quad 59978 + .quad 60008 + .quad 60038 + .quad 60094 + .quad 60122 + .quad 60163 + .quad 60209 + .quad 60255 + .quad 60301 + .quad 60347 + .quad 60393 + .quad 60439 + .quad 60485 + .quad 60531 + .quad 60577 + .quad 60623 + .quad 60669 + .quad 60715 + .quad 60761 + .quad 60807 + .quad 60853 + .quad 60913 + .quad 60973 + .quad 61033 + .quad 61093 + .quad 61105 + .quad 61117 + .quad 61132 + .quad 61148 + .quad 61159 + .quad 61171 + .quad 61184 + .quad 61197 + .quad 61211 + .quad 61223 + .quad 61236 + .quad 61251 + .quad 61265 + .quad 61280 + .quad 61296 + .quad 61308 + .quad 61315 + .quad 61323 + .quad 61331 + .quad 61339 + .quad 61351 + .quad 61363 + .quad 61371 + .quad 61381 + .quad 61390 + .quad 61399 + .quad 61415 + .quad 61431 + .quad 61447 + .quad 61463 + .quad 61480 + .quad 61499 + .quad 61512 + .quad 61520 + .quad 61531 + .quad 61549 + .quad 61558 + .quad 61570 + .quad 61584 + .quad 61598 + .quad 61605 + .quad 61613 + .quad 61629 + .quad 61639 + .quad 61647 + .quad 61659 + .quad 61667 + .quad 61677 + .quad 61684 + .quad 61698 + .quad 61707 + .quad 61718 + .quad 61732 + .quad 61749 + .quad 61769 + .quad 61789 + .quad 61810 + .quad 61822 + .quad 61840 + .quad 61850 + .quad 61861 + .quad 61872 + .quad 61882 + .quad 61891 + .quad 61901 + .quad 61910 + .quad 61920 + .quad 61930 + .quad 61938 + .quad 61947 + .quad 61959 + .quad 61967 + .quad 61979 + .quad 61996 + .quad 62008 + .quad 62020 + .quad 62035 + .quad 62053 + .quad 62062 + .quad 62093 + .quad 62125 + .quad 62155 + .quad 62185 + .quad 62215 + .quad 62254 + .quad 62373 + .quad 62429 + .quad 62480 + .quad 62522 + .quad 62564 + .quad 62606 + .quad 62651 + .quad 62696 + .quad 62746 + .quad 62799 + .quad 62852 + .quad 62908 + .quad 62939 + .quad 62971 + .quad 63009 + .quad 63047 + .quad 63091 + .quad 63103 + .quad 63137 + .quad 63181 + .quad 63198 + .quad 63237 + .quad 63256 + .quad 63274 + .quad 63301 + .quad 63331 + .quad 63362 + .quad 63403 + .quad 63444 + .quad 63486 + .quad 63528 + .quad 63565 + .quad 63602 + .quad 63641 + .quad 63680 + .quad 63710 + .quad 63749 + .quad 63788 + .quad 63827 + .quad 63928 + .quad 64039 + .quad 64068 + .quad 64101 + .quad 64152 + .quad 64203 + .quad 64236 + .quad 64269 + .quad 64302 + .quad 64355 + .quad 64388 + .quad 64421 + .quad 64454 + .quad 64487 + .quad 64520 + .quad 64553 + .quad 64586 + .quad 64619 + .quad 64652 + .quad 64685 + .quad 64718 + .quad 64751 + .quad 64784 + .quad 64817 + .quad 64850 + .quad 64883 + .quad 64916 + .quad 64949 + .quad 64982 + .quad 65015 + .quad 65086 + .quad 65135 + .quad 65188 + .quad 65253 + .quad 65320 + .quad 65388 + .quad 65456 + .quad 65524 + .quad 65594 + .quad 65665 + .quad 65741 + .quad 65821 + .quad 65890 + .quad 65963 + .quad 66037 + .quad 66111 + .quad 66189 + .quad 66264 + .quad 66340 + .quad 66373 + .quad 66406 + .quad 66433 + .quad 66501 + .quad 66569 + .quad 66636 + .quad 66712 + .quad 66788 + .quad 66837 + .quad 66850 + .quad 66863 + .quad 66875 + .quad 66888 + .quad 66900 + .quad 66912 + .quad 66925 + .quad 66943 + .quad 66961 + .quad 66980 + .quad 66996 + .quad 67013 + .quad 67037 + .quad 67053 + .quad 67062 + .quad 67075 + .quad 67089 + .quad 67102 + .quad 67111 + .quad 67123 + .quad 67133 + .quad 67146 + .quad 67159 + .quad 67167 + .quad 67178 + .quad 67195 + .quad 67205 + .quad 67215 + .quad 67233 + .quad 67251 + .quad 67343 + .quad 67373 + .quad 67419 + .quad 67468 + .quad 67532 + .quad 67563 + .quad 67594 + .quad 67625 + .quad 67656 + .quad 67690 + .quad 67719 + .quad 67836 + .quad 67953 + .quad 68001 + .quad 68049 + .quad 68097 + .quad 68149 + .quad 68199 + .quad 68249 + .quad 68299 + .quad 68358 + .quad 68439 + .quad 68520 + .quad 68601 + .quad 68639 + .quad 68674 + .quad 68728 + .quad 68737 + .quad 68823 + .quad 68909 + .quad 68940 + .quad 68971 + .quad 69002 + .quad 69032 + .quad 69062 + .quad 69103 + .quad 69145 + .quad 69182 + .quad 69221 + .quad 69276 + .quad 69304 + .quad 69405 + .quad 69436 + .quad 69479 + .quad 69527 + .quad 69578 + .quad 69633 + .quad 69682 + .quad 69738 + .quad 69793 + .quad 69835 + .quad 69880 + .quad 69925 + .quad 69972 + .quad 70019 + .quad 70066 + .quad 70113 + .quad 70169 + .quad 70219 + .quad 70269 + .quad 70319 + .quad 70369 + .quad 70419 + .quad 70449 + .quad 70479 + .quad 70511 + .quad 70564 + .quad 70620 + .quad 70675 + .quad 70709 + .quad 70765 + .quad 70822 + .quad 70880 + .quad 70937 + .quad 71000 + .quad 71063 + .quad 71119 + .quad 71185 + .quad 71252 + .quad 71315 + .quad 71391 + .quad 71461 + .quad 71530 + .quad 71599 + .quad 71668 + .quad 71739 + .quad 71810 + .quad 71882 + .quad 71943 + .quad 71973 + .quad 72003 + .quad 72070 + .quad 72135 + .quad 72203 + .quad 72270 + .quad 72336 + .quad 72405 + .quad 72475 + .quad 72499 + .quad 72523 + .quad 72549 + .quad 72575 + .quad 72602 + .quad 72629 + .quad 72659 + .quad 72689 + .quad 72730 + .quad 72772 + .quad 72809 + .quad 72848 + .quad 72880 + .quad 72935 + .quad 73036 + .quad 73087 + .quad 73140 + .quad 73174 + .quad 73234 + .quad 73287 + .quad 73344 + .quad 73402 + .quad 73449 + .quad 73496 + .quad 73546 + .quad 73596 + .quad 73646 + .quad 73696 + .quad 73746 + .quad 73796 + .quad 73849 + .quad 73905 + .quad 73961 + .quad 74020 + .quad 74079 + .quad 74114 + .quad 74191 + .quad 74270 + .quad 74285 + .quad 74297 + .quad 74312 + .quad 74327 + .quad 74343 + .quad 74360 + .quad 74375 + .quad 74383 + .quad 74394 + .quad 74405 + .quad 74423 + .quad 74433 + .quad 74442 + .quad 74458 + .quad 74469 + .quad 74478 + .quad 74499 + .quad 74512 + .quad 74525 + .quad 74536 + .quad 74544 + .quad 74571 + .quad 74601 + .quad 74656 + .quad 74784 + .quad 74816 + .quad 74864 + .quad 74918 + .quad 74976 + .quad 75028 + .quad 75072 + .quad 75146 + .quad 75199 + .quad 75253 + .quad 75315 + .quad 75377 + .quad 75432 + .quad 75486 + .quad 75539 + .quad 75587 + .quad 75617 + .quad 75663 + .quad 75694 + .quad 75727 + .quad 75763 + .quad 75797 + .quad 75831 + .quad 75866 + .quad 75901 + .quad 75938 + .quad 75974 + .quad 76011 + .quad 76041 + .quad 76071 + .quad 76101 + .quad 76131 + .quad 76161 + .quad 76191 + .quad 76221 + .quad 76254 + .quad 76307 + .quad 76360 + .quad 76425 + .quad 76490 + .quad 76581 + .quad 76634 + .quad 76664 + .quad 76694 + .quad 76726 + .quad 76777 + .quad 76831 + .quad 76886 + .quad 76941 + .quad 77004 + .quad 77035 + .quad 77058 + .quad 77087 + .quad 77121 + .quad 77161 + .quad 77191 + .quad 77222 + .quad 77263 + .quad 77307 + .quad 77351 + .quad 77405 + .quad 77445 + .quad 77526 + .quad 77569 + .quad 77612 + .quad 77657 + .quad 77702 + .quad 77747 + .quad 77792 + .quad 77872 + .quad 77902 + .quad 77917 + .quad 77948 + .quad 77979 + .quad 78020 + .quad 78061 + .quad 78102 + .quad 78143 + .quad 78184 + .quad 78225 + .quad 78266 + .quad 78307 + .quad 78348 + .quad 78389 + .quad 78431 + .quad 78473 + .quad 78515 + .quad 78557 + .quad 78599 + .quad 78641 + .quad 78683 + .quad 78725 + .quad 78767 + .quad 78809 + .quad 78846 + .quad 78883 + .quad 78920 + .quad 78957 + .quad 78994 + .quad 79031 + .quad 79068 + .quad 79105 + .quad 79142 + .quad 79179 + .quad 79218 + .quad 79257 + .quad 79296 + .quad 79335 + .quad 79374 + .quad 79413 + .quad 79452 + .quad 79491 + .quad 79530 + .quad 79569 + .quad 79608 + .quad 79647 + .quad 79758 + .quad 79885 + .quad 80025 + .quad 80075 + .quad 80125 + .quad 80176 + .quad 80228 + .quad 80280 + .quad 80333 + .quad 80387 + .quad 80442 + .quad 80495 + .quad 80548 + .quad 80579 + .quad 80610 + .quad 80671 + .quad 80730 + .quad 80796 + .quad 80860 + .quad 80924 + .quad 80995 + .quad 81056 + .quad 81124 + .quad 81190 + .quad 81258 + .quad 81331 + .quad 81397 + .quad 81463 + .quad 81531 + .quad 81588 + .quad 81647 + .quad 81706 + .quad 81765 + .quad 81794 + .quad 81823 + .quad 81852 + .quad 81882 + .quad 81912 + .quad 81942 + .quad 81972 + .quad 82004 + .quad 82036 + .quad 82068 + .quad 82100 + .quad 82133 + .quad 82170 + .quad 82207 + .quad 82244 + .quad 82282 + .quad 82320 + .quad 82358 + .quad 82390 + .quad 82422 + .quad 82454 + .quad 82487 + .quad 82520 + .quad 82553 + .quad 82586 + .quad 82619 + .quad 82652 + .quad 82686 + .quad 82720 + .quad 82754 + .quad 82789 + .quad 82824 + .quad 82859 + .quad 82894 + .quad 82929 + .quad 82964 + .quad 83000 + .quad 83036 + .quad 83101 + .quad 83167 + .quad 83233 + .quad 83299 + .quad 83367 + .quad 83436 + .quad 83510 + .quad 83588 + .quad 83655 + .quad 83726 + .quad 83797 + .quad 83869 + .quad 83941 + .quad 84014 + .quad 84085 + .quad 84156 + .quad 84231 + .quad 84296 + .quad 84370 + .quad 84438 + .quad 84505 + .quad 84572 + .quad 84641 + .quad 84667 + .quad 84693 + .quad 84714 + .quad 84739 + .quad 84760 + .quad 84813 + .quad 84846 + .quad 84879 + .quad 84912 + .quad 84945 + .quad 84978 + .quad 85011 + .quad 85044 + .quad 85077 + .quad 85110 + .quad 85143 + .quad 85176 + .quad 85209 + .quad 85242 + .quad 85275 + .quad 85308 + .quad 85341 + .quad 85374 + .quad 85407 + .quad 85440 + .quad 85473 + .quad 85506 + .quad 85539 + .quad 85572 + .quad 85605 + .quad 85638 + .quad 85671 + .quad 85704 + .quad 85737 + .quad 85770 + .quad 85803 + .quad 85836 + .quad 85869 + .quad 85940 + .quad 85989 + .quad 86081 + .quad 86173 + .quad 86265 + .quad 86296 + .quad 86337 + .quad 86378 + .quad 86419 + .quad 86460 + .quad 86502 + .quad 86544 + .quad 86586 + .quad 86628 + .quad 86665 + .quad 86702 + .quad 86739 + .quad 86776 + .quad 86877 + .quad 86927 + .quad 86978 + .quad 87031 + .quad 87084 + .quad 87137 + .quad 87193 + .quad 87249 + .quad 87305 + .quad 87361 + .quad 87417 + .quad 87473 + .quad 87529 + .quad 87585 + .quad 87641 + .quad 87697 + .quad 87753 + .quad 87816 + .quad 87845 + .quad 87875 + .quad 87905 + .quad 87937 + .quad 87970 + .quad 88007 + .quad 88045 + .quad 88076 + .quad 88108 + .quad 88141 + .quad 88174 + .quad 88208 + .quad 88243 + .quad 88278 + .quad 88314 + .quad 88395 + .quad 88476 + .quad 88557 + .quad 88638 + .quad 88719 + .quad 88800 + .quad 88868 + .quad 88944 + .quad 89015 + .quad 89080 + .quad 89144 + .quad 89208 + .quad 89274 + .quad 89343 + .quad 89366 + .quad 89608 + .quad 89850 + .quad 90092 + .quad 90334 + .quad 90576 + .quad 90818 + .quad 91060 + .quad 91302 + .quad 91374 + .quad 91446 + .quad 91518 + .quad 91590 + .quad 91663 + .quad 91736 + .quad 91809 + .quad 91882 + .quad 91964 + .quad 92046 + .quad 92128 + .quad 92210 + .quad 92275 + .quad 92340 + .quad 92405 + .quad 92470 + .quad 92750 + .quad 93030 + .quad 93310 + .quad 93590 + .quad 93884 + .quad 94178 + .quad 94472 + .quad 94766 + .quad 95065 + .quad 95364 + .quad 95663 + .quad 95962 + .quad 96261 + .quad 96560 + .quad 96591 + .quad 96622 + .quad 96653 + .quad 96684 + .quad 96715 + .quad 96756 + .quad 96797 + .quad 96838 + .quad 96880 + .quad 96922 + .quad 96969 + .quad 97011 + .quad 97048 + .quad 97085 + .quad 97122 + .quad 97161 + .quad 97200 + .quad 97239 + .quad 97350 + .quad 97490 + .quad 97632 + .quad 97677 + .quad 97718 + .quad 97759 + .quad 97801 + .quad 97843 + .quad 97887 + .quad 97931 + .quad 98003 + .quad 98047 + .quad 98091 + .quad 98120 + .quad 98150 + .quad 98182 + .quad 98214 + .quad 98247 + .quad 98278 + .quad 98309 + .quad 98340 + .quad 98371 + .quad 98407 + .quad 98443 + .quad 98479 + .quad 98515 + .quad 98583 + .quad 98656 + .quad 98729 + .quad 98803 + .quad 98881 + .quad 98948 + .quad 99016 + .quad 99085 + .quad 99154 + .quad 99224 + .quad 99295 + .quad 99366 + .quad 99437 + .quad 99508 + .quad 99580 + .quad 99655 + .quad 99726 + .quad 99799 + .quad 99872 + .quad 99950 + .quad 100025 + .quad 100089 + .quad 100120 + .quad 100151 + .quad 100182 + .quad 100223 + .quad 100264 + .quad 100305 + .quad 100347 + .quad 100389 + .quad 100431 + .quad 100468 + .quad 100505 + .quad 100542 + .quad 100581 + .quad 100620 + .quad 100659 + .quad 100760 + .quad 100875 + .quad 100998 + .quad 101131 + .quad 101181 + .quad 101209 + .quad 101250 + .quad 101296 + .quad 101342 + .quad 101388 + .quad 101448 + .quad 101508 + .quad 101568 + .quad 101631 + .quad 101696 + .quad 101761 + .quad 101826 + .quad 101871 + .quad 101900 + .quad 101930 + .quad 101962 + .quad 101995 + .quad 102038 + .quad 102071 + .quad 102145 + .quad 102220 + .quad 102298 + .quad 102379 + .quad 102447 + .quad 102515 + .quad 102584 + .quad 102654 + .quad 102724 + .quad 102794 + .quad 102867 + .quad 102947 + .quad 103027 + .quad 103104 + .quad 103182 + .quad 103260 + .quad 103338 + .quad 103422 + .quad 103503 + .quad 103584 + .quad 103665 + .quad 103713 + .quad 103762 + .quad 103815 + .quad 103872 + .quad 103910 + .quad 103950 + .quad 103993 + .quad 104037 + .quad 104065 + .quad 104093 + .quad 104146 + .quad 104199 + .quad 104254 + .quad 104320 + .quad 104407 + .quad 104438 + .quad 104469 + .quad 104500 + .quad 104531 + .quad 104561 + .quad 104602 + .quad 104643 + .quad 104684 + .quad 104726 + .quad 104773 + .quad 104815 + .quad 104857 + .quad 104894 + .quad 104931 + .quad 104968 + .quad 105007 + .quad 105046 + .quad 105085 + .quad 105186 + .quad 105301 + .quad 105430 + .quad 105572 + .quad 105605 + .quad 105633 + .quad 105665 + .quad 105699 + .quad 105746 + .quad 105770 + .quad 105797 + .quad 105836 + .quad 105876 + .quad 105927 + .quad 105984 + .quad 106043 + .quad 106102 + .quad 106161 + .quad 106215 + .quad 106244 + .quad 106274 + .quad 106304 + .quad 106336 + .quad 106369 + .quad 106398 + .quad 106429 + .quad 106460 + .quad 106496 + .quad 106532 + .quad 106605 + .quad 106678 + .quad 106748 + .quad 106819 + .quad 106890 + .quad 106961 + .quad 107039 + .quad 107114 + .quad 107189 + .quad 107220 + .quad 107251 + .quad 107292 + .quad 107333 + .quad 107374 + .quad 107415 + .quad 107456 + .quad 107498 + .quad 107540 + .quad 107582 + .quad 107624 + .quad 107666 + .quad 107703 + .quad 107740 + .quad 107777 + .quad 107814 + .quad 107851 + .quad 107890 + .quad 107929 + .quad 107968 + .quad 108007 + .quad 108046 + .quad 108147 + .quad 108289 + .quad 108431 + .quad 108578 + .quad 108727 + .quad 108777 + .quad 108806 + .quad 108836 + .quad 108866 + .quad 108898 + .quad 108930 + .quad 108963 + .quad 109031 + .quad 109104 + .quad 109177 + .quad 109245 + .quad 109314 + .quad 109383 + .quad 109453 + .quad 109524 + .quad 109595 + .quad 109668 + .quad 109742 + .quad 109823 + .quad 109901 + .quad 109986 + .quad 110053 + .quad 110121 + .quad 110190 + .quad 110259 + .quad 110328 + .quad 110399 + .quad 110470 + .quad 110541 + .quad 110612 + .quad 110684 + .quad 110763 + .quad 110835 + .quad 110910 + .quad 110990 + .quad 111064 + .quad 111139 + .quad 111215 + .quad 111291 + .quad 111367 + .quad 111452 + .quad 111529 + .quad 111607 + .quad 111685 + .quad 111764 + .quad 111839 + .quad 111921 + .quad 112009 + .quad 112040 + .quad 112071 + .quad 112102 + .quad 112133 + .quad 112174 + .quad 112216 + .quad 112253 + .quad 112292 + .quad 112403 + .quad 112431 + .quad 112479 + .quad 112517 + .quad 112556 + .quad 112612 + .quad 112668 + .quad 112726 + .quad 112786 + .quad 112817 + .quad 112848 + .quad 112884 + .quad 112920 + .quad 112982 + .quad 113049 + .quad 113117 + .quad 113185 + .quad 113253 + .quad 113323 + .quad 113394 + .quad 113470 + .quad 113550 + .quad 113619 + .quad 113695 + .quad 113768 + .quad 113842 + .quad 113923 + .quad 113997 + .quad 114078 + .quad 114156 + .quad 114231 + .quad 114305 + .quad 114382 + .quad 114460 + .quad 114542 + .quad 114625 + .quad 114712 + .quad 114792 + .quad 114872 + .quad 114952 + .quad 115013 + .quad 115079 + .quad 115109 + .quad 115195 + .quad 115225 + .quad 115262 + .quad 115299 + .quad 115341 + .quad 115383 + .quad 115425 + .quad 115467 + .quad 115509 + .quad 115553 + .quad 115593 + .quad 115638 + .quad 115684 + .quad 115731 + .quad 115780 + .quad 115821 + .quad 115862 + .quad 115993 + .quad 116135 + .quad 116163 + .quad 116191 + .quad 116230 + .quad 116269 + .quad 116309 + .quad 116349 + .quad 116393 + .quad 116438 + .quad 116473 + .quad 116508 + .quad 116545 + .quad 116583 + .quad 116664 + .quad 116694 + .quad 116735 + .quad 116776 + .quad 116813 + .quad 116843 + .quad 116887 + .quad 116928 + .quad 116991 + .quad 117055 + .quad 117120 + .quad 117148 + .quad 117176 + .quad 117226 + .quad 117291 + .quad 117356 + .quad 117387 + .quad 117418 + .quad 117459 + .quad 117500 + .quad 117541 + .quad 117583 + .quad 117625 + .quad 117667 + .quad 117704 + .quad 117741 + .quad 117778 + .quad 117817 + .quad 117856 + .quad 117895 + .quad 117996 + .quad 118113 + .quad 118236 + .quad 118361 + .quad 118411 + .quad 118462 + .quad 118513 + .quad 118558 + .quad 118587 + .quad 118617 + .quad 118649 + .quad 118681 + .quad 118714 + .quad 118787 + .quad 118862 + .quad 118942 + .quad 119022 + .quad 119103 + .quad 119188 + .quad 119262 + .quad 119337 + .quad 119413 + .quad 119489 + .quad 119565 + .quad 119642 + .quad 119720 + .quad 119798 + .quad 119876 + .quad 119954 + .quad 120033 + .quad 120112 + .quad 120187 + .quad 120264 + .quad 120342 + .quad 120424 + .quad 120511 + .quad 120588 + .quad 120666 + .quad 120744 + .quad 120824 + .quad 120904 + .quad 120984 + .quad 121065 + .quad 121096 + .quad 121137 + .quad 121178 + .quad 121219 + .quad 121260 + .quad 121301 + .quad 121342 + .quad 121384 + .quad 121426 + .quad 121468 + .quad 121510 + .quad 121552 + .quad 121594 + .quad 121631 + .quad 121668 + .quad 121705 + .quad 121742 + .quad 121779 + .quad 121816 + .quad 121855 + .quad 121894 + .quad 121933 + .quad 121972 + .quad 122011 + .quad 122050 + .quad 122079 + .quad 122107 + .quad 122146 + .quad 122247 + .quad 122362 + .quad 122489 + .quad 122616 + .quad 122749 + .quad 122896 + .quad 122937 + .quad 122986 + .quad 123037 + .quad 123105 + .quad 123164 + .quad 123223 + .quad 123280 + .quad 123339 + .quad 123398 + .quad 123463 + .quad 123528 + .quad 123557 + .quad 123587 + .quad 123617 + .quad 123649 + .quad 123682 + .quad 123759 + .quad 123839 + .quad 123917 + .quad 123995 + .quad 124016 + .quad 124037 + .quad 124085 + .quad 124116 + .quad 124147 + .quad 124178 + .quad 124208 + .quad 124238 + .quad 124268 + .quad 124298 + .quad 124328 + .quad 124369 + .quad 124411 + .quad 124448 + .quad 124487 + .quad 124519 + .quad 124551 + .quad 124657 + .quad 124768 + .quad 124816 + .quad 124867 + .quad 124916 + .quad 124945 + .quad 124973 + .quad 125004 + .quad 125035 + .quad 125071 + .quad 125107 + .quad 125185 + .quad 125260 + .quad 125341 + .quad 125422 + .quad 125510 + .quad 125599 + .quad 125692 + .quad 125774 + .quad 125860 + .quad 125946 + .quad 126032 + .quad 126119 + .quad 126206 + .quad 126256 + .quad 126284 + .quad 126335 + .quad 126387 + .quad 126441 + .quad 126496 + .quad 126548 + .quad 126600 + .quad 126651 + .quad 126706 + .quad 126758 + .quad 126818 + .quad 126878 + .quad 126931 + .quad 126983 + .quad 127037 + .quad 127092 + .quad 127150 + .quad 127208 + .quad 127264 + .quad 127315 + .quad 127371 + .quad 127421 + .quad 127497 + .quad 127576 + .quad 127651 + .quad 127729 + .quad 127769 + .quad 127809 + .quad 127862 + .quad 127902 + .quad 127948 + .quad 127996 + .quad 128048 + .quad 128100 + .quad 128157 + .quad 128217 + .quad 128283 + .quad 128332 + .quad 128394 + .quad 128457 + .quad 128521 + .quad 128590 + .quad 128649 + .quad 128722 + .quad 128798 + .quad 128877 + .quad 128958 + .quad 129041 + .quad 129129 + .quad 129150 + .quad 129176 + .quad 129210 + .quad 129237 + .quad 129290 + .quad 129320 + .quad 129353 + .quad 129386 + .quad 129419 + .quad 129452 + .quad 129485 + .quad 129518 + .quad 129551 + .quad 129614 + .quad 129678 + .quad 129738 + .quad 129799 + .quad 129829 + .quad 129883 + .quad 129945 + .quad 130004 + .quad 130063 + .quad 130112 + .quad 130161 + .quad 130203 + .quad 130245 + .quad 130287 + .quad 130329 + .quad 130371 + .quad 130413 + .quad 130455 + .quad 130486 + .quad 130516 + .quad 130546 + .quad 130578 + .quad 130610 + .quad 130641 + .quad 130674 + .quad 130737 + .quad 130801 + .quad 130861 + .quad 130922 + .quad 130988 + .quad 131053 + .quad 131115 + .quad 131176 + .quad 131238 + .quad 131297 + .quad 131325 + .quad 131371 + .quad 131403 + .quad 131442 + .quad 131484 + .quad 131526 + .quad 131579 + .quad 131613 + .quad 131648 + .quad 131890 + .quad 132132 + .quad 132165 + .quad 132193 + .quad 132253 + .quad 132345 + .quad 132401 + .quad 132422 + .quad 132457 + .quad 132469 + .quad 132480 + .quad 132522 + .quad 132573 + .quad 132624 + .quad 132675 + .quad 132708 + .quad 132767 + .quad 132832 + .quad 132909 + .quad 132985 + .quad 133062 + .quad 133111 + .quad 133139 + .quad 133185 + .quad 133231 + .quad 133277 + .quad 133336 + .quad 133395 + .quad 133438 + .quad 133481 + .quad 133524 + .quad 133567 + .quad 133615 + .quad 133664 + .quad 133713 + .quad 133762 + .quad 133829 + .quad 133882 + .quad 133912 + .quad 133983 + .quad 134014 + .quad 134045 + .quad 134110 + .quad 134135 + .quad 134194 + .quad 134253 + .quad 134318 + .quad 134390 + .quad 134454 + .quad 134482 + .quad 134530 + .quad 134599 + .quad 134644 + .quad 134723 + .quad 134815 + .quad 134910 + .quad 134988 + .quad 135063 + .quad 135137 + .quad 135212 + .quad 135245 + .quad 135314 + .quad 135361 + .quad 135444 + .quad 135528 + .quad 135611 + .quad 135662 + .quad 135752 + .quad 135843 + .quad 135928 + .quad 136014 + .quad 136038 + .quad 136074 + .quad 136100 + .quad 136130 + .quad 136176 + .quad 136233 + .quad 136263 + .quad 136293 + .quad 136341 + .quad 136410 + .quad 136446 + .quad 136521 + .quad 136592 + .quad 136636 + .quad 136706 + .quad 136776 + .quad 136838 + .quad 136901 + .quad 136950 + .quad 137001 + .quad 137062 + .quad 137123 + .quad 137185 + .quad 137246 + .quad 137286 + .quad 137370 + .quad 137423 + .quad 137453 + .quad 137525 + .quad 137573 + .quad 137617 + .quad 137645 + .quad 137675 + .quad 137705 + .quad 137737 + .quad 137787 + .quad 137853 + .quad 137899 + .quad 137943 + .quad 137963 + .quad 138003 + .quad 138034 + .quad 138077 + .quad 138128 + .quad 138156 + .quad 138202 + .quad 138264 + .quad 138332 + .quad 138391 + .quad 138449 + .quad 138515 + .quad 138568 + .quad 138621 + .quad 138651 + .quad 138681 + .quad 138736 + .quad 138768 + .quad 138811 + .quad 138855 + .quad 138907 + .quad 138940 + .quad 138970 + .quad 139002 + .quad 139034 + .quad 139068 + .quad 139098 + .quad 139128 + .quad 139158 + .quad 139196 + .quad 139253 + .quad 139286 + .quad 139350 + .quad 139434 + .quad 139487 + .quad 139537 + .quad 139587 + .quad 139637 + .quad 139687 + .quad 139741 + .quad 139795 + .quad 139849 + .quad 139903 + .quad 139957 + .quad 140011 + .quad 140065 + .quad 140119 + .quad 140173 + .quad 140218 + .quad 140270 + .quad 140339 + .quad 140403 + .quad 140470 + .quad 140534 + .quad 140598 + .quad 140662 + .quad 140722 + .quad 140756 + .quad 140794 + .quad 140833 + .quad 140896 + .quad 140959 + .quad 141022 + .quad 141085 + .quad 141148 + .quad 141211 + .quad 141283 + .quad 141312 + .quad 141348 + .quad 141383 + .quad 141413 + .quad 141446 + .quad 141481 + .quad 141514 + .quad 141544 + .quad 141578 + .quad 141608 + .quad 141643 + .quad 141700 + .quad 141807 + .quad 141879 + .quad 141919 + .quad 141962 + .quad 142007 + .quad 142054 + .quad 142097 + .quad 142153 + .quad 142195 + .quad 142237 + .quad 142279 + .quad 142321 + .quad 142371 + .quad 142426 + .quad 142469 + .quad 142508 + .quad 142540 + .quad 142570 + .quad 142600 + .quad 142632 + .quad 142663 + .quad 142695 + .quad 142728 + .quad 142760 + .quad 142793 + .quad 142846 + .quad 142903 + .quad 143002 + .quad 143065 + .quad 143100 + .quad 143141 + .quad 143184 + .quad 143227 + .quad 143255 + .quad 143301 + .quad 143347 + .quad 143383 + .quad 143414 + .quad 143445 + .quad 143503 + .quad 143533 + .quad 143564 + .quad 143595 + .quad 143626 + .quad 143677 + .quad 143729 + .quad 143771 + .quad 143789 + .quad 143814 + .quad 143867 + .quad 143920 + .quad 143977 + .quad 144036 + .quad 144080 + .quad 144130 + .quad 144166 + .quad 144202 + .quad 144243 + .quad 144284 + .quad 144324 + .quad 144364 + .quad 144404 + .quad 144442 + .quad 144480 + .quad 144526 + .quad 144572 + .quad 144619 + .quad 144674 + .quad 144727 + .quad 144769 + .quad 144807 + .quad 144838 + .quad 144870 + .quad 144902 + .quad 144932 + .quad 145012 + .quad 145071 + .quad 145140 + .quad 145209 + .quad 145271 + .quad 145308 + .quad 145344 + .quad 145376 + .quad 145413 + .quad 145444 + .quad 145498 + .quad 145555 + .quad 145659 + .quad 145755 + .quad 145851 + .quad 145913 + .quad 145980 + .quad 146038 + .quad 146092 + .quad 146148 + .quad 146203 + .quad 146252 + .quad 146308 + .quad 146363 + .quad 146403 + .quad 146471 + .quad 146574 + .quad 146684 + .quad 146714 + .quad 146761 + .quad 146815 + .quad 146871 + .quad 146933 + .quad 146996 + .quad 147065 + .quad 147124 + .quad 147204 + .quad 147283 + .quad 147318 + .quad 147352 + .quad 147415 + .quad 147453 + .quad 147493 + .quad 147534 + .quad 147572 + .quad 147604 + .quad 147634 + .quad 147688 + .quad 147726 + .quad 147764 + .quad 147820 + .quad 147877 + .quad 147933 + .quad 147962 + .quad 148019 + .quad 148082 + .quad 148132 + .quad 148192 + .quad 148257 + .quad 148311 + .quad 148362 + .quad 148412 + .quad 148470 + .quad 148528 + .quad 148586 + .quad 148644 + .quad 148707 + .quad 148767 + .quad 148827 + .quad 148891 + .quad 148939 + .quad 148969 + .quad 148999 + .quad 149031 + .quad 149085 + .quad 149126 + .quad 149184 + .quad 149217 + .quad 149249 + .quad 149312 + .quad 149368 + .quad 149398 + .quad 149428 + .quad 149458 + .quad 149488 + .quad 149518 + .quad 149548 + .quad 149580 + .quad 149612 + .quad 149665 + .quad 149697 + .quad 149742 + .quad 149804 + .quad 149856 + .quad 149895 + .quad 149934 + .quad 149968 + .quad 149998 + .quad 150051 + .quad 150144 + .quad 150174 + .quad 150204 + .quad 150241 + .quad 150277 + .quad 150312 + .quad 150346 + .quad 150400 + .quad 150452 + .quad 150506 + .quad 150538 + .quad 150603 + .quad 150671 + .quad 150715 + .quad 150762 + .quad 150793 + .quad 150863 + .quad 150911 + .quad 150957 + .quad 151002 + .quad 151051 + .quad 151089 + .quad 151121 + .quad 151151 + .quad 151204 + .quad 151233 + .quad 151258 + .quad 151298 + .quad 151339 + .quad 151368 + .quad 151458 + .quad 151549 + .quad 151625 + .quad 151701 + .quad 151779 + .quad 151858 + .quad 151938 + .quad 152018 + .quad 152098 + .quad 152178 + .quad 152259 + .quad 152341 + .quad 152425 + .quad 152510 + .quad 152570 + .quad 152636 + .quad 152666 + .quad 152696 + .quad 152726 + .quad 152755 + .quad 152786 + .quad 152817 + .quad 152848 + .quad 152900 + .quad 152949 + .quad 152998 + .quad 153047 + .quad 153096 + .quad 153145 + .quad 153194 + .quad 153243 + .quad 153294 + .quad 153345 + .quad 153396 + .quad 153447 + .quad 153498 + .quad 153549 + .quad 153600 + .quad 153627 + .quad 153654 + .quad 153709 + .quad 153741 + .quad 153775 + .quad 153808 + .quad 153821 + .quad 153833 + .quad 153891 + .quad 153924 + .quad 153999 + .quad 154076 + .quad 154163 + .quad 154233 + .quad 154305 + .quad 154336 + .quad 154391 + .quad 154430 + .quad 154481 + .quad 154509 + .quad 154555 + .quad 154594 + .quad 154633 + .quad 154688 + .quad 154727 + .quad 154784 + .quad 154821 + .quad 154843 + .quad 154872 + .quad 154933 + .quad 154963 + .quad 154993 + .quad 155026 + .quad 155057 + .quad 155075 + .quad 155131 + .quad 155187 + .quad 155243 + .quad 155267 + .quad 155280 + .quad 155295 + .quad 155310 + .quad 155330 + .quad 155572 + .quad 155814 + .quad 155886 + .quad 155959 + .quad 156041 + .quad 156106 + .quad 156386 + .quad 156680 + .quad 156722 + .quad 156764 + .quad 156831 + .quad 156850 + .quad 156867 + .quad 156884 + .quad 156909 + .quad 156973 + .quad 157039 + .quad 157069 + .quad 157102 + .quad 157154 + .quad 157208 + .quad 157265 + .quad 157319 + .quad 157376 + .quad 157443 + .quad 157500 + .quad 157560 + .quad 157618 + .quad 157673 + .quad 157775 + .quad 157827 + .quad 157885 + .quad 157987 + .quad 158098 + .quad 158210 + .quad 158315 + .quad 158412 + .quad 158513 + .quad 158623 + .quad 158723 + .quad 158825 + .quad 158926 + .quad 159030 + .quad 159110 + .quad 159182 + .quad 159252 + .quad 159282 + .quad 159377 + .quad 159444 + .quad 159472 + .quad 159500 + .quad 159528 + .quad 159558 + .quad 159588 + .quad 159618 + .quad 159651 + .quad 159704 + .quad 159734 + .quad 159766 + .quad 159835 + .quad 159884 + .quad 159914 + .quad 159967 + .quad 160020 + .quad 160050 + .quad 160080 + .quad 160145 + .quad 160209 + .quad 160276 + .quad 160337 + .quad 160409 + .quad 160439 + .quad 160469 + .quad 160524 + .quad 160554 + .quad 160585 + .quad 160625 + .quad 160714 + .quad 160781 + .quad 160859 + .quad 160924 + .quad 160975 + .quad 161031 + .quad 161087 + .quad 161141 + .quad 161195 + .quad 161218 + .quad 161243 + .quad 161281 + .quad 161318 + .quad 161363 + .quad 161400 + .quad 161482 + .quad 161569 + .quad 161605 + .quad 161658 + .quad 161703 + .quad 161744 + .quad 161774 + .quad 161804 + .quad 161834 + .quad 161864 + .quad 161894 + .quad 161924 + .quad 161954 + .quad 162007 + .quad 162060 + .quad 162113 + .quad 162141 + .quad 162201 + .quad 162243 + .quad 162293 + .quad 162329 + .quad 162386 + .quad 162444 + .quad 162499 + .quad 162559 + .quad 162627 + .quad 162657 + .quad 162687 + .quad 162739 + .quad 162792 + .quad 162845 + .quad 162874 + .quad 162904 + .quad 162934 + .quad 162995 + .quad 163028 + .quad 163066 + .quad 163106 + .quad 163150 + .quad 163201 + .quad 163248 + .quad 163308 + .quad 163370 + .quad 163428 + .quad 163488 + .quad 163585 + .quad 163628 + .quad 163677 + .quad 163728 + .quad 163780 + .quad 163834 + .quad 163879 + .quad 163911 + .quad 163938 + .quad 163965 + .quad 163993 + .quad 164021 + .quad 164051 + .quad 164102 + .quad 164167 + .quad 164217 + .quad 164245 + .quad 164274 + .quad 164305 + .quad 164340 + .quad 164371 + .quad 164402 + .quad 164435 + .quad 164465 + .quad 164496 + .quad 164529 + .quad 164561 + .quad 164590 + .quad 164620 + .quad 164651 + .quad 164685 + .quad 164719 + .quad 164753 + .quad 164788 + .quad 164817 + .quad 164849 + .quad 164879 + .quad 164908 + .quad 164961 + .quad 165014 + .quad 165069 + .quad 165099 + .quad 165129 + .quad 165194 + .quad 165229 + .quad 165285 + .quad 165340 + .quad 165393 + .quad 165423 + .quad 165453 + .quad 165483 + .quad 165513 + .quad 165545 + .quad 165571 + .quad 165599 + .quad 165627 + .quad 165687 + .quad 165741 + .quad 165793 + .quad 165824 + .quad 165857 + .quad 165910 + .quad 165963 + .quad 165989 + .quad 166017 + .quad 166048 + .quad 166081 + .quad 166114 + .quad 166147 + .quad 166190 + .quad 166296 + .quad 166338 + .quad 166399 + .quad 166449 + .quad 166479 + .quad 166532 + .quad 166585 + .quad 166638 + .quad 166668 + .quad 166698 + .quad 166728 + .quad 166778 + .quad 166826 + .quad 166874 + .quad 166924 + .quad 166970 + .quad 167023 + .quad 167077 + .quad 167130 + .quad 167179 + .quad 167234 + .quad 167283 + .quad 167333 + .quad 167382 + .quad 167431 + .quad 167485 + .quad 167532 + .quad 167585 + .quad 167615 + .quad 167644 + .quad 167716 + .quad 167803 + .quad 167857 + .quad 167908 + .quad 167938 + .quad 167968 + .quad 167998 + .quad 168053 + .quad 168083 + .quad 168114 + .quad 168147 + .quad 168180 + .quad 168263 + .quad 168311 + .quad 168362 + .quad 168414 + .quad 168469 + .quad 168501 + .quad 168529 + .quad 168575 + .quad 168650 + .quad 168711 + .quad 168777 + .quad 168841 + .quad 168871 + .quad 168960 + .quad 168998 + .quad 169041 + .quad 169088 + .quad 169131 + .quad 169179 + .quad 169224 + .quad 169281 + .quad 169396 + .quad 169444 + .quad 169496 + .quad 169547 + .quad 169602 + .quad 169661 + .quad 169722 + .quad 169782 + .quad 169843 + .quad 169907 + .quad 169974 + .quad 170023 + .quad 170074 + .quad 170104 + .quad 170134 + .quad 170166 + .quad 170198 + .quad 170227 + .quad 170255 + .quad 170287 + .quad 170330 + .quad 170361 + .quad 170403 + .quad 170445 + .quad 170496 + .quad 170555 + .quad 170582 + .quad 170615 + .quad 170671 + .quad 170688 + .quad 170698 + .quad 170753 + .quad 170804 + .quad 170857 + .quad 170888 + .quad 170902 + .quad 170929 + .quad 170961 + .quad 171001 + .quad 171044 + .quad 171098 + .quad 171154 + .quad 171193 + .quad 171233 + .quad 171262 + .quad 171286 + .quad 171317 + .quad 171348 + .quad 171369 + .quad 171398 + .quad 171429 + .quad 171455 + .quad 171474 + .quad 171489 + .quad 171504 + .quad 171524 + .quad 171544 + .quad 171568 + .quad 171609 + .quad 171642 + .quad 171680 + .quad 171719 + .quad 171749 + .quad 171779 + .quad 171810 + .quad 171834 + .quad 171861 + .quad 171888 + .quad 171915 + .quad 171943 + .quad 171975 + .quad 172021 + .quad 172069 + .quad 172095 + .quad 172161 + .quad 172226 + .quad 172260 + .quad 172290 + .quad 172320 + .quad 172351 + .quad 172408 + .quad 172439 + .quad 172480 + .quad 172519 + .quad 172558 + .quad 172599 + .quad 172638 + .quad 172666 + .quad 172694 + .quad 172737 + .quad 172785 + .quad 172845 + .quad 172891 + .quad 172919 + .quad 172953 + .quad 172986 + .quad 172996 + .quad 173029 + .quad 173068 + .quad 173096 + .quad 173149 + .quad 173204 + .quad 173260 + .quad 173304 + .quad 173334 + .quad 173365 + .quad 173406 + .quad 173446 + .quad 173484 + .quad 173518 + .quad 173554 + .quad 173570 + .quad 173594 + .quad 173641 + .quad 173680 + .quad 173773 + .quad 173816 + .quad 173842 + .quad 173898 + .quad 173929 + .quad 174013 + .quad 174059 + .quad 174124 + .quad 174175 + .quad 174229 + .quad 174264 + .quad 174307 + .quad 174358 + .quad 174435 + .quad 174512 + .quad 174589 + .quad 174666 + .quad 174724 + .quad 174782 + .quad 174846 + .quad 174908 + .quad 174974 + .quad 175040 + .quad 175068 + .quad 175132 + .quad 175159 + .quad 175195 + .quad 175218 + .quad 175254 + .quad 175285 + .quad 175322 + .quad 175350 + .quad 175415 + .quad 175481 + .quad 175521 + .quad 175562 + .quad 175601 + .quad 175641 + .quad 175680 + .quad 175717 + .quad 175755 + .quad 175794 + .quad 175823 + .quad 175852 + .quad 175881 + .quad 175910 + .quad 175938 + .quad 175966 + .quad 175994 + .quad 176022 + .quad 176050 + .quad 176100 + .quad 176117 + .quad 176152 + .quad 176201 + .quad 176227 + .quad 176259 + .quad 176313 + .quad 176345 + .quad 176399 + .quad 176434 + .quad 176483 + .quad 176532 + .quad 176581 + .quad 176630 + .quad 176679 + .quad 176713 + .quad 176761 + .quad 176809 + .quad 176842 + .quad 176876 + .quad 176907 + .quad 176940 + .quad 176972 + .quad 177006 + .quad 177035 + .quad 177071 + .quad 177100 + .quad 177147 + .quad 177192 + .quad 177235 + .quad 177295 + .quad 177326 + .quad 177359 + .quad 177416 + .quad 177453 + .quad 177532 + .quad 177560 + .quad 177591 + .quad 177623 + .quad 177662 + .quad 177700 + .quad 177755 + .quad 177810 + .quad 177865 + .quad 177920 + .quad 177976 + .quad 178032 + .quad 178088 + .quad 178144 + .quad 178200 + .quad 178256 + .quad 178312 + .quad 178368 + .quad 178422 + .quad 178476 + .quad 178532 + .quad 178588 + .quad 178644 + .quad 178700 + .quad 178758 + .quad 178816 + .quad 178872 + .quad 178928 + .quad 178986 + .quad 179044 + .quad 179096 + .quad 179149 + .quad 179178 + .quad 179237 + .quad 179297 + .quad 179357 + .quad 179417 + .quad 179477 + .quad 179539 + .quad 179599 + .quad 179661 + .quad 179705 + .quad 179735 + .quad 179765 + .quad 179795 + .quad 179825 + .quad 179857 + .quad 179889 + .quad 179921 + .quad 179954 + .quad 180009 + .quad 180062 + .quad 180093 + .quad 180125 + .quad 180156 + .quad 180187 + .quad 180194 + .quad 180203 + .quad 180261 + .quad 180268 + .quad 180276 + .quad 180283 + .quad 180289 + .quad 180297 + .quad 180328 + .quad 180359 + .quad 180391 + .quad 180397 + .quad 180403 + .quad 180409 + .quad 180430 + .quad 180494 + .quad 180548 + .quad 180556 + .quad 180595 + .quad 180601 + .quad 180607 + .quad 180646 + .quad 180685 + .quad 180724 + .quad 180763 + .quad 180802 + .quad 180841 + .quad 180885 + .quad 180929 + .quad 180973 + .quad 181017 + .quad 181061 + .quad 181105 + .quad 181149 + .quad 181193 + .quad 181237 + .quad 181281 + .quad 181325 + .quad 181368 + .quad 181410 + .quad 181451 + .quad 181492 + .quad 181533 + .quad 181574 + .quad 181615 + .quad 181653 + .quad 181691 + .quad 181729 + .quad 181767 + .quad 181805 + .quad 181847 + .quad 181889 + .quad 181931 + .quad 181968 + .quad 182005 + .quad 182051 + .quad 182097 + .quad 182143 + .quad 182189 + .quad 182235 + .quad 182281 + .quad 182324 + .quad 182363 + .quad 182407 + .quad 182449 + .quad 182491 + .quad 182532 + .quad 182573 + .quad 182614 + .quad 182654 + .quad 182694 + .quad 182734 + .quad 182780 + .quad 182825 + .quad 182870 + .quad 182915 + .quad 182960 + .quad 183005 + .quad 183050 + .quad 183095 + .quad 183138 + .quad 183181 + .quad 183224 + .quad 183268 + .quad 183311 + .quad 183354 + .quad 183397 + .quad 183440 + .quad 183483 + .quad 183526 + .quad 183569 + .quad 183612 + .quad 183655 + .quad 183698 + .quad 183741 + .quad 183784 + .quad 183827 + .quad 183870 + .quad 183908 + .quad 183947 + .quad 183990 + .quad 184034 + .quad 184078 + .quad 184119 + .quad 184160 + .quad 184201 + .quad 184239 + .quad 184277 + .quad 184315 + .quad 184353 + .quad 184391 + .quad 184428 + .quad 184470 + .quad 184516 + .quad 184559 + .quad 184598 + .quad 184637 + .quad 184679 + .quad 184721 + .quad 184762 + .quad 184803 + .quad 184847 + .quad 184890 + .quad 184933 + .quad 184976 + .quad 185019 + .quad 185062 + .quad 185105 + .quad 185148 + .quad 185192 + .quad 185236 + .quad 185280 + .quad 185323 + .quad 185364 + .quad 185405 + .quad 185443 + .quad 185481 + .quad 185519 + .quad 185561 + .quad 185598 + .quad 185635 + .quad 185672 + .quad 185715 + .quad 185757 + .quad 185798 + .quad 185839 + .quad 185879 + .quad 185919 + .quad 185962 + .quad 186005 + .quad 186037 + .quad 186043 + .quad 186069 + .quad 186113 + .quad 186157 + .quad 186201 + .quad 186245 + .quad 186289 + .quad 186333 + .quad 186377 + .quad 186426 + .quad 186475 + .quad 186524 + .quad 186573 + .quad 186622 + .quad 186671 + .quad 186720 + .quad 186769 + .quad 186818 + .quad 186867 + .quad 186916 + .quad 186964 + .quad 187011 + .quad 187057 + .quad 187103 + .quad 187149 + .quad 187195 + .quad 187241 + .quad 187284 + .quad 187327 + .quad 187370 + .quad 187413 + .quad 187456 + .quad 187503 + .quad 187550 + .quad 187597 + .quad 187639 + .quad 187681 + .quad 187732 + .quad 187783 + .quad 187834 + .quad 187885 + .quad 187936 + .quad 187987 + .quad 188035 + .quad 188079 + .quad 188128 + .quad 188175 + .quad 188222 + .quad 188268 + .quad 188314 + .quad 188360 + .quad 188405 + .quad 188450 + .quad 188495 + .quad 188546 + .quad 188596 + .quad 188646 + .quad 188696 + .quad 188746 + .quad 188796 + .quad 188846 + .quad 188896 + .quad 188944 + .quad 188992 + .quad 189040 + .quad 189089 + .quad 189137 + .quad 189185 + .quad 189233 + .quad 189281 + .quad 189329 + .quad 189377 + .quad 189425 + .quad 189473 + .quad 189521 + .quad 189569 + .quad 189617 + .quad 189665 + .quad 189713 + .quad 189761 + .quad 189804 + .quad 189843 + .quad 189887 + .quad 189935 + .quad 189984 + .quad 190033 + .quad 190079 + .quad 190125 + .quad 190171 + .quad 190214 + .quad 190257 + .quad 190300 + .quad 190343 + .quad 190386 + .quad 190428 + .quad 190475 + .quad 190526 + .quad 190574 + .quad 190618 + .quad 190662 + .quad 190709 + .quad 190756 + .quad 190802 + .quad 190848 + .quad 190897 + .quad 190945 + .quad 190993 + .quad 191041 + .quad 191089 + .quad 191137 + .quad 191185 + .quad 191233 + .quad 191258 + .quad 191284 + .quad 191311 + .quad 191360 + .quad 191409 + .quad 191458 + .quad 191506 + .quad 191552 + .quad 191598 + .quad 191641 + .quad 191684 + .quad 191727 + .quad 191774 + .quad 191816 + .quad 191858 + .quad 191900 + .quad 191948 + .quad 191995 + .quad 192041 + .quad 192087 + .quad 192132 + .quad 192177 + .quad 192225 + .quad 192273 + .quad 192291 + .quad 192319 + .quad 192327 + .quad 192363 + .quad 192402 + .quad 192441 + .quad 192461 + .quad 192486 + .quad 192518 + .quad 192541 + .quad 192561 + .quad 192577 + .quad 192591 + .quad 192605 + .quad 192641 + .quad 192647 + .quad 192680 + .quad 192685 + .quad 192705 + .quad 192734 + .quad 192765 + .quad 192791 + .quad 192811 + .quad 192830 + .quad 192857 + .quad 192882 + .quad 192911 + .quad 192949 + .quad 192984 + .quad 193009 + .quad 193025 + .quad 193049 + .quad 193070 + .quad 193095 + .quad 193118 + .quad 193146 + .quad 193163 + .quad 193189 + .quad 193215 + .quad 193238 + .quad 193250 + .quad 193266 + .quad 193290 + .quad 193330 + .quad 193363 + .quad 193437 + .quad 193448 + .quad 193474 + .quad 193479 +.globl symbol_name +symbol_name: + .asciz "skernel" + .asciz "stext" + .asciz "strampoline" + .asciz "user_v" + .asciz "user_r" + .asciz "kernel::time::__syscall_115::_::__ctor" + .asciz "etrampoline" + .asciz "kernel::time::__syscall_114::_::__ctor" + .asciz "kernel::time::__syscall_103::_::__ctor" + .asciz "kernel::time::__syscall_102::_::__ctor" + .asciz "kernel::time::__syscall_113::_::__ctor" + .asciz "kernel::time::__syscall_101::_::__ctor" + .asciz "kernel::time::__syscall_153::_::__ctor" + .asciz "kernel::task::cpu::__syscall_261::_::__ctor" + .asciz "kernel::task::cpu::__syscall_214::_::__ctor" + .asciz "kernel::task::cpu::__syscall_260::_::__ctor" + .asciz "kernel::task::cpu::__syscall_221::_::__ctor" + .asciz "kernel::task::cpu::__syscall_177::_::__ctor" + .asciz "kernel::task::cpu::__syscall_176::_::__ctor" + .asciz "kernel::task::cpu::__syscall_175::_::__ctor" + .asciz "kernel::task::cpu::__syscall_174::_::__ctor" + .asciz "kernel::task::cpu::__syscall_157::_::__ctor" + .asciz "kernel::task::cpu::__syscall_155::_::__ctor" + .asciz "kernel::task::cpu::__syscall_154::_::__ctor" + .asciz "kernel::task::cpu::__syscall_93::_::__ctor" + .asciz "kernel::system::__syscall_2003::_::__ctor" + .asciz "kernel::system::__syscall_165::_::__ctor" + .asciz "kernel::system::__syscall_119::_::__ctor" + .asciz "kernel::system::__syscall_123::_::__ctor" + .asciz "kernel::system::__syscall_122::_::__ctor" + .asciz "kernel::system::__syscall_118::_::__ctor" + .asciz "kernel::net::__syscall_199::_::__ctor" + .asciz "kernel::net::__syscall_207::_::__ctor" + .asciz "kernel::net::__syscall_206::_::__ctor" + .asciz "kernel::net::__syscall_204::_::__ctor" + .asciz "kernel::net::__syscall_200::_::__ctor" + .asciz "kernel::mm::map::__syscall_233::_::__ctor" + .asciz "kernel::mm::map::__syscall_227::_::__ctor" + .asciz "kernel::mm::map::__syscall_215::_::__ctor" + .asciz "kernel::ipc::__syscall_98::_::__ctor" + .asciz "kernel::ipc::__syscall_23::_::__ctor" + .asciz "kernel::ipc::signal::__syscall_139::_::__ctor" + .asciz "kernel::ipc::signal::__syscall_130::_::__ctor" + .asciz "kernel::ipc::signal::__syscall_129::_::__ctor" + .asciz "kernel::ipc::signal::__syscall_135::_::__ctor" + .asciz "kernel::ipc::signal::__syscall_137::_::__ctor" + .asciz "kernel::ipc::signal::__syscall_134::_::__ctor" + .asciz "kernel::ipc::shm::__syscall_195::_::__ctor" + .asciz "kernel::gui::__syscall_2000::_::__ctor" + .asciz "kernel::fs::select::__syscall_72::_::__ctor" + .asciz "kernel::fs::poll::__syscall_73::_::__ctor" + .asciz "kernel::fs::link::__syscall_37::_::__ctor" + .asciz "kernel::fs::ext::__syscall_16::_::__ctor" + .asciz "kernel::fs::ext::__syscall_12::_::__ctor" + .asciz "kernel::fs::ext::__syscall_11::_::__ctor" + .asciz "kernel::fs::ext::__syscall_9::_::__ctor" + .asciz "kernel::fs::ext::__syscall_7::_::__ctor" + .asciz "kernel::fs::ext::__syscall_6::_::__ctor" + .asciz "kernel::fs::control::__syscall_166::_::__ctor" + .asciz "kernel::fs::control::__syscall_55::_::__ctor" + .asciz "kernel::fs::control::__syscall_53::_::__ctor" + .asciz "kernel::fs::control::__syscall_52::_::__ctor" + .asciz "kernel::fs::control::__syscall_48::_::__ctor" + .asciz "kernel::fs::control::__syscall_88::_::__ctor" + .asciz "kernel::fs::control::__syscall_29::_::__ctor" + .asciz "kernel::fs::control::__syscall_25::_::__ctor" + .asciz "kernel::fs::basic::__syscall_82::_::__ctor" + .asciz "kernel::fs::basic::__syscall_81::_::__ctor" + .asciz "kernel::fs::basic::__syscall_71::_::__ctor" + .asciz "kernel::fs::basic::__syscall_276::_::__ctor" + .asciz "kernel::fs::basic::__syscall_38::_::__ctor" + .asciz "kernel::fs::basic::__syscall_44::_::__ctor" + .asciz "kernel::fs::basic::__syscall_79::_::__ctor" + .asciz "kernel::fs::basic::__syscall_68::_::__ctor" + .asciz "kernel::fs::basic::__syscall_65::_::__ctor" + .asciz "kernel::fs::basic::__syscall_34::_::__ctor" + .asciz "kernel::fs::basic::__syscall_50::_::__ctor" + .asciz "kernel::fs::basic::__syscall_17::_::__ctor" + .asciz "kernel::fs::basic::__syscall_64::_::__ctor" + .asciz "kernel::fs::basic::__syscall_63::_::__ctor" + .asciz "kernel::fs::basic::__syscall_46::_::__ctor" + .asciz "kernel::fs::basic::__syscall_61::_::__ctor" + .asciz "kernel::fs::basic::__syscall_57::_::__ctor" + .asciz "kernel::fs::basic::__syscall_40::_::__ctor" + .asciz "kernel::ipc::__syscall_100::_::__ctor" + .asciz "kernel::time::__syscall_169::_::__ctor" + .asciz "kernel::task::cpu::__syscall_96::_::__ctor" + .asciz "kernel::task::cpu::__syscall_178::_::__ctor" + .asciz "kernel::task::cpu::__syscall_172::_::__ctor" + .asciz "kernel::system::__syscall_121::_::__ctor" + .asciz "kernel::system::__syscall_179::_::__ctor" + .asciz "kernel::system::__syscall_160::_::__ctor" + .asciz "kernel::net::__syscall_209::_::__ctor" + .asciz "kernel::net::__syscall_208::_::__ctor" + .asciz "kernel::net::__syscall_203::_::__ctor" + .asciz "kernel::net::__syscall_201::_::__ctor" + .asciz "kernel::net::__syscall_198::_::__ctor" + .asciz "kernel::mm::__syscall_283::_::__ctor" + .asciz "kernel::mm::map::__syscall_226::_::__ctor" + .asciz "kernel::ipc::signal::__syscall_133::_::__ctor" + .asciz "kernel::ipc::shm::__syscall_194::_::__ctor" + .asciz "kernel::gui::__syscall_2002::_::__ctor" + .asciz "kernel::gui::__syscall_2001::_::__ctor" + .asciz "kernel::fs::link::__syscall_78::_::__ctor" + .asciz "kernel::fs::link::__syscall_36::_::__ctor" + .asciz "kernel::fs::ext::__syscall_15::_::__ctor" + .asciz "kernel::fs::ext::__syscall_14::_::__ctor" + .asciz "kernel::fs::basic::__syscall_285::_::__ctor" + .asciz "kernel::fs::basic::__syscall_43::_::__ctor" + .asciz "kernel::fs::basic::__syscall_80::_::__ctor" + .asciz "kernel::fs::basic::__syscall_67::_::__ctor" + .asciz "kernel::fs::basic::__syscall_66::_::__ctor" + .asciz "kernel::fs::basic::__syscall_49::_::__ctor" + .asciz "kernel::fs::basic::__syscall_56::_::__ctor" + .asciz "kernel::fs::basic::__syscall_39::_::__ctor" + .asciz "kernel::task::cpu::__syscall_220::_::__ctor" + .asciz "kernel::task::cpu::__syscall_173::_::__ctor" + .asciz "kernel::task::cpu::__syscall_124::_::__ctor" + .asciz "kernel::task::cpu::__syscall_94::_::__ctor" + .asciz "kernel::system::__syscall_120::_::__ctor" + .asciz "kernel::system::__syscall_116::_::__ctor" + .asciz "kernel::net::__syscall_210::_::__ctor" + .asciz "kernel::net::__syscall_205::_::__ctor" + .asciz "kernel::net::__syscall_202::_::__ctor" + .asciz "kernel::mm::map::__syscall_222::_::__ctor" + .asciz "kernel::ipc::__syscall_99::_::__ctor" + .asciz "kernel::ipc::__syscall_24::_::__ctor" + .asciz "kernel::ipc::__syscall_59::_::__ctor" + .asciz "kernel::ipc::shm::__syscall_196::_::__ctor" + .asciz "kernel::fs::link::__syscall_35::_::__ctor" + .asciz "kernel::fs::ext::__syscall_13::_::__ctor" + .asciz "kernel::fs::ext::__syscall_10::_::__ctor" + .asciz "kernel::fs::ext::__syscall_8::_::__ctor" + .asciz "kernel::fs::ext::__syscall_5::_::__ctor" + .asciz "kernel::fs::basic::__syscall_62::_::__ctor" + .asciz "kernel::fs::basic::__syscall_45::_::__ctor" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_left" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_left" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_left" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_left" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_right" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_right" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_right" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_right" + .asciz "alloc::collections::btree::node::BalancingContext::merge_tracking_child_edge" + .asciz "alloc::collections::btree::node::BalancingContext::merge_tracking_child_edge" + .asciz "alloc::collections::btree::node::BalancingContext::merge_tracking_child_edge" + .asciz "alloc::collections::btree::node::BalancingContext::merge_tracking_child_edge" + .asciz "alloc::collections::btree::node::BalancingContext::do_merge" + .asciz "alloc::collections::btree::node::BalancingContext::do_merge" + .asciz "alloc::collections::btree::node::BalancingContext::do_merge" + .asciz "alloc::collections::btree::node::BalancingContext::do_merge" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_leaf_kv" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_leaf_kv" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_leaf_kv" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_leaf_kv" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_kv_tracking" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_kv_tracking" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_kv_tracking" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_kv_tracking" + .asciz "alloc::collections::btree::navigate::,alloc::collections::btree::node::marker::Edge>>::deallocating_next_unchecked" + .asciz "alloc::collections::btree::navigate::,alloc::collections::btree::node::marker::Edge>>::deallocating_next_unchecked" + .asciz "alloc::collections::btree::navigate::,alloc::collections::btree::node::marker::Edge>>::deallocating_next_unchecked" + .asciz "alloc::collections::btree::navigate::,alloc::collections::btree::node::marker::Edge>>::deallocating_next_unchecked" + .asciz "::type_id" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::into_any" + .asciz "core::fmt::num::::fmt" + .asciz "core::ops::function::FnOnce::call_once" + .asciz "core::ptr::drop_in_place<&str>" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "::drop" + .asciz "kernel::task::task::Task::terminate" + .asciz "kernel::task::task::Task::access_inner" + .asciz "kernel::task::task::Task::trap_frame" + .asciz "kernel::task::task::Task::trap_frame_ptr" + .asciz "kernel::task::task::Task::children" + .asciz "kernel::task::task::Task::check_child" + .asciz "kernel::task::task::Task::take_children" + .asciz "kernel::task::task::Task::update_parent" + .asciz "kernel::task::task::Task::get_file" + .asciz "kernel::task::task::Task::add_file" + .asciz "kernel::task::task::Task::remove_file" + .asciz "kernel::task::task::Task::transfer_raw_ptr" + .asciz "kernel::task::task::Task::transfer_raw_ptr" + .asciz "kernel::task::task::Task::transfer_raw_ptr" + .asciz "kernel::task::task::Task::transfer_raw_ptr" + .asciz "kernel::task::task::Task::transfer_raw_ptr" + .asciz "kernel::task::task::Task::transfer_raw_ptr" + .asciz "kernel::task::task::Task::transfer_str" + .asciz "kernel::task::task::Task::transfer_buffer" + .asciz "kernel::task::task::Task::transfer_buffer" + .asciz "kernel::task::task::TaskInner::set_prlimit" + .asciz "kernel::task::task::TaskInner::trap_frame" + .asciz "kernel::task::task::TaskInner::load_trap_frame" + .asciz "kernel::task::task::TaskInner::transfer_raw" + .asciz "kernel::task::task::TaskInner::transfer_buffer" + .asciz "kernel::task::task::TaskInner::transfer_raw_ptr_mut" + .asciz "kernel::task::task::TaskInner::transfer_raw_ptr_mut" + .asciz "kernel::task::task::TaskInner::transfer_raw_ptr_mut" + .asciz "kernel::task::task::TaskInner::transfer_raw_ptr" + .asciz "kernel::task::task::TaskInner::transfer_raw_ptr" + .asciz "kernel::task::task::TaskInner::transfer_raw_ptr" + .asciz "kernel::task::task::TaskInner::transfer_raw_ptr" + .asciz "kernel::task::task::TaskInner::extend_heap" + .asciz "kernel::task::task::TaskInner::add_mmap" + .asciz "kernel::task::task::TaskInner::unmap" + .asciz "kernel::task::task::TaskInner::map_protect" + .asciz "kernel::task::task::TaskInner::do_load_page_fault" + .asciz "kernel::task::task::TaskInner::invalid_page_solver" + .asciz "kernel::task::task::TaskInner::do_instruction_page_fault" + .asciz "kernel::task::task::TaskInner::do_store_page_fault" + .asciz "kernel::task::task::Task::pre_recycle" + .asciz "kernel::task::task::Task::from_elf" + .asciz "kernel::task::task::Task::t_clone" + .asciz "kernel::task::task::Task::exec" + .asciz "kernel::task::::to_wait" + .asciz "kernel::task::::to_wakeup" + .asciz "kernel::task::::have_signal" + .asciz "::fmt" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "syscall_table::Service::from_handler::closure" + .asciz "::submit" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ops::function::FnOnce::call_oncevtable.shim" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place>::closure>" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "<(P0,P1,P2) as syscall_table::FromArgs>::from" + .asciz "<(P0,P1,P2) as syscall_table::FromArgs>::from" + .asciz "<(P0,P1,P2,P3) as syscall_table::FromArgs>::from" + .asciz "<(P0,P1,P2,P3) as syscall_table::FromArgs>::from" + .asciz "<(P0,P1,P2,P3) as syscall_table::FromArgs>::from" + .asciz "<(P0,P1,P2,P3) as syscall_table::FromArgs>::from" + .asciz "<(P0,P1,P2,P3,P4) as syscall_table::FromArgs>::from" + .asciz "<(P0,P1,P2,P3,P4) as syscall_table::FromArgs>::from" + .asciz "vfs::system_support_fs" + .asciz "::fmt" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::into_any" + .asciz "<() as core::fmt::Debug>::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place<()>" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "::fmt" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz "smpscheduler::fifo::FifoSmpScheduler<_,T,L,H>::new" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::into_any_arc" + .asciz "::as_any" + .asciz "::into_any" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place" + .asciz "<*mut T as core::fmt::Debug>::fmt" + .asciz "<*const T as core::fmt::Debug>::fmt" + .asciz "unifs::inode::UniFsDirInode::lookup" + .asciz "unifs::inode::UniFsDirInode::readdir" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz " as vfscore::superblock::VfsSuperBlock>::super_type" + .asciz " as vfscore::superblock::VfsSuperBlock>::sync_fs" + .asciz "kernel::ipc::signal::global_register_signals" + .asciz "kernel::ipc::signal::global_logoff_signals" + .asciz "kernel::ipc::signal::send_signal" + .asciz "kernel::ipc::signal::signal_handler" + .asciz "::type_id" + .asciz "vfs::kfile::File::get_open_flag" + .asciz "vfs::kfile::File::flush" + .asciz "vfs::kfile::File::fsync" + .asciz "vfs::kfile::File::set_open_flag" + .asciz "vfs::kfile::File::ioctl" + .asciz "vfs::kfile::File::read_at" + .asciz "vfs::kfile::File::readdir" + .asciz "vfs::kfile::File::truncate" + .asciz "vfs::kfile::File::write_at" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::into_any_arc" + .asciz "::as_any" + .asciz "::into_any" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ops::function::FnOnce::call_once" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "unifs::UniFsSuperBlock::remove_inode" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz " as vfscore::superblock::VfsSuperBlock>::root_inode" + .asciz " as vfscore::superblock::VfsSuperBlock>::fs_type" + .asciz " as vfscore::superblock::VfsSuperBlock>::stat_fs" + .asciz "gmanager::MinimalManager::insert_with_index" + .asciz "gmanager::MinimalManager::insert" + .asciz "::seek" + .asciz "::get_attr" + .asciz "::is_append" + .asciz "kernel::ipc::futex" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place<&str>" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "kernel::mm::loader::build_thread_address_space" + .asciz "kernel::mm::loader::build_cow_address_space" + .asciz "kernel::mm::loader::build_elf_address_space" + .asciz "main" + .asciz "rust_begin_unwind" + .asciz " as core::ops::drop::Drop>::drop" + .asciz "page_table::table::bits64::PageTable64::map_region" + .asciz "page_table::table::bits64::PageTable64::unmap_region" + .asciz "page_table::table::bits64::PageTable64::modify_pte_flags" + .asciz "page_table::table::bits64::PageTable64::map_region_no_target" + .asciz "page_table::table::bits64::PageTable64::get_entry_mut_or_create" + .asciz "page_table::table::bits64::PageTable64::map" + .asciz "::type_id" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place<&isize>" + .asciz "core::ptr::drop_in_place" + .asciz "alloc::collections::btree::map::entry::Entry::or_insert" + .asciz "alloc::collections::btree::map::entry::OccupiedEntry::remove_kv" + .asciz "alloc::collections::btree::map::entry::OccupiedEntry::remove_kv" + .asciz "alloc::collections::btree::map::entry::OccupiedEntry::remove_kv" + .asciz "alloc::collections::btree::map::entry::OccupiedEntry::remove_kv" + .asciz "dynfs::dir::DynFsDirInode::add_manually" + .asciz "dynfs::dir::DynFsDirInode::remove_manually" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz "vfscore::file::VfsFile::poll" + .asciz "vfscore::file::VfsFile::flush" + .asciz "vfscore::file::VfsFile::ioctl" + .asciz "vfscore::file::VfsFile::read_at" + .asciz "vfscore::file::VfsFile::readdir" + .asciz "vfscore::file::VfsFile::write_at" + .asciz " as vfscore::file::VfsFile>::readdir" + .asciz " as vfscore::inode::VfsInode>::inode_type" + .asciz " as vfscore::inode::VfsInode>::list_xattr" + .asciz " as vfscore::inode::VfsInode>::update_time" + .asciz " as vfscore::inode::VfsInode>::get_super_block" + .asciz " as vfscore::inode::VfsInode>::link" + .asciz " as vfscore::inode::VfsInode>::rmdir" + .asciz " as vfscore::inode::VfsInode>::create" + .asciz " as vfscore::inode::VfsInode>::lookup" + .asciz " as vfscore::inode::VfsInode>::symlink" + .asciz " as vfscore::inode::VfsInode>::get_attr" + .asciz " as vfscore::inode::VfsInode>::readlink" + .asciz " as vfscore::inode::VfsInode>::set_attr" + .asciz " as vfscore::inode::VfsInode>::truncate" + .asciz " as vfscore::inode::VfsInode>::node_perm" + .asciz " as vfscore::inode::VfsInode>::rename_to" + .asciz " as vfscore::inode::VfsInode>::inode_type" + .asciz " as vfscore::inode::VfsInode>::lookup" + .asciz " as vfscore::inode::VfsInode>::readlink" + .asciz " as vfscore::inode::VfsInode>::truncate" + .asciz "kernel::ipc::futex::FutexWaitManager::add_waiter" + .asciz "kernel::ipc::futex::FutexWaitManager::wake_for_signal" + .asciz "kernel::ipc::futex::FutexWaitManager::wake_for_timeout" + .asciz "kernel::ipc::futex::FutexWaitManager::delete_empty_waiters" + .asciz "kernel::ipc::futex::FutexWaitManager::wake" + .asciz "kernel::ipc::futex::FutexWaitManager::requeue" + .asciz " as core::iter::traits::iterator::Iterator>::next" + .asciz " as core::iter::traits::iterator::Iterator>::next" + .asciz " as core::iter::traits::iterator::Iterator>::next" + .asciz " as core::iter::traits::iterator::Iterator>::next" + .asciz " as core::iter::traits::iterator::Iterator>::next" + .asciz " as core::iter::traits::double_ended::DoubleEndedIterator>::next_back" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "::fmt" + .asciz ">::call" + .asciz ">::call" + .asciz "vfscore::path::VfsPath::join" + .asciz ">::call" + .asciz ">::call" + .asciz " as core::clone::Clone>::clone::clone_subtree" + .asciz " as core::clone::Clone>::clone::clone_subtree" + .asciz " as core::ops::drop::Drop>::drop" + .asciz " as core::ops::drop::Drop>::drop" + .asciz " as core::ops::drop::Drop>::drop" + .asciz " as core::ops::drop::Drop>::drop" + .asciz "kernel::fs::user_path_at" + .asciz "kernel::fs::read_all" + .asciz "::relocate" + .asciz "kernel::net::addr::socket_addr_resolution" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::str::pattern::TwoWaySearcher::next" + .asciz "<&str as core::str::pattern::Pattern>::is_contained_in" + .asciz "::fmt" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz "kernel::trap::exception::syscall_exception_handler" + .asciz "kernel::trap::exception::page_exception_handler" + .asciz "kernel::trap::exception::trap_common_read_file" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "alloc::raw_vec::finish_grow" + .asciz "alloc::raw_vec::RawVec::allocate_in" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve::do_reserve_and_handle" + .asciz "alloc::raw_vec::RawVec::reserve::do_reserve_and_handle" + .asciz "alloc::raw_vec::RawVec::reserve::do_reserve_and_handle" + .asciz "alloc::raw_vec::RawVec::reserve::do_reserve_and_handle" + .asciz "__sys_mount" + .asciz "__sys_close" + .asciz "__sys_getdents" + .asciz "__sys_ftruncate" + .asciz "__sys_read" + .asciz "__sys_write" + .asciz "__sys_getcwd" + .asciz "__sys_fchdir" + .asciz "__sys_mkdirat" + .asciz "__sys_readv" + .asciz "__sys_pwrite" + .asciz "__sys_fstateat" + .asciz "__sys_fstatfs" + .asciz "__sys_renameat" + .asciz "__sys_renameat2" + .asciz "__send_file" + .asciz "__sync" + .asciz "__fsync" + .asciz "__fcntl" + .asciz "__ioctl" + .asciz "__utimensat" + .asciz "__faccessat" + .asciz "__chmod" + .asciz "__chmodat" + .asciz "__fchown" + .asciz "__unmask" + .asciz "__sys_lsetxattr" + .asciz "__sys_fsetxattr" + .asciz "__sys_lgetxattr" + .asciz "__sys_listxattr" + .asciz "__sys_llistxattr" + .asciz "__sys_fremovexattr" + .asciz "__sys_linkat" + .asciz "__ppoll" + .asciz "__pselect6" + .asciz "__sys_framebuffer" + .asciz "__shmctl" + .asciz "__sigaction" + .asciz "__sigtimewait" + .asciz "__sigprocmask" + .asciz "__kill" + .asciz "__tkill" + .asciz "__signal_return" + .asciz "__sys_dup" + .asciz "__futex" + .asciz "__do_munmap" + .asciz "__msync" + .asciz "__madvise" + .asciz "__bind" + .asciz "__getsockname" + .asciz "__sendto" + .asciz "__recvfrom" + .asciz "__socket_pair" + .asciz "__sched_setparam" + .asciz "__sched_setaffinity" + .asciz "__sched_getaffinity" + .asciz "__sched_setscheduler" + .asciz "__getrusage" + .asciz "__system_shutdown" + .asciz "__do_exit" + .asciz "__set_pgid" + .asciz "__get_pgid" + .asciz "__set_sid" + .asciz "__getuid" + .asciz "__geteuid" + .asciz "__getgid" + .asciz "__getegid" + .asciz "__do_exec" + .asciz "__wait4" + .asciz "__do_brk" + .asciz "__prlimit64" + .asciz "__times" + .asciz "__nanosleep" + .asciz "__clock_get_time" + .asciz "__getitimer" + .asciz "__setitimer" + .asciz "__clock_getres" + .asciz "__clock_nanosleep" + .asciz "kernel_v" + .asciz "::type_id" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ops::function::FnOnce::call_once" + .asciz "core::ptr::drop_in_place>" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz "kernel::task::cpu::current_cpu" + .asciz "kernel::task::cpu::current_task" + .asciz "kernel::task::cpu::current_user_token" + .asciz "kernel::task::cpu::current_trap_frame" + .asciz "kernel::task::task::TaskInner::update_timer" + .asciz "trap_return" + .asciz "kernel::trap::init_trap_subsystem" + .asciz "kernel::trap::check_timer_interrupt_pending" + .asciz "user_trap_vector" + .asciz "kernel::trap::check_task_timer_expired" + .asciz "kernel_trap_vector" + .asciz "__get_robust_list" + .asciz "kernel::task::cpu::do_exit" + .asciz "kernel::task::cpu::do_suspend" + .asciz "::type_id" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "<() as core::fmt::Debug>::fmt" + .asciz "core::ops::function::FnOnce::call_once" + .asciz "core::ops::function::FnOnce::call_once" + .asciz "core::ops::function::FnOnce::call_once" + .asciz "core::ptr::drop_in_place>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place<()>" + .asciz "core::ptr::drop_in_place<&isize>" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "alloc::sync::Arc::downgrade" + .asciz "alloc::sync::Arc::downgrade" + .asciz "alloc::sync::Arc::downgrade" + .asciz "alloc::sync::Arc::downgrade::panic_cold_display" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Weak::upgrade::checked_increment::panic_cold_display" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as vfscore::file::VfsFile>::poll" + .asciz " as vfscore::file::VfsFile>::flush" + .asciz " as vfscore::file::VfsFile>::fsync" + .asciz " as vfscore::file::VfsFile>::ioctl" + .asciz " as vfscore::file::VfsFile>::read_at" + .asciz " as vfscore::file::VfsFile>::write_at" + .asciz " as vfscore::inode::VfsInode>::update_time" + .asciz " as vfscore::inode::VfsInode>::get_super_block" + .asciz " as vfscore::inode::VfsInode>::link" + .asciz " as vfscore::inode::VfsInode>::get_attr" + .asciz " as vfscore::inode::VfsInode>::node_perm" + .asciz " as vfscore::inode::VfsInode>::rename_to" + .asciz " as vfscore::superblock::VfsSuperBlock>::super_type" + .asciz " as vfscore::superblock::VfsSuperBlock>::sync_fs" + .asciz " as lock_api::mutex::RawMutex>::lock" + .asciz "kernel::task::schedule::run_task" + .asciz "kernel::task::schedule::schedule" + .asciz "kernel::task::init_process" + .asciz "::get_task" + .asciz "::put_task" + .asciz "::suspend" + .asciz "::transfer_ptr_raw" + .asciz "::transfer_buf_raw" + .asciz "kernel::trap::interrupt::timer_interrupt_handler" + .asciz "__sys_umount" + .asciz "__sys_openat" + .asciz "__sys_chdir" + .asciz "__sys_writev" + .asciz "__sys_pread" + .asciz "__sys_fstat" + .asciz "__sys_statfs" + .asciz "__copy_file_range" + .asciz "__sys_removexattr" + .asciz "__sys_lremovexattr" + .asciz "__sys_symlinkat" + .asciz "__sys_readlinkat" + .asciz "__sys_framebuffer_flush" + .asciz "__sys_event_get" + .asciz "__shmget" + .asciz "__sigsuspend" + .asciz "__map_protect" + .asciz "__membarrier" + .asciz "__socket" + .asciz "__listening" + .asciz "__connect" + .asciz "__setsockopt" + .asciz "__getsockopt" + .asciz "__uname" + .asciz "__sys_info" + .asciz "__sched_getparam" + .asciz "__get_pid" + .asciz "__get_tid" + .asciz "__set_tid_address" + .asciz "__get_time_of_day" + .asciz " as core::iter::traits::iterator::Iterator>::next" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place<&pconst::io::PollFd>" + .asciz "core::ptr::drop_in_place<&alloc::string::String>" + .asciz "core::ptr::drop_in_place<&pconst::signal::number::SignalNumber>" + .asciz "core::panicking::assert_failed" + .asciz "core::panicking::assert_failed" + .asciz "core::panicking::assert_failed" + .asciz "core::panicking::assert_failed" + .asciz "<&mut T as core::fmt::Debug>::fmt" + .asciz "alloc::vec::Vec::resize" + .asciz "alloc::vec::in_place_collect:: for alloc::vec::Vec>::from_iter" + .asciz "alloc::vec::in_place_collect:: for alloc::vec::Vec>::from_iter" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::clone::Clone>::clone" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz " as alloc::vec::spec_from_iter::SpecFromIter>::from_iter" + .asciz " as alloc::vec::spec_from_iter::SpecFromIter>::from_iter" + .asciz " as alloc::vec::spec_from_iter::SpecFromIter>::from_iter" + .asciz "kernel::mm::map::MMapInfo::add_region" + .asciz "kernel::mm::map::MMapRegion::split" + .asciz "::fmt" + .asciz "__switch" + .asciz " as core::iter::traits::iterator::Iterator>::fold" + .asciz " as core::iter::traits::iterator::Iterator>::fold" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::type_id" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::into_any" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::Write::write_fmt" + .asciz "core::ptr::drop_in_place>" + .asciz "core::ptr::drop_in_place<&str>" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "::write_char" + .asciz "::write_str" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz " as core::fmt::Debug>::fmt" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz "vfscore::file::VfsFile::flush" + .asciz "vfscore::file::VfsFile::ioctl" + .asciz "vfscore::file::VfsFile::readdir" + .asciz ">::call" + .asciz ">::call" + .asciz "::fmt" + .asciz "kernel::ipc::pipe::make_pipe_file" + .asciz "::read" + .asciz "::write" + .asciz "::dentry" + .asciz "::inode" + .asciz "::is_readable" + .asciz "::is_writable" + .asciz "::poll" + .asciz "::read_at" + .asciz "::write_at" + .asciz "::poll" + .asciz "::get_super_block" + .asciz "::node_perm" + .asciz "::readlink" + .asciz "::set_attr" + .asciz "::get_attr" + .asciz "::list_xattr" + .asciz "::inode_type" + .asciz "::update_time" + .asciz "::drop" + .asciz "kernel::fs::ext::sys_setxattr" + .asciz "kernel::fs::ext::sys_getxattr" + .asciz "::create" + .asciz "::link" + .asciz "::symlink" + .asciz "::lookup" + .asciz "::rmdir" + .asciz "::truncate" + .asciz "::rename_to" + .asciz "vfs::kfile::File::flush" + .asciz "vfs::kfile::File::ioctl" + .asciz "vfs::kfile::File::read_at" + .asciz "vfs::kfile::File::readdir" + .asciz "vfs::kfile::File::truncate" + .asciz "vfs::kfile::File::write_at" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::into_any" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place>" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "<&mut T as core::fmt::Debug>::fmt" + .asciz "::is_readable" + .asciz "::seek" + .asciz "::get_attr" + .asciz "::is_append" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz ">::call" + .asciz "kernel::net::common_socket_syscall" + .asciz "::do_user_handle" + .asciz "::do_kernel_handle" + .asciz "__sys_truncate" + .asciz "__sys_lseek" + .asciz "__sys_setxattr" + .asciz "__sys_getxattr" + .asciz "__sys_fgetxattr" + .asciz "__sys_flistxattr" + .asciz "__sys_unlinkat" + .asciz "__shmat" + .asciz "__sys_pipe" + .asciz "__sys_dup2" + .asciz "__set_robust_list" + .asciz "__do_mmap" + .asciz "__accept" + .asciz "__get_peer_name" + .asciz "__shutdown" + .asciz "__syslog" + .asciz "__sched_getscheduler" + .asciz "__exit_group" + .asciz "__do_suspend" + .asciz "__get_ppid" + .asciz "__clone" + .asciz "__rust_alloc_error_handler" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place,ksync::KernelLockAction>>" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place<&knet::socket::Socket>" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "knet::socket::SocketFile::set_close_on_exec" + .asciz "::get_socketdata" + .asciz "::read" + .asciz "::write" + .asciz "::set_open_flag" + .asciz "::get_open_flag" + .asciz "::dentry" + .asciz "::inode" + .asciz "::poll" + .asciz "::fmt" + .asciz "knet::socket::SocketData::new" + .asciz "knet::socket::SocketData::set_socket_nonblock" + .asciz "knet::socket::SocketData::bind" + .asciz "knet::socket::SocketData::accept" + .asciz "knet::socket::SocketData::listening" + .asciz "knet::socket::SocketData::connect" + .asciz "knet::socket::SocketData::send_to" + .asciz "knet::socket::SocketData::recvfrom" + .asciz "knet::socket::SocketData::shutdown" + .asciz "knet::socket::SocketData::local_addr" + .asciz "knet::socket::SocketData::peer_addr" + .asciz "knet::socket::SocketData::ready_read" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place<&u8>" + .asciz "alloc::sync::Arc::drop_slow" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz ">::from" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place<&&str>" + .asciz "core::ptr::drop_in_place<&xmas_elf::program::Type>" + .asciz "core::ptr::drop_in_place<&xmas_elf::sections::ShType>" + .asciz "core::ptr::drop_in_place<&xmas_elf::dynamic::Tag>" + .asciz "core::ptr::drop_in_place<&xmas_elf::dynamic::Tag>" + .asciz "core::ptr::drop_in_place<&xmas_elf::sections::CompressionType>" + .asciz "core::panicking::assert_failed" + .asciz "xmas_elf::ElfFile::new" + .asciz "xmas_elf::ElfFile::get_shstr" + .asciz "xmas_elf::ElfFile::get_dyn_string" + .asciz "xmas_elf::ElfFile::find_section_by_name" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place<&str>" + .asciz "xmas_elf::sections::parse_section_header" + .asciz "xmas_elf::sections::SectionHeader::get_data" + .asciz "xmas_elf::sections::SectionHeader::raw_data" + .asciz "::fmt" + .asciz "xmas_elf::program::parse_program_header" + .asciz "::next" + .asciz "xmas_elf::program::ProgramHeader::get_type" + .asciz "xmas_elf::program::ProgramHeader::get_data" + .asciz "xmas_elf::program::ProgramHeader32::get_data" + .asciz "xmas_elf::program::ProgramHeader32::raw_data" + .asciz "xmas_elf::program::ProgramHeader64::get_data" + .asciz "xmas_elf::program::ProgramHeader64::raw_data" + .asciz "::get_name" + .asciz "core::ptr::drop_in_place<&u8>" + .asciz "zero::read_str" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "core::ops::function::FnOnce::call_once" + .asciz "core::ops::function::FnOnce::call_once" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place<&vfscore::utils::VfsNodeType>" + .asciz "core::array::::fmt" + .asciz "core::array::::fmt" + .asciz "core::panicking::assert_failed" + .asciz "core::panicking::assert_failed" + .asciz "::read_at" + .asciz "::flush" + .asciz "::inode_type" + .asciz "::get_attr" + .asciz "::set_attr" + .asciz "::get_super_block" + .asciz "::flush" + .asciz "::inode_type" + .asciz "::write_at" + .asciz "::inode_type" + .asciz "::get_super_block" + .asciz "::get_attr" + .asciz "::set_attr" + .asciz "::get_attr" + .asciz " as vfscore::fstype::VfsFsType>::mount" + .asciz " as vfscore::fstype::VfsFsType>::fs_flag" + .asciz " as vfscore::fstype::VfsFsType>::fs_name" + .asciz " as vfscore::fstype::VfsFsType>::kill_sb" + .asciz "vfscore::file::VfsFile::poll" + .asciz "vfscore::file::VfsFile::poll" + .asciz "vfscore::file::VfsFile::poll" + .asciz "vfscore::file::VfsFile::flush" + .asciz "vfscore::file::VfsFile::ioctl" + .asciz "vfscore::file::VfsFile::ioctl" + .asciz "vfscore::file::VfsFile::ioctl" + .asciz "vfscore::file::VfsFile::read_at" + .asciz "vfscore::file::VfsFile::readdir" + .asciz "vfscore::file::VfsFile::readdir" + .asciz "vfscore::file::VfsFile::readdir" + .asciz "vfscore::file::VfsFile::write_at" + .asciz "vfscore::inode::VfsInode::list_xattr" + .asciz "vfscore::inode::VfsInode::list_xattr" + .asciz "vfscore::inode::VfsInode::list_xattr" + .asciz "vfscore::inode::VfsInode::update_time" + .asciz "vfscore::inode::VfsInode::update_time" + .asciz "vfscore::inode::VfsInode::update_time" + .asciz "vfscore::inode::VfsInode::rmdir" + .asciz "vfscore::inode::VfsInode::rmdir" + .asciz "vfscore::inode::VfsInode::rmdir" + .asciz "vfscore::inode::VfsInode::create" + .asciz "vfscore::inode::VfsInode::create" + .asciz "vfscore::inode::VfsInode::create" + .asciz "vfscore::inode::VfsInode::lookup" + .asciz "vfscore::inode::VfsInode::lookup" + .asciz "vfscore::inode::VfsInode::lookup" + .asciz "vfscore::inode::VfsInode::symlink" + .asciz "vfscore::inode::VfsInode::symlink" + .asciz "vfscore::inode::VfsInode::symlink" + .asciz "vfscore::inode::VfsInode::readlink" + .asciz "vfscore::inode::VfsInode::readlink" + .asciz "vfscore::inode::VfsInode::readlink" + .asciz "vfscore::inode::VfsInode::truncate" + .asciz "vfscore::inode::VfsInode::truncate" + .asciz "vfscore::inode::VfsInode::truncate" + .asciz "vfscore::inode::VfsInode::node_perm" + .asciz "vfscore::inode::VfsInode::node_perm" + .asciz " as vfscore::file::VfsFile>::poll" + .asciz " as vfscore::file::VfsFile>::flush" + .asciz " as vfscore::file::VfsFile>::fsync" + .asciz " as vfscore::file::VfsFile>::ioctl" + .asciz " as vfscore::file::VfsFile>::read_at" + .asciz " as vfscore::file::VfsFile>::write_at" + .asciz " as vfscore::inode::VfsInode>::update_time" + .asciz " as vfscore::inode::VfsInode>::get_super_block" + .asciz " as vfscore::inode::VfsInode>::link" + .asciz " as vfscore::inode::VfsInode>::get_attr" + .asciz " as vfscore::inode::VfsInode>::set_attr" + .asciz " as vfscore::inode::VfsInode>::node_perm" + .asciz " as vfscore::inode::VfsInode>::rename_to" + .asciz " as vfscore::inode::VfsInode>::inode_type" + .asciz " as vfscore::inode::VfsInode>::readlink" + .asciz " as vfscore::inode::VfsInode>::truncate" + .asciz " as vfscore::superblock::VfsSuperBlock>::sync_fs" + .asciz "::write_at" + .asciz "::get_super_block" + .asciz "::node_perm" + .asciz "::set_attr" + .asciz "::get_attr" + .asciz "::inode_type" + .asciz "vfs::dev::register_device" + .asciz "vfs::dev::alloc_device_id" + .asciz "vfs::dev::init_devfs" + .asciz "vfs::pipefs::init_pipefs" + .asciz "vfs::sys::init_sysfs" + .asciz "alloc::sync::Arc::downgrade::panic_cold_display" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Weak::upgrade::checked_increment::panic_cold_display" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::iter::traits::iterator::Iterator>::next" + .asciz " as core::iter::traits::iterator::Iterator>::next" + .asciz " as core::iter::traits::iterator::Iterator>::next" + .asciz "::type_id" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "core::ptr::drop_in_place>" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "alloc::collections::btree::map::BTreeMap::get" + .asciz "alloc::collections::btree::map::BTreeMap::get" + .asciz "alloc::collections::btree::map::BTreeMap::get" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "alloc::collections::btree::map::BTreeMap::remove" + .asciz "alloc::collections::btree::map::BTreeMap::remove" + .asciz "alloc::collections::btree::map::BTreeMap::remove" + .asciz "alloc::collections::btree::map::BTreeMap::remove" + .asciz "alloc::collections::btree::map::entry::Entry::or_insert" + .asciz "vfscore::file::VfsFile::poll" + .asciz "vfscore::file::VfsFile::flush" + .asciz "vfscore::file::VfsFile::ioctl" + .asciz "vfscore::file::VfsFile::readdir" + .asciz "vfscore::file::VfsFile::write_at" + .asciz "vfscore::inode::VfsInode::list_xattr" + .asciz "vfscore::inode::VfsInode::update_time" + .asciz "vfscore::inode::VfsInode::link" + .asciz "vfscore::inode::VfsInode::rmdir" + .asciz "vfscore::inode::VfsInode::create" + .asciz "vfscore::inode::VfsInode::lookup" + .asciz "vfscore::inode::VfsInode::symlink" + .asciz "vfscore::inode::VfsInode::readlink" + .asciz "vfscore::inode::VfsInode::truncate" + .asciz "vfscore::inode::VfsInode::rename_to" + .asciz " as core::ops::drop::Drop>::drop" + .asciz " as core::ops::drop::Drop>::drop" + .asciz " as core::ops::drop::Drop>::drop" + .asciz " as core::ops::drop::Drop>::drop" + .asciz " as core::ops::drop::Drop>::drop" + .asciz " as core::ops::drop::Drop>::drop" + .asciz "::read_at" + .asciz "::write_at" + .asciz "::get_super_block" + .asciz "::node_perm" + .asciz "::set_attr" + .asciz "::get_attr" + .asciz "::inode_type" + .asciz "::get_attr" + .asciz "vfs::proc::init_procfs" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_left" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_left" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_left" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_left" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_right" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_right" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_right" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_right" + .asciz "alloc::collections::btree::node::BalancingContext::merge_tracking_child_edge" + .asciz "alloc::collections::btree::node::BalancingContext::merge_tracking_child_edge" + .asciz "alloc::collections::btree::node::BalancingContext::merge_tracking_child_edge" + .asciz "alloc::collections::btree::node::BalancingContext::merge_tracking_child_edge" + .asciz "alloc::collections::btree::node::BalancingContext::do_merge" + .asciz "alloc::collections::btree::node::BalancingContext::do_merge" + .asciz "alloc::collections::btree::node::BalancingContext::do_merge" + .asciz "alloc::collections::btree::node::BalancingContext::do_merge" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_leaf_kv" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_leaf_kv" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_leaf_kv" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_leaf_kv" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_kv_tracking" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_kv_tracking" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_kv_tracking" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_kv_tracking" + .asciz "alloc::collections::btree::navigate::,alloc::collections::btree::node::marker::Edge>>::deallocating_next_unchecked" + .asciz "alloc::collections::btree::navigate::,alloc::collections::btree::node::marker::Edge>>::deallocating_next_unchecked" + .asciz "alloc::collections::btree::navigate::,alloc::collections::btree::node::marker::Edge>>::deallocating_next_unchecked" + .asciz "alloc::collections::btree::navigate::,alloc::collections::btree::node::marker::Edge>>::deallocating_next_unchecked" + .asciz "alloc::collections::btree::navigate::,alloc::collections::btree::node::marker::Edge>>::deallocating_next_unchecked" + .asciz "alloc::collections::btree::navigate::,alloc::collections::btree::node::marker::Edge>>::deallocating_next_unchecked" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_arc" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "dynfs::dir::DynFsDirInode::add_manually" + .asciz "unifs::inode::UniFsDirInode::lookup" + .asciz "unifs::inode::UniFsDirInode::lookup" + .asciz "unifs::inode::UniFsDirInode::readdir" + .asciz "unifs::inode::UniFsDirInode::readdir" + .asciz "unifs::inode::UniFsDirInode::node_perm" + .asciz "unifs::inode::UniFsDirInode::node_perm" + .asciz " as vfscore::inode::VfsInode>::node_perm" + .asciz "unifs::inode::UniFsDirInode::rename_to" + .asciz "unifs::inode::UniFsDirInode::rename_to" + .asciz "vfscore::file::VfsFile::poll" + .asciz "vfscore::file::VfsFile::ioctl" + .asciz "vfscore::file::VfsFile::read_at" + .asciz "vfscore::file::VfsFile::readdir" + .asciz "vfscore::file::VfsFile::write_at" + .asciz "vfscore::inode::VfsInode::link" + .asciz "vfscore::inode::VfsInode::link" + .asciz "vfscore::inode::VfsInode::link" + .asciz "vfscore::inode::VfsInode::link" + .asciz "vfscore::inode::VfsInode::rename_to" + .asciz "vfscore::inode::VfsInode::rename_to" + .asciz "vfscore::inode::VfsInode::rename_to" + .asciz "vfscore::inode::VfsInode::rename_to" + .asciz " as vfscore::file::VfsFile>::readdir" + .asciz " as vfscore::inode::VfsInode>::inode_type" + .asciz " as vfscore::inode::VfsInode>::list_xattr" + .asciz " as vfscore::inode::VfsInode>::update_time" + .asciz " as vfscore::inode::VfsInode>::get_super_block" + .asciz " as vfscore::inode::VfsInode>::link" + .asciz " as vfscore::inode::VfsInode>::rmdir" + .asciz " as vfscore::inode::VfsInode>::create" + .asciz " as vfscore::inode::VfsInode>::lookup" + .asciz " as vfscore::inode::VfsInode>::symlink" + .asciz " as vfscore::inode::VfsInode>::get_attr" + .asciz " as vfscore::inode::VfsInode>::readlink" + .asciz " as vfscore::inode::VfsInode>::set_attr" + .asciz " as vfscore::inode::VfsInode>::truncate" + .asciz " as vfscore::inode::VfsInode>::rename_to" + .asciz " as vfscore::inode::VfsInode>::inode_type" + .asciz " as vfscore::inode::VfsInode>::lookup" + .asciz " as vfscore::inode::VfsInode>::readlink" + .asciz " as vfscore::inode::VfsInode>::truncate" + .asciz " as vfscore::superblock::VfsSuperBlock>::super_type" + .asciz " as vfscore::superblock::VfsSuperBlock>::sync_fs" + .asciz "::read_at" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "core::ptr::drop_in_place>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>" + .asciz "alloc::raw_vec::finish_grow" + .asciz "alloc::raw_vec::RawVec::allocate_in" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve::do_reserve_and_handle" + .asciz "alloc::raw_vec::RawVec::reserve::do_reserve_and_handle" + .asciz "alloc::raw_vec::RawVec::reserve::do_reserve_and_handle" + .asciz " as vfscore::fstype::VfsFsType>::mount" + .asciz " as vfscore::fstype::VfsFsType>::fs_flag" + .asciz " as vfscore::fstype::VfsFsType>::fs_name" + .asciz " as vfscore::fstype::VfsFsType>::kill_sb" + .asciz "fat_vfs::fs::FatFsSuperBlock::root_dentry" + .asciz "vfscore::file::VfsFile::poll" + .asciz "vfscore::file::VfsFile::flush" + .asciz "vfscore::file::VfsFile::read_at" + .asciz "vfscore::file::VfsFile::write_at" + .asciz "vfscore::dentry::VfsDentry::is_mount_point" + .asciz "vfscore::dentry::VfsDentry::path" + .asciz " as vfscore::dentry::VfsDentry>::set_parent" + .asciz " as vfscore::dentry::VfsDentry>::mount_point" + .asciz " as vfscore::dentry::VfsDentry>::to_mount_point" + .asciz " as vfscore::dentry::VfsDentry>::clear_mount_point" + .asciz " as vfscore::dentry::VfsDentry>::find" + .asciz " as vfscore::dentry::VfsDentry>::name" + .asciz " as vfscore::dentry::VfsDentry>::inode" + .asciz " as vfscore::dentry::VfsDentry>::insert" + .asciz " as vfscore::dentry::VfsDentry>::parent" + .asciz " as vfscore::dentry::VfsDentry>::remove" + .asciz " as vfscore::file::VfsFile>::ioctl" + .asciz " as vfscore::inode::VfsInode>::inode_type" + .asciz " as vfscore::inode::VfsInode>::list_xattr" + .asciz " as vfscore::inode::VfsInode>::symlink" + .asciz " as vfscore::inode::VfsInode>::readlink" + .asciz " as vfscore::inode::VfsInode>::set_attr" + .asciz " as vfscore::inode::VfsInode>::truncate" + .asciz " as vfscore::superblock::VfsSuperBlock>::root_inode" + .asciz " as vfscore::superblock::VfsSuperBlock>::fs_type" + .asciz " as vfscore::superblock::VfsSuperBlock>::stat_fs" + .asciz " as vfscore::superblock::VfsSuperBlock>::sync_fs" + .asciz "fatfs::fs::FileSystem::alloc_cluster" + .asciz "fatfs::fs::FileSystem::set_dirty_flag" + .asciz "fatfs::fs::FileSystem::free_cluster_chain" + .asciz "fatfs::fs::FileSystem::truncate_cluster_chain" + .asciz "fatfs::fs::FileSystem::new" + .asciz "fatfs::fs::FileSystem::stats" + .asciz "fatfs::fs::FileSystem::root_dir" + .asciz "fatfs::fs::FileSystem::fat_slice" + .asciz "fatfs::io::Read::read_exact" + .asciz "fatfs::io::Write::write_all" + .asciz " as fatfs::io::Read>::read" + .asciz " as fatfs::io::Seek>::seek" + .asciz " as fatfs::io::Write>::write" + .asciz " as core::ops::drop::Drop>::drop" + .asciz " as core::iter::traits::iterator::Iterator>::next" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::type_id" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::into_any_arc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "core::ptr::drop_in_place>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place<&usize>" + .asciz "fatfs::table::alloc_cluster" + .asciz "fatfs::table::find_free_cluster" + .asciz "fatfs::table::count_free_clusters" + .asciz "fatfs::table::ClusterIterator::truncate" + .asciz "fatfs::table::write_fat" + .asciz "unifs::UniFs::kill_sb" + .asciz "unifs::UniFsSuperBlock::root_dentry" + .asciz "unifs::UniFsSuperBlock::remove_inode" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as vfscore::fstype::VfsFsType>::mount" + .asciz " as vfscore::fstype::VfsFsType>::fs_flag" + .asciz " as vfscore::fstype::VfsFsType>::fs_name" + .asciz " as vfscore::fstype::VfsFsType>::kill_sb" + .asciz " as core::ops::drop::Drop>::drop" + .asciz "vfscore::file::VfsFile::poll" + .asciz "vfscore::file::VfsFile::flush" + .asciz "vfscore::file::VfsFile::ioctl" + .asciz "vfscore::file::VfsFile::read_at" + .asciz "vfscore::file::VfsFile::write_at" + .asciz "vfscore::path::VfsPath::join" + .asciz "vfscore::inode::VfsInode::link" + .asciz "vfscore::inode::VfsInode::link" + .asciz "vfscore::inode::VfsInode::rename_to" + .asciz "vfscore::inode::VfsInode::rename_to" + .asciz " as vfscore::inode::VfsInode>::inode_type" + .asciz " as vfscore::inode::VfsInode>::list_xattr" + .asciz " as vfscore::inode::VfsInode>::symlink" + .asciz " as vfscore::inode::VfsInode>::readlink" + .asciz " as vfscore::inode::VfsInode>::set_attr" + .asciz " as vfscore::inode::VfsInode>::truncate" + .asciz " as vfscore::superblock::VfsSuperBlock>::root_inode" + .asciz " as vfscore::superblock::VfsSuperBlock>::fs_type" + .asciz " as vfscore::superblock::VfsSuperBlock>::stat_fs" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "core::ptr::drop_in_place>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz " as core::fmt::Debug>::fmt" + .asciz "vfscore::file::VfsFile::poll" + .asciz "vfscore::file::VfsFile::flush" + .asciz "vfscore::file::VfsFile::ioctl" + .asciz "vfscore::file::VfsFile::read_at" + .asciz "vfscore::file::VfsFile::readdir" + .asciz "vfscore::file::VfsFile::write_at" + .asciz " as vfscore::file::VfsFile>::readdir" + .asciz " as vfscore::inode::VfsInode>::inode_type" + .asciz " as vfscore::inode::VfsInode>::list_xattr" + .asciz " as vfscore::inode::VfsInode>::rmdir" + .asciz " as vfscore::inode::VfsInode>::create" + .asciz " as vfscore::inode::VfsInode>::lookup" + .asciz " as vfscore::inode::VfsInode>::symlink" + .asciz " as vfscore::inode::VfsInode>::readlink" + .asciz " as vfscore::inode::VfsInode>::truncate" + .asciz " as vfscore::inode::VfsInode>::inode_type" + .asciz " as vfscore::inode::VfsInode>::update_time" + .asciz " as vfscore::inode::VfsInode>::update_time" + .asciz " as vfscore::inode::VfsInode>::get_super_block" + .asciz " as vfscore::inode::VfsInode>::get_super_block" + .asciz " as vfscore::inode::VfsInode>::link" + .asciz " as vfscore::inode::VfsInode>::rmdir" + .asciz " as vfscore::inode::VfsInode>::create" + .asciz " as vfscore::inode::VfsInode>::lookup" + .asciz " as vfscore::inode::VfsInode>::unlink" + .asciz " as vfscore::inode::VfsInode>::get_attr" + .asciz " as vfscore::inode::VfsInode>::readlink" + .asciz " as vfscore::inode::VfsInode>::set_attr" + .asciz " as vfscore::inode::VfsInode>::truncate" + .asciz " as vfscore::inode::VfsInode>::node_perm" + .asciz " as vfscore::inode::VfsInode>::node_perm" + .asciz " as vfscore::inode::VfsInode>::rename_to" + .asciz " as vfscore::file::VfsFile>::readdir" + .asciz " as vfscore::inode::VfsInode>::list_xattr" + .asciz " as vfscore::inode::VfsInode>::link" + .asciz " as vfscore::inode::VfsInode>::rmdir" + .asciz " as vfscore::inode::VfsInode>::create" + .asciz " as vfscore::inode::VfsInode>::lookup" + .asciz " as vfscore::inode::VfsInode>::unlink" + .asciz " as vfscore::inode::VfsInode>::unlink::closure" + .asciz " as vfscore::inode::VfsInode>::symlink" + .asciz " as vfscore::inode::VfsInode>::get_attr" + .asciz " as vfscore::inode::VfsInode>::set_attr" + .asciz " as vfscore::inode::VfsInode>::rename_to" + .asciz " as vfscore::file::VfsFile>::ioctl" + .asciz " as vfscore::inode::VfsInode>::inode_type" + .asciz " as vfscore::inode::VfsInode>::inode_type" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::into_any" + .asciz "core::ptr::drop_in_place>>" + .asciz "fatfs::io::Write::write_all" + .asciz "fatfs::file::File::set_first_cluster" + .asciz "fatfs::file::File::abs_pos" + .asciz "fatfs::file::File::truncate" + .asciz " as fatfs::io::Read>::read" + .asciz " as fatfs::io::Seek>::seek" + .asciz " as fatfs::io::Write>::write" + .asciz " as core::clone::Clone>::clone" + .asciz "vfscore::inode::VfsInode::link" + .asciz "vfscore::inode::VfsInode::link" + .asciz "vfscore::inode::VfsInode::rename_to" + .asciz "vfscore::inode::VfsInode::rename_to" + .asciz " as core::ops::drop::Drop>::drop" + .asciz " as vfscore::file::VfsFile>::poll" + .asciz " as vfscore::file::VfsFile>::flush" + .asciz " as vfscore::file::VfsFile>::fsync" + .asciz " as vfscore::file::VfsFile>::ioctl" + .asciz " as vfscore::file::VfsFile>::read_at" + .asciz " as vfscore::file::VfsFile>::write_at" + .asciz " as vfscore::inode::VfsInode>::update_time" + .asciz " as vfscore::inode::VfsInode>::get_super_block" + .asciz " as vfscore::inode::VfsInode>::link" + .asciz " as vfscore::inode::VfsInode>::link" + .asciz " as vfscore::inode::VfsInode>::get_attr" + .asciz " as vfscore::inode::VfsInode>::node_perm" + .asciz " as vfscore::inode::VfsInode>::node_perm" + .asciz " as vfscore::inode::VfsInode>::rename_to" + .asciz " as vfscore::inode::VfsInode>::rename_to" + .asciz " as vfscore::superblock::VfsSuperBlock>::super_type" + .asciz " as vfscore::superblock::VfsSuperBlock>::sync_fs" + .asciz " as vfscore::file::VfsFile>::poll" + .asciz " as vfscore::file::VfsFile>::read_at" + .asciz " as vfscore::file::VfsFile>::write_at" + .asciz " as vfscore::inode::VfsInode>::list_xattr" + .asciz " as vfscore::inode::VfsInode>::update_time" + .asciz " as vfscore::inode::VfsInode>::get_super_block" + .asciz " as vfscore::inode::VfsInode>::get_attr" + .asciz " as vfscore::inode::VfsInode>::set_attr" + .asciz " as vfscore::inode::VfsInode>::truncate" + .asciz "::read_at" + .asciz "::read_at" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ops::function::impls:: for &mut F>::call_mut" + .asciz "core::ptr::drop_in_place<&u8>" + .asciz "spin::once::Once::try_call_once" + .asciz "spin::once::Once::try_call_once" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "fatfs::dir_entry::DirEntryData::deserialize" + .asciz "fatfs::dir_entry::DirEntryEditor::flush" + .asciz "fatfs::dir_entry::DirLfnEntryData::serialize" + .asciz "fatfs::dir_entry::DirFileEntryData::serialize" + .asciz "fatfs::dir_entry::DirEntry::eq_name" + .asciz "fatfs::dir_entry::DirEntry::file_name" + .asciz "::read_u16_le" + .asciz "::read_u32_le" + .asciz "core::ptr::drop_in_place>" + .asciz "core::ptr::drop_in_place>" + .asciz "fatfs::io::Read::read_exact" + .asciz "fatfs::io::Write::write_all" + .asciz "fatfs::dir::Dir::create_dir" + .asciz "fatfs::dir::Dir::find_entry" + .asciz "fatfs::dir::Dir::create_file" + .asciz "fatfs::dir::Dir::write_entry" + .asciz "fatfs::dir::Dir::rename_internal" + .asciz "fatfs::dir::Dir::create_sfn_entry" + .asciz "fatfs::dir::Dir::remove" + .asciz "fatfs::dir::Dir::rename" + .asciz "fatfs::dir::Dir::open_dir" + .asciz "fatfs::dir::Dir::open_file" + .asciz " as core::iter::traits::iterator::Iterator>::next" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "::read_u16_le" + .asciz "::read_u32_le" + .asciz "::read_u8" + .asciz "core::ptr::drop_in_place<&()>" + .asciz "fatfs::boot_sector::BootSector::deserialize" + .asciz "fatfs::boot_sector::BootSector::validate" + .asciz "fatfs::boot_sector::BiosParameterBlock::validate_total_sectors" + .asciz "fatfs::boot_sector::BiosParameterBlock::validate_total_clusters" + .asciz "fatfs::boot_sector::BiosParameterBlock::validate_sectors_per_fat" + .asciz "fatfs::io::Read::read_exact" + .asciz "fatfs::io::Write::write_all" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz " as core::fmt::Debug>::fmt" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "core::ptr::drop_in_place>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>" + .asciz "core::ptr::drop_in_place<&fatfs::error::Error<()>>" + .asciz "fat_vfs::inode::dir::FatFsDirInode::delete_file" + .asciz "fat_vfs::inode::file::FatFsFileInode::new" + .asciz "vfscore::file::VfsFile::poll" + .asciz "vfscore::file::VfsFile::flush" + .asciz "vfscore::file::VfsFile::read_at" + .asciz "vfscore::file::VfsFile::readdir" + .asciz "vfscore::file::VfsFile::write_at" + .asciz " as vfscore::file::VfsFile>::ioctl" + .asciz " as vfscore::file::VfsFile>::readdir" + .asciz " as vfscore::inode::VfsInode>::inode_type" + .asciz " as vfscore::inode::VfsInode>::list_xattr" + .asciz " as vfscore::inode::VfsInode>::update_time" + .asciz " as vfscore::inode::VfsInode>::get_super_block" + .asciz " as vfscore::inode::VfsInode>::link" + .asciz " as vfscore::inode::VfsInode>::rmdir" + .asciz " as vfscore::inode::VfsInode>::create" + .asciz " as vfscore::inode::VfsInode>::lookup" + .asciz " as vfscore::inode::VfsInode>::unlink" + .asciz " as vfscore::inode::VfsInode>::symlink" + .asciz " as vfscore::inode::VfsInode>::get_attr" + .asciz " as vfscore::inode::VfsInode>::readlink" + .asciz " as vfscore::inode::VfsInode>::set_attr" + .asciz " as vfscore::inode::VfsInode>::truncate" + .asciz " as vfscore::inode::VfsInode>::node_perm" + .asciz " as vfscore::inode::VfsInode>::rename_to" + .asciz " as vfscore::file::VfsFile>::flush" + .asciz " as vfscore::file::VfsFile>::read_at" + .asciz " as vfscore::file::VfsFile>::write_at" + .asciz " as vfscore::inode::VfsInode>::inode_type" + .asciz " as vfscore::inode::VfsInode>::get_super_block" + .asciz " as vfscore::inode::VfsInode>::rmdir" + .asciz " as vfscore::inode::VfsInode>::create" + .asciz " as vfscore::inode::VfsInode>::lookup" + .asciz " as vfscore::inode::VfsInode>::get_attr" + .asciz " as vfscore::inode::VfsInode>::readlink" + .asciz " as vfscore::inode::VfsInode>::truncate" + .asciz " as vfscore::inode::VfsInode>::rename_to" + .asciz "::type_id" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::as_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "::into_any" + .asciz "core::fmt::Write::write_char" + .asciz "core::fmt::Write::write_fmt" + .asciz "core::ops::function::FnOnce::call_once" + .asciz "core::ptr::drop_in_place>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place>" + .asciz " as vfscore::fstype::VfsFsType>::fs_flag" + .asciz " as vfscore::fstype::VfsFsType>::fs_name" + .asciz " as vfscore::fstype::VfsFsType>::mount" + .asciz " as vfscore::fstype::VfsFsType>::fs_name" + .asciz " as vfscore::fstype::VfsFsType>::kill_sb" + .asciz " as vfscore::fstype::VfsFsType>::fs_flag" + .asciz " as vfscore::fstype::VfsFsType>::fs_name" + .asciz "vfscore::file::VfsFile::poll" + .asciz "vfscore::file::VfsFile::flush" + .asciz "vfscore::file::VfsFile::ioctl" + .asciz "vfscore::file::VfsFile::read_at" + .asciz "vfscore::file::VfsFile::write_at" + .asciz ">::extend" + .asciz " as vfscore::inode::VfsInode>::inode_type" + .asciz " as vfscore::inode::VfsInode>::readlink" + .asciz " as vfscore::inode::VfsInode>::truncate" + .asciz "vfs::ram::init_ramfs" + .asciz "vfs::init_filesystem" + .asciz "::write_str" + .asciz "::type_id" + .asciz "::type_id" + .asciz "::type_id" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "::as_any_mut" + .asciz "::into_any_rc" + .asciz "::as_any" + .asciz "::into_any" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "core::ptr::drop_in_place>" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "alloc::vec::Vec::remove" + .asciz "alloc::string::String::push" + .asciz "vfscore::inode::VfsInode::link" + .asciz "vfscore::inode::VfsInode::link" + .asciz "vfscore::inode::VfsInode::rename_to" + .asciz "vfscore::inode::VfsInode::rename_to" + .asciz " as vfscore::superblock::VfsSuperBlock>::super_type" + .asciz " as vfscore::superblock::VfsSuperBlock>::sync_fs" + .asciz " as alloc::vec::spec_from_iter::SpecFromIter>::from_iter" + .asciz " as alloc::vec::spec_from_iter::SpecFromIter>::from_iter" + .asciz " as vfscore::inode::VfsInode>::list_xattr" + .asciz " as vfscore::inode::VfsInode>::update_time" + .asciz " as vfscore::inode::VfsInode>::get_super_block" + .asciz " as vfscore::inode::VfsInode>::link" + .asciz " as vfscore::inode::VfsInode>::get_attr" + .asciz " as vfscore::inode::VfsInode>::readlink" + .asciz " as vfscore::inode::VfsInode>::set_attr" + .asciz " as vfscore::inode::VfsInode>::node_perm" + .asciz " as vfscore::inode::VfsInode>::rename_to" + .asciz "::fmt" + .asciz "vfs::kfile::KernelFile::new" + .asciz "::read" + .asciz "::write" + .asciz "::read_at" + .asciz "::write_at" + .asciz "::flush" + .asciz "::fsync" + .asciz "::seek" + .asciz "::get_attr" + .asciz "::ioctl" + .asciz "::set_open_flag" + .asciz "::get_open_flag" + .asciz "::dentry" + .asciz "::inode" + .asciz "::readdir" + .asciz "::truncate" + .asciz "::is_readable" + .asciz "::is_writable" + .asciz "::is_append" + .asciz "::poll" + .asciz "::drop" + .asciz "vfs::proc::filesystem::SystemSupportFS::serialize" + .asciz "::read_at" + .asciz "::get_attr" + .asciz "::read_at" + .asciz "::get_attr" + .asciz "device_interface::LowBlockDevice::flush" + .asciz "device_interface::LowBlockDevice::flush" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "::can_receive" + .asciz "::can_transmit" + .asciz "::rx_queue_size" + .asciz "::recycle_tx_buffers" + .asciz "::now" + .asciz "::have_space_to_put" + .asciz "::resolution" + .asciz "::update_cursor" + .asciz "::get_framebuffer" + .asciz "::capacity" + .asciz "::capacity" + .asciz "devices::init_device" + .asciz "devices::init_virtio_mmio" + .asciz "devices::init_block_device::sleep" + .asciz "devices::init_input_device" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "::read_at" + .asciz "::write_at" + .asciz "::poll" + .asciz "::ioctl" + .asciz "fdt::node::all_nodes::closure" + .asciz " as core::ops::drop::Drop>::drop" + .asciz "::write_at" + .asciz "::flush" + .asciz "::fsync" + .asciz "::probe_virtio" + .asciz "::probe_common" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "::type_id" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "core::panicking::assert_failed" + .asciz "<(U,T) as core::fmt::Debug>::fmt" + .asciz "::read_at" + .asciz "::write_at" + .asciz "::poll" + .asciz "::ioctl" + .asciz "::get_attr" + .asciz "::read_at" + .asciz "::poll" + .asciz "::read_at" + .asciz "::write_at" + .asciz "::ioctl" + .asciz "alloc::raw_vec::finish_grow" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "core::ops::function::FnOnce::call_once" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "interrupt::ext_interrupt::external_interrupt_handler" + .asciz "interrupt::record::write_irq_info" + .asciz "interrupt::record::interrupts_info" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::raw_vec::finish_grow" + .asciz "alloc::raw_vec::RawVec::reserve::do_reserve_and_handle" + .asciz " as core::iter::traits::iterator::Iterator>::next" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "interrupt::init_plic" + .asciz "interrupt::register_device_to_plic" + .asciz "plic::write" + .asciz "plic::read" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "alloc::collections::vec_deque::VecDeque::grow" + .asciz "alloc::collections::vec_deque::VecDeque::grow" + .asciz "alloc::collections::vec_deque::VecDeque::grow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz " as core::fmt::Debug>::fmt" + .asciz "::dma_dealloc" + .asciz "::_init" + .asciz "::_put" + .asciz "::_read" + .asciz "virtio_drivers::device::blk::VirtIOBlk::new" + .asciz "alloc::raw_vec::finish_grow" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "virtio_drivers::queue::VirtQueue::add_notify_wait_pop" + .asciz "virtio_drivers::queue::VirtQueue::add_notify_wait_pop" + .asciz "virtio_drivers::queue::VirtQueue::add" + .asciz "virtio_drivers::queue::VirtQueue::new" + .asciz "virtio_drivers::queue::VirtQueue::new" + .asciz "virtio_drivers::queue::VirtQueue::new" + .asciz "virtio_drivers::queue::VirtQueue::pop_used" + .asciz "virtio_drivers::transport::Transport::begin_init" + .asciz "virtio_drivers::transport::Transport::begin_init" + .asciz "virtio_drivers::transport::Transport::begin_init" + .asciz "virtio_drivers::device::input::VirtIOInput::pop_pending_event" + .asciz "virtio_drivers::device::input::VirtIOInput::new" + .asciz "core::ptr::drop_in_place<&u8>" + .asciz "core::ptr::drop_in_place" + .asciz "core::panicking::assert_failed" + .asciz "core::panicking::assert_failed" + .asciz "::yield_now" + .asciz "drivers::uart::Uart::new" + .asciz "::put" + .asciz "::get" + .asciz "::put_bytes" + .asciz "::have_data_to_get" + .asciz "::hand_irq" + .asciz "drivers::register_task_func" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "drivers::input::VirtIOInputDriver::from_addr" + .asciz "::is_empty" + .asciz "::read_event_with_block" + .asciz "::read_event_without_block" + .asciz "::hand_irq" + .asciz "::_init" + .asciz "::_put" + .asciz "::_read" + .asciz "core::ptr::drop_in_place<&usize>" + .asciz "::drop" + .asciz "drivers::block_device::GenericBlockDevice::new" + .asciz "::read" + .asciz "::write" + .asciz "::size" + .asciz "drivers::block_device::VirtIOBlkWrapper::from_mmio" + .asciz "::read_block" + .asciz "::write_block" + .asciz "::read_block" + .asciz "::write_block" + .asciz "lru::LruCache::new" + .asciz "lru::LruCache::capturing_put" + .asciz "lru::LruCache::get" + .asciz "lru::LruCache::get_mut" + .asciz "hashbrown::raw::RawTable::reserve_rehash" + .asciz "hashbrown::raw::RawTableInner::fallible_with_capacity" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "drivers::gpu::VirtIOGpuWrapper::new" + .asciz "::hand_irq" + .asciz "::flush" + .asciz "drivers::rtc::GoldFishRtc::read_time_string" + .asciz "::hand_irq" + .asciz "::read_time" + .asciz "virtio_drivers::device::gpu::VirtIOGpu::get_display_info" + .asciz "virtio_drivers::device::gpu::VirtIOGpu::setup_framebuffer" + .asciz "virtio_drivers::device::gpu::VirtIOGpu::new" + .asciz "virtio_drivers::device::gpu::VirtIOGpu::flush" + .asciz "::read_time" + .asciz "::clear_irq" + .asciz "::read_alarm" + .asciz "::set_alarm" + .asciz "::fmt" + .asciz ">::from" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "time::date_time::DateTime::checked_to_offset" + .asciz "time::date::Date::from_julian_day_unchecked" + .asciz "time::date::Date::month_day" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "time::offset_date_time::OffsetDateTime::to_offset" + .asciz "time::offset_date_time::OffsetDateTime::from_unix_timestamp_nanos" + .asciz "time::offset_date_time::OffsetDateTime::month" + .asciz "time::offset_date_time::OffsetDateTime::day" + .asciz "time::expect_failed" + .asciz "time::expect_failed::panic_cold_display" + .asciz "::type_id" + .asciz "core::ptr::drop_in_place" + .asciz "alloc::collections::vec_deque::VecDeque::grow" + .asciz "alloc::raw_vec::finish_grow" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "::mac_address" + .asciz "::recycle_rx_buffer" + .asciz "::transmit" + .asciz "::receive" + .asciz "::alloc_tx_buffer" + .asciz "::packet_mut" + .asciz "::packet_len" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "netcore::tcp::TcpSocket::connect" + .asciz "netcore::tcp::TcpSocket::bind" + .asciz "netcore::tcp::TcpSocket::listen" + .asciz "netcore::tcp::TcpSocket::accept" + .asciz "netcore::tcp::TcpSocket::shutdown" + .asciz "netcore::tcp::TcpSocket::recv" + .asciz "netcore::tcp::TcpSocket::send" + .asciz "netcore::tcp::TcpSocket::poll" + .asciz "netcore::tcp::TcpSocket::poll_connect" + .asciz "::drop" + .asciz "netcore::tcp::get_ephemeral_port" + .asciz "core::ptr::drop_in_place" + .asciz "::poll" + .asciz "netcore::interface::SocketSetWrapper::new_udp_socket" + .asciz "netcore::interface::SocketSetWrapper::with_socket" + .asciz "netcore::interface::SocketSetWrapper::with_socket" + .asciz "netcore::interface::SocketSetWrapper::with_socket" + .asciz "netcore::interface::SocketSetWrapper::with_socket" + .asciz "netcore::interface::SocketSetWrapper::with_socket_mut" + .asciz "netcore::interface::SocketSetWrapper::with_socket_mut" + .asciz "netcore::interface::SocketSetWrapper::with_socket_mut" + .asciz "netcore::interface::SocketSetWrapper::with_socket_mut" + .asciz "netcore::interface::SocketSetWrapper::with_socket_mut" + .asciz "netcore::interface::SocketSetWrapper::with_socket_mut" + .asciz "netcore::interface::SocketSetWrapper::with_socket_mut" + .asciz "netcore::interface::SocketSetWrapper::with_socket_mut" + .asciz "netcore::interface::SocketSetWrapper::with_socket_mut" + .asciz "netcore::interface::SocketSetWrapper::remove" + .asciz "core::ptr::drop_in_place" + .asciz "::receive" + .asciz "::consume" + .asciz "::preprocess" + .asciz "::consume" + .asciz "::consume" + .asciz "::consume" + .asciz "netcore::device::NetDeviceWrapper::bench_transmit_bandwidth" + .asciz "smoltcp::socket::tcp::Socket::new" + .asciz "smoltcp::socket::tcp::Socket::connect" + .asciz "smoltcp::socket::tcp::Socket::dispatch" + .asciz "smoltcp::storage::ring_buffer::RingBuffer::dequeue_one_with" + .asciz "smoltcp::storage::ring_buffer::RingBuffer::dequeue_one_with" + .asciz "smoltcp::storage::ring_buffer::RingBuffer::dequeue_one_with" + .asciz "smoltcp::storage::ring_buffer::RingBuffer::dequeue_one_with" + .asciz "smoltcp::storage::ring_buffer::RingBuffer::dequeue_one_with" + .asciz "smoltcp::storage::ring_buffer::RingBuffer::dequeue_one_with" + .asciz "core::ptr::drop_in_place>" + .asciz "netcore::udp::UdpSocket::new" + .asciz "netcore::udp::UdpSocket::local_addr" + .asciz "netcore::udp::UdpSocket::peer_addr" + .asciz "netcore::udp::UdpSocket::bind" + .asciz "netcore::udp::UdpSocket::send_to" + .asciz "netcore::udp::UdpSocket::recv_from" + .asciz "netcore::udp::UdpSocket::connect" + .asciz "netcore::udp::UdpSocket::send" + .asciz "netcore::udp::UdpSocket::shutdown" + .asciz "netcore::udp::UdpSocket::poll" + .asciz "netcore::udp::UdpSocket::send_impl" + .asciz "::drop" + .asciz "core::ptr::drop_in_place>>" + .asciz "::default" + .asciz "netcore::listen_table::ListenTable::new" + .asciz "netcore::listen_table::ListenTable::listen" + .asciz "netcore::listen_table::ListenTable::unlisten" + .asciz "netcore::listen_table::ListenTable::can_accept" + .asciz "netcore::listen_table::ListenTable::accept" + .asciz "netcore::listen_table::ListenTable::incoming_tcp_packet" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "core::ptr::drop_in_place" + .asciz "smoltcp::iface::interface::InterfaceInner::dispatch_ip" + .asciz "smoltcp::iface::interface::Interface::poll" + .asciz "smoltcp::socket::dns::Socket::dispatch" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place<&bool>" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "smoltcp::wire::ipv4::Repr::emit" + .asciz "smoltcp::wire::ipv4::Repr::parse" + .asciz "::fmt" + .asciz "::fmt" + .asciz " as core::iter::traits::iterator::Iterator>::try_fold" + .asciz ">::from" + .asciz "smoltcp::wire::icmpv4::Repr::parse" + .asciz "smoltcp::socket::udp::Socket::send_slice" + .asciz "smoltcp::iface::socket_set::SocketSet::add" + .asciz "smoltcp::iface::socket_set::SocketSet::add" + .asciz "alloc::raw_vec::finish_grow" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "<&mut T as core::fmt::Display>::fmt" + .asciz "smoltcp::wire::arp::Repr::emit" + .asciz "smoltcp::wire::dns::Repr::emit" + .asciz "smoltcp::storage::packet_buffer::PacketBuffer::enqueue" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place<&u16>" + .asciz "core::panicking::assert_failed" + .asciz "core::panicking::assert_failed" + .asciz "alloc::collections::vec_deque::VecDeque::grow" + .asciz "smoltcp::iface::socket_meta::Meta::egress_permitted" + .asciz "netcore::interface::SocketSetWrapper::new" + .asciz "netcore::init_net" + .asciz "netcore::poll_interfaces" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "::fmt" + .asciz "smoltcp::socket::tcp::RttEstimator::retransmission_timeout" + .asciz "smoltcp::socket::tcp::RttEstimator::on_send" + .asciz "smoltcp::socket::tcp::RttEstimator::on_retransmit" + .asciz "smoltcp::socket::tcp::Socket::reset" + .asciz "smoltcp::socket::tcp::Socket::close" + .asciz "smoltcp::socket::tcp::Socket::send_slice" + .asciz "smoltcp::socket::tcp::Socket::recv_slice" + .asciz "smoltcp::socket::tcp::Socket::set_state" + .asciz "smoltcp::socket::tcp::Socket::rst_reply" + .asciz "smoltcp::socket::tcp::Socket::ack_reply" + .asciz "smoltcp::socket::tcp::Socket::accepts" + .asciz "smoltcp::socket::tcp::Socket::process" + .asciz "smoltcp::socket::tcp::Socket::seq_to_transmit" + .asciz "smoltcp::socket::tcp::Socket::ack_to_transmit" + .asciz "smoltcp::socket::tcp::Socket::window_to_update" + .asciz "::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "smoltcp::socket::dns::DnsQuery::set_state" + .asciz "smoltcp::socket::dns::Socket::process" + .asciz "smoltcp::socket::dns::eq_names" + .asciz "smoltcp::socket::dns::copy_name" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "core::ptr::drop_in_place<&u8>" + .asciz " as core::iter::traits::iterator::Iterator>::fold" + .asciz "::fmt" + .asciz ">::add" + .asciz ">::sub" + .asciz "::sub" + .asciz "smoltcp::wire::tcp::TcpOption::parse" + .asciz "smoltcp::wire::tcp::TcpOption::emit" + .asciz "smoltcp::wire::tcp::Repr::parse" + .asciz "smoltcp::wire::tcp::Repr::buffer_len" + .asciz "smoltcp::wire::tcp::Repr::emit" + .asciz "::fmt" + .asciz "::fmt" + .asciz "smoltcp::iface::interface::ethernet::::process_ethernet" + .asciz "smoltcp::iface::interface::ipv4::::process_ipv4" + .asciz "smoltcp::iface::interface::ipv4::::icmpv4_reply" + .asciz "smoltcp::iface::interface::InterfaceInner::get_source_address" + .asciz "smoltcp::iface::interface::InterfaceInner::get_source_address_ipv4" + .asciz "smoltcp::iface::interface::InterfaceInner::check_ip_addrs" + .asciz "smoltcp::iface::interface::InterfaceInner::process_ip" + .asciz "smoltcp::iface::interface::InterfaceInner::is_broadcast" + .asciz "smoltcp::iface::interface::InterfaceInner::process_udp" + .asciz "smoltcp::iface::interface::InterfaceInner::route" + .asciz "smoltcp::iface::interface::InterfaceInner::has_neighbor" + .asciz "smoltcp::iface::interface::InterfaceInner::flush_cache" + .asciz "smoltcp::wire::udp::Packet<&T>::payload" + .asciz "::fmt" + .asciz "core::ptr::drop_in_place<&smoltcp::storage::packet_buffer::PacketMetadata>" + .asciz "core::ptr::drop_in_place<&smoltcp::storage::packet_buffer::PacketMetadata>" + .asciz "core::ptr::drop_in_place<&u8>" + .asciz "core::ptr::drop_in_place<&alloc::vec::Vec>" + .asciz "core::ptr::drop_in_place<&smoltcp::wire::ip::Address>" + .asciz "core::ptr::drop_in_place<&smoltcp::iface::route::Route>" + .asciz "core::ptr::drop_in_place<&smoltcp::iface::neighbor::Neighbor>" + .asciz "core::ptr::drop_in_place<&smoltcp::storage::assembler::Contig>" + .asciz "core::ptr::drop_in_place<&smoltcp::iface::socket_set::SocketStorage>" + .asciz "core::ptr::drop_in_place<&core::option::Option<(u32,u32)>>" + .asciz "core::ptr::drop_in_place<&core::option::Option>" + .asciz "core::ptr::drop_in_place<&smoltcp::storage::packet_buffer::PacketMetadata<()>>" + .asciz "smoltcp::wire::icmpv4::Repr::parse" + .asciz "smoltcp::wire::icmpv4::Repr::emit" + .asciz ">::from" + .asciz "smoltcp::iface::neighbor::Cache::fill" + .asciz "smoltcp::iface::neighbor::Cache::lookup" + .asciz "smoltcp::socket::udp::Socket::recv_slice" + .asciz "smoltcp::socket::udp::Socket::process" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "smoltcp::iface::route::Routes::add_default_ipv4_route" + .asciz "smoltcp::iface::route::Routes::lookup" + .asciz "smoltcp::wire::ip::Version::of_packet" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "smoltcp::wire::ip::Cidr::new" + .asciz "::fmt" + .asciz "::fmt" + .asciz "smoltcp::wire::HardwareAddress::ethernet_or_panic" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "smoltcp::iface::ip_packet::IpPacket::emit_payload" + .asciz "smoltcp::storage::packet_buffer::PacketBuffer::enqueue" + .asciz "smoltcp::storage::packet_buffer::PacketBuffer::enqueue" + .asciz "smoltcp::storage::packet_buffer::PacketBuffer::enqueue" + .asciz "smoltcp::storage::packet_buffer::PacketBuffer::dequeue" + .asciz "smoltcp::storage::ring_buffer::RingBuffer::dequeue_one_with" + .asciz "smoltcp::storage::ring_buffer::RingBuffer::enqueue_slice" + .asciz "smoltcp::storage::ring_buffer::RingBuffer::dequeue_slice" + .asciz "smoltcp::storage::ring_buffer::RingBuffer::write_unallocated" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "smoltcp::wire::ipv4::Address::from_bytes" + .asciz "::fmt" + .asciz "smoltcp::wire::ipv4::Repr::parse" + .asciz "smoltcp::wire::ipv4::Repr::emit" + .asciz ">::from" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "::fmt" + .asciz "smoltcp::wire::arp::Repr::parse" + .asciz "smoltcp::wire::ethernet::Address::from_bytes" + .asciz "::fmt" + .asciz "smoltcp::iface::socket_meta::Meta::neighbor_missing" + .asciz "smoltcp::socket::icmp::Socket::accepts" + .asciz "smoltcp::socket::icmp::Socket::process" + .asciz "smoltcp::wire::ip::checksum::data" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place<&&mut alloc::collections::vec_deque::VecDeque>>" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "smoltcp::wire::dns::Packet::rcode" + .asciz "smoltcp::wire::dns::Question::parse" + .asciz "smoltcp::wire::dns::Question::emit" + .asciz "smoltcp::wire::dns::Record::parse" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "smoltcp::storage::assembler::Assembler::add" + .asciz "smoltcp::wire::udp::Packet::verify_checksum" + .asciz "smoltcp::wire::udp::Repr::emit" + .asciz "::fmt" + .asciz "smoltcp::iface::socket_set::SocketSet::add::put" + .asciz "smoltcp::iface::socket_set::SocketSet::remove" + .asciz "smoltcp::iface::socket_set::SocketSet::items" + .asciz "smoltcp::iface::socket_set::SocketSet::items_mut" + .asciz "smoltcp::socket::raw::Socket::process" + .asciz "::fmt" + .asciz "<() as core::fmt::Debug>::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place<()>" + .asciz "visionfive2_sd::send_cmd" + .asciz "visionfive2_sd::Vf2SdDriver::read_block" + .asciz "visionfive2_sd::Vf2SdDriver::write_block" + .asciz "core::ptr::drop_in_place" + .asciz ">::from" + .asciz ">::try_from" + .asciz ">::try_from" + .asciz ">::try_from" + .asciz ">::try_from" + .asciz ">::try_from" + .asciz ">::try_from" + .asciz ">::try_from" + .asciz ">::try_from" + .asciz ">::try_from" + .asciz ">::try_from" + .asciz ">::try_from" + .asciz ">::try_from" + .asciz ">::try_from" + .asciz "::fmt" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<() as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place<&u8>" + .asciz "core::ptr::drop_in_place<()>" + .asciz "core::panicking::assert_failed" + .asciz "visionfive2_sd::utils::wait_ms" + .asciz "visionfive2_sd::utils::wait_ms" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "bit_struct::types::u5::new" + .asciz "bit_struct::types::u6::new" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "<&mut T as core::fmt::Debug>::fmt" + .asciz "mem::frame::init_frame_allocator" + .asciz "alloc_frames" + .asciz "free_frames" + .asciz "::drop" + .asciz "mem::frame::alloc_frame_trackers" + .asciz "::alloc_frame" + .asciz "::dealloc_frame" + .asciz "::alloc_contiguous_frames" + .asciz "::alloc" + .asciz "::dealloc" + .asciz "mem::heap::HeapAllocator::init" + .asciz "core::fmt::num::::fmt" + .asciz "core::ops::function::FnOnce::call_once" + .asciz "core::ptr::drop_in_place" + .asciz "alloc::raw_vec::finish_grow" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "mem::manager::FrameRefManager::add_ref" + .asciz "mem::manager::FrameRefManager::dec_ref" + .asciz "core::fmt::num::::fmt" + .asciz "core::ops::function::FnOnce::call_once" + .asciz "core::ptr::drop_in_place" + .asciz "mem::vmm::build_kernel_address_space" + .asciz "mem::vmm::kernel_satp" + .asciz "mem::vmm::query_kernel_space" + .asciz "page_table::table::bits64::PageTable64::map_region" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place<&usize>" + .asciz "core::panicking::assert_failed" + .asciz "talc::alloc_error" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "alloc::collections::btree::map::BTreeMap::insert" + .asciz "alloc::collections::btree::map::BTreeMap::remove" + .asciz "mem::init_memory_system" + .asciz "__rust_alloc" + .asciz "__rust_dealloc" + .asciz "__rust_realloc" + .asciz "__rust_alloc_zeroed" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::Handle,alloc::collections::btree::node::marker::Edge>::insert_recursing" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_left" + .asciz "alloc::collections::btree::node::BalancingContext::bulk_steal_right" + .asciz "alloc::collections::btree::node::BalancingContext::merge_tracking_child_edge" + .asciz "alloc::collections::btree::node::BalancingContext::do_merge" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_leaf_kv" + .asciz "alloc::collections::btree::remove::,alloc::collections::btree::node::marker::KV>>::remove_kv_tracking" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz " as pager::PageAllocatorExt>::alloc_pages" + .asciz "talc::Talc::malloc" + .asciz "talc::Talc::free" + .asciz "talc::Talc::init" + .asciz "talc::talck::Talck::talc" + .asciz "::alloc" + .asciz "::dealloc" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place<&usize>" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz ">::from" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "core::ptr::drop_in_place>" + .asciz "virtio_drivers::transport::mmio::MmioTransport::new" + .asciz "virtio_drivers::transport::mmio::MmioTransport::vendor_id" + .asciz "::device_type" + .asciz "::read_device_features" + .asciz "::write_driver_features" + .asciz "::max_queue_size" + .asciz "::notify" + .asciz "::set_status" + .asciz "::set_guest_page_size" + .asciz "::queue_set" + .asciz "::queue_unset" + .asciz "::queue_used" + .asciz "::ack_interrupt" + .asciz "::drop" + .asciz "::fmt" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place>>" + .asciz "::fmt" + .asciz "bitflags::parser::to_writer" + .asciz "bitflags::parser::to_writer" + .asciz "bitflags::parser::to_writer" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::LowerHex>::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place<&u8>" + .asciz "core::panicking::assert_failed" + .asciz "virtio_drivers::queue::queue_part_sizes" + .asciz "::next" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "::write" + .asciz "::flush" + .asciz "::read" + .asciz "::seek" + .asciz "fatfs::dir::split_path" + .asciz "fatfs::dir::lfn_checksum" + .asciz "fatfs::dir::LongNameBuilder::into_buf" + .asciz "fatfs::dir::LongNameBuilder::process" + .asciz "fatfs::dir::LongNameBuilder::validate_chksum" + .asciz "fatfs::dir::LfnEntriesGenerator::new" + .asciz "::next" + .asciz "::size_hint" + .asciz "fatfs::dir::ShortNameGenerator::new" + .asciz "fatfs::dir::ShortNameGenerator::copy_short_name_part" + .asciz "fatfs::dir::ShortNameGenerator::add_existing" + .asciz "fatfs::dir::ShortNameGenerator::generate" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "core::array::::fmt" + .asciz "core::array::::fmt" + .asciz "core::array::::fmt" + .asciz "alloc::raw_vec::finish_grow" + .asciz "alloc::raw_vec::RawVec::reserve::do_reserve_and_handle" + .asciz "fatfs::fs::FsInfoSector::validate_and_fix" + .asciz "::fmt" + .asciz "core::str::::trim_matches" + .asciz "fatfs::boot_sector::BiosParameterBlock::root_dir_sectors" + .asciz "fatfs::boot_sector::BiosParameterBlock::first_data_sector" + .asciz "fatfs::boot_sector::BiosParameterBlock::total_clusters" + .asciz "fatfs::boot_sector::BiosParameterBlock::clusters_from_bytes" + .asciz "::default" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "fatfs::dir_entry::ShortName::new" + .asciz "fatfs::dir_entry::ShortName::as_bytes" + .asciz "fatfs::dir_entry::DirFileEntryData::new" + .asciz "fatfs::dir_entry::DirFileEntryData::renamed" + .asciz "fatfs::dir_entry::DirFileEntryData::lowercase_name" + .asciz "fatfs::dir_entry::DirEntryEditor::set_modified" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "core::ptr::drop_in_place>>" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::str::iter::SplitInternal

::next_back" + .asciz "core::error::Error::description" + .asciz "core::error::Error::source" + .asciz "core::error::Error::source" + .asciz "core::error::Error::provide" + .asciz "core::error::Error::provide" + .asciz "alloc::alloc::exchange_malloc" + .asciz "::fmt" + .asciz "::description" + .asciz "::fmt" + .asciz "vfscore::path::VfsPath::new" + .asciz "vfscore::path::VfsPath::open" + .asciz "vfscore::path::VfsPath::create" + .asciz "vfscore::path::VfsPath::get_parent" + .asciz "vfscore::path::VfsPath::parent" + .asciz "vfscore::path::VfsPath::exists" + .asciz "vfscore::path::VfsPath::filename" + .asciz "vfscore::path::VfsPath::mount" + .asciz "vfscore::path::VfsPath::umount" + .asciz "vfscore::path::VfsPath::truncate" + .asciz "vfscore::path::VfsPath::symlink" + .asciz "vfscore::path::VfsPath::link" + .asciz "vfscore::path::VfsPath::rmdir" + .asciz "vfscore::path::VfsPath::unlink" + .asciz "vfscore::path::VfsPath::rename_to" + .asciz "vfscore::path::VfsPath::set_xattr" + .asciz "vfscore::path::VfsPath::get_xattr" + .asciz "vfscore::path::checkout_write_perm" + .asciz "vfscore::path::check_same_fs" + .asciz "vfscore::path::real_dentry_down" + .asciz "vfscore::path::real_dentry_up" + .asciz "vfscore::path::print_fs_tree" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz ">::from" + .asciz "vfscore::utils::VfsInodeMode::from" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "core::error::Error::cause" + .asciz "core::error::Error::type_id" + .asciz "alloc::raw_vec::finish_grow" + .asciz "alloc::raw_vec::RawVec::reserve::do_reserve_and_handle" + .asciz "::fmt" + .asciz "::fmt" + .asciz "core::ptr::drop_in_place<&i32>" + .asciz "core::ptr::drop_in_place<&isize>" + .asciz "core::ptr::drop_in_place" + .asciz "core::array::::fmt" + .asciz "core::error::Error::cause" + .asciz "core::error::Error::type_id" + .asciz "core::panicking::assert_failed" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "alloc::sync::Arc::drop_slow" + .asciz "::i_insert" + .asciz "vfscore::error:: for pconst::consts::LinuxErrno>::from" + .asciz "::i_mount" + .asciz ">::from" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "pconst::consts::syscall_name" + .asciz ">::try_from" + .asciz "pconst::consts:: for isize>::from" + .asciz "::fmt" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place<&u8>" + .asciz "core::ptr::drop_in_place<&i32>" + .asciz "core::ptr::drop_in_place<&isize>" + .asciz "core::ptr::drop_in_place<&usize>" + .asciz "core::ptr::drop_in_place<&core::option::Option>" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::ptr::drop_in_place" + .asciz "alloc::raw_vec::finish_grow" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz ">::from" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place<&[core::option::Option; 64]>" + .asciz "pconst::signal::SignalHandlers::clear" + .asciz "pconst::signal::SignalHandlers::get_action" + .asciz "pconst::signal::SignalHandlers::get_action_ref" + .asciz "pconst::signal::SignalHandlers::set_action" + .asciz "pconst::signal::SignalReceivers::get_one_signal" + .asciz "pconst::signal::SignalReceivers::have_signal" + .asciz "pconst::signal::SignalReceivers::have_signal_with_number" + .asciz ">>::into" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "core::fmt::Write::write_char" + .asciz "core::fmt::Write::write_fmt" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::panicking::assert_failed" + .asciz "spin::once::Once::try_call_once_slow" + .asciz "spin::once::Once::try_call_once_slow" + .asciz " as core::fmt::Debug>::fmt" + .asciz "::write_str" + .asciz "platform::console::__print" + .asciz "platform::console::console_write" + .asciz "::print" + .asciz "_start_secondary" + .asciz "clear_bss" + .asciz "::enabled" + .asciz "::log" + .asciz "::flush" + .asciz "platform::logging::init_logger" + .asciz "platform_init" + .asciz "platform::platform_dtb_ptr" + .asciz "platform::platform_machine_info" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "platform::basic::machine_info_from_dtb" + .asciz "core::str::iter::SplitInternal

::next" + .asciz "fdt::node::FdtNode::property" + .asciz "fdt::node::FdtNode::reg" + .asciz "fdt::node::FdtNode::compatible" + .asciz "fdt::node::FdtNode::cell_sizes" + .asciz "fdt::node::find_node" + .asciz "fdt::node::skip_current_node" + .asciz "fdt::node::NodeProperty::parse" + .asciz "fdt::node::skip_4_aligned" + .asciz "fdt::Fdt::from_ptr" + .asciz "fdt::Fdt::cpus" + .asciz "fdt::Fdt::root" + .asciz "fdt::Fdt::find_node" + .asciz "fdt::Fdt::all_nodes" + .asciz "fdt::Fdt::str_at_offset" + .asciz "::fmt" + .asciz "fdt::standard_nodes::Root::model" + .asciz "fdt::standard_nodes::Aliases::resolve" + .asciz "fdt::standard_nodes::Compatible::first" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place<&u8>" + .asciz "core::panicking::assert_failed" + .asciz "fdt::parsing::CStr::new" + .asciz "fdt::parsing::CStr::as_str" + .asciz "fdt::parsing::FdtData::u32" + .asciz "fdt::parsing::FdtData::u64" + .asciz "fdt::parsing::FdtData::skip" + .asciz "fdt::parsing::FdtData::peek_u32" + .asciz "core::ptr::drop_in_place" + .asciz "::print" + .asciz "preprint::__private_print" + .asciz "::before_lock" + .asciz "::after_lock" + .asciz "arch::riscv::activate_paging_mode" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place<&u32>" + .asciz "::fmt" + .asciz "syscall_table::Service::handle" + .asciz "::from" + .asciz "::from" + .asciz "::from" + .asciz "::from" + .asciz "::from" + .asciz "inventory::Registry::submit" + .asciz "core::fmt::Write::write_fmt" + .asciz "core::ptr::drop_in_place" + .asciz "core::ptr::drop_in_place" + .asciz "alloc::raw_vec::RawVec::reserve::do_reserve_and_handle" + .asciz "alloc::raw_vec::RawVec::reserve_for_push" + .asciz "alloc::raw_vec::finish_grow" + .asciz "alloc::raw_vec::capacity_overflow" + .asciz "alloc::alloc::handle_alloc_error" + .asciz "__rdl_oom" + .asciz "alloc::fmt::format::format_inner" + .asciz "alloc::string::String::from_utf8_lossy" + .asciz "alloc::string::String::push" + .asciz "::clone" + .asciz "::write_str" + .asciz "::write_char" + .asciz "alloc::vec::Vec::remove::assert_failed" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "core::ptr::drop_in_place<&u32>" + .asciz "core::ptr::drop_in_place" + .asciz "::fmt" + .asciz "::enabled" + .asciz "::log" + .asciz "::flush" + .asciz "log::set_logger" + .asciz "log::__private_api::log" + .asciz "::fmt" + .asciz "core::ops::function::FnOnce::call_once" + .asciz "core::ptr::drop_in_place<&core::iter::adapters::copied::Copied>>" + .asciz "core::ptr::drop_in_place" + .asciz "core::num::from_str_radix" + .asciz " as core::fmt::Debug>::fmt" + .asciz "::type_id" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "core::cell::panic_already_borrowed" + .asciz "core::cell::panic_already_mutably_borrowed" + .asciz "core::char::methods::::escape_debug_ext" + .asciz " as core::fmt::Write>::write_str" + .asciz " as core::fmt::Write>::write_str" + .asciz " as core::fmt::Write>::write_str" + .asciz " as core::fmt::Write>::write_str" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "core::option::expect_failed" + .asciz "::fmt" + .asciz "core::panicking::panic_fmt" + .asciz "core::panicking::panic_nounwind_fmt" + .asciz "core::panicking::panic" + .asciz "core::panicking::panic_bounds_check" + .asciz "core::panicking::assert_failed" + .asciz "core::panicking::assert_failed_inner" + .asciz "core::result::unwrap_failed" + .asciz "::write_str" + .asciz "::write_char" + .asciz "core::fmt::builders::DebugStruct::field" + .asciz "core::fmt::builders::DebugStruct::finish" + .asciz "core::fmt::builders::DebugTuple::field" + .asciz "core::fmt::builders::DebugTuple::finish" + .asciz "core::fmt::builders::DebugInner::entry" + .asciz "core::fmt::builders::DebugSet::entry" + .asciz "core::fmt::builders::DebugList::entry" + .asciz "core::fmt::builders::DebugList::finish" + .asciz "core::fmt::Write::write_char" + .asciz "core::fmt::Write::write_char" + .asciz "core::fmt::Write::write_char" + .asciz "core::fmt::Write::write_char" + .asciz "core::fmt::Write::write_fmt" + .asciz "core::fmt::Write::write_fmt" + .asciz "core::fmt::Write::write_fmt" + .asciz "core::fmt::Write::write_fmt" + .asciz "core::fmt::Write::write_fmt" + .asciz "::fmt" + .asciz "core::fmt::write" + .asciz "core::fmt::Formatter::pad_integral" + .asciz "core::fmt::Formatter::pad_integral::write_prefix" + .asciz "core::fmt::Formatter::pad" + .asciz "core::fmt::Formatter::write_str" + .asciz "::write_str" + .asciz "core::fmt::Formatter::write_fmt" + .asciz "::write_fmt" + .asciz "core::fmt::Formatter::debug_struct" + .asciz "core::fmt::Formatter::debug_struct_field2_finish" + .asciz "core::fmt::Formatter::debug_struct_field3_finish" + .asciz "core::fmt::Formatter::debug_struct_field4_finish" + .asciz "core::fmt::Formatter::debug_struct_field5_finish" + .asciz "core::fmt::Formatter::debug_struct_fields_finish" + .asciz "core::fmt::Formatter::debug_tuple" + .asciz "core::fmt::Formatter::debug_tuple_field1_finish" + .asciz "core::fmt::Formatter::debug_tuple_field2_finish" + .asciz "core::fmt::Formatter::debug_list" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "::fmt" + .asciz "core::fmt::pointer_fmt_inner" + .asciz "core::slice::memchr::memchr_aligned" + .asciz "core::slice::memchr::memrchr" + .asciz "core::slice::index::slice_start_index_len_fail" + .asciz "core::slice::index::slice_end_index_len_fail" + .asciz "core::slice::index::slice_index_order_fail" + .asciz "core::slice::::copy_from_slice::len_mismatch_fail" + .asciz "core::str::converts::from_utf8" + .asciz "core::str::count::do_count_chars" + .asciz "::fmt" + .asciz "core::str::pattern::StrSearcher::new" + .asciz "::next" + .asciz "core::str::slice_error_fail" + .asciz "core::str::slice_error_fail_rt" + .asciz "core::unicode::printable::check" + .asciz "core::unicode::printable::is_printable" + .asciz "core::num::::from_str_radix" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::::fmt" + .asciz "core::fmt::num::imp::fmt_u64" + .asciz "core::fmt::num::imp::::fmt" + .asciz "core::fmt::num::imp::::fmt" + .asciz "core::fmt::num::imp::::fmt" + .asciz "core::fmt::num::imp::::fmt" + .asciz "core::fmt::num::imp::::fmt" + .asciz "core::fmt::num::imp::::fmt" + .asciz "core::fmt::num::imp::::fmt" + .asciz "core::fmt::num::imp::::fmt" + .asciz "::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Debug>::fmt" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "<&T as core::fmt::Display>::fmt" + .asciz "<&T as core::fmt::LowerHex>::fmt" + .asciz "::fmt" + .asciz "core::unicode::unicode_data::grapheme_extend::lookup" + .asciz "compiler_builtins::mem::memcpy" + .asciz "compiler_builtins::mem::memmove" + .asciz "compiler_builtins::mem::memset" + .asciz "compiler_builtins::mem::memcmp" + .asciz "memset" + .asciz "__divti3" + .asciz "compiler_builtins::int::specialized_div_rem::u128_div_rem" + .asciz "memcmp" + .asciz "memmove" + .asciz "memcpy" + .asciz "etext" + .asciz "srodata" + .asciz "str.0.llvm.1187392117675697175" + .asciz "str.0.llvm.9032329141667060801" + .asciz "str.0.llvm.12830073343055868386" + .asciz "str.0" + .asciz "str.1" + .asciz "str.0" + .asciz "log::LOG_LEVEL_NAMES" + .asciz "core::unicode::unicode_data::grapheme_extend::SHORT_OFFSET_RUNS" + .asciz "core::unicode::unicode_data::grapheme_extend::OFFSETS" + .asciz "erodata" + .asciz "kernel::time::__syscall_115::_::__CTOR" + .asciz "sdata" + .asciz "sinit" + .asciz "kernel::time::__syscall_114::_::__CTOR" + .asciz "kernel::time::__syscall_103::_::__CTOR" + .asciz "kernel::time::__syscall_102::_::__CTOR" + .asciz "kernel::time::__syscall_113::_::__CTOR" + .asciz "kernel::time::__syscall_101::_::__CTOR" + .asciz "kernel::time::__syscall_153::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_261::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_214::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_260::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_221::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_177::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_176::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_175::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_174::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_157::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_155::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_154::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_93::_::__CTOR" + .asciz "kernel::system::__syscall_2003::_::__CTOR" + .asciz "kernel::system::__syscall_165::_::__CTOR" + .asciz "kernel::system::__syscall_119::_::__CTOR" + .asciz "kernel::system::__syscall_123::_::__CTOR" + .asciz "kernel::system::__syscall_122::_::__CTOR" + .asciz "kernel::system::__syscall_118::_::__CTOR" + .asciz "kernel::net::__syscall_199::_::__CTOR" + .asciz "kernel::net::__syscall_207::_::__CTOR" + .asciz "kernel::net::__syscall_206::_::__CTOR" + .asciz "kernel::net::__syscall_204::_::__CTOR" + .asciz "kernel::net::__syscall_200::_::__CTOR" + .asciz "kernel::mm::map::__syscall_233::_::__CTOR" + .asciz "kernel::mm::map::__syscall_227::_::__CTOR" + .asciz "kernel::mm::map::__syscall_215::_::__CTOR" + .asciz "kernel::ipc::__syscall_98::_::__CTOR" + .asciz "kernel::ipc::__syscall_23::_::__CTOR" + .asciz "kernel::ipc::signal::__syscall_139::_::__CTOR" + .asciz "kernel::ipc::signal::__syscall_130::_::__CTOR" + .asciz "kernel::ipc::signal::__syscall_129::_::__CTOR" + .asciz "kernel::ipc::signal::__syscall_135::_::__CTOR" + .asciz "kernel::ipc::signal::__syscall_137::_::__CTOR" + .asciz "kernel::ipc::signal::__syscall_134::_::__CTOR" + .asciz "kernel::ipc::shm::__syscall_195::_::__CTOR" + .asciz "kernel::gui::__syscall_2000::_::__CTOR" + .asciz "kernel::fs::select::__syscall_72::_::__CTOR" + .asciz "kernel::fs::poll::__syscall_73::_::__CTOR" + .asciz "kernel::fs::link::__syscall_37::_::__CTOR" + .asciz "kernel::fs::ext::__syscall_16::_::__CTOR" + .asciz "kernel::fs::ext::__syscall_12::_::__CTOR" + .asciz "kernel::fs::ext::__syscall_11::_::__CTOR" + .asciz "kernel::fs::ext::__syscall_9::_::__CTOR" + .asciz "kernel::fs::ext::__syscall_7::_::__CTOR" + .asciz "kernel::fs::ext::__syscall_6::_::__CTOR" + .asciz "kernel::fs::control::__syscall_166::_::__CTOR" + .asciz "kernel::fs::control::__syscall_55::_::__CTOR" + .asciz "kernel::fs::control::__syscall_53::_::__CTOR" + .asciz "kernel::fs::control::__syscall_52::_::__CTOR" + .asciz "kernel::fs::control::__syscall_48::_::__CTOR" + .asciz "kernel::fs::control::__syscall_88::_::__CTOR" + .asciz "kernel::fs::control::__syscall_29::_::__CTOR" + .asciz "kernel::fs::control::__syscall_25::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_82::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_81::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_71::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_276::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_38::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_44::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_79::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_68::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_65::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_34::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_50::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_17::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_64::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_63::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_46::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_61::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_57::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_40::_::__CTOR" + .asciz "kernel::ipc::__syscall_100::_::__CTOR" + .asciz "kernel::time::__syscall_169::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_96::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_178::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_172::_::__CTOR" + .asciz "kernel::system::__syscall_121::_::__CTOR" + .asciz "kernel::system::__syscall_179::_::__CTOR" + .asciz "kernel::system::__syscall_160::_::__CTOR" + .asciz "kernel::net::__syscall_209::_::__CTOR" + .asciz "kernel::net::__syscall_208::_::__CTOR" + .asciz "kernel::net::__syscall_203::_::__CTOR" + .asciz "kernel::net::__syscall_201::_::__CTOR" + .asciz "kernel::net::__syscall_198::_::__CTOR" + .asciz "kernel::mm::__syscall_283::_::__CTOR" + .asciz "kernel::mm::map::__syscall_226::_::__CTOR" + .asciz "kernel::ipc::signal::__syscall_133::_::__CTOR" + .asciz "kernel::ipc::shm::__syscall_194::_::__CTOR" + .asciz "kernel::gui::__syscall_2002::_::__CTOR" + .asciz "kernel::gui::__syscall_2001::_::__CTOR" + .asciz "kernel::fs::link::__syscall_78::_::__CTOR" + .asciz "kernel::fs::link::__syscall_36::_::__CTOR" + .asciz "kernel::fs::ext::__syscall_15::_::__CTOR" + .asciz "kernel::fs::ext::__syscall_14::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_285::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_43::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_80::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_67::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_66::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_49::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_56::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_39::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_220::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_173::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_124::_::__CTOR" + .asciz "kernel::task::cpu::__syscall_94::_::__CTOR" + .asciz "kernel::system::__syscall_120::_::__CTOR" + .asciz "kernel::system::__syscall_116::_::__CTOR" + .asciz "kernel::net::__syscall_210::_::__CTOR" + .asciz "kernel::net::__syscall_205::_::__CTOR" + .asciz "kernel::net::__syscall_202::_::__CTOR" + .asciz "kernel::mm::map::__syscall_222::_::__CTOR" + .asciz "kernel::ipc::__syscall_99::_::__CTOR" + .asciz "kernel::ipc::__syscall_24::_::__CTOR" + .asciz "kernel::ipc::__syscall_59::_::__CTOR" + .asciz "kernel::ipc::shm::__syscall_196::_::__CTOR" + .asciz "kernel::fs::link::__syscall_35::_::__CTOR" + .asciz "kernel::fs::ext::__syscall_13::_::__CTOR" + .asciz "kernel::fs::ext::__syscall_10::_::__CTOR" + .asciz "kernel::fs::ext::__syscall_8::_::__CTOR" + .asciz "kernel::fs::ext::__syscall_5::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_62::_::__CTOR" + .asciz "kernel::fs::basic::__syscall_45::_::__CTOR" + .asciz "kernel::task::task::TID_MANAGER" + .asciz "einit" + .asciz "kernel::ipc::FUTEX_WAITER" + .asciz "kernel::time::__syscall_115::_::__INVENTORY" + .asciz "kernel::time::__syscall_114::_::__INVENTORY" + .asciz "kernel::time::__syscall_103::_::__INVENTORY" + .asciz "kernel::time::__syscall_102::_::__INVENTORY" + .asciz "kernel::time::__syscall_113::_::__INVENTORY" + .asciz "kernel::time::__syscall_101::_::__INVENTORY" + .asciz "kernel::time::__syscall_153::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_261::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_214::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_260::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_221::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_177::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_176::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_175::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_174::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_157::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_155::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_154::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_93::_::__INVENTORY" + .asciz "kernel::system::__syscall_2003::_::__INVENTORY" + .asciz "kernel::system::__syscall_165::_::__INVENTORY" + .asciz "kernel::system::__syscall_119::_::__INVENTORY" + .asciz "kernel::system::__syscall_123::_::__INVENTORY" + .asciz "kernel::system::__syscall_122::_::__INVENTORY" + .asciz "kernel::system::__syscall_118::_::__INVENTORY" + .asciz "kernel::net::__syscall_199::_::__INVENTORY" + .asciz "kernel::net::__syscall_207::_::__INVENTORY" + .asciz "kernel::net::__syscall_206::_::__INVENTORY" + .asciz "kernel::net::__syscall_204::_::__INVENTORY" + .asciz "kernel::net::__syscall_200::_::__INVENTORY" + .asciz "kernel::mm::map::__syscall_233::_::__INVENTORY" + .asciz "kernel::mm::map::__syscall_227::_::__INVENTORY" + .asciz "kernel::mm::map::__syscall_215::_::__INVENTORY" + .asciz "kernel::ipc::__syscall_98::_::__INVENTORY" + .asciz "kernel::ipc::__syscall_23::_::__INVENTORY" + .asciz "kernel::ipc::signal::__syscall_139::_::__INVENTORY" + .asciz "kernel::ipc::signal::__syscall_130::_::__INVENTORY" + .asciz "kernel::ipc::signal::__syscall_129::_::__INVENTORY" + .asciz "kernel::ipc::signal::__syscall_135::_::__INVENTORY" + .asciz "kernel::ipc::signal::__syscall_137::_::__INVENTORY" + .asciz "kernel::ipc::signal::__syscall_134::_::__INVENTORY" + .asciz "kernel::ipc::shm::__syscall_195::_::__INVENTORY" + .asciz "kernel::gui::__syscall_2000::_::__INVENTORY" + .asciz "kernel::fs::select::__syscall_72::_::__INVENTORY" + .asciz "kernel::fs::poll::__syscall_73::_::__INVENTORY" + .asciz "kernel::fs::link::__syscall_37::_::__INVENTORY" + .asciz "kernel::fs::ext::__syscall_16::_::__INVENTORY" + .asciz "kernel::fs::ext::__syscall_12::_::__INVENTORY" + .asciz "kernel::fs::ext::__syscall_11::_::__INVENTORY" + .asciz "kernel::fs::ext::__syscall_9::_::__INVENTORY" + .asciz "kernel::fs::ext::__syscall_7::_::__INVENTORY" + .asciz "kernel::fs::ext::__syscall_6::_::__INVENTORY" + .asciz "kernel::fs::control::__syscall_166::_::__INVENTORY" + .asciz "kernel::fs::control::__syscall_55::_::__INVENTORY" + .asciz "kernel::fs::control::__syscall_53::_::__INVENTORY" + .asciz "kernel::fs::control::__syscall_52::_::__INVENTORY" + .asciz "kernel::fs::control::__syscall_48::_::__INVENTORY" + .asciz "kernel::fs::control::__syscall_88::_::__INVENTORY" + .asciz "kernel::fs::control::__syscall_29::_::__INVENTORY" + .asciz "kernel::fs::control::__syscall_25::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_82::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_81::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_71::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_276::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_38::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_44::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_79::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_68::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_65::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_34::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_50::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_17::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_64::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_63::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_46::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_61::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_57::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_40::_::__INVENTORY" + .asciz "kernel::ipc::__syscall_100::_::__INVENTORY" + .asciz "kernel::task::cpu::GLOBAL_TASK_MANAGER" + .asciz "kernel::time::__syscall_169::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_96::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_178::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_172::_::__INVENTORY" + .asciz "kernel::system::__syscall_121::_::__INVENTORY" + .asciz "kernel::system::__syscall_179::_::__INVENTORY" + .asciz "kernel::system::__syscall_160::_::__INVENTORY" + .asciz "kernel::net::__syscall_209::_::__INVENTORY" + .asciz "kernel::net::__syscall_208::_::__INVENTORY" + .asciz "kernel::net::__syscall_203::_::__INVENTORY" + .asciz "kernel::net::__syscall_201::_::__INVENTORY" + .asciz "kernel::net::__syscall_198::_::__INVENTORY" + .asciz "kernel::mm::__syscall_283::_::__INVENTORY" + .asciz "kernel::mm::map::__syscall_226::_::__INVENTORY" + .asciz "kernel::ipc::signal::__syscall_133::_::__INVENTORY" + .asciz "kernel::ipc::shm::__syscall_194::_::__INVENTORY" + .asciz "kernel::gui::__syscall_2002::_::__INVENTORY" + .asciz "kernel::gui::__syscall_2001::_::__INVENTORY" + .asciz "kernel::fs::link::__syscall_78::_::__INVENTORY" + .asciz "kernel::fs::link::__syscall_36::_::__INVENTORY" + .asciz "kernel::fs::ext::__syscall_15::_::__INVENTORY" + .asciz "kernel::fs::ext::__syscall_14::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_285::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_43::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_80::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_67::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_66::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_49::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_56::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_39::_::__INVENTORY" + .asciz "kernel::fs::stdio::STDIN" + .asciz "kernel::fs::stdio::STDOUT" + .asciz "kernel::task::INIT_PROCESS" + .asciz "kernel::task::cpu::__syscall_220::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_173::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_124::_::__INVENTORY" + .asciz "kernel::task::cpu::__syscall_94::_::__INVENTORY" + .asciz "kernel::system::__syscall_120::_::__INVENTORY" + .asciz "kernel::system::__syscall_116::_::__INVENTORY" + .asciz "kernel::net::__syscall_210::_::__INVENTORY" + .asciz "kernel::net::__syscall_205::_::__INVENTORY" + .asciz "kernel::net::__syscall_202::_::__INVENTORY" + .asciz "kernel::mm::map::__syscall_222::_::__INVENTORY" + .asciz "kernel::ipc::__syscall_99::_::__INVENTORY" + .asciz "kernel::ipc::__syscall_24::_::__INVENTORY" + .asciz "kernel::ipc::__syscall_59::_::__INVENTORY" + .asciz "kernel::ipc::shm::__syscall_196::_::__INVENTORY" + .asciz "kernel::fs::link::__syscall_35::_::__INVENTORY" + .asciz "kernel::fs::ext::__syscall_13::_::__INVENTORY" + .asciz "kernel::fs::ext::__syscall_10::_::__INVENTORY" + .asciz "kernel::fs::ext::__syscall_8::_::__INVENTORY" + .asciz "kernel::fs::ext::__syscall_5::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_62::_::__INVENTORY" + .asciz "kernel::fs::basic::__syscall_45::_::__INVENTORY" + .asciz "vfs::dev::DEVICES" + .asciz "vfs::dev::DEVICE_ID_MANAGER" + .asciz "vfs::FS" + .asciz "interrupt::record::INTERRUPT_RECORD" + .asciz "netcore::tcp::get_ephemeral_port::CURR" + .asciz "netcore::udp::get_ephemeral_port::CURR" + .asciz "netcore::SOCKET_SET" + .asciz "netcore::LISTENING_TABLE" + .asciz "mem::manager::FRAME_REF_MANAGER" + .asciz "mem::vmm::KERNEL_SPACE" + .asciz "mem::HEAP_ALLOCATOR" + .asciz "preprint::PRINT" + .asciz "log::LOGGER.0" + .asciz "log::LOGGER.1" + .asciz "platform::common_riscv::boot::STACK" + .asciz "edata" + .asciz "kernel::ipc::signal::TID2SIGNALS" + .asciz "sbss" + .asciz "kernel::ipc::FCOUNT" + .asciz "kernel::ipc::shm::SHM_MEMORY" + .asciz "kernel::task::cpu::CPU_MANAGER" + .asciz "vfs::pipefs::PIPE_FS_ROOT" + .asciz "vfs::SYSTEM_ROOT_FS" + .asciz "devices::TASK_FUNC" + .asciz "devices::uart::UART_DEVICE" + .asciz "devices::gpu::GPU_DEVICE" + .asciz "devices::block::BLOCK_DEVICE" + .asciz "devices::input::KEYBOARD_INPUT_DEVICE" + .asciz "devices::input::MOUSE_INPUT_DEVICE" + .asciz "devices::rtc::RTC_DEVICE" + .asciz "interrupt::PLIC" + .asciz "interrupt::DEVICE_TABLE" + .asciz "drivers::DRIVER_TASK" + .asciz "netcore::KERNEL_NET_FUNC" + .asciz "netcore::NET_INTERFACE" + .asciz "mem::frame::FRAME_ALLOCATOR" + .asciz "mem::KERNEL_HEAP" + .asciz "platform::console::STDOUT" + .asciz "platform::qemu_riscv::DTB" + .asciz "platform::MACHINE_INFO" + .asciz "ksync::CPUS" + .asciz "kernel::STARTED" + .asciz "kernel::ipc::pipe::PIPE" + .asciz "__rust_alloc_error_handler_should_panic" + .asciz "__rust_no_alloc_shim_is_unstable" + .asciz "::registry::REGISTRY" + .asciz "log::STATE" + .asciz "log::MAX_LOG_LEVEL_FILTER" + .asciz "ebss" + .asciz "ekernel" diff --git a/subsystems/unwinder/src/lib.rs b/subsystems/unwinder/src/lib.rs new file mode 100644 index 00000000..b8a85f2a --- /dev/null +++ b/subsystems/unwinder/src/lib.rs @@ -0,0 +1,4 @@ +#![no_std] +#![feature(panic_info_message)] +mod panic; +mod symbol; diff --git a/kernel/src/panic.rs b/subsystems/unwinder/src/panic.rs similarity index 90% rename from kernel/src/panic.rs rename to subsystems/unwinder/src/panic.rs index e2c2a26b..4b47b18e 100644 --- a/kernel/src/panic.rs +++ b/subsystems/unwinder/src/panic.rs @@ -1,8 +1,9 @@ //! panic 处理 -use crate::sbi::system_shutdown; -use crate::trace::find_symbol_with_addr; + +use crate::symbol::find_symbol_with_addr; use core::panic::PanicInfo; use core::sync::atomic::AtomicBool; +use platform::{println, system_shutdown}; #[cfg(all(not(feature = "debug-eh-frame"), not(feature = "debug-frame-point")))] use tracer::CompilerTracer; #[cfg(feature = "debug-eh-frame")] @@ -10,6 +11,7 @@ use tracer::DwarfTracer; #[cfg(feature = "debug-frame-point")] use tracer::FramePointTracer; use tracer::{Tracer, TracerProvider}; + /// 递归标志 static RECURSION: AtomicBool = AtomicBool::new(false); @@ -19,28 +21,26 @@ static RECURSION: AtomicBool = AtomicBool::new(false); #[panic_handler] fn panic_handler(info: &PanicInfo) -> ! { if let Some(p) = info.location() { - mprintln!( + println!( "line {}, file {}: {}", p.line(), p.file(), info.message().unwrap() ); } else { - mprintln!("no location information available"); + println!("no location information available"); } if !RECURSION.swap(true, core::sync::atomic::Ordering::SeqCst) { back_trace(); } - mprintln!("!TEST FINISH!"); + println!("!TEST FINISH!"); system_shutdown(); - loop {} } #[derive(Clone)] struct TracerProviderImpl; impl TracerProvider for TracerProviderImpl { fn address2symbol(&self, addr: usize) -> Option<(usize, &'static str)> { - warn!("address2symbol: {:#x}", addr); find_symbol_with_addr(addr) } } diff --git a/kernel/src/trace/mod.rs b/subsystems/unwinder/src/symbol.rs similarity index 95% rename from kernel/src/trace/mod.rs rename to subsystems/unwinder/src/symbol.rs index 5e0ad98d..966b48f4 100644 --- a/kernel/src/trace/mod.rs +++ b/subsystems/unwinder/src/symbol.rs @@ -1,57 +1,53 @@ -use core::arch::global_asm; - -extern "C" { - #[allow(unused)] - fn symbol_num(); - #[allow(unused)] - fn symbol_address(); - #[allow(unused)] - fn symbol_index(); - #[allow(unused)] - fn symbol_name(); -} - -global_asm!(include_str!("kernel_symbol.S")); - -pub fn find_symbol_with_addr(addr: usize) -> Option<(usize, &'static str)> { - let symbol_num_addr = symbol_num as usize as *const usize; - let symbol_num = unsafe { symbol_num_addr.read_volatile() }; - if symbol_num == 0 { - return None; - } - let symbol_addr = symbol_address as usize as *const usize; // 符号地址存储区域 - let addr_data = unsafe { core::slice::from_raw_parts(symbol_addr, symbol_num) }; - // find the symbol with the nearest address - let mut index = -1isize; - for i in 0..symbol_num - 1 { - if addr >= addr_data[i] && addr < addr_data[i + 1] { - index = i as isize; - break; - } - } - if addr == addr_data[symbol_num - 1] { - index = (symbol_num - 1) as isize; - } - if index == -1 { - return None; - } - let index = index as usize; - let symbol_index = symbol_index as usize as *const usize; // 符号字符串的起始位置 - let index_data = unsafe { core::slice::from_raw_parts(symbol_index, symbol_num) }; - let symbol_name = symbol_name as usize as *const u8; // 符号字符串 - let mut last = 0; - unsafe { - for i in index_data[index].. { - let c = symbol_name.add(i); - if *c == 0 { - last = i; - break; - } - } - } - let name = unsafe { - core::slice::from_raw_parts(symbol_name.add(index_data[index]), last - index_data[index]) - }; - let name = core::str::from_utf8(name).unwrap(); - Some((addr_data[index], name)) -} +use core::arch::global_asm; + +extern "C" { + fn symbol_num(); + fn symbol_address(); + fn symbol_index(); + fn symbol_name(); +} + +global_asm!(include_str!("kernel_symbol.S")); + +pub fn find_symbol_with_addr(addr: usize) -> Option<(usize, &'static str)> { + let symbol_num_addr = symbol_num as usize as *const usize; + let symbol_num = unsafe { symbol_num_addr.read_volatile() }; + if symbol_num == 0 { + return None; + } + let symbol_addr = symbol_address as usize as *const usize; // 符号地址存储区域 + let addr_data = unsafe { core::slice::from_raw_parts(symbol_addr, symbol_num) }; + // find the symbol with the nearest address + let mut index = -1isize; + for i in 0..symbol_num - 1 { + if addr >= addr_data[i] && addr < addr_data[i + 1] { + index = i as isize; + break; + } + } + if addr == addr_data[symbol_num - 1] { + index = (symbol_num - 1) as isize; + } + if index == -1 { + return None; + } + let index = index as usize; + let symbol_index = symbol_index as usize as *const usize; // 符号字符串的起始位置 + let index_data = unsafe { core::slice::from_raw_parts(symbol_index, symbol_num) }; + let symbol_name = symbol_name as usize as *const u8; // 符号字符串 + let mut last = 0; + unsafe { + for i in index_data[index].. { + let c = symbol_name.add(i); + if *c == 0 { + last = i; + break; + } + } + } + let name = unsafe { + core::slice::from_raw_parts(symbol_name.add(index_data[index]), last - index_data[index]) + }; + let name = core::str::from_utf8(name).unwrap(); + Some((addr_data[index], name)) +} diff --git a/subsystems/vfs/Cargo.toml b/subsystems/vfs/Cargo.toml new file mode 100644 index 00000000..1b083864 --- /dev/null +++ b/subsystems/vfs/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "vfs" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +spin = "0" +log = "0" +ksync = { path = "../ksync" } +arch = { path = "../arch" } +constants = { path = "../constants" } +interrupt = { path = "../interrupt" } +platform = { path = "../platform" } + +downcast-rs = { version = "1.2.0", default-features = false } +vfscore = { git = "https://github.com/os-module/rvfs.git", features = [ + "linux_error", +] } +devfs = { git = "https://github.com/os-module/rvfs.git" } +dynfs = { git = "https://github.com/os-module/rvfs.git" } +ramfs = { git = "https://github.com/os-module/rvfs.git" } +fat-vfs = { git = "https://github.com/os-module/rvfs.git" } + + +devices = { path = "../devices" } diff --git a/kernel/src/fs/dev/mod.rs b/subsystems/vfs/src/dev/mod.rs similarity index 90% rename from kernel/src/fs/dev/mod.rs rename to subsystems/vfs/src/dev/mod.rs index 47dd6724..fdb51df8 100644 --- a/kernel/src/fs/dev/mod.rs +++ b/subsystems/vfs/src/dev/mod.rs @@ -1,13 +1,15 @@ -use crate::device::{ - BLKDevice, GPUDevice, INPUTDevice, RTCDevice, UARTDevice, BLOCK_DEVICE, GPU_DEVICE, - KEYBOARD_INPUT_DEVICE, MOUSE_INPUT_DEVICE, RTC_DEVICE, UART_DEVICE, -}; -use crate::fs::dev::null::NullDevice; -use crate::fs::dev::random::RandomDevice; -use crate::ksync::Mutex; use alloc::collections::BTreeMap; use alloc::sync::Arc; +use constants::DeviceId; use devfs::DevKernelProvider; +use devices::{ + BLKDevice, GPUDevice, INPUTDevice, RTCDevice, UARTDevice, BLOCK_DEVICE, GPU_DEVICE, + KEYBOARD_INPUT_DEVICE, MOUSE_INPUT_DEVICE, RTC_DEVICE, UART_DEVICE, +}; +use ksync::Mutex; +use log::info; +use null::NullDevice; +use random::RandomDevice; use spin::Lazy; use vfscore::dentry::VfsDentry; use vfscore::fstype::VfsFsType; @@ -37,36 +39,6 @@ pub fn alloc_device_id(inode_type: VfsNodeType) -> DeviceId { DEVICE_ID_MANAGER.lock().alloc(inode_type) } -#[derive(Copy, Clone, Debug, Eq, PartialOrd, PartialEq, Hash, Ord)] -pub struct DeviceId { - major: u32, - minor: u32, -} - -impl DeviceId { - pub fn new(major: u32, minor: u32) -> Self { - Self { major, minor } - } - pub fn major(&self) -> u32 { - self.major - } - pub fn minor(&self) -> u32 { - self.minor - } - pub fn id(&self) -> u64 { - ((self.major as u64) << 32) | (self.minor as u64) - } -} - -impl From for DeviceId { - fn from(id: u64) -> Self { - Self { - major: (id >> 32) as u32, - minor: (id & 0xffffffff) as u32, - } - } -} - pub trait InodeType2u32 { fn to_u32(&self) -> u32; } @@ -113,6 +85,7 @@ impl DevKernelProvider for DevFsProviderImpl { DEVICES.lock().get(&device_id).cloned() } } + ///```bash /// | /// |-- null @@ -197,6 +170,7 @@ fn scan_system_devices(root: Arc) { Some(block_device.device_id().id()), ) .unwrap(); + info!("block device id: {}", block_device.device_id().id()); register_device(block_device); }); GPU_DEVICE.get().map(|gpu| { @@ -211,6 +185,7 @@ fn scan_system_devices(root: Arc) { Some(gpu_device.device_id().id()), ) .unwrap(); + info!("gpu device id: {}", gpu_device.device_id().id()); register_device(gpu_device); }); KEYBOARD_INPUT_DEVICE.get().map(|input| { @@ -226,6 +201,7 @@ fn scan_system_devices(root: Arc) { Some(input_device.device_id().id()), ) .unwrap(); + info!("keyboard device id: {}", input_device.device_id().id()); register_device(input_device); }); MOUSE_INPUT_DEVICE.get().map(|input| { @@ -241,6 +217,7 @@ fn scan_system_devices(root: Arc) { Some(input_device.device_id().id()), ) .unwrap(); + info!("mouse device id: {}", input_device.device_id().id()); register_device(input_device); }); RTC_DEVICE.get().map(|rtc| { @@ -255,6 +232,7 @@ fn scan_system_devices(root: Arc) { Some(rtc_device.device_id().id()), ) .unwrap(); + info!("rtc device id: {}", rtc_device.device_id().id()); register_device(rtc_device); }); UART_DEVICE.get().map(|uart| { diff --git a/kernel/src/fs/dev/null.rs b/subsystems/vfs/src/dev/null.rs similarity index 97% rename from kernel/src/fs/dev/null.rs rename to subsystems/vfs/src/dev/null.rs index fbe37bc6..44a731f8 100644 --- a/kernel/src/fs/dev/null.rs +++ b/subsystems/vfs/src/dev/null.rs @@ -1,4 +1,4 @@ -use crate::fs::dev::DeviceId; +use crate::dev::DeviceId; use alloc::sync::Arc; use vfscore::error::VfsError; use vfscore::file::VfsFile; diff --git a/kernel/src/fs/dev/random.rs b/subsystems/vfs/src/dev/random.rs similarity index 95% rename from kernel/src/fs/dev/random.rs rename to subsystems/vfs/src/dev/random.rs index 97ba584f..16362f62 100644 --- a/kernel/src/fs/dev/random.rs +++ b/subsystems/vfs/src/dev/random.rs @@ -1,13 +1,12 @@ -use crate::fs::dev::DeviceId; -use crate::timer::read_timer; +use crate::dev::DeviceId; use alloc::sync::Arc; +use arch::read_timer; use vfscore::error::VfsError; use vfscore::file::VfsFile; use vfscore::inode::{InodeAttr, VfsInode}; use vfscore::superblock::VfsSuperBlock; use vfscore::utils::{VfsFileStat, VfsNodePerm, VfsNodeType}; use vfscore::VfsResult; - pub struct RandomDevice { device_id: DeviceId, } diff --git a/subsystems/vfs/src/kfile.rs b/subsystems/vfs/src/kfile.rs new file mode 100644 index 00000000..2016a37f --- /dev/null +++ b/subsystems/vfs/src/kfile.rs @@ -0,0 +1,272 @@ +use alloc::sync::Arc; +use constants::io::{Dirent64, DirentType, OpenFlags, PollEvents, SeekFrom}; +use constants::AlienResult; +use constants::LinuxErrno; +use core::fmt::{Debug, Formatter}; +use downcast_rs::{impl_downcast, DowncastSync}; +use ksync::Mutex; +use vfscore::dentry::VfsDentry; +use vfscore::error::VfsError; +use vfscore::inode::VfsInode; +use vfscore::path::VfsPath; +use vfscore::utils::{VfsFileStat, VfsNodeType, VfsPollEvents}; + +pub struct KernelFile { + pos: Mutex, + open_flag: Mutex, + dentry: Arc, +} + +impl Debug for KernelFile { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + f.debug_struct("KernelFile") + .field("pos", &self.pos) + .field("open_flag", &self.open_flag) + .field("name", &self.dentry.name()) + .finish() + } +} + +impl KernelFile { + pub fn new(dentry: Arc, open_flag: OpenFlags) -> Self { + let pos = if open_flag.contains(OpenFlags::O_APPEND) { + dentry.inode().unwrap().get_attr().unwrap().st_size + } else { + 0 + }; + Self { + pos: Mutex::new(pos), + open_flag: Mutex::new(open_flag), + dentry, + } + } +} + +pub trait File: DowncastSync + Debug { + fn read(&self, buf: &mut [u8]) -> AlienResult; + fn write(&self, buf: &[u8]) -> AlienResult; + fn read_at(&self, _offset: u64, _buf: &mut [u8]) -> AlienResult { + Err(LinuxErrno::ENOSYS) + } + fn write_at(&self, _offset: u64, _buf: &[u8]) -> AlienResult { + Err(LinuxErrno::ENOSYS) + } + fn flush(&self) -> AlienResult<()> { + Ok(()) + } + fn fsync(&self) -> AlienResult<()> { + Ok(()) + } + fn seek(&self, pos: SeekFrom) -> AlienResult; + /// Gets the file attributes. + fn get_attr(&self) -> AlienResult; + fn ioctl(&self, _cmd: u32, _arg: usize) -> AlienResult { + Err(LinuxErrno::ENOSYS) + } + fn set_open_flag(&self, _flag: OpenFlags) {} + fn get_open_flag(&self) -> OpenFlags { + OpenFlags::O_RDONLY + } + fn dentry(&self) -> Arc; + fn inode(&self) -> Arc; + fn readdir(&self, _buf: &mut [u8]) -> AlienResult { + Err(LinuxErrno::ENOSYS) + } + fn truncate(&self, _len: u64) -> AlienResult<()> { + Err(LinuxErrno::ENOSYS) + } + fn is_readable(&self) -> bool; + fn is_writable(&self) -> bool; + fn is_append(&self) -> bool; + fn poll(&self, _event: PollEvents) -> AlienResult { + Err(LinuxErrno::ENOSYS) + } +} + +impl_downcast!(sync File); + +// todo! permission check +impl File for KernelFile { + fn read(&self, buf: &mut [u8]) -> AlienResult { + if buf.len() == 0 { + return Ok(0); + } + // warn!("[read] is_interrupt_enable:{}",is_interrupt_enable()); + let pos = *self.pos.lock(); + // warn!("[read] is_interrupt_enable:{}",is_interrupt_enable()); + let read = self.read_at(pos, buf)?; + *self.pos.lock() += read as u64; + Ok(read) + } + fn write(&self, buf: &[u8]) -> AlienResult { + if buf.len() == 0 { + return Ok(0); + } + let mut pos = self.pos.lock(); + let write = self.write_at(*pos, buf)?; + *pos += write as u64; + Ok(write) + } + fn read_at(&self, offset: u64, buf: &mut [u8]) -> AlienResult { + if buf.len() == 0 { + return Ok(0); + } + let open_flag = self.open_flag.lock(); + if !open_flag.contains(OpenFlags::O_RDONLY) && !open_flag.contains(OpenFlags::O_RDWR) { + return Err(LinuxErrno::EPERM); + } + drop(open_flag); + let inode = self.dentry.inode()?; + let read = inode.read_at(offset, buf)?; + Ok(read) + } + + fn write_at(&self, _offset: u64, buf: &[u8]) -> AlienResult { + if buf.len() == 0 { + return Ok(0); + } + let open_flag = self.open_flag.lock(); + if !open_flag.contains(OpenFlags::O_WRONLY) && !open_flag.contains(OpenFlags::O_RDWR) { + return Err(LinuxErrno::EPERM); + } + let inode = self.dentry.inode()?; + let write = inode.write_at(_offset, buf)?; + Ok(write) + } + + fn flush(&self) -> AlienResult<()> { + let open_flag = self.open_flag.lock(); + if !open_flag.contains(OpenFlags::O_WRONLY) & !open_flag.contains(OpenFlags::O_RDWR) { + return Err(LinuxErrno::EPERM); + } + let inode = self.dentry.inode()?; + inode.flush()?; + Ok(()) + } + + fn fsync(&self) -> AlienResult<()> { + let open_flag = self.open_flag.lock(); + if !open_flag.contains(OpenFlags::O_WRONLY) && !open_flag.contains(OpenFlags::O_RDWR) { + return Err(LinuxErrno::EPERM); + } + let inode = self.dentry.inode()?; + inode.fsync()?; + Ok(()) + } + + // check for special file + fn seek(&self, pos: SeekFrom) -> AlienResult { + let mut spos = self.pos.lock(); + let size = self.get_attr()?.st_size; + let new_offset = match pos { + SeekFrom::Start(pos) => Some(pos), + SeekFrom::Current(off) => spos.checked_add_signed(off), + SeekFrom::End(off) => size.checked_add_signed(off), + } + .ok_or_else(|| VfsError::Invalid)?; + *spos = new_offset; + Ok(new_offset) + } + + /// Gets the file attributes. + fn get_attr(&self) -> AlienResult { + self.dentry.inode()?.get_attr().map_err(Into::into) + } + + fn ioctl(&self, _cmd: u32, _arg: usize) -> AlienResult { + let inode = self.dentry.inode().unwrap(); + inode.ioctl(_cmd, _arg).map_err(Into::into) + } + + fn set_open_flag(&self, flag: OpenFlags) { + *self.open_flag.lock() = flag; + } + + fn get_open_flag(&self) -> OpenFlags { + *self.open_flag.lock() + } + fn dentry(&self) -> Arc { + self.dentry.clone() + } + fn inode(&self) -> Arc { + self.dentry.inode().unwrap() + } + fn readdir(&self, buf: &mut [u8]) -> AlienResult { + let inode = self.inode(); + let mut pos = self.pos.lock(); + let mut count = 0; + let mut ptr = buf.as_mut_ptr(); + loop { + let dirent = inode.readdir(*pos as usize).map_err(|e| { + *pos = 0; + e + })?; + match dirent { + Some(d) => { + let dirent64 = + Dirent64::new(&d.name, d.ino, *pos as i64, vfsnodetype2dirent64(d.ty)); + if count + dirent64.len() <= buf.len() { + let dirent_ptr = unsafe { &mut *(ptr as *mut Dirent64) }; + *dirent_ptr = dirent64; + let name_ptr = dirent_ptr.name.as_mut_ptr(); + unsafe { + let mut name = d.name.clone(); + name.push('\0'); + let len = name.len(); + name_ptr.copy_from(name.as_ptr(), len); + ptr = ptr.add(dirent_ptr.len()); + } + count += dirent_ptr.len(); + } else { + break; + } // Buf is small + } + None => { + break; + } // EOF + } + *pos += 1; + } + Ok(count) + } + fn truncate(&self, len: u64) -> AlienResult<()> { + let open_flag = self.open_flag.lock(); + if !open_flag.contains(OpenFlags::O_WRONLY) & !open_flag.contains(OpenFlags::O_RDWR) { + return Err(LinuxErrno::EINVAL); + } + let dt = self.dentry(); + VfsPath::new(dt).truncate(len).map_err(Into::into) + } + fn is_readable(&self) -> bool { + let open_flag = self.open_flag.lock(); + open_flag.contains(OpenFlags::O_RDONLY) | open_flag.contains(OpenFlags::O_RDWR) + } + fn is_writable(&self) -> bool { + let open_flag = self.open_flag.lock(); + open_flag.contains(OpenFlags::O_WRONLY) | open_flag.contains(OpenFlags::O_RDWR) + } + + fn is_append(&self) -> bool { + let open_flag = self.open_flag.lock(); + open_flag.contains(OpenFlags::O_APPEND) + } + + fn poll(&self, _event: PollEvents) -> AlienResult { + let inode = self.dentry.inode()?; + let res = inode + .poll(VfsPollEvents::from_bits_truncate(_event.bits())) + .map(|e| PollEvents::from_bits_truncate(e.bits())); + res.map_err(Into::into) + } +} + +fn vfsnodetype2dirent64(ty: VfsNodeType) -> DirentType { + DirentType::from_u8(ty as u8) +} + +impl Drop for KernelFile { + fn drop(&mut self) { + let _ = self.flush(); + let _ = self.fsync(); + } +} diff --git a/subsystems/vfs/src/lib.rs b/subsystems/vfs/src/lib.rs new file mode 100644 index 00000000..2dd4f54f --- /dev/null +++ b/subsystems/vfs/src/lib.rs @@ -0,0 +1,151 @@ +#![no_std] + +extern crate alloc; +#[macro_use] +extern crate platform; +use crate::dev::DevFsProviderImpl; +use alloc::collections::BTreeMap; +use alloc::string::{String, ToString}; +use alloc::sync::Arc; +use constants::AlienResult; +use core::ops::Index; +use dynfs::DynFsKernelProvider; +use fat_vfs::FatFsProvider; +use ksync::Mutex; +use spin::{Lazy, Once}; +use vfscore::dentry::VfsDentry; +use vfscore::fstype::VfsFsType; +use vfscore::path::VfsPath; +use vfscore::utils::VfsTimeSpec; + +pub mod dev; +pub mod kfile; +pub mod pipefs; +pub mod proc; +pub mod ram; +pub mod sys; + +pub static FS: Lazy>>> = + Lazy::new(|| Mutex::new(BTreeMap::new())); + +static SYSTEM_ROOT_FS: Once> = Once::new(); + +type SysFs = dynfs::DynFs>; +type ProcFs = dynfs::DynFs>; +type RamFs = ramfs::RamFs>; +type DevFs = devfs::DevFs>; +type TmpFs = ramfs::RamFs>; +type PipeFs = dynfs::DynFs>; +type FatFs = fat_vfs::FatFs>; + +#[derive(Clone)] +pub struct CommonFsProviderImpl; + +impl DynFsKernelProvider for CommonFsProviderImpl { + fn current_time(&self) -> VfsTimeSpec { + VfsTimeSpec::new(0, 0) + } +} + +impl ramfs::RamFsProvider for CommonFsProviderImpl { + fn current_time(&self) -> VfsTimeSpec { + DynFsKernelProvider::current_time(self) + } +} + +impl FatFsProvider for CommonFsProviderImpl { + fn current_time(&self) -> VfsTimeSpec { + DynFsKernelProvider::current_time(self) + } +} + +fn register_all_fs() { + let procfs = Arc::new(ProcFs::new(CommonFsProviderImpl, "procfs")); + let sysfs = Arc::new(SysFs::new(CommonFsProviderImpl, "sysfs")); + let ramfs = Arc::new(RamFs::new(CommonFsProviderImpl)); + let devfs = Arc::new(DevFs::new(DevFsProviderImpl)); + let tmpfs = Arc::new(TmpFs::new(CommonFsProviderImpl)); + let pipefs = Arc::new(PipeFs::new(CommonFsProviderImpl, "pipefs")); + + let fatfs = Arc::new(FatFs::new(CommonFsProviderImpl)); + + FS.lock().insert("procfs".to_string(), procfs); + FS.lock().insert("sysfs".to_string(), sysfs); + FS.lock().insert("ramfs".to_string(), ramfs); + FS.lock().insert("devfs".to_string(), devfs); + FS.lock().insert("tmpfs".to_string(), tmpfs); + FS.lock().insert("pipefs".to_string(), pipefs); + FS.lock().insert("fatfs".to_string(), fatfs); + + println!("register fs success"); +} + +/// Init the filesystem +pub fn init_filesystem() -> AlienResult<()> { + register_all_fs(); + let ramfs_root = ram::init_ramfs(FS.lock().index("ramfs").clone()); + let procfs_root = proc::init_procfs(FS.lock().index("procfs").clone()); + let devfs_root = dev::init_devfs(FS.lock().index("devfs").clone()); + let sysfs_root = sys::init_sysfs(FS.lock().index("sysfs").clone()); + let tmpfs_root = FS + .lock() + .index("tmpfs") + .clone() + .i_mount(0, "/tmp", None, &[])?; + + pipefs::init_pipefs(FS.lock().index("pipefs").clone()); + + let path = VfsPath::new(ramfs_root.clone()); + path.join("proc")?.mount(procfs_root, 0)?; + path.join("sys")?.mount(sysfs_root, 0)?; + path.join("dev")?.mount(devfs_root, 0)?; + path.join("tmp")?.mount(tmpfs_root.clone(), 0)?; + + let shm_ramfs = FS + .lock() + .index("ramfs") + .clone() + .i_mount(0, "/dev/shm", None, &[])?; + path.join("dev/shm")?.mount(shm_ramfs, 0)?; + + let fatfs = FS.lock().index("fatfs").clone(); + let blk_inode = path + .join("/dev/sda")? + .open(None) + .expect("open /dev/sda failed") + .inode()?; + let fat32_root = fatfs.i_mount(0, "/bin", Some(blk_inode), &[])?; + path.join("bin")?.mount(fat32_root, 0)?; + + vfscore::path::print_fs_tree(&mut VfsOutPut, ramfs_root.clone(), "".to_string(), false) + .unwrap(); + SYSTEM_ROOT_FS.call_once(|| ramfs_root); + println!("Init filesystem success"); + Ok(()) +} + +struct VfsOutPut; +impl core::fmt::Write for VfsOutPut { + fn write_str(&mut self, s: &str) -> core::fmt::Result { + platform::console::console_write(s); + Ok(()) + } +} + +/// Get the root filesystem of the system +#[inline] +pub fn system_root_fs() -> Arc { + SYSTEM_ROOT_FS.get().unwrap().clone() +} + +/// Get the filesystem by name +#[inline] +pub fn system_support_fs(fs_name: &str) -> Option> { + FS.lock().iter().find_map(|(name, fs)| { + if name == fs_name { + Some(fs.clone()) + } else { + None + } + }) +} diff --git a/subsystems/vfs/src/pipefs.rs b/subsystems/vfs/src/pipefs.rs new file mode 100644 index 00000000..eeaca02a --- /dev/null +++ b/subsystems/vfs/src/pipefs.rs @@ -0,0 +1,20 @@ +use alloc::sync::Arc; +use constants::io::MountFlags; +use dynfs::DynFsDirInode; +use spin::Once; +use vfscore::dentry::VfsDentry; +use vfscore::fstype::VfsFsType; + +use crate::CommonFsProviderImpl; +use ksync::Mutex; + +pub type PipeFsDirInodeImpl = DynFsDirInode>; +pub static PIPE_FS_ROOT: Once> = Once::new(); + +pub fn init_pipefs(fs: Arc) { + let root = fs + .i_mount(MountFlags::empty().bits(), "", None, &[]) + .unwrap(); + PIPE_FS_ROOT.call_once(|| root); + println!("pipefs init success"); +} diff --git a/kernel/src/fs/proc/filesystem.rs b/subsystems/vfs/src/proc/filesystem.rs similarity index 98% rename from kernel/src/fs/proc/filesystem.rs rename to subsystems/vfs/src/proc/filesystem.rs index 44662d32..651a3a89 100644 --- a/kernel/src/fs/proc/filesystem.rs +++ b/subsystems/vfs/src/proc/filesystem.rs @@ -1,4 +1,4 @@ -use crate::fs::FS; +use crate::FS; use alloc::string::String; use alloc::sync::Arc; use core::cmp::min; diff --git a/kernel/src/fs/proc/interrupt.rs b/subsystems/vfs/src/proc/interrupt.rs similarity index 96% rename from kernel/src/fs/proc/interrupt.rs rename to subsystems/vfs/src/proc/interrupt.rs index 83332a7a..9c9c61b9 100644 --- a/kernel/src/fs/proc/interrupt.rs +++ b/subsystems/vfs/src/proc/interrupt.rs @@ -1,6 +1,6 @@ -use crate::interrupt::record::interrupts_info; use alloc::sync::Arc; use core::cmp::min; +use interrupt::record::interrupts_info; use vfscore::error::VfsError; use vfscore::file::VfsFile; use vfscore::inode::{InodeAttr, VfsInode}; diff --git a/subsystems/vfs/src/proc/mem.rs b/subsystems/vfs/src/proc/mem.rs new file mode 100644 index 00000000..ff8af076 --- /dev/null +++ b/subsystems/vfs/src/proc/mem.rs @@ -0,0 +1,87 @@ +use alloc::sync::Arc; +use core::cmp::min; +use vfscore::error::VfsError; +use vfscore::file::VfsFile; +use vfscore::inode::{InodeAttr, VfsInode}; +use vfscore::superblock::VfsSuperBlock; +use vfscore::utils::{VfsFileStat, VfsNodePerm, VfsNodeType}; +use vfscore::VfsResult; + +pub struct MemInfo; + +impl VfsFile for MemInfo { + fn read_at(&self, offset: u64, buf: &mut [u8]) -> VfsResult { + let min_len = min(buf.len(), MEMINFO.as_bytes().len() - offset as usize); + buf[..min_len].copy_from_slice(&MEMINFO.as_bytes()[..min_len]); + Ok(min_len) + } +} + +impl VfsInode for MemInfo { + fn get_super_block(&self) -> VfsResult> { + Err(VfsError::NoSys) + } + fn node_perm(&self) -> VfsNodePerm { + VfsNodePerm::empty() + } + fn set_attr(&self, _attr: InodeAttr) -> VfsResult<()> { + Ok(()) + } + + fn get_attr(&self) -> VfsResult { + Ok(VfsFileStat { + st_size: MEMINFO.as_bytes().len() as u64, + ..Default::default() + }) + } + + fn inode_type(&self) -> VfsNodeType { + VfsNodeType::File + } +} + +/// meminfo文件中保存的内容 +const MEMINFO: &str = r" +MemTotal: 944564 kB +MemFree: 835248 kB +MemAvailable: 873464 kB +Buffers: 6848 kB +Cached: 36684 kB +SwapCached: 0 kB +Active: 19032 kB +Inactive: 32676 kB +Active(anon): 128 kB +Inactive(anon): 8260 kB +Active(file): 18904 kB +Inactive(file): 24416 kB +Unevictable: 0 kB +Mlocked: 0 kB +SwapTotal: 0 kB +SwapFree: 0 kB +Dirty: 0 kB +Writeback: 0 kB +AnonPages: 8172 kB +Mapped: 16376 kB +Shmem: 216 kB +KReclaimable: 9960 kB +Slab: 17868 kB +SReclaimable: 9960 kB +SUnreclaim: 7908 kB +KernelStack: 1072 kB +PageTables: 600 kB +NFS_Unstable: 0 kB +Bounce: 0 kB +WritebackTmp: 0 kB +CommitLimit: 472280 kB +Committed_AS: 64684 kB +VmallocTotal: 67108863 kB +VmallocUsed: 15740 kB +VmallocChunk: 0 kB +Percpu: 496 kB +HugePages_Total: 0 +HugePages_Free: 0 +HugePages_Rsvd: 0 +HugePages_Surp: 0 +Hugepagesize: 2048 kB +Hugetlb: 0 kB +"; diff --git a/kernel/src/fs/proc/mod.rs b/subsystems/vfs/src/proc/mod.rs similarity index 85% rename from kernel/src/fs/proc/mod.rs rename to subsystems/vfs/src/proc/mod.rs index fe6333c0..082a6afb 100644 --- a/kernel/src/fs/proc/mod.rs +++ b/subsystems/vfs/src/proc/mod.rs @@ -2,16 +2,15 @@ mod filesystem; mod interrupt; mod mem; mod mounts; -mod process; -use crate::fs::proc::filesystem::SystemSupportFS; -use crate::fs::proc::interrupt::InterruptRecord; -use crate::fs::proc::mounts::MountInfo; -use crate::fs::CommonFsProviderImpl; -use crate::ksync::Mutex; +use crate::CommonFsProviderImpl; use alloc::sync::Arc; use dynfs::DynFsDirInode; +use filesystem::SystemSupportFS; +use interrupt::InterruptRecord; +use ksync::Mutex; use mem::MemInfo; +use mounts::MountInfo; use vfscore::dentry::VfsDentry; use vfscore::error::VfsError; use vfscore::fstype::VfsFsType; @@ -46,6 +45,7 @@ pub fn init_procfs(procfs: Arc) -> Arc { root_inode .add_file_manually("filesystems", Arc::new(support_fs), "r--r--r--".into()) .unwrap(); + println!("procfs init success"); root_dt diff --git a/kernel/src/fs/proc/mounts.rs b/subsystems/vfs/src/proc/mounts.rs similarity index 100% rename from kernel/src/fs/proc/mounts.rs rename to subsystems/vfs/src/proc/mounts.rs diff --git a/kernel/src/fs/ram/mod.rs b/subsystems/vfs/src/ram/mod.rs similarity index 71% rename from kernel/src/fs/ram/mod.rs rename to subsystems/vfs/src/ram/mod.rs index b1b71834..002e06c0 100644 --- a/kernel/src/fs/ram/mod.rs +++ b/subsystems/vfs/src/ram/mod.rs @@ -1,4 +1,3 @@ -use crate::config::{RTC_TIME, UTC}; use alloc::sync::Arc; use vfscore::dentry::VfsDentry; use vfscore::fstype::VfsFsType; @@ -80,3 +79,33 @@ pub fn init_ramfs(ramfs: Arc) -> Arc { println!("ramfs init success"); root_dt } + +/// localtime文件中保存的内容 +pub const UTC: &[u8] = &[ + b'T', b'Z', b'i', b'f', b'2', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, + 0, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0x4, 0, 0, 0, 0, 0, 0, b'U', b'T', b'C', + 0, 0, 0, b'T', b'Z', b'i', b'f', b'2', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0x4, 0, 0, 0, 0, 0, 0, b'U', + b'T', b'C', 0, 0, 0, 0x0a, 0x55, 0x54, 0x43, 0x30, 0x0a, +]; + +/// rtc文件中保存的内容 +pub const RTC_TIME: &str = r" +rtc_time : 03:01:50 +rtc_date : 2023-07-11 +alrm_time : 13:03:24 +alrm_date : 2023-07-11 +alarm_IRQ : no +alrm_pending : no +update IRQ enabled : no +periodic IRQ enabled : no +periodic IRQ frequency : 1024 +max user IRQ frequency : 64 +24hr : yes +periodic_IRQ : no +update_IRQ : no +HPET_emulated : no +BCD : yes +DST_enable : no +periodic_freq : 1024 +batt_status : okay"; diff --git a/kernel/src/fs/sys/mod.rs b/subsystems/vfs/src/sys/mod.rs similarity index 87% rename from kernel/src/fs/sys/mod.rs rename to subsystems/vfs/src/sys/mod.rs index de12de20..3bfa5a5a 100644 --- a/kernel/src/fs/sys/mod.rs +++ b/subsystems/vfs/src/sys/mod.rs @@ -1,12 +1,10 @@ -use crate::fs::CommonFsProviderImpl; -use crate::ksync::Mutex; +use crate::CommonFsProviderImpl; use alloc::sync::Arc; use dynfs::DynFsDirInode; +use ksync::Mutex; use vfscore::dentry::VfsDentry; use vfscore::fstype::VfsFsType; -mod cpu; -mod info; pub type SysFsDirInodeImpl = DynFsDirInode>; pub fn init_sysfs(sysfs: Arc) -> Arc {