This series of patches gets me to the point that I can run "Hello World" on i386

and x86_64. This is for static binaries only, that are relatively small, but
 it's better than the 100% instant mmap failre that is the current state of all
 things bsd-user in upstream qemu. Future patch sets will refine this, add
 the missing system calls, fix bugs preventing more sophisticated programms
 from running and add a bunch of new architecture support.
 
 There's three large themes in these patches, though the changes that
 represent them are interrelated making it hard to separate out further.
 1. Reorganization to support multiple OS and architectures (though I've only
    tested FreeBSD, other BSDs might not even compile yet).
 2. Diff reduction with the bsd-user fork for several files. These diffs include
    changes that borrowed from linux-user as well as changes to make things work
    on FreeBSD. The records keeping when this was done, however, was poor at
    best, so many of the specific borrowings are going unacknowledged here, apart
    from this general ack. These diffs also include some minor code shuffling.
    Some of the changes are done specifically to make it easier to rebase
    the bsd-user fork's changes when these land in the tree (a number of changes
    have been pushed there to make this more possible).
 3. Filling in the missing pieces to make things work. There's many changes to
    elfload to make it load things in the right places, to find the interpreter
    better, etc. There's changes to mmap.c to make the mappings work better and
    there's changes to main.c that were inspired, at least, by now-ancient changes
    to linux-user's main.c.
 
 I ran checkpatch.pl on this, and there's 350-odd errors it identifies (the vast
 majoirty come from BSD's fetish for tabs), so there will need to be a V2 to fix
 this at the very least. In addition, the change set is big (about +~4.5k/-~2.5k
 lines), so I anticipate some iteration as well just based on its sheer
 size. I've tried to keep each set small to make it easy to review in isolation,
 but I've also allowed some interrelated ones to get a little bigger than I'd
 normally like. I've not done the customary documentation of the expected
 checkpatch.pl output because it is large, and because I wanted to get review
 of the other parts rolling to get this project unstuck. Future versions of the
 patch will document the expected output.
 
 In addition, I noticed a number of places where I could modernize to make the
 code match things like linux-user better. I've resisted the urge to do these at
 this time, since it would complicate merging the other ~30k lines of diff that
 remains after this batch. Future batches should generally be smaller once this
 one has landed since they are, by and large, either a bunch of new files to
 support armv7, aarch64, riscv64, mips, mipsel, mips64, ppc, ppc64 and ppc64le,
 or are adding system calls, which can be done individually or small groups. I've
 removed sparc and sparc64 support as they've been removed from FreeBSD and
 have been near totally busted for years.
 
 Stacey Son did the bulk of this work originally, but since I had to move things
 around so much and/or retool that work in non-trivial ways, I've kept myself as
 author, and added his signed-off-by line. I'm unsure of the qemu standard
 practice for this, but am happy to learn if this is too far outside its current
 mainstream. For a while Sean Bruno did the merges from upstream, and he's
 credited using his signed-off-by in appropriate places, though for this patch
 set there's only a few. I've tried to ensure that others who have work in
 individual patches that I've aggregated together also are reflected in their
 signed-off-by. Given the chaotic stat of the upstream repo for its early
 history, this may be the best that can be reconstructed at this late date. Most
 of these files are 'foundational' so have existed from the earliest days when
 record keeping wasn't quite what I'd wish for in hindsight. There was only
 really one change that I could easily cherry-pick (Colin's), so I did that.
 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - https://gpgtools.org
 
 iQIzBAABCgAdFiEEIDX4lLAKo898zeG3bBzRKH2wEQAFAmE7vugACgkQbBzRKH2w
 EQBdwhAA3q0ljnk893MdOXeiySKpBOYNddfxO824UrAD8wvjGzaXblLF11j4XD01
 C91CueP92cqHfv1umIwNPVkDcchJ52ouesapvyacN6VXMY6jrOJ0wb7rbMelx3G9
 ANrId0DZ0/WfLhqR7aLbds5lEIGh52KjczGlwru06DH6s/WwHjbCWLbjLkvrzxcw
 kthpCAeyLZl2xP6tALDVBF8bpcUoYpBR4tZtlq6Kx4YsUK40iYw5gvbInWEnhuu6
 wnTuvCyUWChGvOSGxxpjKqTFrreRGw3YeS/FfRfm96CkGUVDcJIqItXY5offSKAW
 6P7K8tUKsrJ+nPA2mm9UK9nFRqUgIDbKaVp/6YQlBYC+yGTOjXEiFuue4y/7OLy5
 Ncrqsjp+1hT4qUo7frWcmjlMVw8PWcDhoPRSwo6rk/rnz0gspIEgyzCXYa1F8R4d
 OEH/HRHzjp+DHQ9fQ7HH2ObXQ8b/kyM6Owq0VEFewBlHkrE5B7B0hcql5IBw+y2E
 KpnLyFzpaSy1PGgB0H2WVMWc//e+HI1Ywhe6HDS/YX9uTRqChQGMO7gGwUESm5k5
 U12KgwdA1xGn3t57rlxoYHgIm5VF4xTP25Ot2+uypmT1oHC4bDBWnq8Olm9BwqKa
 htqdBAmDgc6pIOx0VH2YGNeblIdj4/eO4Pj8gaVyDAvqly2Rw7A=
 =HpB5
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/bsdimp/tags/pull-bsd-user-20210910' into staging

This series of patches gets me to the point that I can run "Hello World" on i386
and x86_64. This is for static binaries only, that are relatively small, but
it's better than the 100% instant mmap failre that is the current state of all
things bsd-user in upstream qemu. Future patch sets will refine this, add
the missing system calls, fix bugs preventing more sophisticated programms
from running and add a bunch of new architecture support.

There's three large themes in these patches, though the changes that
represent them are interrelated making it hard to separate out further.
1. Reorganization to support multiple OS and architectures (though I've only
   tested FreeBSD, other BSDs might not even compile yet).
2. Diff reduction with the bsd-user fork for several files. These diffs include
   changes that borrowed from linux-user as well as changes to make things work
   on FreeBSD. The records keeping when this was done, however, was poor at
   best, so many of the specific borrowings are going unacknowledged here, apart
   from this general ack. These diffs also include some minor code shuffling.
   Some of the changes are done specifically to make it easier to rebase
   the bsd-user fork's changes when these land in the tree (a number of changes
   have been pushed there to make this more possible).
