Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Andrea Fioraldi 2021-09-13 16:05:01 +02:00
commit 35ea8abea1
57 changed files with 4426 additions and 2299 deletions

View File

@ -1,121 +0,0 @@
/*-
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)mman.h 8.2 (Berkeley) 1/9/95
* $FreeBSD: src/sys/sys/mman.h,v 1.42 2008/03/28 04:29:27 ps Exp $
*/
#define TARGET_FREEBSD_MAP_RESERVED0080 0x0080 /* previously misimplemented MAP_INHERIT */
#define TARGET_FREEBSD_MAP_RESERVED0100 0x0100 /* previously unimplemented MAP_NOEXTEND */
#define TARGET_FREEBSD_MAP_STACK 0x0400 /* region grows down, like a stack */
#define TARGET_FREEBSD_MAP_NOSYNC 0x0800 /* page to but do not sync underlying file */
#define TARGET_FREEBSD_MAP_FLAGMASK 0x1ff7
/* $NetBSD: mman.h,v 1.42 2008/11/18 22:13:49 ad Exp $ */
/*-
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)mman.h 8.2 (Berkeley) 1/9/95
*/
#define TARGET_NETBSD_MAP_INHERIT 0x0080 /* region is retained after exec */
#define TARGET_NETBSD_MAP_TRYFIXED 0x0400 /* attempt hint address, even within break */
#define TARGET_NETBSD_MAP_WIRED 0x0800 /* mlock() mapping when it is established */
#define TARGET_NETBSD_MAP_STACK 0x2000 /* allocated from memory, swap space (stack) */
#define TARGET_NETBSD_MAP_FLAGMASK 0x3ff7
/* $OpenBSD: mman.h,v 1.18 2003/07/21 22:52:19 tedu Exp $ */
/* $NetBSD: mman.h,v 1.11 1995/03/26 20:24:23 jtc Exp $ */
/*-
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)mman.h 8.1 (Berkeley) 6/2/93
*/
#define TARGET_OPENBSD_MAP_INHERIT 0x0080 /* region is retained after exec */
#define TARGET_OPENBSD_MAP_NOEXTEND 0x0100 /* for MAP_FILE, don't change file size */
#define TARGET_OPENBSD_MAP_TRYFIXED 0x0400 /* attempt hint address, even within heap */
#define TARGET_OPENBSD_MAP_FLAGMASK 0x17f7
// XXX
#define TARGET_BSD_MAP_FLAGMASK 0x3ff7

View File

