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/osdep.h"
|
||||||
|
|
||||||
#include "qemu.h"
|
#include "qemu.h"
|
||||||
|
|
||||||
#define TARGET_NGROUPS 32
|
|
||||||
|
|
||||||
/* ??? This should really be somewhere else. */
|
/* ??? This should really be somewhere else. */
|
||||||
abi_long memcpy_to_target(abi_ulong dest, const void *src,
|
abi_long memcpy_to_target(abi_ulong dest, const void *src,
|
||||||
unsigned long len)
|
unsigned long len)
|
||||||
@ -83,7 +96,7 @@ static int prepare_binprm(struct bsd_binprm *bprm)
|
|||||||
|
|
||||||
/* Construct the envp and argv tables on the target stack. */
|
/* Construct the envp and argv tables on the target stack. */
|
||||||
abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
|
abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
|
||||||
abi_ulong stringp, int push_ptr)
|
abi_ulong stringp)
|
||||||
{
|
{
|
||||||
int n = sizeof(abi_ulong);
|
int n = sizeof(abi_ulong);
|
||||||
abi_ulong envp;
|
abi_ulong envp;
|
||||||
@ -93,13 +106,6 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
|
|||||||
envp = sp;
|
envp = sp;
|
||||||
sp -= (argc + 1) * n;
|
sp -= (argc + 1) * n;
|
||||||
argv = sp;
|
argv = sp;
|
||||||
if (push_ptr) {
|
|
||||||
/* FIXME - handle put_user() failures */
|
|
||||||
sp -= n;
|
|
||||||
put_user_ual(envp, sp);
|
|
||||||
sp -= n;
|
|
||||||
put_user_ual(argv, sp);
|
|
||||||
}
|
|
||||||
sp -= n;
|
sp -= n;
|
||||||
/* FIXME - handle put_user() failures */
|
/* FIXME - handle put_user() failures */
|
||||||
put_user_ual(argc, sp);
|
put_user_ual(argc, sp);
|
||||||
@ -124,36 +130,70 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
|
|||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int loader_exec(const char *filename, char **argv, char **envp,
|
static bool is_there(const char *candidate)
|
||||||
struct target_pt_regs *regs, struct image_info *infop)
|
|
||||||
{
|
{
|
||||||
struct bsd_binprm bprm;
|
struct stat fin;
|
||||||
int retval;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
bprm.p = TARGET_PAGE_SIZE * MAX_ARG_PAGES - sizeof(unsigned int);
|
/* XXX work around access(2) false positives for superuser */
|
||||||
for (i = 0 ; i < MAX_ARG_PAGES ; i++) { /* clear page-table */
|
if (access(candidate, X_OK) == 0 && stat(candidate, &fin) == 0 &&
|
||||||
bprm.page[i] = NULL;
|
S_ISREG(fin.st_mode) && (getuid() != 0 ||
|
||||||
|
(fin.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
retval = open(filename, O_RDONLY);
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int loader_exec(const char *filename, char **argv, char **envp,
|
||||||
|
struct target_pt_regs *regs, struct image_info *infop,
|
||||||
|
struct bsd_binprm *bprm)
|
||||||
|
{
|
||||||
|
char *path, fullpath[PATH_MAX];
|
||||||
|
int retval, i;
|
||||||
|
|
||||||
|
bprm->p = TARGET_PAGE_SIZE * MAX_ARG_PAGES;
|
||||||
|
for (i = 0; i < MAX_ARG_PAGES; i++) { /* clear page-table */
|
||||||
|
bprm->page[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strchr(filename, '/') != NULL) {
|
||||||
|
path = realpath(filename, fullpath);
|
||||||
|
if (path == NULL) {
|
||||||
|
/* Failed to resolve. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!is_there(path)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
path = g_find_program_in_path(filename);
|
||||||
|
if (path == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = open(path, O_RDONLY);
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
|
g_free(path);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
bprm.fd = retval;
|
|
||||||
bprm.filename = (char *)filename;
|
|
||||||
bprm.argc = count(argv);
|
|
||||||
bprm.argv = argv;
|
|
||||||
bprm.envc = count(envp);
|
|
||||||
bprm.envp = envp;
|
|
||||||
|
|
||||||
retval = prepare_binprm(&bprm);
|
bprm->fullpath = path;
|
||||||
|
bprm->fd = retval;
|
||||||
|
bprm->filename = (char *)filename;
|
||||||
|
bprm->argc = count(argv);
|
||||||
|
bprm->argv = argv;
|
||||||
|
bprm->envc = count(envp);
|
||||||
|
bprm->envp = envp;
|
||||||
|
|
||||||
|
retval = prepare_binprm(bprm);
|
||||||
|
|
||||||
if (retval >= 0) {
|
if (retval >= 0) {
|
||||||
if (bprm.buf[0] == 0x7f
|
if (bprm->buf[0] == 0x7f
|
||||||
&& bprm.buf[1] == 'E'
|
&& bprm->buf[1] == 'E'
|
||||||
&& bprm.buf[2] == 'L'
|
&& bprm->buf[2] == 'L'
|
||||||
&& bprm.buf[3] == 'F') {
|
&& bprm->buf[3] == 'F') {
|
||||||
retval = load_elf_binary(&bprm, regs, infop);
|
retval = load_elf_binary(bprm, regs, infop);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unknown binary format\n");
|
fprintf(stderr, "Unknown binary format\n");
|
||||||
return -1;
|
return -1;
|
||||||
@ -168,7 +208,7 @@ int loader_exec(const char *filename, char **argv, char **envp,
|
|||||||
|
|
||||||
/* Something went wrong, return the inode and free the argument pages*/
|
/* Something went wrong, return the inode and free the argument pages*/
|
||||||
for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
|
for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
|
||||||
g_free(bprm.page[i]);
|
g_free(bprm->page[i]);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
10
bsd-user/elfcore.c
Normal file
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;
|
||||||
|
}
|
1479
bsd-user/elfload.c
1479
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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -15,22 +16,16 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#ifndef TARGET_SYSCALL_H
|
|
||||||
#define TARGET_SYSCALL_H
|
|
||||||
|
|
||||||
struct target_pt_regs {
|
#ifndef _TARGET_ARCH_H_
|
||||||
abi_ulong psr;
|
#define _TARGET_ARCH_H_
|
||||||
abi_ulong pc;
|
|
||||||
abi_ulong npc;
|
|
||||||
abi_ulong y;
|
|
||||||
abi_ulong u_regs[16];
|
|
||||||
};
|
|
||||||
|
|
||||||
#define UNAME_MACHINE "sun4"
|
/* target_arch_cpu.c */
|
||||||
#define TARGET_HW_MACHINE "sparc"
|
void bsd_i386_write_dt(void *ptr, unsigned long addr, unsigned long limit,
|
||||||
#define TARGET_HW_MACHINE_ARCH "sparc"
|
int flags);
|
||||||
|
void bsd_i386_set_idt(int n, unsigned int dpl);
|
||||||
|
void bsd_i386_set_idt_base(uint64_t base);
|
||||||
|
|
||||||
#define TARGET_SPARC_UTRAP_INSTALL 1
|
#define target_cpu_set_tls(env, newtls)
|
||||||
#define TARGET_SPARC_SIGTRAMP_INSTALL 2
|
|
||||||
|
|
||||||
#endif /* TARGET_SYSCALL_H */
|
#endif /* ! _TARGET_ARCH_H_ */
|
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_ */
|
834
bsd-user/main.c
834
bsd-user/main.c
@ -1,7 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* qemu user main
|
* qemu bsd user main
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||||
|
* Copyright (c) 2013-14 Stacey Son
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -17,6 +18,11 @@
|
|||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "qemu/units.h"
|
#include "qemu/units.h"
|
||||||
@ -39,496 +45,108 @@
|
|||||||
#include "qemu/cutils.h"
|
#include "qemu/cutils.h"
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
#include "trace/control.h"
|
#include "trace/control.h"
|
||||||
|
#include "crypto/init.h"
|
||||||
|
#include "qemu/guest-random.h"
|
||||||
|
|
||||||
|
#include "host-os.h"
|
||||||
|
#include "target_arch_cpu.h"
|
||||||
|
|
||||||
int singlestep;
|
int singlestep;
|
||||||
unsigned long mmap_min_addr;
|
|
||||||
uintptr_t guest_base;
|
uintptr_t guest_base;
|
||||||
bool have_guest_base;
|
bool have_guest_base;
|
||||||
|
/*
|
||||||
|
* When running 32-on-64 we should make sure we can fit all of the possible
|
||||||
|
* guest address space into a contiguous chunk of virtual host memory.
|
||||||
|
*
|
||||||
|
* This way we will never overlap with our own libraries or binaries or stack
|
||||||
|
* or anything else that QEMU maps.
|
||||||
|
*
|
||||||
|
* Many cpus reserve the high bit (or more than one for some 64-bit cpus)
|
||||||
|
* of the address for the kernel. Some cpus rely on this and user space
|
||||||
|
* uses the high bit(s) for pointer tagging and the like. For them, we
|
||||||
|
* must preserve the expected address space.
|
||||||
|
*/
|
||||||
|
#ifndef MAX_RESERVED_VA
|
||||||
|
# if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
|
||||||
|
# if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \
|
||||||
|
(TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
|
||||||
|
/*
|
||||||
|
* There are a number of places where we assign reserved_va to a variable
|
||||||
|
* of type abi_ulong and expect it to fit. Avoid the last page.
|
||||||
|
*/
|
||||||
|
# define MAX_RESERVED_VA (0xfffffffful & TARGET_PAGE_MASK)
|
||||||
|
# else
|
||||||
|
# define MAX_RESERVED_VA (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define MAX_RESERVED_VA 0
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* That said, reserving *too* much vm space via mmap can run into problems
|
||||||
|
* with rlimits, oom due to page table creation, etc. We will still try it,
|
||||||
|
* if directed by the command-line option, but not by default.
|
||||||
|
*/
|
||||||
|
#if HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32
|
||||||
|
unsigned long reserved_va = MAX_RESERVED_VA;
|
||||||
|
#else
|
||||||
unsigned long reserved_va;
|
unsigned long reserved_va;
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
|
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
|
||||||
const char *qemu_uname_release;
|
const char *qemu_uname_release;
|
||||||
enum BSDType bsd_type;
|
enum BSDType bsd_type;
|
||||||
|
char qemu_proc_pathname[PATH_MAX]; /* full path to exeutable */
|
||||||
|
|
||||||
/*
|
unsigned long target_maxtsiz = TARGET_MAXTSIZ; /* max text size */
|
||||||
* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
|
unsigned long target_dfldsiz = TARGET_DFLDSIZ; /* initial data size limit */
|
||||||
* we allocate a bigger stack. Need a better solution, for example
|
unsigned long target_maxdsiz = TARGET_MAXDSIZ; /* max data size */
|
||||||
* by remapping the process stack directly at the right place
|
unsigned long target_dflssiz = TARGET_DFLSSIZ; /* initial data size limit */
|
||||||
*/
|
unsigned long target_maxssiz = TARGET_MAXSSIZ; /* max stack size */
|
||||||
unsigned long x86_stack_size = 512 * 1024;
|
unsigned long target_sgrowsiz = TARGET_SGROWSIZ; /* amount to grow stack */
|
||||||
|
|
||||||
void gemu_log(const char *fmt, ...)
|
/* Helper routines for implementing atomic operations. */
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vfprintf(stderr, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(TARGET_I386)
|
|
||||||
int cpu_get_pic_interrupt(CPUX86State *env)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void fork_start(void)
|
void fork_start(void)
|
||||||
{
|
{
|
||||||
|
start_exclusive();
|
||||||
|
cpu_list_lock();
|
||||||
|
mmap_fork_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void fork_end(int child)
|
void fork_end(int child)
|
||||||
{
|
{
|
||||||
if (child) {
|
if (child) {
|
||||||
|
CPUState *cpu, *next_cpu;
|
||||||
|
/*
|
||||||
|
* Child processes created by fork() only have a single thread. Discard
|
||||||
|
* information about the parent threads.
|
||||||
|
*/
|
||||||
|
CPU_FOREACH_SAFE(cpu, next_cpu) {
|
||||||
|
if (cpu != thread_cpu) {
|
||||||
|
QTAILQ_REMOVE_RCU(&cpus, cpu, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mmap_fork_end(child);
|
||||||
|
/*
|
||||||
|
* qemu_init_cpu_list() takes care of reinitializing the exclusive
|
||||||
|
* state, so we don't need to end_exclusive() here.
|
||||||
|
*/
|
||||||
|
qemu_init_cpu_list();
|
||||||
gdbserver_fork(thread_cpu);
|
gdbserver_fork(thread_cpu);
|
||||||
|
} else {
|
||||||
|
mmap_fork_end(child);
|
||||||
|
cpu_list_unlock();
|
||||||
|
end_exclusive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_I386
|
void cpu_loop(CPUArchState *env)
|
||||||
/***********************************************************/
|
|
||||||
/* CPUX86 core interface */
|
|
||||||
|
|
||||||
uint64_t cpu_get_tsc(CPUX86State *env)
|
|
||||||
{
|
{
|
||||||
return cpu_get_host_ticks();
|
target_cpu_loop(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#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)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save the register window 'cwp1' */
|
|
||||||
static inline void save_window_offset(CPUSPARCState *env, int cwp1)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
abi_ulong sp_ptr;
|
|
||||||
|
|
||||||
sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
|
|
||||||
#ifdef TARGET_SPARC64
|
|
||||||
if (sp_ptr & 3) {
|
|
||||||
sp_ptr += SPARC64_STACK_BIAS;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if defined(DEBUG_WIN)
|
|
||||||
printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
|
|
||||||
sp_ptr, cwp1);
|
|
||||||
#endif
|
|
||||||
for (i = 0; i < 16; i++) {
|
|
||||||
/* FIXME - what to do if put_user() fails? */
|
|
||||||
put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
|
|
||||||
sp_ptr += sizeof(abi_ulong);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void save_window(CPUSPARCState *env)
|
|
||||||
{
|
|
||||||
#ifndef TARGET_SPARC64
|
|
||||||
unsigned int new_wim;
|
|
||||||
new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
|
|
||||||
((1LL << env->nwindows) - 1);
|
|
||||||
save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
|
|
||||||
env->wim = new_wim;
|
|
||||||
#else
|
|
||||||
/*
|
|
||||||
* cansave is zero if the spill trap handler is triggered by `save` and
|
|
||||||
* nonzero if triggered by a `flushw`
|
|
||||||
*/
|
|
||||||
save_window_offset(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
|
|
||||||
env->cansave++;
|
|
||||||
env->canrestore--;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void restore_window(CPUSPARCState *env)
|
|
||||||
{
|
|
||||||
#ifndef TARGET_SPARC64
|
|
||||||
unsigned int new_wim;
|
|
||||||
#endif
|
|
||||||
unsigned int i, cwp1;
|
|
||||||
abi_ulong sp_ptr;
|
|
||||||
|
|
||||||
#ifndef TARGET_SPARC64
|
|
||||||
new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
|
|
||||||
((1LL << env->nwindows) - 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* restore the invalid window */
|
|
||||||
cwp1 = cpu_cwp_inc(env, env->cwp + 1);
|
|
||||||
sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
|
|
||||||
#ifdef TARGET_SPARC64
|
|
||||||
if (sp_ptr & 3) {
|
|
||||||
sp_ptr += SPARC64_STACK_BIAS;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if defined(DEBUG_WIN)
|
|
||||||
printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
|
|
||||||
sp_ptr, cwp1);
|
|
||||||
#endif
|
|
||||||
for (i = 0; i < 16; i++) {
|
|
||||||
/* FIXME - what to do if get_user() fails? */
|
|
||||||
get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
|
|
||||||
sp_ptr += sizeof(abi_ulong);
|
|
||||||
}
|
|
||||||
#ifdef TARGET_SPARC64
|
|
||||||
env->canrestore++;
|
|
||||||
if (env->cleanwin < env->nwindows - 1) {
|
|
||||||
env->cleanwin++;
|
|
||||||
}
|
|
||||||
env->cansave--;
|
|
||||||
#else
|
|
||||||
env->wim = new_wim;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void flush_windows(CPUSPARCState *env)
|
|
||||||
{
|
|
||||||
int offset, cwp1;
|
|
||||||
|
|
||||||
offset = 1;
|
|
||||||
for (;;) {
|
|
||||||
/* if restore would invoke restore_window(), then we can stop */
|
|
||||||
cwp1 = cpu_cwp_inc(env, env->cwp + offset);
|
|
||||||
#ifndef TARGET_SPARC64
|
|
||||||
if (env->wim & (1 << cwp1)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (env->canrestore == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
env->cansave++;
|
|
||||||
env->canrestore--;
|
|
||||||
#endif
|
|
||||||
save_window_offset(env, cwp1);
|
|
||||||
offset++;
|
|
||||||
}
|
|
||||||
cwp1 = cpu_cwp_inc(env, env->cwp + 1);
|
|
||||||
#ifndef TARGET_SPARC64
|
|
||||||
/* set wim so that restore will reload the registers */
|
|
||||||
env->wim = 1 << cwp1;
|
|
||||||
#endif
|
|
||||||
#if defined(DEBUG_WIN)
|
|
||||||
printf("flush_windows: nb=%d\n", offset - 1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void cpu_loop(CPUSPARCState *env)
|
|
||||||
{
|
|
||||||
CPUState *cs = env_cpu(env);
|
|
||||||
int trapnr, ret, syscall_nr;
|
|
||||||
/* target_siginfo_t info; */
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
cpu_exec_start(cs);
|
|
||||||
trapnr = cpu_exec(cs);
|
|
||||||
cpu_exec_end(cs);
|
|
||||||
process_queued_cpu_work(cs);
|
|
||||||
|
|
||||||
switch (trapnr) {
|
|
||||||
#ifndef TARGET_SPARC64
|
|
||||||
case 0x80:
|
|
||||||
#else
|
|
||||||
/* FreeBSD uses 0x141 for syscalls too */
|
|
||||||
case 0x141:
|
|
||||||
if (bsd_type != target_freebsd) {
|
|
||||||
goto badtrap;
|
|
||||||
}
|
|
||||||
/* fallthrough */
|
|
||||||
case 0x100:
|
|
||||||
#endif
|
|
||||||
syscall_nr = env->gregs[1];
|
|
||||||
if (bsd_type == target_freebsd)
|
|
||||||
ret = do_freebsd_syscall(env, syscall_nr,
|
|
||||||
env->regwptr[0], env->regwptr[1],
|
|
||||||
env->regwptr[2], env->regwptr[3],
|
|
||||||
env->regwptr[4], env->regwptr[5],
|
|
||||||
0, 0);
|
|
||||||
else if (bsd_type == target_netbsd)
|
|
||||||
ret = do_netbsd_syscall(env, syscall_nr,
|
|
||||||
env->regwptr[0], env->regwptr[1],
|
|
||||||
env->regwptr[2], env->regwptr[3],
|
|
||||||
env->regwptr[4], env->regwptr[5]);
|
|
||||||
else { /* if (bsd_type == target_openbsd) */
|
|
||||||
#if defined(TARGET_SPARC64)
|
|
||||||
syscall_nr &= ~(TARGET_OPENBSD_SYSCALL_G7RFLAG |
|
|
||||||
TARGET_OPENBSD_SYSCALL_G2RFLAG);
|
|
||||||
#endif
|
|
||||||
ret = do_openbsd_syscall(env, syscall_nr,
|
|
||||||
env->regwptr[0], env->regwptr[1],
|
|
||||||
env->regwptr[2], env->regwptr[3],
|
|
||||||
env->regwptr[4], env->regwptr[5]);
|
|
||||||
}
|
|
||||||
if ((unsigned int)ret >= (unsigned int)(-515)) {
|
|
||||||
ret = -ret;
|
|
||||||
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
|
|
||||||
env->xcc |= PSR_CARRY;
|
|
||||||
#else
|
|
||||||
env->psr |= PSR_CARRY;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
|
|
||||||
env->xcc &= ~PSR_CARRY;
|
|
||||||
#else
|
|
||||||
env->psr &= ~PSR_CARRY;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
env->regwptr[0] = ret;
|
|
||||||
/* next instruction */
|
|
||||||
#if defined(TARGET_SPARC64)
|
|
||||||
if (bsd_type == target_openbsd &&
|
|
||||||
env->gregs[1] & TARGET_OPENBSD_SYSCALL_G2RFLAG) {
|
|
||||||
env->pc = env->gregs[2];
|
|
||||||
env->npc = env->pc + 4;
|
|
||||||
} else if (bsd_type == target_openbsd &&
|
|
||||||
env->gregs[1] & TARGET_OPENBSD_SYSCALL_G7RFLAG) {
|
|
||||||
env->pc = env->gregs[7];
|
|
||||||
env->npc = env->pc + 4;
|
|
||||||
} else {
|
|
||||||
env->pc = env->npc;
|
|
||||||
env->npc = env->npc + 4;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
env->pc = env->npc;
|
|
||||||
env->npc = env->npc + 4;
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case 0x83: /* flush windows */
|
|
||||||
#ifdef TARGET_ABI32
|
|
||||||
case 0x103:
|
|
||||||
#endif
|
|
||||||
flush_windows(env);
|
|
||||||
/* next instruction */
|
|
||||||
env->pc = env->npc;
|
|
||||||
env->npc = env->npc + 4;
|
|
||||||
break;
|
|
||||||
#ifndef TARGET_SPARC64
|
|
||||||
case TT_WIN_OVF: /* window overflow */
|
|
||||||
save_window(env);
|
|
||||||
break;
|
|
||||||
case TT_WIN_UNF: /* window underflow */
|
|
||||||
restore_window(env);
|
|
||||||
break;
|
|
||||||
case TT_TFAULT:
|
|
||||||
case TT_DFAULT:
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
case TT_SPILL: /* window overflow */
|
|
||||||
save_window(env);
|
|
||||||
break;
|
|
||||||
case TT_FILL: /* window underflow */
|
|
||||||
restore_window(env);
|
|
||||||
break;
|
|
||||||
case TT_TFAULT:
|
|
||||||
case TT_DFAULT:
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case EXCP_INTERRUPT:
|
|
||||||
/* just indicate that signals should be handled asap */
|
|
||||||
break;
|
|
||||||
case EXCP_DEBUG:
|
|
||||||
{
|
|
||||||
gdb_handlesig(cs, TARGET_SIGTRAP);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
#ifdef TARGET_SPARC64
|
|
||||||
badtrap:
|
|
||||||
#endif
|
|
||||||
printf("Unhandled trap: 0x%x\n", trapnr);
|
|
||||||
cpu_dump_state(cs, stderr, 0);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
process_pending_signals(env);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION
|
printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION
|
||||||
@ -552,7 +170,6 @@ static void usage(void)
|
|||||||
"-d item1[,...] enable logging of specified items\n"
|
"-d item1[,...] enable logging of specified items\n"
|
||||||
" (use '-d help' for a list of log items)\n"
|
" (use '-d help' for a list of log items)\n"
|
||||||
"-D logfile write logs to 'logfile' (default stderr)\n"
|
"-D logfile write logs to 'logfile' (default stderr)\n"
|
||||||
"-p pagesize set the host page size to 'pagesize'\n"
|
|
||||||
"-singlestep always run in singlestep mode\n"
|
"-singlestep always run in singlestep mode\n"
|
||||||
"-strace log system calls\n"
|
"-strace log system calls\n"
|
||||||
"-trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
|
"-trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
|
||||||
@ -572,11 +189,11 @@ static void usage(void)
|
|||||||
,
|
,
|
||||||
TARGET_NAME,
|
TARGET_NAME,
|
||||||
interp_prefix,
|
interp_prefix,
|
||||||
x86_stack_size);
|
target_dflssiz);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
THREAD CPUState *thread_cpu;
|
__thread CPUState *thread_cpu;
|
||||||
|
|
||||||
bool qemu_cpu_is_self(CPUState *cpu)
|
bool qemu_cpu_is_self(CPUState *cpu)
|
||||||
{
|
{
|
||||||
@ -601,6 +218,48 @@ void init_task_state(TaskState *ts)
|
|||||||
ts->sigqueue_table[i].next = NULL;
|
ts->sigqueue_table[i].next = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gemu_log(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
adjust_ssize(void)
|
||||||
|
{
|
||||||
|
struct rlimit rl;
|
||||||
|
|
||||||
|
if (getrlimit(RLIMIT_STACK, &rl) != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_maxssiz = MIN(target_maxssiz, rl.rlim_max);
|
||||||
|
target_dflssiz = MIN(MAX(target_dflssiz, rl.rlim_cur), target_maxssiz);
|
||||||
|
|
||||||
|
rl.rlim_max = target_maxssiz;
|
||||||
|
rl.rlim_cur = target_dflssiz;
|
||||||
|
setrlimit(RLIMIT_STACK, &rl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void save_proc_pathname(char *argv0)
|
||||||
|
{
|
||||||
|
int mib[4];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
mib[0] = CTL_KERN;
|
||||||
|
mib[1] = KERN_PROC;
|
||||||
|
mib[2] = KERN_PROC_PATHNAME;
|
||||||
|
mib[3] = -1;
|
||||||
|
|
||||||
|
len = sizeof(qemu_proc_pathname);
|
||||||
|
if (sysctl(mib, 4, qemu_proc_pathname, &len, NULL, 0)) {
|
||||||
|
perror("sysctl");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char *filename;
|
const char *filename;
|
||||||
@ -608,9 +267,11 @@ int main(int argc, char **argv)
|
|||||||
const char *cpu_type;
|
const char *cpu_type;
|
||||||
const char *log_file = NULL;
|
const char *log_file = NULL;
|
||||||
const char *log_mask = NULL;
|
const char *log_mask = NULL;
|
||||||
|
const char *seed_optarg = NULL;
|
||||||
struct target_pt_regs regs1, *regs = ®s1;
|
struct target_pt_regs regs1, *regs = ®s1;
|
||||||
struct image_info info1, *info = &info1;
|
struct image_info info1, *info = &info1;
|
||||||
TaskState ts1, *ts = &ts1;
|
struct bsd_binprm bprm;
|
||||||
|
TaskState *ts;
|
||||||
CPUArchState *env;
|
CPUArchState *env;
|
||||||
CPUState *cpu;
|
CPUState *cpu;
|
||||||
int optind, rv;
|
int optind, rv;
|
||||||
@ -618,12 +279,17 @@ int main(int argc, char **argv)
|
|||||||
const char *gdbstub = NULL;
|
const char *gdbstub = NULL;
|
||||||
char **target_environ, **wrk;
|
char **target_environ, **wrk;
|
||||||
envlist_t *envlist = NULL;
|
envlist_t *envlist = NULL;
|
||||||
bsd_type = target_openbsd;
|
bsd_type = HOST_DEFAULT_BSD_TYPE;
|
||||||
|
char *argv0 = NULL;
|
||||||
|
|
||||||
|
adjust_ssize();
|
||||||
|
|
||||||
if (argc <= 1) {
|
if (argc <= 1) {
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
save_proc_pathname(argv[0]);
|
||||||
|
|
||||||
error_init(argv[0]);
|
error_init(argv[0]);
|
||||||
module_call_init(MODULE_INIT_TRACE);
|
module_call_init(MODULE_INIT_TRACE);
|
||||||
qemu_init_cpu_list();
|
qemu_init_cpu_list();
|
||||||
@ -678,14 +344,17 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
} else if (!strcmp(r, "s")) {
|
} else if (!strcmp(r, "s")) {
|
||||||
r = argv[optind++];
|
r = argv[optind++];
|
||||||
rv = qemu_strtoul(r, &r, 0, &x86_stack_size);
|
rv = qemu_strtoul(r, &r, 0, &target_dflssiz);
|
||||||
if (rv < 0 || x86_stack_size <= 0) {
|
if (rv < 0 || target_dflssiz <= 0) {
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
if (*r == 'M') {
|
if (*r == 'M') {
|
||||||
x86_stack_size *= MiB;
|
target_dflssiz *= 1024 * 1024;
|
||||||
} else if (*r == 'k' || *r == 'K') {
|
} else if (*r == 'k' || *r == 'K') {
|
||||||
x86_stack_size *= KiB;
|
target_dflssiz *= 1024;
|
||||||
|
}
|
||||||
|
if (target_dflssiz > target_maxssiz) {
|
||||||
|
usage();
|
||||||
}
|
}
|
||||||
} else if (!strcmp(r, "L")) {
|
} else if (!strcmp(r, "L")) {
|
||||||
interp_prefix = argv[optind++];
|
interp_prefix = argv[optind++];
|
||||||
@ -728,12 +397,16 @@ int main(int argc, char **argv)
|
|||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
optind++;
|
optind++;
|
||||||
|
} else if (!strcmp(r, "seed")) {
|
||||||
|
seed_optarg = optarg;
|
||||||
} else if (!strcmp(r, "singlestep")) {
|
} else if (!strcmp(r, "singlestep")) {
|
||||||
singlestep = 1;
|
singlestep = 1;
|
||||||
} else if (!strcmp(r, "strace")) {
|
} else if (!strcmp(r, "strace")) {
|
||||||
do_strace = 1;
|
do_strace = 1;
|
||||||
} else if (!strcmp(r, "trace")) {
|
} else if (!strcmp(r, "trace")) {
|
||||||
trace_opt_parse(optarg);
|
trace_opt_parse(optarg);
|
||||||
|
} else if (!strcmp(r, "0")) {
|
||||||
|
argv0 = argv[optind++];
|
||||||
} else {
|
} else {
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
@ -757,6 +430,9 @@ int main(int argc, char **argv)
|
|||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
filename = argv[optind];
|
filename = argv[optind];
|
||||||
|
if (argv0) {
|
||||||
|
argv[optind] = argv0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!trace_init_backends()) {
|
if (!trace_init_backends()) {
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -766,6 +442,9 @@ int main(int argc, char **argv)
|
|||||||
/* Zero out regs */
|
/* Zero out regs */
|
||||||
memset(regs, 0, sizeof(struct target_pt_regs));
|
memset(regs, 0, sizeof(struct target_pt_regs));
|
||||||
|
|
||||||
|
/* Zero bsd params */
|
||||||
|
memset(&bprm, 0, sizeof(bprm));
|
||||||
|
|
||||||
/* Zero out image_info */
|
/* Zero out image_info */
|
||||||
memset(info, 0, sizeof(struct image_info));
|
memset(info, 0, sizeof(struct image_info));
|
||||||
|
|
||||||
@ -773,24 +452,11 @@ int main(int argc, char **argv)
|
|||||||
init_paths(interp_prefix);
|
init_paths(interp_prefix);
|
||||||
|
|
||||||
if (cpu_model == NULL) {
|
if (cpu_model == NULL) {
|
||||||
#if defined(TARGET_I386)
|
cpu_model = TARGET_DEFAULT_CPU_MODEL;
|
||||||
#ifdef TARGET_X86_64
|
|
||||||
cpu_model = "qemu64";
|
|
||||||
#else
|
|
||||||
cpu_model = "qemu32";
|
|
||||||
#endif
|
|
||||||
#elif defined(TARGET_SPARC)
|
|
||||||
#ifdef TARGET_SPARC64
|
|
||||||
cpu_model = "TI UltraSparc II";
|
|
||||||
#else
|
|
||||||
cpu_model = "Fujitsu MB86904";
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
cpu_model = "any";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_type = parse_cpu_option(cpu_model);
|
cpu_type = parse_cpu_option(cpu_model);
|
||||||
|
|
||||||
/* init tcg before creating CPUs and to get qemu_host_page_size */
|
/* init tcg before creating CPUs and to get qemu_host_page_size */
|
||||||
{
|
{
|
||||||
AccelClass *ac = ACCEL_GET_CLASS(current_accel());
|
AccelClass *ac = ACCEL_GET_CLASS(current_accel());
|
||||||
@ -800,9 +466,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
cpu = cpu_create(cpu_type);
|
cpu = cpu_create(cpu_type);
|
||||||
env = cpu->env_ptr;
|
env = cpu->env_ptr;
|
||||||
#if defined(TARGET_SPARC) || defined(TARGET_PPC)
|
|
||||||
cpu_reset(cpu);
|
cpu_reset(cpu);
|
||||||
#endif
|
|
||||||
thread_cpu = cpu;
|
thread_cpu = cpu;
|
||||||
|
|
||||||
if (getenv("QEMU_STRACE")) {
|
if (getenv("QEMU_STRACE")) {
|
||||||
@ -812,36 +476,31 @@ int main(int argc, char **argv)
|
|||||||
target_environ = envlist_to_environ(envlist, NULL);
|
target_environ = envlist_to_environ(envlist, NULL);
|
||||||
envlist_free(envlist);
|
envlist_free(envlist);
|
||||||
|
|
||||||
|
if (reserved_va) {
|
||||||
|
mmap_next_start = reserved_va;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Error *err = NULL;
|
||||||
|
if (seed_optarg != NULL) {
|
||||||
|
qemu_guest_random_seed_main(seed_optarg, &err);
|
||||||
|
} else {
|
||||||
|
qcrypto_init(&err);
|
||||||
|
}
|
||||||
|
if (err) {
|
||||||
|
error_reportf_err(err, "cannot initialize crypto: ");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now that page sizes are configured we can do
|
* Now that page sizes are configured we can do
|
||||||
* proper page alignment for guest_base.
|
* proper page alignment for guest_base.
|
||||||
*/
|
*/
|
||||||
guest_base = HOST_PAGE_ALIGN(guest_base);
|
guest_base = HOST_PAGE_ALIGN(guest_base);
|
||||||
|
|
||||||
/*
|
if (loader_exec(filename, argv + optind, target_environ, regs, info,
|
||||||
* Read in mmap_min_addr kernel parameter. This value is used
|
&bprm) != 0) {
|
||||||
* When loading the ELF image to determine whether guest_base
|
|
||||||
* is needed.
|
|
||||||
*
|
|
||||||
* When user has explicitly set the quest base, we skip this
|
|
||||||
* test.
|
|
||||||
*/
|
|
||||||
if (!have_guest_base) {
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
fp = fopen("/proc/sys/vm/mmap_min_addr", "r");
|
|
||||||
if (fp != NULL) {
|
|
||||||
unsigned long tmp;
|
|
||||||
if (fscanf(fp, "%lu", &tmp) == 1) {
|
|
||||||
mmap_min_addr = tmp;
|
|
||||||
qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n",
|
|
||||||
mmap_min_addr);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loader_exec(filename, argv + optind, target_environ, regs, info) != 0) {
|
|
||||||
printf("Error loading %s\n", filename);
|
printf("Error loading %s\n", filename);
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
@ -869,6 +528,13 @@ int main(int argc, char **argv)
|
|||||||
qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry);
|
qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* build Task State */
|
||||||
|
ts = g_new0(TaskState, 1);
|
||||||
|
init_task_state(ts);
|
||||||
|
ts->info = info;
|
||||||
|
ts->bprm = &bprm;
|
||||||
|
cpu->opaque = ts;
|
||||||
|
|
||||||
target_set_brk(info->brk);
|
target_set_brk(info->brk);
|
||||||
syscall_init();
|
syscall_init();
|
||||||
signal_init();
|
signal_init();
|
||||||
@ -880,143 +546,7 @@ int main(int argc, char **argv)
|
|||||||
*/
|
*/
|
||||||
tcg_prologue_init(tcg_ctx);
|
tcg_prologue_init(tcg_ctx);
|
||||||
|
|
||||||
/* build Task State */
|
target_cpu_init(env, regs);
|
||||||
memset(ts, 0, sizeof(TaskState));
|
|
||||||
init_task_state(ts);
|
|
||||||
ts->info = info;
|
|
||||||
cpu->opaque = ts;
|
|
||||||
|
|
||||||
#if defined(TARGET_I386)
|
|
||||||
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
|
|
||||||
env->hflags |= HF_PE_MASK | HF_CPL_MASK;
|
|
||||||
if (env->features[FEAT_1_EDX] & CPUID_SSE) {
|
|
||||||
env->cr[4] |= CR4_OSFXSR_MASK;
|
|
||||||
env->hflags |= HF_OSFXSR_MASK;
|
|
||||||
}
|
|
||||||
#ifndef TARGET_ABI32
|
|
||||||
/* enable 64 bit mode if possible */
|
|
||||||
if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
|
|
||||||
fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
env->cr[4] |= CR4_PAE_MASK;
|
|
||||||
env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
|
|
||||||
env->hflags |= HF_LMA_MASK;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* flags setup : we activate the IRQs by default as in user mode */
|
|
||||||
env->eflags |= IF_MASK;
|
|
||||||
|
|
||||||
/* linux register setup */
|
|
||||||
#ifndef TARGET_ABI32
|
|
||||||
env->regs[R_EAX] = regs->rax;
|
|
||||||
env->regs[R_EBX] = regs->rbx;
|
|
||||||
env->regs[R_ECX] = regs->rcx;
|
|
||||||
env->regs[R_EDX] = regs->rdx;
|
|
||||||
env->regs[R_ESI] = regs->rsi;
|
|
||||||
env->regs[R_EDI] = regs->rdi;
|
|
||||||
env->regs[R_EBP] = regs->rbp;
|
|
||||||
env->regs[R_ESP] = regs->rsp;
|
|
||||||
env->eip = regs->rip;
|
|
||||||
#else
|
|
||||||
env->regs[R_EAX] = regs->eax;
|
|
||||||
env->regs[R_EBX] = regs->ebx;
|
|
||||||
env->regs[R_ECX] = regs->ecx;
|
|
||||||
env->regs[R_EDX] = regs->edx;
|
|
||||||
env->regs[R_ESI] = regs->esi;
|
|
||||||
env->regs[R_EDI] = regs->edi;
|
|
||||||
env->regs[R_EBP] = regs->ebp;
|
|
||||||
env->regs[R_ESP] = regs->esp;
|
|
||||||
env->eip = regs->eip;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* linux interrupt setup */
|
|
||||||
#ifndef TARGET_ABI32
|
|
||||||
env->idt.limit = 511;
|
|
||||||
#else
|
|
||||||
env->idt.limit = 255;
|
|
||||||
#endif
|
|
||||||
env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
|
|
||||||
PROT_READ | PROT_WRITE,
|
|
||||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
|
||||||
idt_table = g2h_untagged(env->idt.base);
|
|
||||||
set_idt(0, 0);
|
|
||||||
set_idt(1, 0);
|
|
||||||
set_idt(2, 0);
|
|
||||||
set_idt(3, 3);
|
|
||||||
set_idt(4, 3);
|
|
||||||
set_idt(5, 0);
|
|
||||||
set_idt(6, 0);
|
|
||||||
set_idt(7, 0);
|
|
||||||
set_idt(8, 0);
|
|
||||||
set_idt(9, 0);
|
|
||||||
set_idt(10, 0);
|
|
||||||
set_idt(11, 0);
|
|
||||||
set_idt(12, 0);
|
|
||||||
set_idt(13, 0);
|
|
||||||
set_idt(14, 0);
|
|
||||||
set_idt(15, 0);
|
|
||||||
set_idt(16, 0);
|
|
||||||
set_idt(17, 0);
|
|
||||||
set_idt(18, 0);
|
|
||||||
set_idt(19, 0);
|
|
||||||
set_idt(0x80, 3);
|
|
||||||
|
|
||||||
/* linux segment setup */
|
|
||||||
{
|
|
||||||
uint64_t *gdt_table;
|
|
||||||
env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
|
|
||||||
PROT_READ | PROT_WRITE,
|
|
||||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
|
||||||
env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
|
|
||||||
gdt_table = g2h_untagged(env->gdt.base);
|
|
||||||
#ifdef TARGET_ABI32
|
|
||||||
write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
|
|
||||||
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
|
|
||||||
(3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
|
|
||||||
#else
|
|
||||||
/* 64 bit code segment */
|
|
||||||
write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
|
|
||||||
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
|
|
||||||
DESC_L_MASK |
|
|
||||||
(3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
|
|
||||||
#endif
|
|
||||||
write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
|
|
||||||
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
|
|
||||||
(3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu_x86_load_seg(env, R_CS, __USER_CS);
|
|
||||||
cpu_x86_load_seg(env, R_SS, __USER_DS);
|
|
||||||
#ifdef TARGET_ABI32
|
|
||||||
cpu_x86_load_seg(env, R_DS, __USER_DS);
|
|
||||||
cpu_x86_load_seg(env, R_ES, __USER_DS);
|
|
||||||
cpu_x86_load_seg(env, R_FS, __USER_DS);
|
|
||||||
cpu_x86_load_seg(env, R_GS, __USER_DS);
|
|
||||||
/* This hack makes Wine work... */
|
|
||||||
env->segs[R_FS].selector = 0;
|
|
||||||
#else
|
|
||||||
cpu_x86_load_seg(env, R_DS, 0);
|
|
||||||
cpu_x86_load_seg(env, R_ES, 0);
|
|
||||||
cpu_x86_load_seg(env, R_FS, 0);
|
|
||||||
cpu_x86_load_seg(env, R_GS, 0);
|
|
||||||
#endif
|
|
||||||
#elif defined(TARGET_SPARC)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
env->pc = regs->pc;
|
|
||||||
env->npc = regs->npc;
|
|
||||||
env->y = regs->y;
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
env->gregs[i] = regs->u_regs[i];
|
|
||||||
}
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
env->regwptr[i] = regs->u_regs[i + 8];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#error unsupported target CPU
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (gdbstub) {
|
if (gdbstub) {
|
||||||
gdbserver_start(gdbstub);
|
gdbserver_start(gdbstub);
|
||||||
|
486
bsd-user/mmap.c
486
bsd-user/mmap.c
@ -20,8 +20,6 @@
|
|||||||
|
|
||||||
#include "qemu.h"
|
#include "qemu.h"
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "bsd-mman.h"
|
|
||||||
#include "exec/exec-all.h"
|
|
||||||
|
|
||||||
//#define DEBUG_MMAP
|
//#define DEBUG_MMAP
|
||||||
|
|
||||||
@ -70,8 +68,8 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
|
|||||||
int prot1, ret;
|
int prot1, ret;
|
||||||
|
|
||||||
#ifdef DEBUG_MMAP
|
#ifdef DEBUG_MMAP
|
||||||
printf("mprotect: start=0x" TARGET_FMT_lx
|
printf("mprotect: start=0x" TARGET_ABI_FMT_lx
|
||||||
" len=0x" TARGET_FMT_lx " prot=%c%c%c\n", start, len,
|
"len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c\n", start, len,
|
||||||
prot & PROT_READ ? 'r' : '-',
|
prot & PROT_READ ? 'r' : '-',
|
||||||
prot & PROT_WRITE ? 'w' : '-',
|
prot & PROT_WRITE ? 'w' : '-',
|
||||||
prot & PROT_EXEC ? 'x' : '-');
|
prot & PROT_EXEC ? 'x' : '-');
|
||||||
@ -190,90 +188,275 @@ static int mmap_frag(abi_ulong real_start,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static abi_ulong mmap_next_start = 0x40000000;
|
#if HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64
|
||||||
|
# define TASK_UNMAPPED_BASE (1ul << 38)
|
||||||
|
#else
|
||||||
|
# define TASK_UNMAPPED_BASE 0x40000000
|
||||||
|
#endif
|
||||||
|
abi_ulong mmap_next_start = TASK_UNMAPPED_BASE;
|
||||||
|
|
||||||
unsigned long last_brk;
|
unsigned long last_brk;
|
||||||
|
|
||||||
/* find a free memory area of size 'size'. The search starts at
|
/*
|
||||||
'start'. If 'start' == 0, then a default start address is used.
|
* Subroutine of mmap_find_vma, used when we have pre-allocated a chunk of guest
|
||||||
Return -1 if error.
|
* address space.
|
||||||
*/
|
*/
|
||||||
/* page_init() marks pages used by the host as reserved to be sure not
|
static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size,
|
||||||
to use them. */
|
abi_ulong alignment)
|
||||||
static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
|
|
||||||
{
|
{
|
||||||
abi_ulong addr, addr1, addr_start;
|
abi_ulong addr;
|
||||||
|
abi_ulong end_addr;
|
||||||
int prot;
|
int prot;
|
||||||
unsigned long new_brk;
|
int looped = 0;
|
||||||
|
|
||||||
new_brk = (unsigned long)sbrk(0);
|
if (size > reserved_va) {
|
||||||
if (last_brk && last_brk < new_brk && last_brk == (target_ulong)last_brk) {
|
return (abi_ulong)-1;
|
||||||
/* 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
|
size = HOST_PAGE_ALIGN(size) + alignment;
|
||||||
the first place, and maybe leave some slack to avoid switching
|
end_addr = start + size;
|
||||||
to mmap. */
|
if (end_addr > reserved_va) {
|
||||||
page_set_flags(last_brk & TARGET_PAGE_MASK,
|
end_addr = reserved_va;
|
||||||
TARGET_PAGE_ALIGN(new_brk),
|
}
|
||||||
PAGE_RESERVED);
|
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;
|
||||||
}
|
}
|
||||||
last_brk = new_brk;
|
|
||||||
|
|
||||||
size = HOST_PAGE_ALIGN(size);
|
size = HOST_PAGE_ALIGN(size);
|
||||||
start = start & qemu_host_page_mask;
|
|
||||||
addr = start;
|
if (reserved_va) {
|
||||||
if (addr == 0)
|
return mmap_find_vma_reserved(start, size,
|
||||||
addr = mmap_next_start;
|
(alignment != 0 ? 1 << alignment : 0));
|
||||||
addr_start = addr;
|
|
||||||
for (;;) {
|
|
||||||
prot = 0;
|
|
||||||
for (addr1 = addr; addr1 < (addr + size); addr1 += TARGET_PAGE_SIZE) {
|
|
||||||
prot |= page_get_flags(addr1);
|
|
||||||
}
|
|
||||||
if (prot == 0)
|
|
||||||
break;
|
|
||||||
addr += qemu_host_page_size;
|
|
||||||
/* we found nothing */
|
|
||||||
if (addr == addr_start)
|
|
||||||
return (abi_ulong)-1;
|
|
||||||
}
|
}
|
||||||
if (start == 0)
|
|
||||||
mmap_next_start = addr + size;
|
addr = start;
|
||||||
return addr;
|
wrapped = repeat = 0;
|
||||||
|
prev = 0;
|
||||||
|
flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
||||||
|
#ifdef MAP_ALIGNED
|
||||||
|
if (alignment != 0) {
|
||||||
|
flags |= MAP_ALIGNED(alignment);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* XXX TODO */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (;; prev = ptr) {
|
||||||
|
/*
|
||||||
|
* Reserve needed memory area to avoid a race.
|
||||||
|
* It should be discarded using:
|
||||||
|
* - mmap() with MAP_FIXED flag
|
||||||
|
* - mremap() with MREMAP_FIXED flag
|
||||||
|
* - shmat() with SHM_REMAP flag
|
||||||
|
*/
|
||||||
|
ptr = mmap(g2h_untagged(addr), size, PROT_NONE,
|
||||||
|
flags, -1, 0);
|
||||||
|
|
||||||
|
/* ENOMEM, if host address space has no memory */
|
||||||
|
if (ptr == MAP_FAILED) {
|
||||||
|
return (abi_ulong)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count the number of sequential returns of the same address.
|
||||||
|
* This is used to modify the search algorithm below.
|
||||||
|
*/
|
||||||
|
repeat = (ptr == prev ? repeat + 1 : 0);
|
||||||
|
|
||||||
|
if (h2g_valid(ptr + size - 1)) {
|
||||||
|
addr = h2g(ptr);
|
||||||
|
|
||||||
|
if ((addr & ~TARGET_PAGE_MASK) == 0) {
|
||||||
|
/* Success. */
|
||||||
|
if (start == mmap_next_start && addr >= TASK_UNMAPPED_BASE) {
|
||||||
|
mmap_next_start = addr + size;
|
||||||
|
}
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The address is not properly aligned for the target. */
|
||||||
|
switch (repeat) {
|
||||||
|
case 0:
|
||||||
|
/*
|
||||||
|
* Assume the result that the kernel gave us is the
|
||||||
|
* first with enough free space, so start again at the
|
||||||
|
* next higher target page.
|
||||||
|
*/
|
||||||
|
addr = TARGET_PAGE_ALIGN(addr);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
/*
|
||||||
|
* Sometimes the kernel decides to perform the allocation
|
||||||
|
* at the top end of memory instead.
|
||||||
|
*/
|
||||||
|
addr &= TARGET_PAGE_MASK;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
/* Start over at low memory. */
|
||||||
|
addr = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Fail. This unaligned block must the last. */
|
||||||
|
addr = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Since the result the kernel gave didn't fit, start
|
||||||
|
* again at low memory. If any repetition, fail.
|
||||||
|
*/
|
||||||
|
addr = (repeat ? -1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unmap and try again. */
|
||||||
|
munmap(ptr, size);
|
||||||
|
|
||||||
|
/* ENOMEM if we checked the whole of the target address space. */
|
||||||
|
if (addr == (abi_ulong)-1) {
|
||||||
|
return (abi_ulong)-1;
|
||||||
|
} else if (addr == 0) {
|
||||||
|
if (wrapped) {
|
||||||
|
return (abi_ulong)-1;
|
||||||
|
}
|
||||||
|
wrapped = 1;
|
||||||
|
/*
|
||||||
|
* Don't actually use 0 when wrapping, instead indicate
|
||||||
|
* that we'd truly like an allocation in low memory.
|
||||||
|
*/
|
||||||
|
addr = TARGET_PAGE_SIZE;
|
||||||
|
} else if (wrapped && addr >= start) {
|
||||||
|
return (abi_ulong)-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
|
||||||
|
{
|
||||||
|
return mmap_find_vma_aligned(start, size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: all the constants are the HOST ones */
|
/* NOTE: all the constants are the HOST ones */
|
||||||
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||||
int flags, int fd, abi_ulong offset)
|
int flags, int fd, off_t offset)
|
||||||
{
|
{
|
||||||
abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
|
abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
|
||||||
unsigned long host_start;
|
|
||||||
|
|
||||||
mmap_lock();
|
mmap_lock();
|
||||||
#ifdef DEBUG_MMAP
|
#ifdef DEBUG_MMAP
|
||||||
{
|
{
|
||||||
printf("mmap: start=0x" TARGET_FMT_lx
|
printf("mmap: start=0x" TARGET_ABI_FMT_lx
|
||||||
" len=0x" TARGET_FMT_lx " prot=%c%c%c flags=",
|
" len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c flags=",
|
||||||
start, len,
|
start, len,
|
||||||
prot & PROT_READ ? 'r' : '-',
|
prot & PROT_READ ? 'r' : '-',
|
||||||
prot & PROT_WRITE ? 'w' : '-',
|
prot & PROT_WRITE ? 'w' : '-',
|
||||||
prot & PROT_EXEC ? 'x' : '-');
|
prot & PROT_EXEC ? 'x' : '-');
|
||||||
if (flags & MAP_FIXED)
|
if (flags & MAP_ALIGNMENT_MASK) {
|
||||||
printf("MAP_FIXED ");
|
printf("MAP_ALIGNED(%u) ", (flags & MAP_ALIGNMENT_MASK)
|
||||||
if (flags & MAP_ANON)
|
>> MAP_ALIGNMENT_SHIFT);
|
||||||
printf("MAP_ANON ");
|
|
||||||
switch (flags & TARGET_BSD_MAP_FLAGMASK) {
|
|
||||||
case MAP_PRIVATE:
|
|
||||||
printf("MAP_PRIVATE ");
|
|
||||||
break;
|
|
||||||
case MAP_SHARED:
|
|
||||||
printf("MAP_SHARED ");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("[MAP_FLAGMASK=0x%x] ", flags & TARGET_BSD_MAP_FLAGMASK);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
printf("fd=%d offset=" TARGET_FMT_lx "\n", fd, offset);
|
#if MAP_GUARD
|
||||||
|
if (flags & MAP_GUARD) {
|
||||||
|
printf("MAP_GUARD ");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (flags & MAP_FIXED) {
|
||||||
|
printf("MAP_FIXED ");
|
||||||
|
}
|
||||||
|
if (flags & MAP_ANONYMOUS) {
|
||||||
|
printf("MAP_ANON ");
|
||||||
|
}
|
||||||
|
#ifdef MAP_EXCL
|
||||||
|
if (flags & MAP_EXCL) {
|
||||||
|
printf("MAP_EXCL ");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (flags & MAP_PRIVATE) {
|
||||||
|
printf("MAP_PRIVATE ");
|
||||||
|
}
|
||||||
|
if (flags & MAP_SHARED) {
|
||||||
|
printf("MAP_SHARED ");
|
||||||
|
}
|
||||||
|
if (flags & MAP_NOCORE) {
|
||||||
|
printf("MAP_NOCORE ");
|
||||||
|
}
|
||||||
|
#ifdef MAP_STACK
|
||||||
|
if (flags & MAP_STACK) {
|
||||||
|
printf("MAP_STACK ");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
printf("fd=%d offset=0x%llx\n", fd, offset);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((flags & MAP_ANONYMOUS) && fd != -1) {
|
||||||
|
errno = EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#ifdef MAP_STACK
|
||||||
|
if (flags & MAP_STACK) {
|
||||||
|
if ((fd != -1) || ((prot & (PROT_READ | PROT_WRITE)) !=
|
||||||
|
(PROT_READ | PROT_WRITE))) {
|
||||||
|
errno = EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* MAP_STACK */
|
||||||
|
#ifdef MAP_GUARD
|
||||||
|
if ((flags & MAP_GUARD) && (prot != PROT_NONE || fd != -1 ||
|
||||||
|
offset != 0 || (flags & (MAP_SHARED | MAP_PRIVATE |
|
||||||
|
/* MAP_PREFAULT | */ /* MAP_PREFAULT not in mman.h */
|
||||||
|
MAP_PREFAULT_READ | MAP_ANON | MAP_STACK)) != 0)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -283,37 +466,92 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
|||||||
}
|
}
|
||||||
|
|
||||||
len = TARGET_PAGE_ALIGN(len);
|
len = TARGET_PAGE_ALIGN(len);
|
||||||
if (len == 0)
|
if (len == 0) {
|
||||||
goto the_end;
|
errno = EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
real_start = start & qemu_host_page_mask;
|
real_start = start & qemu_host_page_mask;
|
||||||
|
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)) {
|
if (!(flags & MAP_FIXED)) {
|
||||||
abi_ulong mmap_start;
|
|
||||||
void *p;
|
|
||||||
host_offset = offset & qemu_host_page_mask;
|
|
||||||
host_len = len + offset - host_offset;
|
host_len = len + offset - host_offset;
|
||||||
host_len = HOST_PAGE_ALIGN(host_len);
|
host_len = HOST_PAGE_ALIGN(host_len);
|
||||||
mmap_start = mmap_find_vma(real_start, host_len);
|
if ((flags & MAP_ALIGNMENT_MASK) != 0)
|
||||||
if (mmap_start == (abi_ulong)-1) {
|
start = mmap_find_vma_aligned(real_start, host_len,
|
||||||
|
(flags & MAP_ALIGNMENT_MASK) >> MAP_ALIGNMENT_SHIFT);
|
||||||
|
else
|
||||||
|
start = mmap_find_vma(real_start, host_len);
|
||||||
|
if (start == (abi_ulong)-1) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* Note: we prefer to control the mapping address. It is
|
}
|
||||||
especially important if qemu_host_page_size >
|
|
||||||
qemu_real_host_page_size */
|
/*
|
||||||
p = mmap(g2h_untagged(mmap_start),
|
* When mapping files into a memory area larger than the file, accesses
|
||||||
host_len, prot, flags | MAP_FIXED, fd, host_offset);
|
* to pages beyond the file size will cause a SIGBUS.
|
||||||
|
*
|
||||||
|
* For example, if mmaping a file of 100 bytes on a host with 4K pages
|
||||||
|
* emulating a target with 8K pages, the target expects to be able to
|
||||||
|
* access the first 8K. But the host will trap us on any access beyond
|
||||||
|
* 4K.
|
||||||
|
*
|
||||||
|
* When emulating a target with a larger page-size than the hosts, we
|
||||||
|
* may need to truncate file maps at EOF and add extra anonymous pages
|
||||||
|
* up to the targets page boundary.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((qemu_real_host_page_size < qemu_host_page_size) && fd != -1) {
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
if (fstat(fd, &sb) == -1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Are we trying to create a map beyond EOF?. */
|
||||||
|
if (offset + len > sb.st_size) {
|
||||||
|
/*
|
||||||
|
* If so, truncate the file map at eof aligned with
|
||||||
|
* the hosts real pagesize. Additional anonymous maps
|
||||||
|
* will be created beyond EOF.
|
||||||
|
*/
|
||||||
|
len = REAL_HOST_PAGE_ALIGN(sb.st_size - offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & MAP_FIXED)) {
|
||||||
|
unsigned long host_start;
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
host_len = len + offset - host_offset;
|
||||||
|
host_len = HOST_PAGE_ALIGN(host_len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: we prefer to control the mapping address. It is
|
||||||
|
* especially important if qemu_host_page_size >
|
||||||
|
* qemu_real_host_page_size
|
||||||
|
*/
|
||||||
|
p = mmap(g2h_untagged(start), host_len, prot,
|
||||||
|
flags | MAP_FIXED | ((fd != -1) ? MAP_ANONYMOUS : 0), -1, 0);
|
||||||
if (p == MAP_FAILED)
|
if (p == MAP_FAILED)
|
||||||
goto fail;
|
goto fail;
|
||||||
/* update start so that it points to the file position at 'offset' */
|
/* update start so that it points to the file position at 'offset' */
|
||||||
host_start = (unsigned long)p;
|
host_start = (unsigned long)p;
|
||||||
if (!(flags & MAP_ANON))
|
if (fd != -1) {
|
||||||
|
p = mmap(g2h_untagged(start), len, prot,
|
||||||
|
flags | MAP_FIXED, fd, host_offset);
|
||||||
|
if (p == MAP_FAILED) {
|
||||||
|
munmap(g2h_untagged(start), host_len);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
host_start += offset - host_offset;
|
host_start += offset - host_offset;
|
||||||
|
}
|
||||||
start = h2g(host_start);
|
start = h2g(host_start);
|
||||||
} else {
|
} else {
|
||||||
int flg;
|
|
||||||
target_ulong addr;
|
|
||||||
|
|
||||||
if (start & ~TARGET_PAGE_MASK) {
|
if (start & ~TARGET_PAGE_MASK) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -321,20 +559,28 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
|||||||
end = start + len;
|
end = start + len;
|
||||||
real_end = HOST_PAGE_ALIGN(end);
|
real_end = HOST_PAGE_ALIGN(end);
|
||||||
|
|
||||||
for (addr = real_start; addr < real_end; addr += TARGET_PAGE_SIZE) {
|
/*
|
||||||
flg = page_get_flags(addr);
|
* Test if requested memory area fits target address space
|
||||||
if (flg & PAGE_RESERVED) {
|
* It can fail only on 64-bit host with 32-bit target.
|
||||||
errno = ENXIO;
|
* On any other target/host host mmap() handles this error correctly.
|
||||||
goto fail;
|
*/
|
||||||
}
|
#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) &&
|
if (!(flags & MAP_ANON) &&
|
||||||
(offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) {
|
(offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) {
|
||||||
/* msync() won't work here, so we return an error if write is
|
/*
|
||||||
possible while it is a shared mapping */
|
* msync() won't work here, so we return an error if write is
|
||||||
|
* possible while it is a shared mapping
|
||||||
|
*/
|
||||||
if ((flags & TARGET_BSD_MAP_FLAGMASK) == MAP_SHARED &&
|
if ((flags & TARGET_BSD_MAP_FLAGMASK) == MAP_SHARED &&
|
||||||
(prot & PROT_WRITE)) {
|
(prot & PROT_WRITE)) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
@ -375,7 +621,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
|||||||
/* handle the end of the mapping */
|
/* handle the end of the mapping */
|
||||||
if (end < real_end) {
|
if (end < real_end) {
|
||||||
ret = mmap_frag(real_end - qemu_host_page_size,
|
ret = mmap_frag(real_end - qemu_host_page_size,
|
||||||
real_end - qemu_host_page_size, real_end,
|
real_end - qemu_host_page_size, end,
|
||||||
prot, flags, fd,
|
prot, flags, fd,
|
||||||
offset + real_end - qemu_host_page_size - start);
|
offset + real_end - qemu_host_page_size - start);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
@ -401,10 +647,11 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
|||||||
page_set_flags(start, start + len, prot | PAGE_VALID);
|
page_set_flags(start, start + len, prot | PAGE_VALID);
|
||||||
the_end:
|
the_end:
|
||||||
#ifdef DEBUG_MMAP
|
#ifdef DEBUG_MMAP
|
||||||
printf("ret=0x" TARGET_FMT_lx "\n", start);
|
printf("ret=0x" TARGET_ABI_FMT_lx "\n", start);
|
||||||
page_dump(stdout);
|
page_dump(stdout);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
#endif
|
#endif
|
||||||
|
tb_invalidate_phys_range(start, start + len);
|
||||||
mmap_unlock();
|
mmap_unlock();
|
||||||
return start;
|
return start;
|
||||||
fail:
|
fail:
|
||||||
@ -412,13 +659,58 @@ fail:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mmap_reserve(abi_ulong start, abi_ulong size)
|
||||||
|
{
|
||||||
|
abi_ulong real_start;
|
||||||
|
abi_ulong real_end;
|
||||||
|
abi_ulong addr;
|
||||||
|
abi_ulong end;
|
||||||
|
int prot;
|
||||||
|
|
||||||
|
real_start = start & qemu_host_page_mask;
|
||||||
|
real_end = HOST_PAGE_ALIGN(start + size);
|
||||||
|
end = start + size;
|
||||||
|
if (start > real_start) {
|
||||||
|
/* handle host page containing start */
|
||||||
|
prot = 0;
|
||||||
|
for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
|
||||||
|
prot |= page_get_flags(addr);
|
||||||
|
}
|
||||||
|
if (real_end == real_start + qemu_host_page_size) {
|
||||||
|
for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
|
||||||
|
prot |= page_get_flags(addr);
|
||||||
|
}
|
||||||
|
end = real_end;
|
||||||
|
}
|
||||||
|
if (prot != 0) {
|
||||||
|
real_start += qemu_host_page_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (end < real_end) {
|
||||||
|
prot = 0;
|
||||||
|
for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
|
||||||
|
prot |= page_get_flags(addr);
|
||||||
|
}
|
||||||
|
if (prot != 0) {
|
||||||
|
real_end -= qemu_host_page_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (real_start != real_end) {
|
||||||
|
mmap(g2h_untagged(real_start), real_end - real_start, PROT_NONE,
|
||||||
|
MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE,
|
||||||
|
-1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int target_munmap(abi_ulong start, abi_ulong len)
|
int target_munmap(abi_ulong start, abi_ulong len)
|
||||||
{
|
{
|
||||||
abi_ulong end, real_start, real_end, addr;
|
abi_ulong end, real_start, real_end, addr;
|
||||||
int prot, ret;
|
int prot, ret;
|
||||||
|
|
||||||
#ifdef DEBUG_MMAP
|
#ifdef DEBUG_MMAP
|
||||||
printf("munmap: start=0x%lx len=0x%lx\n", start, len);
|
printf("munmap: start=0x" TARGET_ABI_FMT_lx " len=0x"
|
||||||
|
TARGET_ABI_FMT_lx "\n",
|
||||||
|
start, len);
|
||||||
#endif
|
#endif
|
||||||
if (start & ~TARGET_PAGE_MASK)
|
if (start & ~TARGET_PAGE_MASK)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -457,11 +749,17 @@ int target_munmap(abi_ulong start, abi_ulong len)
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
/* unmap what we can */
|
/* unmap what we can */
|
||||||
if (real_start < real_end) {
|
if (real_start < real_end) {
|
||||||
ret = munmap(g2h_untagged(real_start), real_end - real_start);
|
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);
|
page_set_flags(start, start + len, 0);
|
||||||
|
tb_invalidate_phys_range(start, start + len);
|
||||||
|
}
|
||||||
mmap_unlock();
|
mmap_unlock();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
25
bsd-user/netbsd/host-os.h
Normal file
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
|
#define QEMU_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "qemu/units.h"
|
||||||
#include "exec/cpu_ldst.h"
|
#include "exec/cpu_ldst.h"
|
||||||
|
#include "exec/exec-all.h"
|
||||||
|
|
||||||
#undef DEBUG_REMAP
|
#undef DEBUG_REMAP
|
||||||
#ifdef DEBUG_REMAP
|
|
||||||
#endif /* DEBUG_REMAP */
|
|
||||||
|
|
||||||
#include "exec/user/abitypes.h"
|
#include "exec/user/abitypes.h"
|
||||||
|
|
||||||
@ -36,22 +37,21 @@ enum BSDType {
|
|||||||
};
|
};
|
||||||
extern enum BSDType bsd_type;
|
extern enum BSDType bsd_type;
|
||||||
|
|
||||||
|
#include "exec/user/thunk.h"
|
||||||
|
#include "target_arch.h"
|
||||||
#include "syscall_defs.h"
|
#include "syscall_defs.h"
|
||||||
#include "target_syscall.h"
|
#include "target_syscall.h"
|
||||||
|
#include "target_os_vmparam.h"
|
||||||
|
#include "target_os_signal.h"
|
||||||
#include "exec/gdbstub.h"
|
#include "exec/gdbstub.h"
|
||||||
|
|
||||||
#if defined(CONFIG_USE_NPTL)
|
|
||||||
#define THREAD __thread
|
|
||||||
#else
|
|
||||||
#define THREAD
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This struct is used to hold certain information about the image. Basically,
|
* This struct is used to hold certain information about the image. Basically,
|
||||||
* it replicates in user space what would be certain task_struct fields in the
|
* it replicates in user space what would be certain task_struct fields in the
|
||||||
* kernel
|
* kernel
|
||||||
*/
|
*/
|
||||||
struct image_info {
|
struct image_info {
|
||||||
|
abi_ulong load_bias;
|
||||||
abi_ulong load_addr;
|
abi_ulong load_addr;
|
||||||
abi_ulong start_code;
|
abi_ulong start_code;
|
||||||
abi_ulong end_code;
|
abi_ulong end_code;
|
||||||
@ -66,7 +66,9 @@ struct image_info {
|
|||||||
abi_ulong entry;
|
abi_ulong entry;
|
||||||
abi_ulong code_offset;
|
abi_ulong code_offset;
|
||||||
abi_ulong data_offset;
|
abi_ulong data_offset;
|
||||||
int personality;
|
abi_ulong arg_start;
|
||||||
|
abi_ulong arg_end;
|
||||||
|
uint32_t elf_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_SIGQUEUE_SIZE 1024
|
#define MAX_SIGQUEUE_SIZE 1024
|
||||||
@ -89,6 +91,7 @@ typedef struct TaskState {
|
|||||||
pid_t ts_tid; /* tid (or pid) of this task */
|
pid_t ts_tid; /* tid (or pid) of this task */
|
||||||
|
|
||||||
struct TaskState *next;
|
struct TaskState *next;
|
||||||
|
struct bsd_binprm *bprm;
|
||||||
int used; /* non zero if used */
|
int used; /* non zero if used */
|
||||||
struct image_info *info;
|
struct image_info *info;
|
||||||
|
|
||||||
@ -102,14 +105,19 @@ typedef struct TaskState {
|
|||||||
|
|
||||||
void init_task_state(TaskState *ts);
|
void init_task_state(TaskState *ts);
|
||||||
extern const char *qemu_uname_release;
|
extern const char *qemu_uname_release;
|
||||||
extern unsigned long mmap_min_addr;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MAX_ARG_PAGES defines the number of pages allocated for arguments
|
* TARGET_ARG_MAX defines the number of bytes allocated for arguments
|
||||||
* and envelope for the new program. 32 should suffice, this gives
|
* and envelope for the new program. 256k should suffice for a reasonable
|
||||||
* a maximum env+arg of 128kB w/4KB pages!
|
* maxiumum env+arg in 32-bit environments, bump it up to 512k for !ILP32
|
||||||
|
* platforms.
|
||||||
*/
|
*/
|
||||||
#define MAX_ARG_PAGES 32
|
#if TARGET_ABI_BITS > 32
|
||||||
|
#define TARGET_ARG_MAX (512 * KiB)
|
||||||
|
#else
|
||||||
|
#define TARGET_ARG_MAX (256 * KiB)
|
||||||
|
#endif
|
||||||
|
#define MAX_ARG_PAGES (TARGET_ARG_MAX / TARGET_PAGE_SIZE)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This structure is used to hold the arguments that are
|
* This structure is used to hold the arguments that are
|
||||||
@ -119,24 +127,29 @@ struct bsd_binprm {
|
|||||||
char buf[128];
|
char buf[128];
|
||||||
void *page[MAX_ARG_PAGES];
|
void *page[MAX_ARG_PAGES];
|
||||||
abi_ulong p;
|
abi_ulong p;
|
||||||
|
abi_ulong stringp;
|
||||||
int fd;
|
int fd;
|
||||||
int e_uid, e_gid;
|
int e_uid, e_gid;
|
||||||
int argc, envc;
|
int argc, envc;
|
||||||
char **argv;
|
char **argv;
|
||||||
char **envp;
|
char **envp;
|
||||||
char *filename; /* Name of binary */
|
char *filename; /* (Given) Name of binary */
|
||||||
|
char *fullpath; /* Full path of binary */
|
||||||
|
int (*core_dump)(int, CPUArchState *);
|
||||||
};
|
};
|
||||||
|
|
||||||
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
|
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
|
||||||
abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
|
abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
|
||||||
abi_ulong stringp, int push_ptr);
|
abi_ulong stringp);
|
||||||
int loader_exec(const char *filename, char **argv, char **envp,
|
int loader_exec(const char *filename, char **argv, char **envp,
|
||||||
struct target_pt_regs *regs, struct image_info *infop);
|
struct target_pt_regs *regs, struct image_info *infop,
|
||||||
|
struct bsd_binprm *bprm);
|
||||||
|
|
||||||
int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
|
int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
|
||||||
struct image_info *info);
|
struct image_info *info);
|
||||||
int load_flt_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
|
int load_flt_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
|
||||||
struct image_info *info);
|
struct image_info *info);
|
||||||
|
int is_target_elf_binary(int fd);
|
||||||
|
|
||||||
abi_long memcpy_to_target(abi_ulong dest, const void *src,
|
abi_long memcpy_to_target(abi_ulong dest, const void *src,
|
||||||
unsigned long len);
|
unsigned long len);
|
||||||
@ -154,7 +167,7 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
|
|||||||
abi_long arg2, abi_long arg3, abi_long arg4,
|
abi_long arg2, abi_long arg3, abi_long arg4,
|
||||||
abi_long arg5, abi_long arg6);
|
abi_long arg5, abi_long arg6);
|
||||||
void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
||||||
extern THREAD CPUState *thread_cpu;
|
extern __thread CPUState *thread_cpu;
|
||||||
void cpu_loop(CPUArchState *env);
|
void cpu_loop(CPUArchState *env);
|
||||||
char *target_strerror(int err);
|
char *target_strerror(int err);
|
||||||
int get_osversion(void);
|
int get_osversion(void);
|
||||||
@ -201,18 +214,26 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
|
|||||||
/* mmap.c */
|
/* mmap.c */
|
||||||
int target_mprotect(abi_ulong start, abi_ulong len, int prot);
|
int target_mprotect(abi_ulong start, abi_ulong len, int prot);
|
||||||
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||||
int flags, int fd, abi_ulong offset);
|
int flags, int fd, off_t offset);
|
||||||
int target_munmap(abi_ulong start, abi_ulong len);
|
int target_munmap(abi_ulong start, abi_ulong len);
|
||||||
abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
|
abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
|
||||||
abi_ulong new_size, unsigned long flags,
|
abi_ulong new_size, unsigned long flags,
|
||||||
abi_ulong new_addr);
|
abi_ulong new_addr);
|
||||||
int target_msync(abi_ulong start, abi_ulong len, int flags);
|
int target_msync(abi_ulong start, abi_ulong len, int flags);
|
||||||
extern unsigned long last_brk;
|
extern unsigned long last_brk;
|
||||||
|
extern abi_ulong mmap_next_start;
|
||||||
|
abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size);
|
||||||
void mmap_fork_start(void);
|
void mmap_fork_start(void);
|
||||||
void mmap_fork_end(int child);
|
void mmap_fork_end(int child);
|
||||||
|
|
||||||
/* main.c */
|
/* main.c */
|
||||||
extern unsigned long x86_stack_size;
|
extern char qemu_proc_pathname[];
|
||||||
|
extern unsigned long target_maxtsiz;
|
||||||
|
extern unsigned long target_dfldsiz;
|
||||||
|
extern unsigned long target_maxdsiz;
|
||||||
|
extern unsigned long target_dflssiz;
|
||||||
|
extern unsigned long target_maxssiz;
|
||||||
|
extern unsigned long target_sgrowsiz;
|
||||||
|
|
||||||
/* user access */
|
/* user access */
|
||||||
|
|
||||||
@ -421,8 +442,6 @@ static inline void *lock_user_string(abi_ulong guest_addr)
|
|||||||
#define unlock_user_struct(host_ptr, guest_addr, copy) \
|
#define unlock_user_struct(host_ptr, guest_addr, copy) \
|
||||||
unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
|
unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
|
||||||
|
|
||||||
#if defined(CONFIG_USE_NPTL)
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* QEMU_H */
|
#endif /* QEMU_H */
|
||||||
|
@ -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
|
#endif
|
||||||
|
|
||||||
#ifdef TARGET_SPARC
|
|
||||||
static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
|
|
||||||
{
|
|
||||||
/* XXX handle
|
|
||||||
* TARGET_FREEBSD_SPARC_UTRAP_INSTALL,
|
|
||||||
* TARGET_FREEBSD_SPARC_SIGTRAMP_INSTALL
|
|
||||||
*/
|
|
||||||
return -TARGET_EINVAL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
/*
|
/*
|
||||||
* XXX this uses the undocumented oidfmt interface to find the kind of
|
* XXX this uses the undocumented oidfmt interface to find the kind of
|
||||||
|
@ -1,105 +1,26 @@
|
|||||||
/* $OpenBSD: signal.h,v 1.19 2006/01/08 14:20:16 millert Exp $ */
|
|
||||||
/* $NetBSD: signal.h,v 1.21 1996/02/09 18:25:32 christos Exp $ */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1989, 1991, 1993
|
* System call related declarations
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
* (c) UNIX System Laboratories, Inc.
|
|
||||||
* All or some portions of this file are derived from material licensed
|
|
||||||
* to the University of California by American Telephone and Telegraph
|
|
||||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
|
||||||
* the permission of UNIX System Laboratories, Inc.
|
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Copyright (c) 2013-15 Stacey D. Son (sson at FreeBSD)
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* it under the terms of the GNU General Public License as published by
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
* (at your option) any later version.
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
*
|
||||||
* @(#)signal.h 8.2 (Berkeley) 1/21/94
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define TARGET_NSIG 32 /* counting 0; could be 33 (mask is 1-32) */
|
#ifndef _SYSCALL_DEFS_H_
|
||||||
|
#define _SYSCALL_DEFS_H_
|
||||||
|
|
||||||
#define TARGET_SIGHUP 1 /* hangup */
|
#include <sys/syscall.h>
|
||||||
#define TARGET_SIGINT 2 /* interrupt */
|
|
||||||
#define TARGET_SIGQUIT 3 /* quit */
|
|
||||||
#define TARGET_SIGILL 4 /* illegal instruction (not reset when caught) */
|
|
||||||
#define TARGET_SIGTRAP 5 /* trace trap (not reset when caught) */
|
|
||||||
#define TARGET_SIGABRT 6 /* abort() */
|
|
||||||
#define TARGET_SIGIOT SIGABRT /* compatibility */
|
|
||||||
#define TARGET_SIGEMT 7 /* EMT instruction */
|
|
||||||
#define TARGET_SIGFPE 8 /* floating point exception */
|
|
||||||
#define TARGET_SIGKILL 9 /* kill (cannot be caught or ignored) */
|
|
||||||
#define TARGET_SIGBUS 10 /* bus error */
|
|
||||||
#define TARGET_SIGSEGV 11 /* segmentation violation */
|
|
||||||
#define TARGET_SIGSYS 12 /* bad argument to system call */
|
|
||||||
#define TARGET_SIGPIPE 13 /* write on a pipe with no one to read it */
|
|
||||||
#define TARGET_SIGALRM 14 /* alarm clock */
|
|
||||||
#define TARGET_SIGTERM 15 /* software termination signal from kill */
|
|
||||||
#define TARGET_SIGURG 16 /* urgent condition on IO channel */
|
|
||||||
#define TARGET_SIGSTOP 17 /* sendable stop signal not from tty */
|
|
||||||
#define TARGET_SIGTSTP 18 /* stop signal from tty */
|
|
||||||
#define TARGET_SIGCONT 19 /* continue a stopped process */
|
|
||||||
#define TARGET_SIGCHLD 20 /* to parent on child stop or exit */
|
|
||||||
#define TARGET_SIGTTIN 21 /* to readers pgrp upon background tty read */
|
|
||||||
#define TARGET_SIGTTOU 22 /* like TTIN for output if (tp->t_local<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 "errno_defs.h"
|
#include "errno_defs.h"
|
||||||
|
|
||||||
@ -107,8 +28,154 @@
|
|||||||
#include "netbsd/syscall_nr.h"
|
#include "netbsd/syscall_nr.h"
|
||||||
#include "openbsd/syscall_nr.h"
|
#include "openbsd/syscall_nr.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* machine/_types.h
|
||||||
|
* or x86/_types.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* time_t seems to be very inconsistly defined for the different *BSD's...
|
||||||
|
*
|
||||||
|
* FreeBSD uses a 64bits time_t except on i386
|
||||||
|
* so we have to add a special case here.
|
||||||
|
*
|
||||||
|
* On NetBSD time_t is always defined as an int64_t. On OpenBSD time_t
|
||||||
|
* is always defined as an int.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if (!defined(TARGET_I386))
|
||||||
|
typedef int64_t target_freebsd_time_t;
|
||||||
|
#else
|
||||||
|
typedef int32_t target_freebsd_time_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct target_iovec {
|
struct target_iovec {
|
||||||
abi_long iov_base; /* Starting address */
|
abi_long iov_base; /* Starting address */
|
||||||
abi_long iov_len; /* Number of bytes */
|
abi_long iov_len; /* Number of bytes */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sys/mman.h
|
||||||
|
*/
|
||||||
|
#define TARGET_FREEBSD_MAP_RESERVED0080 0x0080 /* previously misimplemented */
|
||||||
|
/* MAP_INHERIT */
|
||||||
|
#define TARGET_FREEBSD_MAP_RESERVED0100 0x0100 /* previously unimplemented */
|
||||||
|
/* MAP_NOEXTEND */
|
||||||
|
#define TARGET_FREEBSD_MAP_STACK 0x0400 /* region grows down, like a */
|
||||||
|
/* stack */
|
||||||
|
#define TARGET_FREEBSD_MAP_NOSYNC 0x0800 /* page to but do not sync */
|
||||||
|
/* underlying file */
|
||||||
|
|
||||||
|
#define TARGET_FREEBSD_MAP_FLAGMASK 0x1ff7
|
||||||
|
|
||||||
|
#define TARGET_NETBSD_MAP_INHERIT 0x0080 /* region is retained after */
|
||||||
|
/* exec */
|
||||||
|
#define TARGET_NETBSD_MAP_TRYFIXED 0x0400 /* attempt hint address, even */
|
||||||
|
/* within break */
|
||||||
|
#define TARGET_NETBSD_MAP_WIRED 0x0800 /* mlock() mapping when it is */
|
||||||
|
/* established */
|
||||||
|
|
||||||
|
#define TARGET_NETBSD_MAP_STACK 0x2000 /* allocated from memory, */
|
||||||
|
/* swap space (stack) */
|
||||||
|
|
||||||
|
#define TARGET_NETBSD_MAP_FLAGMASK 0x3ff7
|
||||||
|
|
||||||
|
#define TARGET_OPENBSD_MAP_INHERIT 0x0080 /* region is retained after */
|
||||||
|
/* exec */
|
||||||
|
#define TARGET_OPENBSD_MAP_NOEXTEND 0x0100 /* for MAP_FILE, don't change */
|
||||||
|
/* file size */
|
||||||
|
#define TARGET_OPENBSD_MAP_TRYFIXED 0x0400 /* attempt hint address, */
|
||||||
|
/* even within heap */
|
||||||
|
|
||||||
|
#define TARGET_OPENBSD_MAP_FLAGMASK 0x17f7
|
||||||
|
|
||||||
|
/* XXX */
|
||||||
|
#define TARGET_BSD_MAP_FLAGMASK 0x3ff7
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sys/time.h
|
||||||
|
* sys/timex.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef abi_long target_freebsd_suseconds_t;
|
||||||
|
|
||||||
|
/* compare to sys/timespec.h */
|
||||||
|
struct target_freebsd_timespec {
|
||||||
|
target_freebsd_time_t tv_sec; /* seconds */
|
||||||
|
abi_long tv_nsec; /* and nanoseconds */
|
||||||
|
#if !defined(TARGET_I386) && TARGET_ABI_BITS == 32
|
||||||
|
abi_long _pad;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TARGET_CPUCLOCK_WHICH_PID 0
|
||||||
|
#define TARGET_CPUCLOCK_WHICH_TID 1
|
||||||
|
|
||||||
|
/* sys/umtx.h */
|
||||||
|
struct target_freebsd__umtx_time {
|
||||||
|
struct target_freebsd_timespec _timeout;
|
||||||
|
uint32_t _flags;
|
||||||
|
uint32_t _clockid;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct target_freebsd_timeval {
|
||||||
|
target_freebsd_time_t tv_sec; /* seconds */
|
||||||
|
target_freebsd_suseconds_t tv_usec;/* and microseconds */
|
||||||
|
#if !defined(TARGET_I386) && TARGET_ABI_BITS == 32
|
||||||
|
abi_long _pad;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sys/resource.h
|
||||||
|
*/
|
||||||
|
#if defined(__FreeBSD__)
|
||||||
|
#define TARGET_RLIM_INFINITY RLIM_INFINITY
|
||||||
|
#else
|
||||||
|
#define TARGET_RLIM_INFINITY ((abi_ulong)-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TARGET_RLIMIT_CPU 0
|
||||||
|
#define TARGET_RLIMIT_FSIZE 1
|
||||||
|
#define TARGET_RLIMIT_DATA 2
|
||||||
|
#define TARGET_RLIMIT_STACK 3
|
||||||
|
#define TARGET_RLIMIT_CORE 4
|
||||||
|
#define TARGET_RLIMIT_RSS 5
|
||||||
|
#define TARGET_RLIMIT_MEMLOCK 6
|
||||||
|
#define TARGET_RLIMIT_NPROC 7
|
||||||
|
#define TARGET_RLIMIT_NOFILE 8
|
||||||
|
#define TARGET_RLIMIT_SBSIZE 9
|
||||||
|
#define TARGET_RLIMIT_AS 10
|
||||||
|
#define TARGET_RLIMIT_NPTS 11
|
||||||
|
#define TARGET_RLIMIT_SWAP 12
|
||||||
|
|
||||||
|
struct target_rlimit {
|
||||||
|
uint64_t rlim_cur;
|
||||||
|
uint64_t rlim_max;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct target_freebsd_rusage {
|
||||||
|
struct target_freebsd_timeval ru_utime; /* user time used */
|
||||||
|
struct target_freebsd_timeval ru_stime; /* system time used */
|
||||||
|
abi_long ru_maxrss; /* maximum resident set size */
|
||||||
|
abi_long ru_ixrss; /* integral shared memory size */
|
||||||
|
abi_long ru_idrss; /* integral unshared data size */
|
||||||
|
abi_long ru_isrss; /* integral unshared stack size */
|
||||||
|
abi_long ru_minflt; /* page reclaims */
|
||||||
|
abi_long ru_majflt; /* page faults */
|
||||||
|
abi_long ru_nswap; /* swaps */
|
||||||
|
abi_long ru_inblock; /* block input operations */
|
||||||
|
abi_long ru_oublock; /* block output operations */
|
||||||
|
abi_long ru_msgsnd; /* messages sent */
|
||||||
|
abi_long ru_msgrcv; /* messages received */
|
||||||
|
abi_long ru_nsignals; /* signals received */
|
||||||
|
abi_long ru_nvcsw; /* voluntary context switches */
|
||||||
|
abi_long ru_nivcsw; /* involuntary context switches */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct target_freebsd__wrusage {
|
||||||
|
struct target_freebsd_rusage wru_self;
|
||||||
|
struct target_freebsd_rusage wru_children;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* ! _SYSCALL_DEFS_H_ */
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* sparc64 dependent system call definitions
|
* Intel x86_64 specific prototypes for bsd-user
|
||||||
*
|
*
|
||||||
|
* Copyright (c) 2013 Stacey D. Son
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -15,23 +16,16 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#ifndef TARGET_SYSCALL_H
|
|
||||||
#define TARGET_SYSCALL_H
|
|
||||||
|
|
||||||
struct target_pt_regs {
|
#ifndef _TARGET_ARCH_H_
|
||||||
abi_ulong u_regs[16];
|
#define _TARGET_ARCH_H_
|
||||||
abi_ulong tstate;
|
|
||||||
abi_ulong pc;
|
|
||||||
abi_ulong npc;
|
|
||||||
abi_ulong y;
|
|
||||||
abi_ulong fprs;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define UNAME_MACHINE "sun4u"
|
/* target_arch_cpu.c */
|
||||||
#define TARGET_HW_MACHINE "sparc"
|
void bsd_x86_64_write_dt(void *ptr, unsigned long addr, unsigned long limit,
|
||||||
#define TARGET_HW_MACHINE_ARCH "sparc64"
|
int flags);
|
||||||
|
void bsd_x86_64_set_idt(int n, unsigned int dpl);
|
||||||
|
void bsd_x86_64_set_idt_base(uint64_t base);
|
||||||
|
|
||||||
#define TARGET_SPARC_UTRAP_INSTALL 1
|
#define target_cpu_set_tls(env, newtls)
|
||||||
#define TARGET_SPARC_SIGTRAMP_INSTALL 2
|
|
||||||
|
|
||||||
#endif /* TARGET_SYSCALL_H */
|
#endif /* !_TARGET_ARCH_H_ */
|
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)
|
FreeBSD)
|
||||||
bsd="yes"
|
bsd="yes"
|
||||||
|
bsd_user="yes"
|
||||||
make="${MAKE-gmake}"
|
make="${MAKE-gmake}"
|
||||||
audio_drv_list="oss try-sdl"
|
audio_drv_list="oss try-sdl"
|
||||||
audio_possible_drivers="oss sdl pa"
|
audio_possible_drivers="oss sdl pa"
|
||||||
@ -782,12 +783,6 @@ Linux)
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [ "$bsd" = "yes" ] ; then
|
|
||||||
if [ "$darwin" != "yes" ] ; then
|
|
||||||
bsd_user="yes"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
: ${make=${MAKE-make}}
|
: ${make=${MAKE-make}}
|
||||||
|
|
||||||
# We prefer python 3.x. A bare 'python' is traditionally
|
# We prefer python 3.x. A bare 'python' is traditionally
|
||||||
|
@ -2569,9 +2569,12 @@ foreach target : target_dirs
|
|||||||
if 'CONFIG_LINUX_USER' in config_target
|
if 'CONFIG_LINUX_USER' in config_target
|
||||||
base_dir = 'linux-user'
|
base_dir = 'linux-user'
|
||||||
target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
|
target_inc += include_directories('linux-user/host/' / config_host['ARCH'])
|
||||||
else
|
endif
|
||||||
|
if 'CONFIG_BSD_USER' in config_target
|
||||||
base_dir = 'bsd-user'
|
base_dir = 'bsd-user'
|
||||||
target_inc += include_directories('bsd-user/freebsd')
|
target_inc += include_directories('bsd-user/' / targetos)
|
||||||
|
dir = base_dir / abi
|
||||||
|
arch_srcs += files(dir / 'target_arch_cpu.c')
|
||||||
endif
|
endif
|
||||||
target_inc += include_directories(
|
target_inc += include_directories(
|
||||||
base_dir,
|
base_dir,
|
||||||
|
@ -132,9 +132,6 @@ class Indentation:
|
|||||||
def __init__(self, initial: int = 0) -> None:
|
def __init__(self, initial: int = 0) -> None:
|
||||||
self._level = initial
|
self._level = initial
|
||||||
|
|
||||||
def __int__(self) -> int:
|
|
||||||
return self._level
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "{}({:d})".format(type(self).__name__, self._level)
|
return "{}({:d})".format(type(self).__name__, self._level)
|
||||||
|
|
||||||
@ -142,19 +139,13 @@ class Indentation:
|
|||||||
"""Return the current indentation as a string of spaces."""
|
"""Return the current indentation as a string of spaces."""
|
||||||
return ' ' * self._level
|
return ' ' * self._level
|
||||||
|
|
||||||
def __bool__(self) -> bool:
|
|
||||||
"""True when there is a non-zero indentation."""
|
|
||||||
return bool(self._level)
|
|
||||||
|
|
||||||
def increase(self, amount: int = 4) -> None:
|
def increase(self, amount: int = 4) -> None:
|
||||||
"""Increase the indentation level by ``amount``, default 4."""
|
"""Increase the indentation level by ``amount``, default 4."""
|
||||||
self._level += amount
|
self._level += amount
|
||||||
|
|
||||||
def decrease(self, amount: int = 4) -> None:
|
def decrease(self, amount: int = 4) -> None:
|
||||||
"""Decrease the indentation level by ``amount``, default 4."""
|
"""Decrease the indentation level by ``amount``, default 4."""
|
||||||
if self._level < amount:
|
assert amount <= self._level
|
||||||
raise ArithmeticError(
|
|
||||||
f"Can't remove {amount:d} spaces from {self!r}")
|
|
||||||
self._level -= amount
|
self._level -= amount
|
||||||
|
|
||||||
|
|
||||||
@ -169,8 +160,9 @@ def cgen(code: str, **kwds: object) -> str:
|
|||||||
Obey `indent`, and strip `EATSPACE`.
|
Obey `indent`, and strip `EATSPACE`.
|
||||||
"""
|
"""
|
||||||
raw = code % kwds
|
raw = code % kwds
|
||||||
if indent:
|
pfx = str(indent)
|
||||||
raw = re.sub(r'^(?!(#|$))', str(indent), raw, flags=re.MULTILINE)
|
if pfx:
|
||||||
|
raw = re.sub(r'^(?!(#|$))', pfx, raw, flags=re.MULTILINE)
|
||||||
return re.sub(re.escape(EATSPACE) + r' *', '', raw)
|
return re.sub(re.escape(EATSPACE) + r' *', '', raw)
|
||||||
|
|
||||||
|
|
||||||
@ -205,7 +197,8 @@ def gen_ifcond(ifcond: Optional[Union[str, Dict[str, Any]]],
|
|||||||
cond_fmt: str, not_fmt: str,
|
cond_fmt: str, not_fmt: str,
|
||||||
all_operator: str, any_operator: str) -> str:
|
all_operator: str, any_operator: str) -> str:
|
||||||
|
|
||||||
def do_gen(ifcond: Union[str, Dict[str, Any]], need_parens: bool):
|
def do_gen(ifcond: Union[str, Dict[str, Any]],
|
||||||
|
need_parens: bool) -> str:
|
||||||
if isinstance(ifcond, str):
|
if isinstance(ifcond, str):
|
||||||
return cond_fmt % ifcond
|
return cond_fmt % ifcond
|
||||||
assert isinstance(ifcond, dict) and len(ifcond) == 1
|
assert isinstance(ifcond, dict) and len(ifcond) == 1
|
||||||
|
@ -293,17 +293,22 @@ def check_if(expr: _JSONObject, info: QAPISourceInfo, source: str) -> None:
|
|||||||
info,
|
info,
|
||||||
"'if' condition of %s has conflicting keys" % source)
|
"'if' condition of %s has conflicting keys" % source)
|
||||||
|
|
||||||
oper, operands = next(iter(cond.items()))
|
if 'not' in cond:
|
||||||
|
_check_if(cond['not'])
|
||||||
|
elif 'all' in cond:
|
||||||
|
_check_infix('all', cond['all'])
|
||||||
|
else:
|
||||||
|
_check_infix('any', cond['any'])
|
||||||
|
|
||||||
|
def _check_infix(operator: str, operands: object) -> None:
|
||||||
|
if not isinstance(operands, list):
|
||||||
|
raise QAPISemError(
|
||||||
|
info,
|
||||||
|
"'%s' condition of %s must be an array"
|
||||||
|
% (operator, source))
|
||||||
if not operands:
|
if not operands:
|
||||||
raise QAPISemError(
|
raise QAPISemError(
|
||||||
info, "'if' condition [] of %s is useless" % source)
|
info, "'if' condition [] of %s is useless" % source)
|
||||||
|
|
||||||
if oper == "not":
|
|
||||||
_check_if(operands)
|
|
||||||
return
|
|
||||||
if oper in ("all", "any") and not isinstance(operands, list):
|
|
||||||
raise QAPISemError(
|
|
||||||
info, "'%s' condition of %s must be an array" % (oper, source))
|
|
||||||
for operand in operands:
|
for operand in operands:
|
||||||
_check_if(operand)
|
_check_if(operand)
|
||||||
|
|
||||||
|
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-key.json',
|
||||||
'bad-if-keys.json',
|
'bad-if-keys.json',
|
||||||
'bad-if-list.json',
|
'bad-if-list.json',
|
||||||
|
'bad-if-not.json',
|
||||||
'bad-type-bool.json',
|
'bad-type-bool.json',
|
||||||
'bad-type-dict.json',
|
'bad-type-dict.json',
|
||||||
'bad-type-int.json',
|
'bad-type-int.json',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user