Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose Linux syscall interface #63745

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/libstd/os/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@

pub mod raw;
pub mod fs;
pub mod syscall;
86 changes: 86 additions & 0 deletions src/libstd/os/linux/syscall/aarch64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#[inline(always)]
pub unsafe fn syscall0(n: usize) -> usize {
let ret : usize;
asm!("svc 0" : "={x0}"(ret)
: "{x8}"(n)
: "memory" "cc"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall1(n: usize, a1: usize) -> usize {
let ret : usize;
asm!("svc 0" : "={x0}"(ret)
: "{x8}"(n), "{x0}"(a1)
: "memory" "cc"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall2(n: usize, a1: usize, a2: usize) -> usize {
let ret : usize;
asm!("svc 0" : "={x0}"(ret)
: "{x8}"(n), "{x0}"(a1), "{x1}"(a2)
: "memory" "cc"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall3(n: usize, a1: usize, a2: usize, a3: usize) -> usize {
let ret : usize;
asm!("svc 0" : "={x0}"(ret)
: "{x8}"(n), "{x0}"(a1), "{x1}"(a2), "{x2}"(a3)
: "memory" "cc"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall4(n: usize, a1: usize, a2: usize, a3: usize,
a4: usize) -> usize {
let ret : usize;
asm!("svc 0" : "={x0}"(ret)
: "{x8}"(n), "{x0}"(a1), "{x1}"(a2), "{x2}"(a3), "{x3}"(a4)
: "memory" "cc"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall5(n: usize, a1: usize, a2: usize, a3: usize,
a4: usize, a5: usize) -> usize {
let ret : usize;
asm!("svc 0" : "={x0}"(ret)
: "{x8}"(n), "{x0}"(a1), "{x1}"(a2), "{x2}"(a3), "{x3}"(a4),
"{x4}"(a5)
: "memory" "cc"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall6(n: usize, a1: usize, a2: usize, a3: usize,
a4: usize, a5: usize, a6: usize) -> usize {
let ret : usize;
asm!("svc 0" : "={x0}"(ret)
: "{x8}"(n), "{x0}"(a1), "{x1}"(a2), "{x2}"(a3), "{x3}"(a4),
"{x4}"(a5), "{x6}"(a6)
: "memory" "cc"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall7(n: usize, a1: usize, a2: usize, a3: usize,
newpavlov marked this conversation as resolved.
Show resolved Hide resolved
a4: usize, a5: usize, a6: usize) -> usize {
let ret : usize;
asm!("svc 0" : "={x0}"(ret)
: "{x8}"(n), "{x0}"(a1), "{x1}"(a2), "{x2}"(a3), "{x3}"(a4)
"{x4}"(a5), "{x6}"(a6)
: "memory" "cc"
: "volatile");
ret
}
67 changes: 67 additions & 0 deletions src/libstd/os/linux/syscall/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//! Raw syscall functions.
#![unstable(feature = "linux_syscall", issue = "63748")]
#![cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))]

#[cfg(target_arch = "x86")]
#[path="x86.rs"] mod platform;

#[cfg(target_arch = "x86_64")]
#[path="x86_64.rs"] mod platform;

#[cfg(target_arch = "aarch64")]
#[path="aarch64"] mod platform;

/// Execute syscall with 0 arguments.
#[unstable(feature = "linux_syscall", issue = "63748")]
#[inline(always)]
pub unsafe fn syscall0(n: usize) -> usize {
platform::syscall0(n)
}

/// Execute syscall with 1 argument.
#[unstable(feature = "linux_syscall", issue = "63748")]
#[inline(always)]
pub unsafe fn syscall1(n: usize, a1: usize) -> usize {
platform::syscall1(n, a1)
}

/// Execute syscall with 2 arguments.
#[unstable(feature = "linux_syscall", issue = "63748")]
#[inline(always)]
pub unsafe fn syscall2(n: usize, a1: usize, a2: usize) -> usize {
platform::syscall2(n, a1, a2)
}

/// Execute syscall with 3 arguments.
#[unstable(feature = "linux_syscall", issue = "63748")]
#[inline(always)]
pub unsafe fn syscall3(n: usize, a1: usize, a2: usize, a3: usize) -> usize {
platform::syscall3(n, a1, a2, a3)
}

/// Execute syscall with 4 arguments.
#[unstable(feature = "linux_syscall", issue = "63748")]
#[inline(always)]
pub unsafe fn syscall4(
n: usize, a1: usize, a2: usize, a3: usize, a4: usize,
) -> usize {
platform::syscall4(n, a1, a2, a3, a4)
}

/// Execute syscall with 5 arguments.
#[unstable(feature = "linux_syscall", issue = "63748")]
#[inline(always)]
pub unsafe fn syscall5(
n: usize, a1: usize, a2: usize, a3: usize, a4: usize, a5: usize,
) -> usize {
platform::syscall5(n, a1, a2, a3, a4, a5)
}

/// Execute syscall with 6 arguments.
#[unstable(feature = "linux_syscall", issue = "63748")]
#[inline(always)]
pub unsafe fn syscall6(
n: usize, a1: usize, a2: usize, a3: usize, a4: usize, a5: usize, a6: usize,
) -> usize {
platform::syscall5(n, a1, a2, a3, a4, a5, a6)
newpavlov marked this conversation as resolved.
Show resolved Hide resolved
}
115 changes: 115 additions & 0 deletions src/libstd/os/linux/syscall/x86.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#[inline(always)]
pub unsafe fn syscall0(n: usize) -> usize {
let ret : usize;
asm!("int $$0x80" : "={eax}"(ret)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these be calling via the VDSO instead?

: "{eax}"(n)
: "memory" "cc"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall1(n: usize, a1: usize) -> usize {
let ret : usize;
asm!("int $$0x80" : "={eax}"(ret)
: "{eax}"(n), "{ebx}"(a1)
: "memory" "cc"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall2(n: usize, a1: usize, a2: usize) -> usize {
let ret : usize;
asm!("int $$0x80" : "={eax}"(ret)
: "{eax}"(n), "{ebx}"(a1), "{ecx}"(a2)
: "memory" "cc"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall3(n: usize, a1: usize, a2: usize, a3: usize) -> usize {
let ret : usize;
asm!("int $$0x80" : "={eax}"(ret)
: "{eax}"(n), "{ebx}"(a1), "{ecx}"(a2), "{edx}"(a3)
: "memory" "cc"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall4(n: usize, a1: usize, a2: usize, a3: usize,
a4: usize) -> usize {
let ret : usize;
asm!("int $$0x80" : "={eax}"(ret)
: "{eax}"(n), "{ebx}"(a1), "{ecx}"(a2), "{edx}"(a3),
"{esi}"(a4)
: "memory" "cc"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall5(n: usize, a1: usize, a2: usize, a3: usize,
a4: usize, a5: usize) -> usize {
let ret : usize;
asm!("int $$0x80" : "={eax}"(ret)
: "{eax}"(n), "{ebx}"(a1), "{ecx}"(a2), "{edx}"(a3),
"{esi}"(a4), "{edi}"(a5)
: "memory" "cc"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall6(n: usize, a1: usize, a2: usize, a3: usize,
a4: usize, a5: usize, a6: usize) -> usize {
let ret : usize;

//
// this fails when building without optimizations:
Copy link
Member

@joshtriplett joshtriplett Aug 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would something like the optimize attribute work here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could, but since optimize attribute is ignored in the presence of -C opt-level=n, I am not sure if we should use it. Although it's worth to check if this bug is still present.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@newpavlov I'm really surprised that optimize is ignored based on command-line options; this is a good use case for it always working.

I'd love to avoid this extra overhead if possible, but this doesn't need to be a blocker.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be concerned if optimize(...) would impact whether the build is successful / not. optimize(...) is a hint and has zero guarantees.

//
// asm!("int $$0x80" : "={eax}"(ret)
// : "{eax}"(n), "{ebx}"(a1), "{ecx}"(a2), "{edx}"(a3),
// "{esi}"(a4), "{edi}"(a5), "{ebp}"(a6)
// : "memory" "cc"
// : "volatile");
//
// error: ran out of registers during register allocation
//
// this fails when building with optimizations as the "m"(a6) gets translated to
// [esp+offset] but the push ebp moved esp.
//
// asm!("push %ebp
// mov $7, %ebp
// int $$0x80
// pop %ebp"
// : "={eax}"(ret)
// : "{eax}"(n), "{ebx}"(a1), "{ecx}"(a2), "{edx}"(a3),
// "{esi}"(a4), "{edi}"(a5), "m"(a6)
// : "memory" "cc"
// : "volatile");
//
// in general putting "ebp" in clobber list seems to not have any effect.
//
// As workaround only use a single input operand with known memory layout and manually save
// restore ebp.
let args = [n, a1, a2, a3, a4, a5, a6];

asm!("push %ebp
movl 24(%eax), %ebp
movl 20(%eax), %edi
movl 16(%eax), %esi
movl 12(%eax), %edx
movl 8(%eax), %ecx
movl 4(%eax), %ebx
movl 0(%eax), %eax
int $$0x80
pop %ebp"
: "={eax}"(ret)
: "{eax}"(args)
: "ebx" "ecx" "edx" "esi" "edi" "ebp" "memory" "cc"
: "volatile");
ret
}
75 changes: 75 additions & 0 deletions src/libstd/os/linux/syscall/x86_64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#[inline(always)]
pub unsafe fn syscall0(n: usize) -> usize {
let ret : usize;
asm!("syscall" : "={rax}"(ret)
: "{rax}"(n)
: "rcx", "r11", "memory"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall1(n: usize, a1: usize) -> usize {
let ret : usize;
asm!("syscall" : "={rax}"(ret)
: "{rax}"(n), "{rdi}"(a1)
: "rcx", "r11", "memory"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall2(n: usize, a1: usize, a2: usize) -> usize {
let ret : usize;
asm!("syscall" : "={rax}"(ret)
: "{rax}"(n), "{rdi}"(a1), "{rsi}"(a2)
: "rcx", "r11", "memory"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall3(n: usize, a1: usize, a2: usize, a3: usize) -> usize {
let ret : usize;
asm!("syscall" : "={rax}"(ret)
: "{rax}"(n), "{rdi}"(a1), "{rsi}"(a2), "{rdx}"(a3)
: "rcx", "r11", "memory"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall4(n: usize, a1: usize, a2: usize, a3: usize,
a4: usize) -> usize {
let ret : usize;
asm!("syscall" : "={rax}"(ret)
: "{rax}"(n), "{rdi}"(a1), "{rsi}"(a2), "{rdx}"(a3),
"{r10}"(a4)
: "rcx", "r11", "memory"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall5(n: usize, a1: usize, a2: usize, a3: usize,
a4: usize, a5: usize) -> usize {
let ret : usize;
asm!("syscall" : "={rax}"(ret)
: "{rax}"(n), "{rdi}"(a1), "{rsi}"(a2), "{rdx}"(a3),
"{r10}"(a4), "{r8}"(a5)
: "rcx", "r11", "memory"
: "volatile");
ret
}

#[inline(always)]
pub unsafe fn syscall6(n: usize, a1: usize, a2: usize, a3: usize,
a4: usize, a5: usize, a6: usize) -> usize {
let ret : usize;
asm!("syscall" : "={rax}"(ret)
: "{rax}"(n), "{rdi}"(a1), "{rsi}"(a2), "{rdx}"(a3),
"{r10}"(a4), "{r8}"(a5), "{r9}"(a6)
: "rcx", "r11", "memory"
: "volatile");
ret
}