M68K
M: Paul Brook <paul@codesourcery.com>
-S: Maintained
+S: Odd Fixes
F: target-m68k/
MicroBlaze
MIPS
M: Aurelien Jarno <aurelien@aurel32.net>
-S: Maintained
+S: Odd Fixes
F: target-mips/
PowerPC
SH4
M: Aurelien Jarno <aurelien@aurel32.net>
-S: Maintained
+S: Odd Fixes
F: target-sh4/
SPARC
S: Maintained
F: bsd-user/
-Darwin user
-M: qemu-devel@nongnu.org
-S: Orphan
-F: darwin-user/
-
Linux user
M: Riku Voipio <riku.voipio@iki.fi>
S: Maintained
GENERATED_HEADERS += trace-dtrace.h
endif
GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
-GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
+GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c trace.c
# Don't try to regenerate Makefile or configure
# We don't generate any of them
rm -f qom/*.o qom/*.d
rm -f qemu-img-cmds.h
rm -f trace/*.o trace/*.d
- rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp
rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp
+ @# May not be present in GENERATED_HEADERS
rm -f trace-dtrace.h trace-dtrace.h-timestamp
- rm -f $(GENERATED_HEADERS)
- rm -f $(GENERATED_SOURCES)
+ rm -f $(foreach f,$(GENERATED_HEADERS),$(f) $(f)-timestamp)
+ rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp)
rm -rf $(qapi-dir)
$(MAKE) -C tests/tcg clean
for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \
pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
+qemu-icon.bmp \
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
mpc8544ds.dtb \
multiboot.bin linuxboot.bin kvmvapic.bin \
# trace
ifeq ($(TRACE_BACKEND),dtrace)
-trace.h: trace.h-timestamp trace-dtrace.h
-else
-trace.h: trace.h-timestamp
+TRACE_H_EXTRA_DEPS=trace-dtrace.h
endif
+trace.h: trace.h-timestamp $(TRACE_H_EXTRA_DEPS)
trace.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=h --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.h")
+ $(call quiet-command,$(TRACETOOL) \
+ --format=h \
+ --backend=$(TRACE_BACKEND) \
+ < $< > $@," GEN trace.h")
@cmp -s $@ trace.h || cp $@ trace.h
trace.c: trace.c-timestamp
trace.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=c --backend=$(TRACE_BACKEND) < $< > $@," GEN trace.c")
+ $(call quiet-command,$(TRACETOOL) \
+ --format=c \
+ --backend=$(TRACE_BACKEND) \
+ < $< > $@," GEN trace.c")
@cmp -s $@ trace.c || cp $@ trace.c
trace.o: trace.c $(GENERATED_HEADERS)
# rule file. So we use '.dtrace' instead
trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp
trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=d --backend=$(TRACE_BACKEND) < $< > $@," GEN trace-dtrace.dtrace")
+ $(call quiet-command,$(TRACETOOL) \
+ --format=d \
+ --backend=$(TRACE_BACKEND) \
+ < $< > $@," GEN trace-dtrace.dtrace")
@cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace
trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS)
- $(call quiet-command,dtrace -o $@ -G -s $<, " GEN trace-dtrace.o")
+ $(call quiet-command,dtrace -o $@ -G -s $<, " GEN trace-dtrace.o")
ifeq ($(LIBTOOL),)
trace-dtrace.lo: trace-dtrace.dtrace
endif
$(QEMU_PROG).stp: $(SRC_PATH)/trace-events
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \
+ $(call quiet-command,$(TRACETOOL) \
--format=stap \
--backend=$(TRACE_BACKEND) \
--binary=$(bindir)/$(QEMU_PROG) \
--target-arch=$(TARGET_ARCH) \
--target-type=$(TARGET_TYPE) \
- < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).stp")
+ < $< > $@," GEN $(QEMU_PROG).stp")
else
stap:
endif
endif
endif
libobj-y += helper.o
-ifeq ($(TARGET_BASE_ARCH), i386)
+ifneq ($(TARGET_BASE_ARCH), ppc)
libobj-y += cpu.o
endif
libobj-$(TARGET_SPARC64) += vis_helper.o
libobj-$(CONFIG_NEED_MMU) += mmu.o
libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
-libobj-$(TARGET_ARM) += cpu.o
-libobj-$(TARGET_CRIS) += cpu.o
-libobj-$(TARGET_LM32) += cpu.o
-libobj-$(TARGET_MICROBLAZE) += cpu.o
-libobj-$(TARGET_S390X) += cpu.o
ifeq ($(TARGET_BASE_ARCH), sparc)
libobj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o
-libobj-y += cpu.o
endif
libobj-$(TARGET_SPARC) += int32_helper.o
libobj-$(TARGET_SPARC64) += int64_helper.o
-libobj-$(TARGET_UNICORE32) += cpu.o
-libobj-$(TARGET_XTENSA) += cpu.o
libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
-libobj-$(TARGET_ALPHA) += cpu.o
libobj-y += disas.o
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
endif #CONFIG_LINUX_USER
-#########################################################
-# Darwin user emulator target
-
-ifdef CONFIG_DARWIN_USER
-
-$(call set-vpath, $(SRC_PATH)/darwin-user)
-
-QEMU_CFLAGS+=-I$(SRC_PATH)/darwin-user -I$(SRC_PATH)/darwin-user/$(TARGET_ARCH)
-
-# Leave some space for the regular program loading zone
-LDFLAGS+=-Wl,-segaddr,__STD_PROG_ZONE,0x1000 -image_base 0x0e000000
-
-LIBS+=-lmx
-
-obj-y = main.o commpage.o machload.o mmap.o signal.o syscall.o thunk.o \
- gdbstub.o user-exec.o
-
-obj-i386-y += ioport-user.o
-
-$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
-
-obj-y += $(addprefix ../, $(universal-obj-y))
-obj-y += $(addprefix ../libuser/, $(user-obj-y))
-obj-y += $(addprefix ../libdis-user/, $(libdis-y))
-obj-y += $(libobj-y)
-
-endif #CONFIG_DARWIN_USER
-
#########################################################
# BSD user emulator target
--- /dev/null
+#!/usr/bin/python
+##
+# QEMU Object Model test tools
+#
+# Copyright IBM, Corp. 2012
+#
+# Authors:
+# Anthony Liguori <aliguori@us.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later. See
+# the COPYING file in the top-level directory.
+##
+
+import fuse, stat
+from fuse import Fuse
+import os, posix
+from errno import *
+from qmp import QEMUMonitorProtocol
+
+fuse.fuse_python_api = (0, 2)
+
+class QOMFS(Fuse):
+ def __init__(self, qmp, *args, **kwds):
+ Fuse.__init__(self, *args, **kwds)
+ self.qmp = qmp
+ self.qmp.connect()
+ self.ino_map = {}
+ self.ino_count = 1
+
+ def get_ino(self, path):
+ if self.ino_map.has_key(path):
+ return self.ino_map[path]
+ self.ino_map[path] = self.ino_count
+ self.ino_count += 1
+ return self.ino_map[path]
+
+ def is_object(self, path):
+ try:
+ items = self.qmp.command('qom-list', path=path)
+ return True
+ except:
+ return False
+
+ def is_property(self, path):
+ try:
+ path, prop = path.rsplit('/', 1)
+ for item in self.qmp.command('qom-list', path=path):
+ if item['name'] == prop:
+ return True
+ return False
+ except:
+ return False
+
+ def is_link(self, path):
+ try:
+ path, prop = path.rsplit('/', 1)
+ for item in self.qmp.command('qom-list', path=path):
+ if item['name'] == prop:
+ if item['type'].startswith('link<'):
+ return True
+ return False
+ return False
+ except:
+ return False
+
+ def read(self, path, length, offset):
+ if not self.is_property(path):
+ return -ENOENT
+
+ path, prop = path.rsplit('/', 1)
+ try:
+ data = str(self.qmp.command('qom-get', path=path, property=prop))
+ data += '\n' # make values shell friendly
+ except:
+ return -EPERM
+
+ if offset > len(data):
+ return ''
+
+ return str(data[offset:][:length])
+
+ def readlink(self, path):
+ if not self.is_link(path):
+ return False
+ path, prop = path.rsplit('/', 1)
+ prefix = '/'.join(['..'] * (len(path.split('/')) - 1))
+ return prefix + str(self.qmp.command('qom-get', path=path,
+ property=prop))
+
+ def getattr(self, path):
+ if self.is_link(path):
+ value = posix.stat_result((0755 | stat.S_IFLNK,
+ self.get_ino(path),
+ 0,
+ 2,
+ 1000,
+ 1000,
+ 4096,
+ 0,
+ 0,
+ 0))
+ elif self.is_object(path):
+ value = posix.stat_result((0755 | stat.S_IFDIR,
+ self.get_ino(path),
+ 0,
+ 2,
+ 1000,
+ 1000,
+ 4096,
+ 0,
+ 0,
+ 0))
+ elif self.is_property(path):
+ value = posix.stat_result((0644 | stat.S_IFREG,
+ self.get_ino(path),
+ 0,
+ 1,
+ 1000,
+ 1000,
+ 4096,
+ 0,
+ 0,
+ 0))
+ else:
+ value = -ENOENT
+ return value
+
+ def readdir(self, path, offset):
+ yield fuse.Direntry('.')
+ yield fuse.Direntry('..')
+ for item in self.qmp.command('qom-list', path=path):
+ yield fuse.Direntry(str(item['name']))
+
+if __name__ == '__main__':
+ import sys, os
+
+ fs = QOMFS(QEMUMonitorProtocol(os.environ['QMP_SOCKET']))
+ fs.main(sys.argv)
bh->deleted = 1;
}
-void qemu_bh_update_timeout(int *timeout)
+void qemu_bh_update_timeout(uint32_t *timeout)
{
QEMUBH *bh;
pa_stream_unref (stream);
}
- qpa_logerr (pa_context_errno (g->context),
- "stream_new() failed\n");
+ *rerror = pa_context_errno (g->context);
return NULL;
}
}
if (value <= 0) {
- qerror_report(QERR_INVALID_PARAMETER_VALUE, "target", "a size");
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, "target", "a size");
return;
}
}
void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
- BlockDriverCompletionFunc *cb, void *opaque)
+ int64_t speed, BlockDriverCompletionFunc *cb,
+ void *opaque, Error **errp)
{
BlockJob *job;
if (bs->job || bdrv_in_use(bs)) {
+ error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
return NULL;
}
bdrv_set_in_use(bs, 1);
job->cb = cb;
job->opaque = opaque;
bs->job = job;
+
+ /* Only set speed when necessary to avoid NotSupported error */
+ if (speed != 0) {
+ Error *local_err = NULL;
+
+ block_job_set_speed(job, speed, &local_err);
+ if (error_is_set(&local_err)) {
+ bs->job = NULL;
+ g_free(job);
+ bdrv_set_in_use(bs, 0);
+ error_propagate(errp, local_err);
+ return NULL;
+ }
+ }
return job;
}
bdrv_set_in_use(bs, 0);
}
-int block_job_set_speed(BlockJob *job, int64_t value)
+void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
{
- int rc;
+ Error *local_err = NULL;
if (!job->job_type->set_speed) {
- return -ENOTSUP;
+ error_set(errp, QERR_NOT_SUPPORTED);
+ return;
}
- rc = job->job_type->set_speed(job, value);
- if (rc == 0) {
- job->speed = value;
+ job->job_type->set_speed(job, speed, &local_err);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
+ return;
}
- return rc;
+
+ job->speed = speed;
}
void block_job_cancel(BlockJob *job)
/* Now that we're connected, set the socket to be non-blocking and
* kick the reply mechanism. */
socket_set_nonblock(sock);
- qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL,
+ qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL,
nbd_have_request, s);
s->sock = sock;
#include "module.h"
#include "block/raw-posix-aio.h"
-#ifdef CONFIG_COCOA
+#if defined(__APPLE__) && (__MACH__)
#include <paths.h>
#include <sys/param.h>
#include <IOKit/IOKitLib.h>
}
if (size == 0)
#endif
-#ifdef CONFIG_COCOA
+#if defined(__APPLE__) && defined(__MACH__)
size = LONG_LONG_MAX;
#else
size = lseek(fd, 0LL, SEEK_END);
/***********************************************/
/* host device */
-#ifdef CONFIG_COCOA
+#if defined(__APPLE__) && defined(__MACH__)
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
{
BDRVRawState *s = bs->opaque;
-#ifdef CONFIG_COCOA
+#if defined(__APPLE__) && defined(__MACH__)
if (strstart(filename, "/dev/cdrom", NULL)) {
kern_return_t kernResult;
io_iterator_t mediaIterator;
block_job_complete(&s->common, ret);
}
-static int stream_set_speed(BlockJob *job, int64_t value)
+static void stream_set_speed(BlockJob *job, int64_t speed, Error **errp)
{
StreamBlockJob *s = container_of(job, StreamBlockJob, common);
- if (value < 0) {
- return -EINVAL;
+ if (speed < 0) {
+ error_set(errp, QERR_INVALID_PARAMETER, "speed");
+ return;
}
- ratelimit_set_speed(&s->limit, value / BDRV_SECTOR_SIZE);
- return 0;
+ ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE);
}
static BlockJobType stream_job_type = {
.set_speed = stream_set_speed,
};
-int stream_start(BlockDriverState *bs, BlockDriverState *base,
- const char *base_id, BlockDriverCompletionFunc *cb,
- void *opaque)
+void stream_start(BlockDriverState *bs, BlockDriverState *base,
+ const char *base_id, int64_t speed,
+ BlockDriverCompletionFunc *cb,
+ void *opaque, Error **errp)
{
StreamBlockJob *s;
Coroutine *co;
- s = block_job_create(&stream_job_type, bs, cb, opaque);
+ s = block_job_create(&stream_job_type, bs, speed, cb, opaque, errp);
if (!s) {
- return -EBUSY; /* bs must already be in use */
+ return;
}
s->base = base;
co = qemu_coroutine_create(stream_run);
trace_stream_start(bs, base, s, co, opaque);
qemu_coroutine_enter(co, s);
- return 0;
}
const char *job_type;
/** Optional callback for job types that support setting a speed limit */
- int (*set_speed)(BlockJob *job, int64_t value);
+ void (*set_speed)(BlockJob *job, int64_t speed, Error **errp);
} BlockJobType;
/**
* block_job_create:
* @job_type: The class object for the newly-created job.
* @bs: The block
+ * @speed: The maximum speed, in bytes per second, or 0 for unlimited.
* @cb: Completion function for the job.
* @opaque: Opaque pointer value passed to @cb.
+ * @errp: Error object.
*
* Create a new long-running block device job and return it. The job
* will call @cb asynchronously when the job completes. Note that
* called from a wrapper that is specific to the job type.
*/
void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
- BlockDriverCompletionFunc *cb, void *opaque);
+ int64_t speed, BlockDriverCompletionFunc *cb,
+ void *opaque, Error **errp);
/**
* block_job_complete:
* block_job_set_speed:
* @job: The job to set the speed for.
* @speed: The new value
+ * @errp: Error object.
*
* Set a rate-limiting parameter for the job; the actual meaning may
* vary depending on the job type.
*/
-int block_job_set_speed(BlockJob *job, int64_t value);
+void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp);
/**
* block_job_cancel:
* flatten the whole backing file chain onto @bs.
* @base_id: The file name that will be written to @bs as the new
* backing file if the job completes. Ignored if @base is %NULL.
+ * @speed: The maximum speed, in bytes per second, or 0 for unlimited.
* @cb: Completion function for the job.
* @opaque: Opaque pointer value passed to @cb.
+ * @errp: Error object.
*
* Start a streaming operation on @bs. Clusters that are unallocated
* in @bs, but allocated in any image between @base and @bs (both
* streaming job, the backing file of @bs will be changed to
* @base_id in the written image and to @base in the live BlockDriverState.
*/
-int stream_start(BlockDriverState *bs, BlockDriverState *base,
- const char *base_id, BlockDriverCompletionFunc *cb,
- void *opaque);
+void stream_start(BlockDriverState *bs, BlockDriverState *base,
+ const char *base_id, int64_t speed,
+ BlockDriverCompletionFunc *cb,
+ void *opaque, Error **errp);
#endif /* BLOCK_INT_H */
}
void qmp_block_stream(const char *device, bool has_base,
- const char *base, Error **errp)
+ const char *base, bool has_speed,
+ int64_t speed, Error **errp)
{
BlockDriverState *bs;
BlockDriverState *base_bs = NULL;
- int ret;
+ Error *local_err = NULL;
bs = bdrv_find(device);
if (!bs) {
}
}
- ret = stream_start(bs, base_bs, base, block_stream_cb, bs);
- if (ret < 0) {
- switch (ret) {
- case -EBUSY:
- error_set(errp, QERR_DEVICE_IN_USE, device);
- return;
- default:
- error_set(errp, QERR_NOT_SUPPORTED);
- return;
- }
+ stream_start(bs, base_bs, base, has_speed ? speed : 0,
+ block_stream_cb, bs, &local_err);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
+ return;
}
/* Grab a reference so hotplug does not delete the BlockDriverState from
return bs->job;
}
-void qmp_block_job_set_speed(const char *device, int64_t value, Error **errp)
+void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp)
{
BlockJob *job = find_block_job(device);
return;
}
- if (block_job_set_speed(job, value) < 0) {
- error_set(errp, QERR_NOT_SUPPORTED);
- }
+ block_job_set_speed(job, speed, errp);
}
void qmp_block_job_cancel(const char *device, Error **errp)
cocoa="no"
softmmu="yes"
linux_user="no"
-darwin_user="no"
bsd_user="no"
guest_base=""
uname_release=""
else
QEMU_CFLAGS="-mdynamic-no-pic $QEMU_CFLAGS"
fi
- darwin_user="yes"
cocoa="yes"
audio_drv_list="coreaudio"
audio_possible_drivers="coreaudio sdl fmod"
if [ "$bsd" = "yes" ] ; then
if [ "$darwin" != "yes" ] ; then
usb="bsd"
+ bsd_user="yes"
fi
- bsd_user="yes"
fi
: ${make=${MAKE-make}}
;;
--enable-profiler) profiler="yes"
;;
+ --disable-cocoa) cocoa="no"
+ ;;
--enable-cocoa)
cocoa="yes" ;
sdl="no" ;
--disable-user)
linux_user="no" ;
bsd_user="no" ;
- darwin_user="no"
;;
--enable-user) ;;
--disable-linux-user) linux_user="no"
;;
--enable-linux-user) linux_user="yes"
;;
- --disable-darwin-user) darwin_user="no"
- ;;
- --enable-darwin-user) darwin_user="yes"
- ;;
--disable-bsd-user) bsd_user="no"
;;
--enable-bsd-user) bsd_user="yes"
s390x-linux-user \
"
fi
-# the following are Darwin specific
-if [ "$darwin_user" = "yes" ] ; then
- default_target_list="$default_target_list i386-darwin-user ppc-darwin-user "
-fi
# the following are BSD specific
if [ "$bsd_user" = "yes" ] ; then
default_target_list="${default_target_list}\
echo " --enable-virtfs enable VirtFS"
echo " --disable-vnc disable VNC"
echo " --enable-vnc enable VNC"
-echo " --enable-cocoa enable COCOA (Mac OS X only)"
+echo " --disable-cocoa disable Cocoa (Mac OS X only)"
+echo " --enable-cocoa enable Cocoa (default on Mac OS X)"
echo " --audio-drv-list=LIST set audio drivers list:"
echo " Available drivers: $audio_possible_drivers"
echo " --audio-card-list=LIST set list of emulated audio cards [$audio_card_list]"
echo " --disable-user disable all user emulation targets"
echo " --enable-linux-user enable all linux usermode emulation targets"
echo " --disable-linux-user disable all linux usermode emulation targets"
-echo " --enable-darwin-user enable all darwin usermode emulation targets"
-echo " --disable-darwin-user disable all darwin usermode emulation targets"
echo " --enable-bsd-user enable all BSD usermode emulation targets"
echo " --disable-bsd-user disable all BSD usermode emulation targets"
echo " --enable-guest-base enable GUEST_BASE support for usermode"
if test "$softmmu" = yes ; then
tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
if test "$virtfs" != no ; then
- if test "$linux" = yes && test "$attr" = yes ; then
+ if test "$cap" = yes && test "$linux" = yes && test "$attr" = yes ; then
virtfs=yes
- if test "$cap" = yes ; then
- tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)"
- fi
+ tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)"
else
if test "$virtfs" = yes; then
feature_not_found "virtfs"
target_softmmu="no"
target_user_only="no"
target_linux_user="no"
-target_darwin_user="no"
target_bsd_user="no"
case "$target" in
${target_arch2}-softmmu)
target_user_only="yes"
target_linux_user="yes"
;;
- ${target_arch2}-darwin-user)
- if test "$darwin" != "yes" ; then
- echo "ERROR: Target '$target' is only available on a Darwin host"
- exit 1
- fi
- target_user_only="yes"
- target_darwin_user="yes"
- ;;
${target_arch2}-bsd-user)
if test "$bsd" != "yes" ; then
echo "ERROR: Target '$target' is only available on a BSD host"
if test "$target_linux_user" = "yes" ; then
echo "CONFIG_LINUX_USER=y" >> $config_target_mak
fi
-if test "$target_darwin_user" = "yes" ; then
- echo "CONFIG_DARWIN_USER=y" >> $config_target_mak
-fi
list=""
if test ! -z "$gdb_xml_files" ; then
for x in $gdb_xml_files; do
+++ /dev/null
- /*
- * Commpage syscalls
- *
- * Copyright (c) 2006 Pierre d'Herbemont
- *
- * 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 <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include <mach/message.h>
-#include <mach/mach.h>
-#include <mach/mach_time.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#include <libkern/OSAtomic.h>
-
-#include "qemu.h"
-
-//#define DEBUG_COMMPAGE
-
-#ifdef DEBUG_COMMPAGE
-# define DPRINTF(...) do { qemu_log(__VA_ARGS__); printf(__VA_ARGS__); } while(0)
-#else
-# define DPRINTF(...) do { qemu_log(__VA_ARGS__); } while(0)
-#endif
-
-/********************************************************************
- * Commpage definitions
- */
-#ifdef TARGET_I386
-/* Reserve space for the commpage see xnu/osfmk/i386/cpu_capabilities.h */
-# define COMMPAGE_START (-16 * 4096) /* base address is -20 * 4096 */
-# define COMMPAGE_SIZE (0x1240) /* _COMM_PAGE_AREA_LENGTH is 19 * 4096 */
-#elif defined(TARGET_PPC)
-/* Reserve space for the commpage see xnu/osfmk/ppc/cpu_capabilities.h */
-# define COMMPAGE_START (-8*4096)
-# define COMMPAGE_SIZE (2*4096) /* its _COMM_PAGE_AREA_USED but _COMM_PAGE_AREA_LENGTH is 7*4096 */
-#endif
-
-void do_compare_and_swap32(void *cpu_env, int num);
-void do_compare_and_swap64(void *cpu_env, int num);
-void do_add_atomic_word32(void *cpu_env, int num);
-void do_cgettimeofday(void *cpu_env, int num, uint32_t arg1);
-void do_nanotime(void *cpu_env, int num);
-
-void unimpl_commpage(void *cpu_env, int num);
-
-typedef void (*commpage_8args_function_t)(uint32_t arg1, uint32_t arg2, uint32_t arg3,
- uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
- uint32_t arg8);
-typedef void (*commpage_indirect_function_t)(void *cpu_env, int num, uint32_t arg1,
- uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5,
- uint32_t arg6, uint32_t arg7, uint32_t arg8);
-
-#define HAS_PTR 0x10
-#define NO_PTR 0x20
-#define CALL_DIRECT 0x1
-#define CALL_INDIRECT 0x2
-
-#define COMMPAGE_ENTRY(name, nargs, offset, func, options) \
- { #name, offset, nargs, options, (commpage_8args_function_t)func }
-
-struct commpage_entry {
- char * name;
- int offset;
- int nargs;
- char options;
- commpage_8args_function_t function;
-};
-
-static inline int commpage_code_num(struct commpage_entry *entry)
-{
- if((entry->options & HAS_PTR))
- return entry->offset + 4;
- else
- return entry->offset;
-}
-
-static inline int commpage_is_indirect(struct commpage_entry *entry)
-{
- return !(entry->options & CALL_DIRECT);
-}
-
-/********************************************************************
- * Commpage entry
- */
-static struct commpage_entry commpage_entries[] =
-{
- COMMPAGE_ENTRY(compare_and_swap32, 0, 0x080, do_compare_and_swap32, CALL_INDIRECT | HAS_PTR),
- COMMPAGE_ENTRY(compare_and_swap64, 0, 0x0c0, do_compare_and_swap64, CALL_INDIRECT | HAS_PTR),
- COMMPAGE_ENTRY(enqueue, 0, 0x100, unimpl_commpage, CALL_INDIRECT),
- COMMPAGE_ENTRY(dequeue, 0, 0x140, unimpl_commpage, CALL_INDIRECT),
- COMMPAGE_ENTRY(memory_barrier, 0, 0x180, unimpl_commpage, CALL_INDIRECT),
- COMMPAGE_ENTRY(add_atomic_word32, 0, 0x1a0, do_add_atomic_word32, CALL_INDIRECT | HAS_PTR),
- COMMPAGE_ENTRY(add_atomic_word64, 0, 0x1c0, unimpl_commpage, CALL_INDIRECT | HAS_PTR),
-
- COMMPAGE_ENTRY(mach_absolute_time, 0, 0x200, unimpl_commpage, CALL_INDIRECT),
- COMMPAGE_ENTRY(spinlock_try, 1, 0x220, unimpl_commpage, CALL_INDIRECT),
- COMMPAGE_ENTRY(spinlock_lock, 1, 0x260, OSSpinLockLock, CALL_DIRECT),
- COMMPAGE_ENTRY(spinlock_unlock, 1, 0x2a0, OSSpinLockUnlock, CALL_DIRECT),
- COMMPAGE_ENTRY(pthread_getspecific, 0, 0x2c0, unimpl_commpage, CALL_INDIRECT),
- COMMPAGE_ENTRY(gettimeofday, 1, 0x2e0, do_cgettimeofday, CALL_INDIRECT),
- COMMPAGE_ENTRY(sys_dcache_flush, 0, 0x4e0, unimpl_commpage, CALL_INDIRECT),
- COMMPAGE_ENTRY(sys_icache_invalidate, 0, 0x520, unimpl_commpage, CALL_INDIRECT),
- COMMPAGE_ENTRY(pthread_self, 0, 0x580, unimpl_commpage, CALL_INDIRECT),
-
- COMMPAGE_ENTRY(relinquish, 0, 0x5c0, unimpl_commpage, CALL_INDIRECT),
-
-#ifdef TARGET_I386
- COMMPAGE_ENTRY(bts, 0, 0x5e0, unimpl_commpage, CALL_INDIRECT),
- COMMPAGE_ENTRY(btc, 0, 0x5f0, unimpl_commpage, CALL_INDIRECT),
-#endif
-
- COMMPAGE_ENTRY(bzero, 2, 0x600, bzero, CALL_DIRECT),
- COMMPAGE_ENTRY(bcopy, 3, 0x780, bcopy, CALL_DIRECT),
- COMMPAGE_ENTRY(memcpy, 3, 0x7a0, memcpy, CALL_DIRECT),
-
-#ifdef TARGET_I386
- COMMPAGE_ENTRY(old_nanotime, 0, 0xf80, do_nanotime, CALL_INDIRECT),
- COMMPAGE_ENTRY(memset_pattern, 0, 0xf80, unimpl_commpage, CALL_INDIRECT),
- COMMPAGE_ENTRY(long_copy, 0, 0x1200, unimpl_commpage, CALL_INDIRECT),
-
- COMMPAGE_ENTRY(sysintegrity, 0, 0x1600, unimpl_commpage, CALL_INDIRECT),
-
- COMMPAGE_ENTRY(nanotime, 0, 0x1700, do_nanotime, CALL_INDIRECT),
-#elif TARGET_PPC
- COMMPAGE_ENTRY(compare_and_swap32b, 0, 0xf80, unimpl_commpage, CALL_INDIRECT),
- COMMPAGE_ENTRY(compare_and_swap64b, 0, 0xfc0, unimpl_commpage, CALL_INDIRECT),
- COMMPAGE_ENTRY(memset_pattern, 0, 0x1000, unimpl_commpage, CALL_INDIRECT),
- COMMPAGE_ENTRY(bigcopy, 0, 0x1140, unimpl_commpage, CALL_INDIRECT),
-#endif
-};
-
-
-/********************************************************************
- * Commpage backdoor
- */
-static inline void print_commpage_entry(struct commpage_entry entry)
-{
- printf("@0x%x %s\n", entry.offset, entry.name);
-}
-
-static inline void install_commpage_backdoor_for_entry(struct commpage_entry entry)
-{
-#ifdef TARGET_I386
- char * commpage = (char*)(COMMPAGE_START+entry.offset);
- int c = 0;
- if(entry.options & HAS_PTR)
- {
- commpage[c++] = (COMMPAGE_START+entry.offset+4) & 0xff;
- commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 8) & 0xff;
- commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 16) & 0xff;
- commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 24) & 0xff;
- }
- commpage[c++] = 0xcd;
- commpage[c++] = 0x79; /* int 0x79 */
- commpage[c++] = 0xc3; /* ret */
-#else
- qerror("can't install the commpage on this arch\n");
-#endif
-}
-
-/********************************************************************
- * Commpage initialization
- */
-void commpage_init(void)
-{
-#if (defined(__i386__) ^ defined(TARGET_I386)) || (defined(_ARCH_PPC) ^ defined(TARGET_PPC))
- int i;
- void * commpage = (void *)target_mmap( COMMPAGE_START, COMMPAGE_SIZE,
- PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_FIXED, -1, 0);
- if((int)commpage != COMMPAGE_START)
- qerror("can't allocate the commpage\n");
-
- bzero(commpage, COMMPAGE_SIZE);
-
- /* XXX: commpage data not handled */
-
- for(i = 0; i < ARRAY_SIZE(commpage_entries); i++)
- install_commpage_backdoor_for_entry(commpage_entries[i]);
-#else
- /* simply map our pages so they can be executed
- XXX: we don't really want to do that since in the ppc on ppc situation we may
- not able to run commpages host optimized instructions (like G5's on a G5),
- hence this is sometimes a broken fix. */
- page_set_flags(COMMPAGE_START, COMMPAGE_START+COMMPAGE_SIZE, PROT_EXEC | PROT_READ | PAGE_VALID);
-#endif
-}
-
-/********************************************************************
- * Commpage implementation
- */
-void do_compare_and_swap32(void *cpu_env, int num)
-{
-#ifdef TARGET_I386
- uint32_t old = ((CPUX86State*)cpu_env)->regs[R_EAX];
- uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_ECX];
- DPRINTF("commpage: compare_and_swap32(%x,new,%p)\n", old, value);
-
- if(old == tswap32(*value))
- {
- uint32_t new = ((CPUX86State*)cpu_env)->regs[R_EDX];
- *value = tswap32(new);
- /* set zf flag */
- ((CPUX86State*)cpu_env)->eflags |= 0x40;
- }
- else
- {
- ((CPUX86State*)cpu_env)->regs[R_EAX] = tswap32(*value);
- /* unset zf flag */
- ((CPUX86State*)cpu_env)->eflags &= ~0x40;
- }
-#else
- qerror("do_compare_and_swap32 unimplemented");
-#endif
-}
-
-void do_compare_and_swap64(void *cpu_env, int num)
-{
-#ifdef TARGET_I386
- /* OSAtomicCompareAndSwap64 is not available on non 64 bits ppc, here is a raw implementation */
- uint64_t old, new, swapped_val;
- uint64_t *value = (uint64_t*)((CPUX86State*)cpu_env)->regs[R_ESI];
- old = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_EDX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EAX];
-
- DPRINTF("commpage: compare_and_swap64(%" PRIx64 ",new,%p)\n", old, value);
- swapped_val = tswap64(*value);
-
- if(old == swapped_val)
- {
- new = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_ECX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EBX];
- *value = tswap64(new);
- /* set zf flag */
- ((CPUX86State*)cpu_env)->eflags |= 0x40;
- }
- else
- {
- ((CPUX86State*)cpu_env)->regs[R_EAX] = (uint32_t)(swapped_val);
- ((CPUX86State*)cpu_env)->regs[R_EDX] = (uint32_t)(swapped_val >> 32);
- /* unset zf flag */
- ((CPUX86State*)cpu_env)->eflags &= ~0x40;
- }
-#else
- qerror("do_compare_and_swap64 unimplemented");
-#endif
-}
-
-void do_add_atomic_word32(void *cpu_env, int num)
-{
-#ifdef TARGET_I386
- uint32_t amt = ((CPUX86State*)cpu_env)->regs[R_EAX];
- uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_EDX];
- uint32_t swapped_value = tswap32(*value);
-
- DPRINTF("commpage: add_atomic_word32(%x,%p)\n", amt, value);
-
- /* old value in EAX */
- ((CPUX86State*)cpu_env)->regs[R_EAX] = swapped_value;
- *value = tswap32(swapped_value + amt);
-#else
- qerror("do_add_atomic_word32 unimplemented");
-#endif
-}
-
-void do_cgettimeofday(void *cpu_env, int num, uint32_t arg1)
-{
-#ifdef TARGET_I386
- extern int __commpage_gettimeofday(struct timeval *);
- DPRINTF("commpage: gettimeofday(0x%x)\n", arg1);
- struct timeval *time = (struct timeval *)arg1;
- int ret = __commpage_gettimeofday(time);
- tswap32s((uint32_t*)&time->tv_sec);
- tswap32s((uint32_t*)&time->tv_usec);
- ((CPUX86State*)cpu_env)->regs[R_EAX] = ret; /* Success */
-#else
- qerror("do_gettimeofday unimplemented");
-#endif
-}
-
-void do_nanotime(void *cpu_env, int num)
-{
-#ifdef TARGET_I386
- uint64_t t = mach_absolute_time();
- ((CPUX86State*)cpu_env)->regs[R_EAX] = (int)(t & 0xffffffff);
- ((CPUX86State*)cpu_env)->regs[R_EDX] = (int)((t >> 32) & 0xffffffff);
-#else
- qerror("do_nanotime unimplemented");
-#endif
-}
-
-void unimpl_commpage(void *cpu_env, int num)
-{
- qerror("qemu: commpage function 0x%x not implemented\n", num);
-}
-
-/********************************************************************
- * do_commpage - called by the main cpu loop
- */
-void
-do_commpage(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
- uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
- uint32_t arg8)
-{
- int i, found = 0;
-
- arg1 = tswap32(arg1);
- arg2 = tswap32(arg2);
- arg3 = tswap32(arg3);
- arg4 = tswap32(arg4);
- arg5 = tswap32(arg5);
- arg6 = tswap32(arg6);
- arg7 = tswap32(arg7);
- arg8 = tswap32(arg8);
-
- num = num-COMMPAGE_START-2;
-
- for(i = 0; i < ARRAY_SIZE(commpage_entries); i++) {
- if( num == commpage_code_num(&commpage_entries[i]) )
- {
- DPRINTF("commpage: %s %s\n", commpage_entries[i].name, commpage_is_indirect(&commpage_entries[i]) ? "[indirect]" : "[direct]");
- found = 1;
- if(commpage_is_indirect(&commpage_entries[i]))
- {
- commpage_indirect_function_t function = (commpage_indirect_function_t)commpage_entries[i].function;
- function(cpu_env, num, arg1, arg2, arg3,
- arg4, arg5, arg6, arg7, arg8);
- }
- else
- {
- commpage_entries[i].function(arg1, arg2, arg3,
- arg4, arg5, arg6, arg7, arg8);
- }
- break;
- }
- }
-
- if(!found)
- {
- gemu_log("qemu: commpage function 0x%x not defined\n", num);
- gdb_handlesig (cpu_env, SIGTRAP);
- exit(-1);
- }
-}
+++ /dev/null
- /* emulated ioctl list */
-
- IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
- IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+++ /dev/null
-STRUCT(termios, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, MK_ARRAY(TYPE_CHAR, 20), TYPE_INT, TYPE_INT)
+++ /dev/null
-/*
- * Mach-O object file loading
- *
- * Copyright (c) 2006 Pierre d'Herbemont
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include <stdio.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "qemu.h"
-#include "disas.h"
-
-#include <mach-o/loader.h>
-#include <mach-o/fat.h>
-#include <mach-o/nlist.h>
-#include <mach-o/reloc.h>
-#include <mach-o/ppc/reloc.h>
-
-//#define DEBUG_MACHLOAD
-
-#ifdef DEBUG_MACHLOAD
-# define DPRINTF(...) do { qemu_log(__VA_ARGS__); printf(__VA_ARGS__); } while(0)
-#else
-# define DPRINTF(...) do { qemu_log(__VA_ARGS__); } while(0)
-#endif
-
-# define check_mach_header(x) (x.magic == MH_CIGAM)
-
-extern const char *interp_prefix;
-
-/* we don't have a good implementation for this */
-#define DONT_USE_DYLD_SHARED_MAP
-
-/* Pass extra arg to DYLD for debug */
-//#define ACTIVATE_DYLD_TRACE
-
-//#define OVERRIDE_DYLINKER
-
-#ifdef OVERRIDE_DYLINKER
-# ifdef TARGET_I386
-# define DYLINKER_NAME "/Users/steg/qemu/tests/i386-darwin-env/usr/lib/dyld"
-# else
-# define DYLINKER_NAME "/usr/lib/dyld"
-# endif
-#endif
-
-/* XXX: in an include */
-struct nlist_extended
-{
- union {
- char *n_name;
- long n_strx;
- } n_un;
- unsigned char n_type;
- unsigned char n_sect;
- short st_desc;
- unsigned long st_value;
- unsigned long st_size;
-};
-
-/* Print symbols in gdb */
-void *macho_text_sect = 0;
-int macho_offset = 0;
-
-int load_object(const char *filename, struct target_pt_regs * regs, void ** mh);
-
-#ifdef TARGET_I386
-typedef struct mach_i386_thread_state {
- unsigned int eax;
- unsigned int ebx;
- unsigned int ecx;
- unsigned int edx;
- unsigned int edi;
- unsigned int esi;
- unsigned int ebp;
- unsigned int esp;
- unsigned int ss;
- unsigned int eflags;
- unsigned int eip;
- unsigned int cs;
- unsigned int ds;
- unsigned int es;
- unsigned int fs;
- unsigned int gs;
-} mach_i386_thread_state_t;
-
-void bswap_i386_thread_state(struct mach_i386_thread_state *ts)
-{
- bswap32s((uint32_t*)&ts->eax);
- bswap32s((uint32_t*)&ts->ebx);
- bswap32s((uint32_t*)&ts->ecx);
- bswap32s((uint32_t*)&ts->edx);
- bswap32s((uint32_t*)&ts->edi);
- bswap32s((uint32_t*)&ts->esi);
- bswap32s((uint32_t*)&ts->ebp);
- bswap32s((uint32_t*)&ts->esp);
- bswap32s((uint32_t*)&ts->ss);
- bswap32s((uint32_t*)&ts->eflags);
- bswap32s((uint32_t*)&ts->eip);
- bswap32s((uint32_t*)&ts->cs);
- bswap32s((uint32_t*)&ts->ds);
- bswap32s((uint32_t*)&ts->es);
- bswap32s((uint32_t*)&ts->fs);
- bswap32s((uint32_t*)&ts->gs);
-}
-#define target_thread_state mach_i386_thread_state
-#define TARGET_CPU_TYPE CPU_TYPE_I386
-#define TARGET_CPU_NAME "i386"
-#endif
-
-#ifdef TARGET_PPC
-struct mach_ppc_thread_state {
- unsigned int srr0; /* Instruction address register (PC) */
- unsigned int srr1; /* Machine state register (supervisor) */
- unsigned int r0;
- unsigned int r1;
- unsigned int r2;
- unsigned int r3;
- unsigned int r4;
- unsigned int r5;
- unsigned int r6;
- unsigned int r7;
- unsigned int r8;
- unsigned int r9;
- unsigned int r10;
- unsigned int r11;
- unsigned int r12;
- unsigned int r13;
- unsigned int r14;
- unsigned int r15;
- unsigned int r16;
- unsigned int r17;
- unsigned int r18;
- unsigned int r19;
- unsigned int r20;
- unsigned int r21;
- unsigned int r22;
- unsigned int r23;
- unsigned int r24;
- unsigned int r25;
- unsigned int r26;
- unsigned int r27;
- unsigned int r28;
- unsigned int r29;
- unsigned int r30;
- unsigned int r31;
-
- unsigned int cr; /* Condition register */
- unsigned int xer; /* User's integer exception register */
- unsigned int lr; /* Link register */
- unsigned int ctr; /* Count register */
- unsigned int mq; /* MQ register (601 only) */
-
- unsigned int vrsave; /* Vector Save Register */
-};
-
-void bswap_ppc_thread_state(struct mach_ppc_thread_state *ts)
-{
- bswap32s((uint32_t*)&ts->srr0);
- bswap32s((uint32_t*)&ts->srr1);
- bswap32s((uint32_t*)&ts->r0);
- bswap32s((uint32_t*)&ts->r1);
- bswap32s((uint32_t*)&ts->r2);
- bswap32s((uint32_t*)&ts->r3);
- bswap32s((uint32_t*)&ts->r4);
- bswap32s((uint32_t*)&ts->r5);
- bswap32s((uint32_t*)&ts->r6);
- bswap32s((uint32_t*)&ts->r7);
- bswap32s((uint32_t*)&ts->r8);
- bswap32s((uint32_t*)&ts->r9);
- bswap32s((uint32_t*)&ts->r10);
- bswap32s((uint32_t*)&ts->r11);
- bswap32s((uint32_t*)&ts->r12);
- bswap32s((uint32_t*)&ts->r13);
- bswap32s((uint32_t*)&ts->r14);
- bswap32s((uint32_t*)&ts->r15);
- bswap32s((uint32_t*)&ts->r16);
- bswap32s((uint32_t*)&ts->r17);
- bswap32s((uint32_t*)&ts->r18);
- bswap32s((uint32_t*)&ts->r19);
- bswap32s((uint32_t*)&ts->r20);
- bswap32s((uint32_t*)&ts->r21);
- bswap32s((uint32_t*)&ts->r22);
- bswap32s((uint32_t*)&ts->r23);
- bswap32s((uint32_t*)&ts->r24);
- bswap32s((uint32_t*)&ts->r25);
- bswap32s((uint32_t*)&ts->r26);
- bswap32s((uint32_t*)&ts->r27);
- bswap32s((uint32_t*)&ts->r28);
- bswap32s((uint32_t*)&ts->r29);
- bswap32s((uint32_t*)&ts->r30);
- bswap32s((uint32_t*)&ts->r31);
-
- bswap32s((uint32_t*)&ts->cr);
- bswap32s((uint32_t*)&ts->xer);
- bswap32s((uint32_t*)&ts->lr);
- bswap32s((uint32_t*)&ts->ctr);
- bswap32s((uint32_t*)&ts->mq);
-
- bswap32s((uint32_t*)&ts->vrsave);
-}
-
-#define target_thread_state mach_ppc_thread_state
-#define TARGET_CPU_TYPE CPU_TYPE_POWERPC
-#define TARGET_CPU_NAME "PowerPC"
-#endif
-
-struct target_thread_command {
- unsigned long cmd; /* LC_THREAD or LC_UNIXTHREAD */
- unsigned long cmdsize; /* total size of this command */
- unsigned long flavor; /* flavor of thread state */
- unsigned long count; /* count of longs in thread state */
- struct target_thread_state state; /* thread state for this flavor */
-};
-
-void bswap_tc(struct target_thread_command *tc)
-{
- bswap32s((uint32_t*)(&tc->flavor));
- bswap32s((uint32_t*)&tc->count);
-#if defined(TARGET_I386)
- bswap_i386_thread_state(&tc->state);
-#elif defined(TARGET_PPC)
- bswap_ppc_thread_state(&tc->state);
-#else
-# error unknown TARGET_CPU_TYPE
-#endif
-}
-
-void bswap_mh(struct mach_header *mh)
-{
- bswap32s((uint32_t*)(&mh->magic));
- bswap32s((uint32_t*)&mh->cputype);
- bswap32s((uint32_t*)&mh->cpusubtype);
- bswap32s((uint32_t*)&mh->filetype);
- bswap32s((uint32_t*)&mh->ncmds);
- bswap32s((uint32_t*)&mh->sizeofcmds);
- bswap32s((uint32_t*)&mh->flags);
-}
-
-void bswap_lc(struct load_command *lc)
-{
- bswap32s((uint32_t*)&lc->cmd);
- bswap32s((uint32_t*)&lc->cmdsize);
-}
-
-
-void bswap_fh(struct fat_header *fh)
-{
- bswap32s((uint32_t*)&fh->magic);
- bswap32s((uint32_t*)&fh->nfat_arch);
-}
-
-void bswap_fa(struct fat_arch *fa)
-{
- bswap32s((uint32_t*)&fa->cputype);
- bswap32s((uint32_t*)&fa->cpusubtype);
- bswap32s((uint32_t*)&fa->offset);
- bswap32s((uint32_t*)&fa->size);
- bswap32s((uint32_t*)&fa->align);
-}
-
-void bswap_segcmd(struct segment_command *sc)
-{
- bswap32s((uint32_t*)&sc->vmaddr);
- bswap32s((uint32_t*)&sc->vmsize);
- bswap32s((uint32_t*)&sc->fileoff);
- bswap32s((uint32_t*)&sc->filesize);
- bswap32s((uint32_t*)&sc->maxprot);
- bswap32s((uint32_t*)&sc->initprot);
- bswap32s((uint32_t*)&sc->nsects);
- bswap32s((uint32_t*)&sc->flags);
-}
-
-void bswap_symtabcmd(struct symtab_command *stc)
-{
- bswap32s((uint32_t*)&stc->cmd);
- bswap32s((uint32_t*)&stc->cmdsize);
- bswap32s((uint32_t*)&stc->symoff);
- bswap32s((uint32_t*)&stc->nsyms);
- bswap32s((uint32_t*)&stc->stroff);
- bswap32s((uint32_t*)&stc->strsize);
-}
-
-void bswap_sym(struct nlist *n)
-{
- bswap32s((uint32_t*)&n->n_un.n_strx);
- bswap16s((uint16_t*)&n->n_desc);
- bswap32s((uint32_t*)&n->n_value);
-}
-
-int load_thread(struct mach_header *mh, struct target_thread_command *tc, struct target_pt_regs * regs, int fd, int mh_pos, int need_bswap)
-{
- int entry;
- if(need_bswap)
- bswap_tc(tc);
-#if defined(TARGET_I386)
- entry = tc->state.eip;
- DPRINTF(" eax 0x%.8x\n ebx 0x%.8x\n ecx 0x%.8x\n edx 0x%.8x\n edi 0x%.8x\n esi 0x%.8x\n ebp 0x%.8x\n esp 0x%.8x\n ss 0x%.8x\n eflags 0x%.8x\n eip 0x%.8x\n cs 0x%.8x\n ds 0x%.8x\n es 0x%.8x\n fs 0x%.8x\n gs 0x%.8x\n",
- tc->state.eax, tc->state.ebx, tc->state.ecx, tc->state.edx, tc->state.edi, tc->state.esi, tc->state.ebp,
- tc->state.esp, tc->state.ss, tc->state.eflags, tc->state.eip, tc->state.cs, tc->state.ds, tc->state.es,
- tc->state.fs, tc->state.gs );
-#define reg_copy(reg) regs->reg = tc->state.reg
- if(regs)
- {
- reg_copy(eax);
- reg_copy(ebx);
- reg_copy(ecx);
- reg_copy(edx);
-
- reg_copy(edi);
- reg_copy(esi);
-
- reg_copy(ebp);
- reg_copy(esp);
-
- reg_copy(eflags);
- reg_copy(eip);
- /*
- reg_copy(ss);
- reg_copy(cs);
- reg_copy(ds);
- reg_copy(es);
- reg_copy(fs);
- reg_copy(gs);*/
- }
-#undef reg_copy
-#elif defined(TARGET_PPC)
- entry = tc->state.srr0;
-#endif
- DPRINTF("load_thread: entry 0x%x\n", entry);
- return entry;
-}
-
-int load_dylinker(struct mach_header *mh, struct dylinker_command *dc, int fd, int mh_pos, int need_bswap)
-{
- int size;
- char * dylinker_name;
- size = dc->cmdsize - sizeof(struct dylinker_command);
-
- if(need_bswap)
- dylinker_name = (char*)(bswap_32(dc->name.offset)+(int)dc);
- else
- dylinker_name = (char*)((dc->name.offset)+(int)dc);
-
-#ifdef OVERRIDE_DYLINKER
- dylinker_name = DYLINKER_NAME;
-#else
- if(asprintf(&dylinker_name, "%s%s", interp_prefix, dylinker_name) == -1)
- qerror("can't allocate the new dylinker name\n");
-#endif
-
- DPRINTF("dylinker_name %s\n", dylinker_name);
- return load_object(dylinker_name, NULL, NULL);
-}
-
-int load_segment(struct mach_header *mh, struct segment_command *sc, int fd, int mh_pos, int need_bswap, int fixed, int slide)
-{
- unsigned long addr = sc->vmaddr;
- unsigned long size = sc->filesize;
- unsigned long error = 0;
-
- if(need_bswap)
- bswap_segcmd(sc);
-
- if(sc->vmaddr == 0)
- {
- DPRINTF("load_segment: sc->vmaddr == 0 returning\n");
- return -1;
- }
-
- if (strcmp(sc->segname, "__PAGEZERO") == 0)
- {
- DPRINTF("load_segment: __PAGEZERO returning\n");
- return -1;
- }
-
- /* Right now mmap memory */
- /* XXX: should check to see that the space is free, because MAP_FIXED is dangerous */
- DPRINTF("load_segment: mmaping %s to 0x%x-(0x%x|0x%x) + 0x%x\n", sc->segname, sc->vmaddr, sc->filesize, sc->vmsize, slide);
-
- if(sc->filesize > 0)
- {
- int opt = 0;
-
- if(fixed)
- opt |= MAP_FIXED;
-
- DPRINTF("sc->vmaddr 0x%x slide 0x%x add 0x%x\n", slide, sc->vmaddr, sc->vmaddr+slide);
-
- addr = target_mmap(sc->vmaddr+slide, sc->filesize, sc->initprot, opt, fd, mh_pos + sc->fileoff);
-
- if(addr==-1)
- qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
-
- error = addr-sc->vmaddr;
- }
- else
- {
- addr = sc->vmaddr+slide;
- error = slide;
- }
-
- if(sc->vmsize > sc->filesize)
- {
- addr += sc->filesize;
- size = sc->vmsize-sc->filesize;
- addr = target_mmap(addr, size, sc->initprot, MAP_ANONYMOUS | MAP_FIXED, -1, 0);
- if(addr==-1)
- qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
- }
-
- return error;
-}
-
-void *load_data(int fd, long offset, unsigned int size)
-{
- char *data;
-
- data = malloc(size);
- if (!data)
- return NULL;
- lseek(fd, offset, SEEK_SET);
- if (read(fd, data, size) != size) {
- free(data);
- return NULL;
- }
- return data;
-}
-
-/* load a mach-o object file */
-int load_object(const char *filename, struct target_pt_regs * regs, void ** mh)
-{
- int need_bswap = 0;
- int entry_point = 0;
- int dyld_entry_point = 0;
- int slide, mmapfixed;
- int fd;
- struct load_command *lcmds, *lc;
- int is_fat = 0;
- unsigned int i, magic;
- int mach_hdr_pos = 0;
- struct mach_header mach_hdr;
-
- /* for symbol lookup with -d flag. */
- struct symtab_command * symtabcmd = 0;
- struct nlist_extended *symtab, *sym;
- struct nlist *symtab_std, *syment;
- char *strtab;
-
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- qerror("can't open file '%s'", filename);
-
- /* Read magic header. */
- if (read(fd, &magic, sizeof (magic)) != sizeof (magic))
- qerror("unable to read Magic of '%s'", filename);
-
- /* Check Mach identification. */
- if(magic == MH_MAGIC)
- {
- is_fat = 0;
- need_bswap = 0;
- } else if (magic == MH_CIGAM)
- {
- is_fat = 0;
- need_bswap = 1;
- } else if (magic == FAT_MAGIC)
- {
- is_fat = 1;
- need_bswap = 0;
- } else if (magic == FAT_CIGAM)
- {
- is_fat = 1;
- need_bswap = 1;
- }
- else
- qerror("Not a Mach-O file.", filename);
-
- DPRINTF("loading %s %s...\n", filename, is_fat ? "[FAT]": "[REGULAR]");
- if(is_fat)
- {
- int found = 0;
- struct fat_header fh;
- struct fat_arch *fa;
-
- lseek(fd, 0, SEEK_SET);
-
- /* Read Fat header. */
- if (read(fd, &fh, sizeof (fh)) != sizeof (fh))
- qerror("unable to read file header");
-
- if(need_bswap)
- bswap_fh(&fh);
-
- /* Read Fat Arch. */
- fa = malloc(sizeof(struct fat_arch)*fh.nfat_arch);
-
- if (read(fd, fa, sizeof(struct fat_arch)*fh.nfat_arch) != sizeof(struct fat_arch)*fh.nfat_arch)
- qerror("unable to read file header");
-
- for( i = 0; i < fh.nfat_arch; i++, fa++)
- {
- if(need_bswap)
- bswap_fa(fa);
- if(fa->cputype == TARGET_CPU_TYPE)
- {
- mach_hdr_pos = fa->offset;
- lseek(fd, mach_hdr_pos, SEEK_SET);
-
- /* Read Mach header. */
-
- if (read(fd, &mach_hdr, sizeof(struct mach_header)) != sizeof (struct mach_header))
- qerror("unable to read file header");
-
- if(mach_hdr.magic == MH_MAGIC)
- need_bswap = 0;
- else if (mach_hdr.magic == MH_CIGAM)
- need_bswap = 1;
- else
- qerror("Invalid mach header in Fat Mach-O File");
- found = 1;
- break;
- }
- }
- if(!found)
- qerror("%s: No %s CPU found in FAT Header", filename, TARGET_CPU_NAME);
- }
- else
- {
- lseek(fd, 0, SEEK_SET);
- /* Read Mach header */
- if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
- qerror("%s: unable to read file header", filename);
- }
-
- if(need_bswap)
- bswap_mh(&mach_hdr);
-
- if ((mach_hdr.cputype) != TARGET_CPU_TYPE)
- qerror("%s: Unsupported CPU 0x%x (only 0x%x(%s) supported)", filename, mach_hdr.cputype, TARGET_CPU_TYPE, TARGET_CPU_NAME);
-
-
- switch(mach_hdr.filetype)
- {
- case MH_EXECUTE: break;
- case MH_FVMLIB:
- case MH_DYLIB:
- case MH_DYLINKER: break;
- default:
- qerror("%s: Unsupported Mach type (0x%x)", filename, mach_hdr.filetype);
- }
-
- /* read segment headers */
- lcmds = malloc(mach_hdr.sizeofcmds);
-
- if(read(fd, lcmds, mach_hdr.sizeofcmds) != mach_hdr.sizeofcmds)
- qerror("%s: unable to read load_command", filename);
- slide = 0;
- mmapfixed = 0;
- for(i=0, lc = lcmds; i < (mach_hdr.ncmds) ; i++)
- {
-
- if(need_bswap)
- bswap_lc(lc);
- switch(lc->cmd)
- {
- case LC_SEGMENT:
- /* The main_exe can't be relocated */
- if(mach_hdr.filetype == MH_EXECUTE)
- mmapfixed = 1;
-
- slide = load_segment(&mach_hdr, (struct segment_command*)lc, fd, mach_hdr_pos, need_bswap, mmapfixed, slide);
-
- /* other segment must be mapped according to slide exactly, if load_segment did something */
- if(slide != -1)
- mmapfixed = 1;
- else
- slide = 0; /* load_segment didn't map the segment */
-
- if(mach_hdr.filetype == MH_EXECUTE && slide != 0)
- qerror("%s: Warning executable can't be mapped at the right address (offset: 0x%x)\n", filename, slide);
-
- if(strcmp(((struct segment_command*)(lc))->segname, "__TEXT") == 0)
- {
- /* Text section */
- if(mach_hdr.filetype == MH_EXECUTE)
- {
- /* return the mach_header */
- *mh = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
- }
- else
- {
- /* it is dyld save the section for gdb, we will be interested in dyld symbol
- while debuging */
- macho_text_sect = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
- macho_offset = slide;
- }
- }
- break;
- case LC_LOAD_DYLINKER:
- dyld_entry_point = load_dylinker( &mach_hdr, (struct dylinker_command*)lc, fd, mach_hdr_pos, need_bswap );
- break;
- case LC_LOAD_DYLIB:
- /* dyld will do that for us */
- break;
- case LC_THREAD:
- case LC_UNIXTHREAD:
- {
- struct target_pt_regs * _regs;
- if(mach_hdr.filetype == MH_DYLINKER)
- _regs = regs;
- else
- _regs = 0;
- entry_point = load_thread( &mach_hdr, (struct target_thread_command*)lc, _regs, fd, mach_hdr_pos, need_bswap );
- }
- break;
- case LC_SYMTAB:
- /* Save the symtab and strtab */
- symtabcmd = (struct symtab_command *)lc;
- break;
- case LC_ID_DYLINKER:
- case LC_ID_DYLIB:
- case LC_UUID:
- case LC_DYSYMTAB:
- case LC_TWOLEVEL_HINTS:
- case LC_PREBIND_CKSUM:
- case LC_SUB_LIBRARY:
- break;
- default: fprintf(stderr, "warning: unknown command 0x%x in '%s'\n", lc->cmd, filename);
- }
- lc = (struct load_command*)((int)(lc)+(lc->cmdsize));
- }
-
- if(symtabcmd)
- {
- if(need_bswap)
- bswap_symtabcmd(symtabcmd);
-
- symtab_std = load_data(fd, symtabcmd->symoff+mach_hdr_pos, symtabcmd->nsyms * sizeof(struct nlist));
- strtab = load_data(fd, symtabcmd->stroff+mach_hdr_pos, symtabcmd->strsize);
-
- symtab = malloc(sizeof(struct nlist_extended) * symtabcmd->nsyms);
-
- if(need_bswap)
- {
- for(i = 0, syment = symtab_std; i < symtabcmd->nsyms; i++, syment++)
- bswap_sym(syment);
- }
-
- for(i = 0, sym = symtab, syment = symtab_std; i < symtabcmd->nsyms; i++, sym++, syment++)
- {
- struct nlist *sym_follow, *sym_next = 0;
- unsigned int j;
- memset(sym, 0, sizeof(*sym));
-
- sym->n_type = syment->n_type;
- if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
- continue;
-
- memcpy(sym, syment, sizeof(*syment));
-
- /* Find the following symbol in order to get the current symbol size */
- for(j = 0, sym_follow = symtab_std; j < symtabcmd->nsyms; j++, sym_follow++) {
- if ( sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
- continue;
- if(!sym_next) {
- sym_next = sym_follow;
- continue;
- }
- if(!(sym_next->n_value > sym_follow->n_value))
- continue;
- sym_next = sym_follow;
- }
- if(sym_next)
- sym->st_size = sym_next->n_value - sym->st_value;
- else
- sym->st_size = 10; /* XXX: text_sec_hdr->size + text_sec_hdr->offset - sym->st_value; */
-
- sym->st_value += slide;
- }
-
- free((void*)symtab_std);
-
- {
- DPRINTF("saving symtab of %s (%d symbol(s))\n", filename, symtabcmd->nsyms);
- struct syminfo *s;
- s = malloc(sizeof(*s));
- s->disas_symtab = symtab;
- s->disas_strtab = strtab;
- s->disas_num_syms = symtabcmd->nsyms;
- s->next = syminfos;
- syminfos = s;
- }
- }
- close(fd);
- if(mach_hdr.filetype == MH_EXECUTE && dyld_entry_point)
- return dyld_entry_point;
- else
- return entry_point+slide;
-}
-
-extern unsigned long stack_size;
-
-unsigned long setup_arg_pages(void * mh, char ** argv, char ** env)
-{
- unsigned long stack_base, error, size;
- int i;
- int * stack;
- int argc, envc;
-
- /* Create enough stack to hold everything. If we don't use
- * it for args, we'll use it for something else...
- */
- size = stack_size;
-
- error = target_mmap(0,
- size + qemu_host_page_size,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS,
- -1, 0);
- if (error == -1)
- qerror("stk mmap");
-
- /* we reserve one extra page at the top of the stack as guard */
- target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
-
- stack_base = error + size;
- stack = (void*)stack_base;
-/*
- * | STRING AREA |
- * +-------------+
- * | 0 |
-* +-------------+
- * | apple[n] |
- * +-------------+
- * :
- * +-------------+
- * | apple[0] |
- * +-------------+
- * | 0 |
- * +-------------+
- * | env[n] |
- * +-------------+
- * :
- * :
- * +-------------+
- * | env[0] |
- * +-------------+
- * | 0 |
- * +-------------+
- * | arg[argc-1] |
- * +-------------+
- * :
- * :
- * +-------------+
- * | arg[0] |
- * +-------------+
- * | argc |
- * +-------------+
- * sp-> | mh | address of where the a.out's file offset 0 is in memory
- * +-------------+
-*/
- /* Construct the stack Stack grows down */
- stack--;
-
- /* XXX: string should go up there */
-
- *stack = 0;
- stack--;
-
- /* Push the absolute path of our executable */
- DPRINTF("pushing apple %s (0x%x)\n", (char*)argv[0], (int)argv[0]);
- stl(stack, (int) argv[0]);
-
- stack--;
-
- stl(stack, 0);
- stack--;
-
- /* Get envc */
- for(envc = 0; env[envc]; envc++);
-
- for(i = envc-1; i >= 0; i--)
- {
- DPRINTF("pushing env %s (0x%x)\n", (char*)env[i], (int)env[i]);
- stl(stack, (int)env[i]);
- stack--;
-
- /* XXX: remove that when string will be on top of the stack */
- page_set_flags((int)env[i], (int)(env[i]+strlen(env[i])), PROT_READ | PAGE_VALID);
- }
-
- /* Add on the stack the interp_prefix chosen if so */
- if(interp_prefix[0])
- {
- char *dyld_root;
- asprintf(&dyld_root, "DYLD_ROOT_PATH=%s", interp_prefix);
- page_set_flags((int)dyld_root, (int)(dyld_root+strlen(interp_prefix)+1), PROT_READ | PAGE_VALID);
-
- stl(stack, (int)dyld_root);
- stack--;
- }
-
-#ifdef DONT_USE_DYLD_SHARED_MAP
- {
- char *shared_map_mode;
- asprintf(&shared_map_mode, "DYLD_SHARED_REGION=avoid");
- page_set_flags((int)shared_map_mode, (int)(shared_map_mode+strlen(shared_map_mode)+1), PROT_READ | PAGE_VALID);
-
- stl(stack, (int)shared_map_mode);
- stack--;
- }
-#endif
-
-#ifdef ACTIVATE_DYLD_TRACE
- char * extra_env_static[] = {"DYLD_DEBUG_TRACE=yes",
- "DYLD_PREBIND_DEBUG=3", "DYLD_UNKNOW_TRACE=yes",
- "DYLD_PRINT_INITIALIZERS=yes",
- "DYLD_PRINT_SEGMENTS=yes", "DYLD_PRINT_REBASINGS=yes", "DYLD_PRINT_BINDINGS=yes", "DYLD_PRINT_INITIALIZERS=yes", "DYLD_PRINT_WARNINGS=yes" };
-
- char ** extra_env = malloc(sizeof(extra_env_static));
- bcopy(extra_env_static, extra_env, sizeof(extra_env_static));
- page_set_flags((int)extra_env, (int)((void*)extra_env+sizeof(extra_env_static)), PROT_READ | PAGE_VALID);
-
- for(i = 0; i<9; i++)
- {
- DPRINTF("pushing (extra) env %s (0x%x)\n", (char*)extra_env[i], (int)extra_env[i]);
- stl(stack, (int) extra_env[i]);
- stack--;
- }
-#endif
-
- stl(stack, 0);
- stack--;
-
- /* Get argc */
- for(argc = 0; argv[argc]; argc++);
-
- for(i = argc-1; i >= 0; i--)
- {
- DPRINTF("pushing arg %s (0x%x)\n", (char*)argv[i], (int)argv[i]);
- stl(stack, (int) argv[i]);
- stack--;
-
- /* XXX: remove that when string will be on top of the stack */
- page_set_flags((int)argv[i], (int)(argv[i]+strlen(argv[i])), PROT_READ | PAGE_VALID);
- }
-
- DPRINTF("pushing argc %d\n", argc);
- stl(stack, argc);
- stack--;
-
- DPRINTF("pushing mh 0x%x\n", (int)mh);
- stl(stack, (int) mh);
-
- /* Stack points on the mh */
- return (unsigned long)stack;
-}
-
-int mach_exec(const char * filename, char ** argv, char ** envp,
- struct target_pt_regs * regs)
-{
- int entrypoint, stack;
- void * mh; /* the Mach Header that will be used by dyld */
-
- DPRINTF("mach_exec at 0x%x\n", (int)mach_exec);
-
- entrypoint = load_object(filename, regs, &mh);
- stack = setup_arg_pages(mh, argv, envp);
-#if defined(TARGET_I386)
- regs->eip = entrypoint;
- regs->esp = stack;
-#elif defined(TARGET_PPC)
- regs->nip = entrypoint;
- regs->gpr[1] = stack;
-#endif
- DPRINTF("mach_exec returns eip set to 0x%x esp 0x%x mh 0x%x\n", entrypoint, stack, (int)mh);
-
- if(!entrypoint)
- qerror("%s: no entry point!\n", filename);
-
- return 0;
-}
+++ /dev/null
-/*
- * qemu user main
- *
- * Copyright (c) 2003 Fabrice Bellard
- * Copyright (c) 2006 Pierre d'Herbemont
- *
- * 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 <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <sys/syscall.h>
-#include <sys/mman.h>
-
-#include "qemu.h"
-#include "qemu-common.h"
-
-#define DEBUG_LOGFILE "/tmp/qemu.log"
-
-#ifdef __APPLE__
-#include <crt_externs.h>
-# define environ (*_NSGetEnviron())
-#endif
-
-#include <mach/mach_init.h>
-#include <mach/vm_map.h>
-
-int singlestep;
-
-const char *interp_prefix = "";
-
-asm(".zerofill __STD_PROG_ZONE, __STD_PROG_ZONE, __std_prog_zone, 0x0dfff000");
-
-/* 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 stack_size = 512 * 1024;
-
-void qerror(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-void gemu_log(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-}
-
-int cpu_get_pic_interrupt(CPUArchState *env)
-{
- return -1;
-}
-#ifdef TARGET_PPC
-
-static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
-{
- /* TO FIX */
- return 0;
-}
-
-uint64_t cpu_ppc_load_tbl(CPUPPCState *env)
-{
- return cpu_ppc_get_tb(env);
-}
-
-uint32_t cpu_ppc_load_tbu(CPUPPCState *env)
-{
- return cpu_ppc_get_tb(env) >> 32;
-}
-
-uint64_t cpu_ppc_load_atbl(CPUPPCState *env)
-{
- return cpu_ppc_get_tb(env);
-}
-
-uint32_t cpu_ppc_load_atbu(CPUPPCState *env)
-{
- return cpu_ppc_get_tb(env) >> 32;
-}
-
-uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env)
-{
- cpu_ppc_load_tbu(env);
-}
-
-uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env)
-{
- return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
-}
-
-/* XXX: to be fixed */
-int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
-{
- return -1;
-}
-
-int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
-{
- return -1;
-}
-
-#define EXCP_DUMP(env, fmt, ...) \
-do { \
- fprintf(stderr, fmt , ## __VA_ARGS__); \
- cpu_dump_state(env, stderr, fprintf, 0); \
- qemu_log(fmt, ## __VA_ARGS__); \
- log_cpu_state(env, 0); \
-} while (0)
-
-void cpu_loop(CPUPPCState *env)
-{
- int trapnr;
- uint32_t ret;
- target_siginfo_t info;
-
- for(;;) {
- trapnr = cpu_ppc_exec(env);
- switch(trapnr) {
- case POWERPC_EXCP_NONE:
- /* Just go on */
- break;
- case POWERPC_EXCP_CRITICAL: /* Critical input */
- cpu_abort(env, "Critical interrupt while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_MCHECK: /* Machine check exception */
- cpu_abort(env, "Machine check exception while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_DSI: /* Data storage exception */
-#ifndef DAR
-/* To deal with multiple qemu header version as host for the darwin-user code */
-# define DAR SPR_DAR
-#endif
- EXCP_DUMP(env, "Invalid data memory access: 0x" TARGET_FMT_lx "\n",
- env->spr[SPR_DAR]);
- /* Handle this via the gdb */
- gdb_handlesig (env, SIGSEGV);
-
- info.si_addr = (void*)env->nip;
- queue_signal(info.si_signo, &info);
- break;
- case POWERPC_EXCP_ISI: /* Instruction storage exception */
- EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" TARGET_FMT_lx "\n",
- env->spr[SPR_DAR]);
- /* Handle this via the gdb */
- gdb_handlesig (env, SIGSEGV);
-
- info.si_addr = (void*)(env->nip - 4);
- queue_signal(info.si_signo, &info);
- break;
- case POWERPC_EXCP_EXTERNAL: /* External input */
- cpu_abort(env, "External interrupt while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_ALIGN: /* Alignment exception */
- EXCP_DUMP(env, "Unaligned memory access\n");
- info.si_errno = 0;
- info.si_code = BUS_ADRALN;
- info.si_addr = (void*)(env->nip - 4);
- queue_signal(info.si_signo, &info);
- break;
- case POWERPC_EXCP_PROGRAM: /* Program exception */
- /* XXX: check this */
- switch (env->error_code & ~0xF) {
- case POWERPC_EXCP_FP:
- EXCP_DUMP(env, "Floating point program exception\n");
- /* Set FX */
- info.si_signo = SIGFPE;
- info.si_errno = 0;
- switch (env->error_code & 0xF) {
- case POWERPC_EXCP_FP_OX:
- info.si_code = FPE_FLTOVF;
- break;
- case POWERPC_EXCP_FP_UX:
- info.si_code = FPE_FLTUND;
- break;
- case POWERPC_EXCP_FP_ZX:
- case POWERPC_EXCP_FP_VXZDZ:
- info.si_code = FPE_FLTDIV;
- break;
- case POWERPC_EXCP_FP_XX:
- info.si_code = FPE_FLTRES;
- break;
- case POWERPC_EXCP_FP_VXSOFT:
- info.si_code = FPE_FLTINV;
- break;
- case POWERPC_EXCP_FP_VXSNAN:
- case POWERPC_EXCP_FP_VXISI:
- case POWERPC_EXCP_FP_VXIDI:
- case POWERPC_EXCP_FP_VXIMZ:
- case POWERPC_EXCP_FP_VXVC:
- case POWERPC_EXCP_FP_VXSQRT:
- case POWERPC_EXCP_FP_VXCVI:
- info.si_code = FPE_FLTSUB;
- break;
- default:
- EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
- env->error_code);
- break;
- }
- break;
- case POWERPC_EXCP_INVAL:
- EXCP_DUMP(env, "Invalid instruction\n");
- info.si_signo = SIGILL;
- info.si_errno = 0;
- switch (env->error_code & 0xF) {
- case POWERPC_EXCP_INVAL_INVAL:
- info.si_code = ILL_ILLOPC;
- break;
- case POWERPC_EXCP_INVAL_LSWX:
- info.si_code = ILL_ILLOPN;
- break;
- case POWERPC_EXCP_INVAL_SPR:
- info.si_code = ILL_PRVREG;
- break;
- case POWERPC_EXCP_INVAL_FP:
- info.si_code = ILL_COPROC;
- break;
- default:
- EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
- env->error_code & 0xF);
- info.si_code = ILL_ILLADR;
- break;
- }
- /* Handle this via the gdb */
- gdb_handlesig (env, SIGSEGV);
- break;
- case POWERPC_EXCP_PRIV:
- EXCP_DUMP(env, "Privilege violation\n");
- info.si_signo = SIGILL;
- info.si_errno = 0;
- switch (env->error_code & 0xF) {
- case POWERPC_EXCP_PRIV_OPC:
- info.si_code = ILL_PRVOPC;
- break;
- case POWERPC_EXCP_PRIV_REG:
- info.si_code = ILL_PRVREG;
- break;
- default:
- EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
- env->error_code & 0xF);
- info.si_code = ILL_PRVOPC;
- break;
- }
- break;
- case POWERPC_EXCP_TRAP:
- cpu_abort(env, "Tried to call a TRAP\n");
- break;
- default:
- /* Should not happen ! */
- cpu_abort(env, "Unknown program exception (%02x)\n",
- env->error_code);
- break;
- }
- info.si_addr = (void*)(env->nip - 4);
- queue_signal(info.si_signo, &info);
- break;
- case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
- EXCP_DUMP(env, "No floating point allowed\n");
- info.si_signo = SIGILL;
- info.si_errno = 0;
- info.si_code = ILL_COPROC;
- info.si_addr = (void*)(env->nip - 4);
- queue_signal(info.si_signo, &info);
- break;
- case POWERPC_EXCP_SYSCALL: /* System call exception */
- cpu_abort(env, "Syscall exception while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
- EXCP_DUMP(env, "No APU instruction allowed\n");
- info.si_signo = SIGILL;
- info.si_errno = 0;
- info.si_code = ILL_COPROC;
- info.si_addr = (void*)(env->nip - 4);
- queue_signal(info.si_signo, &info);
- break;
- case POWERPC_EXCP_DECR: /* Decrementer exception */
- cpu_abort(env, "Decrementer interrupt while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
- cpu_abort(env, "Fix interval timer interrupt while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
- cpu_abort(env, "Watchdog timer interrupt while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_DTLB: /* Data TLB error */
- cpu_abort(env, "Data TLB exception while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_ITLB: /* Instruction TLB error */
- cpu_abort(env, "Instruction TLB exception while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_DEBUG: /* Debug interrupt */
- gdb_handlesig (env, SIGTRAP);
- break;
- case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
- EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
- info.si_signo = SIGILL;
- info.si_errno = 0;
- info.si_code = ILL_COPROC;
- info.si_addr = (void*)(env->nip - 4);
- queue_signal(info.si_signo, &info);
- break;
- case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
- cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
- break;
- case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
- cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
- break;
- case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
- cpu_abort(env, "Performance monitor exception not handled\n");
- break;
- case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
- cpu_abort(env, "Doorbell interrupt while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
- cpu_abort(env, "Doorbell critical interrupt while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_RESET: /* System reset exception */
- cpu_abort(env, "Reset interrupt while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_DSEG: /* Data segment exception */
- cpu_abort(env, "Data segment exception while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_ISEG: /* Instruction segment exception */
- cpu_abort(env, "Instruction segment exception "
- "while in user mode. Aborting\n");
- break;
- case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
- cpu_abort(env, "Hypervisor decrementer interrupt "
- "while in user mode. Aborting\n");
- break;
- case POWERPC_EXCP_TRACE: /* Trace exception */
- /* Nothing to do:
- * we use this exception to emulate step-by-step execution mode.
- */
- break;
- case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
- cpu_abort(env, "Hypervisor data storage exception "
- "while in user mode. Aborting\n");
- break;
- case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
- cpu_abort(env, "Hypervisor instruction storage exception "
- "while in user mode. Aborting\n");
- break;
- case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
- cpu_abort(env, "Hypervisor data segment exception "
- "while in user mode. Aborting\n");
- break;
- case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
- cpu_abort(env, "Hypervisor instruction segment exception "
- "while in user mode. Aborting\n");
- break;
- case POWERPC_EXCP_VPU: /* Vector unavailable exception */
- EXCP_DUMP(env, "No Altivec instructions allowed\n");
- info.si_signo = SIGILL;
- info.si_errno = 0;
- info.si_code = ILL_COPROC;
- info.si_addr = (void*)(env->nip - 4);
- queue_signal(info.si_signo, &info);
- break;
- case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
- cpu_abort(env, "Programmable interval timer interrupt "
- "while in user mode. Aborting\n");
- break;
- case POWERPC_EXCP_IO: /* IO error exception */
- cpu_abort(env, "IO error exception while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_RUNM: /* Run mode exception */
- cpu_abort(env, "Run mode exception while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_EMUL: /* Emulation trap exception */
- cpu_abort(env, "Emulation trap exception not handled\n");
- break;
- case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
- cpu_abort(env, "Instruction fetch TLB exception "
- "while in user-mode. Aborting");
- break;
- case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
- cpu_abort(env, "Data load TLB exception while in user-mode. "
- "Aborting");
- break;
- case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
- cpu_abort(env, "Data store TLB exception while in user-mode. "
- "Aborting");
- break;
- case POWERPC_EXCP_FPA: /* Floating-point assist exception */
- cpu_abort(env, "Floating-point assist exception not handled\n");
- break;
- case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
- cpu_abort(env, "Instruction address breakpoint exception "
- "not handled\n");
- break;
- case POWERPC_EXCP_SMI: /* System management interrupt */
- cpu_abort(env, "System management interrupt while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_THERM: /* Thermal interrupt */
- cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
- cpu_abort(env, "Performance monitor exception not handled\n");
- break;
- case POWERPC_EXCP_VPUA: /* Vector assist exception */
- cpu_abort(env, "Vector assist exception not handled\n");
- break;
- case POWERPC_EXCP_SOFTP: /* Soft patch exception */
- cpu_abort(env, "Soft patch exception not handled\n");
- break;
- case POWERPC_EXCP_MAINT: /* Maintenance exception */
- cpu_abort(env, "Maintenance exception while in user mode. "
- "Aborting\n");
- break;
- case POWERPC_EXCP_STOP: /* stop translation */
- /* We did invalidate the instruction cache. Go on */
- break;
- case POWERPC_EXCP_BRANCH: /* branch instruction: */
- /* We just stopped because of a branch. Go on */
- break;
- case POWERPC_EXCP_SYSCALL_USER:
- /* system call in user-mode emulation */
- /* system call */
- if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
- ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
- env->gpr[5], env->gpr[6], env->gpr[7],
- env->gpr[8], env->gpr[9], env->gpr[10]*/);
- else if(((int)env->gpr[0])<0)
- ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
- env->gpr[5], env->gpr[6], env->gpr[7],
- env->gpr[8], env->gpr[9], env->gpr[10]);
- else
- ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
- env->gpr[5], env->gpr[6], env->gpr[7],
- env->gpr[8], env->gpr[9], env->gpr[10]);
-
- /* Unix syscall error signaling */
- if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
- {
- if( (int)ret < 0 )
- env->nip += 0;
- else
- env->nip += 4;
- }
-
- /* Return value */
- env->gpr[3] = ret;
- break;
- case EXCP_INTERRUPT:
- /* just indicate that signals should be handled asap */
- break;
- default:
- cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
- break;
- }
- process_pending_signals(env);
- }
-}
-#endif
-
-
-#ifdef TARGET_I386
-
-/***********************************************************/
-/* CPUX86 core interface */
-
-uint64_t cpu_get_tsc(CPUX86State *env)
-{
- return cpu_get_real_ticks();
-}
-
-void
-write_dt(void *ptr, unsigned long addr, unsigned long limit,
- int flags)
-{
- unsigned int e1, e2;
- e1 = (addr << 16) | (limit & 0xffff);
- e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
- e2 |= flags;
- stl((uint8_t *)ptr, e1);
- stl((uint8_t *)ptr + 4, e2);
-}
-
-static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
- unsigned long addr, unsigned int sel)
-{
- unsigned int e1, e2;
- e1 = (addr & 0xffff) | (sel << 16);
- e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
- stl((uint8_t *)ptr, e1);
- stl((uint8_t *)ptr + 4, e2);
-}
-
-#define GDT_TABLE_SIZE 14
-#define LDT_TABLE_SIZE 15
-#define IDT_TABLE_SIZE 256
-#define TSS_SIZE 104
-uint64_t gdt_table[GDT_TABLE_SIZE];
-uint64_t ldt_table[LDT_TABLE_SIZE];
-uint64_t idt_table[IDT_TABLE_SIZE];
-uint32_t tss[TSS_SIZE];
-
-/* 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);
-}
-
-/* ABI convention: after a syscall if there was an error the CF flag is set */
-static inline void set_error(CPUX86State *env, int ret)
-{
- if(ret<0)
- env->eflags = env->eflags | 0x1;
- else
- env->eflags &= ~0x1;
- env->regs[R_EAX] = ret;
-}
-
-void cpu_loop(CPUX86State *env)
-{
- int trapnr;
- int ret;
- uint8_t *pc;
- target_siginfo_t info;
-
- for(;;) {
- trapnr = cpu_x86_exec(env);
- uint32_t *params = (uint32_t *)env->regs[R_ESP];
- switch(trapnr) {
- case 0x79: /* Our commpage hack back door exit is here */
- do_commpage(env, env->eip, *(params + 1), *(params + 2),
- *(params + 3), *(params + 4),
- *(params + 5), *(params + 6),
- *(params + 7), *(params + 8));
- break;
- case 0x81: /* mach syscall */
- {
- ret = do_mach_syscall(env, env->regs[R_EAX],
- *(params + 1), *(params + 2),
- *(params + 3), *(params + 4),
- *(params + 5), *(params + 6),
- *(params + 7), *(params + 8));
- set_error(env, ret);
- break;
- }
- case 0x90: /* unix backdoor */
- {
- /* after sysenter, stack is in R_ECX, new eip in R_EDX (sysexit will flip them back)*/
- int saved_stack = env->regs[R_ESP];
- env->regs[R_ESP] = env->regs[R_ECX];
-
- ret = do_unix_syscall(env, env->regs[R_EAX]);
-
- env->regs[R_ECX] = env->regs[R_ESP];
- env->regs[R_ESP] = saved_stack;
-
- set_error(env, ret);
- break;
- }
- case 0x80: /* unix syscall */
- {
- ret = do_unix_syscall(env, env->regs[R_EAX]/*,
- *(params + 1), *(params + 2),
- *(params + 3), *(params + 4),
- *(params + 5), *(params + 6),
- *(params + 7), *(params + 8)*/);
- set_error(env, ret);
- break;
- }
- case 0x82: /* thread syscall */
- {
- ret = do_thread_syscall(env, env->regs[R_EAX],
- *(params + 1), *(params + 2),
- *(params + 3), *(params + 4),
- *(params + 5), *(params + 6),
- *(params + 7), *(params + 8));
- set_error(env, ret);
- break;
- }
- case EXCP0B_NOSEG:
- case EXCP0C_STACK:
- info.si_signo = SIGBUS;
- info.si_errno = 0;
- info.si_code = BUS_NOOP;
- info.si_addr = 0;
- gdb_handlesig (env, SIGBUS);
- queue_signal(info.si_signo, &info);
- break;
- case EXCP0D_GPF:
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
- info.si_code = SEGV_NOOP;
- info.si_addr = 0;
- gdb_handlesig (env, SIGSEGV);
- queue_signal(info.si_signo, &info);
- break;
- case EXCP0E_PAGE:
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
- if (!(env->error_code & 1))
- info.si_code = SEGV_MAPERR;
- else
- info.si_code = SEGV_ACCERR;
- info.si_addr = (void*)env->cr[2];
- gdb_handlesig (env, SIGSEGV);
- queue_signal(info.si_signo, &info);
- break;
- case EXCP00_DIVZ:
- /* division by zero */
- info.si_signo = SIGFPE;
- info.si_errno = 0;
- info.si_code = FPE_INTDIV;
- info.si_addr = (void*)env->eip;
- gdb_handlesig (env, SIGFPE);
- queue_signal(info.si_signo, &info);
- break;
- case EXCP01_SSTP:
- case EXCP03_INT3:
- info.si_signo = SIGTRAP;
- info.si_errno = 0;
- info.si_code = TRAP_BRKPT;
- info.si_addr = (void*)env->eip;
- gdb_handlesig (env, SIGTRAP);
- queue_signal(info.si_signo, &info);
- break;
- case EXCP04_INTO:
- case EXCP05_BOUND:
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
- info.si_code = SEGV_NOOP;
- info.si_addr = 0;
- gdb_handlesig (env, SIGSEGV);
- queue_signal(info.si_signo, &info);
- break;
- case EXCP06_ILLOP:
- info.si_signo = SIGILL;
- info.si_errno = 0;
- info.si_code = ILL_ILLOPN;
- info.si_addr = (void*)env->eip;
- gdb_handlesig (env, SIGILL);
- queue_signal(info.si_signo, &info);
- break;
- case EXCP_INTERRUPT:
- /* just indicate that signals should be handled asap */
- break;
- case EXCP_DEBUG:
- {
- int sig;
-
- sig = gdb_handlesig (env, SIGTRAP);
- if (sig)
- {
- info.si_signo = sig;
- info.si_errno = 0;
- info.si_code = TRAP_BRKPT;
- queue_signal(info.si_signo, &info);
- }
- }
- break;
- default:
- pc = (void*)(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
-
-static void usage(void)
-{
- printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
- "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n"
- "Darwin CPU emulator (compiled for %s emulation)\n"
- "\n"
- "-h print this help\n"
- "-L path set the %s library path (default='%s')\n"
- "-s size set the stack size in bytes (default=%ld)\n"
- "\n"
- "debug options:\n"
- "-d options activate log (logfile='%s')\n"
- "-g wait for gdb on port 1234\n"
- "-p pagesize set the host page size to 'pagesize'\n",
- "-singlestep always run in singlestep mode\n"
- TARGET_ARCH,
- TARGET_ARCH,
- interp_prefix,
- stack_size,
- DEBUG_LOGFILE);
- exit(1);
-}
-
-/* XXX: currently only used for async signals (see signal.c) */
-CPUArchState *global_env;
-
-/* used to free thread contexts */
-TaskState *first_task_state;
-
-int main(int argc, char **argv)
-{
- const char *filename;
- const char *log_file = DEBUG_LOGFILE;
- const char *log_mask = NULL;
- struct target_pt_regs regs1, *regs = ®s1;
- TaskState ts1, *ts = &ts1;
- CPUArchState *env;
- int optind;
- short use_gdbstub = 0;
- const char *r;
- const char *cpu_model;
-
- if (argc <= 1)
- usage();
-
- module_call_init(MODULE_INIT_QOM);
-
- optind = 1;
- for(;;) {
- if (optind >= argc)
- break;
- r = argv[optind];
- if (r[0] != '-')
- break;
- optind++;
- r++;
- if (!strcmp(r, "-")) {
- break;
- } else if (!strcmp(r, "d")) {
- if (optind >= argc) {
- break;
- }
- log_mask = argv[optind++];
- } else if (!strcmp(r, "D")) {
- if (optind >= argc) {
- break;
- }
- log_file = argv[optind++];
- } else if (!strcmp(r, "s")) {
- r = argv[optind++];
- stack_size = strtol(r, (char **)&r, 0);
- if (stack_size <= 0)
- usage();
- if (*r == 'M')
- stack_size *= 1024 * 1024;
- else if (*r == 'k' || *r == 'K')
- stack_size *= 1024;
- } else if (!strcmp(r, "L")) {
- interp_prefix = argv[optind++];
- } else if (!strcmp(r, "p")) {
- qemu_host_page_size = atoi(argv[optind++]);
- if (qemu_host_page_size == 0 ||
- (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
- fprintf(stderr, "page size must be a power of two\n");
- exit(1);
- }
- } else
- if (!strcmp(r, "g")) {
- use_gdbstub = 1;
- } else if (!strcmp(r, "cpu")) {
- cpu_model = argv[optind++];
- if (strcmp(cpu_model, "?") == 0) {
-/* XXX: implement xxx_cpu_list for targets that still miss it */
-#if defined(cpu_list)
- cpu_list(stdout, &fprintf);
-#endif
- exit(1);
- }
- } else if (!strcmp(r, "singlestep")) {
- singlestep = 1;
- } else
- {
- usage();
- }
- }
-
- /* init debug */
- cpu_set_log_filename(log_file);
- if (log_mask) {
- int mask;
- CPULogItem *item;
-
- mask = cpu_str_to_log_mask(log_mask);
- if (!mask) {
- printf("Log items (comma separated):\n");
- for (item = cpu_log_items; item->mask != 0; item++) {
- printf("%-10s %s\n", item->name, item->help);
- }
- exit(1);
- }
- cpu_set_log(mask);
- }
-
- if (optind >= argc) {
- usage();
- }
- filename = argv[optind];
-
- /* Zero out regs */
- memset(regs, 0, sizeof(struct target_pt_regs));
-
- if (cpu_model == NULL) {
-#if defined(TARGET_I386)
-#ifdef TARGET_X86_64
- cpu_model = "qemu64";
-#else
- cpu_model = "qemu32";
-#endif
-#elif defined(TARGET_PPC)
-#ifdef TARGET_PPC64
- cpu_model = "970";
-#else
- cpu_model = "750";
-#endif
-#else
-#error unsupported CPU
-#endif
- }
- tcg_exec_init(0);
- cpu_exec_init_all();
- /* NOTE: we need to init the CPU at this stage to get
- qemu_host_page_size */
- env = cpu_init(cpu_model);
- cpu_state_reset(env);
-
- printf("Starting %s with qemu\n----------------\n", filename);
-
- commpage_init();
-
- if (mach_exec(filename, argv+optind, environ, regs) != 0) {
- printf("Error loading %s\n", filename);
- _exit(1);
- }
-
- syscall_init();
- signal_init();
- global_env = env;
-
- /* build Task State */
- memset(ts, 0, sizeof(TaskState));
- env->opaque = ts;
- ts->used = 1;
-
-#if defined(TARGET_I386)
- cpu_x86_set_cpl(env, 3);
-
- env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
- env->hflags |= HF_PE_MASK;
-
- if (env->cpuid_features & 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;
-
- /* darwin 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;
-
- /* Darwin LDT setup */
- /* 2 - User code segment
- 3 - User data segment
- 4 - User cthread */
- bzero(ldt_table, LDT_TABLE_SIZE * sizeof(ldt_table[0]));
- env->ldt.base = (uint32_t) ldt_table;
- env->ldt.limit = sizeof(ldt_table) - 1;
-
- write_dt(ldt_table + 2, 0, 0xfffff,
- DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
- (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
- write_dt(ldt_table + 3, 0, 0xfffff,
- DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
- (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
- write_dt(ldt_table + 4, 0, 0xfffff,
- DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
- (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
-
- /* Darwin GDT setup.
- * has changed a lot between old Darwin/x86 (pre-Mac Intel) and Mac OS X/x86,
- now everything is done via int 0x81(mach) int 0x82 (thread) and sysenter/sysexit(unix) */
- bzero(gdt_table, sizeof(gdt_table));
- env->gdt.base = (uint32_t)gdt_table;
- env->gdt.limit = sizeof(gdt_table) - 1;
-
- /* Set up a back door to handle sysenter syscalls (unix) */
- char * syscallbackdoor = malloc(64);
- page_set_flags((int)syscallbackdoor, (int)syscallbackdoor + 64, PROT_EXEC | PROT_READ | PAGE_VALID);
-
- int i = 0;
- syscallbackdoor[i++] = 0xcd;
- syscallbackdoor[i++] = 0x90; /* int 0x90 */
- syscallbackdoor[i++] = 0x0F;
- syscallbackdoor[i++] = 0x35; /* sysexit */
-
- /* Darwin sysenter/sysexit setup */
- env->sysenter_cs = 0x1; //XXX
- env->sysenter_eip = (int)syscallbackdoor;
- env->sysenter_esp = (int)malloc(64);
-
- /* Darwin TSS setup
- This must match up with GDT[4] */
- env->tr.base = (uint32_t) tss;
- env->tr.limit = sizeof(tss) - 1;
- env->tr.flags = DESC_P_MASK | (0x9 << DESC_TYPE_SHIFT);
- stw(tss + 2, 0x10); // ss0 = 0x10 = GDT[2] = Kernel Data Segment
-
- /* Darwin interrupt setup */
- bzero(idt_table, sizeof(idt_table));
- env->idt.base = (uint32_t) idt_table;
- env->idt.limit = sizeof(idt_table) - 1;
- set_idt(0, 0);
- set_idt(1, 0);
- set_idt(2, 0);
- set_idt(3, 3);
- set_idt(4, 3);
- set_idt(5, 3);
- 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);
- /* Syscalls are done via
- int 0x80 (unix) (rarely used)
- int 0x81 (mach)
- int 0x82 (thread)
- int 0x83 (diag) (not handled here)
- sysenter/sysexit (unix) -> we redirect that to int 0x90 */
- set_idt(0x79, 3); /* Commpage hack, here is our backdoor interrupt */
- set_idt(0x80, 3); /* Unix Syscall */
- set_idt(0x81, 3); /* Mach Syscalls */
- set_idt(0x82, 3); /* thread Syscalls */
-
- set_idt(0x90, 3); /* qemu-darwin-user's Unix syscalls backdoor */
-
-
- cpu_x86_load_seg(env, R_CS, __USER_CS);
- cpu_x86_load_seg(env, R_DS, __USER_DS);
- cpu_x86_load_seg(env, R_ES, __USER_DS);
- cpu_x86_load_seg(env, R_SS, __USER_DS);
- cpu_x86_load_seg(env, R_FS, __USER_DS);
- cpu_x86_load_seg(env, R_GS, __USER_DS);
-
-#elif defined(TARGET_PPC)
- {
- int i;
-
-#if defined(TARGET_PPC64)
-#if defined(TARGET_ABI32)
- env->msr &= ~((target_ulong)1 << MSR_SF);
-#else
- env->msr |= (target_ulong)1 << MSR_SF;
-#endif
-#endif
- env->nip = regs->nip;
- for(i = 0; i < 32; i++) {
- env->gpr[i] = regs->gpr[i];
- }
- }
-#else
-#error unsupported target CPU
-#endif
-
- if (use_gdbstub) {
- printf("Waiting for gdb Connection on port 1234...\n");
- gdbserver_start (1234);
- gdb_handlesig(env, 0);
- }
-
- cpu_loop(env);
- /* never exits */
- return 0;
-}
+++ /dev/null
-/*
- * mmap support for qemu
- *
- * Copyright (c) 2003 Fabrice Bellard
- *
- * 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 <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/mman.h>
-
-#include "qemu.h"
-
-//#define DEBUG_MMAP
-
-/* NOTE: all the constants are the HOST ones */
-int target_mprotect(unsigned long start, unsigned long len, int prot)
-{
- unsigned long end, host_start, host_end, addr;
- int prot1, ret;
-
-#ifdef DEBUG_MMAP
- printf("mprotect: start=0x%lx len=0x%lx prot=%c%c%c\n", start, len,
- prot & PROT_READ ? 'r' : '-',
- prot & PROT_WRITE ? 'w' : '-',
- prot & PROT_EXEC ? 'x' : '-');
-#endif
-
- if ((start & ~TARGET_PAGE_MASK) != 0)
- return -EINVAL;
- len = TARGET_PAGE_ALIGN(len);
- end = start + len;
- if (end < start)
- return -EINVAL;
- if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
- return -EINVAL;
- if (len == 0)
- return 0;
-
- host_start = start & qemu_host_page_mask;
- host_end = HOST_PAGE_ALIGN(end);
- if (start > host_start) {
- /* handle host page containing start */
- prot1 = prot;
- for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
- prot1 |= page_get_flags(addr);
- }
- if (host_end == host_start + qemu_host_page_size) {
- for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
- prot1 |= page_get_flags(addr);
- }
- end = host_end;
- }
- ret = mprotect((void *)host_start, qemu_host_page_size, prot1 & PAGE_BITS);
- if (ret != 0)
- return ret;
- host_start += qemu_host_page_size;
- }
- if (end < host_end) {
- prot1 = prot;
- for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
- prot1 |= page_get_flags(addr);
- }
- ret = mprotect((void *)(host_end - qemu_host_page_size), qemu_host_page_size,
- prot1 & PAGE_BITS);
- if (ret != 0)
- return ret;
- host_end -= qemu_host_page_size;
- }
-
- /* handle the pages in the middle */
- if (host_start < host_end) {
- ret = mprotect((void *)host_start, host_end - host_start, prot);
- if (ret != 0)
- return ret;
- }
- page_set_flags(start, start + len, prot | PAGE_VALID);
- return 0;
-}
-
-/* map an incomplete host page */
-int mmap_frag(unsigned long host_start,
- unsigned long start, unsigned long end,
- int prot, int flags, int fd, unsigned long offset)
-{
- unsigned long host_end, ret, addr;
- int prot1, prot_new;
-
- host_end = host_start + qemu_host_page_size;
-
- /* get the protection of the target pages outside the mapping */
- prot1 = 0;
- for(addr = host_start; addr < host_end; addr++) {
- if (addr < start || addr >= end)
- prot1 |= page_get_flags(addr);
- }
-
- if (prot1 == 0) {
- /* no page was there, so we allocate one */
- ret = (long)mmap((void *)host_start, qemu_host_page_size, prot,
- flags | MAP_ANONYMOUS, -1, 0);
- if (ret == -1)
- return ret;
- }
- prot1 &= PAGE_BITS;
-
- prot_new = prot | prot1;
- if (!(flags & MAP_ANONYMOUS)) {
- /* msync() won't work here, so we return an error if write is
- possible while it is a shared mapping */
-#ifndef __APPLE__
- if ((flags & MAP_TYPE) == MAP_SHARED &&
-#else
- if ((flags & MAP_SHARED) &&
-#endif
- (prot & PROT_WRITE))
- return -1;
-
- /* adjust protection to be able to read */
- if (!(prot1 & PROT_WRITE))
- mprotect((void *)host_start, qemu_host_page_size, prot1 | PROT_WRITE);
-
- /* read the corresponding file data */
- pread(fd, (void *)start, end - start, offset);
-
- /* put final protection */
- if (prot_new != (prot1 | PROT_WRITE))
- mprotect((void *)host_start, qemu_host_page_size, prot_new);
- } else {
- /* just update the protection */
- if (prot_new != prot1) {
- mprotect((void *)host_start, qemu_host_page_size, prot_new);
- }
- }
- return 0;
-}
-
-/* NOTE: all the constants are the HOST ones */
-long target_mmap(unsigned long start, unsigned long len, int prot,
- int flags, int fd, unsigned long offset)
-{
- unsigned long ret, end, host_start, host_end, retaddr, host_offset, host_len;
-#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__)
- static unsigned long last_start = 0x40000000;
-#endif
-
-#ifdef DEBUG_MMAP
- {
- printf("mmap: start=0x%lx len=0x%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_ANONYMOUS)
- printf("MAP_ANON ");
-#ifndef MAP_TYPE
-# define MAP_TYPE 0x3
-#endif
- switch(flags & MAP_TYPE) {
- case MAP_PRIVATE:
- printf("MAP_PRIVATE ");
- break;
- case MAP_SHARED:
- printf("MAP_SHARED ");
- break;
- default:
- printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE);
- break;
- }
- printf("fd=%d offset=%lx\n", fd, offset);
- }
-#endif
-
- if (offset & ~TARGET_PAGE_MASK)
- return -EINVAL;
-
- len = TARGET_PAGE_ALIGN(len);
- if (len == 0)
- return start;
- host_start = start & qemu_host_page_mask;
-
- if (!(flags & MAP_FIXED)) {
-#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__)
- /* tell the kernel to search at the same place as i386 */
- if (host_start == 0) {
- host_start = last_start;
- last_start += HOST_PAGE_ALIGN(len);
- }
-#endif
- if (qemu_host_page_size != qemu_real_host_page_size) {
- /* NOTE: this code is only for debugging with '-p' option */
- /* reserve a memory area */
- host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE;
- host_start = (long)mmap((void *)host_start, host_len, PROT_NONE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (host_start == -1)
- return host_start;
- host_end = host_start + host_len;
- start = HOST_PAGE_ALIGN(host_start);
- end = start + HOST_PAGE_ALIGN(len);
- if (start > host_start)
- munmap((void *)host_start, start - host_start);
- if (end < host_end)
- munmap((void *)end, host_end - end);
- /* use it as a fixed mapping */
- flags |= MAP_FIXED;
- } else {
- /* if not fixed, no need to do anything */
- host_offset = offset & qemu_host_page_mask;
- host_len = len + offset - host_offset;
- start = (long)mmap((void *)host_start, host_len,
- prot, flags, fd, host_offset);
- if (start == -1)
- return start;
- /* update start so that it points to the file position at 'offset' */
- if (!(flags & MAP_ANONYMOUS))
- start += offset - host_offset;
- goto the_end1;
- }
- }
-
- if (start & ~TARGET_PAGE_MASK)
- return -EINVAL;
- end = start + len;
- host_end = HOST_PAGE_ALIGN(end);
-
- /* worst case: we cannot map the file because the offset is not
- aligned, so we read it */
- if (!(flags & MAP_ANONYMOUS) &&
- (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 */
-#ifndef __APPLE__
- if ((flags & MAP_TYPE) == MAP_SHARED &&
-#else
- if ((flags & MAP_SHARED) &&
-#endif
- (prot & PROT_WRITE))
- return -EINVAL;
- retaddr = target_mmap(start, len, prot | PROT_WRITE,
- MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
- -1, 0);
- if (retaddr == -1)
- return retaddr;
- pread(fd, (void *)start, len, offset);
- if (!(prot & PROT_WRITE)) {
- ret = target_mprotect(start, len, prot);
- if (ret != 0)
- return ret;
- }
- goto the_end;
- }
-
- /* handle the start of the mapping */
- if (start > host_start) {
- if (host_end == host_start + qemu_host_page_size) {
- /* one single host page */
- ret = mmap_frag(host_start, start, end,
- prot, flags, fd, offset);
- if (ret == -1)
- return ret;
- goto the_end1;
- }
- ret = mmap_frag(host_start, start, host_start + qemu_host_page_size,
- prot, flags, fd, offset);
- if (ret == -1)
- return ret;
- host_start += qemu_host_page_size;
- }
- /* handle the end of the mapping */
- if (end < host_end) {
- ret = mmap_frag(host_end - qemu_host_page_size,
- host_end - qemu_host_page_size, host_end,
- prot, flags, fd,
- offset + host_end - qemu_host_page_size - start);
- if (ret == -1)
- return ret;
- host_end -= qemu_host_page_size;
- }
-
- /* map the middle (easier) */
- if (host_start < host_end) {
- unsigned long offset1;
- if (flags & MAP_ANONYMOUS)
- offset1 = 0;
- else
- offset1 = offset + host_start - start;
- ret = (long)mmap((void *)host_start, host_end - host_start,
- prot, flags, fd, offset1);
- if (ret == -1)
- return ret;
- }
- the_end1:
- page_set_flags(start, start + len, prot | PAGE_VALID);
- the_end:
-#ifdef DEBUG_MMAP
- printf("target_mmap: ret=0x%lx\n", (long)start);
- page_dump(stdout);
- printf("\n");
-#endif
- return start;
-}
-
-int target_munmap(unsigned long start, unsigned long len)
-{
- unsigned long end, host_start, host_end, addr;
- int prot, ret;
-
-#ifdef DEBUG_MMAP
- printf("munmap: start=0x%lx len=0x%lx\n", start, len);
-#endif
- if (start & ~TARGET_PAGE_MASK)
- return -EINVAL;
- len = TARGET_PAGE_ALIGN(len);
- if (len == 0)
- return -EINVAL;
- end = start + len;
- host_start = start & qemu_host_page_mask;
- host_end = HOST_PAGE_ALIGN(end);
-
- if (start > host_start) {
- /* handle host page containing start */
- prot = 0;
- for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
- prot |= page_get_flags(addr);
- }
- if (host_end == host_start + qemu_host_page_size) {
- for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
- prot |= page_get_flags(addr);
- }
- end = host_end;
- }
- if (prot != 0)
- host_start += qemu_host_page_size;
- }
- if (end < host_end) {
- prot = 0;
- for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
- prot |= page_get_flags(addr);
- }
- if (prot != 0)
- host_end -= qemu_host_page_size;
- }
-
- /* unmap what we can */
- if (host_start < host_end) {
- ret = munmap((void *)host_start, host_end - host_start);
- if (ret != 0)
- return ret;
- }
-
- page_set_flags(start, start + len, 0);
- return 0;
-}
-
-/* XXX: currently, we only handle MAP_ANONYMOUS and not MAP_FIXED
- blocks which have been allocated starting on a host page */
-long target_mremap(unsigned long old_addr, unsigned long old_size,
- unsigned long new_size, unsigned long flags,
- unsigned long new_addr)
-{
-#ifndef __APPLE__
- /* XXX: use 5 args syscall */
- new_addr = (long)mremap((void *)old_addr, old_size, new_size, flags);
- if (new_addr == -1)
- return new_addr;
- prot = page_get_flags(old_addr);
- page_set_flags(old_addr, old_addr + old_size, 0);
- page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);
- return new_addr;
-#else
- qerror("target_mremap: unsupported\n");
-#endif
-
-}
-
-int target_msync(unsigned long start, unsigned long len, int flags)
-{
- unsigned long end;
-
- if (start & ~TARGET_PAGE_MASK)
- return -EINVAL;
- len = TARGET_PAGE_ALIGN(len);
- end = start + len;
- if (end < start)
- return -EINVAL;
- if (end == start)
- return 0;
-
- start &= qemu_host_page_mask;
- return msync((void *)start, end - start, flags);
-}
+++ /dev/null
-#ifndef GEMU_H
-#define GEMU_H
-
-#include <signal.h>
-#include <string.h>
-
-#include "cpu.h"
-
-#include "thunk.h"
-
-#include "gdbstub.h"
-
-typedef siginfo_t target_siginfo_t;
-#define target_sigaction sigaction
-#ifdef TARGET_I386
-struct target_pt_regs {
- long ebx;
- long ecx;
- long edx;
- long esi;
- long edi;
- long ebp;
- long eax;
- int xds;
- int xes;
- long orig_eax;
- long eip;
- int xcs;
- long eflags;
- long esp;
- int xss;
-};
-struct target_sigcontext {
- int sc_onstack;
- int sc_mask;
- int sc_eax;
- int sc_ebx;
- int sc_ecx;
- int sc_edx;
- int sc_edi;
- int sc_esi;
- int sc_ebp;
- int sc_esp;
- int sc_ss;
- int sc_eflags;
- int sc_eip;
- int sc_cs;
- int sc_ds;
- int sc_es;
- int sc_fs;
- int sc_gs;
-};
-
-#define __USER_CS (0x17)
-#define __USER_DS (0x1F)
-
-#elif defined(TARGET_PPC)
-struct target_pt_regs {
- unsigned long gpr[32];
- unsigned long nip;
- unsigned long msr;
- unsigned long orig_gpr3; /* Used for restarting system calls */
- unsigned long ctr;
- unsigned long link;
- unsigned long xer;
- unsigned long ccr;
- unsigned long mq; /* 601 only (not used at present) */
- /* Used on APUS to hold IPL value. */
- unsigned long trap; /* Reason for being here */
- unsigned long dar; /* Fault registers */
- unsigned long dsisr;
- unsigned long result; /* Result of a system call */
-};
-
-struct target_sigcontext {
- int sc_onstack; /* sigstack state to restore */
- int sc_mask; /* signal mask to restore */
- int sc_ir; /* pc */
- int sc_psw; /* processor status word */
- int sc_sp; /* stack pointer if sc_regs == NULL */
- void *sc_regs; /* (kernel private) saved state */
-};
-
-#endif
-
-typedef struct TaskState {
- struct TaskState *next;
- int used; /* non zero if used */
- uint8_t stack[0];
-} __attribute__((aligned(16))) TaskState;
-
-void syscall_init(void);
-long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
- uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
-long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
- uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
-long do_unix_syscall(void *cpu_env, int num);
-int do_sigaction(int sig, const struct sigaction *act,
- struct sigaction *oact);
-int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss);
-
-void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
-void qerror(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
-
-void write_dt(void *ptr, unsigned long addr, unsigned long limit, int flags);
-
-extern CPUArchState *global_env;
-void cpu_loop(CPUArchState *env);
-void init_paths(const char *prefix);
-const char *path(const char *pathname);
-
-#include "qemu-log.h"
-
-/* commpage.c */
-void commpage_init(void);
-void do_commpage(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
- uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
-
-/* signal.c */
-void process_pending_signals(void *cpu_env);
-void signal_init(void);
-int queue_signal(int sig, target_siginfo_t *info);
-void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
-void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
-long do_sigreturn(CPUArchState *env, int num);
-
-/* machload.c */
-int mach_exec(const char * filename, char ** argv, char ** envp,
- struct target_pt_regs * regs);
-
-/* mmap.c */
-int target_mprotect(unsigned long start, unsigned long len, int prot);
-long target_mmap(unsigned long start, unsigned long len, int prot,
- int flags, int fd, unsigned long offset);
-int target_munmap(unsigned long start, unsigned long len);
-long target_mremap(unsigned long old_addr, unsigned long old_size,
- unsigned long new_size, unsigned long flags,
- unsigned long new_addr);
-int target_msync(unsigned long start, unsigned long len, int flags);
-
-/* user access */
-
-/* XXX: todo protect every memory access */
-#define lock_user(x,y,z) (void*)(x)
-#define unlock_user(x,y,z)
-
-/* Mac OS X ABI arguments processing */
-#ifdef TARGET_I386
-static inline uint32_t get_int_arg(int *i, CPUX86State *cpu_env)
-{
- uint32_t *args = (uint32_t*)(cpu_env->regs[R_ESP] + 4 + *i);
- *i+=4;
- return tswap32(*args);
-}
-static inline uint64_t get_int64_arg(int *i, CPUX86State *cpu_env)
-{
- uint64_t *args = (uint64_t*)(cpu_env->regs[R_ESP] + 4 + *i);
- *i+=8;
- return tswap64(*args);
-}
-#elif defined(TARGET_PPC)
-static inline uint32_t get_int_arg(int *i, CPUPPCState *cpu_env)
-{
- /* XXX: won't work when args goes on stack after gpr10 */
- uint32_t args = (uint32_t)(cpu_env->gpr[3+(*i & 0xff)/4]);
- *i+=4;
- return tswap32(args);
-}
-static inline uint64_t get_int64_arg(int *i, CPUPPCState *cpu_env)
-{
- /* XXX: won't work when args goes on stack after gpr10 */
- uint64_t args = (uint64_t)(cpu_env->fpr[1+(*i >> 8)/8]);
- *i+=(8 << 8) + 8;
- return tswap64(args);
-}
-#endif
-
-#endif
+++ /dev/null
-/*
- * Emulation of Linux signals
- *
- * Copyright (c) 2003 Fabrice Bellard
- *
- * 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 <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/ucontext.h>
-
-#ifdef __ia64__
-#undef uc_mcontext
-#undef uc_sigmask
-#undef uc_stack
-#undef uc_link
-#endif
-
-#include "qemu.h"
-#include "qemu-common.h"
-
-#define DEBUG_SIGNAL
-
-#define MAX_SIGQUEUE_SIZE 1024
-
-struct sigqueue {
- struct sigqueue *next;
- target_siginfo_t info;
-};
-
-struct emulated_sigaction {
- struct target_sigaction sa;
- int pending; /* true if signal is pending */
- struct sigqueue *first;
- struct sigqueue info; /* in order to always have memory for the
- first signal, we put it here */
-};
-
-static struct sigaltstack target_sigaltstack_used = {
- 0, 0, SA_DISABLE
-};
-
-static struct emulated_sigaction sigact_table[NSIG];
-static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
-static struct sigqueue *first_free; /* first free siginfo queue entry */
-static int signal_pending; /* non zero if a signal may be pending */
-
-static void host_signal_handler(int host_signum, siginfo_t *info,
- void *puc);
-
-
-static inline int host_to_target_signal(int sig)
-{
- return sig;
-}
-
-static inline int target_to_host_signal(int sig)
-{
- return sig;
-}
-
-/* siginfo conversion */
-
-
-
-void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
-{
-
-}
-
-void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
-{
-
-}
-
-void signal_init(void)
-{
- struct sigaction act;
- int i;
-
- /* set all host signal handlers. ALL signals are blocked during
- the handlers to serialize them. */
- sigfillset(&act.sa_mask);
- act.sa_flags = SA_SIGINFO;
- act.sa_sigaction = host_signal_handler;
- for(i = 1; i < NSIG; i++) {
- sigaction(i, &act, NULL);
- }
-
- memset(sigact_table, 0, sizeof(sigact_table));
-
- first_free = &sigqueue_table[0];
- for(i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++)
- sigqueue_table[i].next = &sigqueue_table[i + 1];
- sigqueue_table[MAX_SIGQUEUE_SIZE - 1].next = NULL;
-}
-
-/* signal queue handling */
-
-static inline struct sigqueue *alloc_sigqueue(void)
-{
- struct sigqueue *q = first_free;
- if (!q)
- return NULL;
- first_free = q->next;
- return q;
-}
-
-static inline void free_sigqueue(struct sigqueue *q)
-{
- q->next = first_free;
- first_free = q;
-}
-
-/* abort execution with signal */
-void QEMU_NORETURN force_sig(int sig)
-{
- int host_sig;
- host_sig = target_to_host_signal(sig);
- fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
- sig, strsignal(host_sig));
- _exit(-host_sig);
-}
-
-/* queue a signal so that it will be send to the virtual CPU as soon
- as possible */
-int queue_signal(int sig, target_siginfo_t *info)
-{
- struct emulated_sigaction *k;
- struct sigqueue *q, **pq;
- target_ulong handler;
-
-#if defined(DEBUG_SIGNAL)
- fprintf(stderr, "queue_signal: sig=%d\n",
- sig);
-#endif
- k = &sigact_table[sig - 1];
- handler = (target_ulong)k->sa.sa_handler;
- if (handler == SIG_DFL) {
- /* default handler : ignore some signal. The other are fatal */
- if (sig != SIGCHLD &&
- sig != SIGURG &&
- sig != SIGWINCH) {
- force_sig(sig);
- } else {
- return 0; /* indicate ignored */
- }
- } else if (handler == host_to_target_signal(SIG_IGN)) {
- /* ignore signal */
- return 0;
- } else if (handler == host_to_target_signal(SIG_ERR)) {
- force_sig(sig);
- } else {
- pq = &k->first;
- if (!k->pending) {
- /* first signal */
- q = &k->info;
- } else {
- q = alloc_sigqueue();
- if (!q)
- return -EAGAIN;
- while (*pq != NULL)
- pq = &(*pq)->next;
- }
- *pq = q;
- q->info = *info;
- q->next = NULL;
- k->pending = 1;
- /* signal that a new signal is pending */
- signal_pending = 1;
- return 1; /* indicates that the signal was queued */
- }
-}
-
-static void host_signal_handler(int host_signum, siginfo_t *info,
- void *puc)
-{
- int sig;
- target_siginfo_t tinfo;
-
- /* the CPU emulator uses some host signals to detect exceptions,
- we we forward to it some signals */
- if (host_signum == SIGSEGV || host_signum == SIGBUS) {
- if (cpu_signal_handler(host_signum, (void*)info, puc))
- return;
- }
-
- /* get target signal number */
- sig = host_to_target_signal(host_signum);
- if (sig < 1 || sig > NSIG)
- return;
-
-#if defined(DEBUG_SIGNAL)
- fprintf(stderr, "qemu: got signal %d\n", sig);
-#endif
- if (queue_signal(sig, &tinfo) == 1) {
- /* interrupt the virtual CPU as soon as possible */
- cpu_exit(global_env);
- }
-}
-
-int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss)
-{
- /* XXX: test errors */
- if(oss)
- {
- oss->ss_sp = tswap32(target_sigaltstack_used.ss_sp);
- oss->ss_size = tswap32(target_sigaltstack_used.ss_size);
- oss->ss_flags = tswap32(target_sigaltstack_used.ss_flags);
- }
- if(ss)
- {
- target_sigaltstack_used.ss_sp = tswap32(ss->ss_sp);
- target_sigaltstack_used.ss_size = tswap32(ss->ss_size);
- target_sigaltstack_used.ss_flags = tswap32(ss->ss_flags);
- }
- return 0;
-}
-
-int do_sigaction(int sig, const struct sigaction *act,
- struct sigaction *oact)
-{
- struct emulated_sigaction *k;
- struct sigaction act1;
- int host_sig;
-
- if (sig < 1 || sig > NSIG)
- return -EINVAL;
-
- k = &sigact_table[sig - 1];
-#if defined(DEBUG_SIGNAL)
- fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
- sig, (int)act, (int)oact);
-#endif
- if (oact) {
-#if defined(DEBUG_SIGNAL)
- fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
- sig, (int)act, (int)oact);
-#endif
-
- oact->sa_handler = tswapl(k->sa.sa_handler);
- oact->sa_flags = tswapl(k->sa.sa_flags);
- oact->sa_mask = tswapl(k->sa.sa_mask);
- }
- if (act) {
-#if defined(DEBUG_SIGNAL)
- fprintf(stderr, "sigaction handler 0x%x flag 0x%x mask 0x%x\n",
- act->sa_handler, act->sa_flags, act->sa_mask);
-#endif
-
- k->sa.sa_handler = tswapl(act->sa_handler);
- k->sa.sa_flags = tswapl(act->sa_flags);
- k->sa.sa_mask = tswapl(act->sa_mask);
- /* we update the host signal state */
- host_sig = target_to_host_signal(sig);
- if (host_sig != SIGSEGV && host_sig != SIGBUS) {
-#if defined(DEBUG_SIGNAL)
- fprintf(stderr, "sigaction handler going to call sigaction\n");
-#endif
-
- sigfillset(&act1.sa_mask);
- act1.sa_flags = SA_SIGINFO;
- if (k->sa.sa_flags & SA_RESTART)
- act1.sa_flags |= SA_RESTART;
- /* NOTE: it is important to update the host kernel signal
- ignore state to avoid getting unexpected interrupted
- syscalls */
- if (k->sa.sa_handler == SIG_IGN) {
- act1.sa_sigaction = (void *)SIG_IGN;
- } else if (k->sa.sa_handler == SIG_DFL) {
- act1.sa_sigaction = (void *)SIG_DFL;
- } else {
- act1.sa_sigaction = host_signal_handler;
- }
- sigaction(host_sig, &act1, NULL);
- }
- }
- return 0;
-}
-
-
-#ifdef TARGET_I386
-
-static inline void *
-get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size)
-{
- /* XXX Fix that */
- if(target_sigaltstack_used.ss_flags & SA_DISABLE)
- {
- int esp;
- /* Default to using normal stack */
- esp = env->regs[R_ESP];
-
- return (void *)((esp - frame_size) & -8ul);
- }
- else
- {
- return target_sigaltstack_used.ss_sp;
- }
-}
-
-static void setup_frame(int sig, struct emulated_sigaction *ka,
- void *set, CPUX86State *env)
-{
- void *frame;
-
- fprintf(stderr, "setup_frame %d\n", sig);
- frame = get_sigframe(ka, env, sizeof(*frame));
-
- /* Set up registers for signal handler */
- env->regs[R_ESP] = (unsigned long) frame;
- env->eip = (unsigned long) ka->sa.sa_handler;
-
- env->eflags &= ~TF_MASK;
-
- return;
-
-give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV /* , current */);
-}
-
-long do_sigreturn(CPUX86State *env, int num)
-{
- int i = 0;
- struct target_sigcontext *scp = get_int_arg(&i, env);
- /* XXX Get current signal number */
- /* XXX Adjust accordin to sc_onstack, sc_mask */
- if(tswapl(scp->sc_onstack) & 0x1)
- target_sigaltstack_used.ss_flags |= ~SA_DISABLE;
- else
- target_sigaltstack_used.ss_flags &= SA_DISABLE;
- int set = tswapl(scp->sc_eax);
- sigprocmask(SIG_SETMASK, &set, NULL);
-
- fprintf(stderr, "do_sigreturn: partially implemented %x EAX:%x EBX:%x\n", scp->sc_mask, tswapl(scp->sc_eax), tswapl(scp->sc_ebx));
- fprintf(stderr, "ECX:%x EDX:%x EDI:%x\n", scp->sc_ecx, tswapl(scp->sc_edx), tswapl(scp->sc_edi));
- fprintf(stderr, "EIP:%x\n", tswapl(scp->sc_eip));
-
- env->regs[R_EAX] = tswapl(scp->sc_eax);
- env->regs[R_EBX] = tswapl(scp->sc_ebx);
- env->regs[R_ECX] = tswapl(scp->sc_ecx);
- env->regs[R_EDX] = tswapl(scp->sc_edx);
- env->regs[R_EDI] = tswapl(scp->sc_edi);
- env->regs[R_ESI] = tswapl(scp->sc_esi);
- env->regs[R_EBP] = tswapl(scp->sc_ebp);
- env->regs[R_ESP] = tswapl(scp->sc_esp);
- env->segs[R_SS].selector = (void*)tswapl(scp->sc_ss);
- env->eflags = tswapl(scp->sc_eflags);
- env->eip = tswapl(scp->sc_eip);
- env->segs[R_CS].selector = (void*)tswapl(scp->sc_cs);
- env->segs[R_DS].selector = (void*)tswapl(scp->sc_ds);
- env->segs[R_ES].selector = (void*)tswapl(scp->sc_es);
- env->segs[R_FS].selector = (void*)tswapl(scp->sc_fs);
- env->segs[R_GS].selector = (void*)tswapl(scp->sc_gs);
-
- /* Again, because our caller's caller will reset EAX */
- return env->regs[R_EAX];
-}
-
-#else
-
-static void setup_frame(int sig, struct emulated_sigaction *ka,
- void *set, CPUArchState *env)
-{
- fprintf(stderr, "setup_frame: not implemented\n");
-}
-
-long do_sigreturn(CPUArchState *env, int num)
-{
- int i = 0;
- struct target_sigcontext *scp = get_int_arg(&i, env);
- fprintf(stderr, "do_sigreturn: not implemented\n");
- return -ENOSYS;
-}
-
-#endif
-
-void process_pending_signals(void *cpu_env)
-{
- struct emulated_sigaction *k;
- struct sigqueue *q;
- target_ulong handler;
- int sig;
-
- if (!signal_pending)
- return;
-
- k = sigact_table;
-
- for(sig = 1; sig <= NSIG; sig++) {
- if (k->pending)
- goto handle_signal;
- k++;
- }
-
- /* if no signal is pending, just return */
- signal_pending = 0;
- return;
-handle_signal:
- #ifdef DEBUG_SIGNAL
- fprintf(stderr, "qemu: process signal %d\n", sig);
- #endif
- /* dequeue signal */
- q = k->first;
- k->first = q->next;
- if (!k->first)
- k->pending = 0;
-
- sig = gdb_handlesig (cpu_env, sig);
- if (!sig) {
- fprintf (stderr, "Lost signal\n");
- abort();
- }
-
- handler = k->sa.sa_handler;
- if (handler == SIG_DFL) {
- /* default handler : ignore some signal. The other are fatal */
- if (sig != SIGCHLD &&
- sig != SIGURG &&
- sig != SIGWINCH) {
- force_sig(sig);
- }
- } else if (handler == SIG_IGN) {
- /* ignore sig */
- } else if (handler == SIG_ERR) {
- force_sig(sig);
- } else {
-
- setup_frame(sig, k, 0, cpu_env);
- if (k->sa.sa_flags & SA_RESETHAND)
- k->sa.sa_handler = SIG_DFL;
- }
- if (q != &k->info)
- free_sigqueue(q);
-}
+++ /dev/null
-/*
- * Darwin syscalls
- *
- * Copyright (c) 2003 Fabrice Bellard
- * Copyright (c) 2006 Pierre d'Herbemont
- *
- * 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 <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include <mach/host_info.h>
-#include <mach/mach.h>
-#include <mach/mach_time.h>
-#include <mach/message.h>
-
-#include <pthread.h>
-#include <dirent.h>
-
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <sys/sysctl.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/dirent.h>
-#include <sys/uio.h>
-#include <sys/termios.h>
-#include <sys/ptrace.h>
-#include <net/if.h>
-
-#include <sys/param.h>
-#include <sys/mount.h>
-
-#include <sys/attr.h>
-
-#include <mach/ndr.h>
-#include <mach/mig_errors.h>
-
-#include <sys/xattr.h>
-
-#include "qemu.h"
-
-//#define DEBUG_SYSCALL
-
-#ifdef DEBUG_SYSCALL
-# define DEBUG_FORCE_ENABLE_LOCAL() int __DEBUG_qemu_user_force_enable = 1
-# define DEBUG_BEGIN_ENABLE __DEBUG_qemu_user_force_enable = 1;
-# define DEBUG_END_ENABLE __DEBUG_qemu_user_force_enable = 0;
-
-# define DEBUG_DISABLE_ALL() static int __DEBUG_qemu_user_force_enable = 0
-# define DEBUG_ENABLE_ALL() static int __DEBUG_qemu_user_force_enable = 1
- DEBUG_ENABLE_ALL();
-
-# define DPRINTF(...) do { qemu_log(__VA_ARGS__); \
- if(__DEBUG_qemu_user_force_enable) fprintf(stderr, __VA_ARGS__); \
- } while(0)
-#else
-# define DEBUG_FORCE_ENABLE_LOCAL()
-# define DEBUG_BEGIN_ENABLE
-# define DEBUG_END_ENABLE
-
-# define DPRINTF(...) do { qemu_log(__VA_ARGS__); } while(0)
-#endif
-
-enum {
- bswap_out = 0,
- bswap_in = 1
-};
-
-extern const char *interp_prefix;
-
-static inline long get_errno(long ret)
-{
- if (ret == -1)
- return -errno;
- else
- return ret;
-}
-
-static inline int is_error(long ret)
-{
- return (unsigned long)ret >= (unsigned long)(-4096);
-}
-
-/* ------------------------------------------------------------
- Mach syscall handling
-*/
-
-void static inline print_description_msg_header(mach_msg_header_t *hdr)
-{
- char *name = NULL;
- int i;
- struct { int number; char *name; } msg_name[] =
- {
- /* see http://fxr.watson.org/fxr/source/compat/mach/mach_namemap.c?v=NETBSD */
- { 200, "host_info" },
- { 202, "host_page_size" },
- { 206, "host_get_clock_service" },
- { 206, "host_get_clock_service" },
- { 206, "host_get_clock_service" },
- { 306, "host_get_clock_service" },
- { 3204, "mach_port_allocate" },
- { 3206, "mach_port_deallocate" },
- { 3404, "mach_ports_lookup" },
- { 3409, "mach_task_get_special_port" },
- { 3414, "mach_task_get_exception_ports" },
- { 3418, "mach_semaphore_create" },
- { 3504, "mach_semaphore_create" },
- { 3509, "mach_semaphore_create" },
- { 3518, "semaphore_create" },
- { 3616, "thread_policy" },
- { 3801, "vm_allocate" },
- { 3802, "vm_deallocate" },
- { 3802, "vm_deallocate" },
- { 3803, "vm_protect" },
- { 3812, "vm_map" },
- { 4241776, "lu_message_send_id" }, /* lookupd */
- { 4241876, "lu_message_reply_id" }, /* lookupd */
- };
-
- for(i = 0; i < ARRAY_SIZE(msg_name); i++) {
- if(msg_name[i].number == hdr->msgh_id)
- {
- name = msg_name[i].name;
- break;
- }
- }
- if(!name)
- DPRINTF("unknown mach msg %d 0x%x\n", hdr->msgh_id, hdr->msgh_id);
- else
- DPRINTF("%s\n", name);
-#if 0
- DPRINTF("Bits: %8x\n", hdr->msgh_bits);
- DPRINTF("Size: %8x\n", hdr->msgh_size);
- DPRINTF("Rmte: %8x\n", hdr->msgh_remote_port);
- DPRINTF("Locl: %8x\n", hdr->msgh_local_port);
- DPRINTF("Rsrv: %8x\n", hdr->msgh_reserved);
-
- DPRINTF("Id : %8x\n", hdr->msgh_id);
-
- NDR_record_t *ndr = (NDR_record_t *)(hdr + 1);
- DPRINTF("hdr = %p, sizeof(hdr) = %x, NDR = %p\n", hdr, (unsigned int)sizeof(mach_msg_header_t), ndr);
- DPRINTF("%d %d %d %d %d %d %d %d\n",
- ndr->mig_vers, ndr->if_vers, ndr->reserved1, ndr->mig_encoding,
- ndr->int_rep, ndr->char_rep, ndr->float_rep, ndr->reserved2);
-#endif
-}
-
-static inline void print_mach_msg_return(mach_msg_return_t ret)
-{
- int i, found = 0;
-#define MACH_MSG_RET(msg) { msg, #msg }
- struct { int code; char *name; } msg_name[] =
- {
- /* ref: http://darwinsource.opendarwin.org/10.4.2/xnu-792.2.4/osfmk/man/mach_msg.html */
- /* send message */
- MACH_MSG_RET(MACH_SEND_MSG_TOO_SMALL),
- MACH_MSG_RET(MACH_SEND_NO_BUFFER),
- MACH_MSG_RET(MACH_SEND_INVALID_DATA),
- MACH_MSG_RET(MACH_SEND_INVALID_HEADER),
- MACH_MSG_RET(MACH_SEND_INVALID_DEST),
- MACH_MSG_RET(MACH_SEND_INVALID_NOTIFY),
- MACH_MSG_RET(MACH_SEND_INVALID_REPLY),
- MACH_MSG_RET(MACH_SEND_INVALID_TRAILER),
- MACH_MSG_RET(MACH_SEND_INVALID_MEMORY),
- MACH_MSG_RET(MACH_SEND_INVALID_RIGHT),
- MACH_MSG_RET(MACH_SEND_INVALID_TYPE),
- MACH_MSG_RET(MACH_SEND_INTERRUPTED),
- MACH_MSG_RET(MACH_SEND_TIMED_OUT),
-
- MACH_MSG_RET(MACH_RCV_BODY_ERROR),
- MACH_MSG_RET(MACH_RCV_HEADER_ERROR),
-
- MACH_MSG_RET(MACH_RCV_IN_SET),
- MACH_MSG_RET(MACH_RCV_INTERRUPTED),
-
- MACH_MSG_RET(MACH_RCV_INVALID_DATA),
- MACH_MSG_RET(MACH_RCV_INVALID_NAME),
- MACH_MSG_RET(MACH_RCV_INVALID_NOTIFY),
- MACH_MSG_RET(MACH_RCV_INVALID_TRAILER),
- MACH_MSG_RET(MACH_RCV_INVALID_TYPE),
-
- MACH_MSG_RET(MACH_RCV_PORT_CHANGED),
- MACH_MSG_RET(MACH_RCV_PORT_DIED),
-
- MACH_MSG_RET(MACH_RCV_SCATTER_SMALL),
- MACH_MSG_RET(MACH_RCV_TIMED_OUT),
- MACH_MSG_RET(MACH_RCV_TOO_LARGE)
- };
-#undef MACH_MSG_RET
-
- if( ret == MACH_MSG_SUCCESS)
- DPRINTF("MACH_MSG_SUCCESS\n");
- else
- {
- for( i = 0; i < ARRAY_SIZE(msg_name); i++) {
- if(msg_name[i].code == ret) {
- DPRINTF("%s\n", msg_name[i].name);
- found = 1;
- break;
- }
- }
- if(!found)
- qerror("unknow mach message ret code %d\n", ret);
- }
-}
-
-static inline void swap_mach_msg_header(mach_msg_header_t *hdr)
-{
- hdr->msgh_bits = tswap32(hdr->msgh_bits);
- hdr->msgh_size = tswap32(hdr->msgh_size);
- hdr->msgh_remote_port = tswap32(hdr->msgh_remote_port);
- hdr->msgh_local_port = tswap32(hdr->msgh_local_port);
- hdr->msgh_reserved = tswap32(hdr->msgh_reserved);
- hdr->msgh_id = tswap32(hdr->msgh_id);
-}
-
-struct complex_msg {
- mach_msg_header_t hdr;
- mach_msg_body_t body;
-};
-
-static inline void swap_mach_msg_body(struct complex_msg *complex_msg, int bswap)
-{
- mach_msg_port_descriptor_t *descr = (mach_msg_port_descriptor_t *)(complex_msg+1);
- int i,j;
-
- if(bswap == bswap_in)
- tswap32s(&complex_msg->body.msgh_descriptor_count);
-
- DPRINTF("body.msgh_descriptor_count %d\n", complex_msg->body.msgh_descriptor_count);
-
- for(i = 0; i < complex_msg->body.msgh_descriptor_count; i++) {
- switch(descr->type)
- {
- case MACH_MSG_PORT_DESCRIPTOR:
- tswap32s(&descr->name);
- descr++;
- break;
- case MACH_MSG_OOL_DESCRIPTOR:
- {
- mach_msg_ool_descriptor_t *ool = (void *)descr;
- tswap32s((uint32_t *)&ool->address);
- tswap32s(&ool->size);
-
- descr = (mach_msg_port_descriptor_t *)(ool+1);
- break;
- }
- case MACH_MSG_OOL_PORTS_DESCRIPTOR:
- {
- mach_msg_ool_ports_descriptor_t *ool_ports = (void *)descr;
- mach_port_name_t * port_names;
-
- if(bswap == bswap_in)
- {
- tswap32s((uint32_t *)&ool_ports->address);
- tswap32s(&ool_ports->count);
- }
-
- port_names = ool_ports->address;
-
- for(j = 0; j < ool_ports->count; j++)
- tswap32s(&port_names[j]);
-
- if(bswap == bswap_out)
- {
- tswap32s((uint32_t *)&ool_ports->address);
- tswap32s(&ool_ports->count);
- }
-
- descr = (mach_msg_port_descriptor_t *)(ool_ports+1);
- break;
- }
- default: qerror("unknow mach msg descriptor type %x\n", descr->type);
- }
- }
- if(bswap == bswap_out)
- tswap32s(&complex_msg->body.msgh_descriptor_count);
-}
-
-static inline void swap_mach_msg(mach_msg_header_t *hdr, int bswap)
-{
- if (bswap == bswap_out && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
- swap_mach_msg_body((struct complex_msg *)hdr, bswap);
-
- swap_mach_msg_header(hdr);
-
- if (bswap == bswap_in && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
- swap_mach_msg_body((struct complex_msg *)hdr, bswap);
-}
-
-static inline uint32_t target_mach_msg_trap(
- mach_msg_header_t *hdr, uint32_t options, uint32_t send_size,
- uint32_t rcv_size, uint32_t rcv_name, uint32_t time_out, uint32_t notify)
-{
- extern int mach_msg_trap(mach_msg_header_t *, mach_msg_option_t,
- mach_msg_size_t, mach_msg_size_t, mach_port_t,
- mach_msg_timeout_t, mach_port_t);
- mach_msg_audit_trailer_t *trailer;
- mach_msg_id_t msg_id;
- uint32_t ret = 0;
- int i;
-
- swap_mach_msg(hdr, bswap_in);
-
- msg_id = hdr->msgh_id;
-
- print_description_msg_header(hdr);
-
- ret = mach_msg_trap(hdr, options, send_size, rcv_size, rcv_name, time_out, notify);
-
- print_mach_msg_return(ret);
-
- if( (options & MACH_RCV_MSG) && (REQUESTED_TRAILER_SIZE(options) > 0) )
- {
- /* XXX: the kernel always return the full trailer with MACH_SEND_MSG, so we should
- probably always bswap it */
- /* warning: according to Mac OS X Internals (the book) msg_size might be expressed in
- natural_t units but according to xnu/osfmk/mach/message.h: "The size of
- the message must be specified in bytes" */
- trailer = (mach_msg_audit_trailer_t *)((uint8_t *)hdr + hdr->msgh_size);
- /* XXX: Should probably do that based on the option asked by the sender, but dealing
- with kernel answer seems more sound */
- switch(trailer->msgh_trailer_size)
- {
- case sizeof(mach_msg_audit_trailer_t):
- for(i = 0; i < 8; i++)
- tswap32s(&trailer->msgh_audit.val[i]);
- /* Fall in mach_msg_security_trailer_t case */
- case sizeof(mach_msg_security_trailer_t):
- tswap32s(&trailer->msgh_sender.val[0]);
- tswap32s(&trailer->msgh_sender.val[1]);
- /* Fall in mach_msg_seqno_trailer_t case */
- case sizeof(mach_msg_seqno_trailer_t):
- tswap32s(&trailer->msgh_seqno);
- /* Fall in mach_msg_trailer_t case */
- case sizeof(mach_msg_trailer_t):
- tswap32s(&trailer->msgh_trailer_type);
- tswap32s(&trailer->msgh_trailer_size);
- break;
- case 0:
- /* Safer not to byteswap, but probably wrong */
- break;
- default:
- qerror("unknow trailer type given its size %d\n", trailer->msgh_trailer_size);
- break;
- }
- }
-
- /* Special message handling */
- switch (msg_id) {
- case 200: /* host_info */
- {
- mig_reply_error_t *err = (mig_reply_error_t *)hdr;
- struct {
- uint32_t unknow1;
- uint32_t max_cpus;
- uint32_t avail_cpus;
- uint32_t memory_size;
- uint32_t cpu_type;
- uint32_t cpu_subtype;
- } *data = (void *)(err+1);
-
- DPRINTF("maxcpu = 0x%x\n", data->max_cpus);
- DPRINTF("numcpu = 0x%x\n", data->avail_cpus);
- DPRINTF("memsize = 0x%x\n", data->memory_size);
-
-#if defined(TARGET_I386)
- data->cpu_type = CPU_TYPE_I386;
- DPRINTF("cpu_type changed to 0x%x(i386)\n", data->cpu_type);
- data->cpu_subtype = CPU_SUBTYPE_PENT;
- DPRINTF("cpu_subtype changed to 0x%x(i386_pent)\n", data->cpu_subtype);
-#elif defined(TARGET_PPC)
- data->cpu_type = CPU_TYPE_POWERPC;
- DPRINTF("cpu_type changed to 0x%x(ppc)\n", data->cpu_type);
- data->cpu_subtype = CPU_SUBTYPE_POWERPC_750;
- DPRINTF("cpu_subtype changed to 0x%x(ppc_all)\n", data->cpu_subtype);
-#else
-# error target not supported
-#endif
- break;
- }
- case 202: /* host_page_size */
- {
- mig_reply_error_t *err = (mig_reply_error_t *)hdr;
- uint32_t *pagesize = (uint32_t *)(err+1);
-
- DPRINTF("pagesize = %d\n", *pagesize);
- break;
- }
- default: break;
- }
-
- swap_mach_msg(hdr, bswap_out);
-
- return ret;
-}
-
-long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
- uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
- uint32_t arg8)
-{
- extern uint32_t mach_reply_port(void);
-
- long ret = 0;
-
- arg1 = tswap32(arg1);
- arg2 = tswap32(arg2);
- arg3 = tswap32(arg3);
- arg4 = tswap32(arg4);
- arg5 = tswap32(arg5);
- arg6 = tswap32(arg6);
- arg7 = tswap32(arg7);
- arg8 = tswap32(arg8);
-
- DPRINTF("mach syscall %d : " , num);
-
- switch(num) {
- /* see xnu/osfmk/mach/syscall_sw.h */
- case -26:
- DPRINTF("mach_reply_port()\n");
- ret = mach_reply_port();
- break;
- case -27:
- DPRINTF("mach_thread_self()\n");
- ret = mach_thread_self();
- break;
- case -28:
- DPRINTF("mach_task_self()\n");
- ret = mach_task_self();
- break;
- case -29:
- DPRINTF("mach_host_self()\n");
- ret = mach_host_self();
- break;
- case -31:
- DPRINTF("mach_msg_trap(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
- arg1, arg2, arg3, arg4, arg5, arg6, arg7);
- ret = target_mach_msg_trap((mach_msg_header_t *)arg1, arg2, arg3, arg4, arg5, arg6, arg7);
- break;
-/* may need more translation if target arch is different from host */
-#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
- case -33:
- DPRINTF("semaphore_signal_trap(0x%x)\n", arg1);
- ret = semaphore_signal_trap(arg1);
- break;
- case -34:
- DPRINTF("semaphore_signal_all_trap(0x%x)\n", arg1);
- ret = semaphore_signal_all_trap(arg1);
- break;
- case -35:
- DPRINTF("semaphore_signal_thread_trap(0x%x)\n", arg1, arg2);
- ret = semaphore_signal_thread_trap(arg1,arg2);
- break;
-#endif
- case -36:
- DPRINTF("semaphore_wait_trap(0x%x)\n", arg1);
- extern int semaphore_wait_trap(int); // XXX: is there any header for that?
- ret = semaphore_wait_trap(arg1);
- break;
-/* may need more translation if target arch is different from host */
-#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
- case -37:
- DPRINTF("semaphore_wait_signal_trap(0x%x, 0x%x)\n", arg1, arg2);
- ret = semaphore_wait_signal_trap(arg1,arg2);
- break;
-#endif
- case -43:
- DPRINTF("map_fd(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
- arg1, arg2, arg3, arg4, arg5);
- ret = map_fd(arg1, arg2, (void*)arg3, arg4, arg5);
- tswap32s((uint32_t*)arg3);
- break;
-/* may need more translation if target arch is different from host */
-#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
- case -61:
- DPRINTF("syscall_thread_switch(0x%x, 0x%x, 0x%x)\n",
- arg1, arg2, arg3);
- ret = syscall_thread_switch(arg1, arg2, arg3); // just a hint to the scheduler; can drop?
- break;
-#endif
- case -89:
- DPRINTF("mach_timebase_info(0x%x)\n", arg1);
- struct mach_timebase_info info;
- ret = mach_timebase_info(&info);
- if(!is_error(ret))
- {
- struct mach_timebase_info *outInfo = (void*)arg1;
- outInfo->numer = tswap32(info.numer);
- outInfo->denom = tswap32(info.denom);
- }
- break;
- case -90:
- DPRINTF("mach_wait_until()\n");
- extern int mach_wait_until(uint64_t); // XXX: is there any header for that?
- ret = mach_wait_until(((uint64_t)arg2<<32) | (uint64_t)arg1);
- break;
- case -91:
- DPRINTF("mk_timer_create()\n");
- extern int mk_timer_create(); // XXX: is there any header for that?
- ret = mk_timer_create();
- break;
- case -92:
- DPRINTF("mk_timer_destroy()\n");
- extern int mk_timer_destroy(int); // XXX: is there any header for that?
- ret = mk_timer_destroy(arg1);
- break;
- case -93:
- DPRINTF("mk_timer_create()\n");
- extern int mk_timer_arm(int, uint64_t); // XXX: is there any header for that?
- ret = mk_timer_arm(arg1, ((uint64_t)arg3<<32) | (uint64_t)arg2);
- break;
- case -94:
- DPRINTF("mk_timer_cancel()\n");
- extern int mk_timer_cancel(int, uint64_t *); // XXX: is there any header for that?
- ret = mk_timer_cancel(arg1, (uint64_t *)arg2);
- if((!is_error(ret)) && arg2)
- tswap64s((uint64_t *)arg2);
- break;
- default:
- gemu_log("qemu: Unsupported mach syscall: %d(0x%x)\n", num, num);
- gdb_handlesig (cpu_env, SIGTRAP);
- exit(0);
- break;
- }
- return ret;
-}
-
-/* ------------------------------------------------------------
- thread type syscall handling
-*/
-long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
- uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
- uint32_t arg8)
-{
- extern uint32_t cthread_set_self(uint32_t);
- extern uint32_t processor_facilities_used(void);
- long ret = 0;
-
- arg1 = tswap32(arg1);
- arg2 = tswap32(arg2);
- arg3 = tswap32(arg3);
- arg4 = tswap32(arg4);
- arg5 = tswap32(arg5);
- arg6 = tswap32(arg6);
- arg7 = tswap32(arg7);
- arg8 = tswap32(arg8);
-
- DPRINTF("thread syscall %d : " , num);
-
- switch(num) {
-#ifdef TARGET_I386
- case 0x3:
-#endif
- case 0x7FF1: /* cthread_set_self */
- DPRINTF("cthread_set_self(0x%x)\n", (unsigned int)arg1);
- ret = cthread_set_self(arg1);
-#ifdef TARGET_I386
- /* we need to update the LDT with the address of the thread */
- write_dt((void *)(((CPUX86State *) cpu_env)->ldt.base + (4 * sizeof(uint64_t))), arg1, 1,
- DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
- (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
- /* New i386 convention, %gs should be set to our this LDT entry */
- cpu_x86_load_seg(cpu_env, R_GS, 0x27);
- /* Old i386 convention, the kernel returns the selector for the cthread (pre-10.4.8?)*/
- ret = 0x27;
-#endif
- break;
- case 0x7FF2: /* Called the super-fast pthread_self handler by the apple guys */
- DPRINTF("pthread_self()\n");
- ret = (uint32_t)pthread_self();
- break;
- case 0x7FF3:
- DPRINTF("processor_facilities_used()\n");
-#ifdef __i386__
- qerror("processor_facilities_used: not implemented!\n");
-#else
- ret = (uint32_t)processor_facilities_used();
-#endif
- break;
- default:
- gemu_log("qemu: Unsupported thread syscall: %d(0x%x)\n", num, num);
- gdb_handlesig (cpu_env, SIGTRAP);
- exit(0);
- break;
- }
- return ret;
-}
-
-/* ------------------------------------------------------------
- ioctl handling
-*/
-static inline void byteswap_termios(struct termios *t)
-{
- tswap32s((uint32_t*)&t->c_iflag);
- tswap32s((uint32_t*)&t->c_oflag);
- tswap32s((uint32_t*)&t->c_cflag);
- tswap32s((uint32_t*)&t->c_lflag);
- /* 20 (char) bytes then */
- tswap32s((uint32_t*)&t->c_ispeed);
- tswap32s((uint32_t*)&t->c_ospeed);
-}
-
-static inline void byteswap_winsize(struct winsize *w)
-{
- tswap16s(&w->ws_row);
- tswap16s(&w->ws_col);
- tswap16s(&w->ws_xpixel);
- tswap16s(&w->ws_ypixel);
-}
-
-#define STRUCT(name, ...) STRUCT_ ## name,
-#define STRUCT_SPECIAL(name) STRUCT_ ## name,
-enum {
-#include "ioctls_types.h"
-};
-#undef STRUCT
-#undef STRUCT_SPECIAL
-
-#define STRUCT(name, ...) const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
-#define STRUCT_SPECIAL(name)
-#include "ioctls_types.h"
-#undef STRUCT
-#undef STRUCT_SPECIAL
-
-typedef struct IOCTLEntry {
- unsigned int target_cmd;
- unsigned int host_cmd;
- const char *name;
- int access;
- const argtype arg_type[5];
-} IOCTLEntry;
-
-#define IOC_R 0x0001
-#define IOC_W 0x0002
-#define IOC_RW (IOC_R | IOC_W)
-
-#define MAX_STRUCT_SIZE 4096
-
-static IOCTLEntry ioctl_entries[] = {
-#define IOCTL(cmd, access, ...) \
- { cmd, cmd, #cmd, access, { __VA_ARGS__ } },
-#include "ioctls.h"
- { 0, 0, },
-};
-
-/* ??? Implement proper locking for ioctls. */
-static long do_ioctl(long fd, long cmd, long arg)
-{
- const IOCTLEntry *ie;
- const argtype *arg_type;
- int ret;
- uint8_t buf_temp[MAX_STRUCT_SIZE];
- int target_size;
- void *argptr;
-
- ie = ioctl_entries;
- for(;;) {
- if (ie->target_cmd == 0) {
- gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd);
- return -ENOSYS;
- }
- if (ie->target_cmd == cmd)
- break;
- ie++;
- }
- arg_type = ie->arg_type;
-#if defined(DEBUG)
- gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name);
-#endif
- switch(arg_type[0]) {
- case TYPE_NULL:
- /* no argument */
- ret = get_errno(ioctl(fd, ie->host_cmd));
- break;
- case TYPE_PTRVOID:
- case TYPE_INT:
- /* int argment */
- ret = get_errno(ioctl(fd, ie->host_cmd, arg));
- break;
- case TYPE_PTR:
- arg_type++;
- target_size = thunk_type_size(arg_type, 0);
- switch(ie->access) {
- case IOC_R:
- ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
- if (!is_error(ret)) {
- argptr = lock_user(arg, target_size, 0);
- thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
- unlock_user(argptr, arg, target_size);
- }
- break;
- case IOC_W:
- argptr = lock_user(arg, target_size, 1);
- thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
- unlock_user(argptr, arg, 0);
- ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
- break;
- default:
- case IOC_RW:
- argptr = lock_user(arg, target_size, 1);
- thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
- unlock_user(argptr, arg, 0);
- ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
- if (!is_error(ret)) {
- argptr = lock_user(arg, target_size, 0);
- thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
- unlock_user(argptr, arg, target_size);
- }
- break;
- }
- break;
- default:
- gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]);
- ret = -ENOSYS;
- break;
- }
- return ret;
-}
-
-/* ------------------------------------------------------------
- Unix syscall handling
-*/
-
-static inline void byteswap_attrlist(struct attrlist *a)
-{
- tswap16s(&a->bitmapcount);
- tswap16s(&a->reserved);
- tswap32s(&a->commonattr);
- tswap32s(&a->volattr);
- tswap32s(&a->dirattr);
- tswap32s(&a->fileattr);
- tswap32s(&a->forkattr);
-}
-
-struct attrbuf_header {
- unsigned long length;
-};
-
-static inline void byteswap_attrbuf(struct attrbuf_header *attrbuf, struct attrlist *attrlist)
-{
- DPRINTF("attrBuf.length %lx\n", attrbuf->length);
-}
-
-static inline void byteswap_statfs(struct statfs *s)
-{
- tswap16s((uint16_t*)&s->f_otype);
- tswap16s((uint16_t*)&s->f_oflags);
- tswap32s((uint32_t*)&s->f_bsize);
- tswap32s((uint32_t*)&s->f_iosize);
- tswap32s((uint32_t*)&s->f_blocks);
- tswap32s((uint32_t*)&s->f_bfree);
- tswap32s((uint32_t*)&s->f_bavail);
- tswap32s((uint32_t*)&s->f_files);
- tswap32s((uint32_t*)&s->f_ffree);
- tswap32s((uint32_t*)&s->f_fsid.val[0]);
- tswap32s((uint32_t*)&s->f_fsid.val[1]);
- tswap16s((uint16_t*)&s->f_reserved1);
- tswap16s((uint16_t*)&s->f_type);
- tswap32s((uint32_t*)&s->f_flags);
-}
-
-static inline void byteswap_stat(struct stat *s)
-{
- tswap32s((uint32_t*)&s->st_dev);
- tswap32s(&s->st_ino);
- tswap16s(&s->st_mode);
- tswap16s(&s->st_nlink);
- tswap32s(&s->st_uid);
- tswap32s(&s->st_gid);
- tswap32s((uint32_t*)&s->st_rdev);
- tswap32s((uint32_t*)&s->st_atimespec.tv_sec);
- tswap32s((uint32_t*)&s->st_atimespec.tv_nsec);
- tswap32s((uint32_t*)&s->st_mtimespec.tv_sec);
- tswap32s((uint32_t*)&s->st_mtimespec.tv_nsec);
- tswap32s((uint32_t*)&s->st_ctimespec.tv_sec);
- tswap32s((uint32_t*)&s->st_ctimespec.tv_nsec);
- tswap64s((uint64_t*)&s->st_size);
- tswap64s((uint64_t*)&s->st_blocks);
- tswap32s((uint32_t*)&s->st_blksize);
- tswap32s(&s->st_flags);
- tswap32s(&s->st_gen);
-}
-
-static inline void byteswap_dirents(struct dirent *d, int bytes)
-{
- char *b;
- for( b = (char*)d; (int)b < (int)d+bytes; )
- {
- unsigned short s = ((struct dirent *)b)->d_reclen;
- tswap32s(&((struct dirent *)b)->d_ino);
- tswap16s(&((struct dirent *)b)->d_reclen);
- if(s<=0)
- break;
- b += s;
- }
-}
-
-static inline void byteswap_iovec(struct iovec *v, int n)
-{
- int i;
- for(i = 0; i < n; i++)
- {
- tswap32s((uint32_t*)&v[i].iov_base);
- tswap32s((uint32_t*)&v[i].iov_len);
- }
-}
-
-static inline void byteswap_timeval(struct timeval *t)
-{
- tswap32s((uint32_t*)&t->tv_sec);
- tswap32s((uint32_t*)&t->tv_usec);
-}
-
-long do_unix_syscall_indirect(void *cpu_env, int num);
-long do_sync(void);
-long do_exit(uint32_t arg1);
-long do_getlogin(char *out, uint32_t size);
-long do_open(char * arg1, uint32_t arg2, uint32_t arg3);
-long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3);
-long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3);
-long do_execve(char* arg1, char ** arg2, char ** arg3);
-long do_getgroups(uint32_t arg1, gid_t * arg2);
-long do_gettimeofday(struct timeval * arg1, void * arg2);
-long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3);
-long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3);
-long do_utimes(char * arg1, struct timeval * arg2);
-long do_futimes(uint32_t arg1, struct timeval * arg2);
-long do_statfs(char * arg1, struct statfs * arg2);
-long do_fstatfs(uint32_t arg1, struct statfs * arg2);
-long do_stat(char * arg1, struct stat * arg2);
-long do_fstat(uint32_t arg1, struct stat * arg2);
-long do_lstat(char * arg1, struct stat * arg2);
-long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4);
-long do_lseek(void *cpu_env, int num);
-long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen /* ignored */);
-long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5);
-long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8);
-long do_fcntl(int fd, int cmd, int arg);
-
-long no_syscall(void *cpu_env, int num);
-
-long do_pread(uint32_t arg1, void * arg2, size_t arg3, off_t arg4)
-{
- DPRINTF("0x%x, %p, 0x%lx, 0x%" PRIx64 "\n", arg1, arg2, arg3, arg4);
- long ret = pread(arg1, arg2, arg3, arg4);
- return ret;
-}
-
-long do_read(int d, void *buf, size_t nbytes)
-{
- DPRINTF("0x%x, %p, 0x%lx\n", d, buf, nbytes);
- long ret = get_errno(read(d, buf, nbytes));
- if(!is_error(ret))
- DPRINTF("%x\n", *(uint32_t*)buf);
- return ret;
-}
-
-long unimpl_unix_syscall(void *cpu_env, int num);
-
-typedef long (*syscall_function_t)(void *cpu_env, int num);
-
-
-/* define a table that will handle the syscall number->function association */
-#define VOID void
-#define INT (uint32_t)get_int_arg(&i, cpu_env)
-#define INT64 (uint64_t)get_int64_arg(&i, cpu_env)
-#define UINT (unsigned int)INT
-#define PTR (void*)INT
-
-#define SIZE INT
-#define OFFSET INT64
-
-#define WRAPPER_CALL_DIRECT_0(function, args) long __qemu_##function(void *cpu_env) { return (long)function(); }
-#define WRAPPER_CALL_DIRECT_1(function, _arg1) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; return (long)function(arg1); }
-#define WRAPPER_CALL_DIRECT_2(function, _arg1, _arg2) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; return (long)function(arg1, arg2); }
-#define WRAPPER_CALL_DIRECT_3(function, _arg1, _arg2, _arg3) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; return (long)function(arg1, arg2, arg3); }
-#define WRAPPER_CALL_DIRECT_4(function, _arg1, _arg2, _arg3, _arg4) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; return (long)function(arg1, arg2, arg3, arg4); }
-#define WRAPPER_CALL_DIRECT_5(function, _arg1, _arg2, _arg3, _arg4, _arg5) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; return (long)function(arg1, arg2, arg3, arg4, arg5); }
-#define WRAPPER_CALL_DIRECT_6(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; return (long)function(arg1, arg2, arg3, arg4, arg5, arg6); }
-#define WRAPPER_CALL_DIRECT_7(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7); }
-#define WRAPPER_CALL_DIRECT_8(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; typeof(_arg8) arg8 = _arg8; return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); }
-#define WRAPPER_CALL_DIRECT(function, nargs, ...) WRAPPER_CALL_DIRECT_##nargs(function, __VA_ARGS__)
-#define WRAPPER_CALL_NOERRNO(function, nargs, ...) WRAPPER_CALL_DIRECT(function, nargs, __VA_ARGS__)
-#define WRAPPER_CALL_INDIRECT(function, nargs, ...)
-#define ENTRY(name, number, function, nargs, call_type, ...) WRAPPER_##call_type(function, nargs, __VA_ARGS__)
-
-#include "syscalls.h"
-
-#undef ENTRY
-#undef WRAPPER_CALL_DIRECT
-#undef WRAPPER_CALL_NOERRNO
-#undef WRAPPER_CALL_INDIRECT
-#undef OFFSET
-#undef SIZE
-#undef INT
-#undef PTR
-#undef INT64
-
-#define _ENTRY(name, number, function, nargs, call_type) [number] = {\
- name, \
- number, \
- (syscall_function_t)function, \
- nargs, \
- call_type \
- },
-
-#define ENTRY_CALL_DIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, __qemu_##function, nargs, call_type)
-#define ENTRY_CALL_NOERRNO(name, number, function, nargs, call_type) ENTRY_CALL_DIRECT(name, number, function, nargs, call_type)
-#define ENTRY_CALL_INDIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, function, nargs, call_type)
-#define ENTRY(name, number, function, nargs, call_type, ...) ENTRY_##call_type(name, number, function, nargs, call_type)
-
-#define CALL_DIRECT 1
-#define CALL_INDIRECT 2
-#define CALL_NOERRNO (CALL_DIRECT | 4 /* = 5 */)
-
-struct unix_syscall {
- char * name;
- int number;
- syscall_function_t function;
- int nargs;
- int call_type;
-} unix_syscall_table[SYS_MAXSYSCALL] = {
-#include "syscalls.h"
-};
-
-#undef ENTRY
-#undef _ENTRY
-#undef ENTRY_CALL_DIRECT
-#undef ENTRY_CALL_INDIRECT
-#undef ENTRY_CALL_NOERRNO
-
-/* Actual syscalls implementation */
-
-long do_unix_syscall_indirect(void *cpu_env, int num)
-{
- long ret;
- int new_num;
- int i = 0;
-
- new_num = get_int_arg(&i, cpu_env);
-#ifdef TARGET_I386
- ((CPUX86State*)cpu_env)->regs[R_ESP] += 4;
- /* XXX: not necessary */
- ((CPUX86State*)cpu_env)->regs[R_EAX] = new_num;
-#elif TARGET_PPC
- {
- int i;
- uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
- for(i = 3; i < 11; i++)
- *regs[i] = *regs[i+1];
- /* XXX: not necessary */
- *regs[0] = new_num;
- }
-#endif
- ret = do_unix_syscall(cpu_env, new_num);
-#ifdef TARGET_I386
- ((CPUX86State*)cpu_env)->regs[R_ESP] -= 4;
- /* XXX: not necessary */
- ((CPUX86State*)cpu_env)->regs[R_EAX] = num;
-#elif TARGET_PPC
- {
- int i;
- /* XXX: not really needed those regs are volatile across calls */
- uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
- for(i = 11; i > 3; i--)
- *regs[i] = *regs[i-1];
- regs[3] = new_num;
- *regs[0] = num;
- }
-#endif
- return ret;
-}
-
-long do_exit(uint32_t arg1)
-{
- exit(arg1);
- /* not reached */
- return -1;
-}
-
-long do_sync(void)
-{
- sync();
- return 0;
-}
-
-long do_getlogin(char *out, uint32_t size)
-{
- char *login = getlogin();
- if(!login)
- return -1;
- memcpy(out, login, size);
- return 0;
-}
-long do_open(char * arg1, uint32_t arg2, uint32_t arg3)
-{
- /* XXX: don't let the %s stay in there */
- DPRINTF("open(%s, 0x%x, 0x%x)\n", arg1, arg2, arg3);
- return get_errno(open(arg1, arg2, arg3));
-}
-
-long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3)
-{
- long ret;
- DPRINTF("getfsstat(%p, 0x%x, 0x%x)\n", arg1, arg2, arg3);
- ret = get_errno(getfsstat(arg1, arg2, arg3));
- if((!is_error(ret)) && arg1)
- byteswap_statfs(arg1);
- return ret;
-}
-
-long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3)
-{
- long ret;
- DPRINTF("sigprocmask(%d, %p, %p)\n", arg1, arg2, arg3);
- gemu_log("XXX: sigprocmask not tested (%d, %p, %p)\n", arg1, arg2, arg3);
- if(arg2)
- tswap32s(arg2);
- ret = get_errno(sigprocmask(arg1, (void *)arg2, (void *)arg3));
- if((!is_error(ret)) && arg3)
- tswap32s(arg3);
- if(arg2)
- tswap32s(arg2);
- return ret;
-}
-
-long do_execve(char* arg1, char ** arg2, char ** arg3)
-{
- long ret;
- char **argv = arg2;
- char **envp = arg3;
- int argc;
- int envc;
-
- /* XXX: don't let the %s stay in here */
- DPRINTF("execve(%s, %p, %p)\n", arg1, arg2, arg3);
-
- for(argc = 0; argv[argc]; argc++);
- for(envc = 0; envp[envc]; envc++);
-
- argv = (char**)malloc(sizeof(char*)*argc);
- envp = (char**)malloc(sizeof(char*)*envc);
-
- for(; argc >= 0; argc--)
- argv[argc] = (char*)tswap32((uint32_t)(arg2)[argc]);
-
- for(; envc >= 0; envc--)
- envp[envc] = (char*)tswap32((uint32_t)(arg3)[envc]);
-
- ret = get_errno(execve(arg1, argv, envp));
- free(argv);
- free(envp);
- return ret;
-}
-
-long do_getgroups(uint32_t arg1, gid_t * arg2)
-{
- long ret;
- int i;
- DPRINTF("getgroups(0x%x, %p)\n", arg1, arg2);
- ret = get_errno(getgroups(arg1, arg2));
- if(ret > 0)
- for(i = 0; i < arg1; i++)
- tswap32s(&arg2[i]);
- return ret;
-}
-
-long do_gettimeofday(struct timeval * arg1, void * arg2)
-{
- long ret;
- DPRINTF("gettimeofday(%p, %p)\n",
- arg1, arg2);
- ret = get_errno(gettimeofday(arg1, arg2));
- if(!is_error(ret))
- {
- /* timezone no longer used according to the manpage, so don't bother with it */
- byteswap_timeval(arg1);
- }
- return ret;
-}
-
-long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3)
-{
- long ret;
- DPRINTF("readv(0x%x, %p, 0x%x)\n", arg1, arg2, arg3);
- if(arg2)
- byteswap_iovec(arg2, arg3);
- ret = get_errno(readv(arg1, arg2, arg3));
- if((!is_error(ret)) && arg2)
- byteswap_iovec(arg2, arg3);
- return ret;
-}
-
-long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3)
-{
- long ret;
- DPRINTF("writev(0x%x, %p, 0x%x)\n", arg1, arg2, arg3);
- if(arg2)
- byteswap_iovec(arg2, arg3);
- ret = get_errno(writev(arg1, arg2, arg3));
- if((!is_error(ret)) && arg2)
- byteswap_iovec(arg2, arg3);
- return ret;
-}
-
-long do_utimes(char * arg1, struct timeval * arg2)
-{
- DPRINTF("utimes(%p, %p)\n", arg1, arg2);
- if(arg2)
- {
- byteswap_timeval(arg2);
- byteswap_timeval(arg2+1);
- }
- return get_errno(utimes(arg1, arg2));
-}
-
-long do_futimes(uint32_t arg1, struct timeval * arg2)
-{
- DPRINTF("futimes(0x%x, %p)\n", arg1, arg2);
- if(arg2)
- {
- byteswap_timeval(arg2);
- byteswap_timeval(arg2+1);
- }
- return get_errno(futimes(arg1, arg2));
-}
-
-long do_statfs(char * arg1, struct statfs * arg2)
-{
- long ret;
- DPRINTF("statfs(%p, %p)\n", arg1, arg2);
- ret = get_errno(statfs(arg1, arg2));
- if(!is_error(ret))
- byteswap_statfs(arg2);
- return ret;
-}
-
-long do_fstatfs(uint32_t arg1, struct statfs* arg2)
-{
- long ret;
- DPRINTF("fstatfs(0x%x, %p)\n",
- arg1, arg2);
- ret = get_errno(fstatfs(arg1, arg2));
- if(!is_error(ret))
- byteswap_statfs(arg2);
-
- return ret;
-}
-
-long do_stat(char * arg1, struct stat * arg2)
-{
- long ret;
- /* XXX: don't let the %s stay in there */
- DPRINTF("stat(%s, %p)\n", arg1, arg2);
- ret = get_errno(stat(arg1, arg2));
- if(!is_error(ret))
- byteswap_stat(arg2);
- return ret;
-}
-
-long do_fstat(uint32_t arg1, struct stat * arg2)
-{
- long ret;
- DPRINTF("fstat(0x%x, %p)\n", arg1, arg2);
- ret = get_errno(fstat(arg1, arg2));
- if(!is_error(ret))
- byteswap_stat(arg2);
- return ret;
-}
-
-long do_lstat(char * arg1, struct stat * arg2)
-{
- long ret;
- /* XXX: don't let the %s stay in there */
- DPRINTF("lstat(%s, %p)\n", (const char *)arg1, arg2);
- ret = get_errno(lstat(arg1, arg2));
- if(!is_error(ret))
- byteswap_stat(arg2);
- return ret;
-}
-
-long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4)
-{
- long ret;
- DPRINTF("getdirentries(0x%x, %p, 0x%x, %p)\n", arg1, arg2, arg3, arg4);
- if(arg4)
- tswap32s((uint32_t *)arg4);
- ret = get_errno(getdirentries(arg1, arg2, arg3, arg4));
- if(arg4)
- tswap32s((uint32_t *)arg4);
- if(!is_error(ret))
- byteswap_dirents(arg2, ret);
- return ret;
-}
-
-long do_lseek(void *cpu_env, int num)
-{
- long ret;
- int i = 0;
- uint32_t arg1 = get_int_arg(&i, cpu_env);
- uint64_t offset = get_int64_arg(&i, cpu_env);
- uint32_t arg3 = get_int_arg(&i, cpu_env);
- uint64_t r = lseek(arg1, offset, arg3);
-#ifdef TARGET_I386
- /* lowest word in eax, highest in edx */
- ret = r & 0xffffffff; /* will be set to eax after do_unix_syscall exit */
- ((CPUX86State *)cpu_env)->regs[R_EDX] = (uint32_t)((r >> 32) & 0xffffffff) ;
-#elif defined TARGET_PPC
- ret = r & 0xffffffff; /* will be set to r3 after do_unix_syscall exit */
- ((CPUPPCState *)cpu_env)->gpr[4] = (uint32_t)((r >> 32) & 0xffffffff) ;
-#else
- qerror("64 bit ret value on your arch?");
-#endif
- return get_errno(ret);
-}
-
-void no_swap(void * oldp, int size)
-{
-}
-
-void sysctl_tswap32s(void * oldp, int size)
-{
- tswap32s(oldp);
-}
-
-void bswap_oid(uint32_t * oldp, int size)
-{
- int count = size / sizeof(int);
- int i = 0;
- do { tswap32s(oldp + i); } while (++i < count);
-}
-
-void sysctl_usrstack(uint32_t * oldp, int size)
-{
- DPRINTF("sysctl_usrstack: 0x%x\n", *oldp);
- tswap32s(oldp);
-}
-
-void sysctl_ncpu(uint32_t * ncpu, int size)
-{
- *ncpu = 0x1;
- DPRINTF("sysctl_ncpu: 0x%x\n", *ncpu);
- tswap32s(ncpu);
-}
-
-void sysctl_exec(char * exec, int size)
-{
- DPRINTF("sysctl_exec: %s\n", exec);
-}
-
-void sysctl_translate(char * exec, int size)
-{
- DPRINTF("sysctl_translate: %s\n", exec);
-}
-
-struct sysctl_dir {
- int num;
- const char * name;
- void (*swap_func)(void *, int);
- struct sysctl_dir *childs;
-};
-
-#define ENTRYD(num, name, childs) { num, name, NULL, childs }
-#define ENTRYE(num, name, func) { num, name, (void (*)(void *, int))func, NULL }
-struct sysctl_dir sysctls_unspec[] = {
- ENTRYE(3, "oip", bswap_oid),
- { 0, NULL, NULL, NULL }
-};
-
-struct sysctl_dir sysctls_kern[] = {
- ENTRYE(KERN_TRANSLATE, "translate", sysctl_translate), /* 44 */
- ENTRYE(KERN_EXEC, "exec", sysctl_exec), /* 45 */
- ENTRYE(KERN_USRSTACK32, "KERN_USRSTACK32", sysctl_usrstack), /* 35 */
- ENTRYE(KERN_SHREG_PRIVATIZABLE, "KERN_SHREG_PRIVATIZABLE", sysctl_tswap32s), /* 54 */
- { 0, NULL, NULL, NULL }
-};
-
-struct sysctl_dir sysctls_hw[] = {
- ENTRYE(HW_NCPU, "ncpud", sysctl_tswap32s),
- ENTRYE(104, "104", no_swap),
- ENTRYE(105, "105", no_swap),
- { 0, NULL, NULL, NULL }
-};
-
-struct sysctl_dir sysctls[] = {
- ENTRYD(CTL_UNSPEC, "unspec", sysctls_unspec),
- ENTRYD(CTL_KERN, "kern", sysctls_kern),
- ENTRYD(CTL_HW, "hw", sysctls_hw ),
- { 0, NULL, NULL, NULL }
-};
-
-#undef ENTRYE
-#undef ENTRYD
-
-static inline struct sysctl_dir * get_sysctl_entry_for_mib(int mib, struct sysctl_dir * sysctl_elmt)
-{
- if(!sysctl_elmt)
- return NULL;
- for(; sysctl_elmt->name != NULL ; sysctl_elmt++) {
- if(sysctl_elmt->num == mib)
- return sysctl_elmt;
- }
- return NULL;
-}
-
-static inline long bswap_syctl(int * mib, int count, void *buf, int size)
-{
- int i;
- struct sysctl_dir * sysctl = sysctls;
- struct sysctl_dir * ret = NULL;
-
- for(i = 0; i < count; i++) {
-
- if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))) {
- gemu_log("bswap_syctl: can't find mib %d\n", mib[i]);
- return -ENOTDIR;
- }
- if(!(sysctl = sysctl->childs))
- break;
- }
-
- if(ret->childs)
- qerror("we shouldn't have a directory element\n");
-
- ret->swap_func(buf, size);
- return 0;
-}
-
-static inline void print_syctl(int * mib, int count)
-{
- int i;
- struct sysctl_dir * sysctl = sysctls;
- struct sysctl_dir * ret = NULL;
-
- for(i = 0; i < count; i++) {
- if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))){
- gemu_log("print_syctl: can't find mib %d\n", mib[i]);
- return;
- }
- DPRINTF("%s.", sysctl->name);
- if(!(sysctl = sysctl->childs))
- break;
- }
- DPRINTF("\n");
-}
-
-long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen /* ignored */)
-{
- long ret = 0;
- int i;
- DPRINTF("sysctl(%p, 0x%x, %p, %p, %p, 0x%lx)\n",
- name, namelen, oldp, oldlenp, newp, newlen);
- if(name) {
- i = 0;
- do { tswap32s( name + i); } while (++i < namelen);
- print_syctl(name, namelen);
- //bswap_syctl(name, namelen, newp, newlen);
- tswap32s((uint32_t*)oldlenp);
- }
-
- if(name) /* Sometimes sysctl is called with no arg1, ignore */
- ret = get_errno(sysctl(name, namelen, oldp, oldlenp, newp, newlen));
-
-#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
- if (!is_error(ret) && bswap_syctl(name, namelen, oldp, *oldlenp) != 0) {
- return -ENOTDIR;
- }
-#endif
-
- if(name) {
- //bswap_syctl(name, namelen, newp, newlen);
- tswap32s((uint32_t*)oldlenp);
-
- i = 0;
- do { tswap32s( name + i); } while (++i < namelen);
- }
- return ret;
-}
-
-long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5)
-{
- struct attrlist * attrlist = (void *)arg2;
- long ret;
-
-#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
- gemu_log("SYS_getdirentriesattr unimplemented\n");
- return -ENOTSUP;
-#endif
- /* XXX: don't let the %s stay in there */
- DPRINTF("getattrlist(%s, %p, %p, 0x%x, 0x%x)\n",
- (char *)arg1, arg2, arg3, arg4, arg5);
-
- if(arg2) /* XXX: We should handle that in a copy especially
- if the structure is not writable */
- byteswap_attrlist(attrlist);
-
- ret = get_errno(getattrlist((const char* )arg1, attrlist, (void *)arg3, arg4, arg5));
-
- if(!is_error(ret))
- {
- byteswap_attrbuf((void *)arg3, attrlist);
- byteswap_attrlist(attrlist);
- }
- return ret;
-}
-
-long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8)
-{
- DPRINTF("getdirentriesattr(0x%x, %p, %p, 0x%lx, %p, %p, %p, 0x%x)\n",
- arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
-#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
- qerror("SYS_getdirentriesattr unimplemented\n");
-#endif
-
- return get_errno(getdirentriesattr( arg1, (struct attrlist * )arg2, (void *)arg3, arg4,
- (unsigned long *)arg5, (unsigned long *)arg6,
- (unsigned long *)arg7, arg8));
-}
-
-static inline void bswap_flock(struct flock *f)
-{
- tswap64s(&f->l_start);
- tswap64s(&f->l_len);
- tswap32s(&f->l_pid);
- tswap16s(&f->l_type);
- tswap16s(&f->l_whence);
-}
-
-static inline void bswap_fstore(struct fstore *f)
-{
- tswap32s(&f->fst_flags);
- tswap32s(&f->fst_posmode);
- tswap64s(&f->fst_offset);
- tswap64s(&f->fst_length);
- tswap64s(&f->fst_bytesalloc);
-}
-
-static inline void bswap_radvisory(struct radvisory *f)
-{
- tswap64s(&f->ra_offset);
- tswap32s(&f->ra_count);
-}
-
-static inline void bswap_fbootstraptransfer(struct fbootstraptransfer *f)
-{
- tswap64s(&f->fbt_offset);
- tswap32s((uint32_t*)&f->fbt_length);
- tswap32s((uint32_t*)&f->fbt_buffer); /* XXX: this is a ptr */
-}
-
-static inline void bswap_log2phys(struct log2phys *f)
-{
- tswap32s(&f->l2p_flags);
- tswap64s(&f->l2p_contigbytes);
- tswap64s(&f->l2p_devoffset);
-}
-
-static inline void bswap_fcntl_arg(int cmd, void * arg)
-{
- switch(cmd)
- {
- case F_DUPFD:
- case F_GETFD:
- case F_SETFD:
- case F_GETFL:
- case F_SETFL:
- case F_GETOWN:
- case F_SETOWN:
- case F_SETSIZE:
- case F_RDAHEAD:
- case F_FULLFSYNC:
- break;
- case F_GETLK:
- case F_SETLK:
- case F_SETLKW:
- bswap_flock(arg);
- break;
- case F_PREALLOCATE:
- bswap_fstore(arg);
- break;
- case F_RDADVISE:
- bswap_radvisory(arg);
- break;
- case F_READBOOTSTRAP:
- case F_WRITEBOOTSTRAP:
- bswap_fbootstraptransfer(arg);
- break;
- case F_LOG2PHYS:
- bswap_log2phys(arg);
- break;
- default:
- gemu_log("unknow cmd in fcntl\n");
- }
-}
-
-long do_fcntl(int fd, int cmd, int arg)
-{
- long ret;
- bswap_fcntl_arg(cmd, (void *)arg);
- ret = get_errno(fcntl(fd, cmd, arg));
- if(!is_error(ret))
- bswap_fcntl_arg(cmd, (void *)arg);
- return ret;
-}
-
-long no_syscall(void *cpu_env, int num)
-{
- /* XXX: We should probably fordward it to the host kernel */
- qerror("no unix syscall %d\n", num);
- /* not reached */
- return -1;
-}
-
-long unimpl_unix_syscall(void *cpu_env, int num)
-{
- if( (num < 0) || (num > SYS_MAXSYSCALL-1) )
- qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1);
-
- gemu_log("qemu: Unsupported unix syscall %s %d\n", unix_syscall_table[num].name , num);
- gdb_handlesig (cpu_env, SIGTRAP);
- exit(-1);
-}
-
-long do_unix_syscall(void *cpu_env, int num)
-{
- long ret = 0;
-
- DPRINTF("unix syscall %d: " , num);
-
- if( (num < 0) || (num > SYS_MAXSYSCALL-1) )
- qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1);
-
- DPRINTF("%s [%s]", unix_syscall_table[num].name, unix_syscall_table[num].call_type & CALL_DIRECT ? "direct" : "indirect" );
- ret = unix_syscall_table[num].function(cpu_env, num);
-
- if(!(unix_syscall_table[num].call_type & CALL_NOERRNO))
- ret = get_errno(ret);
-
- DPRINTF("[returned 0x%x(%d)]\n", (int)ret, (int)ret);
- return ret;
-}
-
-/* ------------------------------------------------------------
- syscall_init
-*/
-void syscall_init(void)
-{
- /* Nothing yet */
-}
+++ /dev/null
-/* generated from xnu/bsd/kern/syscalls.master */
-
- ENTRY("syscall", SYS_syscall, do_unix_syscall_indirect, 0, CALL_INDIRECT, VOID) /* 0 indirect syscall */
- ENTRY("exit", SYS_exit, do_exit, 1, CALL_DIRECT, INT) /* 1 */
- ENTRY("fork", SYS_fork, fork, 0, CALL_NOERRNO, VOID) /* 2 */
- ENTRY("read", SYS_read, do_read, 3, CALL_DIRECT, INT, PTR, SIZE) /* 3 */
- ENTRY("write", SYS_write, write, 3, CALL_DIRECT, INT, PTR, SIZE) /* 4 */
- ENTRY("open", SYS_open, do_open, 3, CALL_DIRECT, PTR, INT, INT) /* 5 */
- ENTRY("close", SYS_close, close, 1, CALL_DIRECT, INT) /* 6 */
- ENTRY("wait4", SYS_wait4, wait4, 4, CALL_DIRECT, INT, PTR, INT, PTR) /* 7 */
- ENTRY("", 8, no_syscall, 0, CALL_INDIRECT, VOID) /* 8 old creat */
- ENTRY("link", SYS_link, link, 2, CALL_DIRECT, PTR, PTR) /* 9 */
- ENTRY("unlink", SYS_unlink, unlink, 1, CALL_DIRECT, PTR) /* 10 */
- ENTRY("", 11, no_syscall, 0, CALL_INDIRECT, VOID) /* 11 old execv */
- ENTRY("chdir", SYS_chdir, chdir, 1, CALL_DIRECT, PTR) /* 12 */
- ENTRY("fchdir", SYS_fchdir, fchdir, 1, CALL_DIRECT, INT) /* 13 */
- ENTRY("mknod", SYS_mknod, mknod, 3, CALL_DIRECT, PTR, INT, INT) /* 14 */
- ENTRY("chmod", SYS_chmod, chmod, 2, CALL_DIRECT, PTR, INT) /* 15 */
- ENTRY("chown", SYS_chown, chown, 3, CALL_DIRECT, PTR, INT, INT) /* 16 */
- ENTRY("obreak", SYS_obreak, no_syscall, 1, CALL_INDIRECT, VOID) /* 17 old break */
- ENTRY("ogetfsstat", 18, unimpl_unix_syscall, 3, CALL_INDIRECT, PTR, INT, INT) /* 18 */
- ENTRY("", 19, no_syscall, 0, CALL_INDIRECT, VOID) /* 19 old lseek */
- ENTRY("getpid", SYS_getpid, getpid, 0, CALL_NOERRNO, VOID) /* 20 */
- ENTRY("", 21, no_syscall, 0, CALL_INDIRECT, VOID) /* 21 old mount */
- ENTRY("", 22, no_syscall, 0, CALL_INDIRECT, VOID) /* 22 old umount */
- ENTRY("setuid", SYS_setuid, setuid, 1, CALL_DIRECT, INT) /* 23 */
- ENTRY("getuid", SYS_getuid, getuid, 0, CALL_NOERRNO, VOID) /* 24 */
- ENTRY("geteuid", SYS_geteuid, geteuid, 0, CALL_NOERRNO, VOID) /* 25 */
- ENTRY("ptrace", SYS_ptrace, ptrace, 4, CALL_DIRECT, INT, INT, PTR, INT) /* 26 */
- ENTRY("recvmsg", SYS_recvmsg, recvmsg, 3, CALL_DIRECT, INT, PTR, INT) /* 27 */
- ENTRY("sendmsg", SYS_sendmsg, sendmsg, 3, CALL_DIRECT, INT, PTR, INT) /* 28 */
- ENTRY("recvfrom", SYS_recvfrom, recvfrom, 6, CALL_DIRECT, INT, PTR, INT, INT, PTR, PTR) /* 29 */
- ENTRY("accept", SYS_accept, accept, 3, CALL_DIRECT, INT, PTR, PTR) /* 30 */
- ENTRY("getpeername", SYS_getpeername, getpeername, 3, CALL_DIRECT, INT, PTR, PTR) /* 31 */
- ENTRY("getsockname", SYS_getsockname, getsockname, 3, CALL_DIRECT, INT, PTR, PTR) /* 32 */
- ENTRY("access", SYS_access, access, 2, CALL_DIRECT, PTR, INT) /* 33 */
- ENTRY("chflags", SYS_chflags, chflags, 2, CALL_DIRECT, PTR, INT) /* 34 */
- ENTRY("fchflags", SYS_fchflags, fchflags, 2, CALL_DIRECT, INT, INT) /* 35 */
- ENTRY("sync", SYS_sync, do_sync, 0, CALL_INDIRECT, VOID) /* 36 */
- ENTRY("kill", SYS_kill, kill, 2, CALL_DIRECT, INT, INT) /* 37 */
- ENTRY("", 38, no_syscall, 0, CALL_INDIRECT, VOID) /* 38 old stat */
- ENTRY("getppid", SYS_getppid, getppid, 0, CALL_DIRECT, VOID) /* 39 */
- ENTRY("", 40, no_syscall, 0, CALL_INDIRECT, VOID) /* 40 old lstat */
- ENTRY("dup", SYS_dup, dup, 1, CALL_DIRECT, INT) /* 41 */
- ENTRY("pipe", SYS_pipe, pipe, 0, CALL_INDIRECT, PTR) /* 42 */
- ENTRY("getegid", SYS_getegid, getegid, 0, CALL_NOERRNO, VOID) /* 43 */
- ENTRY("profil", SYS_profil, profil, 4, CALL_DIRECT, PTR, SIZE, INT, INT) /* 44 */
- ENTRY("ktrace", SYS_ktrace, no_syscall, 4, CALL_INDIRECT, VOID) /* 45 */
- ENTRY("sigaction", SYS_sigaction, do_sigaction, 3, CALL_DIRECT, INT, PTR, PTR) /* 46 */
- ENTRY("getgid", SYS_getgid, getgid, 0, CALL_NOERRNO, VOID) /* 47 */
- ENTRY("sigprocmask", SYS_sigprocmask, do_sigprocmask, 3, CALL_DIRECT, INT, PTR, PTR) /* 48 */
- ENTRY("getlogin", SYS_getlogin, do_getlogin, 2, CALL_DIRECT, PTR, UINT) /* 49 XXX */
- ENTRY("setlogin", SYS_setlogin, setlogin, 1, CALL_DIRECT, PTR) /* 50 */
- ENTRY("acct", SYS_acct, acct, 1, CALL_DIRECT, PTR) /* 51 */
- ENTRY("sigpending", SYS_sigpending, sigpending, 1, CALL_DIRECT, PTR) /* 52 */
- ENTRY("sigaltstack", SYS_sigaltstack, do_sigaltstack, 2, CALL_DIRECT, PTR, PTR) /* 53 */
- ENTRY("ioctl", SYS_ioctl, do_ioctl, 3, CALL_DIRECT, INT, INT, INT) /* 54 */
- ENTRY("reboot", SYS_reboot, unimpl_unix_syscall, 2, CALL_INDIRECT, INT, PTR) /* 55 */
- ENTRY("revoke", SYS_revoke, revoke, 1, CALL_DIRECT, PTR) /* 56 */
- ENTRY("symlink", SYS_symlink, symlink, 2, CALL_DIRECT, PTR, PTR) /* 57 */
- ENTRY("readlink", SYS_readlink, readlink, 3, CALL_DIRECT, PTR, PTR, INT) /* 58 */
- ENTRY("execve", SYS_execve, do_execve, 3, CALL_DIRECT, PTR, PTR, PTR) /* 59 */
- ENTRY("umask", SYS_umask, umask, 1, CALL_DIRECT, INT) /* 60 */
- ENTRY("chroot", SYS_chroot, chroot, 1, CALL_DIRECT, PTR) /* 61 */
- ENTRY("", 62, no_syscall, 0, CALL_INDIRECT, VOID) /* 62 old fstat */
- ENTRY("", 63, no_syscall, 0, CALL_INDIRECT, VOID) /* 63 used internally , reserved */
- ENTRY("", 64, no_syscall, 0, CALL_INDIRECT, VOID) /* 64 old getpagesize */
- ENTRY("msync", SYS_msync, target_msync, 3, CALL_DIRECT, UINT /*PTR*/, SIZE, INT) /* 65 */
- ENTRY("vfork", SYS_vfork, vfork, 0, CALL_DIRECT, VOID) /* 66 */
- ENTRY("", 67, no_syscall, 0, CALL_INDIRECT, VOID) /* 67 old vread */
- ENTRY("", 68, no_syscall, 0, CALL_INDIRECT, VOID) /* 68 old vwrite */
- ENTRY("sbrk", SYS_sbrk, sbrk, 1, CALL_DIRECT, INT) /* 69 */
- ENTRY("sstk", SYS_sstk, no_syscall, 1, CALL_INDIRECT, VOID) /* 70 */
- ENTRY("", 71, no_syscall, 0, CALL_INDIRECT, VOID) /* 71 old mmap */
- ENTRY("ovadvise", SYS_ovadvise, no_syscall, 0, CALL_INDIRECT, VOID) /* 72 old vadvise */
- ENTRY("munmap", SYS_munmap, target_munmap, 2, CALL_DIRECT, UINT /* PTR */, SIZE) /* 73 */
- ENTRY("mprotect", SYS_mprotect, mprotect, 3, CALL_DIRECT, PTR, SIZE, INT) /* 74 */
- ENTRY("madvise", SYS_madvise, madvise, 3, CALL_DIRECT, PTR, SIZE, INT) /* 75 */
- ENTRY("", 76, no_syscall, 0, CALL_INDIRECT, VOID) /* 76 old vhangup */
- ENTRY("", 77, no_syscall, 0, CALL_INDIRECT, VOID) /* 77 old vlimit */
- ENTRY("mincore", SYS_mincore, mincore, 3, CALL_DIRECT, PTR, SIZE, PTR) /* 78 */
- ENTRY("getgroups", SYS_getgroups, do_getgroups, 2, CALL_DIRECT, UINT, PTR) /* 79 */
- ENTRY("setgroups", SYS_setgroups, setgroups, 2, CALL_DIRECT, UINT, PTR) /* 80 */
- ENTRY("getpgrp", SYS_getpgrp, getpgrp, 0, CALL_DIRECT, VOID) /* 81 */
- ENTRY("setpgid", SYS_setpgid, setpgid, 2, CALL_DIRECT, INT, INT) /* 82 */
- ENTRY("setitimer", SYS_setitimer, setitimer, 3, CALL_DIRECT, INT, PTR, PTR) /* 83 */
- ENTRY("", 84, no_syscall, 0, CALL_INDIRECT, VOID) /* 84 old wait */
- ENTRY("swapon", SYS_swapon, unimpl_unix_syscall, 0, CALL_INDIRECT, VOID) /* 85 */
- ENTRY("getitimer", SYS_getitimer, getitimer, 2, CALL_DIRECT, INT, PTR) /* 86 */
- ENTRY("", 87, no_syscall, 0, CALL_INDIRECT, VOID) /* 87 old gethostname */
- ENTRY("", 88, no_syscall, 0, CALL_INDIRECT, VOID) /* 88 old sethostname */
- ENTRY("getdtablesize", SYS_getdtablesize, getdtablesize, 0, CALL_DIRECT, VOID) /* 89 */
- ENTRY("dup2", SYS_dup2, dup2, 2, CALL_DIRECT, INT, INT) /* 90 */
- ENTRY("", 91, no_syscall, 0, CALL_INDIRECT, VOID) /* 91 old getdopt */
- ENTRY("fcntl", SYS_fcntl, do_fcntl, 3, CALL_DIRECT, INT, INT, INT) /* 92 */
- ENTRY("select", SYS_select, select, 5, CALL_DIRECT, INT, PTR, PTR, PTR, PTR) /* 93 */
- ENTRY("", 94, no_syscall, 0, CALL_INDIRECT, VOID) /* 94 old setdopt */
- ENTRY("fsync", SYS_fsync, fsync, 1, CALL_DIRECT, INT) /* 95 */
- ENTRY("setpriority", SYS_setpriority, setpriority, 3, CALL_DIRECT, INT, INT, INT) /* 96 */
- ENTRY("socket", SYS_socket, socket, 3, CALL_DIRECT, INT, INT, INT) /* 97 */
- ENTRY("connect", SYS_connect, connect, 3, CALL_DIRECT, INT, PTR, INT) /* 98 */
- ENTRY("", 99, no_syscall, 0, CALL_INDIRECT, VOID) /* 99 old accept */
- ENTRY("getpriority", SYS_getpriority, getpriority, 2, CALL_DIRECT, INT, INT) /* 100 */
- ENTRY("", 101, no_syscall, 0, CALL_INDIRECT, VOID) /* 101 old send */
- ENTRY("", 102, no_syscall, 0, CALL_INDIRECT, VOID) /* 102 old recv */
- ENTRY("", 103, no_syscall, 0, CALL_INDIRECT, VOID) /* 103 old sigreturn */
- ENTRY("bind", SYS_bind, bind, 3, CALL_DIRECT, INT, PTR, INT) /* 104 */
- ENTRY("setsockopt", SYS_setsockopt, setsockopt, 5, CALL_DIRECT, INT, INT, INT, PTR, INT) /* 105 */
- ENTRY("listen", SYS_listen, listen, 2, CALL_DIRECT, INT, INT) /* 106 */
- ENTRY("", 107, no_syscall, 0, CALL_INDIRECT, VOID) /* 107 old vtimes */
- ENTRY("", 108, no_syscall, 0, CALL_INDIRECT, VOID) /* 108 old sigvec */
- ENTRY("", 109, no_syscall, 0, CALL_INDIRECT, VOID) /* 109 old sigblock */
- ENTRY("", 110, no_syscall, 0, CALL_INDIRECT, VOID) /* 110 old sigsetmask */
- ENTRY("sigsuspend", SYS_sigsuspend, unimpl_unix_syscall, 1, CALL_INDIRECT, INT) /* 111 */
- ENTRY("", 112, no_syscall, 0, CALL_INDIRECT, VOID) /* 112 old sigstack */
- ENTRY("", 113, no_syscall, 0, CALL_INDIRECT, VOID) /* 113 old recvmsg */
- ENTRY("", 114, no_syscall, 0, CALL_INDIRECT, VOID) /* 114 old sendmsg */
- ENTRY("", 115, no_syscall, 0, CALL_INDIRECT, VOID) /* 115 old vtrace */
- ENTRY("gettimeofday", SYS_gettimeofday, do_gettimeofday, 2, CALL_DIRECT, PTR, PTR) /* 116 */
- ENTRY("getrusage", SYS_getrusage, getrusage, 2, CALL_DIRECT, INT, PTR) /* 117 */
- ENTRY("getsockopt", SYS_getsockopt, getsockopt, 5, CALL_DIRECT, INT, INT, INT, PTR, PTR) /* 118 */
- ENTRY("", 119, no_syscall, 0, CALL_INDIRECT, VOID) /* 119 old resuba */
- ENTRY("readv", SYS_readv, do_readv, 3, CALL_DIRECT, INT, PTR, UINT) /* 120 */
- ENTRY("writev", SYS_writev, do_writev, 3, CALL_DIRECT, INT, PTR, UINT) /* 121 */
- ENTRY("settimeofday", SYS_settimeofday, settimeofday, 2, CALL_DIRECT, PTR, PTR) /* 122 */
- ENTRY("fchown", SYS_fchown, fchown, 3, CALL_DIRECT, INT, INT, INT) /* 123 */
- ENTRY("fchmod", SYS_fchmod, fchmod, 2, CALL_DIRECT, INT, INT) /* 124 */
- ENTRY("", 125, no_syscall, 0, CALL_INDIRECT, VOID) /* 125 old recvfrom */
- ENTRY("", 126, no_syscall, 0, CALL_INDIRECT, VOID) /* 126 old setreuid */
- ENTRY("", 127, no_syscall, 0, CALL_INDIRECT, VOID) /* 127 old setregid */
- ENTRY("rename", SYS_rename, rename, 2, CALL_DIRECT, PTR, PTR) /* 128 */
- ENTRY("", 129, no_syscall, 0, CALL_INDIRECT, VOID) /* 129 old truncate */
- ENTRY("", 130, no_syscall, 0, CALL_INDIRECT, VOID) /* 130 old ftruncate */
- ENTRY("flock", SYS_flock, flock, 2, CALL_DIRECT, INT, INT) /* 131 */
- ENTRY("mkfifo", SYS_mkfifo, mkfifo, 2, CALL_DIRECT, PTR, INT) /* 132 */
- ENTRY("sendto", SYS_sendto, sendto, 6, CALL_DIRECT, INT, PTR, SIZE, INT, PTR, INT) /* 133 */
- ENTRY("shutdown", SYS_shutdown, shutdown, 2, CALL_DIRECT, INT, INT) /* 134 */
- ENTRY("socketpair", SYS_socketpair, socketpair, 4, CALL_DIRECT, INT, INT, INT, PTR) /* 135 */
- ENTRY("mkdir", SYS_mkdir, mkdir, 2, CALL_DIRECT, PTR, INT) /* 136 */
- ENTRY("rmdir", SYS_rmdir, rmdir, 1, CALL_DIRECT, PTR) /* 137 */
- ENTRY("utimes", SYS_utimes, do_utimes, 2, CALL_DIRECT, PTR, PTR) /* 138 */
- ENTRY("futimes", SYS_futimes, do_futimes, 2, CALL_DIRECT, INT, PTR) /* 139 */
- ENTRY("adjtime", SYS_adjtime, adjtime, 2, CALL_DIRECT, PTR, PTR) /* 140 */
- ENTRY("", 141, no_syscall, 0, CALL_INDIRECT, VOID) /* 141 old getpeername */
- ENTRY("", 142, no_syscall, 0, CALL_INDIRECT, VOID) /* 142 old gethostid */
- ENTRY("", 143, no_syscall, 0, CALL_INDIRECT, VOID) /* 143 old sethostid */
- ENTRY("", 144, no_syscall, 0, CALL_INDIRECT, VOID) /* 144 old getrlimit */
- ENTRY("", 145, no_syscall, 0, CALL_INDIRECT, VOID) /* 145 old setrlimit */
- ENTRY("", 146, no_syscall, 0, CALL_INDIRECT, VOID) /* 146 old killpg */
- ENTRY("setsid", SYS_setsid, setsid, 0, CALL_DIRECT, VOID) /* 147 */
- ENTRY("", 148, no_syscall, 0, CALL_INDIRECT, VOID) /* 148 old setquota */
- ENTRY("", 149, no_syscall, 0, CALL_INDIRECT, VOID) /* 149 old qquota */
- ENTRY("", 150, no_syscall, 0, CALL_INDIRECT, VOID) /* 150 old getsockname */
- ENTRY("getpgid", SYS_getpgid, getpgid, 1, CALL_DIRECT, INT) /* 151 */
- ENTRY("setprivexec", SYS_setprivexec, no_syscall, 1, CALL_INDIRECT, VOID) /* 152 */
- ENTRY("pread", SYS_pread, do_pread, 4, CALL_DIRECT, INT, PTR, SIZE, OFFSET) /* 153 */
- ENTRY("pwrite", SYS_pwrite, pwrite, 4, CALL_DIRECT, INT, PTR, SIZE, OFFSET) /* 154 */
-#ifdef SYS_nfssvc
- ENTRY("nfssvc", SYS_nfssvc, nfssvc, 2, CALL_DIRECT, INT, PTR) /* 155 */
-#else
- ENTRY("nfssvc", 155, no_syscall, 2, CALL_INDIRECT, VOID) /* 155 */
-#endif
- ENTRY("", 155, no_syscall, 0, CALL_INDIRECT, VOID) /* 155 */
- ENTRY("", 156, no_syscall, 0, CALL_INDIRECT, VOID) /* 156 old getdirentries */
- ENTRY("statfs", SYS_statfs, do_statfs, 2, CALL_DIRECT, PTR, PTR) /* 157 */
- ENTRY("fstatfs", SYS_fstatfs, do_fstatfs, 2, CALL_DIRECT, INT, PTR) /* 158 */
- ENTRY("unmount", SYS_unmount, unmount, 2, CALL_DIRECT, PTR, INT) /* 159 */
- ENTRY("", 160, no_syscall, 0, CALL_INDIRECT, VOID) /* 160 old async_daemon */
- ENTRY("", 161, no_syscall, 0, CALL_INDIRECT, VOID) /* 161 */
- ENTRY("", 162, no_syscall, 0, CALL_INDIRECT, VOID) /* 162 old getdomainname */
- ENTRY("", 163, no_syscall, 0, CALL_INDIRECT, VOID) /* 163 old setdomainname */
- ENTRY("", 164, no_syscall, 0, CALL_INDIRECT, VOID) /* 164 */
- ENTRY("quotactl", SYS_quotactl, no_syscall, 4, CALL_INDIRECT, VOID) /* 165 */
- ENTRY("", 166, no_syscall, 0, CALL_INDIRECT, VOID) /* 166 old exportfs */
- ENTRY("mount", SYS_mount, mount, 4, CALL_DIRECT, PTR, PTR, INT, PTR) /* 167 */
- ENTRY("", 168, no_syscall, 0, CALL_INDIRECT, VOID) /* 168 old ustat */
- ENTRY("", 169, no_syscall, 0, CALL_INDIRECT, VOID) /* 169 */
- ENTRY("table", SYS_table, no_syscall, 0, CALL_INDIRECT, VOID) /* 170 old table */
- ENTRY("", 171, no_syscall, 0, CALL_INDIRECT, VOID) /* 171 old wait3 */
- ENTRY("", 172, no_syscall, 0, CALL_INDIRECT, VOID) /* 172 old rpause */
- ENTRY("waitid", SYS_waitid, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 173 */
- ENTRY("", 174, no_syscall, 0, CALL_INDIRECT, VOID) /* 174 old getdents */
- ENTRY("", 175, no_syscall, 0, CALL_INDIRECT, VOID) /* 175 old gc_control */
- ENTRY("add_profil", SYS_add_profil, add_profil, 4, CALL_DIRECT, PTR, SIZE, UINT, UINT) /* 176 */
- ENTRY("", 177, no_syscall, 0, CALL_INDIRECT, VOID) /* 177 */
- ENTRY("", 178, no_syscall, 0, CALL_INDIRECT, VOID) /* 178 */
- ENTRY("", 179, no_syscall, 0, CALL_INDIRECT, VOID) /* 179 */
- ENTRY("kdebug_trace", SYS_kdebug_trace, no_syscall, 6, CALL_INDIRECT, VOID) /* 180 */
- ENTRY("setgid", SYS_setgid, setgid, 1, CALL_DIRECT, INT) /* 181 */
- ENTRY("setegid", SYS_setegid, setegid, 1, CALL_DIRECT, INT) /* 182 */
- ENTRY("seteuid", SYS_seteuid, seteuid, 1, CALL_DIRECT, INT) /* 183 */
- ENTRY("sigreturn", SYS_sigreturn, do_sigreturn, 2, CALL_INDIRECT, PTR, INT) /* 184 */
- ENTRY("chud", SYS_chud, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 185 */
- ENTRY("", 186, no_syscall, 0, CALL_INDIRECT, VOID) /* 186 */
- ENTRY("", 187, no_syscall, 0, CALL_INDIRECT, VOID) /* 187 */
- ENTRY("stat", SYS_stat, do_stat, 2, CALL_DIRECT, PTR, PTR) /* 188 */
- ENTRY("fstat", SYS_fstat, do_fstat, 2, CALL_DIRECT, INT, PTR) /* 189 */
- ENTRY("lstat", SYS_lstat, do_lstat, 2, CALL_DIRECT, PTR, PTR) /* 190 */
- ENTRY("pathconf", SYS_pathconf, pathconf, 2, CALL_DIRECT, PTR, INT) /* 191 */
- ENTRY("fpathconf", SYS_fpathconf, fpathconf, 2, CALL_DIRECT, INT, INT) /* 192 */
- ENTRY("getfsstat", SYS_getfsstat, do_getfsstat, 3, CALL_DIRECT, PTR, INT, INT) /* 193 */
- ENTRY("", 193, no_syscall, 0, CALL_INDIRECT, VOID) /* 193 */
- ENTRY("getrlimit", SYS_getrlimit, getrlimit, 2, CALL_DIRECT, UINT, PTR) /* 194 */
- ENTRY("setrlimit", SYS_setrlimit, setrlimit, 2, CALL_DIRECT, UINT, PTR) /* 195 */
- ENTRY("getdirentries", SYS_getdirentries, do_getdirentries, 4, CALL_DIRECT, INT, PTR, UINT, PTR) /* 196 */
- ENTRY("mmap", SYS_mmap, target_mmap, 6, CALL_DIRECT, UINT /*PTR*/, SIZE, INT, INT, INT, OFFSET) /* 197 */
- ENTRY("", 198, no_syscall, 0, CALL_INDIRECT, VOID) /* 198 __syscall */
- ENTRY("lseek", SYS_lseek, do_lseek, 3, CALL_INDIRECT, INT, OFFSET, INT) /* 199 */
- ENTRY("truncate", SYS_truncate, truncate, 2, CALL_DIRECT, PTR, OFFSET) /* 200 */
- ENTRY("ftruncate", SYS_ftruncate, ftruncate, 2, CALL_DIRECT, INT, OFFSET) /* 201 */
- ENTRY("__sysctl", SYS___sysctl, do___sysctl, 6, CALL_DIRECT, PTR, INT, PTR, PTR, PTR, SIZE) /* 202 */
- ENTRY("mlock", SYS_mlock, mlock, 2, CALL_DIRECT, PTR, SIZE) /* 203 */
- ENTRY("munlock", SYS_munlock, munlock, 2, CALL_DIRECT, PTR, SIZE) /* 204 */
- ENTRY("undelete", SYS_undelete, undelete, 1, CALL_DIRECT, PTR) /* 205 */
- ENTRY("ATsocket", SYS_ATsocket, no_syscall, 1, CALL_INDIRECT, VOID) /* 206 */
- ENTRY("ATgetmsg", SYS_ATgetmsg, no_syscall, 4, CALL_INDIRECT, VOID) /* 207 */
- ENTRY("ATputmsg", SYS_ATputmsg, no_syscall, 4, CALL_INDIRECT, VOID) /* 208 */
- ENTRY("ATPsndreq", SYS_ATPsndreq, no_syscall, 4, CALL_INDIRECT, VOID) /* 209 */
- ENTRY("ATPsndrsp", SYS_ATPsndrsp, no_syscall, 4, CALL_INDIRECT, VOID) /* 210 */
- ENTRY("ATPgetreq", SYS_ATPgetreq, no_syscall, 3, CALL_INDIRECT, VOID) /* 211 */
- ENTRY("ATPgetrsp", SYS_ATPgetrsp, no_syscall, 2, CALL_INDIRECT, VOID) /* 212 */
- ENTRY("", 213, no_syscall, 0, CALL_INDIRECT, VOID) /* 213 Reserved for AppleTalk */
- ENTRY("kqueue_from_portset_np", SYS_kqueue_from_portset_np, no_syscall, 1, CALL_INDIRECT, VOID) /* 214 */
- ENTRY("kqueue_portset_np", SYS_kqueue_portset_np, no_syscall, 1, CALL_INDIRECT, VOID) /* 215 */
- ENTRY("mkcomplex", SYS_mkcomplex, no_syscall, 3, CALL_INDIRECT, VOID) /* 216 soon to be obsolete */
- ENTRY("statv", SYS_statv, no_syscall, 2, CALL_INDIRECT, VOID) /* 217 soon to be obsolete */
- ENTRY("lstatv", SYS_lstatv, no_syscall, 2, CALL_INDIRECT, VOID) /* 218 soon to be obsolete */
- ENTRY("fstatv", SYS_fstatv, no_syscall, 2, CALL_INDIRECT, VOID) /* 219 soon to be obsolete */
- ENTRY("getattrlist", SYS_getattrlist, do_getattrlist, 5, CALL_DIRECT, PTR, PTR, PTR, SIZE, UINT) /* 220 */
- ENTRY("setattrlist", SYS_setattrlist, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 221 */
- ENTRY("getdirentriesattr", SYS_getdirentriesattr, do_getdirentriesattr, 8, CALL_DIRECT, INT, PTR, PTR, SIZE, PTR, PTR, PTR, UINT) /* 222 */
- ENTRY("exchangedata", SYS_exchangedata, exchangedata, 3, CALL_DIRECT, PTR, PTR, UINT) /* 223 */
- ENTRY("checkuseraccess", SYS_checkuseraccess, checkuseraccess, 6, CALL_DIRECT, PTR, INT, PTR, INT, INT, UINT) /* 224 */
- ENTRY("", 224, no_syscall, 0, CALL_INDIRECT, VOID) /* 224 HFS checkuseraccess check access to a file */
- ENTRY("searchfs", SYS_searchfs, searchfs, 6, CALL_DIRECT, PTR, PTR, PTR, UINT, UINT, PTR) /* 225 */
- ENTRY("delete", SYS_delete, no_syscall, 1, CALL_INDIRECT, VOID) /* 226 private delete ( Carbon semantics ) */
- ENTRY("copyfile", SYS_copyfile, no_syscall, 4, CALL_INDIRECT, VOID) /* 227 */
- ENTRY("", 228, no_syscall, 0, CALL_INDIRECT, VOID) /* 228 */
- ENTRY("", 229, no_syscall, 0, CALL_INDIRECT, VOID) /* 229 */
- ENTRY("poll", SYS_poll, no_syscall, 3, CALL_INDIRECT, VOID) /* 230 */
- ENTRY("watchevent", SYS_watchevent, no_syscall, 2, CALL_INDIRECT, VOID) /* 231 */
- ENTRY("waitevent", SYS_waitevent, no_syscall, 2, CALL_INDIRECT, VOID) /* 232 */
- ENTRY("modwatch", SYS_modwatch, no_syscall, 2, CALL_INDIRECT, VOID) /* 233 */
- ENTRY("getxattr", SYS_getxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 234 */
- ENTRY("fgetxattr", SYS_fgetxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 235 */
- ENTRY("setxattr", SYS_setxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 236 */
- ENTRY("fsetxattr", SYS_fsetxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 237 */
- ENTRY("removexattr", SYS_removexattr, no_syscall, 3, CALL_INDIRECT, VOID) /* 238 */
- ENTRY("fremovexattr", SYS_fremovexattr, no_syscall, 3, CALL_INDIRECT, VOID) /* 239 */
- ENTRY("listxattr", SYS_listxattr, listxattr, 4, CALL_INDIRECT, VOID) /* 240 */
- ENTRY("flistxattr", SYS_flistxattr, no_syscall, 4, CALL_INDIRECT, VOID) /* 241 */
- ENTRY("fsctl", SYS_fsctl, fsctl, 4, CALL_DIRECT, PTR, UINT, PTR, UINT) /* 242 */
- ENTRY("initgroups", SYS_initgroups, unimpl_unix_syscall, 3, CALL_INDIRECT, UINT, PTR, INT) /* 243 */
- ENTRY("", 244, no_syscall, 0, CALL_INDIRECT, VOID) /* 244 */
- ENTRY("", 245, no_syscall, 0, CALL_INDIRECT, VOID) /* 245 */
- ENTRY("", 246, no_syscall, 0, CALL_INDIRECT, VOID) /* 246 */
-#ifdef SYS_nfsclnt
- ENTRY("nfsclnt", SYS_nfsclnt, nfsclnt, 2, CALL_DIRECT, INT, PTR) /* 247 */
-#else
- ENTRY("nfsclnt", 247, no_syscall, 2, CALL_INDIRECT, VOID) /* 247 */
-#endif
- ENTRY("", 247, no_syscall, 0, CALL_INDIRECT, VOID) /* 247 */
- ENTRY("", 248, no_syscall, 0, CALL_INDIRECT, VOID) /* 248 */
- ENTRY("", 249, no_syscall, 0, CALL_INDIRECT, VOID) /* 249 */
- ENTRY("minherit", SYS_minherit, minherit, 3, CALL_DIRECT, PTR, INT, INT) /* 250 */
- ENTRY("semsys", SYS_semsys, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 251 */
- ENTRY("msgsys", SYS_msgsys, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 252 */
- ENTRY("shmsys", SYS_shmsys, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 253 */
- ENTRY("semctl", SYS_semctl, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 254 */
- ENTRY("semget", SYS_semget, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 255 */
- ENTRY("semop", SYS_semop, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 256 */
- ENTRY("", 257, no_syscall, 0, CALL_INDIRECT, VOID) /* 257 */
- ENTRY("msgctl", SYS_msgctl, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 258 */
- ENTRY("msgget", SYS_msgget, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 259 */
- ENTRY("msgsnd", SYS_msgsnd, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 260 */
- ENTRY("msgrcv", SYS_msgrcv, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 261 */
- ENTRY("shmat", SYS_shmat, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 262 */
- ENTRY("shmctl", SYS_shmctl, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 263 */
- ENTRY("shmdt", SYS_shmdt, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 264 */
- ENTRY("shmget", SYS_shmget, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 265 */
- ENTRY("shm_open", SYS_shm_open, shm_open, 3, CALL_DIRECT, PTR, INT, INT) /* 266 */
- ENTRY("shm_unlink", SYS_shm_unlink, shm_unlink, 1, CALL_DIRECT, PTR) /* 267 */
- ENTRY("sem_open", SYS_sem_open, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 268 */
- ENTRY("sem_close", SYS_sem_close, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 269 */
- ENTRY("sem_unlink", SYS_sem_unlink, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 270 */
- ENTRY("sem_wait", SYS_sem_wait, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 271 */
- ENTRY("sem_trywait", SYS_sem_trywait, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 272 */
- ENTRY("sem_post", SYS_sem_post, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 273 */
- ENTRY("sem_getvalue", SYS_sem_getvalue, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 274 */
- ENTRY("sem_init", SYS_sem_init, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 275 */
- ENTRY("sem_destroy", SYS_sem_destroy, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 276 */
- ENTRY("open_extended", SYS_open_extended, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 277 */
- ENTRY("umask_extended", SYS_umask_extended, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 278 */
- ENTRY("stat_extended", SYS_stat_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 279 */
- ENTRY("lstat_extended", SYS_lstat_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 280 */
- ENTRY("fstat_extended", SYS_fstat_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 281 */
- ENTRY("chmod_extended", SYS_chmod_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 282 */
- ENTRY("fchmod_extended", SYS_fchmod_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 283 */
- ENTRY("access_extended", SYS_access_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 284 */
- ENTRY("settid", SYS_settid, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 285 */
- ENTRY("gettid", SYS_gettid, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 286 */
- ENTRY("setsgroups", SYS_setsgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 287 */
- ENTRY("getsgroups", SYS_getsgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 288 */
- ENTRY("setwgroups", SYS_setwgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 289 */
- ENTRY("getwgroups", SYS_getwgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 290 */
- ENTRY("mkfifo_extended", SYS_mkfifo_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 291 */
- ENTRY("mkdir_extended", SYS_mkdir_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 292 */
- ENTRY("identitysvc", SYS_identitysvc, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 293 */
- ENTRY("", 294, no_syscall, 0, CALL_INDIRECT, VOID) /* 294 */
- ENTRY("", 295, no_syscall, 0, CALL_INDIRECT, VOID) /* 295 */
- ENTRY("load_shared_file", SYS_load_shared_file, unimpl_unix_syscall, 7, CALL_INDIRECT, VOID) /* 296 */
- ENTRY("reset_shared_file", SYS_reset_shared_file, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 297 */
- ENTRY("new_system_shared_regions", SYS_new_system_shared_regions, unimpl_unix_syscall, 0, CALL_INDIRECT, VOID) /* 298 */
- ENTRY("shared_region_map_file_np", SYS_shared_region_map_file_np, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 299 */
- ENTRY("shared_region_make_private_np", SYS_shared_region_make_private_np, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 300 */
- ENTRY("", 301, no_syscall, 0, CALL_INDIRECT, VOID) /* 301 */
- ENTRY("", 302, no_syscall, 0, CALL_INDIRECT, VOID) /* 302 */
- ENTRY("", 303, no_syscall, 0, CALL_INDIRECT, VOID) /* 303 */
- ENTRY("", 304, no_syscall, 0, CALL_INDIRECT, VOID) /* 304 */
- ENTRY("", 305, no_syscall, 0, CALL_INDIRECT, VOID) /* 305 */
- ENTRY("", 306, no_syscall, 0, CALL_INDIRECT, VOID) /* 306 */
- ENTRY("", 307, no_syscall, 0, CALL_INDIRECT, VOID) /* 307 */
- ENTRY("", 308, no_syscall, 0, CALL_INDIRECT, VOID) /* 308 */
- ENTRY("", 309, no_syscall, 0, CALL_INDIRECT, VOID) /* 309 */
- ENTRY("getsid", SYS_getsid, getsid, 1, CALL_DIRECT, INT) /* 310 */
- ENTRY("settid_with_pid", SYS_settid_with_pid, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 311 */
- ENTRY("", 312, no_syscall, 0, CALL_INDIRECT, VOID) /* 312 */
- ENTRY("aio_fsync", SYS_aio_fsync, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 313 */
- ENTRY("aio_return", SYS_aio_return, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 314 */
- ENTRY("aio_suspend", SYS_aio_suspend, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 315 */
- ENTRY("aio_cancel", SYS_aio_cancel, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 316 */
- ENTRY("aio_error", SYS_aio_error, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 317 */
- ENTRY("aio_read", SYS_aio_read, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 318 */
- ENTRY("aio_write", SYS_aio_write, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 319 */
- ENTRY("lio_listio", SYS_lio_listio, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 320 */
- ENTRY("", 321, no_syscall, 0, CALL_INDIRECT, VOID) /* 321 */
- ENTRY("", 322, no_syscall, 0, CALL_INDIRECT, VOID) /* 322 */
- ENTRY("", 323, no_syscall, 0, CALL_INDIRECT, VOID) /* 323 */
- ENTRY("mlockall", SYS_mlockall, mlockall, 1, CALL_DIRECT, INT) /* 324 */
- ENTRY("munlockall", SYS_munlockall, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 325 */
- ENTRY("", 326, no_syscall, 0, CALL_INDIRECT, VOID) /* 326 */
- ENTRY("issetugid", SYS_issetugid, issetugid, 0, CALL_DIRECT, VOID) /* 327 */
- ENTRY("__pthread_kill", SYS___pthread_kill, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 328 */
- ENTRY("pthread_sigmask", SYS_pthread_sigmask, pthread_sigmask, 3, CALL_DIRECT, INT, PTR, PTR) /* 329 */
- ENTRY("sigwait", SYS_sigwait, sigwait, 2, CALL_DIRECT, PTR, PTR) /* 330 */
- ENTRY("__disable_threadsignal", SYS___disable_threadsignal, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 331 */
- ENTRY("__pthread_markcancel", SYS___pthread_markcancel, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 332 */
- ENTRY("__pthread_canceled", SYS___pthread_canceled, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 333 */
- ENTRY("__semwait_signal", SYS___semwait_signal, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 334 */
- ENTRY("utrace", SYS_utrace, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 335 */
- ENTRY("proc_info", SYS_proc_info, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 336 */
- ENTRY("", 337, no_syscall, 0, CALL_INDIRECT, VOID) /* 337 */
- ENTRY("", 338, no_syscall, 0, CALL_INDIRECT, VOID) /* 338 */
- ENTRY("", 339, no_syscall, 0, CALL_INDIRECT, VOID) /* 339 */
- ENTRY("", 340, no_syscall, 0, CALL_INDIRECT, VOID) /* 340 */
- ENTRY("", 341, no_syscall, 0, CALL_INDIRECT, VOID) /* 341 */
- ENTRY("", 342, no_syscall, 0, CALL_INDIRECT, VOID) /* 342 */
- ENTRY("", 343, no_syscall, 0, CALL_INDIRECT, VOID) /* 343 */
- ENTRY("", 344, no_syscall, 0, CALL_INDIRECT, VOID) /* 344 */
- ENTRY("", 345, no_syscall, 0, CALL_INDIRECT, VOID) /* 345 */
- ENTRY("", 346, no_syscall, 0, CALL_INDIRECT, VOID) /* 346 */
- ENTRY("", 347, no_syscall, 0, CALL_INDIRECT, VOID) /* 347 */
- ENTRY("", 348, no_syscall, 0, CALL_INDIRECT, VOID) /* 348 */
- ENTRY("", 349, no_syscall, 0, CALL_INDIRECT, VOID) /* 349 */
- ENTRY("audit", SYS_audit, audit, 2, CALL_DIRECT, PTR, INT) /* 350 */
- ENTRY("auditon", SYS_auditon, auditon, 3, CALL_DIRECT, INT, PTR, INT) /* 351 */
- ENTRY("", 352, no_syscall, 0, CALL_INDIRECT, VOID) /* 352 */
- ENTRY("getauid", SYS_getauid, getauid, 1, CALL_DIRECT, PTR) /* 353 */
- ENTRY("setauid", SYS_setauid, setauid, 1, CALL_DIRECT, PTR) /* 354 */
- ENTRY("getaudit", SYS_getaudit, getaudit, 1, CALL_DIRECT, PTR) /* 355 */
- ENTRY("setaudit", SYS_setaudit, setaudit, 1, CALL_DIRECT, PTR) /* 356 */
- ENTRY("getaudit_addr", SYS_getaudit_addr, getaudit_addr, 2, CALL_DIRECT, PTR, INT) /* 357 */
- ENTRY("setaudit_addr", SYS_setaudit_addr, setaudit_addr, 2, CALL_DIRECT, PTR, INT) /* 358 */
- ENTRY("auditctl", SYS_auditctl, auditctl, 1, CALL_DIRECT, PTR) /* 359 */
- ENTRY("", 360, no_syscall, 0, CALL_INDIRECT, VOID) /* 360 */
- ENTRY("", 361, no_syscall, 0, CALL_INDIRECT, VOID) /* 361 */
- ENTRY("kqueue", SYS_kqueue, kqueue, 0, CALL_DIRECT, VOID) /* 362 */
- ENTRY("kevent", SYS_kevent, kevent, 6, CALL_DIRECT, INT, PTR, INT, PTR, INT, PTR) /* 363 */
- ENTRY("lchown", SYS_lchown, lchown, 3, CALL_DIRECT, PTR, INT , INT) /* 364 */
- ENTRY("stack_snapshot", SYS_stack_snapshot, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 365 */
- ENTRY("", 366, no_syscall, 0, CALL_INDIRECT, VOID) /* 366 */
- ENTRY("", 367, no_syscall, 0, CALL_INDIRECT, VOID) /* 367 */
- ENTRY("", 368, no_syscall, 0, CALL_INDIRECT, VOID) /* 368 */
- ENTRY("", 369, no_syscall, 0, CALL_INDIRECT, VOID) /* 369 */
+++ /dev/null
-# Default configuration for i386-darwin-user
+++ /dev/null
-# Default configuration for ppc-darwin-user
-
-CONFIG_GDBSTUB_XML=y
| The result is stored in the location pointed to by `zPtr'.
*----------------------------------------------------------------------------*/
-INLINE void shift32RightJamming( uint32_t a, int16 count, uint32_t *zPtr )
+INLINE void shift32RightJamming(uint32_t a, int_fast16_t count, uint32_t *zPtr)
{
uint32_t z;
| The result is stored in the location pointed to by `zPtr'.
*----------------------------------------------------------------------------*/
-INLINE void shift64RightJamming( uint64_t a, int16 count, uint64_t *zPtr )
+INLINE void shift64RightJamming(uint64_t a, int_fast16_t count, uint64_t *zPtr)
{
uint64_t z;
INLINE void
shift64ExtraRightJamming(
- uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr )
+ uint64_t a0, uint64_t a1, int_fast16_t count, uint64_t *z0Ptr, uint64_t *z1Ptr)
{
uint64_t z0, z1;
int8 negCount = ( - count ) & 63;
INLINE void
shift128Right(
- uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr )
+ uint64_t a0, uint64_t a1, int_fast16_t count, uint64_t *z0Ptr, uint64_t *z1Ptr)
{
uint64_t z0, z1;
int8 negCount = ( - count ) & 63;
INLINE void
shift128RightJamming(
- uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr )
+ uint64_t a0, uint64_t a1, int_fast16_t count, uint64_t *z0Ptr, uint64_t *z1Ptr)
{
uint64_t z0, z1;
int8 negCount = ( - count ) & 63;
uint64_t a0,
uint64_t a1,
uint64_t a2,
- int16 count,
+ int_fast16_t count,
uint64_t *z0Ptr,
uint64_t *z1Ptr,
uint64_t *z2Ptr
INLINE void
shortShift128Left(
- uint64_t a0, uint64_t a1, int16 count, uint64_t *z0Ptr, uint64_t *z1Ptr )
+ uint64_t a0, uint64_t a1, int_fast16_t count, uint64_t *z0Ptr, uint64_t *z1Ptr)
{
*z1Ptr = a1<<count;
uint64_t a0,
uint64_t a1,
uint64_t a2,
- int16 count,
+ int_fast16_t count,
uint64_t *z0Ptr,
uint64_t *z1Ptr,
uint64_t *z2Ptr
| value.
*----------------------------------------------------------------------------*/
-static uint32_t estimateSqrt32( int16 aExp, uint32_t a )
+static uint32_t estimateSqrt32(int_fast16_t aExp, uint32_t a)
{
static const uint16_t sqrtOddAdjustments[] = {
0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
| Returns the exponent bits of the half-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
-INLINE int16 extractFloat16Exp(float16 a)
+INLINE int_fast16_t extractFloat16Exp(float16 a)
{
return (float16_val(a) >> 10) & 0x1f;
}
| Returns the exponent bits of the single-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
-INLINE int16 extractFloat32Exp( float32 a )
+INLINE int_fast16_t extractFloat32Exp(float32 a)
{
return ( float32_val(a)>>23 ) & 0xFF;
*----------------------------------------------------------------------------*/
static void
- normalizeFloat32Subnormal( uint32_t aSig, int16 *zExpPtr, uint32_t *zSigPtr )
+ normalizeFloat32Subnormal(uint32_t aSig, int_fast16_t *zExpPtr, uint32_t *zSigPtr)
{
int8 shiftCount;
| significand.
*----------------------------------------------------------------------------*/
-INLINE float32 packFloat32( flag zSign, int16 zExp, uint32_t zSig )
+INLINE float32 packFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig)
{
return make_float32(
| Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-static float32 roundAndPackFloat32( flag zSign, int16 zExp, uint32_t zSig STATUS_PARAM)
+static float32 roundAndPackFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig STATUS_PARAM)
{
int8 roundingMode;
flag roundNearestEven;
*----------------------------------------------------------------------------*/
static float32
- normalizeRoundAndPackFloat32( flag zSign, int16 zExp, uint32_t zSig STATUS_PARAM)
+ normalizeRoundAndPackFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig STATUS_PARAM)
{
int8 shiftCount;
| Returns the exponent bits of the double-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
-INLINE int16 extractFloat64Exp( float64 a )
+INLINE int_fast16_t extractFloat64Exp(float64 a)
{
return ( float64_val(a)>>52 ) & 0x7FF;
*----------------------------------------------------------------------------*/
static void
- normalizeFloat64Subnormal( uint64_t aSig, int16 *zExpPtr, uint64_t *zSigPtr )
+ normalizeFloat64Subnormal(uint64_t aSig, int_fast16_t *zExpPtr, uint64_t *zSigPtr)
{
int8 shiftCount;
| significand.
*----------------------------------------------------------------------------*/
-INLINE float64 packFloat64( flag zSign, int16 zExp, uint64_t zSig )
+INLINE float64 packFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig)
{
return make_float64(
| Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-static float64 roundAndPackFloat64( flag zSign, int16 zExp, uint64_t zSig STATUS_PARAM)
+static float64 roundAndPackFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig STATUS_PARAM)
{
int8 roundingMode;
flag roundNearestEven;
- int16 roundIncrement, roundBits;
+ int_fast16_t roundIncrement, roundBits;
flag isTiny;
roundingMode = STATUS(float_rounding_mode);
*----------------------------------------------------------------------------*/
static float64
- normalizeRoundAndPackFloat64( flag zSign, int16 zExp, uint64_t zSig STATUS_PARAM)
+ normalizeRoundAndPackFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig STATUS_PARAM)
{
int8 shiftCount;
int32 float32_to_int32( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint32_t aSig;
uint64_t aSig64;
int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint32_t aSig;
int32_t z;
a = float32_squash_input_denormal(a STATUS_VAR);
| returned.
*----------------------------------------------------------------------------*/
-int16 float32_to_int16_round_to_zero( float32 a STATUS_PARAM )
+int_fast16_t float32_to_int16_round_to_zero(float32 a STATUS_PARAM)
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint32_t aSig;
int32 z;
int64 float32_to_int64( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint32_t aSig;
uint64_t aSig64, aSigExtra;
a = float32_squash_input_denormal(a STATUS_VAR);
int64 float32_to_int64_round_to_zero( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint32_t aSig;
uint64_t aSig64;
int64 z;
float64 float32_to_float64( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t aSig;
a = float32_squash_input_denormal(a STATUS_VAR);
floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t aSig;
a = float32_squash_input_denormal(a STATUS_VAR);
float128 float32_to_float128( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t aSig;
a = float32_squash_input_denormal(a STATUS_VAR);
float32 float32_round_to_int( float32 a STATUS_PARAM)
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t lastBitMask, roundBitsMask;
int8 roundingMode;
uint32_t z;
static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
{
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint32_t aSig, bSig, zSig;
- int16 expDiff;
+ int_fast16_t expDiff;
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
static float32 subFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
{
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint32_t aSig, bSig, zSig;
- int16 expDiff;
+ int_fast16_t expDiff;
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
float32 float32_mul( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign, zSign;
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint32_t aSig, bSig;
uint64_t zSig64;
uint32_t zSig;
float32 float32_div( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign, zSign;
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint32_t aSig, bSig, zSig;
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
float32 float32_rem( float32 a, float32 b STATUS_PARAM )
{
flag aSign, zSign;
- int16 aExp, bExp, expDiff;
+ int_fast16_t aExp, bExp, expDiff;
uint32_t aSig, bSig;
uint32_t q;
uint64_t aSig64, bSig64, q64;
float32 float32_muladd(float32 a, float32 b, float32 c, int flags STATUS_PARAM)
{
flag aSign, bSign, cSign, zSign;
- int aExp, bExp, cExp, pExp, zExp, expDiff;
+ int_fast16_t aExp, bExp, cExp, pExp, zExp, expDiff;
uint32_t aSig, bSig, cSig;
flag pInf, pZero, pSign;
uint64_t pSig64, cSig64, zSig64;
float32 float32_sqrt( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, zExp;
+ int_fast16_t aExp, zExp;
uint32_t aSig, zSig;
uint64_t rem, term;
a = float32_squash_input_denormal(a STATUS_VAR);
float32 float32_exp2( float32 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t aSig;
float64 r, x, xn;
int i;
float32 float32_log2( float32 a STATUS_PARAM )
{
flag aSign, zSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t aSig, zSig, i;
a = float32_squash_input_denormal(a STATUS_VAR);
int32 float64_to_int32( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint64_t aSig;
a = float64_squash_input_denormal(a STATUS_VAR);
int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint64_t aSig, savedASig;
int32_t z;
a = float64_squash_input_denormal(a STATUS_VAR);
| returned.
*----------------------------------------------------------------------------*/
-int16 float64_to_int16_round_to_zero( float64 a STATUS_PARAM )
+int_fast16_t float64_to_int16_round_to_zero(float64 a STATUS_PARAM)
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint64_t aSig, savedASig;
int32 z;
int64 float64_to_int64( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint64_t aSig, aSigExtra;
a = float64_squash_input_denormal(a STATUS_VAR);
int64 float64_to_int64_round_to_zero( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, shiftCount;
+ int_fast16_t aExp, shiftCount;
uint64_t aSig;
int64 z;
a = float64_squash_input_denormal(a STATUS_VAR);
float32 float64_to_float32( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint64_t aSig;
uint32_t zSig;
a = float64_squash_input_denormal(a STATUS_VAR);
| than the desired result exponent whenever `zSig' is a complete, normalized
| significand.
*----------------------------------------------------------------------------*/
-static float16 packFloat16(flag zSign, int16 zExp, uint16_t zSig)
+static float16 packFloat16(flag zSign, int_fast16_t zExp, uint16_t zSig)
{
return make_float16(
(((uint32_t)zSign) << 15) + (((uint32_t)zExp) << 10) + zSig);
float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM)
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t aSig;
aSign = extractFloat16Sign(a);
float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint32_t aSig;
uint32_t mask;
uint32_t increment;
floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint64_t aSig;
a = float64_squash_input_denormal(a STATUS_VAR);
float128 float64_to_float128( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint64_t aSig, zSig0, zSig1;
a = float64_squash_input_denormal(a STATUS_VAR);
float64 float64_round_to_int( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint64_t lastBitMask, roundBitsMask;
int8 roundingMode;
uint64_t z;
static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
{
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint64_t aSig, bSig, zSig;
- int16 expDiff;
+ int_fast16_t expDiff;
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
static float64 subFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
{
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint64_t aSig, bSig, zSig;
- int16 expDiff;
+ int_fast16_t expDiff;
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
float64 float64_mul( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign, zSign;
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint64_t aSig, bSig, zSig0, zSig1;
a = float64_squash_input_denormal(a STATUS_VAR);
float64 float64_div( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign, zSign;
- int16 aExp, bExp, zExp;
+ int_fast16_t aExp, bExp, zExp;
uint64_t aSig, bSig, zSig;
uint64_t rem0, rem1;
uint64_t term0, term1;
float64 float64_rem( float64 a, float64 b STATUS_PARAM )
{
flag aSign, zSign;
- int16 aExp, bExp, expDiff;
+ int_fast16_t aExp, bExp, expDiff;
uint64_t aSig, bSig;
uint64_t q, alternateASig;
int64_t sigMean;
float64 float64_muladd(float64 a, float64 b, float64 c, int flags STATUS_PARAM)
{
flag aSign, bSign, cSign, zSign;
- int aExp, bExp, cExp, pExp, zExp, expDiff;
+ int_fast16_t aExp, bExp, cExp, pExp, zExp, expDiff;
uint64_t aSig, bSig, cSig;
flag pInf, pZero, pSign;
uint64_t pSig0, pSig1, cSig0, cSig1, zSig0, zSig1;
float64 float64_sqrt( float64 a STATUS_PARAM )
{
flag aSign;
- int16 aExp, zExp;
+ int_fast16_t aExp, zExp;
uint64_t aSig, zSig, doubleZSig;
uint64_t rem0, rem1, term0, term1;
a = float64_squash_input_denormal(a STATUS_VAR);
float64 float64_log2( float64 a STATUS_PARAM )
{
flag aSign, zSign;
- int16 aExp;
+ int_fast16_t aExp;
uint64_t aSig, aSig0, aSig1, zSig, i;
a = float64_squash_input_denormal(a STATUS_VAR);
float128 floatx80_to_float128( floatx80 a STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int_fast16_t aExp;
uint64_t aSig, zSig0, zSig1;
aSig = extractFloatx80Frac( a );
return res;
}
-uint16 float32_to_uint16_round_to_zero( float32 a STATUS_PARAM )
+uint_fast16_t float32_to_uint16_round_to_zero(float32 a STATUS_PARAM)
{
int64_t v;
- uint16 res;
+ uint_fast16_t res;
v = float32_to_int64_round_to_zero(a STATUS_VAR);
if (v < 0) {
return res;
}
-uint16 float64_to_uint16_round_to_zero( float64 a STATUS_PARAM )
+uint_fast16_t float64_to_uint16_round_to_zero(float64 a STATUS_PARAM)
{
int64_t v;
- uint16 res;
+ uint_fast16_t res;
v = float64_to_int64_round_to_zero(a STATUS_VAR);
if (v < 0) {
#include <inttypes.h>
#include "config-host.h"
+#include "osdep.h"
/*----------------------------------------------------------------------------
| Each of the following `typedef's defines the most convenient type that holds
typedef uint8_t flag;
typedef uint8_t uint8;
typedef int8_t int8;
-#ifndef _AIX
-typedef int uint16;
-typedef int int16;
-#endif
typedef unsigned int uint32;
typedef signed int int32;
typedef uint64_t uint64;
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision conversion routines.
*----------------------------------------------------------------------------*/
-int16 float32_to_int16_round_to_zero( float32 STATUS_PARAM );
-uint16 float32_to_uint16_round_to_zero( float32 STATUS_PARAM );
+int_fast16_t float32_to_int16_round_to_zero(float32 STATUS_PARAM);
+uint_fast16_t float32_to_uint16_round_to_zero(float32 STATUS_PARAM);
int32 float32_to_int32( float32 STATUS_PARAM );
int32 float32_to_int32_round_to_zero( float32 STATUS_PARAM );
uint32 float32_to_uint32( float32 STATUS_PARAM );
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
-int16 float64_to_int16_round_to_zero( float64 STATUS_PARAM );
-uint16 float64_to_uint16_round_to_zero( float64 STATUS_PARAM );
+int_fast16_t float64_to_int16_round_to_zero(float64 STATUS_PARAM);
+uint_fast16_t float64_to_uint16_round_to_zero(float64 STATUS_PARAM);
int32 float64_to_int32( float64 STATUS_PARAM );
int32 float64_to_int32_round_to_zero( float64 STATUS_PARAM );
uint32 float64_to_uint32( float64 STATUS_PARAM );
{
.name = "block_stream",
- .args_type = "device:B,base:s?",
- .params = "device [base]",
+ .args_type = "device:B,speed:o?,base:s?",
+ .params = "device [speed [base]]",
.help = "copy data from a backing file into a block device",
.mhandler.cmd = hmp_block_stream,
},
{
.name = "block_job_set_speed",
- .args_type = "device:B,value:o",
- .params = "device value",
+ .args_type = "device:B,speed:o",
+ .params = "device speed",
.help = "set maximum speed for a background block operation",
.mhandler.cmd = hmp_block_job_set_speed,
},
Error *error = NULL;
const char *device = qdict_get_str(qdict, "device");
const char *base = qdict_get_try_str(qdict, "base");
+ int64_t speed = qdict_get_try_int(qdict, "speed", 0);
- qmp_block_stream(device, base != NULL, base, &error);
+ qmp_block_stream(device, base != NULL, base,
+ qdict_haskey(qdict, "speed"), speed, &error);
hmp_handle_error(mon, &error);
}
DEBUG_GENERAL, DEBUG_IO, DEBUG_MMIO, DEBUG_INTERRUPT,
DEBUG_RX, DEBUG_TX, DEBUG_MDIC, DEBUG_EEPROM,
DEBUG_UNKNOWN, DEBUG_TXSUM, DEBUG_TXERR, DEBUG_RXERR,
- DEBUG_RXFILTER, DEBUG_NOTYET,
+ DEBUG_RXFILTER, DEBUG_PHY, DEBUG_NOTYET,
};
#define DBGBIT(x) (1<<DEBUG_##x)
static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
uint16_t reading;
uint32_t old_eecd;
} eecd_state;
+
+ QEMUTimer *autoneg_timer;
} E1000State;
#define defreg(x) x = (E1000_##x>>2)
defreg(VET),
};
+static void
+e1000_link_down(E1000State *s)
+{
+ s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
+ s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
+}
+
+static void
+e1000_link_up(E1000State *s)
+{
+ s->mac_reg[STATUS] |= E1000_STATUS_LU;
+ s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS;
+}
+
+static void
+set_phy_ctrl(E1000State *s, int index, uint16_t val)
+{
+ if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) {
+ s->nic->nc.link_down = true;
+ e1000_link_down(s);
+ s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE;
+ DBGOUT(PHY, "Start link auto negotiation\n");
+ qemu_mod_timer(s->autoneg_timer, qemu_get_clock_ms(vm_clock) + 500);
+ }
+}
+
+static void
+e1000_autoneg_timer(void *opaque)
+{
+ E1000State *s = opaque;
+ s->nic->nc.link_down = false;
+ e1000_link_up(s);
+ s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
+ DBGOUT(PHY, "Auto negotiation is completed\n");
+}
+
+static void (*phyreg_writeops[])(E1000State *, int, uint16_t) = {
+ [PHY_CTRL] = set_phy_ctrl,
+};
+
+enum { NPHYWRITEOPS = ARRAY_SIZE(phyreg_writeops) };
+
enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W };
static const char phy_regcap[0x20] = {
[PHY_STATUS] = PHY_R, [M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW,
[PHY_ID2] = PHY_R, [M88E1000_PHY_SPEC_STATUS] = PHY_R
};
+static const uint16_t phy_reg_init[] = {
+ [PHY_CTRL] = 0x1140,
+ [PHY_STATUS] = 0x794d, /* link initially up with not completed autoneg */
+ [PHY_ID1] = 0x141, [PHY_ID2] = PHY_ID2_INIT,
+ [PHY_1000T_CTRL] = 0x0e00, [M88E1000_PHY_SPEC_CTRL] = 0x360,
+ [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60, [PHY_AUTONEG_ADV] = 0xde1,
+ [PHY_LP_ABILITY] = 0x1e0, [PHY_1000T_STATUS] = 0x3c00,
+ [M88E1000_PHY_SPEC_STATUS] = 0xac00,
+};
+
+static const uint32_t mac_reg_init[] = {
+ [PBA] = 0x00100030,
+ [LEDCTL] = 0x602,
+ [CTRL] = E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 |
+ E1000_CTRL_SPD_1000 | E1000_CTRL_SLU,
+ [STATUS] = 0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE |
+ E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK |
+ E1000_STATUS_SPEED_1000 | E1000_STATUS_FD |
+ E1000_STATUS_LU,
+ [MANC] = E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN |
+ E1000_MANC_ARP_EN | E1000_MANC_0298_EN |
+ E1000_MANC_RMCP_EN,
+};
+
static void
set_interrupt_cause(E1000State *s, int index, uint32_t val)
{
- if (val)
+ if (val && (E1000_DEVID >= E1000_DEV_ID_82547EI_MOBILE)) {
+ /* Only for 8257x */
val |= E1000_ICR_INT_ASSERTED;
+ }
s->mac_reg[ICR] = val;
s->mac_reg[ICS] = val;
qemu_set_irq(s->dev.irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0);
return 2048;
}
+static void e1000_reset(void *opaque)
+{
+ E1000State *d = opaque;
+
+ qemu_del_timer(d->autoneg_timer);
+ memset(d->phy_reg, 0, sizeof d->phy_reg);
+ memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
+ memset(d->mac_reg, 0, sizeof d->mac_reg);
+ memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
+ d->rxbuf_min_shift = 1;
+ memset(&d->tx, 0, sizeof d->tx);
+
+ if (d->nic->nc.link_down) {
+ e1000_link_down(d);
+ }
+}
+
static void
set_ctrl(E1000State *s, int index, uint32_t val)
{
if (!(phy_regcap[addr] & PHY_W)) {
DBGOUT(MDIC, "MDIC write reg %x unhandled\n", addr);
val |= E1000_MDIC_ERROR;
- } else
+ } else {
+ if (addr < NPHYWRITEOPS && phyreg_writeops[addr]) {
+ phyreg_writeops[addr](s, index, data);
+ }
s->phy_reg[addr] = data;
+ }
}
s->mac_reg[MDIC] = val | E1000_MDIC_READY;
- set_ics(s, 0, E1000_ICR_MDAC);
+
+ if (val & E1000_MDIC_INT_EN) {
+ set_ics(s, 0, E1000_ICR_MDAC);
+ }
}
static uint32_t
return (s->mac_reg[RCTL] & E1000_RCTL_SECRC) ? 0 : 4;
}
+static void
+e1000_send_packet(E1000State *s, const uint8_t *buf, int size)
+{
+ if (s->phy_reg[PHY_CTRL] & MII_CR_LOOPBACK) {
+ s->nic->nc.info->receive(&s->nic->nc, buf, size);
+ } else {
+ qemu_send_packet(&s->nic->nc, buf, size);
+ }
+}
+
static void
xmit_seg(E1000State *s)
{
memmove(tp->vlan, tp->data, 4);
memmove(tp->data, tp->data + 4, 8);
memcpy(tp->data + 8, tp->vlan_header, 4);
- qemu_send_packet(&s->nic->nc, tp->vlan, tp->size + 4);
+ e1000_send_packet(s, tp->vlan, tp->size + 4);
} else
- qemu_send_packet(&s->nic->nc, tp->data, tp->size);
+ e1000_send_packet(s, tp->data, tp->size);
s->mac_reg[TPT]++;
s->mac_reg[GPTC]++;
n = s->mac_reg[TOTL];
uint32_t old_status = s->mac_reg[STATUS];
if (nc->link_down) {
- s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
- s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
+ e1000_link_down(s);
} else {
- s->mac_reg[STATUS] |= E1000_STATUS_LU;
- s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS;
+ e1000_link_up(s);
}
if (s->mac_reg[STATUS] != old_status)
[MTA ... MTA+127] = &mac_writereg,
[VFTA ... VFTA+127] = &mac_writereg,
};
+
enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) };
static void
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000,
};
-static const uint16_t phy_reg_init[] = {
- [PHY_CTRL] = 0x1140, [PHY_STATUS] = 0x796d, // link initially up
- [PHY_ID1] = 0x141, [PHY_ID2] = PHY_ID2_INIT,
- [PHY_1000T_CTRL] = 0x0e00, [M88E1000_PHY_SPEC_CTRL] = 0x360,
- [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60, [PHY_AUTONEG_ADV] = 0xde1,
- [PHY_LP_ABILITY] = 0x1e0, [PHY_1000T_STATUS] = 0x3c00,
- [M88E1000_PHY_SPEC_STATUS] = 0xac00,
-};
-
-static const uint32_t mac_reg_init[] = {
- [PBA] = 0x00100030,
- [LEDCTL] = 0x602,
- [CTRL] = E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 |
- E1000_CTRL_SPD_1000 | E1000_CTRL_SLU,
- [STATUS] = 0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE |
- E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK |
- E1000_STATUS_SPEED_1000 | E1000_STATUS_FD |
- E1000_STATUS_LU,
- [MANC] = E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN |
- E1000_MANC_ARP_EN | E1000_MANC_0298_EN |
- E1000_MANC_RMCP_EN,
-};
-
/* PCI interface */
static void
{
E1000State *d = DO_UPCAST(E1000State, dev, dev);
+ qemu_del_timer(d->autoneg_timer);
+ qemu_free_timer(d->autoneg_timer);
memory_region_destroy(&d->mmio);
memory_region_destroy(&d->io);
qemu_del_vlan_client(&d->nic->nc);
return 0;
}
-static void e1000_reset(void *opaque)
-{
- E1000State *d = opaque;
-
- memset(d->phy_reg, 0, sizeof d->phy_reg);
- memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
- memset(d->mac_reg, 0, sizeof d->mac_reg);
- memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
- d->rxbuf_min_shift = 1;
- memset(&d->tx, 0, sizeof d->tx);
-
- if (d->nic->nc.link_down) {
- d->mac_reg[STATUS] &= ~E1000_STATUS_LU;
- d->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
- }
-}
-
static NetClientInfo net_e1000_info = {
.type = NET_CLIENT_TYPE_NIC,
.size = sizeof(NICState),
add_boot_device_path(d->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0");
+ d->autoneg_timer = qemu_new_timer_ms(vm_clock, e1000_autoneg_timer, d);
+
return 0;
}
#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */
#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
+#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
+#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN 0x0800 /* Power down */
+#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
+
/* PHY Status Register */
#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
};
+#define POLYNOMIAL 0x04c11db6
+
static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s);
+/* From FreeBSD (locally modified). */
+static unsigned e100_compute_mcast_idx(const uint8_t *ep)
+{
+ uint32_t crc;
+ int carry, i, j;
+ uint8_t b;
+
+ crc = 0xffffffff;
+ for (i = 0; i < 6; i++) {
+ b = *ep++;
+ for (j = 0; j < 8; j++) {
+ carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
+ crc <<= 1;
+ b >>= 1;
+ if (carry) {
+ crc = ((crc ^ POLYNOMIAL) | carry);
+ }
+ }
+ }
+ return (crc & BITS(7, 2)) >> 2;
+}
+
/* Read a 16 bit control/status (CSR) register. */
static uint16_t e100_read_reg2(EEPRO100State *s, E100RegisterOffset addr)
{
uint8_t multicast_addr[6];
pci_dma_read(&s->dev, s->cb_address + 10 + i, multicast_addr, 6);
TRACE(OTHER, logout("multicast entry %s\n", nic_dump(multicast_addr, 6)));
- unsigned mcast_idx = compute_mcast_idx(multicast_addr);
+ unsigned mcast_idx = e100_compute_mcast_idx(multicast_addr);
assert(mcast_idx < 64);
s->mult[mcast_idx >> 3] |= (1 << (mcast_idx & 7));
}
if (s->configuration[21] & BIT(3)) {
/* Multicast all bit is set, receive all multicast frames. */
} else {
- unsigned mcast_idx = compute_mcast_idx(buf);
+ unsigned mcast_idx = e100_compute_mcast_idx(buf);
assert(mcast_idx < 64);
if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
/* Multicast frame is allowed in hash table. */
typedef struct FDCtrlISABus {
ISADevice busdev;
+ uint32_t iobase;
+ uint32_t irq;
+ uint32_t dma;
struct FDCtrl state;
int32_t bootindexA;
int32_t bootindexB;
{
FDCtrlISABus *isa = DO_UPCAST(FDCtrlISABus, busdev, dev);
FDCtrl *fdctrl = &isa->state;
- int iobase = 0x3f0;
- int isairq = 6;
- int dma_chann = 2;
int ret;
- isa_register_portio_list(dev, iobase, fdc_portio_list, fdctrl, "fdc");
+ isa_register_portio_list(dev, isa->iobase, fdc_portio_list, fdctrl, "fdc");
- isa_init_irq(&isa->busdev, &fdctrl->irq, isairq);
- fdctrl->dma_chann = dma_chann;
+ isa_init_irq(&isa->busdev, &fdctrl->irq, isa->irq);
+ fdctrl->dma_chann = isa->dma;
- qdev_set_legacy_instance_id(&dev->qdev, iobase, 2);
+ qdev_set_legacy_instance_id(&dev->qdev, isa->iobase, 2);
ret = fdctrl_init_common(fdctrl);
add_boot_device_path(isa->bootindexA, &dev->qdev, "/floppy@0");
};
static Property isa_fdc_properties[] = {
+ DEFINE_PROP_HEX32("iobase", FDCtrlISABus, iobase, 0x3f0),
+ DEFINE_PROP_UINT32("irq", FDCtrlISABus, irq, 6),
+ DEFINE_PROP_UINT32("dma", FDCtrlISABus, dma, 2),
DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].bs),
DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].bs),
DEFINE_PROP_INT32("bootindexA", FDCtrlISABus, bootindexA, -1),
/* some defines */
#define QEMU_HDA_ID_VENDOR 0x1af4
-#define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x10)
-#define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x20)
-
#define QEMU_HDA_PCM_FORMATS (AC_SUPPCM_BITS_16 | \
0x1fc /* 16 -> 96 kHz */)
#define QEMU_HDA_AMP_NONE (0)
#define QEMU_HDA_AMP_STEPS 0x4a
#ifdef CONFIG_MIXEMU
-#define QEMU_HDA_AMP_CAPS \
+# define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x12)
+# define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x22)
+# define QEMU_HDA_ID_MICRO ((QEMU_HDA_ID_VENDOR << 16) | 0x32)
+# define QEMU_HDA_AMP_CAPS \
(AC_AMPCAP_MUTE | \
(QEMU_HDA_AMP_STEPS << AC_AMPCAP_OFFSET_SHIFT) | \
(QEMU_HDA_AMP_STEPS << AC_AMPCAP_NUM_STEPS_SHIFT) | \
(3 << AC_AMPCAP_STEP_SIZE_SHIFT))
#else
-#define QEMU_HDA_AMP_CAPS QEMU_HDA_AMP_NONE
+# define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x11)
+# define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x21)
+# define QEMU_HDA_ID_MICRO ((QEMU_HDA_ID_VENDOR << 16) | 0x31)
+# define QEMU_HDA_AMP_CAPS QEMU_HDA_AMP_NONE
#endif
/* common: audio output widget */
},
};
+/* common: audio input widget */
+static const desc_param common_params_audio_adc[] = {
+ {
+ .id = AC_PAR_AUDIO_WIDGET_CAP,
+ .val = ((AC_WID_AUD_IN << AC_WCAP_TYPE_SHIFT) |
+ AC_WCAP_CONN_LIST |
+ AC_WCAP_FORMAT_OVRD |
+ AC_WCAP_AMP_OVRD |
+ AC_WCAP_IN_AMP |
+ AC_WCAP_STEREO),
+ },{
+ .id = AC_PAR_CONNLIST_LEN,
+ .val = 1,
+ },{
+ .id = AC_PAR_PCM,
+ .val = QEMU_HDA_PCM_FORMATS,
+ },{
+ .id = AC_PAR_STREAM,
+ .val = AC_SUPFMT_PCM,
+ },{
+ .id = AC_PAR_AMP_IN_CAP,
+ .val = QEMU_HDA_AMP_CAPS,
+ },{
+ .id = AC_PAR_AMP_OUT_CAP,
+ .val = QEMU_HDA_AMP_NONE,
+ },
+};
+
/* common: pin widget (line-out) */
static const desc_param common_params_audio_lineout[] = {
{
},
};
+/* common: pin widget (line-in) */
+static const desc_param common_params_audio_linein[] = {
+ {
+ .id = AC_PAR_AUDIO_WIDGET_CAP,
+ .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) |
+ AC_WCAP_STEREO),
+ },{
+ .id = AC_PAR_PIN_CAP,
+ .val = AC_PINCAP_IN,
+ },{
+ .id = AC_PAR_AMP_IN_CAP,
+ .val = QEMU_HDA_AMP_NONE,
+ },{
+ .id = AC_PAR_AMP_OUT_CAP,
+ .val = QEMU_HDA_AMP_NONE,
+ },
+};
+
/* output: root node */
static const desc_param output_params_root[] = {
{
},
};
-/* duplex: audio input widget */
-static const desc_param duplex_params_audio_adc[] = {
+/* duplex: audio function */
+static const desc_param duplex_params_audio_func[] = {
{
- .id = AC_PAR_AUDIO_WIDGET_CAP,
- .val = ((AC_WID_AUD_IN << AC_WCAP_TYPE_SHIFT) |
- AC_WCAP_CONN_LIST |
- AC_WCAP_FORMAT_OVRD |
- AC_WCAP_AMP_OVRD |
- AC_WCAP_IN_AMP |
- AC_WCAP_STEREO),
+ .id = AC_PAR_FUNCTION_TYPE,
+ .val = AC_GRP_AUDIO_FUNCTION,
},{
- .id = AC_PAR_CONNLIST_LEN,
- .val = 1,
+ .id = AC_PAR_SUBSYSTEM_ID,
+ .val = QEMU_HDA_ID_DUPLEX,
+ },{
+ .id = AC_PAR_NODE_COUNT,
+ .val = 0x00020004,
},{
.id = AC_PAR_PCM,
.val = QEMU_HDA_PCM_FORMATS,
.val = AC_SUPFMT_PCM,
},{
.id = AC_PAR_AMP_IN_CAP,
- .val = QEMU_HDA_AMP_CAPS,
+ .val = QEMU_HDA_AMP_NONE,
},{
.id = AC_PAR_AMP_OUT_CAP,
.val = QEMU_HDA_AMP_NONE,
+ },{
+ .id = AC_PAR_GPIO_CAP,
+ .val = 0,
+ },{
+ .id = AC_PAR_AUDIO_FG_CAP,
+ .val = 0x00000808,
+ },{
+ .id = AC_PAR_POWER_STATE,
+ .val = 0,
},
};
-/* duplex: pin widget (line-in) */
-static const desc_param duplex_params_audio_linein[] = {
+/* duplex: nodes */
+static const desc_node duplex_nodes[] = {
{
- .id = AC_PAR_AUDIO_WIDGET_CAP,
- .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) |
- AC_WCAP_STEREO),
+ .nid = AC_NODE_ROOT,
+ .name = "root",
+ .params = duplex_params_root,
+ .nparams = ARRAY_SIZE(duplex_params_root),
},{
- .id = AC_PAR_PIN_CAP,
- .val = AC_PINCAP_IN,
+ .nid = 1,
+ .name = "func",
+ .params = duplex_params_audio_func,
+ .nparams = ARRAY_SIZE(duplex_params_audio_func),
},{
- .id = AC_PAR_AMP_IN_CAP,
- .val = QEMU_HDA_AMP_NONE,
+ .nid = 2,
+ .name = "dac",
+ .params = common_params_audio_dac,
+ .nparams = ARRAY_SIZE(common_params_audio_dac),
+ .stindex = 0,
},{
- .id = AC_PAR_AMP_OUT_CAP,
- .val = QEMU_HDA_AMP_NONE,
+ .nid = 3,
+ .name = "out",
+ .params = common_params_audio_lineout,
+ .nparams = ARRAY_SIZE(common_params_audio_lineout),
+ .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
+ (AC_JACK_LINE_OUT << AC_DEFCFG_DEVICE_SHIFT) |
+ (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
+ (AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) |
+ 0x10),
+ .pinctl = AC_PINCTL_OUT_EN,
+ .conn = (uint32_t[]) { 2 },
+ },{
+ .nid = 4,
+ .name = "adc",
+ .params = common_params_audio_adc,
+ .nparams = ARRAY_SIZE(common_params_audio_adc),
+ .stindex = 1,
+ .conn = (uint32_t[]) { 5 },
+ },{
+ .nid = 5,
+ .name = "in",
+ .params = common_params_audio_linein,
+ .nparams = ARRAY_SIZE(common_params_audio_linein),
+ .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
+ (AC_JACK_LINE_IN << AC_DEFCFG_DEVICE_SHIFT) |
+ (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
+ (AC_JACK_COLOR_RED << AC_DEFCFG_COLOR_SHIFT) |
+ 0x20),
+ .pinctl = AC_PINCTL_IN_EN,
+ }
+};
+
+/* duplex: codec */
+static const desc_codec duplex = {
+ .name = "duplex",
+ .iid = QEMU_HDA_ID_DUPLEX,
+ .nodes = duplex_nodes,
+ .nnodes = ARRAY_SIZE(duplex_nodes),
+};
+
+/* micro: root node */
+static const desc_param micro_params_root[] = {
+ {
+ .id = AC_PAR_VENDOR_ID,
+ .val = QEMU_HDA_ID_MICRO,
+ },{
+ .id = AC_PAR_SUBSYSTEM_ID,
+ .val = QEMU_HDA_ID_MICRO,
+ },{
+ .id = AC_PAR_REV_ID,
+ .val = 0x00100101,
+ },{
+ .id = AC_PAR_NODE_COUNT,
+ .val = 0x00010001,
},
};
-/* duplex: audio function */
-static const desc_param duplex_params_audio_func[] = {
+/* micro: audio function */
+static const desc_param micro_params_audio_func[] = {
{
.id = AC_PAR_FUNCTION_TYPE,
.val = AC_GRP_AUDIO_FUNCTION,
},{
.id = AC_PAR_SUBSYSTEM_ID,
- .val = QEMU_HDA_ID_DUPLEX,
+ .val = QEMU_HDA_ID_MICRO,
},{
.id = AC_PAR_NODE_COUNT,
.val = 0x00020004,
},
};
-/* duplex: nodes */
-static const desc_node duplex_nodes[] = {
+/* micro: nodes */
+static const desc_node micro_nodes[] = {
{
.nid = AC_NODE_ROOT,
.name = "root",
- .params = duplex_params_root,
- .nparams = ARRAY_SIZE(duplex_params_root),
+ .params = micro_params_root,
+ .nparams = ARRAY_SIZE(micro_params_root),
},{
.nid = 1,
.name = "func",
- .params = duplex_params_audio_func,
- .nparams = ARRAY_SIZE(duplex_params_audio_func),
+ .params = micro_params_audio_func,
+ .nparams = ARRAY_SIZE(micro_params_audio_func),
},{
.nid = 2,
.name = "dac",
.params = common_params_audio_lineout,
.nparams = ARRAY_SIZE(common_params_audio_lineout),
.config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
- (AC_JACK_LINE_OUT << AC_DEFCFG_DEVICE_SHIFT) |
+ (AC_JACK_SPEAKER << AC_DEFCFG_DEVICE_SHIFT) |
(AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
(AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) |
0x10),
},{
.nid = 4,
.name = "adc",
- .params = duplex_params_audio_adc,
- .nparams = ARRAY_SIZE(duplex_params_audio_adc),
+ .params = common_params_audio_adc,
+ .nparams = ARRAY_SIZE(common_params_audio_adc),
.stindex = 1,
.conn = (uint32_t[]) { 5 },
},{
.nid = 5,
.name = "in",
- .params = duplex_params_audio_linein,
- .nparams = ARRAY_SIZE(duplex_params_audio_linein),
+ .params = common_params_audio_linein,
+ .nparams = ARRAY_SIZE(common_params_audio_linein),
.config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
- (AC_JACK_LINE_IN << AC_DEFCFG_DEVICE_SHIFT) |
+ (AC_JACK_MIC_IN << AC_DEFCFG_DEVICE_SHIFT) |
(AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
(AC_JACK_COLOR_RED << AC_DEFCFG_COLOR_SHIFT) |
0x20),
}
};
-/* duplex: codec */
-static const desc_codec duplex = {
- .name = "duplex",
- .iid = QEMU_HDA_ID_DUPLEX,
- .nodes = duplex_nodes,
- .nnodes = ARRAY_SIZE(duplex_nodes),
+/* micro: codec */
+static const desc_codec micro = {
+ .name = "micro",
+ .iid = QEMU_HDA_ID_MICRO,
+ .nodes = micro_nodes,
+ .nnodes = ARRAY_SIZE(micro_nodes),
};
/* -------------------------------------------------------------------------- */
return hda_audio_init(hda, &duplex);
}
+static int hda_audio_init_micro(HDACodecDevice *hda)
+{
+ return hda_audio_init(hda, µ);
+}
+
static void hda_audio_output_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
k->exit = hda_audio_exit;
k->command = hda_audio_command;
k->stream = hda_audio_stream;
- dc->desc = "HDA Audio Codec, output-only";
+ dc->desc = "HDA Audio Codec, output-only (line-out)";
dc->vmsd = &vmstate_hda_audio;
dc->props = hda_audio_properties;
}
k->exit = hda_audio_exit;
k->command = hda_audio_command;
k->stream = hda_audio_stream;
- dc->desc = "HDA Audio Codec, duplex";
+ dc->desc = "HDA Audio Codec, duplex (line-out, line-in)";
dc->vmsd = &vmstate_hda_audio;
dc->props = hda_audio_properties;
}
.class_init = hda_audio_duplex_class_init,
};
+static void hda_audio_micro_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
+
+ k->init = hda_audio_init_micro;
+ k->exit = hda_audio_exit;
+ k->command = hda_audio_command;
+ k->stream = hda_audio_stream;
+ dc->desc = "HDA Audio Codec, duplex (speaker, microphone)";
+ dc->vmsd = &vmstate_hda_audio;
+ dc->props = hda_audio_properties;
+}
+
+static TypeInfo hda_audio_micro_info = {
+ .name = "hda-micro",
+ .parent = TYPE_HDA_CODEC_DEVICE,
+ .instance_size = sizeof(HDAAudioState),
+ .class_init = hda_audio_micro_class_init,
+};
+
static void hda_audio_register_types(void)
{
type_register_static(&hda_audio_output_info);
type_register_static(&hda_audio_duplex_info);
+ type_register_static(&hda_audio_micro_info);
}
type_init(hda_audio_register_types)
#define NIRQ_GIC 160
/* Board init. */
-static void highbank_cpu_reset(void *opaque)
-{
- CPUARMState *env = opaque;
-
- env->cp15.c15_config_base_address = GIC_BASE_ADDR;
-}
static void hb_write_secondary(CPUARMState *env, const struct arm_boot_info *info)
{
}
for (n = 0; n < smp_cpus; n++) {
- env = cpu_init(cpu_model);
- if (!env) {
+ ARMCPU *cpu;
+ cpu = cpu_arm_init(cpu_model);
+ if (cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
+ env = &cpu->env;
+ /* This will become a QOM property eventually */
+ cpu->reset_cbar = GIC_BASE_ADDR;
irqp = arm_pic_init_cpu(env);
cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
- qemu_register_reset(highbank_cpu_reset, env);
}
sysmem = get_system_memory();
typedef struct I82374State {
uint8_t commands[8];
+ qemu_irq out;
} I82374State;
static const VMStateDescription vmstate_i82374 = {
static void i82374_init(I82374State *s)
{
- DMA_init(1, NULL);
+ DMA_init(1, &s->out);
memset(s->commands, 0, sizeof(s->commands));
}
i82374_init(s);
+ qdev_init_gpio_out(&dev->qdev, &s->out, 1);
+
return 0;
}
{
ISABus *isabus = DO_UPCAST(ISABus, qbus, qdev_get_child_bus(dev, "isa.0"));
ISADevice *pit;
+ ISADevice *isa;
qemu_irq *out0_irq;
/* This device has:
pcspk_init(isabus, pit);
/* 2 82C37 (dma) */
- DMA_init(1, &s->out[1]);
- isa_create_simple(isabus, "i82374");
+ isa = isa_create_simple(isabus, "i82374");
+ qdev_connect_gpio_out(&isa->qdev, 0, s->out[1]);
/* timer */
isa_create_simple(isabus, "mc146818rtc");
const MemoryRegionPortio *portio,
void *opaque, const char *name);
+static inline ISABus *isa_bus_from_device(ISADevice *d)
+{
+ return DO_UPCAST(ISABus, qbus, d->qdev.parent_bus);
+}
+
extern target_phys_addr_t isa_mem_base;
void isa_mmio_setup(MemoryRegion *mr, target_phys_addr_t size);
sysfw_dev = (PcSysFwDevice*) qdev_create(NULL, "pc-sysfw");
+ qdev_init_nofail(DEVICE(sysfw_dev));
+
if (sysfw_dev->rom_only) {
old_pc_system_rom_init(rom_memory);
return;
DEFINE_PROP_END_OF_LIST(),
};
+static int pcsysfw_init(DeviceState *dev)
+{
+ return 0;
+}
+
static void pcsysfw_class_init (ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS (klass);
dc->desc = "PC System Firmware";
+ dc->init = pcsysfw_init;
dc->props = pcsysfw_properties;
}
#include "loader.h"
#include "mc146818rtc.h"
#include "blockdev.h"
+#include "arch_init.h"
#include "exec-memory.h"
//#define HARD_DEBUG_PPC_IO
/* ISA IO ports bridge */
#define PPC_IO_BASE 0x80000000
-/* PCI intack register */
-/* Read-only register (?) */
-static void PPC_intack_write (void *opaque, target_phys_addr_t addr,
- uint64_t value, unsigned size)
-{
-#if 0
- printf("%s: 0x" TARGET_FMT_plx " => 0x%08" PRIx64 "\n", __func__, addr,
- value);
-#endif
-}
-
-static uint64_t PPC_intack_read(void *opaque, target_phys_addr_t addr,
- unsigned size)
-{
- uint32_t retval = 0;
-
- if ((addr & 0xf) == 0)
- retval = pic_read_irq(isa_pic);
-#if 0
- printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr,
- retval);
-#endif
-
- return retval;
-}
-
-static const MemoryRegionOps PPC_intack_ops = {
- .read = PPC_intack_read,
- .write = PPC_intack_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
/* PowerPC control and status registers */
#if 0 // Not used
static struct {
nvram_t nvram;
M48t59State *m48t59;
MemoryRegion *PPC_io_memory = g_new(MemoryRegion, 1);
- MemoryRegion *intack = g_new(MemoryRegion, 1);
#if 0
MemoryRegion *xcsr = g_new(MemoryRegion, 1);
#endif
register_ioport_write(0x0092, 0x01, 1, &PREP_io_800_writeb, sysctrl);
register_ioport_read(0x0800, 0x52, 1, &PREP_io_800_readb, sysctrl);
register_ioport_write(0x0800, 0x52, 1, &PREP_io_800_writeb, sysctrl);
- /* PCI intack location */
- memory_region_init_io(intack, &PPC_intack_ops, NULL, "ppc-intack", 4);
- memory_region_add_subregion(sysmem, 0xBFFFFFF0, intack);
/* PowerPC control and status register group */
#if 0
memory_region_init_io(xcsr, &PPC_XCSR_ops, NULL, "ppc-xcsr", 0x1000);
/* Special port to get debug messages from Open-Firmware */
register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
+
+ /* Initialize audio subsystem */
+ audio_init(isa_bus, pci_bus);
}
static QEMUMachine prep_machine = {
#include "hw.h"
#include "pci.h"
#include "pci_host.h"
+#include "pc.h"
#include "exec-memory.h"
typedef struct PRePPCIState {
PCIHostState host_state;
+ MemoryRegion intack;
qemu_irq irq[4];
} PREPPCIState;
.endianness = DEVICE_LITTLE_ENDIAN,
};
+static uint64_t ppc_intack_read(void *opaque, target_phys_addr_t addr,
+ unsigned int size)
+{
+ return pic_read_irq(isa_pic);
+}
+
+static const MemoryRegionOps PPC_intack_ops = {
+ .read = ppc_intack_read,
+ .valid = {
+ .max_access_size = 1,
+ },
+};
+
static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
{
return (irq_num + (pci_dev->devfn >> 3)) & 1;
memory_region_init_io(&h->mmcfg, &PPC_PCIIO_ops, s, "pciio", 0x00400000);
memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg);
+ memory_region_init_io(&s->intack, &PPC_intack_ops, s, "pci-intack", 1);
+ memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->intack);
pci_create_simple(bus, 0, "raven");
return 0;
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep)
{
assert(!usb_packet_is_inflight(p));
+ assert(p->iov.iov != NULL);
p->pid = pid;
p->ep = ep;
p->result = 0;
+#include <ctype.h>
+
#include "hw/usb.h"
#include "hw/usb/desc.h"
#include "trace.h"
s->str = g_strdup(str);
}
+/*
+ * This function creates a serial number for a usb device.
+ * The serial number should:
+ * (a) Be unique within the virtual machine.
+ * (b) Be constant, so you don't get a new one each
+ * time the guest is started.
+ * So we are using the physical location to generate a serial number
+ * from it. It has three pieces: First a fixed, device-specific
+ * prefix. Second the device path of the host controller (which is
+ * the pci address in most cases). Third the physical port path.
+ * Results in serial numbers like this: "314159-0000:00:1d.7-3".
+ */
+void usb_desc_create_serial(USBDevice *dev)
+{
+ DeviceState *hcd = dev->qdev.parent_bus->parent;
+ const USBDesc *desc = usb_device_get_usb_desc(dev);
+ int index = desc->id.iSerialNumber;
+ char serial[64];
+ int dst;
+
+ assert(index != 0 && desc->str[index] != NULL);
+ dst = snprintf(serial, sizeof(serial), "%s", desc->str[index]);
+ if (hcd && hcd->parent_bus && hcd->parent_bus->info->get_dev_path) {
+ char *path = hcd->parent_bus->info->get_dev_path(hcd);
+ dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", path);
+ }
+ dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", dev->port->path);
+ usb_desc_set_string(dev, index, serial);
+}
+
const char *usb_desc_get_string(USBDevice *dev, uint8_t index)
{
USBDescString *s;
void usb_desc_init(USBDevice *dev);
void usb_desc_attach(USBDevice *dev);
void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str);
+void usb_desc_create_serial(USBDevice *dev);
const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len);
{
USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+ usb_desc_create_serial(dev);
usb_desc_init(dev);
s->dev.opaque = s;
AUD_register_card("usb-audio", &s->card);
static int usb_bt_initfn(USBDevice *dev)
{
+ usb_desc_create_serial(dev);
usb_desc_init(dev);
return 0;
}
USBHubPort *port;
int i;
+ usb_desc_create_serial(dev);
usb_desc_init(dev);
s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
for (i = 0; i < NUM_PORTS; i++) {
{
USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
+ usb_desc_create_serial(dev);
usb_desc_init(dev);
s->rndis_state = RNDIS_UNINITIALIZED;
{
USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
+ usb_desc_create_serial(dev);
usb_desc_init(dev);
if (!s->cs) {
{
USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+ usb_desc_create_serial(dev);
usb_desc_init(dev);
qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP);
if (req == s->req) {
scsi_req_unref(s->req);
s->req = NULL;
- s->packet = NULL;
s->scsi_len = 0;
}
}
{
MSDState *s = DO_UPCAST(MSDState, dev, dev);
+ assert(s->packet == p);
+ s->packet = NULL;
+
if (s->req) {
scsi_req_cancel(s->req);
}
}
if (s->serial) {
usb_desc_set_string(dev, STR_SERIALNUMBER, s->serial);
+ } else {
+ usb_desc_create_serial(dev);
}
usb_desc_init(dev);
static int usb_wacom_initfn(USBDevice *dev)
{
USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev);
+ usb_desc_create_serial(dev);
usb_desc_init(dev);
s->changed = 1;
return 0;
#define NB_MAXINTRATE 8 // Max rate at which controller issues ints
#define NB_PORTS 6 // Number of downstream ports
#define BUFF_SIZE 5*4096 // Max bytes to transfer per transaction
-#define MAX_ITERATIONS 20 // Max number of QH before we break the loop
#define MAX_QH 100 // Max allowable queue heads in a chain
/* Internal periodic / asynchronous schedule state machine states
q = g_malloc0(sizeof(*q));
q->ehci = ehci;
+ usb_packet_init(&q->packet);
QTAILQ_INSERT_HEAD(head, q, next);
trace_usb_ehci_queue_action(q, "alloc");
return q;
val &= USBINTR_MASK;
break;
+ case FRINDEX:
+ val &= 0x00003ff8; /* frindex is 14bits and always a multiple of 8 */
+ break;
+
case CONFIGFLAG:
val &= 0x1;
if (val) {
{
EHCIQueue *q = NULL;
int again;
- int iter = 0;
do {
- if (ehci_get_state(ehci, async) == EST_FETCHQH) {
- iter++;
- /* if we are roaming a lot of QH without executing a qTD
- * something is wrong with the linked list. TO-DO: why is
- * this hack needed?
- */
- assert(iter < MAX_ITERATIONS);
-#if 0
- if (iter > MAX_ITERATIONS) {
- DPRINTF("\n*** advance_state: bailing on MAX ITERATIONS***\n");
- ehci_set_state(ehci, async, EST_ACTIVE);
- break;
- }
-#endif
- }
switch(ehci_get_state(ehci, async)) {
case EST_WAITLISTHEAD:
again = ehci_state_waitlisthead(ehci, async);
break;
case EST_EXECUTE:
- iter = 0;
again = ehci_state_execute(q, async);
break;
}
uhci_async_cancel_all(s);
+ uhci_update_irq(s);
}
static void uhci_pre_save(void *opaque)
#include "qemu-timer.h"
#include "hw/usb.h"
#include "hw/pci.h"
-#include "hw/qdev-addr.h"
#include "hw/msi.h"
//#define DEBUG_XHCI
uint64_t parameter;
uint32_t status;
uint32_t control;
- target_phys_addr_t addr;
+ dma_addr_t addr;
bool ccs;
} XHCITRB;
} EPType;
typedef struct XHCIRing {
- target_phys_addr_t base;
- target_phys_addr_t dequeue;
+ dma_addr_t base;
+ dma_addr_t dequeue;
bool ccs;
} XHCIRing;
unsigned int next_bg;
XHCITransfer bg_transfers[BG_XFERS];
EPType type;
- target_phys_addr_t pctx;
+ dma_addr_t pctx;
unsigned int max_psize;
bool has_bg;
uint32_t state;
typedef struct XHCISlot {
bool enabled;
- target_phys_addr_t ctx;
+ dma_addr_t ctx;
unsigned int port;
unsigned int devaddr;
XHCIEPContext * eps[31];
uint32_t erdp_low;
uint32_t erdp_high;
- target_phys_addr_t er_start;
+ dma_addr_t er_start;
uint32_t er_size;
bool er_pcs;
unsigned int er_ep_idx;
static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
unsigned int epid);
-static inline target_phys_addr_t xhci_addr64(uint32_t low, uint32_t high)
+static inline dma_addr_t xhci_addr64(uint32_t low, uint32_t high)
{
-#if TARGET_PHYS_ADDR_BITS > 32
- return low | ((target_phys_addr_t)high << 32);
-#else
- return low;
-#endif
+ if (sizeof(dma_addr_t) == 4) {
+ return low;
+ } else {
+ return low | (((dma_addr_t)high << 16) << 16);
+ }
}
-static inline target_phys_addr_t xhci_mask64(uint64_t addr)
+static inline dma_addr_t xhci_mask64(uint64_t addr)
{
-#if TARGET_PHYS_ADDR_BITS > 32
- return addr;
-#else
- return addr & 0xffffffff;
-#endif
+ if (sizeof(dma_addr_t) == 4) {
+ return addr & 0xffffffff;
+ } else {
+ return addr;
+ }
}
static void xhci_irq_update(XHCIState *xhci)
int level = 0;
if (xhci->iman & IMAN_IP && xhci->iman & IMAN_IE &&
- xhci->usbcmd && USBCMD_INTE) {
+ xhci->usbcmd & USBCMD_INTE) {
level = 1;
}
static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
{
XHCITRB ev_trb;
- target_phys_addr_t addr;
+ dma_addr_t addr;
ev_trb.parameter = cpu_to_le64(event->ptr);
ev_trb.status = cpu_to_le32(event->length | (event->ccode << 24));
trb_name(&ev_trb));
addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx;
- cpu_physical_memory_write(addr, (uint8_t *) &ev_trb, TRB_SIZE);
+ pci_dma_write(&xhci->pci_dev, addr, &ev_trb, TRB_SIZE);
xhci->er_ep_idx++;
if (xhci->er_ep_idx >= xhci->er_size) {
static void xhci_events_update(XHCIState *xhci)
{
- target_phys_addr_t erdp;
+ dma_addr_t erdp;
unsigned int dp_idx;
bool do_irq = 0;
erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high);
if (erdp < xhci->er_start ||
erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) {
- fprintf(stderr, "xhci: ERDP out of bounds: "TARGET_FMT_plx"\n", erdp);
- fprintf(stderr, "xhci: ER at "TARGET_FMT_plx" len %d\n",
+ fprintf(stderr, "xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp);
+ fprintf(stderr, "xhci: ER at "DMA_ADDR_FMT" len %d\n",
xhci->er_start, xhci->er_size);
xhci_die(xhci);
return;
static void xhci_event(XHCIState *xhci, XHCIEvent *event)
{
- target_phys_addr_t erdp;
+ dma_addr_t erdp;
unsigned int dp_idx;
if (xhci->er_full) {
erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high);
if (erdp < xhci->er_start ||
erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) {
- fprintf(stderr, "xhci: ERDP out of bounds: "TARGET_FMT_plx"\n", erdp);
- fprintf(stderr, "xhci: ER at "TARGET_FMT_plx" len %d\n",
+ fprintf(stderr, "xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp);
+ fprintf(stderr, "xhci: ER at "DMA_ADDR_FMT" len %d\n",
xhci->er_start, xhci->er_size);
xhci_die(xhci);
return;
}
static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring,
- target_phys_addr_t base)
+ dma_addr_t base)
{
ring->base = base;
ring->dequeue = base;
}
static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
- target_phys_addr_t *addr)
+ dma_addr_t *addr)
{
while (1) {
TRBType type;
- cpu_physical_memory_read(ring->dequeue, (uint8_t *) trb, TRB_SIZE);
+ pci_dma_read(&xhci->pci_dev, ring->dequeue, trb, TRB_SIZE);
trb->addr = ring->dequeue;
trb->ccs = ring->ccs;
le64_to_cpus(&trb->parameter);
le32_to_cpus(&trb->status);
le32_to_cpus(&trb->control);
- DPRINTF("xhci: TRB fetched [" TARGET_FMT_plx "]: "
+ DPRINTF("xhci: TRB fetched [" DMA_ADDR_FMT "]: "
"%016" PRIx64 " %08x %08x %s\n",
ring->dequeue, trb->parameter, trb->status, trb->control,
trb_name(trb));
{
XHCITRB trb;
int length = 0;
- target_phys_addr_t dequeue = ring->dequeue;
+ dma_addr_t dequeue = ring->dequeue;
bool ccs = ring->ccs;
/* hack to bundle together the two/three TDs that make a setup transfer */
bool control_td_set = 0;
while (1) {
TRBType type;
- cpu_physical_memory_read(dequeue, (uint8_t *) &trb, TRB_SIZE);
+ pci_dma_read(&xhci->pci_dev, dequeue, &trb, TRB_SIZE);
le64_to_cpus(&trb.parameter);
le32_to_cpus(&trb.status);
le32_to_cpus(&trb.control);
- DPRINTF("xhci: TRB peeked [" TARGET_FMT_plx "]: "
+ DPRINTF("xhci: TRB peeked [" DMA_ADDR_FMT "]: "
"%016" PRIx64 " %08x %08x\n",
dequeue, trb.parameter, trb.status, trb.control);
xhci_die(xhci);
return;
}
- target_phys_addr_t erstba = xhci_addr64(xhci->erstba_low, xhci->erstba_high);
- cpu_physical_memory_read(erstba, (uint8_t *) &seg, sizeof(seg));
+ dma_addr_t erstba = xhci_addr64(xhci->erstba_low, xhci->erstba_high);
+ pci_dma_read(&xhci->pci_dev, erstba, &seg, sizeof(seg));
le32_to_cpus(&seg.addr_low);
le32_to_cpus(&seg.addr_high);
le32_to_cpus(&seg.size);
xhci->er_pcs = 1;
xhci->er_full = 0;
- DPRINTF("xhci: event ring:" TARGET_FMT_plx " [%d]\n",
+ DPRINTF("xhci: event ring:" DMA_ADDR_FMT " [%d]\n",
xhci->er_start, xhci->er_size);
}
return;
}
- cpu_physical_memory_read(epctx->pctx, (uint8_t *) ctx, sizeof(ctx));
+ pci_dma_read(&xhci->pci_dev, epctx->pctx, ctx, sizeof(ctx));
ctx[0] &= ~EP_STATE_MASK;
ctx[0] |= state;
ctx[2] = epctx->ring.dequeue | epctx->ring.ccs;
ctx[3] = (epctx->ring.dequeue >> 16) >> 16;
- DPRINTF("xhci: set epctx: " TARGET_FMT_plx " state=%d dequeue=%08x%08x\n",
+ DPRINTF("xhci: set epctx: " DMA_ADDR_FMT " state=%d dequeue=%08x%08x\n",
epctx->pctx, state, ctx[3], ctx[2]);
- cpu_physical_memory_write(epctx->pctx, (uint8_t *) ctx, sizeof(ctx));
+ pci_dma_write(&xhci->pci_dev, epctx->pctx, ctx, sizeof(ctx));
epctx->state = state;
}
static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
- unsigned int epid, target_phys_addr_t pctx,
+ unsigned int epid, dma_addr_t pctx,
uint32_t *ctx)
{
XHCISlot *slot;
XHCIEPContext *epctx;
- target_phys_addr_t dequeue;
+ dma_addr_t dequeue;
int i;
assert(slotid >= 1 && slotid <= MAXSLOTS);
{
XHCISlot *slot;
XHCIEPContext *epctx;
- target_phys_addr_t dequeue;
+ dma_addr_t dequeue;
assert(slotid >= 1 && slotid <= MAXSLOTS);
for (i = 0; i < xfer->trb_count; i++) {
XHCITRB *trb = &xfer->trbs[i];
- target_phys_addr_t addr;
+ dma_addr_t addr;
unsigned int chunk = 0;
switch (TRB_TYPE(*trb)) {
memcpy(data, &idata, chunk);
} else {
DPRINTF("xhci_xfer_data: r/w(%d) %d bytes at "
- TARGET_FMT_plx "\n", in_xfer, chunk, addr);
+ DMA_ADDR_FMT "\n", in_xfer, chunk, addr);
if (in_xfer) {
- cpu_physical_memory_write(addr, data, chunk);
+ pci_dma_write(&xhci->pci_dev, addr, data, chunk);
} else {
- cpu_physical_memory_read(addr, data, chunk);
+ pci_dma_read(&xhci->pci_dev, addr, data, chunk);
}
#ifdef DEBUG_DATA
unsigned int count = chunk;
epctx->ring.ccs = xfer->trbs[0].ccs;
xhci_set_ep_state(xhci, epctx, EP_HALTED);
DPRINTF("xhci: stalled slot %d ep %d\n", xfer->slotid, xfer->epid);
- DPRINTF("xhci: will continue at "TARGET_FMT_plx"\n", epctx->ring.dequeue);
+ DPRINTF("xhci: will continue at "DMA_ADDR_FMT"\n", epctx->ring.dequeue);
}
static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer,
{
XHCISlot *slot;
USBDevice *dev;
- target_phys_addr_t ictx, octx, dcbaap;
+ dma_addr_t ictx, octx, dcbaap;
uint64_t poctx;
uint32_t ictl_ctx[2];
uint32_t slot_ctx[4];
DPRINTF("xhci_address_slot(%d)\n", slotid);
dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);
- cpu_physical_memory_read(dcbaap + 8*slotid,
- (uint8_t *) &poctx, sizeof(poctx));
+ pci_dma_read(&xhci->pci_dev, dcbaap + 8*slotid, &poctx, sizeof(poctx));
ictx = xhci_mask64(pictx);
octx = xhci_mask64(le64_to_cpu(poctx));
- DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
- DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+ DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx);
+ DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx);
- cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx));
if (ictl_ctx[0] != 0x0 || ictl_ctx[1] != 0x3) {
fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
return CC_TRB_ERROR;
}
- cpu_physical_memory_read(ictx+32, (uint8_t *) slot_ctx, sizeof(slot_ctx));
- cpu_physical_memory_read(ictx+64, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx+32, slot_ctx, sizeof(slot_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx+64, ep0_ctx, sizeof(ep0_ctx));
DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n",
slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n",
ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
- cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
- cpu_physical_memory_write(octx+32, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+ pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
+ pci_dma_write(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx));
return res;
}
static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
uint64_t pictx, bool dc)
{
- target_phys_addr_t ictx, octx;
+ dma_addr_t ictx, octx;
uint32_t ictl_ctx[2];
uint32_t slot_ctx[4];
uint32_t islot_ctx[4];
ictx = xhci_mask64(pictx);
octx = xhci->slots[slotid-1].ctx;
- DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
- DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+ DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx);
+ DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx);
if (dc) {
for (i = 2; i <= 31; i++) {
}
}
- cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
slot_ctx[3] |= SLOT_ADDRESSED << SLOT_STATE_SHIFT;
DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
- cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
return CC_SUCCESS;
}
- cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx));
if ((ictl_ctx[0] & 0x3) != 0x0 || (ictl_ctx[1] & 0x3) != 0x1) {
fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
return CC_TRB_ERROR;
}
- cpu_physical_memory_read(ictx+32, (uint8_t *) islot_ctx, sizeof(islot_ctx));
- cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx+32, islot_ctx, sizeof(islot_ctx));
+ pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
if (SLOT_STATE(slot_ctx[3]) < SLOT_ADDRESSED) {
fprintf(stderr, "xhci: invalid slot state %08x\n", slot_ctx[3]);
xhci_disable_ep(xhci, slotid, i);
}
if (ictl_ctx[1] & (1<<i)) {
- cpu_physical_memory_read(ictx+32+(32*i),
- (uint8_t *) ep_ctx, sizeof(ep_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx+32+(32*i), ep_ctx,
+ sizeof(ep_ctx));
DPRINTF("xhci: input ep%d.%d context: %08x %08x %08x %08x %08x\n",
i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2],
ep_ctx[3], ep_ctx[4]);
DPRINTF("xhci: output ep%d.%d context: %08x %08x %08x %08x %08x\n",
i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2],
ep_ctx[3], ep_ctx[4]);
- cpu_physical_memory_write(octx+(32*i),
- (uint8_t *) ep_ctx, sizeof(ep_ctx));
+ pci_dma_write(&xhci->pci_dev, octx+(32*i), ep_ctx, sizeof(ep_ctx));
}
}
DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
- cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
return CC_SUCCESS;
}
static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
uint64_t pictx)
{
- target_phys_addr_t ictx, octx;
+ dma_addr_t ictx, octx;
uint32_t ictl_ctx[2];
uint32_t iep0_ctx[5];
uint32_t ep0_ctx[5];
ictx = xhci_mask64(pictx);
octx = xhci->slots[slotid-1].ctx;
- DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx);
- DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+ DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx);
+ DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx);
- cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx));
if (ictl_ctx[0] != 0x0 || ictl_ctx[1] & ~0x3) {
fprintf(stderr, "xhci: invalid input context control %08x %08x\n",
}
if (ictl_ctx[1] & 0x1) {
- cpu_physical_memory_read(ictx+32,
- (uint8_t *) islot_ctx, sizeof(islot_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx+32, islot_ctx, sizeof(islot_ctx));
DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n",
islot_ctx[0], islot_ctx[1], islot_ctx[2], islot_ctx[3]);
- cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
slot_ctx[1] &= ~0xFFFF; /* max exit latency */
slot_ctx[1] |= islot_ctx[1] & 0xFFFF;
DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
- cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
}
if (ictl_ctx[1] & 0x2) {
- cpu_physical_memory_read(ictx+64,
- (uint8_t *) iep0_ctx, sizeof(iep0_ctx));
+ pci_dma_read(&xhci->pci_dev, ictx+64, iep0_ctx, sizeof(iep0_ctx));
DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n",
iep0_ctx[0], iep0_ctx[1], iep0_ctx[2],
iep0_ctx[3], iep0_ctx[4]);
- cpu_physical_memory_read(octx+32, (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+ pci_dma_read(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx));
ep0_ctx[1] &= ~0xFFFF0000; /* max packet size*/
ep0_ctx[1] |= iep0_ctx[1] & 0xFFFF0000;
DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n",
ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
- cpu_physical_memory_write(octx+32,
- (uint8_t *) ep0_ctx, sizeof(ep0_ctx));
+ pci_dma_write(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx));
}
return CC_SUCCESS;
static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid)
{
uint32_t slot_ctx[4];
- target_phys_addr_t octx;
+ dma_addr_t octx;
int i;
assert(slotid >= 1 && slotid <= MAXSLOTS);
octx = xhci->slots[slotid-1].ctx;
- DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx);
+ DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx);
for (i = 2; i <= 31; i++) {
if (xhci->slots[slotid-1].eps[i-1]) {
}
}
- cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
slot_ctx[3] |= SLOT_DEFAULT << SLOT_STATE_SHIFT;
DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
- cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx));
+ pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx));
return CC_SUCCESS;
}
static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx)
{
- target_phys_addr_t ctx;
+ dma_addr_t ctx;
uint8_t bw_ctx[MAXPORTS+1];
DPRINTF("xhci_get_port_bandwidth()\n");
ctx = xhci_mask64(pctx);
- DPRINTF("xhci: bandwidth context at "TARGET_FMT_plx"\n", ctx);
+ DPRINTF("xhci: bandwidth context at "DMA_ADDR_FMT"\n", ctx);
/* TODO: actually implement real values here */
bw_ctx[0] = 0;
memset(&bw_ctx[1], 80, MAXPORTS); /* 80% */
- cpu_physical_memory_write(ctx, bw_ctx, sizeof(bw_ctx));
+ pci_dma_write(&xhci->pci_dev, ctx, bw_ctx, sizeof(bw_ctx));
return CC_SUCCESS;
}
return ~val;
}
-static void xhci_via_challenge(uint64_t addr)
+static void xhci_via_challenge(XHCIState *xhci, uint64_t addr)
{
uint32_t buf[8];
uint32_t obuf[8];
- target_phys_addr_t paddr = xhci_mask64(addr);
+ dma_addr_t paddr = xhci_mask64(addr);
- cpu_physical_memory_read(paddr, (uint8_t *) &buf, 32);
+ pci_dma_read(&xhci->pci_dev, paddr, &buf, 32);
memcpy(obuf, buf, sizeof(obuf));
obuf[7] = obuf[2] ^ obuf[3] ^ 0x65866593;
}
- cpu_physical_memory_write(paddr, (uint8_t *) &obuf, 32);
+ pci_dma_write(&xhci->pci_dev, paddr, &obuf, 32);
}
static void xhci_process_commands(XHCIState *xhci)
XHCITRB trb;
TRBType type;
XHCIEvent event = {ER_COMMAND_COMPLETE, CC_SUCCESS};
- target_phys_addr_t addr;
+ dma_addr_t addr;
unsigned int i, slotid = 0;
DPRINTF("xhci_process_commands()\n");
event.ccode = xhci_get_port_bandwidth(xhci, trb.parameter);
break;
case CR_VENDOR_VIA_CHALLENGE_RESPONSE:
- xhci_via_challenge(trb.parameter);
+ xhci_via_challenge(xhci, trb.parameter);
break;
case CR_VENDOR_NEC_FIRMWARE_REVISION:
event.type = 48; /* NEC reply */
xhci_event(xhci, &event);
DPRINTF("xhci: command ring stopped (CRCR=%08x)\n", xhci->crcr_low);
} else {
- target_phys_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val);
+ dma_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val);
xhci_ring_init(xhci, &xhci->cmd_ring, base);
}
xhci->crcr_low &= ~(CRCR_CA | CRCR_CS);
}
v = 0;
- prem = p->iov.iov[v].iov_len;
- pbuf = p->iov.iov[v].iov_base;
+ prem = 0;
+ pbuf = NULL;
rem = p->iov.size;
- while (rem) {
- if (prem == 0) {
- v++;
+ do {
+ if (prem == 0 && rem > 0) {
assert(v < p->iov.niov);
prem = p->iov.iov[v].iov_len;
pbuf = p->iov.iov[v].iov_base;
assert(prem <= rem);
+ v++;
}
aurb = async_alloc(s);
aurb->packet = p;
return USB_RET_STALL;
}
}
- }
+ } while (rem > 0);
return USB_RET_ASYNC;
}
#include "hw/usb.h"
#define MAX_ENDPOINTS 32
+#define NO_INTERFACE_INFO 255 /* Valid interface_count always <= 32 */
#define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f))
#define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f))
return aurb;
}
}
- ERROR("could not find async urb for packet_id %u\n", packet_id);
+ DPRINTF("could not find async urb for packet_id %u\n", packet_id);
return NULL;
}
static int usbredir_check_filter(USBRedirDevice *dev)
{
- if (dev->interface_info.interface_count == 0) {
+ if (dev->interface_info.interface_count == NO_INTERFACE_INFO) {
ERROR("No interface info for device\n");
goto error;
}
QTAILQ_INIT(&dev->endpoint[i].bufpq);
}
usb_ep_init(&dev->dev);
- dev->interface_info.interface_count = 0;
+ dev->interface_info.interface_count = NO_INTERFACE_INFO;
+ dev->dev.addr = 0;
+ dev->dev.speed = 0;
}
static void usbredir_interface_info(void *priv,
memcpy(&config, config_data, sizeof(config));
}
+static void guest_reset(VirtIOSerial *vser)
+{
+ VirtIOSerialPort *port;
+ VirtIOSerialPortClass *vsc;
+
+ QTAILQ_FOREACH(port, &vser->ports, next) {
+ vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
+ if (port->guest_connected) {
+ port->guest_connected = false;
+
+ if (vsc->guest_close)
+ vsc->guest_close(port);
+ }
+ }
+}
+
+static void set_status(VirtIODevice *vdev, uint8_t status)
+{
+ VirtIOSerial *vser;
+ VirtIOSerialPort *port;
+
+ vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
+ port = find_port_by_id(vser, 0);
+
+ if (port && !use_multiport(port->vser)
+ && (status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+ /*
+ * Non-multiport guests won't be able to tell us guest
+ * open/close status. Such guests can only have a port at id
+ * 0, so set guest_connected for such ports as soon as guest
+ * is up.
+ */
+ port->guest_connected = true;
+ }
+ if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+ guest_reset(vser);
+ }
+}
+
+static void vser_reset(VirtIODevice *vdev)
+{
+ VirtIOSerial *vser;
+
+ vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
+ guest_reset(vser);
+}
+
static void virtio_serial_save(QEMUFile *f, void *opaque)
{
VirtIOSerial *s = opaque;
return ret;
}
- if (!use_multiport(port->vser)) {
- /*
- * Allow writes to guest in this case; we have no way of
- * knowing if a guest port is connected.
- */
- port->guest_connected = true;
- }
-
port->elem.out_num = 0;
QTAILQ_INSERT_TAIL(&port->vser->ports, port, next);
vser->vdev.get_features = get_features;
vser->vdev.get_config = get_config;
vser->vdev.set_config = set_config;
+ vser->vdev.set_status = set_status;
+ vser->vdev.reset = vser_reset;
vser->qdev = dev;
} else {
vring_used_flags_set_bit(vq, VRING_USED_F_NO_NOTIFY);
}
+ if (enable) {
+ /* Expose avail event/used flags before caller checks the avail idx. */
+ smp_mb();
+ }
}
int virtio_queue_ready(VirtQueue *vq)
idx, vring_avail_idx(vq));
exit(1);
}
+ /* On success, callers read a descriptor at vq->last_avail_idx.
+ * Make sure descriptor read does not bypass avail index read. */
+ if (num_heads) {
+ smp_rmb();
+ }
return num_heads;
}
{
uint16_t old, new;
bool v;
+ /* We need to expose used array entries before checking used event. */
+ smp_mb();
/* Always notify when queue is empty (when feature acknowledge) */
if (((vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) &&
!vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx)) {
#ifndef _WIN32
static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds,
- fd_set *xfds, int *cur_timeout)
+ fd_set *xfds, uint32_t *cur_timeout)
{
GMainContext *context = g_main_context_default();
int i;
}
}
-static int os_host_main_loop_wait(int timeout)
+static int os_host_main_loop_wait(uint32_t timeout)
{
- struct timeval tv;
+ struct timeval tv, *tvarg = NULL;
int ret;
glib_select_fill(&nfds, &rfds, &wfds, &xfds, &timeout);
+ if (timeout < UINT32_MAX) {
+ tvarg = &tv;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ }
+
if (timeout > 0) {
qemu_mutex_unlock_iothread();
}
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
+ ret = select(nfds + 1, &rfds, &wfds, &xfds, tvarg);
if (timeout > 0) {
qemu_mutex_lock_iothread();
FD_CONNECT | FD_WRITE | FD_OOB);
}
-static int os_host_main_loop_wait(int timeout)
+static int os_host_main_loop_wait(uint32_t timeout)
{
GMainContext *context = g_main_context_default();
int ret, i;
PollingEntry *pe;
WaitObjects *w = &wait_objects;
+ gint poll_timeout;
static struct timeval tv0;
/* XXX: need to suppress polling by better using win32 events */
if (nfds >= 0) {
ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0);
if (ret != 0) {
- timeout = 0;
+ /* TODO. */
}
}
g_main_context_prepare(context, &max_priority);
- n_poll_fds = g_main_context_query(context, max_priority, &timeout,
+ n_poll_fds = g_main_context_query(context, max_priority, &poll_timeout,
poll_fds, ARRAY_SIZE(poll_fds));
g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds));
}
qemu_mutex_unlock_iothread();
- ret = g_poll(poll_fds, n_poll_fds + w->num, timeout);
+ ret = g_poll(poll_fds, n_poll_fds + w->num, poll_timeout);
qemu_mutex_lock_iothread();
if (ret > 0) {
for (i = 0; i < w->num; i++) {
int main_loop_wait(int nonblocking)
{
- int ret, timeout;
+ int ret;
+ uint32_t timeout = UINT32_MAX;
if (nonblocking) {
timeout = 0;
} else {
- timeout = qemu_calculate_timeout();
qemu_bh_update_timeout(&timeout);
}
FD_ZERO(&xfds);
#ifdef CONFIG_SLIRP
+ slirp_update_timeout(&timeout);
slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
#endif
qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds);
void qemu_bh_schedule_idle(QEMUBH *bh);
int qemu_bh_poll(void);
-void qemu_bh_update_timeout(int *timeout);
+void qemu_bh_update_timeout(uint32_t *timeout);
#endif
#include <sys/prctl.h>
#endif
+#ifdef __FreeBSD__
+#include <sys/sysctl.h>
+#endif
+
static struct passwd *user_pwd;
static const char *chroot_dir;
static int daemonize;
#include <sys/time.h>
+#if defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10
+/* [u]int_fast*_t not in <sys/int_types.h> */
+typedef unsigned char uint_fast8_t;
+typedef unsigned int uint_fast16_t;
+typedef signed int int_fast16_t;
+#endif
+
#ifndef glue
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
#
# @base: #optional the common backing file name
#
+# @speed: #optional the maximum speed, in bytes per second
+#
# Returns: Nothing on success
# If streaming is already active on this device, DeviceInUse
# If @device does not exist, DeviceNotFound
# If image streaming is not supported by this device, NotSupported
# If @base does not exist, BaseNotFound
+# If @speed is invalid, InvalidParameter
#
# Since: 1.1
##
-{ 'command': 'block-stream', 'data': { 'device': 'str', '*base': 'str' } }
+{ 'command': 'block-stream', 'data': { 'device': 'str', '*base': 'str',
+ '*speed': 'int' } }
##
# @block-job-set-speed:
#
# @device: the device name
#
-# @value: the maximum speed, in bytes per second
+# @speed: the maximum speed, in bytes per second, or 0 for unlimited.
+# Defaults to 0.
#
# Returns: Nothing on success
# If the job type does not support throttling, NotSupported
+# If the speed value is invalid, InvalidParameter
# If streaming is not active on this device, DeviceNotActive
#
# Since: 1.1
##
{ 'command': 'block-job-set-speed',
- 'data': { 'device': 'str', 'value': 'int' } }
+ 'data': { 'device': 'str', 'speed': 'int' } }
##
# @block-job-cancel:
/* Compiler barrier */
#define barrier() asm volatile("" ::: "memory")
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__)
/*
- * Because of the strongly ordered x86 storage model, wmb() is a nop
+ * Because of the strongly ordered x86 storage model, wmb() and rmb() are nops
* on x86(well, a compiler barrier only). Well, at least as long as
* qemu doesn't do accesses to write-combining memory or non-temporal
* load/stores from C code.
*/
#define smp_wmb() barrier()
+#define smp_rmb() barrier()
+/*
+ * We use GCC builtin if it's available, as that can use
+ * mfence on 32 bit as well, e.g. if built with -march=pentium-m.
+ * However, on i386, there seem to be known bugs as recently as 4.3.
+ * */
+#if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
+#define smp_mb() __sync_synchronize()
+#else
+#define smp_mb() asm volatile("lock; addl $0,0(%%esp) " ::: "memory")
+#endif
+
+#elif defined(__x86_64__)
+
+#define smp_wmb() barrier()
+#define smp_rmb() barrier()
+#define smp_mb() asm volatile("mfence" ::: "memory")
#elif defined(_ARCH_PPC)
/*
- * We use an eieio() for a wmb() on powerpc. This assumes we don't
+ * We use an eieio() for wmb() on powerpc. This assumes we don't
* need to order cacheable and non-cacheable stores with respect to
* each other
*/
#define smp_wmb() asm volatile("eieio" ::: "memory")
+#if defined(__powerpc64__)
+#define smp_rmb() asm volatile("lwsync" ::: "memory")
+#else
+#define smp_rmb() asm volatile("sync" ::: "memory")
+#endif
+
+#define smp_mb() asm volatile("sync" ::: "memory")
+
#else
/*
* For (host) platforms we don't have explicit barrier definitions
* for, we use the gcc __sync_synchronize() primitive to generate a
* full barrier. This should be safe on all platforms, though it may
- * be overkill.
+ * be overkill for wmb() and rmb().
*/
#define smp_wmb() __sync_synchronize()
+#define smp_mb() __sync_synchronize()
+#define smp_rmb() __sync_synchronize()
#endif
@menu
* Supported Operating Systems ::
* Linux User space emulator::
-* Mac OS X/Darwin User space emulator ::
* BSD User space emulator ::
@end menu
@item
Linux (referred as qemu-linux-user)
@item
-Mac OS X/Darwin (referred as qemu-darwin-user)
-@item
BSD (referred as qemu-bsd-user)
@end itemize
@command{qemu-sparc64} can execute some Sparc64 (Sparc64 CPU, 64 bit ABI) and
SPARC32PLUS binaries (Sparc64 CPU, 32 bit ABI).
-@node Mac OS X/Darwin User space emulator
-@section Mac OS X/Darwin User space emulator
-
-@menu
-* Mac OS X/Darwin Status::
-* Mac OS X/Darwin Quick Start::
-* Mac OS X/Darwin Command line options::
-@end menu
-
-@node Mac OS X/Darwin Status
-@subsection Mac OS X/Darwin Status
-
-@itemize @minus
-@item
-target x86 on x86: Most apps (Cocoa and Carbon too) works. [1]
-@item
-target PowerPC on x86: Not working as the ppc commpage can't be mapped (yet!)
-@item
-target PowerPC on PowerPC: Most apps (Cocoa and Carbon too) works. [1]
-@item
-target x86 on PowerPC: most utilities work. Cocoa and Carbon apps are not yet supported.
-@end itemize
-
-[1] If you're host commpage can be executed by qemu.
-
-@node Mac OS X/Darwin Quick Start
-@subsection Quick Start
-
-In order to launch a Mac OS X/Darwin process, QEMU needs the process executable
-itself and all the target dynamic libraries used by it. If you don't have the FAT
-libraries (you're running Mac OS X/ppc) you'll need to obtain it from a Mac OS X
-CD or compile them by hand.
-
-@itemize
-
-@item On x86, you can just try to launch any process by using the native
-libraries:
-
-@example
-qemu-i386 /bin/ls
-@end example
-
-or to run the ppc version of the executable:
-
-@example
-qemu-ppc /bin/ls
-@end example
-
-@item On ppc, you'll have to tell qemu where your x86 libraries (and dynamic linker)
-are installed:
-
-@example
-qemu-i386 -L /opt/x86_root/ /bin/ls
-@end example
-
-@code{-L /opt/x86_root/} tells that the dynamic linker (dyld) path is in
-@file{/opt/x86_root/usr/bin/dyld}.
-
-@end itemize
-
-@node Mac OS X/Darwin Command line options
-@subsection Command line options
-
-@example
-usage: qemu-i386 [-h] [-d] [-L path] [-s size] program [arguments...]
-@end example
-
-@table @option
-@item -h
-Print the help
-@item -L path
-Set the library root path (default=/)
-@item -s size
-Set the stack size in bytes (default=524288)
-@end table
-
-Debug options:
-
-@table @option
-@item -d
-Activate log (logfile=/tmp/qemu.log)
-@item -p pagesize
-Act as if the host page size was 'pagesize' bytes
-@item -singlestep
-Run the emulation in single step mode.
-@end table
-
@node BSD User space emulator
@section BSD User space emulator
@end itemize
Linux user emulator (Linux host only) can be used to launch the Wine
-Windows API emulator (@url{http://www.winehq.org}). A Darwin user
-emulator (Darwin hosts only) exists and a BSD user emulator for BSD
+Windows API emulator (@url{http://www.winehq.org}). A BSD user emulator for BSD
hosts is under development. It would also be possible to develop a
similar user emulator for Solaris.
#include "hw/hw.h"
-#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <signal.h>
+#include "qemu-timer.h"
+
#ifdef __FreeBSD__
#include <sys/param.h>
#endif
#ifdef _WIN32
-#include <windows.h>
#include <mmsystem.h>
#endif
-#include "qemu-timer.h"
-
/***********************************************************/
/* timers */
#define QEMU_CLOCK_HOST 2
struct QEMUClock {
- int type;
- int enabled;
-
QEMUTimer *active_timers;
NotifierList reset_notifiers;
int64_t last;
+
+ int type;
+ bool enabled;
};
struct QEMUTimer {
- QEMUClock *clock;
int64_t expire_time; /* in nanoseconds */
- int scale;
+ QEMUClock *clock;
QEMUTimerCB *cb;
void *opaque;
- struct QEMUTimer *next;
+ QEMUTimer *next;
+ int scale;
};
struct qemu_alarm_timer {
void (*stop)(struct qemu_alarm_timer *t);
void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);
#if defined(__linux__)
- int fd;
timer_t timer;
+ int fd;
#elif defined(_WIN32)
HANDLE timer;
#endif
- char expired;
- char pending;
+ bool expired;
+ bool pending;
};
static struct qemu_alarm_timer *alarm_timer;
return timer_head && (timer_head->expire_time <= current_time);
}
-int qemu_alarm_pending(void)
-{
- return alarm_timer->pending;
-}
-
-static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
-{
- return !!t->rearm;
-}
-
static int64_t qemu_next_alarm_deadline(void)
{
- int64_t delta;
+ int64_t delta = INT64_MAX;
int64_t rtdelta;
- if (!use_icount && vm_clock->active_timers) {
+ if (!use_icount && vm_clock->enabled && vm_clock->active_timers) {
delta = vm_clock->active_timers->expire_time -
qemu_get_clock_ns(vm_clock);
- } else {
- delta = INT32_MAX;
}
- if (host_clock->active_timers) {
+ if (host_clock->enabled && host_clock->active_timers) {
int64_t hdelta = host_clock->active_timers->expire_time -
qemu_get_clock_ns(host_clock);
if (hdelta < delta) {
delta = hdelta;
}
}
- if (rt_clock->active_timers) {
+ if (rt_clock->enabled && rt_clock->active_timers) {
rtdelta = (rt_clock->active_timers->expire_time -
qemu_get_clock_ns(rt_clock));
if (rtdelta < delta) {
static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
{
int64_t nearest_delta_ns;
- assert(alarm_has_dynticks(t));
if (!rt_clock->active_timers &&
!vm_clock->active_timers &&
!host_clock->active_timers) {
clock = g_malloc0(sizeof(QEMUClock));
clock->type = type;
- clock->enabled = 1;
+ clock->enabled = true;
clock->last = INT64_MIN;
notifier_list_init(&clock->reset_notifiers);
return clock;
}
-void qemu_clock_enable(QEMUClock *clock, int enabled)
+void qemu_clock_enable(QEMUClock *clock, bool enabled)
{
bool old = clock->enabled;
clock->enabled = enabled;
qemu_mod_timer_ns(ts, expire_time * ts->scale);
}
-int qemu_timer_pending(QEMUTimer *ts)
+bool qemu_timer_pending(QEMUTimer *ts)
{
QEMUTimer *t;
for (t = ts->clock->active_timers; t != NULL; t = t->next) {
- if (t == ts)
- return 1;
+ if (t == ts) {
+ return true;
+ }
}
- return 0;
+ return false;
}
-int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
+bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
{
return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale);
}
void qemu_run_all_timers(void)
{
- alarm_timer->pending = 0;
+ alarm_timer->pending = false;
/* vm time timers */
qemu_run_timers(vm_clock);
/* rearm timer, if not periodic */
if (alarm_timer->expired) {
- alarm_timer->expired = 0;
+ alarm_timer->expired = false;
qemu_rearm_alarm_timer(alarm_timer);
}
}
if (!t)
return;
- if (alarm_has_dynticks(t) ||
- qemu_next_alarm_deadline () <= 0) {
- t->expired = alarm_has_dynticks(t);
- t->pending = 1;
- qemu_notify_event();
- }
+ t->expired = true;
+ t->pending = true;
+ qemu_notify_event();
}
#if defined(__linux__)
if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {
perror("timer_create");
-
- /* disable dynticks */
- fprintf(stderr, "Dynamic Ticks disabled\n");
-
return -1;
}
if (!t) {
return;
}
- if (alarm_has_dynticks(t) || qemu_next_alarm_deadline() <= 0) {
- t->expired = alarm_has_dynticks(t);
- t->pending = 1;
- qemu_notify_event();
- }
+ t->expired = true;
+ t->pending = true;
+ qemu_notify_event();
}
static int mm_start_timer(struct qemu_alarm_timer *t)
{
TIMECAPS tc;
- UINT flags;
memset(&tc, 0, sizeof(tc));
timeGetDevCaps(&tc, sizeof(tc));
mm_period = tc.wPeriodMin;
timeBeginPeriod(mm_period);
- flags = TIME_CALLBACK_FUNCTION;
- if (alarm_has_dynticks(t)) {
- flags |= TIME_ONESHOT;
- } else {
- flags |= TIME_PERIODIC;
- }
-
mm_timer = timeSetEvent(1, /* interval (ms) */
mm_period, /* resolution */
mm_alarm_handler, /* function */
(DWORD_PTR)t, /* parameter */
- flags);
+ TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
if (!mm_timer) {
fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
{
- int nearest_delta_ms = (delta + 999999) / 1000000;
+ int64_t nearest_delta_ms = delta / 1000000;
if (nearest_delta_ms < 1) {
nearest_delta_ms = 1;
}
+ /* UINT_MAX can be 32 bit */
+ if (nearest_delta_ms > UINT_MAX) {
+ nearest_delta_ms = UINT_MAX;
+ }
timeKillEvent(mm_timer);
- mm_timer = timeSetEvent(nearest_delta_ms,
+ mm_timer = timeSetEvent((unsigned int) nearest_delta_ms,
mm_period,
mm_alarm_handler,
(DWORD_PTR)t,
host_alarm_handler,
t,
1,
- alarm_has_dynticks(t) ? 3600000 : 1,
+ 3600000,
WT_EXECUTEINTIMERTHREAD);
if (!success) {
int64_t nearest_delta_ns)
{
HANDLE hTimer = t->timer;
- int nearest_delta_ms;
+ int64_t nearest_delta_ms;
BOOLEAN success;
- nearest_delta_ms = (nearest_delta_ns + 999999) / 1000000;
+ nearest_delta_ms = nearest_delta_ns / 1000000;
if (nearest_delta_ms < 1) {
nearest_delta_ms = 1;
}
+ /* ULONG_MAX can be 32 bit */
+ if (nearest_delta_ms > ULONG_MAX) {
+ nearest_delta_ms = ULONG_MAX;
+ }
success = ChangeTimerQueueTimer(NULL,
hTimer,
- nearest_delta_ms,
+ (unsigned long) nearest_delta_ms,
3600000);
if (!success) {
/* first event is at time 0 */
atexit(quit_timers);
- t->pending = 1;
+ t->pending = true;
alarm_timer = t;
return 0;
return err;
}
-int qemu_calculate_timeout(void)
-{
- return 1000;
-}
-
#include "qemu-common.h"
#include "main-loop.h"
#include "notify.h"
-#include <time.h>
-#include <sys/time.h>
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
/* timers */
int64_t qemu_clock_has_timers(QEMUClock *clock);
int64_t qemu_clock_expired(QEMUClock *clock);
int64_t qemu_clock_deadline(QEMUClock *clock);
-void qemu_clock_enable(QEMUClock *clock, int enabled);
+void qemu_clock_enable(QEMUClock *clock, bool enabled);
void qemu_clock_warp(QEMUClock *clock);
void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier);
void qemu_del_timer(QEMUTimer *ts);
void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time);
void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
-int qemu_timer_pending(QEMUTimer *ts);
-int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
+bool qemu_timer_pending(QEMUTimer *ts);
+bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts);
void qemu_run_timers(QEMUClock *clock);
void qemu_run_all_timers(void);
-int qemu_alarm_pending(void);
void configure_alarms(char const *opt);
-int qemu_calculate_timeout(void);
void init_clocks(void);
int init_timer_alarm(void);
return main_loop_init();
}
+void slirp_update_timeout(uint32_t *timeout)
+{
+}
+
void slirp_select_fill(int *pnfds, fd_set *readfds,
fd_set *writefds, fd_set *xfds)
{
{
.name = "block-stream",
- .args_type = "device:B,base:s?",
+ .args_type = "device:B,base:s?,speed:o?",
.mhandler.cmd_new = qmp_marshal_input_block_stream,
},
{
.name = "block-job-set-speed",
- .args_type = "device:B,value:o",
+ .args_type = "device:B,speed:o",
.mhandler.cmd_new = qmp_marshal_input_block_job_set_speed,
},
$(wildcard $1), \
$(wildcard $(patsubst %, %/$1, $(subst :, ,$(PATH)))))
+# Generate files with tracetool
+TRACETOOL=$(PYTHON) $(SRC_PATH)/scripts/tracetool.py
+
# Generate timestamp files for .h include files
%.h: %.h-timestamp
struct in_addr vnameserver, void *opaque);
void slirp_cleanup(Slirp *slirp);
+void slirp_update_timeout(uint32_t *timeout);
void slirp_select_fill(int *pnfds,
fd_set *readfds, fd_set *writefds, fd_set *xfds);
#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
+void slirp_update_timeout(uint32_t *timeout)
+{
+ if (!QTAILQ_EMPTY(&slirp_instances)) {
+ *timeout = MIN(1000, *timeout);
+ }
+}
+
void slirp_select_fill(int *pnfds,
fd_set *readfds, fd_set *writefds, fd_set *xfds)
{
#define QEMU_ARM_CPU_QOM_H
#include "qemu/cpu.h"
-#include "cpu.h"
#define TYPE_ARM_CPU "arm-cpu"
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
*/
uint32_t ccsidr[16];
+ uint32_t reset_cbar;
} ARMCPU;
static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
* <http://www.gnu.org/licenses/gpl-2.0.html>
*/
-#include "cpu-qom.h"
+#include "cpu.h"
#include "qemu-common.h"
#if !defined(CONFIG_USER_ONLY)
#include "hw/loader.h"
ARMCPU *cpu = ARM_CPU(s);
ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu);
CPUARMState *env = &cpu->env;
- uint32_t tmp = 0;
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
acc->parent_reset(s);
- tmp = env->cp15.c15_config_base_address;
memset(env, 0, offsetof(CPUARMState, breakpoints));
- env->cp15.c15_config_base_address = tmp;
+ env->cp15.c15_config_base_address = cpu->reset_cbar;
env->cp15.c0_cpuid = cpu->midr;
env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid;
env->vfp.xregs[ARM_VFP_MVFR0] = cpu->mvfr0;
const struct arm_boot_info *boot_info;
} CPUARMState;
-CPUARMState *cpu_arm_init(const char *cpu_model);
+#include "cpu-qom.h"
+
+ARMCPU *cpu_arm_init(const char *cpu_model);
void arm_translate_init(void);
int cpu_arm_exec(CPUARMState *s);
void do_interrupt(CPUARMState *);
#define TARGET_PHYS_ADDR_SPACE_BITS 32
#define TARGET_VIRT_ADDR_SPACE_BITS 32
-#define cpu_init cpu_arm_init
+#define cpu_init(model) (&cpu_arm_init(model)->env)
#define cpu_exec cpu_arm_exec
#define cpu_gen_code cpu_arm_gen_code
#define cpu_signal_handler cpu_arm_signal_handler
#endif
#include "cpu-all.h"
-#include "cpu-qom.h"
/* Bit usage in the TB flags field: */
#define ARM_TBFLAG_THUMB_SHIFT 0
return 0;
}
-CPUARMState *cpu_arm_init(const char *cpu_model)
+ARMCPU *cpu_arm_init(const char *cpu_model)
{
ARMCPU *cpu;
CPUARMState *env;
19, "arm-vfp.xml", 0);
}
qemu_init_vcpu(env);
- return env;
+ return cpu;
}
typedef struct ARMCPUListState {
if ((insn & 0x0ffffdff) == 0x01010000) {
ARCH(6);
/* setend */
- if (insn & (1 << 9)) {
- /* BE8 mode not implemented. */
+ if (((insn >> 9) & 1) != s->bswap_code) {
+ /* Dynamic endianness switching not implemented. */
goto illegal_op;
}
return;
case 2:
/* setend */
ARCH(6);
- if (insn & (1 << 3)) {
- /* BE8 mode not implemented. */
+ if (((insn >> 3) & 1) != s->bswap_code) {
+ /* Dynamic endianness switching not implemented. */
goto illegal_op;
}
break;
#include "qemu-option.h"
#include "qemu-config.h"
+#include "qapi/qapi-visit-core.h"
+
#include "hyperv.h"
/* feature flags taken from "Intel Processor Identification and the CPUID
return rv;
}
-static void x86_cpuid_version_set_family(CPUX86State *env, int family)
+static void x86_cpuid_version_get_family(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ int64_t value;
+
+ value = (env->cpuid_version >> 8) & 0xf;
+ if (value == 0xf) {
+ value += (env->cpuid_version >> 20) & 0xff;
+ }
+ visit_type_int(v, &value, name, errp);
+}
+
+static void x86_cpuid_version_set_family(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ const int64_t min = 0;
+ const int64_t max = 0xff + 0xf;
+ int64_t value;
+
+ visit_type_int(v, &value, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (value < min || value > max) {
+ error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
+ name ? name : "null", value, min, max);
+ return;
+ }
+
env->cpuid_version &= ~0xff00f00;
- if (family > 0x0f) {
- env->cpuid_version |= 0xf00 | ((family - 0x0f) << 20);
+ if (value > 0x0f) {
+ env->cpuid_version |= 0xf00 | ((value - 0x0f) << 20);
} else {
- env->cpuid_version |= family << 8;
+ env->cpuid_version |= value << 8;
}
}
-static void x86_cpuid_version_set_model(CPUX86State *env, int model)
+static void x86_cpuid_version_get_model(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ int64_t value;
+
+ value = (env->cpuid_version >> 4) & 0xf;
+ value |= ((env->cpuid_version >> 16) & 0xf) << 4;
+ visit_type_int(v, &value, name, errp);
+}
+
+static void x86_cpuid_version_set_model(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ const int64_t min = 0;
+ const int64_t max = 0xff;
+ int64_t value;
+
+ visit_type_int(v, &value, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (value < min || value > max) {
+ error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
+ name ? name : "null", value, min, max);
+ return;
+ }
+
env->cpuid_version &= ~0xf00f0;
- env->cpuid_version |= ((model & 0xf) << 4) | ((model >> 4) << 16);
+ env->cpuid_version |= ((value & 0xf) << 4) | ((value >> 4) << 16);
}
-static void x86_cpuid_version_set_stepping(CPUX86State *env, int stepping)
+static void x86_cpuid_version_get_stepping(Object *obj, Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ int64_t value;
+
+ value = env->cpuid_version & 0xf;
+ visit_type_int(v, &value, name, errp);
+}
+
+static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ const int64_t min = 0;
+ const int64_t max = 0xf;
+ int64_t value;
+
+ visit_type_int(v, &value, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (value < min || value > max) {
+ error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
+ name ? name : "null", value, min, max);
+ return;
+ }
+
env->cpuid_version &= ~0xf;
- env->cpuid_version |= stepping & 0xf;
+ env->cpuid_version |= value & 0xf;
}
-static void x86_cpuid_set_model_id(CPUX86State *env, const char *model_id)
+static void x86_cpuid_get_level(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
+ X86CPU *cpu = X86_CPU(obj);
+ int64_t value;
+
+ value = cpu->env.cpuid_level;
+ /* TODO Use visit_type_uint32() once available */
+ visit_type_int(v, &value, name, errp);
+}
+
+static void x86_cpuid_set_level(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ const int64_t min = 0;
+ const int64_t max = UINT32_MAX;
+ int64_t value;
+
+ /* TODO Use visit_type_uint32() once available */
+ visit_type_int(v, &value, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (value < min || value > max) {
+ error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
+ name ? name : "null", value, min, max);
+ return;
+ }
+
+ cpu->env.cpuid_level = value;
+}
+
+static void x86_cpuid_get_xlevel(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ int64_t value;
+
+ value = cpu->env.cpuid_xlevel;
+ /* TODO Use visit_type_uint32() once available */
+ visit_type_int(v, &value, name, errp);
+}
+
+static void x86_cpuid_set_xlevel(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ const int64_t min = 0;
+ const int64_t max = UINT32_MAX;
+ int64_t value;
+
+ /* TODO Use visit_type_uint32() once available */
+ visit_type_int(v, &value, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (value < min || value > max) {
+ error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
+ name ? name : "null", value, min, max);
+ return;
+ }
+
+ cpu->env.cpuid_xlevel = value;
+}
+
+static char *x86_cpuid_get_vendor(Object *obj, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ char *value;
+ int i;
+
+ value = (char *)g_malloc(12 + 1);
+ for (i = 0; i < 4; i++) {
+ value[i ] = env->cpuid_vendor1 >> (8 * i);
+ value[i + 4] = env->cpuid_vendor2 >> (8 * i);
+ value[i + 8] = env->cpuid_vendor3 >> (8 * i);
+ }
+ value[12] = '\0';
+ return value;
+}
+
+static void x86_cpuid_set_vendor(Object *obj, const char *value,
+ Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ int i;
+
+ if (strlen(value) != 12) {
+ error_set(errp, QERR_PROPERTY_VALUE_BAD, "",
+ "vendor", value);
+ return;
+ }
+
+ env->cpuid_vendor1 = 0;
+ env->cpuid_vendor2 = 0;
+ env->cpuid_vendor3 = 0;
+ for (i = 0; i < 4; i++) {
+ env->cpuid_vendor1 |= ((uint8_t)value[i ]) << (8 * i);
+ env->cpuid_vendor2 |= ((uint8_t)value[i + 4]) << (8 * i);
+ env->cpuid_vendor3 |= ((uint8_t)value[i + 8]) << (8 * i);
+ }
+ env->cpuid_vendor_override = 1;
+}
+
+static char *x86_cpuid_get_model_id(Object *obj, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+ char *value;
+ int i;
+
+ value = g_malloc(48 + 1);
+ for (i = 0; i < 48; i++) {
+ value[i] = env->cpuid_model[i >> 2] >> (8 * (i & 3));
+ }
+ value[48] = '\0';
+ return value;
+}
+
+static void x86_cpuid_set_model_id(Object *obj, const char *model_id,
+ Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
int c, len, i;
if (model_id == NULL) {
model_id = "";
}
len = strlen(model_id);
+ memset(env->cpuid_model, 0, 48);
for (i = 0; i < 48; i++) {
if (i >= len) {
c = '\0';
}
}
+static void x86_cpuid_get_tsc_freq(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ int64_t value;
+
+ value = cpu->env.tsc_khz * 1000;
+ visit_type_int(v, &value, name, errp);
+}
+
+static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ const int64_t min = 0;
+ const int64_t max = INT_MAX;
+ int64_t value;
+
+ visit_type_int(v, &value, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+ if (value < min || value > max) {
+ error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
+ name ? name : "null", value, min, max);
+ return;
+ }
+
+ cpu->env.tsc_khz = value / 1000;
+}
+
static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
{
unsigned int i;
if (!strcmp(featurestr, "family")) {
char *err;
numvalue = strtoul(val, &err, 0);
- if (!*val || *err) {
+ if (!*val || *err || numvalue > 0xff + 0xf) {
fprintf(stderr, "bad numerical value %s\n", val);
goto error;
}
}
}
-int cpu_x86_register (CPUX86State *env, const char *cpu_model)
+int cpu_x86_register(X86CPU *cpu, const char *cpu_model)
{
+ CPUX86State *env = &cpu->env;
x86_def_t def1, *def = &def1;
+ Error *error = NULL;
memset(def, 0, sizeof(*def));
env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
}
env->cpuid_vendor_override = def->vendor_override;
- env->cpuid_level = def->level;
- x86_cpuid_version_set_family(env, def->family);
- x86_cpuid_version_set_model(env, def->model);
- x86_cpuid_version_set_stepping(env, def->stepping);
+ object_property_set_int(OBJECT(cpu), def->level, "level", &error);
+ object_property_set_int(OBJECT(cpu), def->family, "family", &error);
+ object_property_set_int(OBJECT(cpu), def->model, "model", &error);
+ object_property_set_int(OBJECT(cpu), def->stepping, "stepping", &error);
env->cpuid_features = def->features;
env->cpuid_ext_features = def->ext_features;
env->cpuid_ext2_features = def->ext2_features;
env->cpuid_ext3_features = def->ext3_features;
- env->cpuid_xlevel = def->xlevel;
+ object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", &error);
env->cpuid_kvm_features = def->kvm_features;
env->cpuid_svm_features = def->svm_features;
env->cpuid_ext4_features = def->ext4_features;
env->cpuid_xlevel2 = def->xlevel2;
- env->tsc_khz = def->tsc_khz;
+ object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000,
+ "tsc-frequency", &error);
if (!kvm_enabled()) {
env->cpuid_features &= TCG_FEATURES;
env->cpuid_ext_features &= TCG_EXT_FEATURES;
env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
env->cpuid_svm_features &= TCG_SVM_FEATURES;
}
- x86_cpuid_set_model_id(env, def->model_id);
+ object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error);
+ if (error_is_set(&error)) {
+ error_free(error);
+ return -1;
+ }
return 0;
}
CPUX86State *env = &cpu->env;
cpu_exec_init(env);
+
+ object_property_add(obj, "family", "int",
+ x86_cpuid_version_get_family,
+ x86_cpuid_version_set_family, NULL, NULL, NULL);
+ object_property_add(obj, "model", "int",
+ x86_cpuid_version_get_model,
+ x86_cpuid_version_set_model, NULL, NULL, NULL);
+ object_property_add(obj, "stepping", "int",
+ x86_cpuid_version_get_stepping,
+ x86_cpuid_version_set_stepping, NULL, NULL, NULL);
+ object_property_add(obj, "level", "int",
+ x86_cpuid_get_level,
+ x86_cpuid_set_level, NULL, NULL, NULL);
+ object_property_add(obj, "xlevel", "int",
+ x86_cpuid_get_xlevel,
+ x86_cpuid_set_xlevel, NULL, NULL, NULL);
+ object_property_add_str(obj, "vendor",
+ x86_cpuid_get_vendor,
+ x86_cpuid_set_vendor, NULL);
+ object_property_add_str(obj, "model-id",
+ x86_cpuid_get_model_id,
+ x86_cpuid_set_model_id, NULL);
+ object_property_add(obj, "tsc-frequency", "int",
+ x86_cpuid_get_tsc_freq,
+ x86_cpuid_set_tsc_freq, NULL, NULL, NULL);
+
env->cpuid_apic_id = env->cpu_index;
mce_init(cpu);
}
void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx);
-int cpu_x86_register (CPUX86State *env, const char *cpu_model);
+int cpu_x86_register(X86CPU *cpu, const char *cpu_model);
void cpu_clear_apic_feature(CPUX86State *env);
void host_cpuid(uint32_t function, uint32_t count,
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
cpu_set_debug_excp_handler(breakpoint_handler);
#endif
}
- if (cpu_x86_register(env, cpu_model) < 0) {
+ if (cpu_x86_register(cpu, cpu_model) < 0) {
object_delete(OBJECT(cpu));
return NULL;
}
--- /dev/null
+/*
+ * QEMU Motorola 68k CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+#ifndef QEMU_M68K_CPU_QOM_H
+#define QEMU_M68K_CPU_QOM_H
+
+#include "qemu/cpu.h"
+
+#define TYPE_M68K_CPU "m68k-cpu"
+
+#define M68K_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(M68kCPUClass, (klass), TYPE_M68K_CPU)
+#define M68K_CPU(obj) \
+ OBJECT_CHECK(M68kCPU, (obj), TYPE_M68K_CPU)
+#define M68K_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(M68kCPUClass, (obj), TYPE_M68K_CPU)
+
+/**
+ * M68kCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A Motorola 68k CPU model.
+ */
+typedef struct M68kCPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ void (*parent_reset)(CPUState *cpu);
+} M68kCPUClass;
+
+/**
+ * M68kCPU:
+ * @env: #CPUM68KState
+ *
+ * A Motorola 68k CPU.
+ */
+typedef struct M68kCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUM68KState env;
+} M68kCPU;
+
+static inline M68kCPU *m68k_env_get_cpu(CPUM68KState *env)
+{
+ return M68K_CPU(container_of(env, M68kCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(m68k_env_get_cpu(e))
+
+
+#endif
--- /dev/null
+/*
+ * QEMU Motorola 68k CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+
+
+static void m68k_set_feature(CPUM68KState *env, int feature)
+{
+ env->features |= (1u << feature);
+}
+
+/* CPUClass::reset() */
+static void m68k_cpu_reset(CPUState *s)
+{
+ M68kCPU *cpu = M68K_CPU(s);
+ M68kCPUClass *mcc = M68K_CPU_GET_CLASS(cpu);
+ CPUM68KState *env = &cpu->env;
+
+ if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+ qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+ log_cpu_state(env, 0);
+ }
+
+ mcc->parent_reset(s);
+
+ memset(env, 0, offsetof(CPUM68KState, breakpoints));
+#if !defined(CONFIG_USER_ONLY)
+ env->sr = 0x2700;
+#endif
+ m68k_switch_sp(env);
+ /* ??? FP regs should be initialized to NaN. */
+ env->cc_op = CC_OP_FLAGS;
+ /* TODO: We should set PC from the interrupt vector. */
+ env->pc = 0;
+ tlb_flush(env, 1);
+}
+
+/* CPU models */
+
+static void m5206_cpu_initfn(Object *obj)
+{
+ M68kCPU *cpu = M68K_CPU(obj);
+ CPUM68KState *env = &cpu->env;
+
+ m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
+}
+
+static void m5208_cpu_initfn(Object *obj)
+{
+ M68kCPU *cpu = M68K_CPU(obj);
+ CPUM68KState *env = &cpu->env;
+
+ m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
+ m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
+ m68k_set_feature(env, M68K_FEATURE_BRAL);
+ m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
+ m68k_set_feature(env, M68K_FEATURE_USP);
+}
+
+static void cfv4e_cpu_initfn(Object *obj)
+{
+ M68kCPU *cpu = M68K_CPU(obj);
+ CPUM68KState *env = &cpu->env;
+
+ m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
+ m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
+ m68k_set_feature(env, M68K_FEATURE_BRAL);
+ m68k_set_feature(env, M68K_FEATURE_CF_FPU);
+ m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
+ m68k_set_feature(env, M68K_FEATURE_USP);
+}
+
+static void any_cpu_initfn(Object *obj)
+{
+ M68kCPU *cpu = M68K_CPU(obj);
+ CPUM68KState *env = &cpu->env;
+
+ m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
+ m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
+ m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
+ m68k_set_feature(env, M68K_FEATURE_BRAL);
+ m68k_set_feature(env, M68K_FEATURE_CF_FPU);
+ /* MAC and EMAC are mututally exclusive, so pick EMAC.
+ It's mostly backwards compatible. */
+ m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
+ m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
+ m68k_set_feature(env, M68K_FEATURE_USP);
+ m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
+ m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+}
+
+typedef struct M68kCPUInfo {
+ const char *name;
+ void (*instance_init)(Object *obj);
+} M68kCPUInfo;
+
+static const M68kCPUInfo m68k_cpus[] = {
+ { .name = "m5206", .instance_init = m5206_cpu_initfn },
+ { .name = "m5208", .instance_init = m5208_cpu_initfn },
+ { .name = "cfv4e", .instance_init = cfv4e_cpu_initfn },
+ { .name = "any", .instance_init = any_cpu_initfn },
+};
+
+static void m68k_cpu_initfn(Object *obj)
+{
+ M68kCPU *cpu = M68K_CPU(obj);
+ CPUM68KState *env = &cpu->env;
+
+ cpu_exec_init(env);
+}
+
+static void m68k_cpu_class_init(ObjectClass *c, void *data)
+{
+ M68kCPUClass *mcc = M68K_CPU_CLASS(c);
+ CPUClass *cc = CPU_CLASS(c);
+
+ mcc->parent_reset = cc->reset;
+ cc->reset = m68k_cpu_reset;
+}
+
+static void register_cpu_type(const M68kCPUInfo *info)
+{
+ TypeInfo type_info = {
+ .name = info->name,
+ .parent = TYPE_M68K_CPU,
+ .instance_init = info->instance_init,
+ };
+
+ type_register_static(&type_info);
+}
+
+static const TypeInfo m68k_cpu_type_info = {
+ .name = TYPE_M68K_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(M68kCPU),
+ .instance_init = m68k_cpu_initfn,
+ .abstract = true,
+ .class_size = sizeof(M68kCPUClass),
+ .class_init = m68k_cpu_class_init,
+};
+
+static void m68k_cpu_register_types(void)
+{
+ int i;
+
+ type_register_static(&m68k_cpu_type_info);
+ for (i = 0; i < ARRAY_SIZE(m68k_cpus); i++) {
+ register_cpu_type(&m68k_cpus[i]);
+ }
+}
+
+type_init(m68k_cpu_register_types)
uint32_t features;
} CPUM68KState;
+#include "cpu-qom.h"
+
void m68k_tcg_init(void);
CPUM68KState *cpu_m68k_init(const char *cpu_model);
int cpu_m68k_exec(CPUM68KState *s);
-void cpu_m68k_close(CPUM68KState *s);
void do_interrupt(CPUM68KState *env1);
void do_interrupt_m68k_hardirq(CPUM68KState *env1);
/* you can call this signal handler from your SIGBUS and SIGSEGV
#define SIGNBIT (1u << 31)
-enum m68k_cpuid {
- M68K_CPUID_M5206,
- M68K_CPUID_M5208,
- M68K_CPUID_CFV4E,
- M68K_CPUID_ANY,
-};
-
-typedef struct m68k_def_t m68k_def_t;
-
-struct m68k_def_t {
- const char * name;
- enum m68k_cpuid id;
-};
-
-static m68k_def_t m68k_cpu_defs[] = {
- {"m5206", M68K_CPUID_M5206},
- {"m5208", M68K_CPUID_M5208},
- {"cfv4e", M68K_CPUID_CFV4E},
- {"any", M68K_CPUID_ANY},
- {NULL, 0},
-};
+typedef struct M68kCPUListState {
+ fprintf_function cpu_fprintf;
+ FILE *file;
+} M68kCPUListState;
+
+/* Sort alphabetically, except for "any". */
+static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+ ObjectClass *class_a = (ObjectClass *)a;
+ ObjectClass *class_b = (ObjectClass *)b;
+ const char *name_a, *name_b;
+
+ name_a = object_class_get_name(class_a);
+ name_b = object_class_get_name(class_b);
+ if (strcmp(name_a, "any") == 0) {
+ return 1;
+ } else if (strcmp(name_b, "any") == 0) {
+ return -1;
+ } else {
+ return strcasecmp(name_a, name_b);
+ }
+}
+
+static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
+{
+ ObjectClass *c = data;
+ M68kCPUListState *s = user_data;
+
+ (*s->cpu_fprintf)(s->file, "%s\n",
+ object_class_get_name(c));
+}
void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
{
- unsigned int i;
+ M68kCPUListState s = {
+ .file = f,
+ .cpu_fprintf = cpu_fprintf,
+ };
+ GSList *list;
- for (i = 0; m68k_cpu_defs[i].name; i++) {
- (*cpu_fprintf)(f, "%s\n", m68k_cpu_defs[i].name);
- }
+ list = object_class_get_list(TYPE_M68K_CPU, false);
+ list = g_slist_sort(list, m68k_cpu_list_compare);
+ g_slist_foreach(list, m68k_cpu_list_entry, &s);
+ g_slist_free(list);
}
static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
return 0;
}
-static void m68k_set_feature(CPUM68KState *env, int feature)
-{
- env->features |= (1u << feature);
-}
-
-static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
-{
- m68k_def_t *def;
-
- for (def = m68k_cpu_defs; def->name; def++) {
- if (strcmp(def->name, name) == 0)
- break;
- }
- if (!def->name)
- return -1;
-
- switch (def->id) {
- case M68K_CPUID_M5206:
- m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
- break;
- case M68K_CPUID_M5208:
- m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
- m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
- m68k_set_feature(env, M68K_FEATURE_BRAL);
- m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
- m68k_set_feature(env, M68K_FEATURE_USP);
- break;
- case M68K_CPUID_CFV4E:
- m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
- m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
- m68k_set_feature(env, M68K_FEATURE_BRAL);
- m68k_set_feature(env, M68K_FEATURE_CF_FPU);
- m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
- m68k_set_feature(env, M68K_FEATURE_USP);
- break;
- case M68K_CPUID_ANY:
- m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
- m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
- m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
- m68k_set_feature(env, M68K_FEATURE_BRAL);
- m68k_set_feature(env, M68K_FEATURE_CF_FPU);
- /* MAC and EMAC are mututally exclusive, so pick EMAC.
- It's mostly backwards compatible. */
- m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
- m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
- m68k_set_feature(env, M68K_FEATURE_USP);
- m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
- m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
- break;
- }
-
- register_m68k_insns(env);
- if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
- gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
- 11, "cf-fp.xml", 18);
- }
- /* TODO: Add [E]MAC registers. */
- return 0;
-}
-
void cpu_state_reset(CPUM68KState *env)
{
- if (qemu_loglevel_mask(CPU_LOG_RESET)) {
- qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
- log_cpu_state(env, 0);
- }
-
- memset(env, 0, offsetof(CPUM68KState, breakpoints));
-#if !defined (CONFIG_USER_ONLY)
- env->sr = 0x2700;
-#endif
- m68k_switch_sp(env);
- /* ??? FP regs should be initialized to NaN. */
- env->cc_op = CC_OP_FLAGS;
- /* TODO: We should set PC from the interrupt vector. */
- env->pc = 0;
- tlb_flush(env, 1);
+ cpu_reset(ENV_GET_CPU(env));
}
CPUM68KState *cpu_m68k_init(const char *cpu_model)
{
+ M68kCPU *cpu;
CPUM68KState *env;
static int inited;
- env = g_malloc0(sizeof(CPUM68KState));
- cpu_exec_init(env);
+ if (object_class_by_name(cpu_model) == NULL) {
+ return NULL;
+ }
+ cpu = M68K_CPU(object_new(cpu_model));
+ env = &cpu->env;
+
if (!inited) {
inited = 1;
m68k_tcg_init();
env->cpu_model_str = cpu_model;
- if (cpu_m68k_set_model(env, cpu_model) < 0) {
- cpu_m68k_close(env);
- return NULL;
+ register_m68k_insns(env);
+ if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
+ gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
+ 11, "cf-fp.xml", 18);
}
+ /* TODO: Add [E]MAC registers. */
- cpu_state_reset(env);
+ cpu_reset(ENV_GET_CPU(env));
qemu_init_vcpu(env);
return env;
}
-void cpu_m68k_close(CPUM68KState *env)
-{
- g_free(env);
-}
-
void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
{
int flags;
--- /dev/null
+/*
+ * QEMU MIPS CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+#ifndef QEMU_MIPS_CPU_QOM_H
+#define QEMU_MIPS_CPU_QOM_H
+
+#include "qemu/cpu.h"
+
+#ifdef TARGET_MIPS64
+#define TYPE_MIPS_CPU "mips64-cpu"
+#else
+#define TYPE_MIPS_CPU "mips-cpu"
+#endif
+
+#define MIPS_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(MIPSCPUClass, (klass), TYPE_MIPS_CPU)
+#define MIPS_CPU(obj) \
+ OBJECT_CHECK(MIPSCPU, (obj), TYPE_MIPS_CPU)
+#define MIPS_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(MIPSCPUClass, (obj), TYPE_MIPS_CPU)
+
+/**
+ * MIPSCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A MIPS CPU model.
+ */
+typedef struct MIPSCPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ void (*parent_reset)(CPUState *cpu);
+} MIPSCPUClass;
+
+/**
+ * MIPSCPU:
+ * @env: #CPUMIPSState
+ *
+ * A MIPS CPU.
+ */
+typedef struct MIPSCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUMIPSState env;
+} MIPSCPU;
+
+static inline MIPSCPU *mips_env_get_cpu(CPUMIPSState *env)
+{
+ return MIPS_CPU(container_of(env, MIPSCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(mips_env_get_cpu(e))
+
+
+#endif
--- /dev/null
+/*
+ * QEMU MIPS CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+
+
+/* CPUClass::reset() */
+static void mips_cpu_reset(CPUState *s)
+{
+ MIPSCPU *cpu = MIPS_CPU(s);
+ MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
+ CPUMIPSState *env = &cpu->env;
+
+ mcc->parent_reset(s);
+
+ cpu_state_reset(env);
+}
+
+static void mips_cpu_initfn(Object *obj)
+{
+ MIPSCPU *cpu = MIPS_CPU(obj);
+ CPUMIPSState *env = &cpu->env;
+
+ cpu_exec_init(env);
+}
+
+static void mips_cpu_class_init(ObjectClass *c, void *data)
+{
+ MIPSCPUClass *mcc = MIPS_CPU_CLASS(c);
+ CPUClass *cc = CPU_CLASS(c);
+
+ mcc->parent_reset = cc->reset;
+ cc->reset = mips_cpu_reset;
+}
+
+static const TypeInfo mips_cpu_type_info = {
+ .name = TYPE_MIPS_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(MIPSCPU),
+ .instance_init = mips_cpu_initfn,
+ .abstract = false,
+ .class_size = sizeof(MIPSCPUClass),
+ .class_init = mips_cpu_class_init,
+};
+
+static void mips_cpu_register_types(void)
+{
+ type_register_static(&mips_cpu_type_info);
+}
+
+type_init(mips_cpu_register_types)
#include "cpu-defs.h"
#include "softfloat.h"
-// uint_fast8_t and uint_fast16_t not in <sys/int_types.h>
-// XXX: move that elsewhere
-#if defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10
-typedef unsigned char uint_fast8_t;
-typedef unsigned int uint_fast16_t;
-#endif
-
struct CPUMIPSState;
typedef struct r4k_tlb_t r4k_tlb_t;
struct QEMUTimer *timer; /* Internal timer */
};
+#include "cpu-qom.h"
+
#if !defined(CONFIG_USER_ONLY)
int no_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot,
target_ulong address, int rw, int access_type);
CPUMIPSState *cpu_mips_init (const char *cpu_model)
{
+ MIPSCPU *cpu;
CPUMIPSState *env;
const mips_def_t *def;
def = cpu_mips_find_by_name(cpu_model);
if (!def)
return NULL;
- env = g_malloc0(sizeof(CPUMIPSState));
+ cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
+ env = &cpu->env;
env->cpu_model = def;
env->cpu_model_str = cpu_model;
- cpu_exec_init(env);
#ifndef CONFIG_USER_ONLY
mmu_init(env, def);
#endif
--- /dev/null
+/*
+ * QEMU SuperH CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+#ifndef QEMU_SUPERH_CPU_QOM_H
+#define QEMU_SUPERH_CPU_QOM_H
+
+#include "qemu/cpu.h"
+
+#define TYPE_SUPERH_CPU "superh-cpu"
+
+#define SUPERH_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(SuperHCPUClass, (klass), TYPE_SUPERH_CPU)
+#define SUPERH_CPU(obj) \
+ OBJECT_CHECK(SuperHCPU, (obj), TYPE_SUPERH_CPU)
+#define SUPERH_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SuperHCPUClass, (obj), TYPE_SUPERH_CPU)
+
+/**
+ * SuperHCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A SuperH CPU model.
+ */
+typedef struct SuperHCPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ void (*parent_reset)(CPUState *cpu);
+} SuperHCPUClass;
+
+/**
+ * SuperHCPU:
+ * @env: #CPUSH4State
+ *
+ * A SuperH CPU.
+ */
+typedef struct SuperHCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUSH4State env;
+} SuperHCPU;
+
+static inline SuperHCPU *sh_env_get_cpu(CPUSH4State *env)
+{
+ return SUPERH_CPU(container_of(env, SuperHCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(sh_env_get_cpu(e))
+
+
+#endif
--- /dev/null
+/*
+ * QEMU SuperH CPU
+ *
+ * Copyright (c) 2005 Samuel Tardieu
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+
+
+/* CPUClass::reset() */
+static void superh_cpu_reset(CPUState *s)
+{
+ SuperHCPU *cpu = SUPERH_CPU(s);
+ SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(cpu);
+ CPUSH4State *env = &cpu->env;
+
+ if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+ qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+ log_cpu_state(env, 0);
+ }
+
+ scc->parent_reset(s);
+
+ memset(env, 0, offsetof(CPUSH4State, breakpoints));
+ tlb_flush(env, 1);
+
+ env->pc = 0xA0000000;
+#if defined(CONFIG_USER_ONLY)
+ env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
+ set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
+#else
+ env->sr = SR_MD | SR_RB | SR_BL | SR_I3 | SR_I2 | SR_I1 | SR_I0;
+ env->fpscr = FPSCR_DN | FPSCR_RM_ZERO; /* CPU reset value according to SH4 manual */
+ set_float_rounding_mode(float_round_to_zero, &env->fp_status);
+ set_flush_to_zero(1, &env->fp_status);
+#endif
+ set_default_nan_mode(1, &env->fp_status);
+}
+
+static void superh_cpu_initfn(Object *obj)
+{
+ SuperHCPU *cpu = SUPERH_CPU(obj);
+ CPUSH4State *env = &cpu->env;
+
+ cpu_exec_init(env);
+
+ env->movcal_backup_tail = &(env->movcal_backup);
+}
+
+static void superh_cpu_class_init(ObjectClass *oc, void *data)
+{
+ CPUClass *cc = CPU_CLASS(oc);
+ SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
+
+ scc->parent_reset = cc->reset;
+ cc->reset = superh_cpu_reset;
+}
+
+static const TypeInfo superh_cpu_type_info = {
+ .name = TYPE_SUPERH_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(SuperHCPU),
+ .instance_init = superh_cpu_initfn,
+ .abstract = false,
+ .class_size = sizeof(SuperHCPUClass),
+ .class_init = superh_cpu_class_init,
+};
+
+static void superh_cpu_register_types(void)
+{
+ type_register_static(&superh_cpu_type_info);
+}
+
+type_init(superh_cpu_register_types)
memory_content **movcal_backup_tail;
} CPUSH4State;
+#include "cpu-qom.h"
+
CPUSH4State *cpu_sh4_init(const char *cpu_model);
int cpu_sh4_exec(CPUSH4State * s);
int cpu_sh4_signal_handler(int host_signum, void *pinfo,
void cpu_state_reset(CPUSH4State *env)
{
- if (qemu_loglevel_mask(CPU_LOG_RESET)) {
- qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
- log_cpu_state(env, 0);
- }
-
- memset(env, 0, offsetof(CPUSH4State, breakpoints));
- tlb_flush(env, 1);
-
- env->pc = 0xA0000000;
-#if defined(CONFIG_USER_ONLY)
- env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
- set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
-#else
- env->sr = SR_MD | SR_RB | SR_BL | SR_I3 | SR_I2 | SR_I1 | SR_I0;
- env->fpscr = FPSCR_DN | FPSCR_RM_ZERO; /* CPU reset value according to SH4 manual */
- set_float_rounding_mode(float_round_to_zero, &env->fp_status);
- set_flush_to_zero(1, &env->fp_status);
-#endif
- set_default_nan_mode(1, &env->fp_status);
+ cpu_reset(ENV_GET_CPU(env));
}
typedef struct {
CPUSH4State *cpu_sh4_init(const char *cpu_model)
{
+ SuperHCPU *cpu;
CPUSH4State *env;
const sh4_def_t *def;
def = cpu_sh4_find_by_name(cpu_model);
if (!def)
return NULL;
- env = g_malloc0(sizeof(CPUSH4State));
+ cpu = SUPERH_CPU(object_new(TYPE_SUPERH_CPU));
+ env = &cpu->env;
env->features = def->features;
- cpu_exec_init(env);
- env->movcal_backup_tail = &(env->movcal_backup);
sh4_translate_init();
env->cpu_model_str = cpu_model;
- cpu_state_reset(env);
+ cpu_reset(CPU(cpu));
cpu_register(env, def);
qemu_init_vcpu(env);
return env;
#include <unistd.h>
#include <string.h>
+#include "compiler.h"
#include "osdep.h"
#define MAX_IRQ 256
}
}
-static void qtest_sendf(QTestState *s, const char *fmt, ...)
+static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
{
va_list ap;
gchar *str;
gchar **args;
size_t i;
- qtest_sendf(s, "read 0x%" PRIx64 " 0x%x\n", addr, size);
+ qtest_sendf(s, "read 0x%" PRIx64 " 0x%zx\n", addr, size);
args = qtest_rsp(s, 2);
for (i = 0; i < size; i++) {
const uint8_t *ptr = data;
size_t i;
- qtest_sendf(s, "write 0x%" PRIx64 " 0x%x 0x", addr, size);
+ qtest_sendf(s, "write 0x%" PRIx64 " 0x%zx 0x", addr, size);
for (i = 0; i < size; i++) {
qtest_sendf(s, "%02x", ptr[i]);
}
result = self.vm.qmp('query-block-jobs')
self.assert_qmp(result, 'return', [])
+ def cancel_and_wait(self, drive='drive0'):
+ '''Cancel a block job and wait for it to finish'''
+ result = self.vm.qmp('block-job-cancel', device=drive)
+ self.assert_qmp(result, 'return', {})
+
+ cancelled = False
+ while not cancelled:
+ for event in self.vm.get_qmp_events(wait=True):
+ if event['event'] == 'BLOCK_JOB_CANCELLED':
+ self.assert_qmp(event, 'data/type', 'stream')
+ self.assert_qmp(event, 'data/device', drive)
+ cancelled = True
+
+ self.assert_no_active_streams()
+
class TestSingleDrive(ImageStreamingTestCase):
image_len = 1 * 1024 * 1024 # MB
events = self.vm.get_qmp_events(wait=False)
self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
- self.vm.qmp('block-job-cancel', device='drive0')
- self.assert_qmp(result, 'return', {})
+ self.cancel_and_wait()
- cancelled = False
- while not cancelled:
- for event in self.vm.get_qmp_events(wait=True):
- if event['event'] == 'BLOCK_JOB_CANCELLED':
- self.assert_qmp(event, 'data/type', 'stream')
- self.assert_qmp(event, 'data/device', 'drive0')
- cancelled = True
-
- self.assert_no_active_streams()
-
-# This is a short performance test which is not run by default.
-# Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_set_speed"
class TestSetSpeed(ImageStreamingTestCase):
image_len = 80 * 1024 * 1024 # MB
os.remove(test_img)
os.remove(backing_img)
- def perf_test_set_speed(self):
+ # This is a short performance test which is not run by default.
+ # Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_throughput"
+ def perf_test_throughput(self):
self.assert_no_active_streams()
result = self.vm.qmp('block-stream', device='drive0')
self.assert_qmp(result, 'return', {})
- result = self.vm.qmp('block-job-set-speed', device='drive0', value=8 * 1024 * 1024)
+ result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
self.assert_qmp(result, 'return', {})
completed = False
self.assert_no_active_streams()
+ def test_set_speed(self):
+ self.assert_no_active_streams()
+
+ result = self.vm.qmp('block-stream', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ # Default speed is 0
+ result = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(result, 'return[0]/device', 'drive0')
+ self.assert_qmp(result, 'return[0]/speed', 0)
+
+ result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
+ self.assert_qmp(result, 'return', {})
+
+ # Ensure the speed we set was accepted
+ result = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(result, 'return[0]/device', 'drive0')
+ self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
+
+ self.cancel_and_wait()
+
+ # Check setting speed in block-stream works
+ result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(result, 'return[0]/device', 'drive0')
+ self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
+
+ self.cancel_and_wait()
+
+ def test_set_speed_invalid(self):
+ self.assert_no_active_streams()
+
+ result = self.vm.qmp('block-stream', device='drive0', speed=-1)
+ self.assert_qmp(result, 'error/class', 'InvalidParameter')
+ self.assert_qmp(result, 'error/data/name', 'speed')
+
+ self.assert_no_active_streams()
+
+ result = self.vm.qmp('block-stream', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
+ self.assert_qmp(result, 'error/class', 'InvalidParameter')
+ self.assert_qmp(result, 'error/data/name', 'speed')
+
+ self.cancel_and_wait()
+
if __name__ == '__main__':
iotests.main(supported_fmts=['qcow2', 'qed'])
-...
+.....
----------------------------------------------------------------------
-Ran 3 tests
+Ran 5 tests
OK