3. Filling in the missing pieces to make things work. There's many changes to
   elfload to make it load things in the right places, to find the interpreter
   better, etc. There's changes to mmap.c to make the mappings work better and
   there's changes to main.c that were inspired, at least, by now-ancient changes
   to linux-user's main.c.

I ran checkpatch.pl on this, and there's 350-odd errors it identifies (the vast
majoirty come from BSD's fetish for tabs), so there will need to be a V2 to fix
this at the very least. In addition, the change set is big (about +~4.5k/-~2.5k
lines), so I anticipate some iteration as well just based on its sheer
size. I've tried to keep each set small to make it easy to review in isolation,
but I've also allowed some interrelated ones to get a little bigger than I'd
normally like. I've not done the customary documentation of the expected
checkpatch.pl output because it is large, and because I wanted to get review
of the other parts rolling to get this project unstuck. Future versions of the
patch will document the expected output.

In addition, I noticed a number of places where I could modernize to make the
code match things like linux-user better. I've resisted the urge to do these at
this time, since it would complicate merging the other ~30k lines of diff that
remains after this batch. Future batches should generally be smaller once this
one has landed since they are, by and large, either a bunch of new files to
support armv7, aarch64, riscv64, mips, mipsel, mips64, ppc, ppc64 and ppc64le,
or are adding system calls, which can be done individually or small groups. I've
removed sparc and sparc64 support as they've been removed from FreeBSD and
have been near totally busted for years.

