Merge branch 'better_proc_apis' into 'master'
Use improved `proc:` APIs from demand paging See merge request redox-os/relibc!415
This commit is contained in:
Generated
+60
-61
@@ -27,16 +27,16 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cbindgen"
|
||||
version = "0.24.3"
|
||||
version = "0.24.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6358dedf60f4d9b8db43ad187391afe959746101346fe51bb978126bec61dfb"
|
||||
checksum = "4b922faaf31122819ec80c4047cc684c6979a087366c069611e33649bf98e18d"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"heck",
|
||||
"indexmap",
|
||||
"log",
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.32",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 1.0.109",
|
||||
@@ -55,9 +55,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
version = "1.0.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
checksum = "51f1226cd9da55587234753d1245dd5b132343ea240f26b6a9003d68706141ba"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@@ -67,9 +70,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.2.23"
|
||||
version = "3.2.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5"
|
||||
checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
@@ -110,9 +113,9 @@ version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
|
||||
checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
@@ -172,9 +175,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
@@ -197,20 +200,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.10"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
|
||||
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.1",
|
||||
"hermit-abi 0.3.2",
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.6"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
@@ -232,15 +235,15 @@ source = "git+https://gitlab.redox-os.org/redox-os/liblibc.git?branch=redox_0.2.
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.1"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
|
||||
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.9"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
|
||||
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
@@ -248,12 +251,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
@@ -272,18 +272,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.5.0"
|
||||
version = "6.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267"
|
||||
checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac"
|
||||
|
||||
[[package]]
|
||||
name = "plain"
|
||||
@@ -306,9 +306,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.56"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
|
||||
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -324,11 +324,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.26"
|
||||
version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
||||
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"proc-macro2 1.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -389,8 +389,7 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/syscall#a525620c818a801bb7038e111b71033eff56a3ee"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
@@ -454,9 +453,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.13"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
||||
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||
|
||||
[[package]]
|
||||
name = "sc"
|
||||
@@ -466,9 +465,9 @@ checksum = "010e18bd3bfd1d45a7e666b236c78720df0d9a7698ebaa9c1c559961eb60a38b"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "scroll"
|
||||
@@ -514,29 +513,29 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.160"
|
||||
version = "1.0.180"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
|
||||
checksum = "0ea67f183f058fe88a4e3ec6e2788e003840893b91bac4559cabedd00863b3ed"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.160"
|
||||
version = "1.0.180"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
|
||||
checksum = "24e744d7782b686ab3b73267ef05697159cc0e5abbed3f47f9933165e5219036"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"syn 2.0.15",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.32",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.96"
|
||||
version = "1.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
|
||||
checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@@ -581,19 +580,19 @@ version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.32",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.15"
|
||||
version = "2.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
|
||||
checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.56",
|
||||
"quote 1.0.26",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.32",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
@@ -642,9 +641,9 @@ checksum = "e92e959f029e4f8ee25d70d15ab58d2b46f98a17bc238b9265ff0c26f6f3d67f"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.8"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
@@ -704,7 +703,7 @@ version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.0",
|
||||
"windows-targets 0.48.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -724,9 +723,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.0"
|
||||
version = "0.48.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
|
||||
checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.0",
|
||||
"windows_aarch64_msvc 0.48.0",
|
||||
|
||||
@@ -61,3 +61,4 @@ panic = "abort"
|
||||
|
||||
[patch.crates-io]
|
||||
libc = { git = "https://gitlab.redox-os.org/redox-os/liblibc.git", branch = "redox_0.2.138" }
|
||||
redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall" }
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use core::{ptr, slice};
|
||||
|
||||
use crate::platform::{sys::e, types::*};
|
||||
|
||||
use syscall::{error::*, F_SETFD, F_SETFL};
|
||||
|
||||
pub use redox_exec::*;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn redox_fpath(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t {
|
||||
e(syscall::fpath(
|
||||
@@ -46,5 +47,3 @@ pub fn pipe2(fds: &mut [c_int], flags: usize) -> syscall::error::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub use redox_exec::{create_set_addr_space_buf, FdGuard};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#![no_std]
|
||||
#![feature(array_chunks)]
|
||||
#![feature(array_chunks, int_roundings, let_chains, slice_ptr_get)]
|
||||
#![forbid(unreachable_patterns)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
@@ -22,7 +23,8 @@ use goblin::elf64::{
|
||||
use syscall::{
|
||||
error::*,
|
||||
flag::{MapFlags, SEEK_SET},
|
||||
PAGE_SIZE,
|
||||
PAGE_SIZE, Map, PROT_WRITE, O_CLOEXEC,
|
||||
GrantDesc, GrantFlags, PROT_READ, PROT_EXEC, MAP_SHARED, MAP_FIXED_NOREPLACE,
|
||||
};
|
||||
|
||||
pub use self::arch::*;
|
||||
@@ -82,7 +84,6 @@ where
|
||||
let current_addrspace_fd = FdGuard::new(syscall::dup(*open_via_dup, b"addrspace")?);
|
||||
FdGuard::new(syscall::dup(*current_addrspace_fd, b"empty")?)
|
||||
};
|
||||
let memory_fd = FdGuard::new(syscall::dup(*grants_fd, b"mem")?);
|
||||
|
||||
// Never allow more than 1 MiB of program headers.
|
||||
const MAX_PH_SIZE: usize = 1024 * 1024;
|
||||
@@ -105,9 +106,6 @@ where
|
||||
|o| core::mem::take(&mut o.tree),
|
||||
);
|
||||
|
||||
const BUFSZ: usize = 1024 * 256;
|
||||
let mut buf = vec![0_u8; BUFSZ];
|
||||
|
||||
read_all(*image_file as usize, Some(header.e_phoff as u64), phs)
|
||||
.map_err(|_| Error::new(EIO))?;
|
||||
|
||||
@@ -124,14 +122,6 @@ where
|
||||
flags |= syscall::PROT_WRITE;
|
||||
}
|
||||
|
||||
let voff = segment.p_vaddr as usize % PAGE_SIZE;
|
||||
let vaddr = segment.p_vaddr as usize - voff;
|
||||
let size = (segment.p_memsz as usize + voff + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE;
|
||||
|
||||
if segment.p_filesz > segment.p_memsz {
|
||||
return Err(Error::new(ENOEXEC));
|
||||
}
|
||||
#[forbid(unreachable_patterns)]
|
||||
match segment.p_type {
|
||||
// PT_INTERP must come before any PT_LOAD, so we don't have to iterate twice.
|
||||
PT_INTERP => {
|
||||
@@ -157,28 +147,100 @@ where
|
||||
});
|
||||
}
|
||||
PT_LOAD => {
|
||||
let voff = segment.p_vaddr as usize % PAGE_SIZE;
|
||||
let vaddr = segment.p_vaddr as usize - voff;
|
||||
let filesz = segment.p_filesz as usize;
|
||||
|
||||
let total_page_count = (segment.p_memsz as usize + voff).div_ceil(PAGE_SIZE);
|
||||
|
||||
// The case where segments overlap so that they share one page, is not handled.
|
||||
// TODO: Should it be?
|
||||
|
||||
if segment.p_filesz > segment.p_memsz {
|
||||
return Err(Error::new(ENOEXEC));
|
||||
}
|
||||
|
||||
allocate_remote(
|
||||
&grants_fd,
|
||||
memory_scheme_fd,
|
||||
vaddr,
|
||||
size,
|
||||
syscall::PROT_READ | syscall::PROT_WRITE,
|
||||
total_page_count * PAGE_SIZE,
|
||||
flags,
|
||||
)?;
|
||||
syscall::lseek(*image_file as usize, segment.p_offset as isize, SEEK_SET)
|
||||
.map_err(|_| Error::new(EIO))?;
|
||||
syscall::lseek(*memory_fd, segment.p_vaddr as isize, SEEK_SET)
|
||||
syscall::lseek(*image_file, segment.p_offset as isize, SEEK_SET)
|
||||
.map_err(|_| Error::new(EIO))?;
|
||||
|
||||
for size in core::iter::repeat(buf.len())
|
||||
.take((segment.p_filesz as usize) / buf.len())
|
||||
.chain(Some((segment.p_filesz as usize) % buf.len()))
|
||||
{
|
||||
read_all(*image_file as usize, None, &mut buf[..size])
|
||||
.map_err(|_| Error::new(EIO))?;
|
||||
let _ =
|
||||
syscall::write(*memory_fd, &buf[..size]).map_err(|_| Error::new(EIO))?;
|
||||
// If unaligned, read the head page separately.
|
||||
let (first_aligned_page, remaining_filesz) = if voff > 0 {
|
||||
let bytes_to_next_page = PAGE_SIZE - voff;
|
||||
|
||||
let (_guard, dst_page) = unsafe {
|
||||
MmapGuard::map_mut_anywhere(
|
||||
*grants_fd,
|
||||
vaddr,
|
||||
PAGE_SIZE,
|
||||
)?
|
||||
};
|
||||
|
||||
let length = core::cmp::min(bytes_to_next_page, filesz);
|
||||
|
||||
read_all(*image_file, None, &mut dst_page[voff..][..length])?;
|
||||
|
||||
(vaddr + PAGE_SIZE, filesz - length)
|
||||
} else {
|
||||
(vaddr, filesz)
|
||||
};
|
||||
|
||||
let remaining_page_count = remaining_filesz.div_floor(PAGE_SIZE);
|
||||
let tail_bytes = remaining_filesz % PAGE_SIZE;
|
||||
|
||||
// TODO: Unless the calling process if *very* memory-constrained, the max amount of
|
||||
// pages per iteration has no limit other than the time it takes to setup page
|
||||
// tables.
|
||||
//
|
||||
// TODO: Reserve PAGES_PER_ITER "scratch pages" of virtual memory for that type of
|
||||
// situation?
|
||||
const PAGES_PER_ITER: usize = 64;
|
||||
|
||||
// TODO: Before this loop, attempt to mmap with MAP_PRIVATE directly from the image
|
||||
// file.
|
||||
|
||||
for page_idx in (0..remaining_page_count).step_by(PAGES_PER_ITER) {
|
||||
// Use commented out lines to trigger kernel bug (FIXME).
|
||||
|
||||
//let pages_in_this_group = core::cmp::min(PAGES_PER_ITER, file_page_count - page_idx * PAGES_PER_ITER);
|
||||
let pages_in_this_group = core::cmp::min(PAGES_PER_ITER, remaining_page_count - page_idx);
|
||||
|
||||
if pages_in_this_group == 0 { break }
|
||||
|
||||
// TODO: MAP_FIXED to optimize away funmap?
|
||||
let (_guard, dst_memory) = unsafe {
|
||||
MmapGuard::map_mut_anywhere(
|
||||
*grants_fd,
|
||||
first_aligned_page + page_idx * PAGE_SIZE, // offset
|
||||
pages_in_this_group * PAGE_SIZE, // size
|
||||
)?
|
||||
};
|
||||
|
||||
// TODO: Are &mut [u8] and &mut [[u8; PAGE_SIZE]] interchangeable (if the
|
||||
// lengths are aligned, obviously)?
|
||||
|
||||
read_all(*image_file, None, dst_memory)?;
|
||||
}
|
||||
mprotect_remote(&grants_fd, vaddr, size, flags)?;
|
||||
|
||||
if tail_bytes > 0 {
|
||||
let (_guard, dst_page) = unsafe {
|
||||
MmapGuard::map_mut_anywhere(
|
||||
*grants_fd,
|
||||
first_aligned_page + remaining_page_count * PAGE_SIZE,
|
||||
PAGE_SIZE,
|
||||
)?
|
||||
};
|
||||
read_all(*image_file, None, &mut dst_page[..tail_bytes])?;
|
||||
}
|
||||
|
||||
// file_page_count..file_page_count + zero_page_count are already zero-initialized
|
||||
// by the kernel.
|
||||
|
||||
if !tree
|
||||
.range(..=vaddr)
|
||||
@@ -186,7 +248,7 @@ where
|
||||
.filter(|(start, size)| **start + **size > vaddr)
|
||||
.is_some()
|
||||
{
|
||||
tree.insert(vaddr, size);
|
||||
tree.insert(vaddr, total_page_count * PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
@@ -202,11 +264,36 @@ where
|
||||
)?;
|
||||
tree.insert(STACK_TOP - STACK_SIZE, STACK_SIZE);
|
||||
|
||||
let mut sp = STACK_TOP - 256;
|
||||
let mut sp = STACK_TOP;
|
||||
let mut stack_page = Option::<MmapGuard>::None;
|
||||
|
||||
let mut push = |word: usize| {
|
||||
let old_page_no = sp / PAGE_SIZE;
|
||||
sp -= size_of::<usize>();
|
||||
write_all(*memory_fd, Some(sp as u64), &usize::to_ne_bytes(word))
|
||||
let new_page_no = sp / PAGE_SIZE;
|
||||
let new_page_off = sp % PAGE_SIZE;
|
||||
|
||||
let page = if let Some(ref mut page) = stack_page && old_page_no == new_page_no {
|
||||
page
|
||||
} else if let Some(ref mut stack_page) = stack_page {
|
||||
stack_page.remap(new_page_no * PAGE_SIZE, PROT_WRITE)?;
|
||||
stack_page
|
||||
} else {
|
||||
let new = MmapGuard::map(*grants_fd, &Map {
|
||||
offset: new_page_no * PAGE_SIZE,
|
||||
size: PAGE_SIZE,
|
||||
flags: PROT_WRITE,
|
||||
address: 0, // let kernel decide
|
||||
})?;
|
||||
|
||||
stack_page.insert(new)
|
||||
};
|
||||
|
||||
unsafe {
|
||||
page.as_mut_ptr_slice().as_mut_ptr().add(new_page_off).cast::<usize>().write(word);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let pheaders_to_convey = if let Some(ref r#override) = interp_override {
|
||||
@@ -214,7 +301,7 @@ where
|
||||
} else {
|
||||
&*phs_raw
|
||||
};
|
||||
let pheaders_size_aligned = (pheaders_to_convey.len() + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE;
|
||||
let pheaders_size_aligned = pheaders_to_convey.len().next_multiple_of(PAGE_SIZE);
|
||||
let pheaders = find_free_target_addr(&tree, pheaders_size_aligned).ok_or(Error::new(ENOMEM))?;
|
||||
tree.insert(pheaders, pheaders_size_aligned);
|
||||
allocate_remote(
|
||||
@@ -224,7 +311,15 @@ where
|
||||
pheaders_size_aligned,
|
||||
MapFlags::PROT_READ | MapFlags::PROT_WRITE,
|
||||
)?;
|
||||
write_all(*memory_fd, Some(pheaders as u64), &pheaders_to_convey)?;
|
||||
unsafe {
|
||||
let (_guard, memory) = MmapGuard::map_mut_anywhere(
|
||||
*grants_fd,
|
||||
pheaders,
|
||||
pheaders_size_aligned,
|
||||
)?;
|
||||
|
||||
memory[..pheaders_to_convey.len()].copy_from_slice(pheaders_to_convey);
|
||||
}
|
||||
mprotect_remote(
|
||||
&grants_fd,
|
||||
pheaders,
|
||||
@@ -257,8 +352,7 @@ where
|
||||
|
||||
let total_args_envs_auxvpointee_size =
|
||||
total_args_envs_size + extrainfo.cwd.map_or(0, |s| s.len() + 1);
|
||||
let args_envs_size_aligned =
|
||||
(total_args_envs_auxvpointee_size + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE;
|
||||
let args_envs_size_aligned = total_args_envs_auxvpointee_size.next_multiple_of(PAGE_SIZE);
|
||||
let target_args_env_address =
|
||||
find_free_target_addr(&tree, args_envs_size_aligned).ok_or(Error::new(ENOMEM))?;
|
||||
allocate_remote(
|
||||
@@ -276,8 +370,25 @@ where
|
||||
|
||||
{
|
||||
let mut append = |source_slice: &[u8]| {
|
||||
// TODO
|
||||
let address = target_args_env_address + offset;
|
||||
write_all(*memory_fd, Some(address as u64), source_slice)?;
|
||||
|
||||
if !source_slice.is_empty() {
|
||||
let containing_page = address.div_floor(PAGE_SIZE) * PAGE_SIZE;
|
||||
let displacement = address - containing_page;
|
||||
let size = source_slice.len() + displacement;
|
||||
let aligned_size = size.next_multiple_of(PAGE_SIZE);
|
||||
|
||||
let (_guard, memory) = unsafe {
|
||||
MmapGuard::map_mut_anywhere(
|
||||
*grants_fd,
|
||||
containing_page,
|
||||
aligned_size,
|
||||
)?
|
||||
};
|
||||
memory[displacement..][..source_slice.len()].copy_from_slice(source_slice);
|
||||
}
|
||||
|
||||
offset += source_slice.len() + 1;
|
||||
Ok(address)
|
||||
};
|
||||
@@ -328,7 +439,7 @@ where
|
||||
if interp_override.is_some() {
|
||||
let mmap_min_fd = FdGuard::new(syscall::dup(*grants_fd, b"mmap-min-addr")?);
|
||||
let last_addr = tree.iter().rev().nth(1).map_or(0, |(off, len)| *off + *len);
|
||||
let aligned_last_addr = (last_addr + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE;
|
||||
let aligned_last_addr = last_addr.next_multiple_of(PAGE_SIZE);
|
||||
let _ = syscall::write(*mmap_min_fd, &usize::to_ne_bytes(aligned_last_addr));
|
||||
}
|
||||
|
||||
@@ -456,21 +567,6 @@ fn read_all(fd: usize, offset: Option<u64>, buf: &mut [u8]) -> Result<()> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn write_all(fd: usize, offset: Option<u64>, buf: &[u8]) -> Result<()> {
|
||||
if let Some(offset) = offset {
|
||||
syscall::lseek(fd, offset as isize, SEEK_SET)?;
|
||||
}
|
||||
|
||||
let mut total_bytes_written = 0;
|
||||
|
||||
while total_bytes_written < buf.len() {
|
||||
total_bytes_written += match syscall::write(fd, &buf[total_bytes_written..])? {
|
||||
0 => return Err(Error::new(EIO)),
|
||||
bytes_written => bytes_written,
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO: With the introduction of remote mmaps, remove this and let the kernel handle address
|
||||
// allocation.
|
||||
@@ -493,6 +589,64 @@ fn find_free_target_addr(tree: &BTreeMap<usize, usize>, size: usize) -> Option<u
|
||||
None
|
||||
}
|
||||
|
||||
pub struct MmapGuard {
|
||||
fd: usize,
|
||||
base: usize,
|
||||
size: usize,
|
||||
}
|
||||
impl MmapGuard {
|
||||
pub fn map(fd: usize, map: &Map) -> Result<Self> {
|
||||
Ok(Self {
|
||||
fd,
|
||||
size: map.size,
|
||||
base: unsafe { syscall::fmap(fd, map)? },
|
||||
})
|
||||
}
|
||||
pub fn remap(&mut self, offset: usize, mut flags: MapFlags) -> Result<()> {
|
||||
flags.remove(MapFlags::MAP_FIXED_NOREPLACE);
|
||||
flags.insert(MapFlags::MAP_FIXED);
|
||||
|
||||
let _new_base = unsafe { syscall::fmap(self.fd, &Map {
|
||||
offset,
|
||||
size: self.size,
|
||||
flags,
|
||||
address: self.base,
|
||||
})? };
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub unsafe fn map_mut_anywhere<'a>(fd: usize, offset: usize, size: usize) -> Result<(Self, &'a mut [u8])> {
|
||||
let mut this = Self::map(fd, &Map {
|
||||
size,
|
||||
offset,
|
||||
address: 0,
|
||||
flags: PROT_WRITE,
|
||||
})?;
|
||||
let slice = &mut *this.as_mut_ptr_slice();
|
||||
|
||||
Ok((this, slice))
|
||||
}
|
||||
pub fn addr(&self) -> usize {
|
||||
self.base
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
self.size
|
||||
}
|
||||
pub fn as_mut_ptr_slice(&mut self) -> *mut [u8] {
|
||||
core::ptr::slice_from_raw_parts_mut(self.base as *mut u8, self.size)
|
||||
}
|
||||
pub fn take(mut self) {
|
||||
self.size = 0;
|
||||
}
|
||||
}
|
||||
impl Drop for MmapGuard {
|
||||
fn drop(&mut self) {
|
||||
if self.size != 0 {
|
||||
let _ = unsafe { syscall::funmap(self.base, self.size) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FdGuard {
|
||||
fd: usize,
|
||||
taken: bool,
|
||||
@@ -552,7 +706,7 @@ fn fork_inner(initial_rsp: *mut usize) -> Result<usize> {
|
||||
{
|
||||
let cur_pid_fd = FdGuard::new(syscall::open(
|
||||
"thisproc:current/open_via_dup",
|
||||
syscall::O_CLOEXEC,
|
||||
O_CLOEXEC,
|
||||
)?);
|
||||
(new_pid_fd, new_pid) = new_context()?;
|
||||
|
||||
@@ -596,50 +750,64 @@ fn fork_inner(initial_rsp: *mut usize) -> Result<usize> {
|
||||
|
||||
// CoW-duplicate address space.
|
||||
{
|
||||
let new_addr_space_sel_fd =
|
||||
FdGuard::new(syscall::dup(*new_pid_fd, b"current-addrspace")?);
|
||||
|
||||
let cur_addr_space_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"addrspace")?);
|
||||
|
||||
// FIXME: Find mappings which use external file descriptors
|
||||
|
||||
let new_addr_space_fd = FdGuard::new(syscall::dup(*cur_addr_space_fd, b"exclusive")?);
|
||||
|
||||
let mut buf = vec![0_u8; 4096];
|
||||
let mut bytes_read = 0;
|
||||
|
||||
let mut grant_desc_buf = [GrantDesc::default(); 16];
|
||||
loop {
|
||||
let new_bytes_read = syscall::read(*cur_addr_space_fd, &mut buf[bytes_read..])?;
|
||||
|
||||
if new_bytes_read == 0 {
|
||||
let bytes_read = {
|
||||
let buf = unsafe { core::slice::from_raw_parts_mut(grant_desc_buf.as_mut_ptr().cast(), grant_desc_buf.len() * size_of::<GrantDesc>()) };
|
||||
syscall::read(*cur_addr_space_fd, buf)?
|
||||
};
|
||||
if bytes_read == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
bytes_read += new_bytes_read;
|
||||
}
|
||||
let bytes = &buf[..bytes_read];
|
||||
let grants = &grant_desc_buf[..bytes_read / size_of::<GrantDesc>()];
|
||||
|
||||
for struct_bytes in bytes.array_chunks::<{ size_of::<usize>() * 4 }>() {
|
||||
let mut words = struct_bytes
|
||||
.array_chunks::<{ size_of::<usize>() }>()
|
||||
.copied()
|
||||
.map(usize::from_ne_bytes);
|
||||
for grant in grants {
|
||||
if !grant.flags.contains(GrantFlags::GRANT_SCHEME) || !grant.flags.contains(GrantFlags::GRANT_SHARED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let addr = words.next().unwrap();
|
||||
let size = words.next().unwrap();
|
||||
let flags = words.next().unwrap();
|
||||
let offset = words.next().unwrap();
|
||||
let mut buf;
|
||||
|
||||
if flags & 0x8000_0000 == 0 {
|
||||
continue;
|
||||
// TODO: write! using some #![no_std] Cursor type (tracking the length)?
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
{
|
||||
//buf = *b"grant-fd-AAAABBBBCCCCDDDD";
|
||||
//write!(&mut buf, "grant-fd-{:>016x}", grant.base).unwrap();
|
||||
buf = alloc::format!("grant-fd-{:>016x}", grant.base).into_bytes();
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
{
|
||||
//buf = *b"grant-fd-AAAABBBB";
|
||||
//write!(&mut buf[..], "grant-fd-{:>08x}", grant.base).unwrap();
|
||||
buf = alloc::format!("grant-fd-{:>08x}", grant.base).into_bytes();
|
||||
}
|
||||
|
||||
let grant_fd = FdGuard::new(syscall::dup(*cur_addr_space_fd, &buf)?);
|
||||
|
||||
let mut flags = MAP_SHARED | MAP_FIXED_NOREPLACE;
|
||||
|
||||
flags.set(PROT_READ, grant.flags.contains(GrantFlags::GRANT_READ));
|
||||
flags.set(PROT_WRITE, grant.flags.contains(GrantFlags::GRANT_WRITE));
|
||||
flags.set(PROT_EXEC, grant.flags.contains(GrantFlags::GRANT_EXEC));
|
||||
|
||||
mmap_remote(
|
||||
&new_addr_space_fd,
|
||||
&grant_fd,
|
||||
grant.offset as usize,
|
||||
grant.base,
|
||||
grant.size,
|
||||
flags,
|
||||
)?;
|
||||
}
|
||||
let map_flags = MapFlags::from_bits_truncate(flags);
|
||||
|
||||
let grant_fd = FdGuard::new(syscall::dup(
|
||||
*cur_addr_space_fd,
|
||||
alloc::format!("grant-{:x}", addr).as_bytes(),
|
||||
)?);
|
||||
mmap_remote(&new_addr_space_fd, &grant_fd, offset, addr, size, map_flags)?;
|
||||
}
|
||||
let new_addr_space_sel_fd =
|
||||
FdGuard::new(syscall::dup(*new_pid_fd, b"current-addrspace")?);
|
||||
|
||||
let buf = create_set_addr_space_buf(
|
||||
*new_addr_space_fd,
|
||||
@@ -680,7 +848,7 @@ pub fn new_context() -> Result<(FdGuard, usize)> {
|
||||
// Create a new context (fields such as uid/gid will be inherited from the current context).
|
||||
let fd = FdGuard::new(syscall::open(
|
||||
"thisproc:new/open_via_dup",
|
||||
syscall::O_CLOEXEC,
|
||||
O_CLOEXEC,
|
||||
)?);
|
||||
|
||||
// Extract pid.
|
||||
|
||||
Reference in New Issue
Block a user