@ -1,11 +1,24 @@
/* Code for loading BSD executables. Mostly linux kernel code. */ /*
* Load BSD executables.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu.h" #include "qemu.h"
#define TARGET_NGROUPS 32
/* ??? This should really be somewhere else. */ /* ??? This should really be somewhere else. */
abi_long memcpy_to_target(abi_ulong dest, const void *src, abi_long memcpy_to_target(abi_ulong dest, const void *src,
unsigned long len) unsigned long len)
@ -83,7 +96,7 @@ static int prepare_binprm(struct bsd_binprm *bprm)
/* Construct the envp and argv tables on the target stack. */ /* Construct the envp and argv tables on the target stack. */
abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
abi_ulong stringp, int push_ptr) abi_ulong stringp)
{ {
int n = sizeof(abi_ulong); int n = sizeof(abi_ulong);
abi_ulong envp; abi_ulong envp;
@ -93,13 +106,6 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
envp = sp; envp = sp;
sp -= (argc + 1) * n; sp -= (argc + 1) * n;
argv = sp; argv = sp;
if (push_ptr) {
/* FIXME - handle put_user() failures */
sp -= n;
put_user_ual(envp, sp);
sp -= n;
put_user_ual(argv, sp);
}
sp -= n; sp -= n;
/* FIXME - handle put_user() failures */ /* FIXME - handle put_user() failures */
put_user_ual(argc, sp); put_user_ual(argc, sp);
@ -124,36 +130,70 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
return sp; return sp;
} }
int loader_exec(const char *filename, char **argv, char **envp, static bool is_there(const char *candidate)
struct target_pt_regs *regs, struct image_info *infop)
{ {
struct bsd_binprm bprm; struct stat fin;
int retval;
int i;
bprm.p = TARGET_PAGE_SIZE * MAX_ARG_PAGES - sizeof(unsigned int); /* XXX work around access(2) false positives for superuser */
for (i = 0 ; i < MAX_ARG_PAGES ; i++) { /* clear page-table */ if (access(candidate, X_OK) == 0 && stat(candidate, &fin) == 0 &&
bprm.page[i] = NULL; S_ISREG(fin.st_mode) && (getuid() != 0 ||
(fin.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)) {
return true;
} }
retval = open(filename, O_RDONLY);
return false;
}
int loader_exec(const char *filename, char **argv, char **envp,
struct target_pt_regs *regs, struct image_info *infop,
struct bsd_binprm *bprm)
{
char *path, fullpath[PATH_MAX];
int retval, i;
bprm->p = TARGET_PAGE_SIZE * MAX_ARG_PAGES;
for (i = 0; i < MAX_ARG_PAGES; i++) { /* clear page-table */
bprm->page[i] = NULL;
}
if (strchr(filename, '/') != NULL) {
path = realpath(filename, fullpath);
if (path == NULL) {
/* Failed to resolve. */
return -1;
}
if (!is_there(path)) {
return -1;
}
} else {
path = g_find_program_in_path(filename);
if (path == NULL) {
return -1;
}
}
retval = open(path, O_RDONLY);
if (retval < 0) { if (retval < 0) {
g_free(path);
return retval; return retval;
} }
bprm.fd = retval;
bprm.filename = (char *)filename;
bprm.argc = count(argv);
bprm.argv = argv;
bprm.envc = count(envp);
bprm.envp = envp;
retval = prepare_binprm(&bprm); bprm->fullpath = path;
bprm->fd = retval;
bprm->filename = (char *)filename;
bprm->argc = count(argv);
bprm->argv = argv;
bprm->envc = count(envp);
bprm->envp = envp;
retval = prepare_binprm(bprm);
if (retval >= 0) { if (retval >= 0) {
if (bprm.buf[0] == 0x7f if (bprm->buf[0] == 0x7f
&& bprm.buf[1] == 'E' && bprm->buf[1] == 'E'
&& bprm.buf[2] == 'L' && bprm->buf[2] == 'L'
&& bprm.buf[3] == 'F') { && bprm->buf[3] == 'F') {
retval = load_elf_binary(&bprm, regs, infop); retval = load_elf_binary(bprm, regs, infop);
} else { } else {
fprintf(stderr, "Unknown binary format\n"); fprintf(stderr, "Unknown binary format\n");
return -1; return -1;
@ -168,7 +208,7 @@ int loader_exec(const char *filename, char **argv, char **envp,
/* Something went wrong, return the inode and free the argument pages*/ /* Something went wrong, return the inode and free the argument pages*/
for (i = 0 ; i < MAX_ARG_PAGES ; i++) { for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
g_free(bprm.page[i]); g_free(bprm->page[i]);
} }
return retval; return retval;
} }

10
bsd-user/elfcore.c Normal file
View File

@ -0,0 +1,10 @@
/* Stubbed out version of core dump support, explicitly in public domain */
static int elf_core_dump(int signr, CPUArchState *env)
{
struct elf_note en = { 0 };
bswap_note(&en);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
/*
* FreeBSD host dependent code and definitions
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _HOST_OS_H_
#define _HOST_OS_H_
#define HOST_DEFAULT_BSD_TYPE target_freebsd
#endif /*!_HOST_OS_H_ */

View File

@ -0,0 +1,137 @@
/*
* freebsd ELF definitions
*
* Copyright (c) 2013-15 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_OS_ELF_H_
#define _TARGET_OS_ELF_H_
#include "target_arch_elf.h"
#include "elf.h"
#define bsd_get_ncpu() 1 /* until we pull in bsd-proc.[hc] */
/* this flag is uneffective under linux too, should be deleted */
#ifndef MAP_DENYWRITE
#define MAP_DENYWRITE 0
#endif
/* should probably go in elf.h */
#ifndef ELIBBAD
#define ELIBBAD 80
#endif
#ifndef ELF_PLATFORM
#define ELF_PLATFORM (NULL)
#endif
#ifndef ELF_HWCAP
#define ELF_HWCAP 0
#endif
/* XXX Look at the other conflicting AT_* values. */
#define FREEBSD_AT_NCPUS 19
#define FREEBSD_AT_HWCAP 25
#define FREEBSD_AT_HWCAP2 26
#ifdef TARGET_ABI32
#undef ELF_CLASS
#define ELF_CLASS ELFCLASS32
#undef bswaptls
#define bswaptls(ptr) bswap32s(ptr)
#endif
/* max code+data+bss space allocated to elf interpreter */
#define INTERP_MAP_SIZE (32 * 1024 * 1024)
/* max code+data+bss+brk space allocated to ET_DYN executables */
#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
/* Necessary parameters */
#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
#define TARGET_ELF_PAGESTART(_v) ((_v) & \
~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE - 1))
#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE - 1))
#define DLINFO_ITEMS 14
static abi_ulong target_create_elf_tables(abi_ulong p, int argc, int envc,
abi_ulong stringp,
struct elfhdr *exec,
abi_ulong load_addr,
abi_ulong load_bias,
abi_ulong interp_load_addr,
struct image_info *info)
{
abi_ulong features, sp;
int size;
const int n = sizeof(elf_addr_t);
target_auxents_sz = 0;
sp = p;
/*
* Force 16 byte _final_ alignment here for generality.
*/
sp = sp & ~(abi_ulong)15;
size = (DLINFO_ITEMS + 1) * 2;
size += envc + argc + 2;
size += 1; /* argc itself */
size *= n;
if (size & 15) {
sp -= 16 - (size & 15);
}
/*
* FreeBSD defines elf_addr_t as Elf32_Off / Elf64_Off
*/
#define NEW_AUX_ENT(id, val) do { \
sp -= n; put_user_ual(val, sp); \
sp -= n; put_user_ual(id, sp); \
target_auxents_sz += 2 * n; \
} while (0)
NEW_AUX_ENT(AT_NULL, 0);
/* There must be exactly DLINFO_ITEMS entries here. */
NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof(struct elf_phdr)));
NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
NEW_AUX_ENT(FREEBSD_AT_NCPUS, (abi_ulong)bsd_get_ncpu());
NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
NEW_AUX_ENT(AT_UID, (abi_ulong)getuid());
NEW_AUX_ENT(AT_EUID, (abi_ulong)geteuid());
NEW_AUX_ENT(AT_GID, (abi_ulong)getgid());
NEW_AUX_ENT(AT_EGID, (abi_ulong)getegid());
features = ELF_HWCAP;
NEW_AUX_ENT(FREEBSD_AT_HWCAP, features);
target_auxents = sp; /* Note where the aux entries are in the target */
#ifdef ARCH_DLINFO
/*
* ARCH_DLINFO must come last so platform specific code can enforce
* special alignment requirements on the AUXV if necessary (eg. PPC).
*/
ARCH_DLINFO;
#endif
#undef NEW_AUX_ENT
sp = loader_build_argptr(envc, argc, sp, stringp);
return sp;
}
#endif /* _TARGET_OS_ELF_H_ */

View File

@ -0,0 +1,145 @@
/*
* FreeBSD siginfo related definitions
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_OS_SIGINFO_H_
#define _TARGET_OS_SIGINFO_H_
#define TARGET_NSIG 128
#define TARGET_NSIG_BPW (sizeof(uint32_t) * 8)
#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
/* this struct defines a stack used during syscall handling */
typedef struct target_sigaltstack {
abi_long ss_sp;
abi_ulong ss_size;
abi_long ss_flags;
} target_stack_t;
typedef struct {
uint32_t __bits[TARGET_NSIG_WORDS];
} target_sigset_t;
struct target_sigaction {
abi_ulong _sa_handler;
int32_t sa_flags;
target_sigset_t sa_mask;
};
typedef union target_sigval {
int32_t sival_int;
abi_ulong sival_ptr;
int32_t sigval_int;
abi_ulong sigval_ptr;
} target_sigval_t;
typedef struct target_siginfo {
int32_t si_signo; /* signal number */
int32_t si_errno; /* errno association */
int32_t si_code; /* signal code */
int32_t si_pid; /* sending process */
int32_t si_uid; /* sender's ruid */
int32_t si_status; /* exit value */
abi_ulong si_addr; /* faulting instruction */
union target_sigval si_value; /* signal value */
union {
struct {
int32_t _trapno; /* machine specific trap code */
} _fault;
/* POSIX.1b timers */
struct {
int32_t _timerid;
int32_t _overrun;
} _timer;
struct {
int32_t _mqd;
} _mesgp;
/* SIGPOLL */
struct {
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
} _poll;
struct {
abi_long __spare1__;
int32_t __spare2_[7];
} __spare__;
} _reason;
} target_siginfo_t;
struct target_sigevent {
abi_int sigev_notify;
abi_int sigev_signo;
target_sigval_t sigev_value;
union {
abi_int _threadid;
/*
* The kernel (and thus QEMU) never looks at these;
* they're only used as part of the ABI between a
* userspace program and libc.
*/
struct {
abi_ulong _function;
abi_ulong _attribute;
} _sigev_thread;
abi_ushort _kevent_flags;
abi_long _pad[8];
} _sigev_un;
};
#define target_si_signo si_signo
#define target_si_code si_code
#define target_si_errno si_errno
#define target_si_addr si_addr
/* SIGILL si_codes */
#define TARGET_ILL_ILLOPC (1) /* Illegal opcode. */
#define TARGET_ILL_ILLOPN (2) /* Illegal operand. */
#define TARGET_ILL_ILLADR (3) /* Illegal addressing mode. */
#define TARGET_ILL_ILLTRP (4) /* Illegal trap. */
#define TARGET_ILL_PRVOPC (5) /* Privileged opcode. */
#define TARGET_ILL_PRVREG (6) /* Privileged register. */
#define TARGET_ILL_COPROC (7) /* Coprocessor error. */
#define TARGET_ILL_BADSTK (8) /* Internal stack error. */
/* SIGSEGV si_codes */
#define TARGET_SEGV_MAPERR (1) /* address not mapped to object */
#define TARGET_SEGV_ACCERR (2) /* invalid permissions for mapped object */
/* SIGTRAP si_codes */
#define TARGET_TRAP_BRKPT (1) /* process beakpoint */
#define TARGET_TRAP_TRACE (2) /* process trace trap */
/* SIGBUS si_codes */
#define TARGET_BUS_ADRALN (1)
#define TARGET_BUS_ADRERR (2)
#define TARGET_BUS_OBJERR (3)
/* SIGFPE codes */
#define TARGET_FPE_INTOVF (1) /* Integer overflow. */
#define TARGET_FPE_INTDIV (2) /* Integer divide by zero. */
#define TARGET_FPE_FLTDIV (3) /* Floating point divide by zero. */
#define TARGET_FPE_FLTOVF (4) /* Floating point overflow. */
#define TARGET_FPE_FLTUND (5) /* Floating point underflow. */
#define TARGET_FPE_FLTRES (6) /* Floating point inexact result. */
#define TARGET_FPE_FLTINV (7) /* Invalid floating point operation. */
#define TARGET_FPE_FLTSUB (8) /* Subscript out of range. */
#endif /* !_TARGET_OS_SIGINFO_H_ */

View File

@ -0,0 +1,78 @@
#ifndef _TARGET_OS_SIGNAL_H_
#define _TARGET_OS_SIGNAL_H_
#include "target_os_siginfo.h"
#include "target_arch_signal.h"
/* Compare to sys/signal.h */
#define TARGET_SIGHUP 1 /* hangup */
#define TARGET_SIGINT 2 /* interrupt */
#define TARGET_SIGQUIT 3 /* quit */
#define TARGET_SIGILL 4 /* illegal instruction (not reset when caught) */
#define TARGET_SIGTRAP 5 /* trace trap (not reset when caught) */
#define TARGET_SIGABRT 6 /* abort() */
#define TARGET_SIGIOT SIGABRT /* compatibility */
#define TARGET_SIGEMT 7 /* EMT instruction */
#define TARGET_SIGFPE 8 /* floating point exception */
#define TARGET_SIGKILL 9 /* kill (cannot be caught or ignored) */
#define TARGET_SIGBUS 10 /* bus error */
#define TARGET_SIGSEGV 11 /* segmentation violation */
#define TARGET_SIGSYS 12 /* bad argument to system call */
#define TARGET_SIGPIPE 13 /* write on a pipe with no one to read it */
#define TARGET_SIGALRM 14 /* alarm clock */
#define TARGET_SIGTERM 15 /* software termination signal from kill */
#define TARGET_SIGURG 16 /* urgent condition on IO channel */
#define TARGET_SIGSTOP 17 /* sendable stop signal not from tty */
#define TARGET_SIGTSTP 18 /* stop signal from tty */
#define TARGET_SIGCONT 19 /* continue a stopped process */
#define TARGET_SIGCHLD 20 /* to parent on child stop or exit */
#define TARGET_SIGTTIN 21 /* to readers pgrp upon background tty read */
#define TARGET_SIGTTOU 22 /* like TTIN for output if(tp->t_local&LTOSTOP)*/
#define TARGET_SIGIO 23 /* input/output possible signal */
#define TARGET_SIGXCPU 24 /* exceeded CPU time limit */
#define TARGET_SIGXFSZ 25 /* exceeded file size limit */
#define TARGET_SIGVTALRM 26 /* virtual time alarm */
#define TARGET_SIGPROF 27 /* profiling time alarm */
#define TARGET_SIGWINCH 28 /* window size changes */
#define TARGET_SIGINFO 29 /* information request */
#define TARGET_SIGUSR1 30 /* user defined signal 1 */
#define TARGET_SIGUSR2 31 /* user defined signal 2 */
#define TARGET_SIGTHR 32 /* reserved by thread library */
#define TARGET_SIGLWP SIGTHR /* compatibility */
#define TARGET_SIGLIBRT 33 /* reserved by the real-time library */
#define TARGET_SIGRTMIN 65
#define TARGET_SIGRTMAX 126
/*
* Language spec says we must list exactly one parameter, even though we
* actually supply three. Ugh!
*/
#define TARGET_SIG_DFL ((abi_long)0) /* default signal handling */
#define TARGET_SIG_IGN ((abi_long)1) /* ignore signal */
#define TARGET_SIG_ERR ((abi_long)-1) /* error return from signal */
#define TARGET_SA_ONSTACK 0x0001 /* take signal on signal stack */
#define TARGET_SA_RESTART 0x0002 /* restart system on signal return */
#define TARGET_SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */
#define TARGET_SA_NODEFER 0x0010 /* don't mask the signal we're delivering */
#define TARGET_SA_NOCLDWAIT 0x0020 /* don't create zombies (assign to pid 1) */
#define TARGET_SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */
#define TARGET_SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */
#define TARGET_SA_SIGINFO 0x0040 /* generate siginfo_t */
/*
* Flags for sigprocmask:
*/
#define TARGET_SIG_BLOCK 1 /* block specified signal set */
#define TARGET_SIG_UNBLOCK 2 /* unblock specified signal set */
#define TARGET_SIG_SETMASK 3 /* set specified signal set */
#define TARGET_BADSIG SIG_ERR
/*
* sigaltstack control
*/
#define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */
#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate stack*/
#endif /* !_TARGET_OS_SIGNAL_H_ */

View File

@ -0,0 +1,181 @@
/*
* FreeBSD setup_initial_stack() implementation.
*
* Copyright (c) 2013-14 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_OS_STACK_H_
#define _TARGET_OS_STACK_H_
#include <sys/param.h>
#include "target_arch_sigtramp.h"
#include "qemu/guest-random.h"
/*
* The inital FreeBSD stack is as follows:
* (see kern/kern_exec.c exec_copyout_strings() )
*
* Hi Address -> char **ps_argvstr (struct ps_strings for ps, w, etc.)
* unsigned ps_nargvstr
* char **ps_envstr
* PS_STRINGS -> unsigned ps_nenvstr
*
* machine dependent sigcode (sv_sigcode of size
* sv_szsigcode)
*
* execpath (absolute image path for rtld)
*
* SSP Canary (sizeof(long) * 8)
*
* page sizes array (usually sizeof(u_long) )
*
* "destp" -> argv, env strings (up to 262144 bytes)
*/
static inline int setup_initial_stack(struct bsd_binprm *bprm,
abi_ulong *ret_addr, abi_ulong *stringp)
{
int i;
abi_ulong stack_hi_addr;
size_t execpath_len, stringspace;
abi_ulong destp, argvp, envp, p;
struct target_ps_strings ps_strs;
char canary[sizeof(abi_long) * 8];
stack_hi_addr = p = target_stkbas + target_stksiz;
/* Save some space for ps_strings. */
p -= sizeof(struct target_ps_strings);
/* Add machine depedent sigcode. */
p -= TARGET_SZSIGCODE;
if (setup_sigtramp(p, (unsigned)offsetof(struct target_sigframe, sf_uc),
TARGET_FREEBSD_NR_sigreturn)) {
errno = EFAULT;
return -1;
}
if (bprm->fullpath) {
execpath_len = strlen(bprm->fullpath) + 1;
p -= roundup(execpath_len, sizeof(abi_ulong));
if (memcpy_to_target(p, bprm->fullpath, execpath_len)) {
errno = EFAULT;
return -1;
}
}
/* Add canary for SSP. */
qemu_guest_getrandom_nofail(canary, sizeof(canary));
p -= roundup(sizeof(canary), sizeof(abi_ulong));
if (memcpy_to_target(p, canary, sizeof(canary))) {
errno = EFAULT;
return -1;
}
/* Add page sizes array. */
p -= sizeof(abi_ulong);
if (put_user_ual(TARGET_PAGE_SIZE, p)) {
errno = EFAULT;
return -1;
}
/*
* Deviate from FreeBSD stack layout: force stack to new page here
* so that signal trampoline is not sharing the page with user stack
* frames. This is actively harmful in qemu as it marks pages with
* code it translated as read-only, which is somewhat problematic
* for user trying to use the stack as intended.
*/
p = rounddown(p, TARGET_PAGE_SIZE);
/* Calculate the string space needed */
stringspace = 0;
for (i = 0; i < bprm->argc; ++i) {
stringspace += strlen(bprm->argv[i]) + 1;
}
for (i = 0; i < bprm->envc; ++i) {
stringspace += strlen(bprm->envp[i]) + 1;
}
if (stringspace > TARGET_ARG_MAX) {
errno = ENOMEM;
return -1;
}
/* Make room for the argv and envp strings */
destp = rounddown(p - stringspace, sizeof(abi_ulong));
p = argvp = destp - (bprm->argc + bprm->envc + 2) * sizeof(abi_ulong);
/* Remember the strings pointer */
if (stringp) {
*stringp = destp;
}
/*
* Add argv strings. Note that the argv[] vectors are added by
* loader_build_argptr()
*/
/* XXX need to make room for auxargs */
ps_strs.ps_argvstr = tswapl(argvp);
ps_strs.ps_nargvstr = tswap32(bprm->argc);
for (i = 0; i < bprm->argc; ++i) {
size_t len = strlen(bprm->argv[i]) + 1;
if (memcpy_to_target(destp, bprm->argv[i], len)) {
errno = EFAULT;
return -1;
}
if (put_user_ual(destp, argvp)) {
errno = EFAULT;
return -1;
}
argvp += sizeof(abi_ulong);
destp += len;
}
if (put_user_ual(0, argvp)) {
errno = EFAULT;
return -1;
}
/*
* Add env strings. Note that the envp[] vectors are added by
* loader_build_argptr().
*/
envp = argvp + sizeof(abi_ulong);
ps_strs.ps_envstr = tswapl(envp);
ps_strs.ps_nenvstr = tswap32(bprm->envc);
for (i = 0; i < bprm->envc; ++i) {
size_t len = strlen(bprm->envp[i]) + 1;
if (memcpy_to_target(destp, bprm->envp[i], len)) {
errno = EFAULT;
return -1;
}
if (put_user_ual(destp, envp)) {
errno = EFAULT;
return -1;
}
envp += sizeof(abi_ulong);
destp += len;
}
if (put_user_ual(0, envp)) {
errno = EFAULT;
return -1;
}
if (memcpy_to_target(stack_hi_addr - sizeof(ps_strs), &ps_strs,
sizeof(ps_strs))) {
errno = EFAULT;
return -1;
}
if (ret_addr) {
*ret_addr = p;
}
return 0;
}
#endif /* !_TARGET_OS_STACK_H_ */

View File

@ -0,0 +1,25 @@
/*
* FreeBSD thread dependent code and definitions
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_OS_THREAD_H_
#define _TARGET_OS_THREAD_H_
#include "target_arch_thread.h"
#endif /* !_TARGET_OS_THREAD_H_ */

View File

@ -0,0 +1,427 @@
/*
* sys/user.h definitions
*
* Copyright (c) 2015 Stacey D. Son (sson at FreeBSD)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_OS_USER_H_
#define _TARGET_OS_USER_H_
/*
* from sys/priority.h
*/
struct target_priority {
uint8_t pri_class; /* Scheduling class. */
uint8_t pri_level; /* Normal priority level. */
uint8_t pri_native; /* Priority before propogation. */
uint8_t pri_user; /* User priority based on p_cpu and p_nice. */
};
/*
* sys/caprights.h
*/
#define TARGET_CAP_RIGHTS_VERSION 0
typedef struct target_cap_rights {
uint64_t cr_rights[TARGET_CAP_RIGHTS_VERSION + 2];
} target_cap_rights_t;
/*
* From sys/_socketaddr_storage.h
*
*/
#define TARGET_SS_MAXSIZE 128U
#define TARGET_SS_ALIGNSIZE (sizeof(__int64_t))
#define TARGET_SS_PAD1SIZE (TARGET_SS_ALIGNSIZE - sizeof(unsigned char) - \
sizeof(uint8_t))
#define TARGET_SS_PAD2SIZE (TARGET_SS_MAXSIZE - sizeof(unsigned char) - \
sizeof(uint8_t) - TARGET_SS_PAD1SIZE - TARGET_SS_ALIGNSIZE)
struct target_sockaddr_storage {
unsigned char ss_len; /* address length */
uint8_t ss_family; /* address family */
char __ss_pad1[TARGET_SS_PAD1SIZE];
__int64_t __ss_align; /* force desired struct alignment */
char __ss_pad2[TARGET_SS_PAD2SIZE];
};
/*
* from sys/user.h
*/
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
#define TARGET_KI_NSPARE_INT 2
#elif defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
#define TARGET_KI_NSPARE_INT 4
#elif defined(__FreeBSD_version) && __FreeBSD_version >= 1000000
#define TARGET_KI_NSPARE_INT 7
#else
#define TARGET_KI_NSPARE_INT 9
#endif /* ! __FreeBSD_version >= 1000000 */
#define TARGET_KI_NSPARE_LONG 12
#define TARGET_KI_NSPARE_PTR 6
#define TARGET_WMESGLEN 8
#define TARGET_LOCKNAMELEN 8
#define TARGET_TDNAMLEN 16
#define TARGET_COMMLEN 19
#define TARGET_KI_EMULNAMELEN 16
#define TARGET_KI_NGROUPS 16
#define TARGET_LOGNAMELEN 17
#define TARGET_LOGINCLASSLEN 17
#define TARGET_KF_TYPE_NONE 0
#define TARGET_KF_TYPE_VNODE 1
#define TARGET_KF_TYPE_SOCKET 2
#define TARGET_KF_TYPE_PIPE 3
#define TARGET_KF_TYPE_FIFO 4
#define TARGET_KF_TYPE_KQUEUE 5
#define TARGET_KF_TYPE_CRYPTO 6
#define TARGET_KF_TYPE_MQUEUE 7
#define TARGET_KF_TYPE_SHM 8
#define TARGET_KF_TYPE_SEM 9
#define TARGET_KF_TYPE_PTS 10
#define TARGET_KF_TYPE_PROCDESC 11
#define TARGET_KF_TYPE_DEV 12
#define TARGET_KF_TYPE_UNKNOWN 255
struct target_kinfo_proc {
int32_t ki_structsize; /* size of this structure */
int32_t ki_layout; /* reserved: layout identifier */
abi_ulong ki_args; /* address of command arguments */
abi_ulong ki_paddr; /* address of proc */
abi_ulong ki_addr; /* kernel virtual addr of u-area */
abi_ulong ki_tracep; /* pointer to trace file */
abi_ulong ki_textvp; /* pointer to executable file */
abi_ulong ki_fd; /* pointer to open file info */
abi_ulong ki_vmspace; /* pointer to kernel vmspace struct */
abi_ulong ki_wchan; /* sleep address */
int32_t ki_pid; /* Process identifier */
int32_t ki_ppid; /* parent process id */
int32_t ki_pgid; /* process group id */
int32_t ki_tpgid; /* tty process group id */
int32_t ki_sid; /* Process session ID */
int32_t ki_tsid; /* Terminal session ID */
int16_t ki_jobc; /* job control counter */
int16_t ki_spare_short1; /* unused (just here for alignment) */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
int32_t ki_tdev__freebsd11; /* controlling tty dev */
#else
int32_t ki_tdev; /* controlling tty dev */
#endif
target_sigset_t ki_siglist; /* Signals arrived but not delivered */
target_sigset_t ki_sigmask; /* Current signal mask */
target_sigset_t ki_sigignore; /* Signals being ignored */
target_sigset_t ki_sigcatch; /* Signals being caught by user */
int32_t ki_uid; /* effective user id */
int32_t ki_ruid; /* Real user id */
int32_t ki_svuid; /* Saved effective user id */
int32_t ki_rgid; /* Real group id */
int32_t ki_svgid; /* Saved effective group id */
int16_t ki_ngroups; /* number of groups */
int16_t ki_spare_short2; /* unused (just here for alignment) */
int32_t ki_groups[TARGET_KI_NGROUPS]; /* groups */
abi_long ki_size; /* virtual size */
abi_long ki_rssize; /* current resident set size in pages */
abi_long ki_swrss; /* resident set size before last swap */
abi_long ki_tsize; /* text size (pages) XXX */
abi_long ki_dsize; /* data size (pages) XXX */
abi_long ki_ssize; /* stack size (pages) */
uint16_t ki_xstat; /* Exit status for wait & stop signal */
uint16_t ki_acflag; /* Accounting flags */
uint32_t ki_pctcpu; /* %cpu for process during ki_swtime */
uint32_t ki_estcpu; /* Time averaged value of ki_cpticks */
uint32_t ki_slptime; /* Time since last blocked */
uint32_t ki_swtime; /* Time swapped in or out */
uint32_t ki_cow; /* number of copy-on-write faults */
uint64_t ki_runtime; /* Real time in microsec */
struct target_freebsd_timeval ki_start; /* starting time */
struct target_freebsd_timeval ki_childtime; /* time used by process children */
abi_long ki_flag; /* P_* flags */
abi_long ki_kiflag; /* KI_* flags (below) */
int32_t ki_traceflag; /* Kernel trace points */
char ki_stat; /* S* process status */
int8_t ki_nice; /* Process "nice" value */
char ki_lock; /* Process lock (prevent swap) count */
char ki_rqindex; /* Run queue index */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
u_char ki_oncpu_old; /* Which cpu we are on (legacy) */
u_char ki_lastcpu_old; /* Last cpu we were on (legacy) */
#else
u_char ki_oncpu; /* Which cpu we are on */
u_char ki_lastcpu; /* Last cpu we were on */
#endif /* ! __FreeBSD_version >= 1100000 */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
char ki_tdname[TARGET_TDNAMLEN + 1]; /* thread name */
#else
char ki_ocomm[TARGET_TDNAMLEN + 1]; /* thread name */
#endif /* ! __FreeBSD_version >= 900000 */
char ki_wmesg[TARGET_WMESGLEN + 1]; /* wchan message */
char ki_login[TARGET_LOGNAMELEN + 1]; /* setlogin name */
char ki_lockname[TARGET_LOCKNAMELEN + 1]; /* lock name */
char ki_comm[TARGET_COMMLEN + 1]; /* command name */
char ki_emul[TARGET_KI_EMULNAMELEN + 1]; /* emulation name */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
char ki_loginclass[TARGET_LOGINCLASSLEN + 1]; /* login class */
#endif /* ! __FreeBSD_version >= 900000 */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
char ki_sparestrings[50]; /* spare string space */
#else
char ki_sparestrings[68]; /* spare string space */
#endif /* ! __FreeBSD_version >= 900000 */
int32_t ki_spareints[TARGET_KI_NSPARE_INT]; /* spare room for growth */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint64_t ki_tdev; /* controlling tty dev */
#endif
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
int32_t ki_oncpu; /* Which cpu we are on */
int32_t ki_lastcpu; /* Last cpu we were on */
int32_t ki_tracer; /* Pid of tracing process */
#endif /* __FreeBSD_version >= 1100000 */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
int32_t ki_flag2; /* P2_* flags */
int32_t ki_fibnum; /* Default FIB number */
#endif /* ! __FreeBSD_version >= 900000 */
uint32_t ki_cr_flags; /* Credential flags */
int32_t ki_jid; /* Process jail ID */
int32_t ki_numthreads; /* XXXKSE number of threads in total */
int32_t ki_tid; /* XXXKSE thread id */
struct target_priority ki_pri; /* process priority */
struct target_freebsd_rusage ki_rusage; /* process rusage statistics */
/* XXX - most fields in ki_rusage_ch are not (yet) filled in */
struct target_freebsd_rusage ki_rusage_ch; /* rusage of children processes */
abi_ulong ki_pcb; /* kernel virtual addr of pcb */
abi_ulong ki_kstack; /* kernel virtual addr of stack */
abi_ulong ki_udata; /* User convenience pointer */
abi_ulong ki_tdaddr; /* address of thread */
abi_ulong ki_spareptrs[TARGET_KI_NSPARE_PTR]; /* spare room for growth */
abi_long ki_sparelongs[TARGET_KI_NSPARE_LONG];/* spare room for growth */
abi_long ki_sflag; /* PS_* flags */
abi_long ki_tdflags; /* XXXKSE kthread flag */
};
struct target_kinfo_file {
int32_t kf_structsize; /* Variable size of record. */
int32_t kf_type; /* Descriptor type. */
int32_t kf_fd; /* Array index. */
int32_t kf_ref_count; /* Reference count. */
int32_t kf_flags; /* Flags. */
int32_t kf_pad0; /* Round to 64 bit alignment. */
int64_t kf_offset; /* Seek location. */
#if defined(__FreeBSD_version) && __FreeBSD_version < 1200031
int32_t kf_vnode_type; /* Vnode type. */
int32_t kf_sock_domain; /* Socket domain. */
int32_t kf_sock_type; /* Socket type. */
int32_t kf_sock_protocol; /* Socket protocol. */
struct target_sockaddr_storage kf_sa_local; /* Socket address. */
struct target_sockaddr_storage kf_sa_peer; /* Peer address. */
#endif
#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
union {
struct {
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint32_t kf_spareint;
/* Socket domain. */
int kf_sock_domain0;
/* Socket type. */
int kf_sock_type0;
/* Socket protocol. */
int kf_sock_protocol0;
/* Socket address. */
struct sockaddr_storage kf_sa_local;
/* Peer address. */
struct sockaddr_storage kf_sa_peer;
#endif
/* Address of so_pcb. */
uint64_t kf_sock_pcb;
/* Address of inp_ppcb. */
uint64_t kf_sock_inpcb;
/* Address of unp_conn. */
uint64_t kf_sock_unpconn;
/* Send buffer state. */
uint16_t kf_sock_snd_sb_state;
/* Receive buffer state. */
uint16_t kf_sock_rcv_sb_state;
/* Round to 64 bit alignment. */
uint32_t kf_sock_pad0;
} kf_sock;
struct {
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
/* Vnode type. */
int kf_file_type;
/* Space for future use */
int kf_spareint[3];
uint64_t kf_spareint64[30];
/* Vnode filesystem id. */
uint64_t kf_file_fsid;
/* File device. */
uint64_t kf_file_rdev;
/* Global file id. */
uint64_t kf_file_fileid;
/* File size. */
uint64_t kf_file_size;
/* Vnode filesystem id, FreeBSD 11 compat. */
uint32_t kf_file_fsid_freebsd11;
/* File device, FreeBSD 11 compat. */
uint32_t kf_file_rdev_freebsd11;
#else
/* Global file id. */
uint64_t kf_file_fileid;
/* File size. */
uint64_t kf_file_size;
/* Vnode filesystem id. */
uint32_t kf_file_fsid;
/* File device. */
uint32_t kf_file_rdev;
#endif
/* File mode. */
uint16_t kf_file_mode;
/* Round to 64 bit alignment. */
uint16_t kf_file_pad0;
uint32_t kf_file_pad1;
} kf_file;
struct {
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint32_t kf_spareint[4];
uint64_t kf_spareint64[32];
#endif
uint32_t kf_sem_value;
uint16_t kf_sem_mode;
} kf_sem;
struct {
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint32_t kf_spareint[4];
uint64_t kf_spareint64[32];
#endif
uint64_t kf_pipe_addr;
uint64_t kf_pipe_peer;
uint32_t kf_pipe_buffer_cnt;
/* Round to 64 bit alignment. */
uint32_t kf_pipe_pad0[3];
} kf_pipe;
struct {
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint32_t kf_spareint[4];
uint64_t kf_spareint64[32];
uint32_t kf_pts_dev_freebsd11;
uint32_t kf_pts_pad0;
uint64_t kf_pts_dev;
/* Round to 64 bit alignment. */
uint32_t kf_pts_pad1[4];
#else
uint32_t kf_pts_dev;
/* Round to 64 bit alignment. */
uint32_t kf_pts_pad0[7];
#endif
} kf_pts;
struct {
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint32_t kf_spareint[4];
uint64_t kf_spareint64[32];
#endif
int32_t kf_pid;
} kf_proc;
} kf_un;
uint16_t kf_status; /* Status flags. */
uint16_t kf_pad1; /* Round to 32 bit alignment. */
int32_t _kf_ispare0; /* Space for more stuff. */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1000000
target_cap_rights_t kf_cap_rights; /* Capability rights. */
uint64_t _kf_cap_spare; /* Space for future cap_rights_t. */
#else /* ! __FreeBSD_version >= 1000000 */
uint64_t kf_cap_rights;
int _kf_ispare[4];
#endif /* ! __FreeBSD_version >= 1000000 */
#else /* ! __FreeBSD_version >= 900000 */
int _kf_ispare[16];
#endif /* ! __FreeBSD_version >= 900000 */
/* Truncated before copyout in sysctl */
char kf_path[PATH_MAX]; /* Path to file, if any. */
};
struct target_kinfo_vmentry {
int32_t kve_structsize; /* Variable size of record. */
int32_t kve_type; /* Type of map entry. */
uint64_t kve_start; /* Starting address. */
uint64_t kve_end; /* Finishing address. */
uint64_t kve_offset; /* Mapping offset in object */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
uint64_t kve_vn_fileid; /* inode number if vnode */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint32_t kve_vn_fsid_freebsd11; /* dev_t of vnode location */
#else
uint32_t kve_vn_fsid; /* dev_t of vnode location */
#endif
#else /* ! __FreeBSD_version >= 900000 */
uint64_t kve_fileid; /* inode number if vnode */
uint32_t kve_fsid; /* dev_t of vnode location */
#endif /* ! __FreeBSD_version >= 900000 */
int32_t kve_flags; /* Flags on map entry. */
int32_t kve_resident; /* Number of resident pages. */
int32_t kve_private_resident; /* Number of private pages. */
int32_t kve_protection; /* Protection bitmask. */
int32_t kve_ref_count; /* VM obj ref count. */
int32_t kve_shadow_count; /* VM obj shadow count. */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
int32_t kve_vn_type; /* Vnode type. */
uint64_t kve_vn_size; /* File size. */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint32_t kve_vn_rdev_freebsd11; /* Device id if device. */
#else
uint32_t kve_vn_rdev; /* Device id if device. */
#endif
uint16_t kve_vn_mode; /* File mode. */
uint16_t kve_status; /* Status flags. */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
#if (__FreeBSD_version >= 1300501 && __FreeBSD_version < 1400000) || \
__FreeBSD_version >= 1400009
union {
uint64_t _kve_vn_fsid; /* dev_t of vnode location */
uint64_t _kve_obj; /* handle of anon obj */
} kve_type_spec;
#define kve_vn_fsid kve_type_spec._kve_vn_fsid
#define kve_obj kve_type_spec._kve_obj
#else
uint64_t kve_vn_fsid; /* dev_t of vnode location */
#endif
uint64_t kve_vn_rdev; /* Device id if device. */
int _kve_ispare[8]; /* Space for more stuff. */
#else
int32_t _kve_ispare[12]; /* Space for more stuff. */
#endif
#else /* ! __FreeBSD_version >= 900000 */
int _kve_pad0;
int32_t _kve_ispare[16]; /* Space for more stuff. */
#endif /* ! __FreeBSD_version >= 900000 */
/* Truncated before copyout in sysctl */
char kve_path[PATH_MAX]; /* Path to VM obj, if any. */
};
#endif /* ! _TARGET_OS_USER_H_ */

View File

@ -0,0 +1,38 @@
/*
* FreeBSD VM parameters definitions
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_OS_VMPARAM_H_
#define _TARGET_OS_VMPARAM_H_
#include "target_arch_vmparam.h"
/* Compare to sys/exec.h */
struct target_ps_strings {
abi_ulong ps_argvstr;
uint32_t ps_nargvstr;
abi_ulong ps_envstr;
uint32_t ps_nenvstr;
};
extern abi_ulong target_stkbas;
extern abi_ulong target_stksiz;
#define TARGET_PS_STRINGS ((target_stkbas + target_stksiz) - \
sizeof(struct target_ps_strings))
#endif /* !TARGET_OS_VMPARAM_H_ */

View File