Stacey Son did the bulk of this work originally, but since I had to move things
around so much and/or retool that work in non-trivial ways, I've kept myself as
author, and added his signed-off-by line. I'm unsure of the qemu standard
practice for this, but am happy to learn if this is too far outside its current
mainstream. For a while Sean Bruno did the merges from upstream, and he's
credited using his signed-off-by in appropriate places, though for this patch
set there's only a few. I've tried to ensure that others who have work in
individual patches that I've aggregated together also are reflected in their
signed-off-by. Given the chaotic stat of the upstream repo for its early
history, this may be the best that can be reconstructed at this late date. Most
of these files are 'foundational' so have existed from the earliest days when
record keeping wasn't quite what I'd wish for in hindsight. There was only
really one change that I could easily cherry-pick (Colin's), so I did that.

# gpg: Signature made Fri 10 Sep 2021 21:24:08 BST
# gpg:                using RSA key 2035F894B00AA3CF7CCDE1B76C1CD1287DB01100
# gpg: Good signature from "Warner Losh <wlosh@netflix.com>" [unknown]
# gpg:                 aka "Warner Losh <imp@bsdimp.com>" [unknown]
# gpg:                 aka "Warner Losh <imp@freebsd.org>" [unknown]
# gpg:                 aka "Warner Losh <imp@village.org>" [unknown]
# gpg:                 aka "Warner Losh <wlosh@bsdimp.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 2035 F894 B00A A3CF 7CCD  E1B7 6C1C D128 7DB0 1100

* remotes/bsdimp/tags/pull-bsd-user-20210910: (42 commits)
  bsd-user: Update mapping to handle reserved and starting conditions
  bsd-user: Add '-0 argv0' option to bsd-user/main.c
  bsd-user: Implement interlock for atomic operations
  bsd-user: move gemu_log to later in the file
  bsd-user: Refactor load_elf_sections and is_target_elf_binary
  bsd-user: elfload.c style catch up patch
  bsd-user: add stubbed out core dump support
  bsd-user: Add target_os_user.h to capture the user/kernel structures
  bsd-user: Add target_arch_reg to describe a target's register set
  bsd-user: update debugging in mmap.c
  bsd-user: Rewrite target system call definintion glue
  bsd-user: Remove dead #ifdefs from elfload.c
  bsd-user: elf cleanup
  bsd-user: Add architecture specific signal tramp code
  bsd-user: Move stack initializtion into a per-os file.
  bsd-user: Implement --seed and initialize random state
  bsd-user: *BSD specific siginfo defintions
  bsd-user: Add system independent stack, data and text limiting
  bsd-user: Create target specific vmparam.h
  bsd-user: define max args in terms of pages
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-09-11 14:00:39 +01:00
commit 99c44988d5
51 changed files with 4401 additions and 2278 deletions

View file

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

View file

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

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

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,8 @@
/*
* qemu user main
* qemu bsd user main
*
* Copyright (c) 2003-2008 Fabrice Bellard
* Copyright (c) 2013-14 Stacey Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -17,6 +18,11 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/sysctl.h>
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/units.h"
@ -39,496 +45,108 @@
#include "qemu/cutils.h"
#include "exec/log.h"
#include "trace/control.h"
#include "crypto/init.h"
#include "qemu/guest-random.h"
#include "host-os.h"
#include "target_arch_cpu.h"
int singlestep;
unsigned long mmap_min_addr;
uintptr_t guest_base;
bool have_guest_base;
/*
* When running 32-on-64 we should make sure we can fit all of the possible
* guest address space into a contiguous chunk of virtual host memory.
*
* This way we will never overlap with our own libraries or binaries or stack
* or anything else that QEMU maps.
*
* Many cpus reserve the high bit (or more than one for some 64-bit cpus)
* of the address for the kernel. Some cpus rely on this and user space
* uses the high bit(s) for pointer tagging and the like. For them, we
* must preserve the expected address space.
*/
#ifndef MAX_RESERVED_VA
# if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
# if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \
(TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
/*
* There are a number of places where we assign reserved_va to a variable
* of type abi_ulong and expect it to fit. Avoid the last page.
*/
# define MAX_RESERVED_VA (0xfffffffful & TARGET_PAGE_MASK)
# else
# define MAX_RESERVED_VA (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
# endif
# else
# define MAX_RESERVED_VA 0
# endif
#endif
/*
* That said, reserving *too* much vm space via mmap can run into problems
* with rlimits, oom due to page table creation, etc. We will still try it,
* if directed by the command-line option, but not by default.
*/
#if HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32
unsigned long reserved_va = MAX_RESERVED_VA;
#else
unsigned long reserved_va;
#endif
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
const char *qemu_uname_release;
enum BSDType bsd_type;
char qemu_proc_pathname[PATH_MAX]; /* full path to exeutable */
/*
* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
* we allocate a bigger stack. Need a better solution, for example
* by remapping the process stack directly at the right place
*/
unsigned long x86_stack_size = 512 * 1024;
unsigned long target_maxtsiz = TARGET_MAXTSIZ; /* max text size */
unsigned long target_dfldsiz = TARGET_DFLDSIZ; /* initial data size limit */
unsigned long target_maxdsiz = TARGET_MAXDSIZ; /* max data size */
unsigned long target_dflssiz = TARGET_DFLSSIZ; /* initial data size limit */
unsigned long target_maxssiz = TARGET_MAXSSIZ; /* max stack size */
unsigned long target_sgrowsiz = TARGET_SGROWSIZ; /* amount to grow stack */
void gemu_log(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
#if defined(TARGET_I386)
int cpu_get_pic_interrupt(CPUX86State *env)
{
return -1;
}
#endif
/* Helper routines for implementing atomic operations. */
void fork_start(void)
{
start_exclusive();
cpu_list_lock();
mmap_fork_start();
}
void fork_end(int child)
{
if (child) {
CPUState *cpu, *next_cpu;
/*
* Child processes created by fork() only have a single thread. Discard
* information about the parent threads.
*/
CPU_FOREACH_SAFE(cpu, next_cpu) {
if (cpu != thread_cpu) {
QTAILQ_REMOVE_RCU(&cpus, cpu, node);
}
}
mmap_fork_end(child);
/*
* qemu_init_cpu_list() takes care of reinitializing the exclusive
* state, so we don't need to end_exclusive() here.
*/
qemu_init_cpu_list();
gdbserver_fork(thread_cpu);
} else {
mmap_fork_end(child);
cpu_list_unlock();
end_exclusive();
}
}
#ifdef TARGET_I386
/***********************************************************/
/* CPUX86 core interface */
uint64_t cpu_get_tsc(CPUX86State *env)
void cpu_loop(CPUArchState *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)
{
printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION
@ -552,7 +170,6 @@ static void usage(void)
"-d item1[,...] enable logging of specified items\n"
" (use '-d help' for a list of log items)\n"
"-D logfile write logs to 'logfile' (default stderr)\n"
"-p pagesize set the host page size to 'pagesize'\n"
"-singlestep always run in singlestep mode\n"
"-strace log system calls\n"
"-trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
@ -572,11 +189,11 @@ static void usage(void)
,
TARGET_NAME,
interp_prefix,
x86_stack_size);
target_dflssiz);
exit(1);
}
THREAD CPUState *thread_cpu;
__thread CPUState *thread_cpu;
bool qemu_cpu_is_self(CPUState *cpu)
{
@ -601,6 +218,48 @@ void init_task_state(TaskState *ts)
ts->sigqueue_table[i].next = NULL;
}
void gemu_log(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
static void
adjust_ssize(void)
{
struct rlimit rl;
if (getrlimit(RLIMIT_STACK, &rl) != 0) {
return;
}
target_maxssiz = MIN(target_maxssiz, rl.rlim_max);
target_dflssiz = MIN(MAX(target_dflssiz, rl.rlim_cur), target_maxssiz);
rl.rlim_max = target_maxssiz;
rl.rlim_cur = target_dflssiz;
setrlimit(RLIMIT_STACK, &rl);
}
static void save_proc_pathname(char *argv0)
{
int mib[4];
size_t len;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;
len = sizeof(qemu_proc_pathname);
if (sysctl(mib, 4, qemu_proc_pathname, &len, NULL, 0)) {
perror("sysctl");
}
}
int main(int argc, char **argv)
{
const char *filename;
@ -608,9 +267,11 @@ int main(int argc, char **argv)
const char *cpu_type;
const char *log_file = NULL;
const char *log_mask = NULL;
const char *seed_optarg = NULL;
struct target_pt_regs regs1, *regs = &regs1;
struct image_info info1, *info = &info1;
TaskState ts1, *ts = &ts1;
struct bsd_binprm bprm;
TaskState *ts;
CPUArchState *env;
CPUState *cpu;
int optind, rv;
@ -618,12 +279,17 @@ int main(int argc, char **argv)
const char *gdbstub = NULL;
char **target_environ, **wrk;
envlist_t *envlist = NULL;
bsd_type = target_openbsd;
bsd_type = HOST_DEFAULT_BSD_TYPE;
char *argv0 = NULL;
adjust_ssize();
if (argc <= 1) {
usage();
}
save_proc_pathname(argv[0]);
error_init(argv[0]);
module_call_init(MODULE_INIT_TRACE);
qemu_init_cpu_list();
@ -678,14 +344,17 @@ int main(int argc, char **argv)
}
} else if (!strcmp(r, "s")) {
r = argv[optind++];
rv = qemu_strtoul(r, &r, 0, &x86_stack_size);
if (rv < 0 || x86_stack_size <= 0) {
rv = qemu_strtoul(r, &r, 0, &target_dflssiz);
if (rv < 0 || target_dflssiz <= 0) {
usage();
}
if (*r == 'M') {
x86_stack_size *= MiB;
target_dflssiz *= 1024 * 1024;
} else if (*r == 'k' || *r == 'K') {
x86_stack_size *= KiB;
target_dflssiz *= 1024;
}
if (target_dflssiz > target_maxssiz) {
usage();
}
} else if (!strcmp(r, "L")) {
interp_prefix = argv[optind++];
@ -728,12 +397,16 @@ int main(int argc, char **argv)
usage();
}
optind++;
} else if (!strcmp(r, "seed")) {
seed_optarg = optarg;
} else if (!strcmp(r, "singlestep")) {
singlestep = 1;
} else if (!strcmp(r, "strace")) {
do_strace = 1;
} else if (!strcmp(r, "trace")) {
trace_opt_parse(optarg);
} else if (!strcmp(r, "0")) {
argv0 = argv[optind++];
} else {
usage();
}
@ -757,6 +430,9 @@ int main(int argc, char **argv)
usage();
}
filename = argv[optind];
if (argv0) {
argv[optind] = argv0;
}
if (!trace_init_backends()) {
exit(1);
@ -766,6 +442,9 @@ int main(int argc, char **argv)
/* Zero out regs */
memset(regs, 0, sizeof(struct target_pt_regs));
/* Zero bsd params */
memset(&bprm, 0, sizeof(bprm));
/* Zero out image_info */
memset(info, 0, sizeof(struct image_info));
@ -773,24 +452,11 @@ int main(int argc, char **argv)
init_paths(interp_prefix);
if (cpu_model == NULL) {
#if defined(TARGET_I386)
#ifdef TARGET_X86_64
cpu_model = "qemu64";
#else
cpu_model = "qemu32";
#endif
#elif defined(TARGET_SPARC)
#ifdef TARGET_SPARC64
cpu_model = "TI UltraSparc II";
#else
cpu_model = "Fujitsu MB86904";
#endif
#else
cpu_model = "any";
#endif
cpu_model = TARGET_DEFAULT_CPU_MODEL;
}
cpu_type = parse_cpu_option(cpu_model);
/* init tcg before creating CPUs and to get qemu_host_page_size */
{
AccelClass *ac = ACCEL_GET_CLASS(current_accel());
@ -800,9 +466,7 @@ int main(int argc, char **argv)
}
cpu = cpu_create(cpu_type);
env = cpu->env_ptr;
#if defined(TARGET_SPARC) || defined(TARGET_PPC)
cpu_reset(cpu);
#endif
thread_cpu = cpu;
if (getenv("QEMU_STRACE")) {
@ -812,36 +476,31 @@ int main(int argc, char **argv)
target_environ = envlist_to_environ(envlist, NULL);
envlist_free(envlist);
if (reserved_va) {
mmap_next_start = reserved_va;
}
{
Error *err = NULL;
if (seed_optarg != NULL) {
qemu_guest_random_seed_main(seed_optarg, &err);
} else {
qcrypto_init(&err);
}
if (err) {
error_reportf_err(err, "cannot initialize crypto: ");
exit(1);
}
}
/*
* Now that page sizes are configured we can do
* proper page alignment for guest_base.
*/
guest_base = HOST_PAGE_ALIGN(guest_base);
/*
* Read in mmap_min_addr kernel parameter. This value is used
* When loading the ELF image to determine whether guest_base
* is needed.
*
* When user has explicitly set the quest base, we skip this
* test.
*/
if (!have_guest_base) {
FILE *fp;
fp = fopen("/proc/sys/vm/mmap_min_addr", "r");
if (fp != NULL) {
unsigned long tmp;
if (fscanf(fp, "%lu", &tmp) == 1) {
mmap_min_addr = tmp;
qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n",
mmap_min_addr);
}
fclose(fp);
}
}
if (loader_exec(filename, argv + optind, target_environ, regs, info) != 0) {
if (loader_exec(filename, argv + optind, target_environ, regs, info,
&bprm) != 0) {
printf("Error loading %s\n", filename);
_exit(1);
}
@ -869,6 +528,13 @@ int main(int argc, char **argv)
qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry);
}
/* build Task State */
ts = g_new0(TaskState, 1);
init_task_state(ts);
ts->info = info;
ts->bprm = &bprm;
cpu->opaque = ts;
target_set_brk(info->brk);
syscall_init();
signal_init();
@ -880,143 +546,7 @@ int main(int argc, char **argv)
*/
tcg_prologue_init(tcg_ctx);
/* build Task State */
memset(ts, 0, sizeof(TaskState));
init_task_state(ts);
ts->info = info;
cpu->opaque = ts;
#if defined(TARGET_I386)
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
env->hflags |= HF_PE_MASK | HF_CPL_MASK;
if (env->features[FEAT_1_EDX] & CPUID_SSE) {
env->cr[4] |= CR4_OSFXSR_MASK;
env->hflags |= HF_OSFXSR_MASK;
}
#ifndef TARGET_ABI32
/* enable 64 bit mode if possible */
if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
exit(1);
}
env->cr[4] |= CR4_PAE_MASK;
env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
env->hflags |= HF_LMA_MASK;
#endif
/* flags setup : we activate the IRQs by default as in user mode */
env->eflags |= IF_MASK;
/* linux register setup */
#ifndef TARGET_ABI32
env->regs[R_EAX] = regs->rax;
env->regs[R_EBX] = regs->rbx;
env->regs[R_ECX] = regs->rcx;
env->regs[R_EDX] = regs->rdx;
env->regs[R_ESI] = regs->rsi;
env->regs[R_EDI] = regs->rdi;
env->regs[R_EBP] = regs->rbp;
env->regs[R_ESP] = regs->rsp;
env->eip = regs->rip;
#else
env->regs[R_EAX] = regs->eax;
env->regs[R_EBX] = regs->ebx;
env->regs[R_ECX] = regs->ecx;
env->regs[R_EDX] = regs->edx;
env->regs[R_ESI] = regs->esi;
env->regs[R_EDI] = regs->edi;
env->regs[R_EBP] = regs->ebp;
env->regs[R_ESP] = regs->esp;
env->eip = regs->eip;
#endif
/* linux interrupt setup */
#ifndef TARGET_ABI32
env->idt.limit = 511;
#else
env->idt.limit = 255;
#endif
env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
idt_table = g2h_untagged(env->idt.base);
set_idt(0, 0);
set_idt(1, 0);
set_idt(2, 0);
set_idt(3, 3);
set_idt(4, 3);
set_idt(5, 0);
set_idt(6, 0);
set_idt(7, 0);
set_idt(8, 0);
set_idt(9, 0);
set_idt(10, 0);
set_idt(11, 0);
set_idt(12, 0);
set_idt(13, 0);
set_idt(14, 0);
set_idt(15, 0);
set_idt(16, 0);
set_idt(17, 0);
set_idt(18, 0);
set_idt(19, 0);
set_idt(0x80, 3);
/* linux segment setup */
{
uint64_t *gdt_table;
env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
gdt_table = g2h_untagged(env->gdt.base);
#ifdef TARGET_ABI32
write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
(3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
#else
/* 64 bit code segment */
write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
DESC_L_MASK |
(3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
#endif
write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
(3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
}
cpu_x86_load_seg(env, R_CS, __USER_CS);
cpu_x86_load_seg(env, R_SS, __USER_DS);
#ifdef TARGET_ABI32
cpu_x86_load_seg(env, R_DS, __USER_DS);
cpu_x86_load_seg(env, R_ES, __USER_DS);
cpu_x86_load_seg(env, R_FS, __USER_DS);
cpu_x86_load_seg(env, R_GS, __USER_DS);
/* This hack makes Wine work... */
env->segs[R_FS].selector = 0;
#else
cpu_x86_load_seg(env, R_DS, 0);
cpu_x86_load_seg(env, R_ES, 0);
cpu_x86_load_seg(env, R_FS, 0);
cpu_x86_load_seg(env, R_GS, 0);
#endif
#elif defined(TARGET_SPARC)
{
int i;
env->pc = regs->pc;
env->npc = regs->npc;
env->y = regs->y;
for (i = 0; i < 8; i++) {
env->gregs[i] = regs->u_regs[i];
}
for (i = 0; i < 8; i++) {
env->regwptr[i] = regs->u_regs[i + 8];
}
}
#else
#error unsupported target CPU
#endif
target_cpu_init(env, regs);
if (gdbstub) {
gdbserver_start(gdbstub);

View file

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

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

7
configure vendored
View file

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

View file

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