Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
35ea8abea1
@ -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
|
@ -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.h"
|
||||
|
||||
#define TARGET_NGROUPS 32
|
||||
|
||||
/* ??? This should really be somewhere else. */
|
||||
abi_long memcpy_to_target(abi_ulong dest, const void *src,
|
||||
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. */
|
||||
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);
|
||||
abi_ulong envp;
|
||||
@ -93,13 +106,6 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
|
||||
envp = sp;
|
||||
sp -= (argc + 1) * n;
|
||||
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;
|
||||
/* FIXME - handle put_user() failures */
|
||||
put_user_ual(argc, sp);
|
||||
@ -124,36 +130,70 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
|
||||
return sp;
|
||||
}
|
||||
|
||||
int loader_exec(const char *filename, char **argv, char **envp,
|
||||
struct target_pt_regs *regs, struct image_info *infop)
|
||||
static bool is_there(const char *candidate)
|
||||
{
|
||||
struct bsd_binprm bprm;
|
||||
int retval;
|
||||
int i;
|
||||
struct stat fin;
|
||||
|
||||
bprm.p = TARGET_PAGE_SIZE * MAX_ARG_PAGES - sizeof(unsigned int);
|
||||
for (i = 0 ; i < MAX_ARG_PAGES ; i++) { /* clear page-table */
|
||||
bprm.page[i] = NULL;
|
||||
/* XXX work around access(2) false positives for superuser */
|
||||
if (access(candidate, X_OK) == 0 && stat(candidate, &fin) == 0 &&
|
||||
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) {
|
||||
g_free(path);
|
||||
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 (bprm.buf[0] == 0x7f
|
||||
&& bprm.buf[1] == 'E'
|
||||
&& bprm.buf[2] == 'L'
|
||||
&& bprm.buf[3] == 'F') {
|
||||
retval = load_elf_binary(&bprm, regs, infop);
|
||||
if (bprm->buf[0] == 0x7f
|
||||
&& bprm->buf[1] == 'E'
|
||||
&& bprm->buf[2] == 'L'
|
||||
&& bprm->buf[3] == 'F') {
|
||||
retval = load_elf_binary(bprm, regs, infop);
|
||||
} else {
|
||||
fprintf(stderr, "Unknown binary format\n");
|
||||
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*/
|
||||
for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
|
||||
g_free(bprm.page[i]);
|
||||
g_free(bprm->page[i]);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
10
bsd-user/elfcore.c
Normal file
10
bsd-user/elfcore.c
Normal 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;
|
||||
}
|
1333
bsd-user/elfload.c
1333
bsd-user/elfload.c
File diff suppressed because it is too large
Load Diff
25
bsd-user/freebsd/host-os.h
Normal file
25
bsd-user/freebsd/host-os.h
Normal 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_ */
|
137
bsd-user/freebsd/target_os_elf.h
Normal file
137
bsd-user/freebsd/target_os_elf.h
Normal 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_ */
|
145
bsd-user/freebsd/target_os_siginfo.h
Normal file
145
bsd-user/freebsd/target_os_siginfo.h
Normal 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_ */
|
78
bsd-user/freebsd/target_os_signal.h
Normal file
78
bsd-user/freebsd/target_os_signal.h
Normal 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<OSTOP)*/
|
||||
#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_ */
|
181
bsd-user/freebsd/target_os_stack.h
Normal file
181
bsd-user/freebsd/target_os_stack.h
Normal 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_ */
|
25
bsd-user/freebsd/target_os_thread.h
Normal file
25
bsd-user/freebsd/target_os_thread.h
Normal 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_ */
|
427
bsd-user/freebsd/target_os_user.h
Normal file
427
bsd-user/freebsd/target_os_user.h
Normal 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_ */
|
38
bsd-user/freebsd/target_os_vmparam.h
Normal file
38
bsd-user/freebsd/target_os_vmparam.h
Normal 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_ */
|
@ -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
|
||||
* 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
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef TARGET_SYSCALL_H
|
||||
#define TARGET_SYSCALL_H
|
||||
|
||||
struct target_pt_regs {
|
||||
abi_ulong psr;
|
||||
abi_ulong pc;
|
||||
abi_ulong npc;
|
||||
abi_ulong y;
|
||||
abi_ulong u_regs[16];
|
||||
};
|
||||
#ifndef _TARGET_ARCH_H_
|
||||
#define _TARGET_ARCH_H_
|
||||
|
||||
#define UNAME_MACHINE "sun4"
|
||||
#define TARGET_HW_MACHINE "sparc"
|
||||
#define TARGET_HW_MACHINE_ARCH "sparc"
|
||||
/* target_arch_cpu.c */
|
||||
void bsd_i386_write_dt(void *ptr, unsigned long addr, unsigned long limit,
|
||||
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_SPARC_SIGTRAMP_INSTALL 2
|
||||
#define target_cpu_set_tls(env, newtls)
|
||||
|
||||
#endif /* TARGET_SYSCALL_H */
|
||||
#endif /* ! _TARGET_ARCH_H_ */
|
76
bsd-user/i386/target_arch_cpu.c
Normal file
76
bsd-user/i386/target_arch_cpu.c
Normal 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);
|
||||
}
|
||||
|
209
bsd-user/i386/target_arch_cpu.h
Normal file
209
bsd-user/i386/target_arch_cpu.h
Normal 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_ */
|
35
bsd-user/i386/target_arch_elf.h
Normal file
35
bsd-user/i386/target_arch_elf.h
Normal 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_ */
|
82
bsd-user/i386/target_arch_reg.h
Normal file
82
bsd-user/i386/target_arch_reg.h
Normal 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_ */
|
94
bsd-user/i386/target_arch_signal.h
Normal file
94
bsd-user/i386/target_arch_signal.h
Normal 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 */
|
29
bsd-user/i386/target_arch_sigtramp.h
Normal file
29
bsd-user/i386/target_arch_sigtramp.h
Normal 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_ */
|
47
bsd-user/i386/target_arch_thread.h
Normal file
47
bsd-user/i386/target_arch_thread.h
Normal 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_ */
|
46
bsd-user/i386/target_arch_vmparam.h
Normal file
46
bsd-user/i386/target_arch_vmparam.h
Normal 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_ */
|
832
bsd-user/main.c
832
bsd-user/main.c
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* qemu user main
|
||||
* qemu bsd user main
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
* Copyright (c) 2013-14 Stacey 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
|
||||
@ -17,6 +18,11 @@
|
||||
* 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-common.h"
|
||||
#include "qemu/units.h"
|
||||
@ -39,495 +45,107 @@
|
||||
#include "qemu/cutils.h"
|
||||
#include "exec/log.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;
|
||||
unsigned long mmap_min_addr;
|
||||
uintptr_t 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;
|
||||
#endif
|
||||
|
||||
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
|
||||
const char *qemu_uname_release;
|
||||
enum BSDType bsd_type;
|
||||
char qemu_proc_pathname[PATH_MAX]; /* full path to exeutable */
|
||||
|
||||
/*
|
||||
* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
|
||||
* we allocate a bigger stack. Need a better solution, for example
|
||||
* by remapping the process stack directly at the right place
|
||||
*/
|
||||
unsigned long x86_stack_size = 512 * 1024;
|
||||
unsigned long target_maxtsiz = TARGET_MAXTSIZ; /* max text size */
|
||||
unsigned long target_dfldsiz = TARGET_DFLDSIZ; /* initial data size limit */
|
||||
unsigned long target_maxdsiz = TARGET_MAXDSIZ; /* max data size */
|
||||
unsigned long target_dflssiz = TARGET_DFLSSIZ; /* initial data size limit */
|
||||
unsigned long target_maxssiz = TARGET_MAXSSIZ; /* max stack size */
|
||||
unsigned long target_sgrowsiz = TARGET_SGROWSIZ; /* amount to grow stack */
|
||||
|
||||
void gemu_log(const char *fmt, ...)
|
||||
{
|
||||
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
|
||||
/* Helper routines for implementing atomic operations. */
|
||||
|
||||
void fork_start(void)
|
||||
{
|
||||
start_exclusive();
|
||||
cpu_list_lock();
|
||||
mmap_fork_start();
|
||||
}
|
||||
|
||||
void fork_end(int 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);
|
||||
}
|
||||
}
|
||||
|
||||
#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 {
|
||||
env->eflags &= ~CC_C;
|
||||
}
|
||||
break;
|
||||
#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);
|
||||
mmap_fork_end(child);
|
||||
cpu_list_unlock();
|
||||
end_exclusive();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_SPARC
|
||||
#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)
|
||||
void cpu_loop(CPUArchState *env)
|
||||
{
|
||||
index = (index + cwp * 16) % (16 * env->nwindows);
|
||||
/*
|
||||
* 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;
|
||||
target_cpu_loop(env);
|
||||
}
|
||||
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)
|
||||
{
|
||||
@ -552,7 +170,6 @@ static void usage(void)
|
||||
"-d item1[,...] enable logging of specified items\n"
|
||||
" (use '-d help' for a list of log items)\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"
|
||||
"-strace log system calls\n"
|
||||
"-trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
|
||||
@ -572,11 +189,11 @@ static void usage(void)
|
||||
,
|
||||
TARGET_NAME,
|
||||
interp_prefix,
|
||||
x86_stack_size);
|
||||
target_dflssiz);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
THREAD CPUState *thread_cpu;
|
||||
__thread CPUState *thread_cpu;
|
||||
|
||||
bool qemu_cpu_is_self(CPUState *cpu)
|
||||
{
|
||||
@ -601,6 +218,48 @@ void init_task_state(TaskState *ts)
|
||||
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)
|
||||
{
|
||||
const char *filename;
|
||||
@ -608,9 +267,11 @@ int main(int argc, char **argv)
|
||||
const char *cpu_type;
|
||||
const char *log_file = NULL;
|
||||
const char *log_mask = NULL;
|
||||
const char *seed_optarg = NULL;
|
||||
struct target_pt_regs regs1, *regs = ®s1;
|
||||
struct image_info info1, *info = &info1;
|
||||
TaskState ts1, *ts = &ts1;
|
||||
struct bsd_binprm bprm;
|
||||
TaskState *ts;
|
||||
CPUArchState *env;
|
||||
CPUState *cpu;
|
||||
int optind, rv;
|
||||
@ -618,12 +279,17 @@ int main(int argc, char **argv)
|
||||
const char *gdbstub = NULL;
|
||||
char **target_environ, **wrk;
|
||||
envlist_t *envlist = NULL;
|
||||
bsd_type = target_openbsd;
|
||||
bsd_type = HOST_DEFAULT_BSD_TYPE;
|
||||
char *argv0 = NULL;
|
||||
|
||||
adjust_ssize();
|
||||
|
||||
if (argc <= 1) {
|
||||
usage();
|
||||
}
|
||||
|
||||
save_proc_pathname(argv[0]);
|
||||
|
||||
error_init(argv[0]);
|
||||
module_call_init(MODULE_INIT_TRACE);
|
||||
qemu_init_cpu_list();
|
||||
@ -678,14 +344,17 @@ int main(int argc, char **argv)
|
||||
}
|
||||
} else if (!strcmp(r, "s")) {
|
||||
r = argv[optind++];
|
||||
rv = qemu_strtoul(r, &r, 0, &x86_stack_size);
|
||||
if (rv < 0 || x86_stack_size <= 0) {
|
||||
rv = qemu_strtoul(r, &r, 0, &target_dflssiz);
|
||||
if (rv < 0 || target_dflssiz <= 0) {
|
||||
usage();
|
||||
}
|
||||
if (*r == 'M') {
|
||||
x86_stack_size *= MiB;
|
||||
target_dflssiz *= 1024 * 1024;
|
||||
} else if (*r == 'k' || *r == 'K') {
|
||||
x86_stack_size *= KiB;
|
||||
target_dflssiz *= 1024;
|
||||
}
|
||||
if (target_dflssiz > target_maxssiz) {
|
||||
usage();
|
||||
}
|
||||
} else if (!strcmp(r, "L")) {
|
||||
interp_prefix = argv[optind++];
|
||||
@ -728,12 +397,16 @@ int main(int argc, char **argv)
|
||||
usage();
|
||||
}
|
||||
optind++;
|
||||
} else if (!strcmp(r, "seed")) {
|
||||
seed_optarg = optarg;
|
||||
} else if (!strcmp(r, "singlestep")) {
|
||||
singlestep = 1;
|
||||
} else if (!strcmp(r, "strace")) {
|
||||
do_strace = 1;
|
||||
} else if (!strcmp(r, "trace")) {
|
||||
trace_opt_parse(optarg);
|
||||
} else if (!strcmp(r, "0")) {
|
||||
argv0 = argv[optind++];
|
||||
} else {
|
||||
usage();
|
||||
}
|
||||
@ -757,6 +430,9 @@ int main(int argc, char **argv)
|
||||
usage();
|
||||
}
|
||||
filename = argv[optind];
|
||||
if (argv0) {
|
||||
argv[optind] = argv0;
|
||||
}
|
||||
|
||||
if (!trace_init_backends()) {
|
||||
exit(1);
|
||||
@ -766,6 +442,9 @@ int main(int argc, char **argv)
|
||||
/* Zero out regs */
|
||||
memset(regs, 0, sizeof(struct target_pt_regs));
|
||||
|
||||
/* Zero bsd params */
|
||||
memset(&bprm, 0, sizeof(bprm));
|
||||
|
||||
/* Zero out image_info */
|
||||
memset(info, 0, sizeof(struct image_info));
|
||||
|
||||
@ -773,24 +452,11 @@ int main(int argc, char **argv)
|
||||
init_paths(interp_prefix);
|
||||
|
||||
if (cpu_model == NULL) {
|
||||
#if defined(TARGET_I386)
|
||||
#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_model = TARGET_DEFAULT_CPU_MODEL;
|
||||
}
|
||||
|
||||
cpu_type = parse_cpu_option(cpu_model);
|
||||
|
||||
/* init tcg before creating CPUs and to get qemu_host_page_size */
|
||||
{
|
||||
AccelClass *ac = ACCEL_GET_CLASS(current_accel());
|
||||
@ -800,9 +466,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
cpu = cpu_create(cpu_type);
|
||||
env = cpu->env_ptr;
|
||||
#if defined(TARGET_SPARC) || defined(TARGET_PPC)
|
||||
cpu_reset(cpu);
|
||||
#endif
|
||||
thread_cpu = cpu;
|
||||
|
||||
if (getenv("QEMU_STRACE")) {
|
||||
@ -812,36 +476,31 @@ int main(int argc, char **argv)
|
||||
target_environ = envlist_to_environ(envlist, NULL);
|
||||
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
|
||||
* proper page alignment for guest_base.
|
||||
*/
|
||||
guest_base = HOST_PAGE_ALIGN(guest_base);
|
||||
|
||||
/*
|
||||
* Read in mmap_min_addr kernel parameter. This value is used
|
||||
* 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) {
|
||||
if (loader_exec(filename, argv + optind, target_environ, regs, info,
|
||||
&bprm) != 0) {
|
||||
printf("Error loading %s\n", filename);
|
||||
_exit(1);
|
||||
}
|
||||
@ -869,6 +528,13 @@ int main(int argc, char **argv)
|
||||
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);
|
||||
syscall_init();
|
||||
signal_init();
|
||||
@ -880,143 +546,7 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
tcg_prologue_init(tcg_ctx);
|
||||
|
||||
/* build Task State */
|
||||
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
|
||||
target_cpu_init(env, regs);
|
||||
|
||||
if (gdbstub) {
|
||||
gdbserver_start(gdbstub);
|
||||
|
484
bsd-user/mmap.c
484
bsd-user/mmap.c
@ -20,8 +20,6 @@
|
||||
|
||||
#include "qemu.h"
|
||||
#include "qemu-common.h"
|
||||
#include "bsd-mman.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
//#define DEBUG_MMAP
|
||||
|
||||
@ -70,8 +68,8 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
|
||||
int prot1, ret;
|
||||
|
||||
#ifdef DEBUG_MMAP
|
||||
printf("mprotect: start=0x" TARGET_FMT_lx
|
||||
" len=0x" TARGET_FMT_lx " prot=%c%c%c\n", start, len,
|
||||
printf("mprotect: start=0x" TARGET_ABI_FMT_lx
|
||||
"len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c\n", start, len,
|
||||
prot & PROT_READ ? 'r' : '-',
|
||||
prot & PROT_WRITE ? 'w' : '-',
|
||||
prot & PROT_EXEC ? 'x' : '-');
|
||||
@ -190,90 +188,275 @@ static int mmap_frag(abi_ulong real_start,
|
||||
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;
|
||||
|
||||
/* find a free memory area of size 'size'. The search starts at
|
||||
'start'. If 'start' == 0, then a default start address is used.
|
||||
Return -1 if error.
|
||||
/*
|
||||
* Subroutine of mmap_find_vma, used when we have pre-allocated a chunk of guest
|
||||
* address space.
|
||||
*/
|
||||
/* page_init() marks pages used by the host as reserved to be sure not
|
||||
to use them. */
|
||||
static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
|
||||
static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size,
|
||||
abi_ulong alignment)
|
||||
{
|
||||
abi_ulong addr, addr1, addr_start;
|
||||
abi_ulong addr;
|
||||
abi_ulong end_addr;
|
||||
int prot;
|
||||
unsigned long new_brk;
|
||||
int looped = 0;
|
||||
|
||||
new_brk = (unsigned long)sbrk(0);
|
||||
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)
|
||||
if (size > reserved_va) {
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
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;
|
||||
unsigned long host_start;
|
||||
|
||||
mmap_lock();
|
||||
#ifdef DEBUG_MMAP
|
||||
{
|
||||
printf("mmap: start=0x" TARGET_FMT_lx
|
||||
" len=0x" TARGET_FMT_lx " prot=%c%c%c flags=",
|
||||
printf("mmap: start=0x" TARGET_ABI_FMT_lx
|
||||
" len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c flags=",
|
||||
start, len,
|
||||
prot & PROT_READ ? 'r' : '-',
|
||||
prot & PROT_WRITE ? 'w' : '-',
|
||||
prot & PROT_EXEC ? 'x' : '-');
|
||||
if (flags & MAP_FIXED)
|
||||
printf("MAP_FIXED ");
|
||||
if (flags & MAP_ANON)
|
||||
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;
|
||||
if (flags & MAP_ALIGNMENT_MASK) {
|
||||
printf("MAP_ALIGNED(%u) ", (flags & MAP_ALIGNMENT_MASK)
|
||||
>> MAP_ALIGNMENT_SHIFT);
|
||||
}
|
||||
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
|
||||
|
||||
@ -283,37 +466,92 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
}
|
||||
|
||||
len = TARGET_PAGE_ALIGN(len);
|
||||
if (len == 0)
|
||||
goto the_end;
|
||||
if (len == 0) {
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
real_start = start & qemu_host_page_mask;
|
||||
|
||||
if (!(flags & MAP_FIXED)) {
|
||||
abi_ulong mmap_start;
|
||||
void *p;
|
||||
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 = HOST_PAGE_ALIGN(host_len);
|
||||
mmap_start = mmap_find_vma(real_start, host_len);
|
||||
if (mmap_start == (abi_ulong)-1) {
|
||||
if ((flags & MAP_ALIGNMENT_MASK) != 0)
|
||||
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;
|
||||
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),
|
||||
host_len, prot, flags | MAP_FIXED, fd, host_offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* When mapping files into a memory area larger than the file, accesses
|
||||
* 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)
|
||||
goto fail;
|
||||
/* update start so that it points to the file position at 'offset' */
|
||||
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;
|
||||
}
|
||||
start = h2g(host_start);
|
||||
} else {
|
||||
int flg;
|
||||
target_ulong addr;
|
||||
|
||||
if (start & ~TARGET_PAGE_MASK) {
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
@ -321,20 +559,28 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
end = start + len;
|
||||
real_end = HOST_PAGE_ALIGN(end);
|
||||
|
||||
for (addr = real_start; addr < real_end; addr += TARGET_PAGE_SIZE) {
|
||||
flg = page_get_flags(addr);
|
||||
if (flg & PAGE_RESERVED) {
|
||||
errno = ENXIO;
|
||||
/*
|
||||
* Test if requested memory area fits target address space
|
||||
* It can fail only on 64-bit host with 32-bit target.
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
#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) &&
|
||||
(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 &&
|
||||
(prot & PROT_WRITE)) {
|
||||
errno = EINVAL;
|
||||
@ -375,7 +621,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
/* handle the end of the mapping */
|
||||
if (end < real_end) {
|
||||
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,
|
||||
offset + real_end - qemu_host_page_size - start);
|
||||
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);
|
||||
the_end:
|
||||
#ifdef DEBUG_MMAP
|
||||
printf("ret=0x" TARGET_FMT_lx "\n", start);
|
||||
printf("ret=0x" TARGET_ABI_FMT_lx "\n", start);
|
||||
page_dump(stdout);
|
||||
printf("\n");
|
||||
#endif
|
||||
tb_invalidate_phys_range(start, start + len);
|
||||
mmap_unlock();
|
||||
return start;
|
||||
fail:
|
||||
@ -412,13 +659,58 @@ fail:
|
||||
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)
|
||||
{
|
||||
abi_ulong end, real_start, real_end, addr;
|
||||
int prot, ret;
|
||||
|
||||
#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
|
||||
if (start & ~TARGET_PAGE_MASK)
|
||||
return -EINVAL;
|
||||
@ -457,11 +749,17 @@ int target_munmap(abi_ulong start, abi_ulong len)
|
||||
ret = 0;
|
||||
/* unmap what we can */
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
if (ret == 0) {
|
||||
page_set_flags(start, start + len, 0);
|
||||
tb_invalidate_phys_range(start, start + len);
|
||||
}
|
||||
mmap_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
25
bsd-user/netbsd/host-os.h
Normal file
25
bsd-user/netbsd/host-os.h
Normal 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_ */
|
146
bsd-user/netbsd/target_os_elf.h
Normal file
146
bsd-user/netbsd/target_os_elf.h
Normal 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_ */
|
82
bsd-user/netbsd/target_os_siginfo.h
Normal file
82
bsd-user/netbsd/target_os_siginfo.h
Normal 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_ */
|
69
bsd-user/netbsd/target_os_signal.h
Normal file
69
bsd-user/netbsd/target_os_signal.h
Normal 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<OSTOP) */
|
||||
#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_ */
|
56
bsd-user/netbsd/target_os_stack.h
Normal file
56
bsd-user/netbsd/target_os_stack.h
Normal 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_ */
|
25
bsd-user/netbsd/target_os_thread.h
Normal file
25
bsd-user/netbsd/target_os_thread.h
Normal 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_ */
|
25
bsd-user/openbsd/host-os.h
Normal file
25
bsd-user/openbsd/host-os.h
Normal 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_ */
|
146
bsd-user/openbsd/target_os_elf.h
Normal file
146
bsd-user/openbsd/target_os_elf.h
Normal 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_ */
|
82
bsd-user/openbsd/target_os_siginfo.h
Normal file
82
bsd-user/openbsd/target_os_siginfo.h
Normal 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_ */
|
69
bsd-user/openbsd/target_os_signal.h
Normal file
69
bsd-user/openbsd/target_os_signal.h
Normal 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<OSTOP) */
|
||||
#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_ */
|
56
bsd-user/openbsd/target_os_stack.h
Normal file
56
bsd-user/openbsd/target_os_stack.h
Normal 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_ */
|
25
bsd-user/openbsd/target_os_thread.h
Normal file
25
bsd-user/openbsd/target_os_thread.h
Normal 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_ */
|
@ -18,12 +18,13 @@
|
||||
#define QEMU_H
|
||||
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/units.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
#undef DEBUG_REMAP
|
||||
#ifdef DEBUG_REMAP
|
||||
#endif /* DEBUG_REMAP */
|
||||
|
||||
#include "exec/user/abitypes.h"
|
||||
|
||||
@ -36,22 +37,21 @@ enum BSDType {
|
||||
};
|
||||
extern enum BSDType bsd_type;
|
||||
|
||||
#include "exec/user/thunk.h"
|
||||
#include "target_arch.h"
|
||||
#include "syscall_defs.h"
|
||||
#include "target_syscall.h"
|
||||
#include "target_os_vmparam.h"
|
||||
#include "target_os_signal.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,
|
||||
* it replicates in user space what would be certain task_struct fields in the
|
||||
* kernel
|
||||
*/
|
||||
struct image_info {
|
||||
abi_ulong load_bias;
|
||||
abi_ulong load_addr;
|
||||
abi_ulong start_code;
|
||||
abi_ulong end_code;
|
||||
@ -66,7 +66,9 @@ struct image_info {
|
||||
abi_ulong entry;
|
||||
abi_ulong code_offset;
|
||||
abi_ulong data_offset;
|
||||
int personality;
|
||||
abi_ulong arg_start;
|
||||
abi_ulong arg_end;
|
||||
uint32_t elf_flags;
|
||||
};
|
||||
|
||||
#define MAX_SIGQUEUE_SIZE 1024
|
||||
@ -89,6 +91,7 @@ typedef struct TaskState {
|
||||
pid_t ts_tid; /* tid (or pid) of this task */
|
||||
|
||||
struct TaskState *next;
|
||||
struct bsd_binprm *bprm;
|
||||
int used; /* non zero if used */
|
||||
struct image_info *info;
|
||||
|
||||
@ -102,14 +105,19 @@ typedef struct TaskState {
|
||||
|
||||
void init_task_state(TaskState *ts);
|
||||
extern const char *qemu_uname_release;
|
||||
extern unsigned long mmap_min_addr;
|
||||
|
||||
/*
|
||||
* MAX_ARG_PAGES defines the number of pages allocated for arguments
|
||||
* and envelope for the new program. 32 should suffice, this gives
|
||||
* a maximum env+arg of 128kB w/4KB pages!
|
||||
* TARGET_ARG_MAX defines the number of bytes allocated for arguments
|
||||
* and envelope for the new program. 256k should suffice for a reasonable
|
||||
* 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
|
||||
@ -119,24 +127,29 @@ struct bsd_binprm {
|
||||
char buf[128];
|
||||
void *page[MAX_ARG_PAGES];
|
||||
abi_ulong p;
|
||||
abi_ulong stringp;
|
||||
int fd;
|
||||
int e_uid, e_gid;
|
||||
int argc, envc;
|
||||
char **argv;
|
||||
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);
|
||||
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,
|
||||
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,
|
||||
struct image_info *info);
|
||||
int load_flt_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
|
||||
struct image_info *info);
|
||||
int is_target_elf_binary(int fd);
|
||||
|
||||
abi_long memcpy_to_target(abi_ulong dest, const void *src,
|
||||
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 arg5, abi_long arg6);
|
||||
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);
|
||||
char *target_strerror(int err);
|
||||
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 */
|
||||
int target_mprotect(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);
|
||||
abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
|
||||
abi_ulong new_size, unsigned long flags,
|
||||
abi_ulong new_addr);
|
||||
int target_msync(abi_ulong start, abi_ulong len, int flags);
|
||||
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_end(int child);
|
||||
|
||||
/* 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 */
|
||||
|
||||
@ -421,8 +442,6 @@ static inline void *lock_user_string(abi_ulong guest_addr)
|
||||
#define unlock_user_struct(host_ptr, guest_addr, copy) \
|
||||
unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
|
||||
|
||||
#if defined(CONFIG_USE_NPTL)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#endif /* QEMU_H */
|
||||
|
@ -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_ */
|
@ -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_ */
|
@ -138,17 +138,6 @@ static abi_long do_freebsd_sysarch(CPUX86State *env, int op, abi_ulong parms)
|
||||
}
|
||||
#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__
|
||||
/*
|
||||
* XXX this uses the undocumented oidfmt interface to find the kind of
|
||||
|
@ -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
|
||||
* 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.
|
||||
* System call related declarations
|
||||
*
|
||||
* 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.
|
||||
* Copyright (c) 2013-15 Stacey D. Son (sson at FreeBSD)
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)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 */
|
||||
#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<OSTOP) */
|
||||
#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 <sys/syscall.h>
|
||||
|
||||
#include "errno_defs.h"
|
||||
|
||||
@ -107,8 +28,154 @@
|
||||
#include "netbsd/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 {
|
||||
abi_long iov_base; /* Starting address */
|
||||
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_ */
|
||||
|
@ -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
|
||||
* 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
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef TARGET_SYSCALL_H
|
||||
#define TARGET_SYSCALL_H
|
||||
|
||||
struct target_pt_regs {
|
||||
abi_ulong u_regs[16];
|
||||
abi_ulong tstate;
|
||||
abi_ulong pc;
|
||||
abi_ulong npc;
|
||||
abi_ulong y;
|
||||
abi_ulong fprs;
|
||||
};
|
||||
#ifndef _TARGET_ARCH_H_
|
||||
#define _TARGET_ARCH_H_
|
||||
|
||||
#define UNAME_MACHINE "sun4u"
|
||||
#define TARGET_HW_MACHINE "sparc"
|
||||
#define TARGET_HW_MACHINE_ARCH "sparc64"
|
||||
/* target_arch_cpu.c */
|
||||
void bsd_x86_64_write_dt(void *ptr, unsigned long addr, unsigned long limit,
|
||||
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_SPARC_SIGTRAMP_INSTALL 2
|
||||
#define target_cpu_set_tls(env, newtls)
|
||||
|
||||
#endif /* TARGET_SYSCALL_H */
|
||||
#endif /* !_TARGET_ARCH_H_ */
|
76
bsd-user/x86_64/target_arch_cpu.c
Normal file
76
bsd-user/x86_64/target_arch_cpu.c
Normal 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);
|
||||
}
|
247
bsd-user/x86_64/target_arch_cpu.h
Normal file
247
bsd-user/x86_64/target_arch_cpu.h
Normal 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_ */
|
35
bsd-user/x86_64/target_arch_elf.h
Normal file
35
bsd-user/x86_64/target_arch_elf.h
Normal 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_ */
|
92
bsd-user/x86_64/target_arch_reg.h
Normal file
92
bsd-user/x86_64/target_arch_reg.h
Normal 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_ */
|
94
bsd-user/x86_64/target_arch_signal.h
Normal file
94
bsd-user/x86_64/target_arch_signal.h
Normal 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_ */
|
29
bsd-user/x86_64/target_arch_sigtramp.h
Normal file
29
bsd-user/x86_64/target_arch_sigtramp.h
Normal 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_ */
|
40
bsd-user/x86_64/target_arch_thread.h
Normal file
40
bsd-user/x86_64/target_arch_thread.h
Normal 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_ */
|
46
bsd-user/x86_64/target_arch_vmparam.h
Normal file
46
bsd-user/x86_64/target_arch_vmparam.h
Normal 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
7
configure
vendored
@ -721,6 +721,7 @@ GNU/kFreeBSD)
|
||||
;;
|
||||
FreeBSD)
|
||||
bsd="yes"
|
||||
bsd_user="yes"
|
||||
make="${MAKE-gmake}"
|
||||
audio_drv_list="oss try-sdl"
|
||||
audio_possible_drivers="oss sdl pa"
|
||||
@ -782,12 +783,6 @@ Linux)
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$bsd" = "yes" ] ; then
|
||||
if [ "$darwin" != "yes" ] ; then
|
||||
bsd_user="yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
: ${make=${MAKE-make}}
|
||||
|
||||
# We prefer python 3.x. A bare 'python' is traditionally
|
||||
|
@ -2569,9 +2569,12 @@ foreach target : target_dirs
|
||||
if 'CONFIG_LINUX_USER' in config_target
|
||||
base_dir = 'linux-user'
|
||||
target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
|
||||
else
|
||||
endif
|
||||
if 'CONFIG_BSD_USER' in config_target
|
||||
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
|
||||
target_inc += include_directories(
|
||||
base_dir,
|
||||
|
@ -132,9 +132,6 @@ class Indentation:
|
||||
def __init__(self, initial: int = 0) -> None:
|
||||
self._level = initial
|
||||
|
||||
def __int__(self) -> int:
|
||||
return self._level
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "{}({:d})".format(type(self).__name__, self._level)
|
||||
|
||||
@ -142,19 +139,13 @@ class Indentation:
|
||||
"""Return the current indentation as a string of spaces."""
|
||||
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:
|
||||
"""Increase the indentation level by ``amount``, default 4."""
|
||||
self._level += amount
|
||||
|
||||
def decrease(self, amount: int = 4) -> None:
|
||||
"""Decrease the indentation level by ``amount``, default 4."""
|
||||
if self._level < amount:
|
||||
raise ArithmeticError(
|
||||
f"Can't remove {amount:d} spaces from {self!r}")
|
||||
assert amount <= self._level
|
||||
self._level -= amount
|
||||
|
||||
|
||||
@ -169,8 +160,9 @@ def cgen(code: str, **kwds: object) -> str:
|
||||
Obey `indent`, and strip `EATSPACE`.
|
||||
"""
|
||||
raw = code % kwds
|
||||
if indent:
|
||||
raw = re.sub(r'^(?!(#|$))', str(indent), raw, flags=re.MULTILINE)
|
||||
pfx = str(indent)
|
||||
if pfx:
|
||||
raw = re.sub(r'^(?!(#|$))', pfx, raw, flags=re.MULTILINE)
|
||||
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,
|
||||
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):
|
||||
return cond_fmt % ifcond
|
||||
assert isinstance(ifcond, dict) and len(ifcond) == 1
|
||||
|
@ -293,17 +293,22 @@ def check_if(expr: _JSONObject, info: QAPISourceInfo, source: str) -> None:
|
||||
info,
|
||||
"'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:
|
||||
raise QAPISemError(
|
||||
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:
|
||||
_check_if(operand)
|
||||
|
||||
|
2
tests/qapi-schema/bad-if-not.err
Normal file
2
tests/qapi-schema/bad-if-not.err
Normal 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
|
3
tests/qapi-schema/bad-if-not.json
Normal file
3
tests/qapi-schema/bad-if-not.json
Normal file
@ -0,0 +1,3 @@
|
||||
# check 'if not' with empy argument
|
||||
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||
'if': { 'not': '' } }
|
0
tests/qapi-schema/bad-if-not.out
Normal file
0
tests/qapi-schema/bad-if-not.out
Normal file
@ -43,6 +43,7 @@ schemas = [
|
||||
'bad-if-key.json',
|
||||
'bad-if-keys.json',
|
||||
'bad-if-list.json',
|
||||
'bad-if-not.json',
|
||||
'bad-type-bool.json',
|
||||
'bad-type-dict.json',
|
||||
'bad-type-int.json',
|
||||
|
Loading…
x
Reference in New Issue
Block a user