@ -1,6 +1,7 @@
/* /*
* sparc dependent system call definitions * Intel x86 specific prototypes for bsd-user
* *
* Copyright (c) 2013 Stacey D. Son
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -15,22 +16,16 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef TARGET_SYSCALL_H
#define TARGET_SYSCALL_H
struct target_pt_regs { #ifndef _TARGET_ARCH_H_
abi_ulong psr; #define _TARGET_ARCH_H_
abi_ulong pc;
abi_ulong npc;
abi_ulong y;
abi_ulong u_regs[16];
};
#define UNAME_MACHINE "sun4" /* target_arch_cpu.c */
#define TARGET_HW_MACHINE "sparc" void bsd_i386_write_dt(void *ptr, unsigned long addr, unsigned long limit,
#define TARGET_HW_MACHINE_ARCH "sparc" int flags);
void bsd_i386_set_idt(int n, unsigned int dpl);
void bsd_i386_set_idt_base(uint64_t base);
#define TARGET_SPARC_UTRAP_INSTALL 1 #define target_cpu_set_tls(env, newtls)
#define TARGET_SPARC_SIGTRAMP_INSTALL 2
#endif /* TARGET_SYSCALL_H */ #endif /* ! _TARGET_ARCH_H_ */

View File

@ -0,0 +1,76 @@
/*
* i386 cpu related code
*
* Copyright (c) 2013 Stacey Son <sson@FreeBSD.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/types.h>
#include "qemu/osdep.h"
#include "cpu.h"
#include "qemu.h"
#include "qemu/timer.h"
#include "target_arch.h"
static uint64_t *idt_table;
uint64_t cpu_get_tsc(CPUX86State *env)
{
return cpu_get_host_ticks();
}
int cpu_get_pic_interrupt(CPUX86State *env)
{
return -1;
}
void bsd_i386_write_dt(void *ptr, unsigned long addr, unsigned long limit,
int flags)
{
unsigned int e1, e2;
uint32_t *p;
e1 = (addr << 16) | (limit & 0xffff);
e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
e2 |= flags;
p = ptr;
p[0] = tswap32(e1);
p[1] = tswap32(e2);
}
static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
uint32_t addr, unsigned int sel)
{
uint32_t *p, e1, e2;
e1 = (addr & 0xffff) | (sel << 16);
e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
p = ptr;
p[0] = tswap32(e1);
p[1] = tswap32(e2);
}
/* only dpl matters as we do only user space emulation */
void bsd_i386_set_idt(int n, unsigned int dpl)
{
set_gate(idt_table + n, 0, dpl, 0, 0);
}
void bsd_i386_set_idt_base(uint64_t base)
{
idt_table = g2h_untagged(base);
}

View File

@ -0,0 +1,209 @@
/*
* i386 cpu init and loop
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_ARCH_CPU_H_
#define _TARGET_ARCH_CPU_H_
#include "target_arch.h"
#define TARGET_DEFAULT_CPU_MODEL "qemu32"
#define TARGET_CPU_RESET(cpu)
static inline void target_cpu_init(CPUX86State *env,
struct target_pt_regs *regs)
{
uint64_t *gdt_table;
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
env->hflags |= HF_PE_MASK | HF_CPL_MASK;
if (env->features[FEAT_1_EDX] & CPUID_SSE) {
env->cr[4] |= CR4_OSFXSR_MASK;
env->hflags |= HF_OSFXSR_MASK;
}
/* flags setup : we activate the IRQs by default as in user mode */
env->eflags |= IF_MASK;
/* register setup */
env->regs[R_EAX] = regs->eax;
env->regs[R_EBX] = regs->ebx;
env->regs[R_ECX] = regs->ecx;
env->regs[R_EDX] = regs->edx;
env->regs[R_ESI] = regs->esi;
env->regs[R_EDI] = regs->edi;
env->regs[R_EBP] = regs->ebp;
env->regs[R_ESP] = regs->esp;
env->eip = regs->eip;
/* interrupt setup */
env->idt.limit = 255;
env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
bsd_i386_set_idt_base(env->idt.base);
bsd_i386_set_idt(0, 0);
bsd_i386_set_idt(1, 0);
bsd_i386_set_idt(2, 0);
bsd_i386_set_idt(3, 3);
bsd_i386_set_idt(4, 3);
bsd_i386_set_idt(5, 0);
bsd_i386_set_idt(6, 0);
bsd_i386_set_idt(7, 0);
bsd_i386_set_idt(8, 0);
bsd_i386_set_idt(9, 0);
bsd_i386_set_idt(10, 0);
bsd_i386_set_idt(11, 0);
bsd_i386_set_idt(12, 0);
bsd_i386_set_idt(13, 0);
bsd_i386_set_idt(14, 0);
bsd_i386_set_idt(15, 0);
bsd_i386_set_idt(16, 0);
bsd_i386_set_idt(17, 0);
bsd_i386_set_idt(18, 0);
bsd_i386_set_idt(19, 0);
bsd_i386_set_idt(0x80, 3);
/* segment setup */
env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
gdt_table = g2h_untagged(env->gdt.base);
bsd_i386_write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
(3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
bsd_i386_write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
(3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
cpu_x86_load_seg(env, R_CS, __USER_CS);
cpu_x86_load_seg(env, R_SS, __USER_DS);
cpu_x86_load_seg(env, R_DS, __USER_DS);
cpu_x86_load_seg(env, R_ES, __USER_DS);
cpu_x86_load_seg(env, R_FS, __USER_DS);
cpu_x86_load_seg(env, R_GS, __USER_DS);
/* This hack makes Wine work... */
env->segs[R_FS].selector = 0;
}
static inline void target_cpu_loop(CPUX86State *env)
{
CPUState *cs = env_cpu(env);
int trapnr;
abi_ulong pc;
/* target_siginfo_t info; */
for (;;) {
cpu_exec_start(cs);
trapnr = cpu_exec(cs);
cpu_exec_end(cs);
process_queued_cpu_work(cs);
switch (trapnr) {
case 0x80:
/* syscall from int $0x80 */
if (bsd_type == target_freebsd) {
abi_ulong params = (abi_ulong) env->regs[R_ESP] +
sizeof(int32_t);
int32_t syscall_nr = env->regs[R_EAX];
int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
get_user_s32(syscall_nr, params);
params += sizeof(int32_t);
} else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
get_user_s32(syscall_nr, params);
params += sizeof(int64_t);
}
get_user_s32(arg1, params);
params += sizeof(int32_t);
get_user_s32(arg2, params);
params += sizeof(int32_t);
get_user_s32(arg3, params);
params += sizeof(int32_t);
get_user_s32(arg4, params);
params += sizeof(int32_t);
get_user_s32(arg5, params);
params += sizeof(int32_t);
get_user_s32(arg6, params);
params += sizeof(int32_t);
get_user_s32(arg7, params);
params += sizeof(int32_t);
get_user_s32(arg8, params);
env->regs[R_EAX] = do_freebsd_syscall(env,
syscall_nr,
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8);
} else { /* if (bsd_type == target_openbsd) */
env->regs[R_EAX] = do_openbsd_syscall(env,
env->regs[R_EAX],
env->regs[R_EBX],
env->regs[R_ECX],
env->regs[R_EDX],
env->regs[R_ESI],
env->regs[R_EDI],
env->regs[R_EBP]);
}
if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
env->regs[R_EAX] = -env->regs[R_EAX];
env->eflags |= CC_C;
} else {
env->eflags &= ~CC_C;
}
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
break;
default:
pc = env->segs[R_CS].base + env->eip;
fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - "
"aborting\n", (long)pc, trapnr);
abort();
}
process_pending_signals(env);
}
}
static inline void target_cpu_clone_regs(CPUX86State *env, target_ulong newsp)
{
if (newsp) {
env->regs[R_ESP] = newsp;
}
env->regs[R_EAX] = 0;
}
static inline void target_cpu_reset(CPUArchState *cpu)
{
cpu_reset(env_cpu(cpu));
}
#endif /* ! _TARGET_ARCH_CPU_H_ */

View File

@ -0,0 +1,35 @@
/*
* i386 ELF definitions
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_ARCH_ELF_H_
#define _TARGET_ARCH_ELF_H_
#define ELF_START_MMAP 0x80000000
#define ELF_ET_DYN_LOAD_ADDR 0x01001000
#define elf_check_arch(x) (((x) == EM_386) || ((x) == EM_486))
#define ELF_HWCAP 0 /* FreeBSD doesn't do AT_HWCAP{,2} on x86 */
#define ELF_CLASS ELFCLASS32
#define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_386
#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
#endif /* _TARGET_ARCH_ELF_H_ */

View File

@ -0,0 +1,82 @@
/*
* FreeBSD i386 register structures
*
* Copyright (c) 2015 Stacey Son
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_ARCH_REG_H_
#define _TARGET_ARCH_REG_H_
/* See sys/i386/include/reg.h */
typedef struct target_reg {
uint32_t r_fs;
uint32_t r_es;
uint32_t r_ds;
uint32_t r_edi;
uint32_t r_esi;
uint32_t r_ebp;
uint32_t r_isp;
uint32_t r_ebx;
uint32_t r_edx;
uint32_t r_ecx;
uint32_t r_eax;
uint32_t r_trapno;
uint32_t r_err;
uint32_t r_eip;
uint32_t r_cs;
uint32_t r_eflags;
uint32_t r_esp;
uint32_t r_ss;
uint32_t r_gs;
} target_reg_t;
typedef struct target_fpreg {
uint32_t fpr_env[7];
uint8_t fpr_acc[8][10];
uint32_t fpr_ex_sw;
uint8_t fpr_pad[64];
} target_fpreg_t;
static inline void target_copy_regs(target_reg_t *regs, const CPUX86State *env)
{
regs->r_fs = env->segs[R_FS].selector & 0xffff;
regs->r_es = env->segs[R_ES].selector & 0xffff;
regs->r_ds = env->segs[R_DS].selector & 0xffff;
regs->r_edi = env->regs[R_EDI];
regs->r_esi = env->regs[R_ESI];
regs->r_ebp = env->regs[R_EBP];
/* regs->r_isp = env->regs[R_ISP]; XXX */
regs->r_ebx = env->regs[R_EBX];
regs->r_edx = env->regs[R_EDX];
regs->r_ecx = env->regs[R_ECX];
regs->r_eax = env->regs[R_EAX];
/* regs->r_trapno = env->regs[R_TRAPNO]; XXX */
regs->r_err = env->error_code; /* XXX ? */
regs->r_eip = env->eip;
regs->r_cs = env->segs[R_CS].selector & 0xffff;
regs->r_eflags = env->eflags;
regs->r_esp = env->regs[R_ESP];
regs->r_ss = env->segs[R_SS].selector & 0xffff;
regs->r_gs = env->segs[R_GS].selector & 0xffff;
}
#endif /* !_TARGET_ARCH_REG_H_ */

View File

@ -0,0 +1,94 @@
/*
* i386 dependent signal definitions
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TARGET_ARCH_SIGNAL_H
#define TARGET_ARCH_SIGNAL_H
#include "cpu.h"
/* Size of the signal trampolin code placed on the stack. */
#define TARGET_SZSIGCODE 0
/* compare to x86/include/_limits.h */
#define TARGET_MINSIGSTKSZ (512 * 4) /* min sig stack size */
#define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */
#define TARGET_MC_GET_CLEAR_RET 0x0001
struct target_sigcontext {
/* to be added */
};
typedef struct target_mcontext {
} target_mcontext_t;
typedef struct target_ucontext {
target_sigset_t uc_sigmask;
target_mcontext_t uc_mcontext;
abi_ulong uc_link;
target_stack_t uc_stack;
int32_t uc_flags;
int32_t __spare__[4];
} target_ucontext_t;
struct target_sigframe {
abi_ulong sf_signum;
abi_ulong sf_siginfo; /* code or pointer to sf_si */
abi_ulong sf_ucontext; /* points to sf_uc */
abi_ulong sf_addr; /* undocumented 4th arg */
target_ucontext_t sf_uc; /* = *sf_uncontext */
target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/
uint32_t __spare__[2];
};
/*
* Compare to i386/i386/machdep.c sendsig()
* Assumes that target stack frame memory is locked.
*/
static inline abi_long set_sigtramp_args(CPUX86State *regs,
int sig, struct target_sigframe *frame, abi_ulong frame_addr,
struct target_sigaction *ka)
{
/* XXX return -TARGET_EOPNOTSUPP; */
return 0;
}
/* Compare to i386/i386/machdep.c get_mcontext() */
static inline abi_long get_mcontext(CPUX86State *regs,
target_mcontext_t *mcp, int flags)
{
/* XXX */
return -TARGET_EOPNOTSUPP;
}
/* Compare to i386/i386/machdep.c set_mcontext() */
static inline abi_long set_mcontext(CPUX86State *regs,
target_mcontext_t *mcp, int srflag)
{
/* XXX */
return -TARGET_EOPNOTSUPP;
}
static inline abi_long get_ucontext_sigreturn(CPUX86State *regs,
abi_ulong target_sf, abi_ulong *target_uc)
{
/* XXX */
*target_uc = 0;
return -TARGET_EOPNOTSUPP;
}
#endif /* TARGET_ARCH_SIGNAL_H */

View File

@ -0,0 +1,29 @@
/*
* Intel i386 sigcode for bsd-user
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_ARCH_SIGTRAMP_H_
#define _TARGET_ARCH_SIGTRAMP_H_
static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
unsigned sys_sigreturn)
{
return 0;
}
#endif /* _TARGET_ARCH_SIGTRAMP_H_ */

View File

@ -0,0 +1,47 @@
/*
* i386 thread support
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_ARCH_THREAD_H_
#define _TARGET_ARCH_THREAD_H_
/* Compare to vm_machdep.c cpu_set_upcall_kse() */
static inline void target_thread_set_upcall(CPUX86State *regs, abi_ulong entry,
abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size)
{
/* XXX */
}
static inline void target_thread_init(struct target_pt_regs *regs,
struct image_info *infop)
{
regs->esp = infop->start_stack;
regs->eip = infop->entry;
/*
* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program starts %edx
* contains a pointer to a function which might be registered using
* `atexit'. This provides a mean for the dynamic linker to call DT_FINI
* functions for shared libraries that have been loaded before the code
* runs.
*
* A value of 0 tells we have no such handler.
*/
regs->edx = 0;
}
#endif /* !_TARGET_ARCH_THREAD_H_ */

View File

@ -0,0 +1,46 @@
/*
* i386 VM parameters definitions
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_ARCH_VMPARAM_H_
#define _TARGET_ARCH_VMPARAM_H_
#include "cpu.h"
/* compare to i386/include/vmparam.h */
#define TARGET_MAXTSIZ (128 * MiB) /* max text size */
#define TARGET_DFLDSIZ (128 * MiB) /* initial data size limit */
#define TARGET_MAXDSIZ (512 * MiB) /* max data size */
#define TARGET_DFLSSIZ (8 * MiB) /* initial stack size limit */
#define TARGET_MAXSSIZ (64 * MiB) /* max stack size */
#define TARGET_SGROWSIZ (128 * KiB) /* amount to grow stack */
#define TARGET_RESERVED_VA 0xf7000000
#define TARGET_USRSTACK (0xbfc00000)
static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
{
return state->regs[R_ESP];
}
static inline void set_second_rval(CPUX86State *state, abi_ulong retval2)
{
state->regs[R_EDX] = retval2;
}
#endif /* !_TARGET_ARCH_VMPARAM_H_ */

View File

