#include "core_asm.h"
#include "vki_unistd.h"
-# XXX: must reinstate comments also -- see x86-linux/syscall.S
+/*
+ Perform a Linux syscall with the "syscall" instruction.
+
+ Incoming args (syscall number + up to 6 args) come in
+ %rdi, %rsi, %rdx, %rcx, %r8, %r9, and the last one on the stack
+ (ie. the C calling convention).
+
+ They are passed to the syscall in the regs
+ %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx), ie. the
+ kernel's syscall calling convention.
+ %rax holds the syscall number and gets the return value.
+ %rcx and %r11 are clobbered by the syscall; no matter, they
+ are caller-save (the syscall clobbers no callee-save regs, so
+ we don't have to do any register saving/restoring).
+
+ This has no effect on the virtual machine; the expectation is
+ that the syscall mechanism makes no useful changes to any
+ register except %rax, which is returned.
+*/
.globl VG_(do_syscall)
VG_(do_syscall):
- ud2
+ # Convert function calling convention --> syscall calling convention
+ movq %rdi, %rax
+ movq %rsi, %rdi
+ movq %rdx, %rsi
+ movq %rcx, %rdx
+ movq %r8, %r10
+ movq %r9, %r8
+ movq 8(%rsp), %r9 # last arg from stack
+ syscall
+ ret
+
+
+
+# XXX: must reinstate comments also -- see x86-linux/syscall.S
.globl VG_(clone)
VG_(clone):
ESZ(Off) off;
ESZ(Word) filesz;
ESZ(Word) memsz;
- ESZ(Word) align;
unsigned prot = 0;
if (ph->p_type != PT_LOAD)
if (ph->p_flags & PF_W) prot |= PROT_WRITE;
if (ph->p_flags & PF_R) prot |= PROT_READ;
- align = ph->p_align;
addr = ph->p_vaddr+base;
off = ph->p_offset;
filesz = ph->p_filesz;
memsz = ph->p_memsz;
brkaddr = addr+memsz;
- res = mmap((char *)ROUNDDN(addr, align),
- ROUNDUP(bss, align)-ROUNDDN(addr, align),
- prot, MAP_FIXED|MAP_PRIVATE, e->fd, ROUNDDN(off, align));
- check_mmap(res, (char*)ROUNDDN(addr,align),
- ROUNDUP(bss, align)-ROUNDDN(addr, align));
+ // Tom says: In the following, do what the Linux kernel does and only
+ // map the pages that are required instead of rounding everything to
+ // the specified alignment (ph->p_align). (AMD64 doesn't work if you
+ // use ph->p_align -- part of stage2's memory gets trashed somehow.)
- /* if memsz > filesz, then we need to fill the remainder with zeroed pages */
+ res = mmap((char *)PGROUNDDN(addr), PGROUNDUP(bss)-PGROUNDDN(addr),
+ prot, MAP_FIXED|MAP_PRIVATE, e->fd, PGROUNDDN(off));
+ check_mmap(res, (char*)PGROUNDDN(addr),
+ PGROUNDUP(bss)-PGROUNDDN(addr));
+
+ // if memsz > filesz, fill the remainder with zeroed pages
if (memsz > filesz) {
UInt bytes;
- bytes = ROUNDUP(brkaddr, align)-ROUNDUP(bss, align);
+ bytes = PGROUNDUP(brkaddr)-PGROUNDUP(bss);
if (bytes > 0) {
- res = mmap((char *)ROUNDUP(bss, align), bytes,
+ res = mmap((char *)PGROUNDUP(bss), bytes,
prot, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- check_mmap(res, (char*)ROUNDUP(bss,align), bytes);
+ check_mmap(res, (char*)PGROUNDUP(bss), bytes);
}
bytes = bss & (VKI_PAGE_SIZE - 1);