@ -1,7 +1,8 @@
/* /*
* qemu user main * qemu bsd user main
* *
* Copyright (c) 2003-2008 Fabrice Bellard * Copyright (c) 2003-2008 Fabrice Bellard
* Copyright (c) 2013-14 Stacey Son
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -17,6 +18,11 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/sysctl.h>
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu/units.h" #include "qemu/units.h"
@ -39,495 +45,107 @@
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "exec/log.h" #include "exec/log.h"
#include "trace/control.h" #include "trace/control.h"
#include "crypto/init.h"
#include "qemu/guest-random.h"
#include "host-os.h"
#include "target_arch_cpu.h"
int singlestep; int singlestep;
unsigned long mmap_min_addr;
uintptr_t guest_base; uintptr_t guest_base;
bool have_guest_base; bool have_guest_base;
/*
* When running 32-on-64 we should make sure we can fit all of the possible
* guest address space into a contiguous chunk of virtual host memory.
*
* This way we will never overlap with our own libraries or binaries or stack
* or anything else that QEMU maps.
*
* Many cpus reserve the high bit (or more than one for some 64-bit cpus)
* of the address for the kernel. Some cpus rely on this and user space
* uses the high bit(s) for pointer tagging and the like. For them, we
* must preserve the expected address space.
*/
#ifndef MAX_RESERVED_VA
# if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
# if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \
(TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
/*
* There are a number of places where we assign reserved_va to a variable
* of type abi_ulong and expect it to fit. Avoid the last page.
*/
# define MAX_RESERVED_VA (0xfffffffful & TARGET_PAGE_MASK)
# else
# define MAX_RESERVED_VA (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
# endif
# else
# define MAX_RESERVED_VA 0
# endif
#endif
/*
* That said, reserving *too* much vm space via mmap can run into problems
* with rlimits, oom due to page table creation, etc. We will still try it,
* if directed by the command-line option, but not by default.
*/
#if HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32
unsigned long reserved_va = MAX_RESERVED_VA;
#else
unsigned long reserved_va; unsigned long reserved_va;
#endif
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
const char *qemu_uname_release; const char *qemu_uname_release;
enum BSDType bsd_type; enum BSDType bsd_type;
char qemu_proc_pathname[PATH_MAX]; /* full path to exeutable */
/* unsigned long target_maxtsiz = TARGET_MAXTSIZ; /* max text size */
* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so unsigned long target_dfldsiz = TARGET_DFLDSIZ; /* initial data size limit */
* we allocate a bigger stack. Need a better solution, for example unsigned long target_maxdsiz = TARGET_MAXDSIZ; /* max data size */
* by remapping the process stack directly at the right place unsigned long target_dflssiz = TARGET_DFLSSIZ; /* initial data size limit */
*/ unsigned long target_maxssiz = TARGET_MAXSSIZ; /* max stack size */
unsigned long x86_stack_size = 512 * 1024; unsigned long target_sgrowsiz = TARGET_SGROWSIZ; /* amount to grow stack */
void gemu_log(const char *fmt, ...) /* Helper routines for implementing atomic operations. */
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
#if defined(TARGET_I386)
int cpu_get_pic_interrupt(CPUX86State *env)
{
return -1;
}
#endif
void fork_start(void) void fork_start(void)
{ {
start_exclusive();
cpu_list_lock();
mmap_fork_start();
} }
void fork_end(int child) void fork_end(int child)
{ {
if (child) { if (child) {
CPUState *cpu, *next_cpu;
/*
* Child processes created by fork() only have a single thread. Discard
* information about the parent threads.
*/
CPU_FOREACH_SAFE(cpu, next_cpu) {
if (cpu != thread_cpu) {
QTAILQ_REMOVE_RCU(&cpus, cpu, node);
}
}
mmap_fork_end(child);
/*
* qemu_init_cpu_list() takes care of reinitializing the exclusive
* state, so we don't need to end_exclusive() here.
*/
qemu_init_cpu_list();
gdbserver_fork(thread_cpu); gdbserver_fork(thread_cpu);
}
}
#ifdef TARGET_I386
/***********************************************************/
/* CPUX86 core interface */
uint64_t cpu_get_tsc(CPUX86State *env)
{
return cpu_get_host_ticks();
}
static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
int flags)
{
unsigned int e1, e2;
uint32_t *p;
e1 = (addr << 16) | (limit & 0xffff);
e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
e2 |= flags;
p = ptr;
p[0] = tswap32(e1);
p[1] = tswap32(e2);
}
static uint64_t *idt_table;
#ifdef TARGET_X86_64
static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
uint64_t addr, unsigned int sel)
{
uint32_t *p, e1, e2;
e1 = (addr & 0xffff) | (sel << 16);
e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
p = ptr;
p[0] = tswap32(e1);
p[1] = tswap32(e2);
p[2] = tswap32(addr >> 32);
p[3] = 0;
}
/* only dpl matters as we do only user space emulation */
static void set_idt(int n, unsigned int dpl)
{
set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
}
#else
static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
uint32_t addr, unsigned int sel)
{
uint32_t *p, e1, e2;
e1 = (addr & 0xffff) | (sel << 16);
e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
p = ptr;
p[0] = tswap32(e1);
p[1] = tswap32(e2);
}
/* only dpl matters as we do only user space emulation */
static void set_idt(int n, unsigned int dpl)
{
set_gate(idt_table + n, 0, dpl, 0, 0);
}
#endif
void cpu_loop(CPUX86State *env)
{
CPUState *cs = env_cpu(env);
int trapnr;
abi_ulong pc;
/* target_siginfo_t info; */
for (;;) {
cpu_exec_start(cs);
trapnr = cpu_exec(cs);
cpu_exec_end(cs);
process_queued_cpu_work(cs);
switch (trapnr) {
case 0x80:
/* syscall from int $0x80 */
if (bsd_type == target_freebsd) {
abi_ulong params = (abi_ulong) env->regs[R_ESP] +
sizeof(int32_t);
int32_t syscall_nr = env->regs[R_EAX];
int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
get_user_s32(syscall_nr, params);
params += sizeof(int32_t);
} else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
get_user_s32(syscall_nr, params);
params += sizeof(int64_t);
}
get_user_s32(arg1, params);
params += sizeof(int32_t);
get_user_s32(arg2, params);
params += sizeof(int32_t);
get_user_s32(arg3, params);
params += sizeof(int32_t);
get_user_s32(arg4, params);
params += sizeof(int32_t);
get_user_s32(arg5, params);
params += sizeof(int32_t);
get_user_s32(arg6, params);
params += sizeof(int32_t);
get_user_s32(arg7, params);
params += sizeof(int32_t);
get_user_s32(arg8, params);
env->regs[R_EAX] = do_freebsd_syscall(env,
syscall_nr,
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8);
} else { /* if (bsd_type == target_openbsd) */
env->regs[R_EAX] = do_openbsd_syscall(env,
env->regs[R_EAX],
env->regs[R_EBX],
env->regs[R_ECX],
env->regs[R_EDX],
env->regs[R_ESI],
env->regs[R_EDI],
env->regs[R_EBP]);
}
if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
env->regs[R_EAX] = -env->regs[R_EAX];
env->eflags |= CC_C;
} else { } else {
env->eflags &= ~CC_C; mmap_fork_end(child);
} cpu_list_unlock();
break; end_exclusive();
#ifndef TARGET_ABI32
case EXCP_SYSCALL:
/* syscall from syscall instruction */
if (bsd_type == target_freebsd) {
env->regs[R_EAX] = do_freebsd_syscall(env,
env->regs[R_EAX],
env->regs[R_EDI],
env->regs[R_ESI],
env->regs[R_EDX],
env->regs[R_ECX],
env->regs[8],
env->regs[9], 0, 0);
} else { /* if (bsd_type == target_openbsd) */
env->regs[R_EAX] = do_openbsd_syscall(env,
env->regs[R_EAX],
env->regs[R_EDI],
env->regs[R_ESI],
env->regs[R_EDX],
env->regs[10],
env->regs[8],
env->regs[9]);
}
env->eip = env->exception_next_eip;
if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
env->regs[R_EAX] = -env->regs[R_EAX];
env->eflags |= CC_C;
} else {
env->eflags &= ~CC_C;
}
break;
#endif
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
default:
pc = env->segs[R_CS].base + env->eip;
fprintf(stderr,
"qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
(long)pc, trapnr);
abort();
}
process_pending_signals(env);
} }
} }
#endif
#ifdef TARGET_SPARC void cpu_loop(CPUArchState *env)
#define SPARC64_STACK_BIAS 2047
/* #define DEBUG_WIN */
/*
* WARNING: dealing with register windows _is_ complicated. More info
* can be found at http://www.sics.se/~psm/sparcstack.html
*/
static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
{ {
index = (index + cwp * 16) % (16 * env->nwindows); target_cpu_loop(env);
/*
* wrap handling : if cwp is on the last window, then we use the
* registers 'after' the end
*/
if (index < 8 && env->cwp == env->nwindows - 1) {
index += 16 * env->nwindows;
} }
return index;
}
/* save the register window 'cwp1' */
static inline void save_window_offset(CPUSPARCState *env, int cwp1)
{
unsigned int i;
abi_ulong sp_ptr;
sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
#ifdef TARGET_SPARC64
if (sp_ptr & 3) {
sp_ptr += SPARC64_STACK_BIAS;
}
#endif
#if defined(DEBUG_WIN)
printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
sp_ptr, cwp1);
#endif
for (i = 0; i < 16; i++) {
/* FIXME - what to do if put_user() fails? */
put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
sp_ptr += sizeof(abi_ulong);
}
}
static void save_window(CPUSPARCState *env)
{
#ifndef TARGET_SPARC64
unsigned int new_wim;
new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
((1LL << env->nwindows) - 1);
save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
env->wim = new_wim;
#else
/*
* cansave is zero if the spill trap handler is triggered by `save` and
* nonzero if triggered by a `flushw`
*/
save_window_offset(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
env->cansave++;
env->canrestore--;
#endif
}
static void restore_window(CPUSPARCState *env)
{
#ifndef TARGET_SPARC64
unsigned int new_wim;
#endif
unsigned int i, cwp1;
abi_ulong sp_ptr;
#ifndef TARGET_SPARC64
new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
((1LL << env->nwindows) - 1);
#endif
/* restore the invalid window */
cwp1 = cpu_cwp_inc(env, env->cwp + 1);
sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
#ifdef TARGET_SPARC64
if (sp_ptr & 3) {
sp_ptr += SPARC64_STACK_BIAS;
}
#endif
#if defined(DEBUG_WIN)
printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
sp_ptr, cwp1);
#endif
for (i = 0; i < 16; i++) {
/* FIXME - what to do if get_user() fails? */
get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
sp_ptr += sizeof(abi_ulong);
}
#ifdef TARGET_SPARC64
env->canrestore++;
if (env->cleanwin < env->nwindows - 1) {
env->cleanwin++;
}
env->cansave--;
#else
env->wim = new_wim;
#endif
}
static void flush_windows(CPUSPARCState *env)
{
int offset, cwp1;
offset = 1;
for (;;) {
/* if restore would invoke restore_window(), then we can stop */
cwp1 = cpu_cwp_inc(env, env->cwp + offset);
#ifndef TARGET_SPARC64
if (env->wim & (1 << cwp1)) {
break;
}
#else
if (env->canrestore == 0) {
break;
}
env->cansave++;
env->canrestore--;
#endif
save_window_offset(env, cwp1);
offset++;
}
cwp1 = cpu_cwp_inc(env, env->cwp + 1);
#ifndef TARGET_SPARC64
/* set wim so that restore will reload the registers */
env->wim = 1 << cwp1;
#endif
#if defined(DEBUG_WIN)
printf("flush_windows: nb=%d\n", offset - 1);
#endif
}
void cpu_loop(CPUSPARCState *env)
{
CPUState *cs = env_cpu(env);
int trapnr, ret, syscall_nr;
/* target_siginfo_t info; */
while (1) {
cpu_exec_start(cs);
trapnr = cpu_exec(cs);
cpu_exec_end(cs);
process_queued_cpu_work(cs);
switch (trapnr) {
#ifndef TARGET_SPARC64
case 0x80:
#else
/* FreeBSD uses 0x141 for syscalls too */
case 0x141:
if (bsd_type != target_freebsd) {
goto badtrap;
}
/* fallthrough */
case 0x100:
#endif
syscall_nr = env->gregs[1];
if (bsd_type == target_freebsd)
ret = do_freebsd_syscall(env, syscall_nr,
env->regwptr[0], env->regwptr[1],
env->regwptr[2], env->regwptr[3],
env->regwptr[4], env->regwptr[5],
0, 0);
else if (bsd_type == target_netbsd)
ret = do_netbsd_syscall(env, syscall_nr,
env->regwptr[0], env->regwptr[1],
env->regwptr[2], env->regwptr[3],
env->regwptr[4], env->regwptr[5]);
else { /* if (bsd_type == target_openbsd) */
#if defined(TARGET_SPARC64)
syscall_nr &= ~(TARGET_OPENBSD_SYSCALL_G7RFLAG |
TARGET_OPENBSD_SYSCALL_G2RFLAG);
#endif
ret = do_openbsd_syscall(env, syscall_nr,
env->regwptr[0], env->regwptr[1],
env->regwptr[2], env->regwptr[3],
env->regwptr[4], env->regwptr[5]);
}
if ((unsigned int)ret >= (unsigned int)(-515)) {
ret = -ret;
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
env->xcc |= PSR_CARRY;
#else
env->psr |= PSR_CARRY;
#endif
} else {
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
env->xcc &= ~PSR_CARRY;
#else
env->psr &= ~PSR_CARRY;
#endif
}
env->regwptr[0] = ret;
/* next instruction */
#if defined(TARGET_SPARC64)
if (bsd_type == target_openbsd &&
env->gregs[1] & TARGET_OPENBSD_SYSCALL_G2RFLAG) {
env->pc = env->gregs[2];
env->npc = env->pc + 4;
} else if (bsd_type == target_openbsd &&
env->gregs[1] & TARGET_OPENBSD_SYSCALL_G7RFLAG) {
env->pc = env->gregs[7];
env->npc = env->pc + 4;
} else {
env->pc = env->npc;
env->npc = env->npc + 4;
}
#else
env->pc = env->npc;
env->npc = env->npc + 4;
#endif
break;
case 0x83: /* flush windows */
#ifdef TARGET_ABI32
case 0x103:
#endif
flush_windows(env);
/* next instruction */
env->pc = env->npc;
env->npc = env->npc + 4;
break;
#ifndef TARGET_SPARC64
case TT_WIN_OVF: /* window overflow */
save_window(env);
break;
case TT_WIN_UNF: /* window underflow */
restore_window(env);
break;
case TT_TFAULT:
case TT_DFAULT:
break;
#else
case TT_SPILL: /* window overflow */
save_window(env);
break;
case TT_FILL: /* window underflow */
restore_window(env);
break;
case TT_TFAULT:
case TT_DFAULT:
break;
#endif
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
case EXCP_DEBUG:
{
gdb_handlesig(cs, TARGET_SIGTRAP);
}
break;
default:
#ifdef TARGET_SPARC64
badtrap:
#endif
printf("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(cs, stderr, 0);
exit(1);
}
process_pending_signals(env);
}
}
#endif
static void usage(void) static void usage(void)
{ {
@ -552,7 +170,6 @@ static void usage(void)
"-d item1[,...] enable logging of specified items\n" "-d item1[,...] enable logging of specified items\n"
" (use '-d help' for a list of log items)\n" " (use '-d help' for a list of log items)\n"
"-D logfile write logs to 'logfile' (default stderr)\n" "-D logfile write logs to 'logfile' (default stderr)\n"
"-p pagesize set the host page size to 'pagesize'\n"
"-singlestep always run in singlestep mode\n" "-singlestep always run in singlestep mode\n"
"-strace log system calls\n" "-strace log system calls\n"
"-trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n" "-trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
@ -572,11 +189,11 @@ static void usage(void)
, ,
TARGET_NAME, TARGET_NAME,
interp_prefix, interp_prefix,
x86_stack_size); target_dflssiz);
exit(1); exit(1);
} }
THREAD CPUState *thread_cpu; __thread CPUState *thread_cpu;
bool qemu_cpu_is_self(CPUState *cpu) bool qemu_cpu_is_self(CPUState *cpu)
{ {
@ -601,6 +218,48 @@ void init_task_state(TaskState *ts)
ts->sigqueue_table[i].next = NULL; ts->sigqueue_table[i].next = NULL;
} }
void gemu_log(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
static void
adjust_ssize(void)
{
struct rlimit rl;
if (getrlimit(RLIMIT_STACK, &rl) != 0) {
return;
}
target_maxssiz = MIN(target_maxssiz, rl.rlim_max);
target_dflssiz = MIN(MAX(target_dflssiz, rl.rlim_cur), target_maxssiz);
rl.rlim_max = target_maxssiz;
rl.rlim_cur = target_dflssiz;
setrlimit(RLIMIT_STACK, &rl);
}
static void save_proc_pathname(char *argv0)
{
int mib[4];
size_t len;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;
len = sizeof(qemu_proc_pathname);
if (sysctl(mib, 4, qemu_proc_pathname, &len, NULL, 0)) {
perror("sysctl");
}
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
const char *filename; const char *filename;
@ -608,9 +267,11 @@ int main(int argc, char **argv)
const char *cpu_type; const char *cpu_type;
const char *log_file = NULL; const char *log_file = NULL;
const char *log_mask = NULL; const char *log_mask = NULL;
const char *seed_optarg = NULL;
struct target_pt_regs regs1, *regs = &regs1; struct target_pt_regs regs1, *regs = &regs1;
struct image_info info1, *info = &info1; struct image_info info1, *info = &info1;
TaskState ts1, *ts = &ts1; struct bsd_binprm bprm;
TaskState *ts;
CPUArchState *env; CPUArchState *env;
CPUState *cpu; CPUState *cpu;
int optind, rv; int optind, rv;
@ -618,12 +279,17 @@ int main(int argc, char **argv)
const char *gdbstub = NULL; const char *gdbstub = NULL;
char **target_environ, **wrk; char **target_environ, **wrk;
envlist_t *envlist = NULL; envlist_t *envlist = NULL;
bsd_type = target_openbsd; bsd_type = HOST_DEFAULT_BSD_TYPE;
char *argv0 = NULL;
adjust_ssize();
if (argc <= 1) { if (argc <= 1) {
usage(); usage();
} }
save_proc_pathname(argv[0]);
error_init(argv[0]); error_init(argv[0]);
module_call_init(MODULE_INIT_TRACE); module_call_init(MODULE_INIT_TRACE);
qemu_init_cpu_list(); qemu_init_cpu_list();
@ -678,14 +344,17 @@ int main(int argc, char **argv)
} }
} else if (!strcmp(r, "s")) { } else if (!strcmp(r, "s")) {
r = argv[optind++]; r = argv[optind++];
rv = qemu_strtoul(r, &r, 0, &x86_stack_size); rv = qemu_strtoul(r, &r, 0, &target_dflssiz);
if (rv < 0 || x86_stack_size <= 0) { if (rv < 0 || target_dflssiz <= 0) {
usage(); usage();
} }
if (*r == 'M') { if (*r == 'M') {
x86_stack_size *= MiB; target_dflssiz *= 1024 * 1024;
} else if (*r == 'k' || *r == 'K') { } else if (*r == 'k' || *r == 'K') {
x86_stack_size *= KiB; target_dflssiz *= 1024;
}
if (target_dflssiz > target_maxssiz) {
usage();
} }
} else if (!strcmp(r, "L")) { } else if (!strcmp(r, "L")) {
interp_prefix = argv[optind++]; interp_prefix = argv[optind++];
@ -728,12 +397,16 @@ int main(int argc, char **argv)
usage(); usage();
} }
optind++; optind++;
} else if (!strcmp(r, "seed")) {
seed_optarg = optarg;
} else if (!strcmp(r, "singlestep")) { } else if (!strcmp(r, "singlestep")) {
singlestep = 1; singlestep = 1;
} else if (!strcmp(r, "strace")) { } else if (!strcmp(r, "strace")) {
do_strace = 1; do_strace = 1;
} else if (!strcmp(r, "trace")) { } else if (!strcmp(r, "trace")) {
trace_opt_parse(optarg); trace_opt_parse(optarg);
} else if (!strcmp(r, "0")) {
argv0 = argv[optind++];
} else { } else {
usage(); usage();
} }
@ -757,6 +430,9 @@ int main(int argc, char **argv)
usage(); usage();
} }
filename = argv[optind]; filename = argv[optind];
if (argv0) {
argv[optind] = argv0;
}
if (!trace_init_backends()) { if (!trace_init_backends()) {
exit(1); exit(1);
@ -766,6 +442,9 @@ int main(int argc, char **argv)
/* Zero out regs */ /* Zero out regs */
memset(regs, 0, sizeof(struct target_pt_regs)); memset(regs, 0, sizeof(struct target_pt_regs));
/* Zero bsd params */
memset(&bprm, 0, sizeof(bprm));
/* Zero out image_info */ /* Zero out image_info */
memset(info, 0, sizeof(struct image_info)); memset(info, 0, sizeof(struct image_info));
@ -773,24 +452,11 @@ int main(int argc, char **argv)
init_paths(interp_prefix); init_paths(interp_prefix);
if (cpu_model == NULL) { if (cpu_model == NULL) {
#if defined(TARGET_I386) cpu_model = TARGET_DEFAULT_CPU_MODEL;
#ifdef TARGET_X86_64
cpu_model = "qemu64";
#else
cpu_model = "qemu32";
#endif
#elif defined(TARGET_SPARC)
#ifdef TARGET_SPARC64
cpu_model = "TI UltraSparc II";
#else
cpu_model = "Fujitsu MB86904";
#endif
#else
cpu_model = "any";
#endif
} }
cpu_type = parse_cpu_option(cpu_model); cpu_type = parse_cpu_option(cpu_model);
/* init tcg before creating CPUs and to get qemu_host_page_size */ /* init tcg before creating CPUs and to get qemu_host_page_size */
{ {
AccelClass *ac = ACCEL_GET_CLASS(current_accel()); AccelClass *ac = ACCEL_GET_CLASS(current_accel());
@ -800,9 +466,7 @@ int main(int argc, char **argv)
} }
cpu = cpu_create(cpu_type); cpu = cpu_create(cpu_type);
env = cpu->env_ptr; env = cpu->env_ptr;
#if defined(TARGET_SPARC) || defined(TARGET_PPC)
cpu_reset(cpu); cpu_reset(cpu);
#endif
thread_cpu = cpu; thread_cpu = cpu;
if (getenv("QEMU_STRACE")) { if (getenv("QEMU_STRACE")) {
@ -812,36 +476,31 @@ int main(int argc, char **argv)
target_environ = envlist_to_environ(envlist, NULL); target_environ = envlist_to_environ(envlist, NULL);
envlist_free(envlist); envlist_free(envlist);
if (reserved_va) {
mmap_next_start = reserved_va;
}
{
Error *err = NULL;
if (seed_optarg != NULL) {
qemu_guest_random_seed_main(seed_optarg, &err);
} else {
qcrypto_init(&err);
}
if (err) {
error_reportf_err(err, "cannot initialize crypto: ");
exit(1);
}
}
/* /*
* Now that page sizes are configured we can do * Now that page sizes are configured we can do
* proper page alignment for guest_base. * proper page alignment for guest_base.
*/ */
guest_base = HOST_PAGE_ALIGN(guest_base); guest_base = HOST_PAGE_ALIGN(guest_base);
/* if (loader_exec(filename, argv + optind, target_environ, regs, info,
* Read in mmap_min_addr kernel parameter. This value is used &bprm) != 0) {
* When loading the ELF image to determine whether guest_base
* is needed.
*
* When user has explicitly set the quest base, we skip this
* test.
*/
if (!have_guest_base) {
FILE *fp;
fp = fopen("/proc/sys/vm/mmap_min_addr", "r");
if (fp != NULL) {
unsigned long tmp;
if (fscanf(fp, "%lu", &tmp) == 1) {
mmap_min_addr = tmp;
qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n",
mmap_min_addr);
}
fclose(fp);
}
}
if (loader_exec(filename, argv + optind, target_environ, regs, info) != 0) {
printf("Error loading %s\n", filename); printf("Error loading %s\n", filename);
_exit(1); _exit(1);
} }
@ -869,6 +528,13 @@ int main(int argc, char **argv)
qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry); qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry);
} }
/* build Task State */
ts = g_new0(TaskState, 1);
init_task_state(ts);
ts->info = info;
ts->bprm = &bprm;
cpu->opaque = ts;
target_set_brk(info->brk); target_set_brk(info->brk);
syscall_init(); syscall_init();
signal_init(); signal_init();
@ -880,143 +546,7 @@ int main(int argc, char **argv)
*/ */
tcg_prologue_init(tcg_ctx); tcg_prologue_init(tcg_ctx);
/* build Task State */ target_cpu_init(env, regs);
memset(ts, 0, sizeof(TaskState));
init_task_state(ts);
ts->info = info;
cpu->opaque = ts;
#if defined(TARGET_I386)
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
env->hflags |= HF_PE_MASK | HF_CPL_MASK;
if (env->features[FEAT_1_EDX] & CPUID_SSE) {
env->cr[4] |= CR4_OSFXSR_MASK;
env->hflags |= HF_OSFXSR_MASK;
}
#ifndef TARGET_ABI32
/* enable 64 bit mode if possible */
if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
exit(1);
}
env->cr[4] |= CR4_PAE_MASK;
env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
env->hflags |= HF_LMA_MASK;
#endif
/* flags setup : we activate the IRQs by default as in user mode */
env->eflags |= IF_MASK;
/* linux register setup */
#ifndef TARGET_ABI32
env->regs[R_EAX] = regs->rax;
env->regs[R_EBX] = regs->rbx;
env->regs[R_ECX] = regs->rcx;
env->regs[R_EDX] = regs->rdx;
env->regs[R_ESI] = regs->rsi;
env->regs[R_EDI] = regs->rdi;
env->regs[R_EBP] = regs->rbp;
env->regs[R_ESP] = regs->rsp;
env->eip = regs->rip;
#else
env->regs[R_EAX] = regs->eax;
env->regs[R_EBX] = regs->ebx;
env->regs[R_ECX] = regs->ecx;
env->regs[R_EDX] = regs->edx;
env->regs[R_ESI] = regs->esi;
env->regs[R_EDI] = regs->edi;
env->regs[R_EBP] = regs->ebp;
env->regs[R_ESP] = regs->esp;
env->eip = regs->eip;
#endif
/* linux interrupt setup */
#ifndef TARGET_ABI32
env->idt.limit = 511;
#else
env->idt.limit = 255;
#endif
env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
idt_table = g2h_untagged(env->idt.base);
set_idt(0, 0);
set_idt(1, 0);
set_idt(2, 0);
set_idt(3, 3);
set_idt(4, 3);
set_idt(5, 0);
set_idt(6, 0);
set_idt(7, 0);
set_idt(8, 0);
set_idt(9, 0);
set_idt(10, 0);
set_idt(11, 0);
set_idt(12, 0);
set_idt(13, 0);
set_idt(14, 0);
set_idt(15, 0);
set_idt(16, 0);
set_idt(17, 0);
set_idt(18, 0);
set_idt(19, 0);
set_idt(0x80, 3);
/* linux segment setup */
{
uint64_t *gdt_table;
env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
gdt_table = g2h_untagged(env->gdt.base);
#ifdef TARGET_ABI32
write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
(3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
#else
/* 64 bit code segment */
write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
DESC_L_MASK |
(3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
#endif
write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
(3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
}
cpu_x86_load_seg(env, R_CS, __USER_CS);
cpu_x86_load_seg(env, R_SS, __USER_DS);
#ifdef TARGET_ABI32
cpu_x86_load_seg(env, R_DS, __USER_DS);
cpu_x86_load_seg(env, R_ES, __USER_DS);
cpu_x86_load_seg(env, R_FS, __USER_DS);
cpu_x86_load_seg(env, R_GS, __USER_DS);
/* This hack makes Wine work... */
env->segs[R_FS].selector = 0;
#else
cpu_x86_load_seg(env, R_DS, 0);
cpu_x86_load_seg(env, R_ES, 0);
cpu_x86_load_seg(env, R_FS, 0);
cpu_x86_load_seg(env, R_GS, 0);
#endif
#elif defined(TARGET_SPARC)
{
int i;
env->pc = regs->pc;
env->npc = regs->npc;
env->y = regs->y;
for (i = 0; i < 8; i++) {
env->gregs[i] = regs->u_regs[i];
}
for (i = 0; i < 8; i++) {
env->regwptr[i] = regs->u_regs[i + 8];
}
}
#else
#error unsupported target CPU
#endif
if (gdbstub) { if (gdbstub) {
gdbserver_start(gdbstub); gdbserver_start(gdbstub);

View File

@ -20,8 +20,6 @@
#include "qemu.h" #include "qemu.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "bsd-mman.h"
#include "exec/exec-all.h"
//#define DEBUG_MMAP //#define DEBUG_MMAP
@ -70,8 +68,8 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
int prot1, ret; int prot1, ret;
#ifdef DEBUG_MMAP #ifdef DEBUG_MMAP
printf("mprotect: start=0x" TARGET_FMT_lx printf("mprotect: start=0x" TARGET_ABI_FMT_lx
" len=0x" TARGET_FMT_lx " prot=%c%c%c\n", start, len, "len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c\n", start, len,
prot & PROT_READ ? 'r' : '-', prot & PROT_READ ? 'r' : '-',
prot & PROT_WRITE ? 'w' : '-', prot & PROT_WRITE ? 'w' : '-',
prot & PROT_EXEC ? 'x' : '-'); prot & PROT_EXEC ? 'x' : '-');
@ -190,90 +188,275 @@ static int mmap_frag(abi_ulong real_start,
return 0; return 0;
} }
static abi_ulong mmap_next_start = 0x40000000; #if HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64
# define TASK_UNMAPPED_BASE (1ul << 38)
#else
# define TASK_UNMAPPED_BASE 0x40000000
#endif
abi_ulong mmap_next_start = TASK_UNMAPPED_BASE;
unsigned long last_brk; unsigned long last_brk;
/* find a free memory area of size 'size'. The search starts at /*
'start'. If 'start' == 0, then a default start address is used. * Subroutine of mmap_find_vma, used when we have pre-allocated a chunk of guest
Return -1 if error. * address space.
*/ */
/* page_init() marks pages used by the host as reserved to be sure not static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size,
to use them. */ abi_ulong alignment)
static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
{ {
abi_ulong addr, addr1, addr_start; abi_ulong addr;
abi_ulong end_addr;
int prot; int prot;
unsigned long new_brk; int looped = 0;
new_brk = (unsigned long)sbrk(0); if (size > reserved_va) {
if (last_brk && last_brk < new_brk && last_brk == (target_ulong)last_brk) {
/* This is a hack to catch the host allocating memory with brk().
If it uses mmap then we loose.
FIXME: We really want to avoid the host allocating memory in
the first place, and maybe leave some slack to avoid switching
to mmap. */
page_set_flags(last_brk & TARGET_PAGE_MASK,
TARGET_PAGE_ALIGN(new_brk),
PAGE_RESERVED);
}
last_brk = new_brk;
size = HOST_PAGE_ALIGN(size);
start = start & qemu_host_page_mask;
addr = start;
if (addr == 0)
addr = mmap_next_start;
addr_start = addr;
for (;;) {
prot = 0;
for (addr1 = addr; addr1 < (addr + size); addr1 += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr1);
}
if (prot == 0)
break;
addr += qemu_host_page_size;
/* we found nothing */
if (addr == addr_start)
return (abi_ulong)-1; return (abi_ulong)-1;
} }
if (start == 0)
mmap_next_start = addr + size; size = HOST_PAGE_ALIGN(size) + alignment;
end_addr = start + size;
if (end_addr > reserved_va) {
end_addr = reserved_va;
}
addr = end_addr - qemu_host_page_size;
while (1) {
if (addr > end_addr) {
if (looped) {
return (abi_ulong)-1;
}
end_addr = reserved_va;
addr = end_addr - qemu_host_page_size;
looped = 1;
continue;
}
prot = page_get_flags(addr);
if (prot) {
end_addr = addr;
}
if (end_addr - addr >= size) {
break;
}
addr -= qemu_host_page_size;
}
if (start == mmap_next_start) {
mmap_next_start = addr;
}
/* addr is sufficiently low to align it up */
if (alignment != 0) {
addr = (addr + alignment) & ~(alignment - 1);
}
return addr; return addr;
} }
/*
* Find and reserve a free memory area of size 'size'. The search
* starts at 'start'.
* It must be called with mmap_lock() held.
* Return -1 if error.
*/
static abi_ulong mmap_find_vma_aligned(abi_ulong start, abi_ulong size,
abi_ulong alignment)
{
void *ptr, *prev;
abi_ulong addr;
int flags;
int wrapped, repeat;
/* If 'start' == 0, then a default start address is used. */
if (start == 0) {
start = mmap_next_start;
} else {
start &= qemu_host_page_mask;
}
size = HOST_PAGE_ALIGN(size);
if (reserved_va) {
return mmap_find_vma_reserved(start, size,
(alignment != 0 ? 1 << alignment : 0));
}
addr = start;
wrapped = repeat = 0;
prev = 0;
flags = MAP_ANONYMOUS | MAP_PRIVATE;
#ifdef MAP_ALIGNED
if (alignment != 0) {
flags |= MAP_ALIGNED(alignment);
}
#else
/* XXX TODO */
#endif
for (;; prev = ptr) {
/*
* Reserve needed memory area to avoid a race.
* It should be discarded using:
* - mmap() with MAP_FIXED flag
* - mremap() with MREMAP_FIXED flag
* - shmat() with SHM_REMAP flag
*/
ptr = mmap(g2h_untagged(addr), size, PROT_NONE,
flags, -1, 0);
/* ENOMEM, if host address space has no memory */
if (ptr == MAP_FAILED) {
return (abi_ulong)-1;
}
/*
* Count the number of sequential returns of the same address.
* This is used to modify the search algorithm below.
*/
repeat = (ptr == prev ? repeat + 1 : 0);
if (h2g_valid(ptr + size - 1)) {
addr = h2g(ptr);
if ((addr & ~TARGET_PAGE_MASK) == 0) {
/* Success. */
if (start == mmap_next_start && addr >= TASK_UNMAPPED_BASE) {
mmap_next_start = addr + size;
}
return addr;
}
/* The address is not properly aligned for the target. */
switch (repeat) {
case 0:
/*
* Assume the result that the kernel gave us is the
* first with enough free space, so start again at the
* next higher target page.
*/
addr = TARGET_PAGE_ALIGN(addr);
break;
case 1:
/*
* Sometimes the kernel decides to perform the allocation
* at the top end of memory instead.
*/
addr &= TARGET_PAGE_MASK;
break;
case 2:
/* Start over at low memory. */
addr = 0;
break;
default:
/* Fail. This unaligned block must the last. */
addr = -1;
break;
}
} else {
/*
* Since the result the kernel gave didn't fit, start
* again at low memory. If any repetition, fail.
*/
addr = (repeat ? -1 : 0);
}
/* Unmap and try again. */
munmap(ptr, size);
/* ENOMEM if we checked the whole of the target address space. */
if (addr == (abi_ulong)-1) {
return (abi_ulong)-1;
} else if (addr == 0) {
if (wrapped) {
return (abi_ulong)-1;
}
wrapped = 1;
/*
* Don't actually use 0 when wrapping, instead indicate
* that we'd truly like an allocation in low memory.
*/
addr = TARGET_PAGE_SIZE;
} else if (wrapped && addr >= start) {
return (abi_ulong)-1;
}
}
}
abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
{
return mmap_find_vma_aligned(start, size, 0);
}
/* NOTE: all the constants are the HOST ones */ /* NOTE: all the constants are the HOST ones */
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
int flags, int fd, abi_ulong offset) int flags, int fd, off_t offset)
{ {
abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len; abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
unsigned long host_start;
mmap_lock(); mmap_lock();
#ifdef DEBUG_MMAP #ifdef DEBUG_MMAP
{ {
printf("mmap: start=0x" TARGET_FMT_lx printf("mmap: start=0x" TARGET_ABI_FMT_lx
" len=0x" TARGET_FMT_lx " prot=%c%c%c flags=", " len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c flags=",
start, len, start, len,
prot & PROT_READ ? 'r' : '-', prot & PROT_READ ? 'r' : '-',
prot & PROT_WRITE ? 'w' : '-', prot & PROT_WRITE ? 'w' : '-',
prot & PROT_EXEC ? 'x' : '-'); prot & PROT_EXEC ? 'x' : '-');
if (flags & MAP_FIXED) if (flags & MAP_ALIGNMENT_MASK) {
printf("MAP_FIXED "); printf("MAP_ALIGNED(%u) ", (flags & MAP_ALIGNMENT_MASK)
if (flags & MAP_ANON) >> MAP_ALIGNMENT_SHIFT);
printf("MAP_ANON ");
switch (flags & TARGET_BSD_MAP_FLAGMASK) {
case MAP_PRIVATE:
printf("MAP_PRIVATE ");
break;
case MAP_SHARED:
printf("MAP_SHARED ");
break;
default:
printf("[MAP_FLAGMASK=0x%x] ", flags & TARGET_BSD_MAP_FLAGMASK);
break;
} }
printf("fd=%d offset=" TARGET_FMT_lx "\n", fd, offset); #if MAP_GUARD
if (flags & MAP_GUARD) {
printf("MAP_GUARD ");
}
#endif
if (flags & MAP_FIXED) {
printf("MAP_FIXED ");
}
if (flags & MAP_ANONYMOUS) {
printf("MAP_ANON ");
}
#ifdef MAP_EXCL
if (flags & MAP_EXCL) {
printf("MAP_EXCL ");
}
#endif
if (flags & MAP_PRIVATE) {
printf("MAP_PRIVATE ");
}
if (flags & MAP_SHARED) {
printf("MAP_SHARED ");
}
if (flags & MAP_NOCORE) {
printf("MAP_NOCORE ");
}
#ifdef MAP_STACK
if (flags & MAP_STACK) {
printf("MAP_STACK ");
}
#endif
printf("fd=%d offset=0x%llx\n", fd, offset);
}
#endif
if ((flags & MAP_ANONYMOUS) && fd != -1) {
errno = EINVAL;
goto fail;
}
#ifdef MAP_STACK
if (flags & MAP_STACK) {
if ((fd != -1) || ((prot & (PROT_READ | PROT_WRITE)) !=
(PROT_READ | PROT_WRITE))) {
errno = EINVAL;
goto fail;
}
}
#endif /* MAP_STACK */
#ifdef MAP_GUARD
if ((flags & MAP_GUARD) && (prot != PROT_NONE || fd != -1 ||
offset != 0 || (flags & (MAP_SHARED | MAP_PRIVATE |
/* MAP_PREFAULT | */ /* MAP_PREFAULT not in mman.h */
MAP_PREFAULT_READ | MAP_ANON | MAP_STACK)) != 0)) {
errno = EINVAL;
goto fail;
} }
#endif #endif
@ -283,37 +466,92 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
} }
len = TARGET_PAGE_ALIGN(len); len = TARGET_PAGE_ALIGN(len);
if (len == 0) if (len == 0) {
goto the_end; errno = EINVAL;
goto fail;
}
real_start = start & qemu_host_page_mask; real_start = start & qemu_host_page_mask;
if (!(flags & MAP_FIXED)) {
abi_ulong mmap_start;
void *p;
host_offset = offset & qemu_host_page_mask; host_offset = offset & qemu_host_page_mask;
/*
* If the user is asking for the kernel to find a location, do that
* before we truncate the length for mapping files below.
*/
if (!(flags & MAP_FIXED)) {
host_len = len + offset - host_offset; host_len = len + offset - host_offset;
host_len = HOST_PAGE_ALIGN(host_len); host_len = HOST_PAGE_ALIGN(host_len);
mmap_start = mmap_find_vma(real_start, host_len); if ((flags & MAP_ALIGNMENT_MASK) != 0)
if (mmap_start == (abi_ulong)-1) { start = mmap_find_vma_aligned(real_start, host_len,
(flags & MAP_ALIGNMENT_MASK) >> MAP_ALIGNMENT_SHIFT);
else
start = mmap_find_vma(real_start, host_len);
if (start == (abi_ulong)-1) {
errno = ENOMEM; errno = ENOMEM;
goto fail; goto fail;
} }
/* Note: we prefer to control the mapping address. It is }
especially important if qemu_host_page_size >
qemu_real_host_page_size */ /*
p = mmap(g2h_untagged(mmap_start), * When mapping files into a memory area larger than the file, accesses
host_len, prot, flags | MAP_FIXED, fd, host_offset); * to pages beyond the file size will cause a SIGBUS.
*
* For example, if mmaping a file of 100 bytes on a host with 4K pages
* emulating a target with 8K pages, the target expects to be able to
* access the first 8K. But the host will trap us on any access beyond
* 4K.
*
* When emulating a target with a larger page-size than the hosts, we
* may need to truncate file maps at EOF and add extra anonymous pages
* up to the targets page boundary.
*/
if ((qemu_real_host_page_size < qemu_host_page_size) && fd != -1) {
struct stat sb;
if (fstat(fd, &sb) == -1) {
goto fail;
}
/* Are we trying to create a map beyond EOF?. */
if (offset + len > sb.st_size) {
/*
* If so, truncate the file map at eof aligned with
* the hosts real pagesize. Additional anonymous maps
* will be created beyond EOF.
*/
len = REAL_HOST_PAGE_ALIGN(sb.st_size - offset);
}
}
if (!(flags & MAP_FIXED)) {
unsigned long host_start;
void *p;
host_len = len + offset - host_offset;
host_len = HOST_PAGE_ALIGN(host_len);
/*
* Note: we prefer to control the mapping address. It is
* especially important if qemu_host_page_size >
* qemu_real_host_page_size
*/
p = mmap(g2h_untagged(start), host_len, prot,
flags | MAP_FIXED | ((fd != -1) ? MAP_ANONYMOUS : 0), -1, 0);
if (p == MAP_FAILED) if (p == MAP_FAILED)
goto fail; goto fail;
/* update start so that it points to the file position at 'offset' */ /* update start so that it points to the file position at 'offset' */
host_start = (unsigned long)p; host_start = (unsigned long)p;
if (!(flags & MAP_ANON)) if (fd != -1) {
p = mmap(g2h_untagged(start), len, prot,
flags | MAP_FIXED, fd, host_offset);
if (p == MAP_FAILED) {
munmap(g2h_untagged(start), host_len);
goto fail;
}
host_start += offset - host_offset; host_start += offset - host_offset;
}
start = h2g(host_start); start = h2g(host_start);
} else { } else {
int flg;
target_ulong addr;
if (start & ~TARGET_PAGE_MASK) { if (start & ~TARGET_PAGE_MASK) {
errno = EINVAL; errno = EINVAL;
goto fail; goto fail;
@ -321,20 +559,28 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
end = start + len; end = start + len;
real_end = HOST_PAGE_ALIGN(end); real_end = HOST_PAGE_ALIGN(end);
for (addr = real_start; addr < real_end; addr += TARGET_PAGE_SIZE) { /*
flg = page_get_flags(addr); * Test if requested memory area fits target address space
if (flg & PAGE_RESERVED) { * It can fail only on 64-bit host with 32-bit target.
errno = ENXIO; * On any other target/host host mmap() handles this error correctly.
*/
#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
if ((unsigned long)start + len - 1 > (abi_ulong) -1) {
errno = EINVAL;
goto fail; goto fail;
} }
} #endif
/* worst case: we cannot map the file because the offset is not /*
aligned, so we read it */ * worst case: we cannot map the file because the offset is not
* aligned, so we read it
*/
if (!(flags & MAP_ANON) && if (!(flags & MAP_ANON) &&
(offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) { (offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) {
/* msync() won't work here, so we return an error if write is /*
possible while it is a shared mapping */ * msync() won't work here, so we return an error if write is
* possible while it is a shared mapping
*/
if ((flags & TARGET_BSD_MAP_FLAGMASK) == MAP_SHARED && if ((flags & TARGET_BSD_MAP_FLAGMASK) == MAP_SHARED &&
(prot & PROT_WRITE)) { (prot & PROT_WRITE)) {
errno = EINVAL; errno = EINVAL;
@ -375,7 +621,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
/* handle the end of the mapping */ /* handle the end of the mapping */
if (end < real_end) { if (end < real_end) {
ret = mmap_frag(real_end - qemu_host_page_size, ret = mmap_frag(real_end - qemu_host_page_size,
real_end - qemu_host_page_size, real_end, real_end - qemu_host_page_size, end,
prot, flags, fd, prot, flags, fd,
offset + real_end - qemu_host_page_size - start); offset + real_end - qemu_host_page_size - start);
if (ret == -1) if (ret == -1)
@ -401,10 +647,11 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
page_set_flags(start, start + len, prot | PAGE_VALID); page_set_flags(start, start + len, prot | PAGE_VALID);
the_end: the_end:
#ifdef DEBUG_MMAP #ifdef DEBUG_MMAP
printf("ret=0x" TARGET_FMT_lx "\n", start); printf("ret=0x" TARGET_ABI_FMT_lx "\n", start);
page_dump(stdout); page_dump(stdout);
printf("\n"); printf("\n");
#endif #endif
tb_invalidate_phys_range(start, start + len);
mmap_unlock(); mmap_unlock();
return start; return start;
fail: fail:
@ -412,13 +659,58 @@ fail:
return -1; return -1;
} }
static void mmap_reserve(abi_ulong start, abi_ulong size)
{
abi_ulong real_start;
abi_ulong real_end;
abi_ulong addr;
abi_ulong end;
int prot;
real_start = start & qemu_host_page_mask;
real_end = HOST_PAGE_ALIGN(start + size);
end = start + size;
if (start > real_start) {
/* handle host page containing start */
prot = 0;
for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr);
}
if (real_end == real_start + qemu_host_page_size) {
for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr);
}
end = real_end;
}
if (prot != 0) {
real_start += qemu_host_page_size;
}
}
if (end < real_end) {
prot = 0;
for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr);
}
if (prot != 0) {
real_end -= qemu_host_page_size;
}
}
if (real_start != real_end) {
mmap(g2h_untagged(real_start), real_end - real_start, PROT_NONE,
MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE,
-1, 0);
}
}
int target_munmap(abi_ulong start, abi_ulong len) int target_munmap(abi_ulong start, abi_ulong len)
{ {
abi_ulong end, real_start, real_end, addr; abi_ulong end, real_start, real_end, addr;
int prot, ret; int prot, ret;
#ifdef DEBUG_MMAP #ifdef DEBUG_MMAP
printf("munmap: start=0x%lx len=0x%lx\n", start, len); printf("munmap: start=0x" TARGET_ABI_FMT_lx " len=0x"
TARGET_ABI_FMT_lx "\n",
start, len);
#endif #endif
if (start & ~TARGET_PAGE_MASK) if (start & ~TARGET_PAGE_MASK)
return -EINVAL; return -EINVAL;
@ -457,11 +749,17 @@ int target_munmap(abi_ulong start, abi_ulong len)
ret = 0; ret = 0;
/* unmap what we can */ /* unmap what we can */
if (real_start < real_end) { if (real_start < real_end) {
if (reserved_va) {
mmap_reserve(real_start, real_end - real_start);
} else {
ret = munmap(g2h_untagged(real_start), real_end - real_start); ret = munmap(g2h_untagged(real_start), real_end - real_start);
} }
}
if (ret == 0) if (ret == 0) {
page_set_flags(start, start + len, 0); page_set_flags(start, start + len, 0);
tb_invalidate_phys_range(start, start + len);
}
mmap_unlock(); mmap_unlock();
return ret; return ret;
} }

25
bsd-user/netbsd/host-os.h Normal file
View File

@ -0,0 +1,25 @@
/*
* NetBSD host dependent code and definitions
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _HOST_OS_H_
#define _HOST_OS_H_
#define HOST_DEFAULT_BSD_TYPE target_netbsd
#endif /*!_HOST_OS_H_ */

View File

@ -0,0 +1,146 @@
/*
* netbsd ELF definitions
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_OS_ELF_H_
#define _TARGET_OS_ELF_H_
#include "target_arch_elf.h"
#include "elf.h"
/* this flag is uneffective under linux too, should be deleted */
#ifndef MAP_DENYWRITE
#define MAP_DENYWRITE 0
#endif
/* should probably go in elf.h */
#ifndef ELIBBAD
#define ELIBBAD 80
#endif
#ifndef ELF_PLATFORM
#define ELF_PLATFORM (NULL)
#endif
#ifndef ELF_HWCAP
#define ELF_HWCAP 0
#endif
#ifdef TARGET_ABI32
#undef ELF_CLASS
#define ELF_CLASS ELFCLASS32
#undef bswaptls
#define bswaptls(ptr) bswap32s(ptr)
#endif
/* max code+data+bss space allocated to elf interpreter */
#define INTERP_MAP_SIZE (32 * 1024 * 1024)
/* max code+data+bss+brk space allocated to ET_DYN executables */
#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
/* Necessary parameters */
#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
#define TARGET_ELF_PAGESTART(_v) ((_v) & \
~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE - 1))
#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE - 1))
#define DLINFO_ITEMS 12
static abi_ulong target_create_elf_tables(abi_ulong p, int argc, int envc,
abi_ulong stringp,
struct elfhdr *exec,
abi_ulong load_addr,
abi_ulong load_bias,
abi_ulong interp_load_addr,
struct image_info *info)
{
abi_ulong sp;
int size;
abi_ulong u_platform;
const char *k_platform;
const int n = sizeof(elf_addr_t);
sp = p;
u_platform = 0;
k_platform = ELF_PLATFORM;
if (k_platform) {
size_t len = strlen(k_platform) + 1;
sp -= (len + n - 1) & ~(n - 1);
u_platform = sp;
/* FIXME - check return value of memcpy_to_target() for failure */
memcpy_to_target(sp, k_platform, len);
}
/*
* Force 16 byte _final_ alignment here for generality.
*/
sp = sp & ~(abi_ulong)15;
size = (DLINFO_ITEMS + 1) * 2;
if (k_platform) {
size += 2;
}
#ifdef DLINFO_ARCH_ITEMS
size += DLINFO_ARCH_ITEMS * 2;
#endif
size += envc + argc + 2;
size += 1; /* argc itself */
size *= n;
if (size & 15) {
sp -= 16 - (size & 15);
}
/*
* NetBSD defines elf_addr_t as Elf32_Off / Elf64_Off
*/
#define NEW_AUX_ENT(id, val) do { \
sp -= n; put_user_ual(val, sp); \
sp -= n; put_user_ual(id, sp); \
} while (0)
NEW_AUX_ENT(AT_NULL, 0);
/* There must be exactly DLINFO_ITEMS entries here. */
NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof(struct elf_phdr)));
NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
NEW_AUX_ENT(AT_UID, (abi_ulong)getuid());
NEW_AUX_ENT(AT_EUID, (abi_ulong)geteuid());
NEW_AUX_ENT(AT_GID, (abi_ulong)getgid());
NEW_AUX_ENT(AT_EGID, (abi_ulong)getegid());
NEW_AUX_ENT(AT_HWCAP, (abi_ulong)ELF_HWCAP);
NEW_AUX_ENT(AT_CLKTCK, (abi_ulong)sysconf(_SC_CLK_TCK));
if (k_platform) {
NEW_AUX_ENT(AT_PLATFORM, u_platform);
}
#ifdef ARCH_DLINFO
/*
* ARCH_DLINFO must come last so platform specific code can enforce
* special alignment requirements on the AUXV if necessary (eg. PPC).
*/
ARCH_DLINFO;
#endif
#undef NEW_AUX_ENT
sp = loader_build_argptr(envc, argc, sp, stringp);
return sp;
}
#endif /* _TARGET_OS_ELF_H_ */

View File

@ -0,0 +1,82 @@
#ifndef _TARGET_OS_SIGINFO_H_
#define _TARGET_OS_SIGINFO_H_
#define TARGET_NSIG 32 /* counting 0; could be 33 (mask is 1-32) */
#define TARGET_NSIG_BPW (sizeof(uint32_t) * 8)
#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
/* this struct defines a stack used during syscall handling */
typedef struct target_sigaltstack {
abi_long ss_sp;
abi_ulong ss_size;
abi_long ss_flags;
} target_stack_t;
typedef struct {
uint32_t __bits[TARGET_NSIG_WORDS];
} target_sigset_t
struct target_sigaction {
abi_ulong _sa_handler;
int32_t sa_flags;
target_sigset_t sa_mask;
};
/* Compare to sys/siginfo.h */
typedef union target_sigval {
int sival_int;
abi_ulong sival_ptr;
} target_sigval_t;
struct target_ksiginfo {
int32_t _signo;
int32_t _code;
int32_t _errno;
#if TARGET_ABI_BITS == 64
int32_t _pad;
#endif
union {
struct {
int32_t _pid;
int32_t _uid;
target_sigval_t _value;
} _rt;
struct {
int32_t _pid;
int32_t _uid;
int32_t _struct;
/* clock_t _utime; */
/* clock_t _stime; */
} _child;
struct {
abi_ulong _addr;
int32_t _trap;
} _fault;
struct {
long _band;
int _fd;
} _poll;
} _reason;
};
typedef union target_siginfo {
int8_t si_pad[128];
struct target_ksiginfo _info;
} target_siginfo_t;
#define target_si_signo _info._signo
#define target_si_code _info._code
#define target_si_errno _info._errno
#define target_si_addr _info._reason._fault._addr
#define TARGET_SEGV_MAPERR 1
#define TARGET_SEGV_ACCERR 2
#define TARGET_TRAP_BRKPT 1
#define TARGET_TRAP_TRACE 2
#endif /* ! _TARGET_OS_SIGINFO_H_ */

View File

@ -0,0 +1,69 @@
#ifndef _TARGET_OS_SIGNAL_H_
#define _TARGET_OS_SIGNAL_H_
#include "target_os_siginfo.h"
#include "target_arch_signal.h"
#define TARGET_SIGHUP 1 /* hangup */
#define TARGET_SIGINT 2 /* interrupt */
#define TARGET_SIGQUIT 3 /* quit */
#define TARGET_SIGILL 4 /* illegal instruction (not reset when caught) */
#define TARGET_SIGTRAP 5 /* trace trap (not reset when caught) */
#define TARGET_SIGABRT 6 /* abort() */
#define TARGET_SIGIOT SIGABRT /* compatibility */
#define TARGET_SIGEMT 7 /* EMT instruction */
#define TARGET_SIGFPE 8 /* floating point exception */
#define TARGET_SIGKILL 9 /* kill (cannot be caught or ignored) */
#define TARGET_SIGBUS 10 /* bus error */
#define TARGET_SIGSEGV 11 /* segmentation violation */
#define TARGET_SIGSYS 12 /* bad argument to system call */
#define TARGET_SIGPIPE 13 /* write on a pipe with no one to read it */
#define TARGET_SIGALRM 14 /* alarm clock */
#define TARGET_SIGTERM 15 /* software termination signal from kill */
#define TARGET_SIGURG 16 /* urgent condition on IO channel */
#define TARGET_SIGSTOP 17 /* sendable stop signal not from tty */
#define TARGET_SIGTSTP 18 /* stop signal from tty */
#define TARGET_SIGCONT 19 /* continue a stopped process */
#define TARGET_SIGCHLD 20 /* to parent on child stop or exit */
#define TARGET_SIGTTIN 21 /* to readers pgrp upon background tty read */
#define TARGET_SIGTTOU 22 /* like TTIN for out if (tp->t_local&LTOSTOP) */
#define TARGET_SIGIO 23 /* input/output possible signal */
#define TARGET_SIGXCPU 24 /* exceeded CPU time limit */
#define TARGET_SIGXFSZ 25 /* exceeded file size limit */
#define TARGET_SIGVTALRM 26 /* virtual time alarm */
#define TARGET_SIGPROF 27 /* profiling time alarm */
#define TARGET_SIGWINCH 28 /* window size changes */
#define TARGET_SIGINFO 29 /* information request */
#define TARGET_SIGUSR1 30 /* user defined signal 1 */
#define TARGET_SIGUSR2 31 /* user defined signal 2 */
/*
* Language spec says we must list exactly one parameter, even though we
* actually supply three. Ugh!
*/
#define TARGET_SIG_DFL ((void (*)(int))0)
#define TARGET_SIG_IGN ((void (*)(int))1)
#define TARGET_SIG_ERR ((void (*)(int))-1)
#define TARGET_SA_ONSTACK 0x0001 /* take signal on signal stack */
#define TARGET_SA_RESTART 0x0002 /* restart system on signal return */
#define TARGET_SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */
#define TARGET_SA_NODEFER 0x0010 /* don't mask the signal we're delivering */
#define TARGET_SA_NOCLDWAIT 0x0020 /* don't create zombies (assign to pid 1) */
#define TARGET_SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */
#define TARGET_SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */
#define TARGET_SA_SIGINFO 0x0040 /* generate siginfo_t */
/*
* Flags for sigprocmask:
*/
#define TARGET_SIG_BLOCK 1 /* block specified signal set */
#define TARGET_SIG_UNBLOCK 2 /* unblock specified signal set */
#define TARGET_SIG_SETMASK 3 /* set specified signal set */
#define TARGET_BADSIG SIG_ERR
#define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */
#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate stack */
#endif /* !_TARGET_OS_SIGNAL_H_ */

View File

@ -0,0 +1,56 @@
/*
* NetBSD setup_initial_stack() implementation.
*
* Copyright (c) 2013-14 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_OS_STACK_H_
#define _TARGET_OS_STACK_H_
#include "target_arch_sigtramp.h"
static inline int setup_initial_stack(struct bsd_binprm *bprm, abi_ulong *p,
abi_ulong *stringp)
{
int i;
abi_ulong stack_base;
stack_base = (target_stkbas + target_stksiz) -
MAX_ARG_PAGES * TARGET_PAGE_SIZE;
if (p) {
*p = stack_base;
}
if (stringp) {
*stringp = stack_base;
}
for (i = 0; i < MAX_ARG_PAGES; i++) {
if (bprm->page[i]) {
info->rss++;
if (!memcpy_to_target(stack_base, bprm->page[i],
TARGET_PAGE_SIZE)) {
errno = EFAULT;
return -1;
}
g_free(bprm->page[i]);
}
stack_base += TARGET_PAGE_SIZE;
}
return 0;
}
#endif /* !_TARGET_OS_STACK_H_ */

View File

@ -0,0 +1,25 @@
/*
* NetBSD thread dependent code and definitions
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_OS_THREAD_H_
#define _TARGET_OS_THREAD_H_
#include "target_arch_thread.h"
#endif /* !_TARGET_OS_THREAD_H_ */

View File

@ -0,0 +1,25 @@
/*
* OpenBSD host dependent code and definitions
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _HOST_OS_H_
#define _HOST_OS_H_
#define HOST_DEFAULT_BSD_TYPE target_openbsd
#endif /*!_HOST_OS_H_ */

View File

@ -0,0 +1,146 @@
/*
* openbsd ELF definitions
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_OS_ELF_H_
#define _TARGET_OS_ELF_H_
#include "target_arch_elf.h"
#include "elf.h"
/* this flag is uneffective under linux too, should be deleted */
#ifndef MAP_DENYWRITE
#define MAP_DENYWRITE 0
#endif
/* should probably go in elf.h */
#ifndef ELIBBAD
#define ELIBBAD 80
#endif
#ifndef ELF_PLATFORM
#define ELF_PLATFORM (NULL)
#endif
#ifndef ELF_HWCAP
#define ELF_HWCAP 0
#endif
#ifdef TARGET_ABI32
#undef ELF_CLASS
#define ELF_CLASS ELFCLASS32
#undef bswaptls
#define bswaptls(ptr) bswap32s(ptr)
#endif
/* max code+data+bss space allocated to elf interpreter */
#define INTERP_MAP_SIZE (32 * 1024 * 1024)
/* max code+data+bss+brk space allocated to ET_DYN executables */
#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
/* Necessary parameters */
#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
#define TARGET_ELF_PAGESTART(_v) ((_v) & \
~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE - 1))
#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE - 1))
#define DLINFO_ITEMS 12
static abi_ulong target_create_elf_tables(abi_ulong p, int argc, int envc,
abi_ulong stringp,
struct elfhdr *exec,
abi_ulong load_addr,
abi_ulong load_bias,
abi_ulong interp_load_addr,
struct image_info *info)
{
abi_ulong sp;
int size;
abi_ulong u_platform;
const char *k_platform;
const int n = sizeof(elf_addr_t);
sp = p;
u_platform = 0;
k_platform = ELF_PLATFORM;
if (k_platform) {
size_t len = strlen(k_platform) + 1;
sp -= (len + n - 1) & ~(n - 1);
u_platform = sp;
/* FIXME - check return value of memcpy_to_target() for failure */
memcpy_to_target(sp, k_platform, len);
}
/*
* Force 16 byte _final_ alignment here for generality.
*/
sp = sp & ~(abi_ulong)15;
size = (DLINFO_ITEMS + 1) * 2;
if (k_platform) {
size += 2;
}
#ifdef DLINFO_ARCH_ITEMS
size += DLINFO_ARCH_ITEMS * 2;
#endif
size += envc + argc + 2;
size += 1; /* argc itself */
size *= n;
if (size & 15) {
sp -= 16 - (size & 15);
}
/*
* OpenBSD defines elf_addr_t as Elf32_Off / Elf64_Off
*/
#define NEW_AUX_ENT(id, val) do { \
sp -= n; put_user_ual(val, sp); \
sp -= n; put_user_ual(id, sp); \
} while (0)
NEW_AUX_ENT(AT_NULL, 0);
/* There must be exactly DLINFO_ITEMS entries here. */
NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof(struct elf_phdr)));
NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
NEW_AUX_ENT(AT_UID, (abi_ulong)getuid());
NEW_AUX_ENT(AT_EUID, (abi_ulong)geteuid());
NEW_AUX_ENT(AT_GID, (abi_ulong)getgid());
NEW_AUX_ENT(AT_EGID, (abi_ulong)getegid());
NEW_AUX_ENT(AT_HWCAP, (abi_ulong)ELF_HWCAP);
NEW_AUX_ENT(AT_CLKTCK, (abi_ulong)sysconf(_SC_CLK_TCK));
if (k_platform) {
NEW_AUX_ENT(AT_PLATFORM, u_platform);
}
#ifdef ARCH_DLINFO
/*
* ARCH_DLINFO must come last so platform specific code can enforce
* special alignment requirements on the AUXV if necessary (eg. PPC).
*/
ARCH_DLINFO;
#endif
#undef NEW_AUX_ENT
sp = loader_build_argptr(envc, argc, sp, stringp);
return sp;
}
#endif /* _TARGET_OS_ELF_H_ */

View File

@ -0,0 +1,82 @@
#ifndef _TARGET_OS_SIGINFO_H_
#define _TARGET_OS_SIGINFO_H_
#define TARGET_NSIG 32 /* counting 0; could be 33 (mask is 1-32) */
#define TARGET_NSIG_BPW (sizeof(uint32_t) * 8)
#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
/* this struct defines a stack used during syscall handling */
typedef struct target_sigaltstack {
abi_long ss_sp;
abi_ulong ss_size;
abi_long ss_flags;
} target_stack_t;
typedef struct {
uint32_t __bits[TARGET_NSIG_WORDS];
} target_sigset_t
struct target_sigaction {
abi_ulong _sa_handler;
int32_t sa_flags;
target_sigset_t sa_mask;
};
/* Compare to sys/siginfo.h */
typedef union target_sigval {
int sival_int;
abi_ulong sival_ptr;
} target_sigval_t;
struct target_ksiginfo {
int32_t _signo;
int32_t _code;
int32_t _errno;
#if TARGET_ABI_BITS == 64
int32_t _pad;
#endif
union {
struct {
int32_t _pid;
int32_t _uid;
target_sigval_t _value;
} _rt;
struct {
int32_t _pid;
int32_t _uid;
int32_t _struct;
/* clock_t _utime; */
/* clock_t _stime; */
} _child;
struct {
abi_ulong _addr;
int32_t _trap;
} _fault;
struct {
long _band;
int _fd;
} _poll;
} _reason;
};
typedef union target_siginfo {
int8_t si_pad[128];
struct target_ksiginfo _info;
} target_siginfo_t;
#define target_si_signo _info._signo
#define target_si_code _info._code
#define target_si_errno _info._errno
#define target_si_addr _info._reason._fault._addr
#define TARGET_SEGV_MAPERR 1
#define TARGET_SEGV_ACCERR 2
#define TARGET_TRAP_BRKPT 1
#define TARGET_TRAP_TRACE 2
#endif /* ! _TARGET_OS_SIGINFO_H_ */

View File

@ -0,0 +1,69 @@
#ifndef _TARGET_OS_SIGNAL_H_
#define _TARGET_OS_SIGNAL_H_
#include "target_os_siginfo.h"
#include "target_arch_signal.h"
#define TARGET_SIGHUP 1 /* hangup */
#define TARGET_SIGINT 2 /* interrupt */
#define TARGET_SIGQUIT 3 /* quit */
#define TARGET_SIGILL 4 /* illegal instruction (not reset when caught) */
#define TARGET_SIGTRAP 5 /* trace trap (not reset when caught) */
#define TARGET_SIGABRT 6 /* abort() */
#define TARGET_SIGIOT SIGABRT /* compatibility */
#define TARGET_SIGEMT 7 /* EMT instruction */
#define TARGET_SIGFPE 8 /* floating point exception */
#define TARGET_SIGKILL 9 /* kill (cannot be caught or ignored) */
#define TARGET_SIGBUS 10 /* bus error */
#define TARGET_SIGSEGV 11 /* segmentation violation */
#define TARGET_SIGSYS 12 /* bad argument to system call */
#define TARGET_SIGPIPE 13 /* write on a pipe with no one to read it */
#define TARGET_SIGALRM 14 /* alarm clock */
#define TARGET_SIGTERM 15 /* software termination signal from kill */
#define TARGET_SIGURG 16 /* urgent condition on IO channel */
#define TARGET_SIGSTOP 17 /* sendable stop signal not from tty */
#define TARGET_SIGTSTP 18 /* stop signal from tty */
#define TARGET_SIGCONT 19 /* continue a stopped process */
#define TARGET_SIGCHLD 20 /* to parent on child stop or exit */
#define TARGET_SIGTTIN 21 /* to readers pgrp upon background tty read */
#define TARGET_SIGTTOU 22 /* like TTIN for out if (tp->t_local&LTOSTOP) */
#define TARGET_SIGIO 23 /* input/output possible signal */
#define TARGET_SIGXCPU 24 /* exceeded CPU time limit */
#define TARGET_SIGXFSZ 25 /* exceeded file size limit */
#define TARGET_SIGVTALRM 26 /* virtual time alarm */
#define TARGET_SIGPROF 27 /* profiling time alarm */
#define TARGET_SIGWINCH 28 /* window size changes */
#define TARGET_SIGINFO 29 /* information request */
#define TARGET_SIGUSR1 30 /* user defined signal 1 */
#define TARGET_SIGUSR2 31 /* user defined signal 2 */
/*
* Language spec says we must list exactly one parameter, even though we
* actually supply three. Ugh!
*/
#define TARGET_SIG_DFL ((void (*)(int))0)
#define TARGET_SIG_IGN ((void (*)(int))1)
#define TARGET_SIG_ERR ((void (*)(int))-1)
#define TARGET_SA_ONSTACK 0x0001 /* take signal on signal stack */
#define TARGET_SA_RESTART 0x0002 /* restart system on signal return */
#define TARGET_SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */
#define TARGET_SA_NODEFER 0x0010 /* don't mask the signal we're delivering */
#define TARGET_SA_NOCLDWAIT 0x0020 /* don't create zombies (assign to pid 1) */
#define TARGET_SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */
#define TARGET_SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */
#define TARGET_SA_SIGINFO 0x0040 /* generate siginfo_t */
/*
* Flags for sigprocmask:
*/
#define TARGET_SIG_BLOCK 1 /* block specified signal set */
#define TARGET_SIG_UNBLOCK 2 /* unblock specified signal set */
#define TARGET_SIG_SETMASK 3 /* set specified signal set */
#define TARGET_BADSIG SIG_ERR
#define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */
#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate stack */
#endif /* !_TARGET_OS_SIGNAL_H_ */

View File

@ -0,0 +1,56 @@
/*
* OpenBSD setup_initial_stack() implementation.
*
* Copyright (c) 2013-14 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_OS_STACK_H_
#define _TARGET_OS_STACK_H_
#include "target_arch_sigtramp.h"
static inline int setup_initial_stack(struct bsd_binprm *bprm, abi_ulong *p,
abi_ulong *stringp)
{
int i;
abi_ulong stack_base;
stack_base = (target_stkbas + target_stksiz) -
MAX_ARG_PAGES * TARGET_PAGE_SIZE;
if (p) {
*p = stack_base;
}
if (stringp) {
*stringp = stack_base;
}
for (i = 0; i < MAX_ARG_PAGES; i++) {
if (bprm->page[i]) {
info->rss++;
if (!memcpy_to_target(stack_base, bprm->page[i],
TARGET_PAGE_SIZE)) {
errno = EFAULT;
return -1;
}
g_free(bprm->page[i]);
}
stack_base += TARGET_PAGE_SIZE;
}
return 0;
}
#endif /* !_TARGET_OS_STACK_H_ */

View File

@ -0,0 +1,25 @@
/*
* OpenBSD thread dependent code and definitions
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_OS_THREAD_H_
#define _TARGET_OS_THREAD_H_
#include "target_arch_thread.h"
#endif /* !_TARGET_OS_THREAD_H_ */

View File

@ -18,12 +18,13 @@
#define QEMU_H #define QEMU_H
#include "qemu/osdep.h"
#include "cpu.h" #include "cpu.h"
#include "qemu/units.h"
#include "exec/cpu_ldst.h" #include "exec/cpu_ldst.h"
#include "exec/exec-all.h"
#undef DEBUG_REMAP #undef DEBUG_REMAP
#ifdef DEBUG_REMAP
#endif /* DEBUG_REMAP */
#include "exec/user/abitypes.h" #include "exec/user/abitypes.h"
@ -36,22 +37,21 @@ enum BSDType {
}; };
extern enum BSDType bsd_type; extern enum BSDType bsd_type;
#include "exec/user/thunk.h"
#include "target_arch.h"
#include "syscall_defs.h" #include "syscall_defs.h"
#include "target_syscall.h" #include "target_syscall.h"
#include "target_os_vmparam.h"
#include "target_os_signal.h"
#include "exec/gdbstub.h" #include "exec/gdbstub.h"
#if defined(CONFIG_USE_NPTL)
#define THREAD __thread
#else
#define THREAD
#endif
/* /*
* This struct is used to hold certain information about the image. Basically, * This struct is used to hold certain information about the image. Basically,
* it replicates in user space what would be certain task_struct fields in the * it replicates in user space what would be certain task_struct fields in the
* kernel * kernel
*/ */
struct image_info { struct image_info {
abi_ulong load_bias;
abi_ulong load_addr; abi_ulong load_addr;
abi_ulong start_code; abi_ulong start_code;
abi_ulong end_code; abi_ulong end_code;
@ -66,7 +66,9 @@ struct image_info {
abi_ulong entry; abi_ulong entry;
abi_ulong code_offset; abi_ulong code_offset;
abi_ulong data_offset; abi_ulong data_offset;
int personality; abi_ulong arg_start;
abi_ulong arg_end;
uint32_t elf_flags;
}; };
#define MAX_SIGQUEUE_SIZE 1024 #define MAX_SIGQUEUE_SIZE 1024
@ -89,6 +91,7 @@ typedef struct TaskState {
pid_t ts_tid; /* tid (or pid) of this task */ pid_t ts_tid; /* tid (or pid) of this task */
struct TaskState *next; struct TaskState *next;
struct bsd_binprm *bprm;
int used; /* non zero if used */ int used; /* non zero if used */
struct image_info *info; struct image_info *info;
@ -102,14 +105,19 @@ typedef struct TaskState {
void init_task_state(TaskState *ts); void init_task_state(TaskState *ts);
extern const char *qemu_uname_release; extern const char *qemu_uname_release;
extern unsigned long mmap_min_addr;
/* /*
* MAX_ARG_PAGES defines the number of pages allocated for arguments * TARGET_ARG_MAX defines the number of bytes allocated for arguments
* and envelope for the new program. 32 should suffice, this gives * and envelope for the new program. 256k should suffice for a reasonable
* a maximum env+arg of 128kB w/4KB pages! * maxiumum env+arg in 32-bit environments, bump it up to 512k for !ILP32
* platforms.
*/ */
#define MAX_ARG_PAGES 32 #if TARGET_ABI_BITS > 32
#define TARGET_ARG_MAX (512 * KiB)
#else
#define TARGET_ARG_MAX (256 * KiB)
#endif
#define MAX_ARG_PAGES (TARGET_ARG_MAX / TARGET_PAGE_SIZE)
/* /*
* This structure is used to hold the arguments that are * This structure is used to hold the arguments that are
@ -119,24 +127,29 @@ struct bsd_binprm {
char buf[128]; char buf[128];
void *page[MAX_ARG_PAGES]; void *page[MAX_ARG_PAGES];
abi_ulong p; abi_ulong p;
abi_ulong stringp;
int fd; int fd;
int e_uid, e_gid; int e_uid, e_gid;
int argc, envc; int argc, envc;
char **argv; char **argv;
char **envp; char **envp;
char *filename; /* Name of binary */ char *filename; /* (Given) Name of binary */
char *fullpath; /* Full path of binary */
int (*core_dump)(int, CPUArchState *);
}; };
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop); void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
abi_ulong stringp, int push_ptr); abi_ulong stringp);
int loader_exec(const char *filename, char **argv, char **envp, int loader_exec(const char *filename, char **argv, char **envp,
struct target_pt_regs *regs, struct image_info *infop); struct target_pt_regs *regs, struct image_info *infop,
struct bsd_binprm *bprm);
int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs, int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
struct image_info *info); struct image_info *info);
int load_flt_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs, int load_flt_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
struct image_info *info); struct image_info *info);
int is_target_elf_binary(int fd);
abi_long memcpy_to_target(abi_ulong dest, const void *src, abi_long memcpy_to_target(abi_ulong dest, const void *src,
unsigned long len); unsigned long len);
@ -154,7 +167,7 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg2, abi_long arg3, abi_long arg4,
abi_long arg5, abi_long arg6); abi_long arg5, abi_long arg6);
void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2); void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
extern THREAD CPUState *thread_cpu; extern __thread CPUState *thread_cpu;
void cpu_loop(CPUArchState *env); void cpu_loop(CPUArchState *env);
char *target_strerror(int err); char *target_strerror(int err);
int get_osversion(void); int get_osversion(void);
@ -201,18 +214,26 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
/* mmap.c */ /* mmap.c */
int target_mprotect(abi_ulong start, abi_ulong len, int prot); int target_mprotect(abi_ulong start, abi_ulong len, int prot);
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
int flags, int fd, abi_ulong offset); int flags, int fd, off_t offset);
int target_munmap(abi_ulong start, abi_ulong len); int target_munmap(abi_ulong start, abi_ulong len);
abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
abi_ulong new_size, unsigned long flags, abi_ulong new_size, unsigned long flags,
abi_ulong new_addr); abi_ulong new_addr);
int target_msync(abi_ulong start, abi_ulong len, int flags); int target_msync(abi_ulong start, abi_ulong len, int flags);
extern unsigned long last_brk; extern unsigned long last_brk;
extern abi_ulong mmap_next_start;
abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size);
void mmap_fork_start(void); void mmap_fork_start(void);
void mmap_fork_end(int child); void mmap_fork_end(int child);
/* main.c */ /* main.c */
extern unsigned long x86_stack_size; extern char qemu_proc_pathname[];
extern unsigned long target_maxtsiz;
extern unsigned long target_dfldsiz;
extern unsigned long target_maxdsiz;
extern unsigned long target_dflssiz;
extern unsigned long target_maxssiz;
extern unsigned long target_sgrowsiz;
/* user access */ /* user access */
@ -421,8 +442,6 @@ static inline void *lock_user_string(abi_ulong guest_addr)
#define unlock_user_struct(host_ptr, guest_addr, copy) \ #define unlock_user_struct(host_ptr, guest_addr, copy) \
unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0) unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
#if defined(CONFIG_USE_NPTL)
#include <pthread.h> #include <pthread.h>
#endif
#endif /* QEMU_H */ #endif /* QEMU_H */

View File

@ -1,52 +0,0 @@
/*
* SPARC sysarch() system call emulation
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BSD_USER_ARCH_SYSARCH_H_
#define BSD_USER_ARCH_SYSARCH_H_
#include "target_syscall.h"
static inline abi_long do_freebsd_arch_sysarch(void *env, int op,
abi_ulong parms)
{
int ret = 0;
switch (op) {
case TARGET_SPARC_SIGTRAMP_INSTALL:
/* XXX not currently handled */
case TARGET_SPARC_UTRAP_INSTALL:
/* XXX not currently handled */
default:
ret = -TARGET_EINVAL;
break;
}
return ret;
}
static inline void do_freebsd_arch_print_sysarch(
const struct syscallname *name, abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
{
gemu_log("%s(%d, " TARGET_ABI_FMT_lx ", " TARGET_ABI_FMT_lx ", "
TARGET_ABI_FMT_lx ")", name->name, (int)arg1, arg2, arg3, arg4);
}
#endif /*!BSD_USER_ARCH_SYSARCH_H_ */

View File

@ -1,52 +0,0 @@
/*
* SPARC64 sysarch() system call emulation
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BSD_USER_ARCH_SYSARCH_H_
#define BSD_USER_ARCH_SYSARCH_H_
#include "target_syscall.h"
static inline abi_long do_freebsd_arch_sysarch(void *env, int op,
abi_ulong parms)
{
int ret = 0;
switch (op) {
case TARGET_SPARC_SIGTRAMP_INSTALL:
/* XXX not currently handled */
case TARGET_SPARC_UTRAP_INSTALL:
/* XXX not currently handled */
default:
ret = -TARGET_EINVAL;
break;
}
return ret;
}
static inline void do_freebsd_arch_print_sysarch(
const struct syscallname *name, abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
{
gemu_log("%s(%d, " TARGET_ABI_FMT_lx ", " TARGET_ABI_FMT_lx ", "
TARGET_ABI_FMT_lx ")", name->name, (int)arg1, arg2, arg3, arg4);
}
#endif /*!BSD_USER_ARCH_SYSARCH_H_ */

View File

@ -138,17 +138,6 @@ static abi_long do_freebsd_sysarch(CPUX86State *env, int op, abi_ulong parms)
} }
#endif #endif
#ifdef TARGET_SPARC
static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
{
/* XXX handle
* TARGET_FREEBSD_SPARC_UTRAP_INSTALL,
* TARGET_FREEBSD_SPARC_SIGTRAMP_INSTALL
*/
return -TARGET_EINVAL;
}
#endif
#ifdef __FreeBSD__ #ifdef __FreeBSD__
/* /*
* XXX this uses the undocumented oidfmt interface to find the kind of * XXX this uses the undocumented oidfmt interface to find the kind of

View File

@ -1,105 +1,26 @@
/* $OpenBSD: signal.h,v 1.19 2006/01/08 14:20:16 millert Exp $ */
/* $NetBSD: signal.h,v 1.21 1996/02/09 18:25:32 christos Exp $ */
/* /*
* Copyright (c) 1982, 1986, 1989, 1991, 1993 * System call related declarations
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
* *
* Redistribution and use in source and binary forms, with or without * Copyright (c) 2013-15 Stacey D. Son (sson at FreeBSD)
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * This program is free software; you can redistribute it and/or modify
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * it under the terms of the GNU General Public License as published by
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * the Free Software Foundation; either version 2 of the License, or
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * (at your option) any later version.
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* *
* @(#)signal.h 8.2 (Berkeley) 1/21/94 * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
#define TARGET_NSIG 32 /* counting 0; could be 33 (mask is 1-32) */ #ifndef _SYSCALL_DEFS_H_
#define _SYSCALL_DEFS_H_
#define TARGET_SIGHUP 1 /* hangup */ #include <sys/syscall.h>
#define TARGET_SIGINT 2 /* interrupt */
#define TARGET_SIGQUIT 3 /* quit */
#define TARGET_SIGILL 4 /* illegal instruction (not reset when caught) */
#define TARGET_SIGTRAP 5 /* trace trap (not reset when caught) */
#define TARGET_SIGABRT 6 /* abort() */
#define TARGET_SIGIOT SIGABRT /* compatibility */
#define TARGET_SIGEMT 7 /* EMT instruction */
#define TARGET_SIGFPE 8 /* floating point exception */
#define TARGET_SIGKILL 9 /* kill (cannot be caught or ignored) */
#define TARGET_SIGBUS 10 /* bus error */
#define TARGET_SIGSEGV 11 /* segmentation violation */
#define TARGET_SIGSYS 12 /* bad argument to system call */
#define TARGET_SIGPIPE 13 /* write on a pipe with no one to read it */
#define TARGET_SIGALRM 14 /* alarm clock */
#define TARGET_SIGTERM 15 /* software termination signal from kill */
#define TARGET_SIGURG 16 /* urgent condition on IO channel */
#define TARGET_SIGSTOP 17 /* sendable stop signal not from tty */
#define TARGET_SIGTSTP 18 /* stop signal from tty */
#define TARGET_SIGCONT 19 /* continue a stopped process */
#define TARGET_SIGCHLD 20 /* to parent on child stop or exit */
#define TARGET_SIGTTIN 21 /* to readers pgrp upon background tty read */
#define TARGET_SIGTTOU 22 /* like TTIN for output if (tp->t_local&LTOSTOP) */
#define TARGET_SIGIO 23 /* input/output possible signal */
#define TARGET_SIGXCPU 24 /* exceeded CPU time limit */
#define TARGET_SIGXFSZ 25 /* exceeded file size limit */
#define TARGET_SIGVTALRM 26 /* virtual time alarm */
#define TARGET_SIGPROF 27 /* profiling time alarm */
#define TARGET_SIGWINCH 28 /* window size changes */
#define TARGET_SIGINFO 29 /* information request */
#define TARGET_SIGUSR1 30 /* user defined signal 1 */
#define TARGET_SIGUSR2 31 /* user defined signal 2 */
/*
* Language spec says we must list exactly one parameter, even though we
* actually supply three. Ugh!
*/
#define TARGET_SIG_DFL (void (*)(int))0
#define TARGET_SIG_IGN (void (*)(int))1
#define TARGET_SIG_ERR (void (*)(int))-1
#define TARGET_SA_ONSTACK 0x0001 /* take signal on signal stack */
#define TARGET_SA_RESTART 0x0002 /* restart system on signal return */
#define TARGET_SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */
#define TARGET_SA_NODEFER 0x0010 /* don't mask the signal we're delivering */
#define TARGET_SA_NOCLDWAIT 0x0020 /* don't create zombies (assign to pid 1) */
#define TARGET_SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */
#define TARGET_SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */
#define TARGET_SA_SIGINFO 0x0040 /* generate siginfo_t */
/*
* Flags for sigprocmask:
*/
#define TARGET_SIG_BLOCK 1 /* block specified signal set */
#define TARGET_SIG_UNBLOCK 2 /* unblock specified signal set */
#define TARGET_SIG_SETMASK 3 /* set specified signal set */
#define TARGET_BADSIG SIG_ERR
#define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */
#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate stack */
#include "errno_defs.h" #include "errno_defs.h"
@ -107,8 +28,154 @@
#include "netbsd/syscall_nr.h" #include "netbsd/syscall_nr.h"
#include "openbsd/syscall_nr.h" #include "openbsd/syscall_nr.h"
/*
* machine/_types.h
* or x86/_types.h
*/
/*
* time_t seems to be very inconsistly defined for the different *BSD's...
*
* FreeBSD uses a 64bits time_t except on i386
* so we have to add a special case here.
*
* On NetBSD time_t is always defined as an int64_t. On OpenBSD time_t
* is always defined as an int.
*
*/
#if (!defined(TARGET_I386))
typedef int64_t target_freebsd_time_t;
#else
typedef int32_t target_freebsd_time_t;
#endif
struct target_iovec { struct target_iovec {
abi_long iov_base; /* Starting address */ abi_long iov_base; /* Starting address */
abi_long iov_len; /* Number of bytes */ abi_long iov_len; /* Number of bytes */
}; };
/*
* sys/mman.h
*/
#define TARGET_FREEBSD_MAP_RESERVED0080 0x0080 /* previously misimplemented */
/* MAP_INHERIT */
#define TARGET_FREEBSD_MAP_RESERVED0100 0x0100 /* previously unimplemented */
/* MAP_NOEXTEND */
#define TARGET_FREEBSD_MAP_STACK 0x0400 /* region grows down, like a */
/* stack */
#define TARGET_FREEBSD_MAP_NOSYNC 0x0800 /* page to but do not sync */
/* underlying file */
#define TARGET_FREEBSD_MAP_FLAGMASK 0x1ff7
#define TARGET_NETBSD_MAP_INHERIT 0x0080 /* region is retained after */
/* exec */
#define TARGET_NETBSD_MAP_TRYFIXED 0x0400 /* attempt hint address, even */
/* within break */
#define TARGET_NETBSD_MAP_WIRED 0x0800 /* mlock() mapping when it is */
/* established */
#define TARGET_NETBSD_MAP_STACK 0x2000 /* allocated from memory, */
/* swap space (stack) */
#define TARGET_NETBSD_MAP_FLAGMASK 0x3ff7
#define TARGET_OPENBSD_MAP_INHERIT 0x0080 /* region is retained after */
/* exec */
#define TARGET_OPENBSD_MAP_NOEXTEND 0x0100 /* for MAP_FILE, don't change */
/* file size */
#define TARGET_OPENBSD_MAP_TRYFIXED 0x0400 /* attempt hint address, */
/* even within heap */
#define TARGET_OPENBSD_MAP_FLAGMASK 0x17f7
/* XXX */
#define TARGET_BSD_MAP_FLAGMASK 0x3ff7
/*
* sys/time.h
* sys/timex.h
*/
typedef abi_long target_freebsd_suseconds_t;
/* compare to sys/timespec.h */
struct target_freebsd_timespec {
target_freebsd_time_t tv_sec; /* seconds */
abi_long tv_nsec; /* and nanoseconds */
#if !defined(TARGET_I386) && TARGET_ABI_BITS == 32
abi_long _pad;
#endif
};
#define TARGET_CPUCLOCK_WHICH_PID 0
#define TARGET_CPUCLOCK_WHICH_TID 1
/* sys/umtx.h */
struct target_freebsd__umtx_time {
struct target_freebsd_timespec _timeout;
uint32_t _flags;
uint32_t _clockid;
};
struct target_freebsd_timeval {
target_freebsd_time_t tv_sec; /* seconds */
target_freebsd_suseconds_t tv_usec;/* and microseconds */
#if !defined(TARGET_I386) && TARGET_ABI_BITS == 32
abi_long _pad;
#endif
};
/*
* sys/resource.h
*/
#if defined(__FreeBSD__)
#define TARGET_RLIM_INFINITY RLIM_INFINITY
#else
#define TARGET_RLIM_INFINITY ((abi_ulong)-1)
#endif
#define TARGET_RLIMIT_CPU 0
#define TARGET_RLIMIT_FSIZE 1
#define TARGET_RLIMIT_DATA 2
#define TARGET_RLIMIT_STACK 3
#define TARGET_RLIMIT_CORE 4
#define TARGET_RLIMIT_RSS 5
#define TARGET_RLIMIT_MEMLOCK 6
#define TARGET_RLIMIT_NPROC 7
#define TARGET_RLIMIT_NOFILE 8
#define TARGET_RLIMIT_SBSIZE 9
#define TARGET_RLIMIT_AS 10
#define TARGET_RLIMIT_NPTS 11
#define TARGET_RLIMIT_SWAP 12
struct target_rlimit {
uint64_t rlim_cur;
uint64_t rlim_max;
};
struct target_freebsd_rusage {
struct target_freebsd_timeval ru_utime; /* user time used */
struct target_freebsd_timeval ru_stime; /* system time used */
abi_long ru_maxrss; /* maximum resident set size */
abi_long ru_ixrss; /* integral shared memory size */
abi_long ru_idrss; /* integral unshared data size */
abi_long ru_isrss; /* integral unshared stack size */
abi_long ru_minflt; /* page reclaims */
abi_long ru_majflt; /* page faults */
abi_long ru_nswap; /* swaps */
abi_long ru_inblock; /* block input operations */
abi_long ru_oublock; /* block output operations */
abi_long ru_msgsnd; /* messages sent */
abi_long ru_msgrcv; /* messages received */
abi_long ru_nsignals; /* signals received */
abi_long ru_nvcsw; /* voluntary context switches */
abi_long ru_nivcsw; /* involuntary context switches */
};
struct target_freebsd__wrusage {
struct target_freebsd_rusage wru_self;
struct target_freebsd_rusage wru_children;
};
#endif /* ! _SYSCALL_DEFS_H_ */

View File

@ -1,6 +1,7 @@
/* /*
* sparc64 dependent system call definitions * Intel x86_64 specific prototypes for bsd-user
* *
* Copyright (c) 2013 Stacey D. Son
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -15,23 +16,16 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef TARGET_SYSCALL_H
#define TARGET_SYSCALL_H
struct target_pt_regs { #ifndef _TARGET_ARCH_H_
abi_ulong u_regs[16]; #define _TARGET_ARCH_H_
abi_ulong tstate;
abi_ulong pc;
abi_ulong npc;
abi_ulong y;
abi_ulong fprs;
};
#define UNAME_MACHINE "sun4u" /* target_arch_cpu.c */
#define TARGET_HW_MACHINE "sparc" void bsd_x86_64_write_dt(void *ptr, unsigned long addr, unsigned long limit,
#define TARGET_HW_MACHINE_ARCH "sparc64" int flags);
void bsd_x86_64_set_idt(int n, unsigned int dpl);
void bsd_x86_64_set_idt_base(uint64_t base);
#define TARGET_SPARC_UTRAP_INSTALL 1 #define target_cpu_set_tls(env, newtls)
#define TARGET_SPARC_SIGTRAMP_INSTALL 2
#endif /* TARGET_SYSCALL_H */ #endif /* !_TARGET_ARCH_H_ */

View File

@ -0,0 +1,76 @@
/*
* x86_64 cpu related code
*
* Copyright (c) 2013 Stacey Son <sson@FreeBSD.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/types.h>
#include "qemu/osdep.h"
#include "cpu.h"
#include "qemu.h"
#include "qemu/timer.h"
#include "target_arch.h"
static uint64_t *idt_table;
uint64_t cpu_get_tsc(CPUX86State *env)
{
return cpu_get_host_ticks();
}
int cpu_get_pic_interrupt(CPUX86State *env)
{
return -1;
}
void bsd_x86_64_write_dt(void *ptr, unsigned long addr,
unsigned long limit, int flags)
{
unsigned int e1, e2;
uint32_t *p;
e1 = (addr << 16) | (limit & 0xffff);
e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
e2 |= flags;
p = ptr;
p[0] = tswap32(e1);
p[1] = tswap32(e2);
}
static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
uint64_t addr, unsigned int sel)
{
uint32_t *p, e1, e2;
e1 = (addr & 0xffff) | (sel << 16);
e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
p = ptr;
p[0] = tswap32(e1);
p[1] = tswap32(e2);
p[2] = tswap32(addr >> 32);
p[3] = 0;
}
/* only dpl matters as we do only user space emulation */
void bsd_x86_64_set_idt(int n, unsigned int dpl)
{
set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
}
void bsd_x86_64_set_idt_base(uint64_t base)
{
idt_table = g2h_untagged(base);
}

View File

@ -0,0 +1,247 @@
/*
* x86_64 cpu init and loop
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_ARCH_CPU_H_
#define _TARGET_ARCH_CPU_H_
#include "target_arch.h"
#define TARGET_DEFAULT_CPU_MODEL "qemu64"
#define TARGET_CPU_RESET(cpu)
static inline void target_cpu_init(CPUX86State *env,
struct target_pt_regs *regs)
{
uint64_t *gdt_table;
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
env->hflags |= HF_PE_MASK | HF_CPL_MASK;
if (env->features[FEAT_1_EDX] & CPUID_SSE) {
env->cr[4] |= CR4_OSFXSR_MASK;
env->hflags |= HF_OSFXSR_MASK;
}
/* enable 64 bit mode if possible */
if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
exit(1);
}
env->cr[4] |= CR4_PAE_MASK;
env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
env->hflags |= HF_LMA_MASK;
/* flags setup : we activate the IRQs by default as in user mode */
env->eflags |= IF_MASK;
/* register setup */
env->regs[R_EAX] = regs->rax;
env->regs[R_EBX] = regs->rbx;
env->regs[R_ECX] = regs->rcx;
env->regs[R_EDX] = regs->rdx;
env->regs[R_ESI] = regs->rsi;
env->regs[R_EDI] = regs->rdi;
env->regs[R_EBP] = regs->rbp;
env->regs[R_ESP] = regs->rsp;
env->eip = regs->rip;
/* interrupt setup */
env->idt.limit = 511;
env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
bsd_x86_64_set_idt_base(env->idt.base);
bsd_x86_64_set_idt(0, 0);
bsd_x86_64_set_idt(1, 0);
bsd_x86_64_set_idt(2, 0);
bsd_x86_64_set_idt(3, 3);
bsd_x86_64_set_idt(4, 3);
bsd_x86_64_set_idt(5, 0);
bsd_x86_64_set_idt(6, 0);
bsd_x86_64_set_idt(7, 0);
bsd_x86_64_set_idt(8, 0);
bsd_x86_64_set_idt(9, 0);
bsd_x86_64_set_idt(10, 0);
bsd_x86_64_set_idt(11, 0);
bsd_x86_64_set_idt(12, 0);
bsd_x86_64_set_idt(13, 0);
bsd_x86_64_set_idt(14, 0);
bsd_x86_64_set_idt(15, 0);
bsd_x86_64_set_idt(16, 0);
bsd_x86_64_set_idt(17, 0);
bsd_x86_64_set_idt(18, 0);
bsd_x86_64_set_idt(19, 0);
bsd_x86_64_set_idt(0x80, 3);
/* segment setup */
env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
gdt_table = g2h_untagged(env->gdt.base);
/* 64 bit code segment */
bsd_x86_64_write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | DESC_L_MASK
| (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
bsd_x86_64_write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
(3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
cpu_x86_load_seg(env, R_CS, __USER_CS);
cpu_x86_load_seg(env, R_SS, __USER_DS);
cpu_x86_load_seg(env, R_DS, 0);
cpu_x86_load_seg(env, R_ES, 0);
cpu_x86_load_seg(env, R_FS, 0);
cpu_x86_load_seg(env, R_GS, 0);
}
static inline void target_cpu_loop(CPUX86State *env)
{
CPUState *cs = env_cpu(env);
int trapnr;
abi_ulong pc;
/* target_siginfo_t info; */
for (;;) {
cpu_exec_start(cs);
trapnr = cpu_exec(cs);
cpu_exec_end(cs);
process_queued_cpu_work(cs);
switch (trapnr) {
case 0x80:
/* syscall from int $0x80 */
if (bsd_type == target_freebsd) {
abi_ulong params = (abi_ulong) env->regs[R_ESP] +
sizeof(int32_t);
int32_t syscall_nr = env->regs[R_EAX];
int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
get_user_s32(syscall_nr, params);
params += sizeof(int32_t);
} else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
get_user_s32(syscall_nr, params);
params += sizeof(int64_t);
}
get_user_s32(arg1, params);
params += sizeof(int32_t);
get_user_s32(arg2, params);
params += sizeof(int32_t);
get_user_s32(arg3, params);
params += sizeof(int32_t);
get_user_s32(arg4, params);
params += sizeof(int32_t);
get_user_s32(arg5, params);
params += sizeof(int32_t);
get_user_s32(arg6, params);
params += sizeof(int32_t);
get_user_s32(arg7, params);
params += sizeof(int32_t);
get_user_s32(arg8, params);
env->regs[R_EAX] = do_freebsd_syscall(env,
syscall_nr,
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8);
} else { /* if (bsd_type == target_openbsd) */
env->regs[R_EAX] = do_openbsd_syscall(env,
env->regs[R_EAX],
env->regs[R_EBX],
env->regs[R_ECX],
env->regs[R_EDX],
env->regs[R_ESI],
env->regs[R_EDI],
env->regs[R_EBP]);
}
if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
env->regs[R_EAX] = -env->regs[R_EAX];
env->eflags |= CC_C;
} else {
env->eflags &= ~CC_C;
}
break;
case EXCP_SYSCALL:
/* syscall from syscall instruction */
if (bsd_type == target_freebsd) {
env->regs[R_EAX] = do_freebsd_syscall(env,
env->regs[R_EAX],
env->regs[R_EDI],
env->regs[R_ESI],
env->regs[R_EDX],
env->regs[R_ECX],
env->regs[8],
env->regs[9], 0, 0);
} else { /* if (bsd_type == target_openbsd) */
env->regs[R_EAX] = do_openbsd_syscall(env,
env->regs[R_EAX],
env->regs[R_EDI],
env->regs[R_ESI],
env->regs[R_EDX],
env->regs[10],
env->regs[8],
env->regs[9]);
}
env->eip = env->exception_next_eip;
if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
env->regs[R_EAX] = -env->regs[R_EAX];
env->eflags |= CC_C;
} else {
env->eflags &= ~CC_C;
}
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
break;
default:
pc = env->segs[R_CS].base + env->eip;
fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - "
"aborting\n", (long)pc, trapnr);
abort();
}
process_pending_signals(env);
}
}
static inline void target_cpu_clone_regs(CPUX86State *env, target_ulong newsp)
{
if (newsp) {
env->regs[R_ESP] = newsp;
}
env->regs[R_EAX] = 0;
}
static inline void target_cpu_reset(CPUArchState *cpu)
{
cpu_reset(env_cpu(cpu));
}
#endif /* ! _TARGET_ARCH_CPU_H_ */

View File

@ -0,0 +1,35 @@
/*
* x86_64 ELF definitions
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_ARCH_ELF_H_
#define _TARGET_ARCH_ELF_H_
#define ELF_START_MMAP 0x2aaaaab000ULL
#define ELF_ET_DYN_LOAD_ADDR 0x01021000
#define elf_check_arch(x) (((x) == ELF_ARCH))
#define ELF_HWCAP 0 /* FreeBSD doesn't do AT_HWCAP{,2} on x86 */
#define ELF_CLASS ELFCLASS64
#define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_X86_64
#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
#endif /* _TARGET_ARCH_ELF_H_ */

View File

@ -0,0 +1,92 @@
/*
* FreeBSD amd64 register structures
*
* Copyright (c) 2015 Stacey Son
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_ARCH_REG_H_
#define _TARGET_ARCH_REG_H_
/* See sys/amd64/include/reg.h */
typedef struct target_reg {
uint64_t r_r15;
uint64_t r_r14;
uint64_t r_r13;
uint64_t r_r12;
uint64_t r_r11;
uint64_t r_r10;
uint64_t r_r9;
uint64_t r_r8;
uint64_t r_rdi;
uint64_t r_rsi;
uint64_t r_rbp;
uint64_t r_rbx;
uint64_t r_rdx;
uint64_t r_rcx;
uint64_t r_rax;
uint32_t r_trapno;
uint16_t r_fs;
uint16_t r_gs;
uint32_t r_err;
uint16_t r_es;
uint16_t r_ds;
uint64_t r_rip;
uint64_t r_cs;
uint64_t r_rflags;
uint64_t r_rsp;
uint64_t r_ss;
} target_reg_t;
typedef struct target_fpreg {
uint64_t fpr_env[4];
uint8_t fpr_acc[8][16];
uint8_t fpr_xacc[16][16];
uint64_t fpr_spare[12];
} target_fpreg_t;
static inline void target_copy_regs(target_reg_t *regs, const CPUX86State *env)
{
regs->r_r15 = env->regs[15];
regs->r_r14 = env->regs[14];
regs->r_r13 = env->regs[13];
regs->r_r12 = env->regs[12];
regs->r_r11 = env->regs[11];
regs->r_r10 = env->regs[10];
regs->r_r9 = env->regs[9];
regs->r_r8 = env->regs[8];
regs->r_rdi = env->regs[R_EDI];
regs->r_rsi = env->regs[R_ESI];
regs->r_rbp = env->regs[R_EBP];
regs->r_rbx = env->regs[R_EBX];
regs->r_rdx = env->regs[R_EDX];
regs->r_rcx = env->regs[R_ECX];
regs->r_rax = env->regs[R_EAX];
/* regs->r_trapno = env->regs[R_TRAPNO]; XXX */
regs->r_fs = env->segs[R_FS].selector & 0xffff;
regs->r_gs = env->segs[R_GS].selector & 0xffff;
regs->r_err = env->error_code; /* XXX ? */
regs->r_es = env->segs[R_ES].selector & 0xffff;
regs->r_ds = env->segs[R_DS].selector & 0xffff;
regs->r_rip = env->eip;
regs->r_cs = env->segs[R_CS].selector & 0xffff;
regs->r_rflags = env->eflags;
regs->r_rsp = env->regs[R_ESP];
regs->r_ss = env->segs[R_SS].selector & 0xffff;
}
#endif /* !_TARGET_ARCH_REG_H_ */

View File

@ -0,0 +1,94 @@
/*
* x86_64 signal definitions
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_ARCH_SIGNAL_H_
#define _TARGET_ARCH_SIGNAL_H_
#include "cpu.h"
/* Size of the signal trampolin code placed on the stack. */
#define TARGET_SZSIGCODE 0
/* compare to x86/include/_limits.h */
#define TARGET_MINSIGSTKSZ (512 * 4) /* min sig stack size */
#define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */
#define TARGET_MC_GET_CLEAR_RET 0x0001
struct target_sigcontext {
/* to be added */
};
typedef struct target_mcontext {
} target_mcontext_t;
typedef struct target_ucontext {
target_sigset_t uc_sigmask;
target_mcontext_t uc_mcontext;
abi_ulong uc_link;
target_stack_t uc_stack;
int32_t uc_flags;
int32_t __spare__[4];
} target_ucontext_t;
struct target_sigframe {
abi_ulong sf_signum;
abi_ulong sf_siginfo; /* code or pointer to sf_si */
abi_ulong sf_ucontext; /* points to sf_uc */
abi_ulong sf_addr; /* undocumented 4th arg */
target_ucontext_t sf_uc; /* = *sf_uncontext */
target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/
uint32_t __spare__[2];
};
/*
* Compare to amd64/amd64/machdep.c sendsig()
* Assumes that target stack frame memory is locked.
*/
static inline abi_long set_sigtramp_args(CPUX86State *regs,
int sig, struct target_sigframe *frame, abi_ulong frame_addr,
struct target_sigaction *ka)
{
/* XXX return -TARGET_EOPNOTSUPP; */
return 0;
}
/* Compare to amd64/amd64/machdep.c get_mcontext() */
static inline abi_long get_mcontext(CPUX86State *regs,
target_mcontext_t *mcp, int flags)
{
/* XXX */
return -TARGET_EOPNOTSUPP;
}
/* Compare to amd64/amd64/machdep.c set_mcontext() */
static inline abi_long set_mcontext(CPUX86State *regs,
target_mcontext_t *mcp, int srflag)
{
/* XXX */
return -TARGET_EOPNOTSUPP;
}
static inline abi_long get_ucontext_sigreturn(CPUX86State *regs,
abi_ulong target_sf, abi_ulong *target_uc)
{
/* XXX */
*target_uc = 0;
return -TARGET_EOPNOTSUPP;
}
#endif /* !TARGET_ARCH_SIGNAL_H_ */

View File

@ -0,0 +1,29 @@
/*
* Intel x86_64 sigcode for bsd-user
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_ARCH_SIGTRAMP_H_
#define _TARGET_ARCH_SIGTRAMP_H_
static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
unsigned sys_sigreturn)
{
return 0;
}
#endif /* _TARGET_ARCH_SIGTRAMP_H_ */

View File

@ -0,0 +1,40 @@
/*
* x86_64 thread support
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_ARCH_THREAD_H_
#define _TARGET_ARCH_THREAD_H_
/* Compare to vm_machdep.c cpu_set_upcall_kse() */
static inline void target_thread_set_upcall(CPUX86State *regs, abi_ulong entry,
abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size)
{
/* XXX */
}
static inline void target_thread_init(struct target_pt_regs *regs,
struct image_info *infop)
{
regs->rax = 0;
regs->rsp = infop->start_stack;
regs->rip = infop->entry;
if (bsd_type == target_freebsd) {
regs->rdi = infop->start_stack;
}
}
#endif /* !_TARGET_ARCH_THREAD_H_ */

View File

@ -0,0 +1,46 @@
/*
* Intel x86_64 VM parameters definitions
*
* Copyright (c) 2013 Stacey D. Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TARGET_ARCH_VMPARAM_H_
#define _TARGET_ARCH_VMPARAM_H_
#include "cpu.h"
/* compare to amd64/include/vmparam.h */
#define TARGET_MAXTSIZ (128 * MiB) /* max text size */
#define TARGET_DFLDSIZ (32 * GiB) /* initial data size limit */
#define TARGET_MAXDSIZ (32 * GiB) /* max data size */
#define TARGET_DFLSSIZ (8 * MiB) /* initial stack size limit */
#define TARGET_MAXSSIZ (512 * MiB) /* max stack size */
#define TARGET_SGROWSIZ (128 * KiB) /* amount to grow stack */
#define TARGET_VM_MAXUSER_ADDRESS (0x00007fffff000000UL)
#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
{
return state->regs[R_ESP];
}
static inline void set_second_rval(CPUX86State *state, abi_ulong retval2)
{
state->regs[R_EDX] = retval2;
}
#endif /* !_TARGET_ARCH_VMPARAM_H_ */

7
configure vendored
View File

@ -721,6 +721,7 @@ GNU/kFreeBSD)
;; ;;
FreeBSD) FreeBSD)
bsd="yes" bsd="yes"
bsd_user="yes"
make="${MAKE-gmake}" make="${MAKE-gmake}"
audio_drv_list="oss try-sdl" audio_drv_list="oss try-sdl"
audio_possible_drivers="oss sdl pa" audio_possible_drivers="oss sdl pa"
@ -782,12 +783,6 @@ Linux)
;; ;;
esac esac
if [ "$bsd" = "yes" ] ; then
if [ "$darwin" != "yes" ] ; then
bsd_user="yes"
fi
fi
: ${make=${MAKE-make}} : ${make=${MAKE-make}}
# We prefer python 3.x. A bare 'python' is traditionally # We prefer python 3.x. A bare 'python' is traditionally

View File

@ -2569,9 +2569,12 @@ foreach target : target_dirs
if 'CONFIG_LINUX_USER' in config_target if 'CONFIG_LINUX_USER' in config_target
base_dir = 'linux-user' base_dir = 'linux-user'
target_inc += include_directories('linux-user/host/' / config_host['ARCH']) target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
else endif
if 'CONFIG_BSD_USER' in config_target
base_dir = 'bsd-user' base_dir = 'bsd-user'
target_inc += include_directories('bsd-user/freebsd') target_inc += include_directories('bsd-user/' / targetos)
dir = base_dir / abi
arch_srcs += files(dir / 'target_arch_cpu.c')
endif endif
target_inc += include_directories( target_inc += include_directories(
base_dir, base_dir,

View File

@ -132,9 +132,6 @@ class Indentation:
def __init__(self, initial: int = 0) -> None: def __init__(self, initial: int = 0) -> None:
self._level = initial self._level = initial
def __int__(self) -> int:
return self._level
def __repr__(self) -> str: def __repr__(self) -> str:
return "{}({:d})".format(type(self).__name__, self._level) return "{}({:d})".format(type(self).__name__, self._level)
@ -142,19 +139,13 @@ class Indentation:
"""Return the current indentation as a string of spaces.""" """Return the current indentation as a string of spaces."""
return ' ' * self._level return ' ' * self._level
def __bool__(self) -> bool:
"""True when there is a non-zero indentation."""
return bool(self._level)
def increase(self, amount: int = 4) -> None: def increase(self, amount: int = 4) -> None:
"""Increase the indentation level by ``amount``, default 4.""" """Increase the indentation level by ``amount``, default 4."""
self._level += amount self._level += amount
def decrease(self, amount: int = 4) -> None: def decrease(self, amount: int = 4) -> None:
"""Decrease the indentation level by ``amount``, default 4.""" """Decrease the indentation level by ``amount``, default 4."""
if self._level < amount: assert amount <= self._level
raise ArithmeticError(
f"Can't remove {amount:d} spaces from {self!r}")
self._level -= amount self._level -= amount
@ -169,8 +160,9 @@ def cgen(code: str, **kwds: object) -> str:
Obey `indent`, and strip `EATSPACE`. Obey `indent`, and strip `EATSPACE`.
""" """
raw = code % kwds raw = code % kwds
if indent: pfx = str(indent)
raw = re.sub(r'^(?!(#|$))', str(indent), raw, flags=re.MULTILINE) if pfx:
raw = re.sub(r'^(?!(#|$))', pfx, raw, flags=re.MULTILINE)
return re.sub(re.escape(EATSPACE) + r' *', '', raw) return re.sub(re.escape(EATSPACE) + r' *', '', raw)
@ -205,7 +197,8 @@ def gen_ifcond(ifcond: Optional[Union[str, Dict[str, Any]]],
cond_fmt: str, not_fmt: str, cond_fmt: str, not_fmt: str,
all_operator: str, any_operator: str) -> str: all_operator: str, any_operator: str) -> str:
def do_gen(ifcond: Union[str, Dict[str, Any]], need_parens: bool): def do_gen(ifcond: Union[str, Dict[str, Any]],
need_parens: bool) -> str:
if isinstance(ifcond, str): if isinstance(ifcond, str):
return cond_fmt % ifcond return cond_fmt % ifcond
assert isinstance(ifcond, dict) and len(ifcond) == 1 assert isinstance(ifcond, dict) and len(ifcond) == 1

View File

@ -293,17 +293,22 @@ def check_if(expr: _JSONObject, info: QAPISourceInfo, source: str) -> None:
info, info,
"'if' condition of %s has conflicting keys" % source) "'if' condition of %s has conflicting keys" % source)
oper, operands = next(iter(cond.items())) if 'not' in cond:
_check_if(cond['not'])
elif 'all' in cond:
_check_infix('all', cond['all'])
else:
_check_infix('any', cond['any'])
def _check_infix(operator: str, operands: object) -> None:
if not isinstance(operands, list):
raise QAPISemError(
info,
"'%s' condition of %s must be an array"
% (operator, source))
if not operands: if not operands:
raise QAPISemError( raise QAPISemError(
info, "'if' condition [] of %s is useless" % source) info, "'if' condition [] of %s is useless" % source)
if oper == "not":
_check_if(operands)
return
if oper in ("all", "any") and not isinstance(operands, list):
raise QAPISemError(
info, "'%s' condition of %s must be an array" % (oper, source))
for operand in operands: for operand in operands:
_check_if(operand) _check_if(operand)

View File

@ -0,0 +1,2 @@
bad-if-not.json: In struct 'TestIfStruct':
bad-if-not.json:2: 'if' condition '' of struct is not a valid identifier

View File

@ -0,0 +1,3 @@
# check 'if not' with empy argument
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
'if': { 'not': '' } }

View File

View File

@ -43,6 +43,7 @@ schemas = [
'bad-if-key.json', 'bad-if-key.json',
'bad-if-keys.json', 'bad-if-keys.json',
'bad-if-list.json', 'bad-if-list.json',
'bad-if-not.json',
'bad-type-bool.json', 'bad-type-bool.json',
'bad-type-dict.json', 'bad-type-dict.json',
'bad-type-int.json', 'bad-type-int.json',