Merge remote-tracking branch 'origin/master' into pci

Conflicts:
	hw/virtio-pci.c
This commit is contained in:
Michael S. Tsirkin 2011-06-14 17:51:11 +03:00
commit befeac45d4
283 changed files with 22871 additions and 8772 deletions

View File

@ -1,3 +1,9 @@
This file documents changes for QEMU releases 0.12 and earlier.
For changelog information for later releases, see
http://wiki.qemu.org/ChangeLog or look at the git history for
more detailed information.
version 0.12.0:
- Update to SeaBIOS 0.5.0
@ -525,7 +531,7 @@ version 0.1.5:
- ppc64 support + personality() patch (Rusty Russell)
- first Alpha CPU patches (Falk Hueffner)
- removed bfd.h dependancy
- removed bfd.h dependency
- fixed shrd, shld, idivl and divl on PowerPC.
- fixed buggy glibc PowerPC rint() function (test-i386 passes now on PowerPC).

View File

@ -56,8 +56,8 @@ M: Paul Brook <paul@codesourcery.com>
Guest CPU cores (TCG):
----------------------
Alpha
M: qemu-devel@nongnu.org
S: Orphan
M: Richard Henderson <rth@twiddle.net>
S: Maintained
F: target-alpha/
ARM

View File

@ -88,6 +88,8 @@ include $(SRC_PATH)/Makefile.objs
endif
$(common-obj-y): $(GENERATED_HEADERS)
subdir-libcacard: $(oslib-obj-y) $(trace-obj-y) qemu-malloc.o qemu-timer-common.o
$(filter %-softmmu,$(SUBDIR_RULES)): $(trace-obj-y) $(common-obj-y) subdir-libdis
$(filter %-user,$(SUBDIR_RULES)): $(GENERATED_HEADERS) $(trace-obj-y) subdir-libdis-user subdir-libuser
@ -132,14 +134,14 @@ qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o: $(GENERATED_HEADERS)
CHECK_PROG_DEPS = qemu-malloc.o $(oslib-obj-y) $(trace-obj-y)
CHECK_PROG_DEPS = qemu-malloc.o $(oslib-obj-y) $(trace-obj-y) qemu-tool.o
check-qint: check-qint.o qint.o $(CHECK_PROG_DEPS)
check-qstring: check-qstring.o qstring.o $(CHECK_PROG_DEPS)
check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(CHECK_PROG_DEPS)
check-qlist: check-qlist.o qlist.o qint.o $(CHECK_PROG_DEPS)
check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS)
check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o $(CHECK_PROG_DEPS)
check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o error.o qerror.o qemu-error.o $(CHECK_PROG_DEPS)
QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
@ -183,6 +185,7 @@ 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 \
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
mpc8544ds.dtb \
multiboot.bin linuxboot.bin \
s390-zipl.rom \
spapr-rtas.bin slof.bin

View File

@ -2,13 +2,13 @@
# QObject
qobject-obj-y = qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o
qobject-obj-y += qjson.o json-lexer.o json-streamer.o json-parser.o
qobject-obj-y += qerror.o
qobject-obj-y += qerror.o error.o
#######################################################################
# oslib-obj-y is code depending on the OS (win32 vs posix)
oslib-obj-y = osdep.o
oslib-obj-$(CONFIG_WIN32) += oslib-win32.o
oslib-obj-$(CONFIG_POSIX) += oslib-posix.o
oslib-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o
oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o
#######################################################################
# block-obj-y is code used by both qemu system emulation and qemu-img
@ -45,12 +45,14 @@ net-nested-$(CONFIG_SLIRP) += slirp.o
net-nested-$(CONFIG_VDE) += vde.o
net-obj-y += $(addprefix net/, $(net-nested-y))
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS),yy)
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
# only pull in the actual virtio-9p device if we also enabled virtio.
CONFIG_REALLY_VIRTFS=y
fsdev-nested-y = qemu-fsdev.o
else
fsdev-nested-y = qemu-fsdev-dummy.o
endif
fsdev-nested-$(CONFIG_VIRTFS) = qemu-fsdev.o
fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y))
######################################################################
@ -143,8 +145,7 @@ common-obj-y += $(addprefix ui/, $(ui-obj-y))
common-obj-$(CONFIG_VNC) += $(addprefix ui/, $(vnc-obj-y))
common-obj-y += iov.o acl.o
common-obj-$(CONFIG_POSIX) += qemu-thread-posix.o compatfd.o
common-obj-$(CONFIG_WIN32) += qemu-thread-win32.o
common-obj-$(CONFIG_POSIX) += compatfd.o
common-obj-y += notify.o event_notifier.o
common-obj-y += qemu-timer.o qemu-timer-common.o
@ -171,6 +172,7 @@ user-obj-y += cutils.o cache-utils.o
hw-obj-y =
hw-obj-y += vl.o loader.o
hw-obj-$(CONFIG_VIRTIO) += virtio.o virtio-console.o
hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
hw-obj-y += fw_cfg.o
hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
hw-obj-$(CONFIG_PCI) += msix.o msi.o
@ -194,6 +196,7 @@ hw-obj-$(CONFIG_PCSPK) += pcspk.o
hw-obj-$(CONFIG_PCKBD) += pckbd.o
hw-obj-$(CONFIG_USB_UHCI) += usb-uhci.o
hw-obj-$(CONFIG_USB_OHCI) += usb-ohci.o
hw-obj-$(CONFIG_USB_EHCI) += usb-ehci.o
hw-obj-$(CONFIG_FDC) += fdc.o
hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
@ -285,12 +288,11 @@ sound-obj-$(CONFIG_HDA) += intel-hda.o hda-audio.o
adlib.o fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
9pfs-nested-$(CONFIG_REALLY_VIRTFS) = virtio-9p-debug.o
9pfs-nested-$(CONFIG_VIRTFS) = virtio-9p.o virtio-9p-debug.o
9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o
9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
hw-obj-$(CONFIG_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
$(addprefix 9pfs/, $(9pfs-nested-y)): CFLAGS += -I$(SRC_PATH)/hw/
hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
######################################################################
@ -335,7 +337,7 @@ trace-dtrace.h: trace-dtrace.dtrace
$(call quiet-command,dtrace -o $@ -h -s $<, " GEN trace-dtrace.h")
# Normal practice is to name DTrace probe file with a '.d' extension
# but that gets picked up by QEMU's Makefile as an external dependancy
# but that gets picked up by QEMU's Makefile as an external dependency
# rule file. So we use '.dtrace' instead
trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp
trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events config-host.mak

View File

@ -71,8 +71,7 @@ all: $(PROGS) stap
# cpu emulator library
libobj-y = exec.o translate-all.o cpu-exec.o translate.o
libobj-y += tcg/tcg.o
libobj-$(CONFIG_SOFTFLOAT) += fpu/softfloat.o
libobj-$(CONFIG_NOSOFTFLOAT) += fpu/softfloat-native.o
libobj-y += fpu/softfloat.o
libobj-y += op_helper.o helper.o
ifeq ($(TARGET_BASE_ARCH), i386)
libobj-y += cpuid.o
@ -94,10 +93,10 @@ tcg/tcg.o: cpu.h
# HELPER_CFLAGS is used for all the code compiled with static register
# variables
%_helper.o cpu-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
%_helper.o cpu-exec.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
# Note: this is a workaround. The real fix is to avoid compiling
# cpu_signal_handler() in cpu-exec.c.
# cpu_signal_handler() in user-exec.c.
signal.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
#########################################################
@ -110,7 +109,7 @@ $(call set-vpath, $(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR
QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
obj-y = main.o syscall.o strace.o mmap.o signal.o thunk.o \
elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o \
qemu-malloc.o $(oslib-obj-y)
qemu-malloc.o user-exec.o $(oslib-obj-y)
obj-$(TARGET_HAS_BFLT) += flatload.o
@ -148,7 +147,7 @@ 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
gdbstub.o user-exec.o
obj-i386-y += ioport-user.o
@ -170,7 +169,7 @@ $(call set-vpath, $(SRC_PATH)/bsd-user)
QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ARCH)
obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
gdbstub.o uaccess.o
gdbstub.o uaccess.o user-exec.o
obj-i386-y += ioport-user.o
@ -191,10 +190,9 @@ obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o
# need to fix this properly
obj-$(CONFIG_NO_PCI) += pci-stub.o
obj-$(CONFIG_VIRTIO) += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
obj-y += vhost_net.o
obj-$(CONFIG_VHOST_NET) += vhost.o
obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p.o
obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
obj-y += rwhandler.o
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
obj-$(CONFIG_NO_KVM) += kvm-stub.o
@ -206,7 +204,19 @@ QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
# xen backend driver support
obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
obj-i386-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
ifeq ($(TARGET_BASE_ARCH), i386)
CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
else
CONFIG_NO_XEN = y
endif
# xen support
CONFIG_NO_XEN_MAPCACHE = $(if $(subst n,,$(CONFIG_XEN_MAPCACHE)),n,y)
obj-i386-$(CONFIG_XEN) += xen-all.o
obj-$(CONFIG_NO_XEN) += xen-stub.o
obj-i386-$(CONFIG_XEN_MAPCACHE) += xen-mapcache.o
obj-$(CONFIG_NO_XEN_MAPCACHE) += xen-mapcache-stub.o
# Inter-VM PCI shared memory
CONFIG_IVSHMEM =
@ -220,7 +230,7 @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o
# Hardware support
obj-i386-y += vga.o
obj-i386-y += mc146818rtc.o i8259.o pc.o
obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o
obj-i386-y += vmport.o
obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
obj-i386-y += debugcon.o multiboot.o
@ -364,7 +374,8 @@ obj-m68k-y += m68k-semi.o dummy_m68k.o
obj-s390x-y = s390-virtio-bus.o s390-virtio.o
obj-alpha-y = alpha_palcode.o
obj-alpha-y = i8259.o mc146818rtc.o
obj-alpha-y += vga.o cirrus_vga.o
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
@ -401,8 +412,6 @@ hmp-commands.h: $(SRC_PATH)/hmp-commands.hx
qmp-commands.h: $(SRC_PATH)/qmp-commands.hx
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
9pfs/virtio-9p.o: CFLAGS += -I$(SRC_PATH)/hw/
clean:
rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
rm -f *.d */*.d tcg/*.o ide/*.o 9pfs/*.o

View File

@ -22,19 +22,24 @@ class QMPCapabilitiesError(QMPError):
pass
class QEMUMonitorProtocol:
def __init__(self, address):
def __init__(self, address, server=False):
"""
Create a QEMUMonitorProtocol class.
@param address: QEMU address, can be either a unix socket path (string)
or a tuple in the form ( address, port ) for a TCP
connection
@note No connection is established, this is done by the connect() method
@param server: server mode listens on the socket (bool)
@raise socket.error on socket connection errors
@note No connection is established, this is done by the connect() or
accept() methods
"""
self.__events = []
self.__address = address
self.__sock = self.__get_sock()
self.__sockfile = self.__sock.makefile()
if server:
self.__sock.bind(self.__address)
self.__sock.listen(1)
def __get_sock(self):
if isinstance(self.__address, tuple):
@ -43,7 +48,18 @@ class QEMUMonitorProtocol:
family = socket.AF_UNIX
return socket.socket(family, socket.SOCK_STREAM)
def __json_read(self):
def __negotiate_capabilities(self):
self.__sockfile = self.__sock.makefile()
greeting = self.__json_read()
if greeting is None or not greeting.has_key('QMP'):
raise QMPConnectError
# Greeting seems ok, negotiate capabilities
resp = self.cmd('qmp_capabilities')
if "return" in resp:
return greeting
raise QMPCapabilitiesError
def __json_read(self, only_event=False):
while True:
data = self.__sockfile.readline()
if not data:
@ -51,7 +67,8 @@ class QEMUMonitorProtocol:
resp = json.loads(data)
if 'event' in resp:
self.__events.append(resp)
continue
if not only_event:
continue
return resp
error = socket.error
@ -66,14 +83,19 @@ class QEMUMonitorProtocol:
@raise QMPCapabilitiesError if fails to negotiate capabilities
"""
self.__sock.connect(self.__address)
greeting = self.__json_read()
if greeting is None or not greeting.has_key('QMP'):
raise QMPConnectError
# Greeting seems ok, negotiate capabilities
resp = self.cmd('qmp_capabilities')
if "return" in resp:
return greeting
raise QMPCapabilitiesError
return self.__negotiate_capabilities()
def accept(self):
"""
Await connection from QMP Monitor and perform capabilities negotiation.
@return QMP greeting dict
@raise socket.error on socket connection errors
@raise QMPConnectError if the greeting is not received
@raise QMPCapabilitiesError if fails to negotiate capabilities
"""
self.__sock, _ = self.__sock.accept()
return self.__negotiate_capabilities()
def cmd_obj(self, qmp_cmd):
"""
@ -106,9 +128,11 @@ class QEMUMonitorProtocol:
qmp_cmd['id'] = id
return self.cmd_obj(qmp_cmd)
def get_events(self):
def get_events(self, wait=False):
"""
Get a list of available QMP events.
@param wait: block until an event is available (bool)
"""
self.__sock.setblocking(0)
try:
@ -118,6 +142,8 @@ class QEMUMonitorProtocol:
# No data available
pass
self.__sock.setblocking(1)
if not self.__events and wait:
self.__json_read(only_event=True)
return self.__events
def clear_events(self):

View File

@ -238,10 +238,6 @@ extern const unsigned alpha_num_operands;
#define AXP_REG_SP 30
#define AXP_REG_ZERO 31
#define bfd_mach_alpha_ev4 0x10
#define bfd_mach_alpha_ev5 0x20
#define bfd_mach_alpha_ev6 0x30
enum bfd_reloc_code_real {
BFD_RELOC_23_PCREL_S2,
BFD_RELOC_ALPHA_HINT

View File

@ -709,6 +709,11 @@ int audio_available(void)
#endif
}
int tcg_available(void)
{
return 1;
}
int kvm_available(void)
{
#ifdef CONFIG_KVM

View File

@ -27,6 +27,7 @@ void do_smbios_option(const char *optarg);
void cpudef_init(void);
int audio_available(void);
void audio_init(qemu_irq *isa_pic, PCIBus *pci_bus);
int tcg_available(void);
int kvm_available(void);
int xen_available(void);

View File

@ -6,8 +6,6 @@
#include "audio_int.h"
#include "audio_pt_int.h"
#include <signal.h>
static void GCC_FMT_ATTR(3, 4) logerr (struct audio_pt *pt, int err,
const char *fmt, ...)
{

View File

@ -46,7 +46,7 @@ static mixeng_real inline glue (conv_, ET) (IN_T v)
#endif
#else /* !RECIPROCAL */
#ifdef SIGNED
return nv / (mixeng_real) (IN_MAX - IN_MIN);
return nv / (mixeng_real) ((mixeng_real) IN_MAX - IN_MIN);
#else
return (nv - HALF) / (mixeng_real) IN_MAX;
#endif
@ -63,7 +63,7 @@ static IN_T inline glue (clip_, ET) (mixeng_real v)
}
#ifdef SIGNED
return ENDIAN_CONVERT ((IN_T) (v * (IN_MAX - IN_MIN)));
return ENDIAN_CONVERT ((IN_T) (v * ((mixeng_real) IN_MAX - IN_MIN)));
#else
return ENDIAN_CONVERT ((IN_T) ((v * IN_MAX) + HALF));
#endif

View File

@ -32,7 +32,6 @@
#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
#include <pthread.h>
#endif
#include <signal.h>
#endif
#define AUDIO_CAP "sdl"

49
block.c
View File

@ -439,13 +439,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
bs->drv = drv;
bs->opaque = qemu_mallocz(drv->instance_size);
/*
* Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a
* write cache to the guest. We do need the fdatasync to flush
* out transactions for block allocations, and we maybe have a
* volatile write cache in our backing device to deal with.
*/
if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))
if (flags & BDRV_O_CACHE_WB)
bs->enable_write_cache = 1;
/*
@ -455,7 +449,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
/*
* Snapshots should be writeable.
* Snapshots should be writable.
*/
if (bs->is_temporary) {
open_flags |= BDRV_O_RDWR;
@ -747,7 +741,7 @@ DeviceState *bdrv_get_attached(BlockDriverState *bs)
* Run consistency checks on an image
*
* Returns 0 if the check could be completed (it doesn't mean that the image is
* free of errors) or -errno when an internal error occured. The results of the
* free of errors) or -errno when an internal error occurred. The results of the
* check are stored in res.
*/
int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res)
@ -1305,13 +1299,6 @@ void bdrv_set_geometry_hint(BlockDriverState *bs,
bs->secs = secs;
}
void bdrv_set_type_hint(BlockDriverState *bs, int type)
{
bs->type = type;
bs->removable = ((type == BDRV_TYPE_CDROM ||
type == BDRV_TYPE_FLOPPY));
}
void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
{
bs->translation = translation;
@ -1428,11 +1415,6 @@ void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads,
}
}
int bdrv_get_type_hint(BlockDriverState *bs)
{
return bs->type;
}
int bdrv_get_translation_hint(BlockDriverState *bs)
{
return bs->translation;
@ -1704,9 +1686,8 @@ static void bdrv_print_dict(QObject *obj, void *opaque)
bs_dict = qobject_to_qdict(obj);
monitor_printf(mon, "%s: type=%s removable=%d",
monitor_printf(mon, "%s: removable=%d",
qdict_get_str(bs_dict, "device"),
qdict_get_str(bs_dict, "type"),
qdict_get_bool(bs_dict, "removable"));
if (qdict_get_bool(bs_dict, "removable")) {
@ -1747,23 +1728,10 @@ void bdrv_info(Monitor *mon, QObject **ret_data)
QTAILQ_FOREACH(bs, &bdrv_states, list) {
QObject *bs_obj;
const char *type = "unknown";
switch(bs->type) {
case BDRV_TYPE_HD:
type = "hd";
break;
case BDRV_TYPE_CDROM:
type = "cdrom";
break;
case BDRV_TYPE_FLOPPY:
type = "floppy";
break;
}
bs_obj = qobject_from_jsonf("{ 'device': %s, 'type': %s, "
bs_obj = qobject_from_jsonf("{ 'device': %s, 'type': 'unknown', "
"'removable': %i, 'locked': %i }",
bs->device_name, type, bs->removable,
bs->device_name, bs->removable,
bs->locked);
if (bs->drv) {
@ -2913,7 +2881,7 @@ int bdrv_img_create(const char *filename, const char *fmt,
char *options, uint64_t img_size, int flags)
{
QEMUOptionParameter *param = NULL, *create_options = NULL;
QEMUOptionParameter *backing_fmt, *backing_file;
QEMUOptionParameter *backing_fmt, *backing_file, *size;
BlockDriverState *bs = NULL;
BlockDriver *drv, *proto_drv;
BlockDriver *backing_drv = NULL;
@ -2996,7 +2964,8 @@ int bdrv_img_create(const char *filename, const char *fmt,
// The size for the image must always be specified, with one exception:
// If we are using a backing file, we can obtain the size from there
if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) {
size = get_option_parameter(param, BLOCK_OPT_SIZE);
if (size && size->value.n == -1) {
if (backing_file && backing_file->value.s) {
uint64_t size;
char buf[32];

View File

@ -152,9 +152,6 @@ int bdrv_has_zero_init(BlockDriverState *bs);
int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
int *pnum);
#define BDRV_TYPE_HD 0
#define BDRV_TYPE_CDROM 1
#define BDRV_TYPE_FLOPPY 2
#define BIOS_ATA_TRANSLATION_AUTO 0
#define BIOS_ATA_TRANSLATION_NONE 1
#define BIOS_ATA_TRANSLATION_LBA 2
@ -163,7 +160,6 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
void bdrv_set_geometry_hint(BlockDriverState *bs,
int cyls, int heads, int secs);
void bdrv_set_type_hint(BlockDriverState *bs, int type);
void bdrv_set_translation_hint(BlockDriverState *bs, int translation);
void bdrv_get_geometry_hint(BlockDriverState *bs,
int *pcyls, int *pheads, int *psecs);
@ -177,7 +173,6 @@ typedef enum FDriveType {
void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads,
int *max_track, int *last_sect,
FDriveType drive_in, FDriveType *drive);
int bdrv_get_type_hint(BlockDriverState *bs);
int bdrv_get_translation_hint(BlockDriverState *bs);
void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error,
BlockErrorAction on_write_error);

View File

@ -70,7 +70,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size, bool exact_size)
ret = qcow2_cache_flush(bs, s->refcount_block_cache);
if (ret < 0) {
return ret;
goto fail;
}
BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE);

View File

@ -1063,7 +1063,7 @@ fail:
* Checks an image for refcount consistency.
*
* Returns 0 if no errors are found, the number of errors in case the image is
* detected as corrupted, and -errno when an internal error occured.
* detected as corrupted, and -errno when an internal error occurred.
*/
int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res)
{
@ -1086,7 +1086,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res)
ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters,
s->l1_table_offset, s->l1_size, 1);
if (ret < 0) {
return ret;
goto fail;
}
/* snapshots */
@ -1095,7 +1095,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res)
ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters,
sn->l1_table_offset, sn->l1_size, 0);
if (ret < 0) {
return ret;
goto fail;
}
}
inc_refcounts(bs, res, refcount_table, nb_clusters,
@ -1159,8 +1159,11 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res)
}
}
ret = 0;
fail:
qemu_free(refcount_table);
return 0;
return ret;
}

View File

@ -229,7 +229,7 @@ static int qcow2_open(BlockDriverState *bs, int flags)
}
/* alloc L2 table/refcount block cache */
writethrough = ((flags & BDRV_O_CACHE_MASK) == 0);
writethrough = ((flags & BDRV_O_CACHE_WB) == 0);
s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE, writethrough);
s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE,
writethrough);
@ -1036,7 +1036,7 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options)
const char *backing_fmt = NULL;
uint64_t sectors = 0;
int flags = 0;
size_t cluster_size = 65536;
size_t cluster_size = DEFAULT_CLUSTER_SIZE;
int prealloc = 0;
/* Read out options */
@ -1343,7 +1343,8 @@ static QEMUOptionParameter qcow2_create_options[] = {
{
.name = BLOCK_OPT_CLUSTER_SIZE,
.type = OPT_SIZE,
.help = "qcow2 cluster size"
.help = "qcow2 cluster size",
.value = { .n = DEFAULT_CLUSTER_SIZE },
},
{
.name = BLOCK_OPT_PREALLOC,

View File

@ -54,6 +54,8 @@
/* Must be at least 4 to cover all cases of refcount table growth */
#define REFCOUNT_CACHE_SIZE 4
#define DEFAULT_CLUSTER_SIZE 65536
typedef struct QCowHeader {
uint32_t magic;
uint32_t version;

View File

@ -12,6 +12,7 @@
*
*/
#include "qemu-timer.h"
#include "trace.h"
#include "qed.h"
#include "qerror.h"
@ -291,6 +292,88 @@ static CachedL2Table *qed_new_l2_table(BDRVQEDState *s)
static void qed_aio_next_io(void *opaque, int ret);
static void qed_plug_allocating_write_reqs(BDRVQEDState *s)
{
assert(!s->allocating_write_reqs_plugged);
s->allocating_write_reqs_plugged = true;
}
static void qed_unplug_allocating_write_reqs(BDRVQEDState *s)
{
QEDAIOCB *acb;
assert(s->allocating_write_reqs_plugged);
s->allocating_write_reqs_plugged = false;
acb = QSIMPLEQ_FIRST(&s->allocating_write_reqs);
if (acb) {
qed_aio_next_io(acb, 0);
}
}
static void qed_finish_clear_need_check(void *opaque, int ret)
{
/* Do nothing */
}
static void qed_flush_after_clear_need_check(void *opaque, int ret)
{
BDRVQEDState *s = opaque;
bdrv_aio_flush(s->bs, qed_finish_clear_need_check, s);
/* No need to wait until flush completes */
qed_unplug_allocating_write_reqs(s);
}
static void qed_clear_need_check(void *opaque, int ret)
{
BDRVQEDState *s = opaque;
if (ret) {
qed_unplug_allocating_write_reqs(s);
return;
}
s->header.features &= ~QED_F_NEED_CHECK;
qed_write_header(s, qed_flush_after_clear_need_check, s);
}
static void qed_need_check_timer_cb(void *opaque)
{
BDRVQEDState *s = opaque;
/* The timer should only fire when allocating writes have drained */
assert(!QSIMPLEQ_FIRST(&s->allocating_write_reqs));
trace_qed_need_check_timer_cb(s);
qed_plug_allocating_write_reqs(s);
/* Ensure writes are on disk before clearing flag */
bdrv_aio_flush(s->bs, qed_clear_need_check, s);
}
static void qed_start_need_check_timer(BDRVQEDState *s)
{
trace_qed_start_need_check_timer(s);
/* Use vm_clock so we don't alter the image file while suspended for
* migration.
*/
qemu_mod_timer(s->need_check_timer, qemu_get_clock_ns(vm_clock) +
get_ticks_per_sec() * QED_NEED_CHECK_TIMEOUT);
}
/* It's okay to call this multiple times or when no timer is started */
static void qed_cancel_need_check_timer(BDRVQEDState *s)
{
trace_qed_cancel_need_check_timer(s);
qemu_del_timer(s->need_check_timer);
}
static int bdrv_qed_open(BlockDriverState *bs, int flags)
{
BDRVQEDState *s = bs->opaque;
@ -406,7 +489,10 @@ static int bdrv_qed_open(BlockDriverState *bs, int flags)
BdrvCheckResult result = {0};
ret = qed_check(s, &result, true);
if (!ret && !result.corruptions && !result.check_errors) {
if (ret) {
goto out;
}
if (!result.corruptions && !result.check_errors) {
/* Ensure fixes reach storage before clearing check bit */
bdrv_flush(s->bs);
@ -416,6 +502,9 @@ static int bdrv_qed_open(BlockDriverState *bs, int flags)
}
}
s->need_check_timer = qemu_new_timer_ns(vm_clock,
qed_need_check_timer_cb, s);
out:
if (ret) {
qed_free_l2_cache(&s->l2_cache);
@ -428,6 +517,9 @@ static void bdrv_qed_close(BlockDriverState *bs)
{
BDRVQEDState *s = bs->opaque;
qed_cancel_need_check_timer(s);
qemu_free_timer(s->need_check_timer);
/* Ensure writes reach stable storage */
bdrv_flush(bs->file);
@ -809,6 +901,8 @@ static void qed_aio_complete(QEDAIOCB *acb, int ret)
acb = QSIMPLEQ_FIRST(&s->allocating_write_reqs);
if (acb) {
qed_aio_next_io(acb, 0);
} else if (s->header.features & QED_F_NEED_CHECK) {
qed_start_need_check_timer(s);
}
}
}
@ -1014,11 +1108,17 @@ static void qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
{
BDRVQEDState *s = acb_to_s(acb);
/* Cancel timer when the first allocating request comes in */
if (QSIMPLEQ_EMPTY(&s->allocating_write_reqs)) {
qed_cancel_need_check_timer(s);
}
/* Freeze this request if another allocating write is in progress */
if (acb != QSIMPLEQ_FIRST(&s->allocating_write_reqs)) {
QSIMPLEQ_INSERT_TAIL(&s->allocating_write_reqs, acb, next);
}
if (acb != QSIMPLEQ_FIRST(&s->allocating_write_reqs)) {
if (acb != QSIMPLEQ_FIRST(&s->allocating_write_reqs) ||
s->allocating_write_reqs_plugged) {
return; /* wait for existing request to finish */
}
@ -1233,7 +1333,27 @@ static BlockDriverAIOCB *bdrv_qed_aio_flush(BlockDriverState *bs,
static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset)
{
return -ENOTSUP;
BDRVQEDState *s = bs->opaque;
uint64_t old_image_size;
int ret;
if (!qed_is_image_size_valid(offset, s->header.cluster_size,
s->header.table_size)) {
return -EINVAL;
}
/* Shrinking is currently not supported */
if ((uint64_t)offset < s->header.image_size) {
return -ENOTSUP;
}
old_image_size = s->header.image_size;
s->header.image_size = offset;
ret = qed_write_header_sync(s);
if (ret < 0) {
s->header.image_size = old_image_size;
}
return ret;
}
static int64_t bdrv_qed_getlength(BlockDriverState *bs)
@ -1344,7 +1464,8 @@ static QEMUOptionParameter qed_create_options[] = {
}, {
.name = BLOCK_OPT_CLUSTER_SIZE,
.type = OPT_SIZE,
.help = "Cluster size (in bytes)"
.help = "Cluster size (in bytes)",
.value = { .n = QED_DEFAULT_CLUSTER_SIZE },
}, {
.name = BLOCK_OPT_TABLE_SIZE,
.type = OPT_SIZE,

View File

@ -78,6 +78,9 @@ enum {
QED_MIN_TABLE_SIZE = 1, /* in clusters */
QED_MAX_TABLE_SIZE = 16,
QED_DEFAULT_TABLE_SIZE = 4,
/* Delay to flush and clean image after last allocating write completes */
QED_NEED_CHECK_TIMEOUT = 5, /* in seconds */
};
typedef struct {
@ -157,6 +160,10 @@ typedef struct {
/* Allocating write request queue */
QSIMPLEQ_HEAD(, QEDAIOCB) allocating_write_reqs;
bool allocating_write_reqs_plugged;
/* Periodic flush and clear need check flag */
QEMUTimer *need_check_timer;
} BDRVQEDState;
enum {

View File

@ -43,7 +43,6 @@
#ifdef __sun__
#define _POSIX_PTHREAD_SEMANTICS 1
#include <signal.h>
#include <sys/dkio.h>
#endif
#ifdef __linux__
@ -53,7 +52,6 @@
#include <linux/fd.h>
#endif
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <signal.h>
#include <sys/disk.h>
#include <sys/cdio.h>
#endif
@ -64,6 +62,13 @@
#include <sys/dkio.h>
#endif
#ifdef __NetBSD__
#include <sys/ioctl.h>
#include <sys/disklabel.h>
#include <sys/dkio.h>
#include <sys/disk.h>
#endif
#ifdef __DragonFly__
#include <sys/ioctl.h>
#include <sys/diskslice.h>
@ -136,12 +141,55 @@ static int64_t raw_getlength(BlockDriverState *bs);
static int cdrom_reopen(BlockDriverState *bs);
#endif
#if defined(__NetBSD__)
static int raw_normalize_devicepath(const char **filename)
{
static char namebuf[PATH_MAX];
const char *dp, *fname;
struct stat sb;
fname = *filename;
dp = strrchr(fname, '/');
if (lstat(fname, &sb) < 0) {
fprintf(stderr, "%s: stat failed: %s\n",
fname, strerror(errno));
return -errno;
}
if (!S_ISBLK(sb.st_mode)) {
return 0;
}
if (dp == NULL) {
snprintf(namebuf, PATH_MAX, "r%s", fname);
} else {
snprintf(namebuf, PATH_MAX, "%.*s/r%s",
(int)(dp - fname), fname, dp + 1);
}
fprintf(stderr, "%s is a block device", fname);
*filename = namebuf;
fprintf(stderr, ", using %s\n", *filename);
return 0;
}
#else
static int raw_normalize_devicepath(const char **filename)
{
return 0;
}
#endif
static int raw_open_common(BlockDriverState *bs, const char *filename,
int bdrv_flags, int open_flags)
{
BDRVRawState *s = bs->opaque;
int fd, ret;
ret = raw_normalize_devicepath(&filename);
if (ret != 0) {
return ret;
}
s->open_flags = open_flags | O_BINARY;
s->open_flags &= ~O_ACCMODE;
if (bdrv_flags & BDRV_O_RDWR) {
@ -154,7 +202,7 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
* and O_DIRECT for no caching. */
if ((bdrv_flags & BDRV_O_NOCACHE))
s->open_flags |= O_DIRECT;
else if (!(bdrv_flags & BDRV_O_CACHE_WB))
if (!(bdrv_flags & BDRV_O_CACHE_WB))
s->open_flags |= O_DSYNC;
s->fd = -1;
@ -622,6 +670,31 @@ static int64_t raw_getlength(BlockDriverState *bs)
} else
return st.st_size;
}
#elif defined(__NetBSD__)
static int64_t raw_getlength(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
int fd = s->fd;
struct stat st;
if (fstat(fd, &st))
return -1;
if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
struct dkwedge_info dkw;
if (ioctl(fd, DIOCGWEDGEINFO, &dkw) != -1) {
return dkw.dkw_size * 512;
} else {
struct disklabel dl;
if (ioctl(fd, DIOCGDINFO, &dl))
return -1;
return (uint64_t)dl.d_secsize *
dl.d_partitions[DISKPART(st.st_rdev)].p_size;
}
} else
return st.st_size;
}
#elif defined(__sun__)
static int64_t raw_getlength(BlockDriverState *bs)
{

View File

@ -88,9 +88,9 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
}
overlapped = FILE_ATTRIBUTE_NORMAL;
if ((flags & BDRV_O_NOCACHE))
overlapped |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
else if (!(flags & BDRV_O_CACHE_WB))
if (flags & BDRV_O_NOCACHE)
overlapped |= FILE_FLAG_NO_BUFFERING;
if (!(flags & BDRV_O_CACHE_WB))
overlapped |= FILE_FLAG_WRITE_THROUGH;
s->hfile = CreateFile(filename, access_flags,
FILE_SHARE_READ, NULL,
@ -349,9 +349,9 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
create_flags = OPEN_EXISTING;
overlapped = FILE_ATTRIBUTE_NORMAL;
if ((flags & BDRV_O_NOCACHE))
overlapped |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
else if (!(flags & BDRV_O_CACHE_WB))
if (flags & BDRV_O_NOCACHE)
overlapped |= FILE_FLAG_NO_BUFFERING;
if (!(flags & BDRV_O_CACHE_WB))
overlapped |= FILE_FLAG_WRITE_THROUGH;
s->hfile = CreateFile(filename, access_flags,
FILE_SHARE_READ, NULL,

File diff suppressed because it is too large Load Diff

View File

@ -1,71 +0,0 @@
/*
* Ceph - scalable distributed file system
*
* Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software
* Foundation. See file COPYING.LIB.
*
*/
#ifndef CEPH_RBD_TYPES_H
#define CEPH_RBD_TYPES_H
/*
* rbd image 'foo' consists of objects
* foo.rbd - image metadata
* foo.00000000
* foo.00000001
* ... - data
*/
#define RBD_SUFFIX ".rbd"
#define RBD_DIRECTORY "rbd_directory"
#define RBD_INFO "rbd_info"
#define RBD_DEFAULT_OBJ_ORDER 22 /* 4MB */
#define RBD_MAX_OBJ_NAME_SIZE 96
#define RBD_MAX_BLOCK_NAME_SIZE 24
#define RBD_MAX_SEG_NAME_SIZE 128
#define RBD_COMP_NONE 0
#define RBD_CRYPT_NONE 0
#define RBD_HEADER_TEXT "<<< Rados Block Device Image >>>\n"
#define RBD_HEADER_SIGNATURE "RBD"
#define RBD_HEADER_VERSION "001.005"
struct rbd_info {
uint64_t max_id;
} __attribute__ ((packed));
struct rbd_obj_snap_ondisk {
uint64_t id;
uint64_t image_size;
} __attribute__((packed));
struct rbd_obj_header_ondisk {
char text[40];
char block_name[RBD_MAX_BLOCK_NAME_SIZE];
char signature[4];
char version[8];
struct {
uint8_t order;
uint8_t crypt_type;
uint8_t comp_type;
uint8_t unused;
} __attribute__((packed)) options;
uint64_t image_size;
uint64_t snap_seq;
uint32_t snap_count;
uint32_t reserved;
uint64_t snap_names_len;
struct rbd_obj_snap_ondisk snaps[0];
} __attribute__((packed));
#endif

View File

@ -196,7 +196,7 @@ static inline uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval)
return hval;
}
static inline int is_data_obj_writeable(SheepdogInode *inode, unsigned int idx)
static inline int is_data_obj_writable(SheepdogInode *inode, unsigned int idx)
{
return inode->vdi_id == inode->data_vdi_id[idx];
}
@ -1577,7 +1577,7 @@ static void sd_readv_writev_bh_cb(void *p)
create = 1;
} else if (acb->aiocb_type == AIOCB_WRITE_UDATA
&& !is_data_obj_writeable(inode, idx)) {
&& !is_data_obj_writable(inode, idx)) {
/* Copy-On-Write */
create = 1;
old_oid = oid;

View File

@ -87,6 +87,7 @@ void uuid_unparse(const uuid_t uu, char *out);
#define MiB (KiB * KiB)
#define SECTOR_SIZE 512
#define DEFAULT_CLUSTER_SIZE (1 * MiB)
#if defined(CONFIG_VDI_DEBUG)
#define logout(fmt, ...) \
@ -803,7 +804,7 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
int result = 0;
uint64_t bytes = 0;
uint32_t blocks;
size_t block_size = 1 * MiB;
size_t block_size = DEFAULT_CLUSTER_SIZE;
uint32_t image_type = VDI_TYPE_DYNAMIC;
VdiHeader header;
size_t i;
@ -921,7 +922,8 @@ static QEMUOptionParameter vdi_create_options[] = {
{
.name = BLOCK_OPT_CLUSTER_SIZE,
.type = OPT_SIZE,
.help = "VDI cluster (block) size"
.help = "VDI cluster (block) size",
.value = { .n = DEFAULT_CLUSTER_SIZE },
},
#endif
#if defined(CONFIG_VDI_STATIC_IMAGE)

View File

@ -716,11 +716,11 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
return -errno;
magic = cpu_to_be32(VMDK4_MAGIC);
memset(&header, 0, sizeof(header));
header.version = cpu_to_le32(1);
header.flags = cpu_to_le32(3); /* ?? */
header.capacity = cpu_to_le64(total_size);
header.granularity = cpu_to_le64(128);
header.num_gtes_per_gte = cpu_to_le32(512);
header.version = 1;
header.flags = 3; /* ?? */
header.capacity = total_size;
header.granularity = 128;
header.num_gtes_per_gte = 512;
grains = (total_size + header.granularity - 1) / header.granularity;
gt_size = ((header.num_gtes_per_gte * sizeof(uint32_t)) + 511) >> 9;
@ -736,6 +736,12 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
header.granularity - 1) / header.granularity) *
header.granularity;
/* swap endianness for all header fields */
header.version = cpu_to_le32(header.version);
header.flags = cpu_to_le32(header.flags);
header.capacity = cpu_to_le64(header.capacity);
header.granularity = cpu_to_le64(header.granularity);
header.num_gtes_per_gte = cpu_to_le32(header.num_gtes_per_gte);
header.desc_offset = cpu_to_le64(header.desc_offset);
header.desc_size = cpu_to_le64(header.desc_size);
header.rgd_offset = cpu_to_le64(header.rgd_offset);
@ -759,7 +765,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
goto exit;
}
ret = ftruncate(fd, header.grain_offset << 9);
ret = ftruncate(fd, le64_to_cpu(header.grain_offset) << 9);
if (ret < 0) {
ret = -errno;
goto exit;
@ -767,7 +773,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
/* write grain directory */
lseek(fd, le64_to_cpu(header.rgd_offset) << 9, SEEK_SET);
for (i = 0, tmp = header.rgd_offset + gd_size;
for (i = 0, tmp = le64_to_cpu(header.rgd_offset) + gd_size;
i < gt_count; i++, tmp += gt_size) {
ret = qemu_write_full(fd, &tmp, sizeof(tmp));
if (ret != sizeof(tmp)) {
@ -778,7 +784,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
/* write backup grain directory */
lseek(fd, le64_to_cpu(header.gd_offset) << 9, SEEK_SET);
for (i = 0, tmp = header.gd_offset + gd_size;
for (i = 0, tmp = le64_to_cpu(header.gd_offset) + gd_size;
i < gt_count; i++, tmp += gt_size) {
ret = qemu_write_full(fd, &tmp, sizeof(tmp));
if (ret != sizeof(tmp)) {

View File

@ -194,7 +194,6 @@ struct BlockDriverState {
/* NOTE: the following infos are only hints for real hardware
drivers. They are not used by the block driver */
int cyls, heads, secs, translation;
int type;
BlockErrorAction on_read_error, on_write_error;
char device_name[32];
unsigned long *dirty_bitmap;

View File

@ -326,7 +326,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
if (!strcmp(buf, "off") || !strcmp(buf, "none")) {
bdrv_flags |= BDRV_O_NOCACHE;
bdrv_flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB;
} else if (!strcmp(buf, "writeback")) {
bdrv_flags |= BDRV_O_CACHE_WB;
} else if (!strcmp(buf, "unsafe")) {
@ -487,7 +487,8 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
}
break;
case MEDIA_CDROM:
bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM);
bdrv_set_removable(dinfo->bdrv, 1);
dinfo->media_cd = 1;
break;
}
break;
@ -495,7 +496,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
/* FIXME: This isn't really a floppy, but it's a reasonable
approximation. */
case IF_FLOPPY:
bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY);
bdrv_set_removable(dinfo->bdrv, 1);
break;
case IF_PFLASH:
case IF_MTD:

View File

@ -33,6 +33,7 @@ struct DriveInfo {
int bus;
int unit;
int auto_del; /* see blockdev_mark_auto_del() */
int media_cd;
QemuOpts *opts;
char serial[BLOCK_SERIAL_STRLEN + 1];
QTAILQ_ENTRY(DriveInfo) next;

View File

@ -237,7 +237,7 @@ void cpu_loop(CPUX86State *env)
break;
#ifndef TARGET_ABI32
case EXCP_SYSCALL:
/* syscall from syscall intruction */
/* syscall from syscall instruction */
if (bsd_type == target_freebsd)
env->regs[R_EAX] = do_freebsd_syscall(env,
env->regs[R_EAX],

View File

@ -323,7 +323,7 @@ abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len);
abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len);
/* Functions for accessing guest memory. The tget and tput functions
read/write single values, byteswapping as neccessary. The lock_user
read/write single values, byteswapping as necessary. The lock_user
gets a pointer to a contiguous area of guest memory, but does not perform
and byteswapping. lock_user may return either a pointer to the guest
memory, or a temporary buffer. */

View File

@ -31,7 +31,6 @@
#include <sys/syscall.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <signal.h>
#include <utime.h>
#include "qemu.h"

View File

@ -29,7 +29,7 @@ static void *sigwait_compat(void *opaque)
sigset_t all;
sigfillset(&all);
sigprocmask(SIG_BLOCK, &all, NULL);
pthread_sigmask(SIG_BLOCK, &all, NULL);
while (1) {
int sig;

274
configure vendored
View File

@ -127,6 +127,7 @@ vnc_jpeg=""
vnc_png=""
vnc_thread="no"
xen=""
xen_ctrl_version=""
linux_aio=""
attr=""
vhost_net=""
@ -228,7 +229,7 @@ sdl_config="${cross_prefix}${SDL_CONFIG-sdl-config}"
# default flags for all hosts
QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS"
CFLAGS="-g $CFLAGS"
QEMU_CFLAGS="-Wall -Wundef -Wendif-labels -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS"
QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS"
QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS"
QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS"
QEMU_CFLAGS="-D_FORTIFY_SOURCE=2 $QEMU_CFLAGS"
@ -822,6 +823,75 @@ esac
[ -z "$guest_base" ] && guest_base="$host_guest_base"
default_target_list=""
# these targets are portable
if [ "$softmmu" = "yes" ] ; then
default_target_list="\
i386-softmmu \
x86_64-softmmu \
alpha-softmmu \
arm-softmmu \
cris-softmmu \
lm32-softmmu \
m68k-softmmu \
microblaze-softmmu \
microblazeel-softmmu \
mips-softmmu \
mipsel-softmmu \
mips64-softmmu \
mips64el-softmmu \
ppc-softmmu \
ppcemb-softmmu \
ppc64-softmmu \
sh4-softmmu \
sh4eb-softmmu \
sparc-softmmu \
sparc64-softmmu \
s390x-softmmu \
"
fi
# the following are Linux specific
if [ "$linux_user" = "yes" ] ; then
default_target_list="${default_target_list}\
i386-linux-user \
x86_64-linux-user \
alpha-linux-user \
arm-linux-user \
armeb-linux-user \
cris-linux-user \
m68k-linux-user \
microblaze-linux-user \
microblazeel-linux-user \
mips-linux-user \
mipsel-linux-user \
ppc-linux-user \
ppc64-linux-user \
ppc64abi32-linux-user \
sh4-linux-user \
sh4eb-linux-user \
sparc-linux-user \
sparc64-linux-user \
sparc32plus-linux-user \
unicore32-linux-user \
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}\
i386-bsd-user \
x86_64-bsd-user \
sparc-bsd-user \
sparc64-bsd-user \
"
fi
if test x"$show_help" = x"yes" ; then
cat << EOF
@ -834,7 +904,9 @@ echo " --help print this message"
echo " --prefix=PREFIX install in PREFIX [$prefix]"
echo " --interp-prefix=PREFIX where to find shared libraries, etc."
echo " use %M for cpu name [$interp_prefix]"
echo " --target-list=LIST set target list [$target_list]"
echo " --target-list=LIST set target list (default: build everything)"
echo "Available targets: $default_target_list" | \
fold -s -w 53 | sed -e 's/^/ /'
echo ""
echo "Advanced options (experts only):"
echo " --source-path=PATH path of source code [$source_path]"
@ -895,6 +967,7 @@ echo " --disable-check-utests disable check unit-tests"
echo " --enable-check-utests enable check unit-tests"
echo " --disable-bluez disable bluez stack connectivity"
echo " --enable-bluez enable bluez stack connectivity"
echo " --disable-slirp disable SLIRP userspace network connectivity"
echo " --disable-kvm disable KVM acceleration support"
echo " --enable-kvm enable KVM acceleration support"
echo " --disable-nptl disable usermode NPTL support"
@ -965,7 +1038,7 @@ fi
gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
gcc_flags="-fstack-protector-all $gcc_flags"
gcc_flags="-fstack-protector-all -Wendif-labels $gcc_flags"
cat > $TMPC << EOF
int main(void) { return 0; }
EOF
@ -1004,70 +1077,8 @@ if test "$solaris" = "yes" ; then
fi
fi
if test -z "$target_list" ; then
# these targets are portable
if [ "$softmmu" = "yes" ] ; then
target_list="\
i386-softmmu \
x86_64-softmmu \
arm-softmmu \
cris-softmmu \
lm32-softmmu \
m68k-softmmu \
microblaze-softmmu \
microblazeel-softmmu \
mips-softmmu \
mipsel-softmmu \
mips64-softmmu \
mips64el-softmmu \
ppc-softmmu \
ppcemb-softmmu \
ppc64-softmmu \
sh4-softmmu \
sh4eb-softmmu \
sparc-softmmu \
sparc64-softmmu \
"
fi
# the following are Linux specific
if [ "$linux_user" = "yes" ] ; then
target_list="${target_list}\
i386-linux-user \
x86_64-linux-user \
alpha-linux-user \
arm-linux-user \
armeb-linux-user \
cris-linux-user \
m68k-linux-user \
microblaze-linux-user \
microblazeel-linux-user \
mips-linux-user \
mipsel-linux-user \
ppc-linux-user \
ppc64-linux-user \
ppc64abi32-linux-user \
sh4-linux-user \
sh4eb-linux-user \
sparc-linux-user \
sparc64-linux-user \
sparc32plus-linux-user \
unicore32-linux-user \
"
fi
# the following are Darwin specific
if [ "$darwin_user" = "yes" ] ; then
target_list="$target_list i386-darwin-user ppc-darwin-user "
fi
# the following are BSD specific
if [ "$bsd_user" = "yes" ] ; then
target_list="${target_list}\
i386-bsd-user \
x86_64-bsd-user \
sparc-bsd-user \
sparc64-bsd-user \
"
fi
target_list="$default_target_list"
else
target_list=`echo "$target_list" | sed -e 's/,/ /g'`
fi
@ -1180,20 +1191,81 @@ fi
if test "$xen" != "no" ; then
xen_libs="-lxenstore -lxenctrl -lxenguest"
# Xen unstable
cat > $TMPC <<EOF
#include <xenctrl.h>
#include <xs.h>
int main(void) { xs_daemon_open(); xc_interface_open(); return 0; }
#include <stdint.h>
#include <xen/hvm/hvm_info_table.h>
#if !defined(HVM_MAX_VCPUS)
# error HVM_MAX_VCPUS not defined
#endif
int main(void) {
xc_interface *xc;
xs_daemon_open();
xc = xc_interface_open(0, 0, 0);
xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
xc_gnttab_open(NULL, 0);
return 0;
}
EOF
if compile_prog "" "$xen_libs" ; then
xen_ctrl_version=410
xen=yes
libs_softmmu="$xen_libs $libs_softmmu"
# Xen 4.0.0
elif (
cat > $TMPC <<EOF
#include <xenctrl.h>
#include <xs.h>
#include <stdint.h>
#include <xen/hvm/hvm_info_table.h>
#if !defined(HVM_MAX_VCPUS)
# error HVM_MAX_VCPUS not defined
#endif
int main(void) {
xs_daemon_open();
xc_interface_open();
xc_gnttab_open();
xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
return 0;
}
EOF
compile_prog "" "$xen_libs"
) ; then
xen_ctrl_version=400
xen=yes
# Xen 3.3.0, 3.4.0
elif (
cat > $TMPC <<EOF
#include <xenctrl.h>
#include <xs.h>
int main(void) {
xs_daemon_open();
xc_interface_open();
xc_gnttab_open();
xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
return 0;
}
EOF
compile_prog "" "$xen_libs"
) ; then
xen_ctrl_version=330
xen=yes
# Xen not found or unsupported
else
if test "$xen" = "yes" ; then
feature_not_found "xen"
fi
xen=no
fi
if test "$xen" = yes; then
libs_softmmu="$xen_libs $libs_softmmu"
fi
fi
##########################################
@ -1638,7 +1710,7 @@ fi
if test "$curl" != "no" ; then
cat > $TMPC << EOF
#include <curl/curl.h>
int main(void) { return curl_easy_init(); }
int main(void) { curl_easy_init(); curl_multi_setopt(0, 0, 0); return 0; }
EOF
curl_cflags=`$curlconfig --cflags 2>/dev/null`
curl_libs=`$curlconfig --libs 2>/dev/null`
@ -1771,6 +1843,21 @@ recent kvm-kmod from http://sourceforge.net/projects/kvm."
fi
fi
##########################################
# test for ppc kvm pvr setting
if test "$kvm" = "yes" && test "$cpu" = "ppc" -o "$cpu" = "ppc64"; then
cat > $TMPC <<EOF
#include <asm/kvm.h>
int main(void) { struct kvm_sregs s; s.pvr = 0; return 0; }
EOF
if compile_prog "$kvm_cflags" "" ; then
kvm_ppc_pvr=yes
else
kvm_ppc_pvr=no
fi
fi
##########################################
# test for vhost net
@ -1831,41 +1918,24 @@ fi
if test "$rbd" != "no" ; then
cat > $TMPC <<EOF
#include <stdio.h>
#include <rados/librados.h>
int main(void) { rados_initialize(0, NULL); return 0; }
EOF
rbd_libs="-lrados"
if compile_prog "" "$rbd_libs" ; then
librados_too_old=no
cat > $TMPC <<EOF
#include <stdio.h>
#include <rados/librados.h>
#ifndef CEPH_OSD_TMAP_SET
#error missing CEPH_OSD_TMAP_SET
#endif
#include <rbd/librbd.h>
int main(void) {
int (*func)(const rados_pool_t pool, uint64_t *snapid) = rados_selfmanaged_snap_create;
rados_initialize(0, NULL);
rados_t cluster;
rados_create(&cluster, NULL);
return 0;
}
EOF
if compile_prog "" "$rbd_libs" ; then
rbd=yes
libs_tools="$rbd_libs $libs_tools"
libs_softmmu="$rbd_libs $libs_softmmu"
else
rbd=no
librados_too_old=yes
fi
rbd_libs="-lrbd -lrados"
if compile_prog "" "$rbd_libs" ; then
rbd=yes
libs_tools="$rbd_libs $libs_tools"
libs_softmmu="$rbd_libs $libs_softmmu"
else
if test "$rbd" = "yes" ; then
feature_not_found "rados block device"
fi
rbd=no
fi
if test "$librados_too_old" = "yes" ; then
echo "-> Your librados version is too old - upgrade needed to have rbd support"
fi
fi
##########################################
@ -2345,7 +2415,7 @@ int main(void) { spice_server_new(); return 0; }
EOF
spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null)
spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null)
if $pkg_config --atleast-version=0.5.3 spice-server >/dev/null 2>&1 && \
if $pkg_config --atleast-version=0.6.0 spice-server >/dev/null 2>&1 && \
compile_prog "$spice_cflags" "$spice_libs" ; then
spice="yes"
libs_softmmu="$libs_softmmu $spice_libs"
@ -2540,7 +2610,7 @@ if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) -a \
"$softmmu" = yes ; then
roms="optionrom"
fi
if test "$cpu" = "ppc64" ; then
if test "$cpu" = "ppc64" -a "$targetos" != "Darwin" ; then
roms="$roms spapr-rtas"
fi
@ -2855,6 +2925,7 @@ if test "$bluez" = "yes" ; then
fi
if test "$xen" = "yes" ; then
echo "CONFIG_XEN=y" >> $config_host_mak
echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak
fi
if test "$io_thread" = "yes" ; then
echo "CONFIG_IOTHREAD=y" >> $config_host_mak
@ -3235,7 +3306,11 @@ echo "TARGET_ABI_DIR=$TARGET_ABI_DIR" >> $config_target_mak
case "$target_arch2" in
i386|x86_64)
if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
target_phys_bits=64
echo "CONFIG_XEN=y" >> $config_target_mak
if test "$cpu" = "i386" -o "$cpu" = "x86_64"; then
echo "CONFIG_XEN_MAPCACHE=y" >> $config_target_mak
fi
fi
esac
case "$target_arch2" in
@ -3257,6 +3332,9 @@ case "$target_arch2" in
if test $vhost_net = "yes" ; then
echo "CONFIG_VHOST_NET=y" >> $config_target_mak
fi
if test "$kvm_ppc_pvr" = "yes" ; then
echo "CONFIG_KVM_PPC_PVR=y" >> $config_target_mak
fi
fi
esac
if test "$target_bigendian" = "yes" ; then
@ -3291,8 +3369,6 @@ if test ! -z "$gdb_xml_files" ; then
echo "TARGET_XML_FILES=$list" >> $config_target_mak
fi
echo "CONFIG_SOFTFLOAT=y" >> $config_target_mak
if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
echo "TARGET_HAS_BFLT=y" >> $config_target_mak
fi
@ -3457,11 +3533,13 @@ done # for target in $targets
# build tree in object directory in case the source is not in the current directory
DIRS="tests tests/cris slirp audio block net pc-bios/optionrom"
DIRS="$DIRS pc-bios/spapr-rtas"
DIRS="$DIRS roms/seabios roms/vgabios"
DIRS="$DIRS fsdev ui"
FILES="Makefile tests/Makefile"
FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
FILES="$FILES pc-bios/spapr-rtas/Makefile"
FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.rom $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
FILES="$FILES pc-bios/`basename $bios_file`"

View File

@ -180,7 +180,7 @@ void vga_hw_screen_dump(const char *filename)
active_console = consoles[0];
/* There is currently no way of specifying which screen we want to dump,
so always dump the first one. */
if (consoles[0]->hw_screen_dump)
if (consoles[0] && consoles[0]->hw_screen_dump)
consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
active_console = previous_active_console;
}

View File

@ -123,8 +123,7 @@ typedef union {
endian ! */
typedef union {
float64 d;
#if defined(HOST_WORDS_BIGENDIAN) \
|| (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
#if defined(HOST_WORDS_BIGENDIAN)
struct {
uint32_t upper;
uint32_t lower;
@ -138,7 +137,6 @@ typedef union {
uint64_t ll;
} CPU_DoubleU;
#if defined(FLOATX80)
typedef union {
floatx80 d;
struct {
@ -146,9 +144,7 @@ typedef union {
uint16_t upper;
} l;
} CPU_LDoubleU;
#endif
#if defined(CONFIG_SOFTFLOAT)
typedef union {
float128 q;
#if defined(HOST_WORDS_BIGENDIAN)
@ -175,7 +171,6 @@ typedef union {
} ll;
#endif
} CPU_QuadU;
#endif
/* CPU memory access without any memory or io remapping */
@ -786,18 +781,54 @@ void QEMU_NORETURN cpu_abort(CPUState *env, const char *fmt, ...)
extern CPUState *first_cpu;
extern CPUState *cpu_single_env;
#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
#define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */
#define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */
#define CPU_INTERRUPT_SMI 0x40 /* (x86 only) SMI interrupt pending */
#define CPU_INTERRUPT_DEBUG 0x80 /* Debug event occured. */
#define CPU_INTERRUPT_VIRQ 0x100 /* virtual interrupt pending. */
#define CPU_INTERRUPT_NMI 0x200 /* NMI pending. */
#define CPU_INTERRUPT_INIT 0x400 /* INIT pending. */
#define CPU_INTERRUPT_SIPI 0x800 /* SIPI pending. */
#define CPU_INTERRUPT_MCE 0x1000 /* (x86 only) MCE pending. */
/* Flags for use in ENV->INTERRUPT_PENDING.
The numbers assigned here are non-sequential in order to preserve
binary compatibility with the vmstate dump. Bit 0 (0x0001) was
previously used for CPU_INTERRUPT_EXIT, and is cleared when loading
the vmstate dump. */
/* External hardware interrupt pending. This is typically used for
interrupts from devices. */
#define CPU_INTERRUPT_HARD 0x0002
/* Exit the current TB. This is typically used when some system-level device
makes some change to the memory mapping. E.g. the a20 line change. */
#define CPU_INTERRUPT_EXITTB 0x0004
/* Halt the CPU. */
#define CPU_INTERRUPT_HALT 0x0020
/* Debug event pending. */
#define CPU_INTERRUPT_DEBUG 0x0080
/* Several target-specific external hardware interrupts. Each target/cpu.h
should define proper names based on these defines. */
#define CPU_INTERRUPT_TGT_EXT_0 0x0008
#define CPU_INTERRUPT_TGT_EXT_1 0x0010
#define CPU_INTERRUPT_TGT_EXT_2 0x0040
#define CPU_INTERRUPT_TGT_EXT_3 0x0200
#define CPU_INTERRUPT_TGT_EXT_4 0x1000
/* Several target-specific internal interrupts. These differ from the
preceeding target-specific interrupts in that they are intended to
originate from within the cpu itself, typically in response to some
instruction being executed. These, therefore, are not masked while
single-stepping within the debugger. */
#define CPU_INTERRUPT_TGT_INT_0 0x0100
#define CPU_INTERRUPT_TGT_INT_1 0x0400
#define CPU_INTERRUPT_TGT_INT_2 0x0800
/* First unused bit: 0x2000. */
/* The set of all bits that should be masked when single-stepping. */
#define CPU_INTERRUPT_SSTEP_MASK \
(CPU_INTERRUPT_HARD \
| CPU_INTERRUPT_TGT_EXT_0 \
| CPU_INTERRUPT_TGT_EXT_1 \
| CPU_INTERRUPT_TGT_EXT_2 \
| CPU_INTERRUPT_TGT_EXT_3 \
| CPU_INTERRUPT_TGT_EXT_4)
#ifndef CONFIG_USER_ONLY
typedef void (*CPUInterruptHandler)(CPUState *, int);

View File

@ -61,12 +61,14 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
ram_addr_t size, void *host);
ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size);
void qemu_ram_free(ram_addr_t addr);
void qemu_ram_free_from_ptr(ram_addr_t addr);
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
/* This should only be used for ram local to a device. */
void *qemu_get_ram_ptr(ram_addr_t addr);
/* Same but slower, to use for migration, where the order of
* RAMBlocks must not change. */
void *qemu_safe_ram_ptr(ram_addr_t addr);
void qemu_put_ram_ptr(void *addr);
/* This should not be used by devices. */
int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);

View File

@ -23,22 +23,6 @@
#include "kvm.h"
#include "qemu-barrier.h"
#if !defined(CONFIG_SOFTMMU)
#undef EAX
#undef ECX
#undef EDX
#undef EBX
#undef ESP
#undef EBP
#undef ESI
#undef EDI
#undef EIP
#include <signal.h>
#ifdef __linux__
#include <sys/ucontext.h>
#endif
#endif
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
// Work around ugly bugs in glibc that mangle global register contents
#undef env
@ -48,7 +32,6 @@
int tb_invalidated_flag;
//#define CONFIG_DEBUG_EXEC
//#define DEBUG_SIGNAL
int qemu_cpu_has_work(CPUState *env)
{
@ -64,37 +47,17 @@ void cpu_loop_exit(void)
/* exit the current TB from a signal handler. The host registers are
restored in a state compatible with the CPU emulator
*/
#if defined(CONFIG_SOFTMMU)
void cpu_resume_from_signal(CPUState *env1, void *puc)
{
#if !defined(CONFIG_SOFTMMU)
#ifdef __linux__
struct ucontext *uc = puc;
#elif defined(__OpenBSD__)
struct sigcontext *uc = puc;
#endif
#endif
env = env1;
/* XXX: restore cpu registers saved in host registers */
#if !defined(CONFIG_SOFTMMU)
if (puc) {
/* XXX: use siglongjmp ? */
#ifdef __linux__
#ifdef __ia64
sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
#else
sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
#endif
#elif defined(__OpenBSD__)
sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
#endif
}
#endif
env->exception_index = -1;
longjmp(env->jmp_env, 1);
}
#endif
/* Execute the code without caching the generated code. An interpreter
could be used if available. */
@ -360,10 +323,7 @@ int cpu_exec(CPUState *env1)
if (unlikely(interrupt_request)) {
if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
/* Mask out external interrupts for this step. */
interrupt_request &= ~(CPU_INTERRUPT_HARD |
CPU_INTERRUPT_FIQ |
CPU_INTERRUPT_SMI |
CPU_INTERRUPT_NMI);
interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
}
if (interrupt_request & CPU_INTERRUPT_DEBUG) {
env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
@ -492,9 +452,6 @@ int cpu_exec(CPUState *env1)
next_tb = 0;
}
}
} else if (interrupt_request & CPU_INTERRUPT_TIMER) {
//do_interrupt(0, 0, 0, 0, 0);
env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
}
#elif defined(TARGET_ARM)
if (interrupt_request & CPU_INTERRUPT_FIQ
@ -509,7 +466,7 @@ int cpu_exec(CPUState *env1)
jump normally, then does the exception return when the
CPU tries to execute code at the magic address.
This will cause the magic PC value to be pushed to
the stack if an interrupt occured at the wrong time.
the stack if an interrupt occurred at the wrong time.
We avoid this by disabling interrupts when
pc contains a magic address. */
if (interrupt_request & CPU_INTERRUPT_HARD
@ -531,9 +488,36 @@ int cpu_exec(CPUState *env1)
next_tb = 0;
}
#elif defined(TARGET_ALPHA)
if (interrupt_request & CPU_INTERRUPT_HARD) {
do_interrupt(env);
next_tb = 0;
{
int idx = -1;
/* ??? This hard-codes the OSF/1 interrupt levels. */
switch (env->pal_mode ? 7 : env->ps & PS_INT_MASK) {
case 0 ... 3:
if (interrupt_request & CPU_INTERRUPT_HARD) {
idx = EXCP_DEV_INTERRUPT;
}
/* FALLTHRU */
case 4:
if (interrupt_request & CPU_INTERRUPT_TIMER) {
idx = EXCP_CLK_INTERRUPT;
}
/* FALLTHRU */
case 5:
if (interrupt_request & CPU_INTERRUPT_SMP) {
idx = EXCP_SMP_INTERRUPT;
}
/* FALLTHRU */
case 6:
if (interrupt_request & CPU_INTERRUPT_MCHK) {
idx = EXCP_MCHK;
}
}
if (idx >= 0) {
env->exception_index = idx;
env->error_code = 0;
do_interrupt(env);
next_tb = 0;
}
}
#elif defined(TARGET_CRIS)
if (interrupt_request & CPU_INTERRUPT_HARD
@ -569,7 +553,7 @@ int cpu_exec(CPUState *env1)
next_tb = 0;
}
#endif
/* Don't use the cached interupt_request value,
/* Don't use the cached interrupt_request value,
do_interrupt may have updated the EXITTB flag. */
if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
@ -709,593 +693,3 @@ int cpu_exec(CPUState *env1)
cpu_single_env = NULL;
return ret;
}
/* must only be called from the generated code as an exception can be
generated */
void tb_invalidate_page_range(target_ulong start, target_ulong end)
{
/* XXX: cannot enable it yet because it yields to MMU exception
where NIP != read address on PowerPC */
#if 0
target_ulong phys_addr;
phys_addr = get_phys_addr_code(env, start);
tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
#endif
}
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
{
CPUX86State *saved_env;
saved_env = env;
env = s;
if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
selector &= 0xffff;
cpu_x86_load_seg_cache(env, seg_reg, selector,
(selector << 4), 0xffff, 0);
} else {
helper_load_seg(seg_reg, selector);
}
env = saved_env;
}
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
{
CPUX86State *saved_env;
saved_env = env;
env = s;
helper_fsave(ptr, data32);
env = saved_env;
}
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
{
CPUX86State *saved_env;
saved_env = env;
env = s;
helper_frstor(ptr, data32);
env = saved_env;
}
#endif /* TARGET_I386 */
#if !defined(CONFIG_SOFTMMU)
#if defined(TARGET_I386)
#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
#else
#define EXCEPTION_ACTION cpu_loop_exit()
#endif
/* 'pc' is the host PC at which the exception was raised. 'address' is
the effective address of the memory exception. 'is_write' is 1 if a
write caused the exception and otherwise 0'. 'old_set' is the
signal set which should be restored */
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
int is_write, sigset_t *old_set,
void *puc)
{
TranslationBlock *tb;
int ret;
if (cpu_single_env)
env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
pc, address, is_write, *(unsigned long *)old_set);
#endif
/* XXX: locking issue */
if (is_write && page_unprotect(h2g(address), pc, puc)) {
return 1;
}
/* see if it is an MMU fault */
ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
if (ret < 0)
return 0; /* not an MMU fault */
if (ret == 0)
return 1; /* the MMU fault was handled without causing real CPU fault */
/* now we have a real cpu fault */
tb = tb_find_pc(pc);
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
cpu_restore_state(tb, env, pc);
}
/* we restore the process signal mask as the sigreturn should
do it (XXX: use sigsetjmp) */
sigprocmask(SIG_SETMASK, old_set, NULL);
EXCEPTION_ACTION;
/* never comes here */
return 1;
}
#if defined(__i386__)
#if defined(__APPLE__)
# include <sys/ucontext.h>
# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
# define ERROR_sig(context) ((context)->uc_mcontext->es.err)
# define MASK_sig(context) ((context)->uc_sigmask)
#elif defined (__NetBSD__)
# include <ucontext.h>
# define EIP_sig(context) ((context)->uc_mcontext.__gregs[_REG_EIP])
# define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
# define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
# define MASK_sig(context) ((context)->uc_sigmask)
#elif defined (__FreeBSD__) || defined(__DragonFly__)
# include <ucontext.h>
# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
# define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
# define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
# define MASK_sig(context) ((context)->uc_sigmask)
#elif defined(__OpenBSD__)
# define EIP_sig(context) ((context)->sc_eip)
# define TRAP_sig(context) ((context)->sc_trapno)
# define ERROR_sig(context) ((context)->sc_err)
# define MASK_sig(context) ((context)->sc_mask)
#else
# define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
# define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
# define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
# define MASK_sig(context) ((context)->uc_sigmask)
#endif
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
ucontext_t *uc = puc;
#elif defined(__OpenBSD__)
struct sigcontext *uc = puc;
#else
struct ucontext *uc = puc;
#endif
unsigned long pc;
int trapno;
#ifndef REG_EIP
/* for glibc 2.1 */
#define REG_EIP EIP
#define REG_ERR ERR
#define REG_TRAPNO TRAPNO
#endif
pc = EIP_sig(uc);
trapno = TRAP_sig(uc);
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
trapno == 0xe ?
(ERROR_sig(uc) >> 1) & 1 : 0,
&MASK_sig(uc), puc);
}
#elif defined(__x86_64__)
#ifdef __NetBSD__
#define PC_sig(context) _UC_MACHINE_PC(context)
#define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
#define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
#define MASK_sig(context) ((context)->uc_sigmask)
#elif defined(__OpenBSD__)
#define PC_sig(context) ((context)->sc_rip)
#define TRAP_sig(context) ((context)->sc_trapno)
#define ERROR_sig(context) ((context)->sc_err)
#define MASK_sig(context) ((context)->sc_mask)
#elif defined (__FreeBSD__) || defined(__DragonFly__)
#include <ucontext.h>
#define PC_sig(context) (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
#define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
#define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
#define MASK_sig(context) ((context)->uc_sigmask)
#else
#define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP])
#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
#define MASK_sig(context) ((context)->uc_sigmask)
#endif
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
unsigned long pc;
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
ucontext_t *uc = puc;
#elif defined(__OpenBSD__)
struct sigcontext *uc = puc;
#else
struct ucontext *uc = puc;
#endif
pc = PC_sig(uc);
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
TRAP_sig(uc) == 0xe ?
(ERROR_sig(uc) >> 1) & 1 : 0,
&MASK_sig(uc), puc);
}
#elif defined(_ARCH_PPC)
/***********************************************************************
* signal context platform-specific definitions
* From Wine
*/
#ifdef linux
/* All Registers access - only for local access */
# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
/* Gpr Registers access */
# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
# define IAR_sig(context) REG_sig(nip, context) /* Program counter */
# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
# define CTR_sig(context) REG_sig(ctr, context) /* Count register */
# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
# define LR_sig(context) REG_sig(link, context) /* Link register */
# define CR_sig(context) REG_sig(ccr, context) /* Condition register */
/* Float Registers access */
# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
/* Exception Registers access */
# define DAR_sig(context) REG_sig(dar, context)
# define DSISR_sig(context) REG_sig(dsisr, context)
# define TRAP_sig(context) REG_sig(trap, context)
#endif /* linux */
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <ucontext.h>
# define IAR_sig(context) ((context)->uc_mcontext.mc_srr0)
# define MSR_sig(context) ((context)->uc_mcontext.mc_srr1)
# define CTR_sig(context) ((context)->uc_mcontext.mc_ctr)
# define XER_sig(context) ((context)->uc_mcontext.mc_xer)
# define LR_sig(context) ((context)->uc_mcontext.mc_lr)
# define CR_sig(context) ((context)->uc_mcontext.mc_cr)
/* Exception Registers access */
# define DAR_sig(context) ((context)->uc_mcontext.mc_dar)
# define DSISR_sig(context) ((context)->uc_mcontext.mc_dsisr)
# define TRAP_sig(context) ((context)->uc_mcontext.mc_exc)
#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
#ifdef __APPLE__
# include <sys/ucontext.h>
typedef struct ucontext SIGCONTEXT;
/* All Registers access - only for local access */
# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
/* Gpr Registers access */
# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
# define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
# define CTR_sig(context) REG_sig(ctr, context)
# define XER_sig(context) REG_sig(xer, context) /* Link register */
# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
# define CR_sig(context) REG_sig(cr, context) /* Condition register */
/* Float Registers access */
# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
# define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
/* Exception Registers access */
# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
#endif /* __APPLE__ */
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
ucontext_t *uc = puc;
#else
struct ucontext *uc = puc;
#endif
unsigned long pc;
int is_write;
pc = IAR_sig(uc);
is_write = 0;
#if 0
/* ppc 4xx case */
if (DSISR_sig(uc) & 0x00800000)
is_write = 1;
#else
if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
is_write = 1;
#endif
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, &uc->uc_sigmask, puc);
}
#elif defined(__alpha__)
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
uint32_t *pc = uc->uc_mcontext.sc_pc;
uint32_t insn = *pc;
int is_write = 0;
/* XXX: need kernel patch to get write flag faster */
switch (insn >> 26) {
case 0x0d: // stw
case 0x0e: // stb
case 0x0f: // stq_u
case 0x24: // stf
case 0x25: // stg
case 0x26: // sts
case 0x27: // stt
case 0x2c: // stl
case 0x2d: // stq
case 0x2e: // stl_c
case 0x2f: // stq_c
is_write = 1;
}
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, &uc->uc_sigmask, puc);
}
#elif defined(__sparc__)
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
int is_write;
uint32_t insn;
#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
uint32_t *regs = (uint32_t *)(info + 1);
void *sigmask = (regs + 20);
/* XXX: is there a standard glibc define ? */
unsigned long pc = regs[1];
#else
#ifdef __linux__
struct sigcontext *sc = puc;
unsigned long pc = sc->sigc_regs.tpc;
void *sigmask = (void *)sc->sigc_mask;
#elif defined(__OpenBSD__)
struct sigcontext *uc = puc;
unsigned long pc = uc->sc_pc;
void *sigmask = (void *)(long)uc->sc_mask;
#endif
#endif
/* XXX: need kernel patch to get write flag faster */
is_write = 0;
insn = *(uint32_t *)pc;
if ((insn >> 30) == 3) {
switch((insn >> 19) & 0x3f) {
case 0x05: // stb
case 0x15: // stba
case 0x06: // sth
case 0x16: // stha
case 0x04: // st
case 0x14: // sta
case 0x07: // std
case 0x17: // stda
case 0x0e: // stx
case 0x1e: // stxa
case 0x24: // stf
case 0x34: // stfa
case 0x27: // stdf
case 0x37: // stdfa
case 0x26: // stqf
case 0x36: // stqfa
case 0x25: // stfsr
case 0x3c: // casa
case 0x3e: // casxa
is_write = 1;
break;
}
}
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, sigmask, NULL);
}
#elif defined(__arm__)
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc;
int is_write;
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
pc = uc->uc_mcontext.gregs[R15];
#else
pc = uc->uc_mcontext.arm_pc;
#endif
/* XXX: compute is_write */
is_write = 0;
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write,
&uc->uc_sigmask, puc);
}
#elif defined(__mc68000)
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc;
int is_write;
pc = uc->uc_mcontext.gregs[16];
/* XXX: compute is_write */
is_write = 0;
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write,
&uc->uc_sigmask, puc);
}
#elif defined(__ia64)
#ifndef __ISR_VALID
/* This ought to be in <bits/siginfo.h>... */
# define __ISR_VALID 1
#endif
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long ip;
int is_write = 0;
ip = uc->uc_mcontext.sc_ip;
switch (host_signum) {
case SIGILL:
case SIGFPE:
case SIGSEGV:
case SIGBUS:
case SIGTRAP:
if (info->si_code && (info->si_segvflags & __ISR_VALID))
/* ISR.W (write-access) is bit 33: */
is_write = (info->si_isr >> 33) & 1;
break;
default:
break;
}
return handle_cpu_signal(ip, (unsigned long)info->si_addr,
is_write,
(sigset_t *)&uc->uc_sigmask, puc);
}
#elif defined(__s390__)
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc;
uint16_t *pinsn;
int is_write = 0;
pc = uc->uc_mcontext.psw.addr;
/* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
of the normal 2 arguments. The 3rd argument contains the "int_code"
from the hardware which does in fact contain the is_write value.
The rt signal handler, as far as I can tell, does not give this value
at all. Not that we could get to it from here even if it were. */
/* ??? This is not even close to complete, since it ignores all
of the read-modify-write instructions. */
pinsn = (uint16_t *)pc;
switch (pinsn[0] >> 8) {
case 0x50: /* ST */
case 0x42: /* STC */
case 0x40: /* STH */
is_write = 1;
break;
case 0xc4: /* RIL format insns */
switch (pinsn[0] & 0xf) {
case 0xf: /* STRL */
case 0xb: /* STGRL */
case 0x7: /* STHRL */
is_write = 1;
}
break;
case 0xe3: /* RXY format insns */
switch (pinsn[2] & 0xff) {
case 0x50: /* STY */
case 0x24: /* STG */
case 0x72: /* STCY */
case 0x70: /* STHY */
case 0x8e: /* STPQ */
case 0x3f: /* STRVH */
case 0x3e: /* STRV */
case 0x2f: /* STRVG */
is_write = 1;
}
break;
}
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, &uc->uc_sigmask, puc);
}
#elif defined(__mips__)
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
greg_t pc = uc->uc_mcontext.pc;
int is_write;
/* XXX: compute is_write */
is_write = 0;
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, &uc->uc_sigmask, puc);
}
#elif defined(__hppa__)
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
struct siginfo *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
uint32_t insn = *(uint32_t *)pc;
int is_write = 0;
/* XXX: need kernel patch to get write flag faster. */
switch (insn >> 26) {
case 0x1a: /* STW */
case 0x19: /* STH */
case 0x18: /* STB */
case 0x1b: /* STWM */
is_write = 1;
break;
case 0x09: /* CSTWX, FSTWX, FSTWS */
case 0x0b: /* CSTDX, FSTDX, FSTDS */
/* Distinguish from coprocessor load ... */
is_write = (insn >> 9) & 1;
break;
case 0x03:
switch ((insn >> 6) & 15) {
case 0xa: /* STWS */
case 0x9: /* STHS */
case 0x8: /* STBS */
case 0xe: /* STWAS */
case 0xc: /* STBYS */
is_write = 1;
}
break;
}
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, &uc->uc_sigmask, puc);
}
#else
#error host CPU specific signal handler needed
#endif
#endif /* !defined(CONFIG_SOFTMMU) */

View File

@ -21,7 +21,6 @@
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/ucontext.h>
@ -32,8 +31,6 @@
#undef uc_link
#endif
#include <signal.h>
#include "qemu.h"
#include "qemu-common.h"

View File

@ -977,7 +977,7 @@ long do_unix_syscall_indirect(void *cpu_env, int num)
#elif TARGET_PPC
{
int i;
/* XXX: not really needed those regs are volatile accross calls */
/* 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];

View File

@ -0,0 +1,9 @@
# Default configuration for alpha-softmmu
include pci.mak
CONFIG_SERIAL=y
CONFIG_I8254=y
CONFIG_VGA_PCI=y
CONFIG_IDE_CORE=y
CONFIG_IDE_QDEV=y
CONFIG_VMWARE_VGA=y

View File

@ -3,6 +3,7 @@ CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO=y
CONFIG_USB_UHCI=y
CONFIG_USB_OHCI=y
CONFIG_USB_EHCI=y
CONFIG_NE2000_PCI=y
CONFIG_EEPRO100_PCI=y
CONFIG_PCNET_PCI=y

View File

@ -0,0 +1 @@
# Default configuration for s390x-linux-user

View File

@ -184,6 +184,9 @@ enum bfd_architecture
#define bfd_mach_sh5 0x50
bfd_arch_alpha, /* Dec Alpha */
#define bfd_mach_alpha 1
#define bfd_mach_alpha_ev4 0x10
#define bfd_mach_alpha_ev5 0x20
#define bfd_mach_alpha_ev6 0x30
bfd_arch_arm, /* Advanced Risc Machines ARM */
#define bfd_mach_arm_unknown 0
#define bfd_mach_arm_2 1

View File

@ -205,7 +205,7 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
disasm_info.mach = bfd_mach_sh4;
print_insn = print_insn_sh;
#elif defined(TARGET_ALPHA)
disasm_info.mach = bfd_mach_alpha;
disasm_info.mach = bfd_mach_alpha_ev6;
print_insn = print_insn_alpha;
#elif defined(TARGET_CRIS)
if (flags != 32) {

View File

@ -8,20 +8,23 @@ more buses for children. You can specify a device's parent bus with
A device typically has a device address on its parent bus. For buses
where this address can be configured, devices provide a bus-specific
property. These are
property. Examples:
bus property name value format
PCI addr %x.%x (dev.fn, .fn optional)
I2C address %u
SCSI scsi-id %u
bus property name value format
PCI addr %x.%x (dev.fn, .fn optional)
I2C address %u
SCSI scsi-id %u
IDE unit %u
HDA cad %u
virtio-serial-bus nr %u
ccid-bus slot %u
USB port %d(.%d)* (port.port...)
Example: device i440FX-pcihost is on the root bus, and provides a PCI
bus named pci.0. To put a FOO device into its slot 4, use -device
FOO,bus=/i440FX-pcihost/pci.0,addr=4. The abbreviated form bus=pci.0
also works as long as the bus name is unique.
Note: the USB device address can't be controlled at this time.
=== Block Devices ===
A QEMU block device (drive) has a host and a guest part.
@ -44,28 +47,43 @@ The new way keeps the parts separate: you create the host part with
The various old ways to define drives all boil down to the common form
-drive if=TYPE,index=IDX,bus=BUS,unit=UNIT,HOST-OPTS...
-drive if=TYPE,bus=BUS,unit=UNIT,OPTS...
TYPE, BUS and UNIT identify the controller device, which of its buses
to use, and the drive's address on that bus. Details depend on TYPE.
IDX is an alternative way to specify BUS and UNIT.
Instead of bus=BUS,unit=UNIT, you can also say index=IDX.
In the new way, this becomes something like
-drive if=none,id=DRIVE-ID,HOST-OPTS...
-device DEVNAME,drive=DRIVE-ID,DEV-OPTS...
The -device argument differs in detail for each kind of drive:
The old OPTS get split into HOST-OPTS and DEV-OPTS as follows:
* file, format, snapshot, cache, aio, readonly, rerror, werror go into
HOST-OPTS.
* cyls, head, secs and trans go into HOST-OPTS. Future work: they
should go into DEV-OPTS instead.
* serial goes into DEV-OPTS, for devices supporting serial numbers.
For other devices, it goes nowhere.
* media is special. In the old way, it selects disk vs. CD-ROM with
if=ide, if=scsi and if=xen. The new way uses DEVNAME for that.
Additionally, readonly=on goes into HOST-OPTS.
* addr is special, see if=virtio below.
The -device argument differs in detail for each type of drive:
* if=ide
-device ide-drive,drive=DRIVE-ID,bus=IDE-BUS,unit=UNIT
-device DEVNAME,drive=DRIVE-ID,bus=IDE-BUS,unit=UNIT
where IDE-BUS identifies an IDE bus, normally either ide.0 or ide.1,
and UNIT is either 0 or 1.
Bug: new way does not work for ide.1 unit 0 (in old terms: index=2)
unless you disable the default CD-ROM with -nodefaults.
where DEVNAME is either ide-hd or ide-cd, IDE-BUS identifies an IDE
bus, normally either ide.0 or ide.1, and UNIT is either 0 or 1.
* if=scsi
@ -77,27 +95,25 @@ The -device argument differs in detail for each kind of drive:
As for all PCI devices, you can add bus=PCI-BUS,addr=DEVFN to
control the PCI device address.
This SCSI controller a single SCSI bus, named ID.0. Put a disk on
it:
This SCSI controller provides a single SCSI bus, named ID.0. Put a
disk on it:
-device scsi-disk,drive=DRIVE-ID,bus=ID.0,scsi-id=SCSI-ID,removable=RMB
-device DEVNAME,drive=DRIVE-ID,bus=ID.0,scsi-id=UNIT
The (optional) removable parameter lets you override the SCSI INQUIRY
removable (RMB) bit for non CD-ROM devices. It is ignored for CD-ROM devices
which are always removable. RMB is "on" or "off".
where DEVNAME is either scsi-hd, scsi-cd or scsi-generic.
* if=floppy
-global isa-fdc,driveA=DRIVE-ID,driveB=DRIVE-ID
-global isa-fdc.driveA=DRIVE-ID
-global isa-fdc.driveB=DRIVE-ID
This is -global instead of -device, because the floppy controller is
created automatically, and we want to configure that one, not create
a second one (which isn't possible anyway).
Omitting a drive parameter makes that drive empty.
Bug: driveA works only if you disable the default floppy drive with
-nodefaults.
Without any -global isa-fdc,... you get an empty driveA and no
driveB. You can use -nodefaults to suppress the default driveA, see
"Default Devices".
* if=virtio
@ -105,11 +121,12 @@ The -device argument differs in detail for each kind of drive:
This lets you control PCI device class and MSI-X vectors.
IOEVENTFD controls whether or not ioeventfd is used for virtqueue notify. It
can be set to on (default) or off.
IOEVENTFD controls whether or not ioeventfd is used for virtqueue
notify. It can be set to on (default) or off.
As for all PCI devices, you can add bus=PCI-BUS,addr=DEVFN to
control the PCI device address.
control the PCI device address. This replaces option addr available
with -drive if=virtio.
* if=pflash, if=mtd, if=sd, if=xen are not yet available with -device
@ -117,15 +134,20 @@ For USB devices, the old way is actually different:
-usbdevice disk:format=FMT:FILENAME
Provides much less control than -drive's HOST-OPTS... The new way
fixes that:
Provides much less control than -drive's OPTS... The new way fixes
that:
-device usb-storage,drive=DRIVE-ID,removable=RMB
The removable parameter gives control over the SCSI INQUIRY removable (RMB)
bit. USB thumbdrives usually set removable=on, while USB hard disks set
removable=off. See the if=scsi description above for details on the removable
parameter, which applies only to scsi-disk devices and not to scsi-generic.
The removable parameter gives control over the SCSI INQUIRY removable
(RMB) bit. USB thumbdrives usually set removable=on, while USB hard
disks set removable=off.
Bug: usb-storage pretends to be a block device, but it's really a SCSI
controller that can serve only a single device, which it creates
automatically. The automatic creation guesses what kind of guest part
to create from the host part, like -drive if=scsi. Host and guest
part are not cleanly separated.
=== Character Devices ===
@ -170,7 +192,9 @@ The appropriate DEVNAME depends on the machine type. For type "pc":
-device usb-braille,chardev=braille,vendorid=VID,productid=PRID
-chardev braille,id=braille
* -virtioconsole is still being worked on
* -virtioconsole becomes
-device virtio-serial-pci,class=C,vectors=V,ioeventfd=IOEVENTFD,max_ports=N
-device virtconsole,is_console=NUM,nr=NR,name=NAME
LEGACY-CHARDEV translates to -chardev HOST-OPTS... as follows:
@ -219,38 +243,29 @@ LEGACY-CHARDEV to refer to a host part defined with -chardev.
=== Network Devices ===
A QEMU network device (NIC) has a host and a guest part.
Host and guest part of network devices have always been separate.
The old ways to define NICs define host and guest part together. It
looks like this:
The old way to define the guest part looks like this:
-net nic,vlan=VLAN,macaddr=MACADDR,model=MODEL,name=ID,addr=STR,vectors=V
-net nic,netdev=NET-ID,macaddr=MACADDR,model=MODEL,name=ID,addr=STR,vectors=V
Except for USB it looks like this:
-usbdevice net:vlan=VLAN,macaddr=MACADDR,name=ID,addr=STR,vectors=V
-usbdevice net:netdev=NET-ID,macaddr=MACADDR,name=ID
The new way keeps the parts separate: you create the host part with
-netdev, and the guest device with -device, like this:
The new way is -device:
-netdev type=TYPE,id=NET-ID
-device DEVNAME,netdev=NET-ID,mac=MACADDR,DEV-OPTS...
Unlike the old way, this creates just a network device, not a VLAN.
If you really want a VLAN, create it the usual way, then create the
guest device like this:
-device DEVNAME,vlan=VLAN,mac=MACADDR,DEV-OPTS...
DEVNAME equals MODEL, except for virtio you have to name the virtio
device appropriate for the bus (virtio-net-pci for PCI), and for USB
NIC you have to use usb-net.
you have to use usb-net.
The old name=ID parameter becomes the usual id=ID with -device.
For PCI devices, you can add bus=PCI-BUS,addr=DEVFN to control the PCI
device address, as usual. The old -net nic provides parameter addr
for that, it is silently ignored when the NIC is not a PCI device.
for that, which is silently ignored when the NIC is not a PCI device.
For virtio-net-pci, you can control whether or not ioeventfd is used for
virtqueue notify by setting ioeventfd= to on or off (default).
@ -264,20 +279,25 @@ devices and ne2k_isa are.
Some PCI devices aren't available with -net nic, e.g. i82558a.
Bug: usb-net does not work, yet. Patch posted.
To connect to a VLAN instead of an ordinary host part, replace
netdev=NET-ID by vlan=VLAN.
=== Graphics Devices ===
Host and guest part of graphics devices have always been separate.
The old way to define the guest graphics device is -vga VGA.
The old way to define the guest graphics device is -vga VGA. Not all
machines support all -vga options.
The new way is -device. Map from -vga argument to -device:
The new way is -device. The mapping from -vga argument to -device
depends on the machine type. For machine "pc", it's:
std -device VGA
cirrus -device cirrus-vga
vmware -device vmware-svga
xenfb not yet available with -device
qxl -device qxl-vga
none -nodefaults
disables more than just VGA, see "Default Devices"
As for all PCI devices, you can add bus=PCI-BUS,addr=DEVFN to control
the PCI device address.
@ -285,13 +305,16 @@ the PCI device address.
-device VGA supports properties bios-offset and bios-size, but they
aren't used with machine type "pc".
Bug: -device cirrus-vga and -device vmware-svga require -nodefaults.
For machine "isapc", it's
Bug: the new way requires PCI; ISA VGA is not yet available with
-device.
std -device isa-vga
cirrus not yet available with -device
none -nodefaults
disables more than just VGA, see "Default Devices"
Bug: the new way doesn't work for machine type "pc", because it
violates obscure device initialization ordering constraints.
Bug: the new way doesn't work for machine types "pc" and "isapc",
because it violates obscure device initialization ordering
constraints.
=== Audio Devices ===
@ -308,6 +331,7 @@ Map from -soundhw sound card name to -device:
cs4231a -device cs4231a,iobase=IOADDR,irq=IRQ,dma=DMA
es1370 -device ES1370
gus -device gus,iobase=IOADDR,irq=IRQ,dma=DMA,freq=F
hda -device intel-hda,msi=MSI -device hda-duplex
sb16 -device sb16,iobase=IOADDR,irq=IRQ,dma=DMA,dma16=DMA16,version=V
adlib not yet available with -device
pcspk not yet available with -device
@ -321,9 +345,10 @@ The old way to define a virtual USB device is -usbdevice DRIVER:OPTS...
The new way is -device DEVNAME,DEV-OPTS... Details depend on DRIVER:
* ccid -device usb-ccid
* keyboard -device usb-kbd
* mouse -device usb-mouse
* tablet -device usb-tablet
* keyboard -device usb-kdb
* wacom-tablet -device usb-wacom-tablet
* host:... See "Host Device Assignment"
* disk:... See "Block Devices"
@ -353,7 +378,7 @@ The new way is
-device pci-assign,host=ADDR,iommu=IOMMU,id=ID
The old dma=none becomes iommu=0 with -device.
The old dma=none becomes iommu=off with -device.
The old way to assign a host USB device is
@ -365,4 +390,27 @@ The new way is
-device usb-host,hostbus=BUS,hostaddr=ADDR,vendorid=VID,productid=PRID
where left out or zero BUS, ADDR, VID, PRID serve as wildcard.
Omitted options match anything, just like the old way's wildcard.
=== Default Devices ===
QEMU creates a number of devices by default, depending on the machine
type.
-device DEVNAME... and global DEVNAME... suppress default devices for
some DEVNAMEs:
default device suppressing DEVNAMEs
CD-ROM ide-cd, ide-drive, scsi-cd
isa-fdc's driveA isa-fdc
parallel isa-parallel
serial isa-serial
VGA VGA, cirrus-vga, vmware-svga
virtioconsole virtio-serial-pci, virtio-serial-s390, virtio-serial
The default NIC is connected to a default part created along with it.
It is *not* suppressed by configuring a NIC with -device (you may call
that a bug). -net and -netdev suppress the default NIC.
-nodefaults suppresses all the default devices mentioned above, plus a
few other things such as default SD-Card drive and default monitor.

38
docs/usb2.txt Normal file
View File

@ -0,0 +1,38 @@
USB 2.0 Quick Start
===================
The QEMU EHCI Adapter does *not* support companion controllers. That
implies there are two completely separate USB busses: One USB 1.1 bus
driven by the UHCI controller and one USB 2.0 bus driven by the EHCI
controller. Devices must be attached to the correct controller
manually.
The '-usb' switch will make qemu create the UHCI controller as part of
the PIIX3 chipset. The USB 1.1 bus will carry the name "usb.0".
You can use the standard -device switch to add a EHCI controller to
your virtual machine. It is strongly recommended to specify an ID for
the controller so the USB 2.0 bus gets a individual name, for example
'-device usb-ehci,id=ehci". This will give you a USB 2.0 bus named
"ehci.0".
I strongly recomment to also use -device to attach usb devices because
you can specify the bus they should be attached to this way. Here is
a complete example:
qemu -M pc ${otheroptions} \
-drive if=none,id=usbstick,file=/path/to/image \
-usb \
-device usb-ehci,id=ehci \
-device usb-tablet,bus=usb.0 \
-device usb-storage,bus=ehci.0,drive=usbstick
This attaches a usb tablet to the UHCI adapter and a usb mass storage
device to the EHCI adapter.
enjoy,
Gerd
--
Gerd Hoffmann <kraxel@redhat.com>

140
error.c Normal file
View File

@ -0,0 +1,140 @@
/*
* QEMU Error Objects
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2. See
* the COPYING.LIB file in the top-level directory.
*/
#include "error.h"
#include "error_int.h"
#include "qemu-objects.h"
#include "qerror.h"
#include <assert.h>
struct Error
{
QDict *obj;
const char *fmt;
char *msg;
};
void error_set(Error **errp, const char *fmt, ...)
{
Error *err;
va_list ap;
if (errp == NULL) {
return;
}
err = qemu_mallocz(sizeof(*err));
va_start(ap, fmt);
err->obj = qobject_to_qdict(qobject_from_jsonv(fmt, &ap));
va_end(ap);
err->fmt = fmt;
*errp = err;
}
bool error_is_set(Error **errp)
{
return (errp && *errp);
}
const char *error_get_pretty(Error *err)
{
if (err->msg == NULL) {
QString *str;
str = qerror_format(err->fmt, err->obj);
err->msg = qemu_strdup(qstring_get_str(str));
QDECREF(str);
}
return err->msg;
}
const char *error_get_field(Error *err, const char *field)
{
if (strcmp(field, "class") == 0) {
return qdict_get_str(err->obj, field);
} else {
QDict *dict = qdict_get_qdict(err->obj, "data");
return qdict_get_str(dict, field);
}
}
QDict *error_get_data(Error *err)
{
QDict *data = qdict_get_qdict(err->obj, "data");
QINCREF(data);
return data;
}
void error_set_field(Error *err, const char *field, const char *value)
{
QDict *dict = qdict_get_qdict(err->obj, "data");
return qdict_put(dict, field, qstring_from_str(value));
}
void error_free(Error *err)
{
if (err) {
QDECREF(err->obj);
qemu_free(err->msg);
qemu_free(err);
}
}
bool error_is_type(Error *err, const char *fmt)
{
const char *error_class;
char *ptr;
char *end;
ptr = strstr(fmt, "'class': '");
assert(ptr != NULL);
ptr += strlen("'class': '");
end = strchr(ptr, '\'');
assert(end != NULL);
error_class = error_get_field(err, "class");
if (strlen(error_class) != end - ptr) {
return false;
}
return strncmp(ptr, error_class, end - ptr) == 0;
}
void error_propagate(Error **dst_err, Error *local_err)
{
if (dst_err) {
*dst_err = local_err;
} else if (local_err) {
error_free(local_err);
}
}
QObject *error_get_qobject(Error *err)
{
QINCREF(err->obj);
return QOBJECT(err->obj);
}
void error_set_qobject(Error **errp, QObject *obj)
{
Error *err;
if (errp == NULL) {
return;
}
err = qemu_mallocz(sizeof(*err));
err->obj = qobject_to_qdict(obj);
qobject_incref(obj);
*errp = err;
}

70
error.h Normal file
View File

@ -0,0 +1,70 @@
/*
* QEMU Error Objects
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2. See
* the COPYING.LIB file in the top-level directory.
*/
#ifndef ERROR_H
#define ERROR_H
#include <stdbool.h>
/**
* A class representing internal errors within QEMU. An error has a string
* typename and optionally a set of named string parameters.
*/
typedef struct Error Error;
/**
* Set an indirect pointer to an error given a printf-style format parameter.
* Currently, qerror.h defines these error formats. This function is not
* meant to be used outside of QEMU.
*/
void error_set(Error **err, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
/**
* Returns true if an indirect pointer to an error is pointing to a valid
* error object.
*/
bool error_is_set(Error **err);
/**
* Get a human readable representation of an error object.
*/
const char *error_get_pretty(Error *err);
/**
* Get an individual named error field.
*/
const char *error_get_field(Error *err, const char *field);
/**
* Get an individual named error field.
*/
void error_set_field(Error *err, const char *field, const char *value);
/**
* Propagate an error to an indirect pointer to an error. This function will
* always transfer ownership of the error reference and handles the case where
* dst_err is NULL correctly.
*/
void error_propagate(Error **dst_err, Error *local_err);
/**
* Free an error object.
*/
void error_free(Error *err);
/**
* Determine if an error is of a speific type (based on the qerror format).
* Non-QEMU users should get the `class' field to identify the error type.
*/
bool error_is_type(Error *err, const char *fmt);
#endif

29
error_int.h Normal file
View File

@ -0,0 +1,29 @@
/*
* QEMU Error Objects
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2. See
* the COPYING.LIB file in the top-level directory.
*/
#ifndef QEMU_ERROR_INT_H
#define QEMU_ERROR_INT_H
#include "qemu-common.h"
#include "qobject.h"
#include "qdict.h"
#include "error.h"
/**
* Internal QEMU functions for working with Error.
*
* These are used to convert QErrors to Errors
*/
QDict *error_get_data(Error *err);
QObject *error_get_qobject(Error *err);
void error_set_qobject(Error **errp, QObject *obj);
#endif

View File

@ -43,7 +43,11 @@ typedef ram_addr_t tb_page_addr_t;
typedef struct TranslationBlock TranslationBlock;
/* XXX: make safe guess about sizes */
#if (HOST_LONG_BITS == 32) && (TARGET_LONG_BITS == 64)
#define MAX_OP_PER_INSTR 128
#else
#define MAX_OP_PER_INSTR 96
#endif
#if HOST_LONG_BITS == 32
#define MAX_OPC_PARAM_PER_ARG 2
@ -95,7 +99,6 @@ void QEMU_NORETURN cpu_loop_exit(void);
int page_unprotect(target_ulong address, unsigned long pc, void *puc);
void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
int is_cpu_write_access);
void tb_invalidate_page_range(target_ulong start, target_ulong end);
void tlb_flush_page(CPUState *env, target_ulong addr);
void tlb_flush(CPUState *env, int flush_global);
#if !defined(CONFIG_USER_ONLY)
@ -322,7 +325,7 @@ static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong add
}
pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK;
if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
#if defined(TARGET_SPARC) || defined(TARGET_MIPS)
#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
do_unassigned_access(addr, 0, 1, 0, 4);
#else
cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);

128
exec.c
View File

@ -32,10 +32,10 @@
#include "hw/qdev.h"
#include "osdep.h"
#include "kvm.h"
#include "hw/xen.h"
#include "qemu-timer.h"
#if defined(CONFIG_USER_ONLY)
#include <qemu.h>
#include <signal.h>
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <sys/param.h>
#if __FreeBSD_version >= 700104
@ -51,6 +51,8 @@
#include <libutil.h>
#endif
#endif
#else /* !CONFIG_USER_ONLY */
#include "xen-mapcache.h"
#endif
//#define DEBUG_TB_INVALIDATE
@ -2085,7 +2087,7 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
/* we modify the TLB cache so that the dirty bit will be set again
when accessing the range */
start1 = (unsigned long)qemu_safe_ram_ptr(start);
/* Chek that we don't span multiple blocks - this breaks the
/* Check that we don't span multiple blocks - this breaks the
address comparisons below. */
if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
!= (end - 1) - start) {
@ -2916,6 +2918,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
}
}
new_block->offset = find_ram_offset(size);
if (host) {
new_block->host = host;
new_block->flags |= RAM_PREALLOC_MASK;
@ -2933,18 +2936,28 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
#endif
} else {
#if defined(TARGET_S390X) && defined(CONFIG_KVM)
/* XXX S390 KVM requires the topmost vma of the RAM to be < 256GB */
new_block->host = mmap((void*)0x1000000, size,
/* S390 KVM requires the topmost vma of the RAM to be smaller than
an system defined value, which is at least 256GB. Larger systems
have larger values. We put the guest between the end of data
segment (system break) and this value. We use 32GB as a base to
have enough room for the system break to grow. */
new_block->host = mmap((void*)0x800000000, size,
PROT_EXEC|PROT_READ|PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if (new_block->host == MAP_FAILED) {
fprintf(stderr, "Allocating RAM failed\n");
abort();
}
#else
new_block->host = qemu_vmalloc(size);
if (xen_mapcache_enabled()) {
xen_ram_alloc(new_block->offset, size);
} else {
new_block->host = qemu_vmalloc(size);
}
#endif
qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
}
}
new_block->offset = find_ram_offset(size);
new_block->length = size;
QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
@ -2965,6 +2978,19 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
return qemu_ram_alloc_from_ptr(dev, name, size, NULL);
}
void qemu_ram_free_from_ptr(ram_addr_t addr)
{
RAMBlock *block;
QLIST_FOREACH(block, &ram_list.blocks, next) {
if (addr == block->offset) {
QLIST_REMOVE(block, next);
qemu_free(block);
return;
}
}
}
void qemu_ram_free(ram_addr_t addr)
{
RAMBlock *block;
@ -2989,7 +3015,11 @@ void qemu_ram_free(ram_addr_t addr)
#if defined(TARGET_S390X) && defined(CONFIG_KVM)
munmap(block->host, block->length);
#else
qemu_vfree(block->host);
if (xen_mapcache_enabled()) {
qemu_invalidate_entry(block->host);
} else {
qemu_vfree(block->host);
}
#endif
}
qemu_free(block);
@ -3078,6 +3108,16 @@ void *qemu_get_ram_ptr(ram_addr_t addr)
QLIST_REMOVE(block, next);
QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
}
if (xen_mapcache_enabled()) {
/* We need to check if the requested address is in the RAM
* because we don't want to map the entire memory in QEMU.
*/
if (block->offset == 0) {
return qemu_map_cache(addr, 0, 1);
} else if (block->host == NULL) {
block->host = xen_map_block(block->offset, block->length);
}
}
return block->host + (addr - block->offset);
}
}
@ -3097,6 +3137,16 @@ void *qemu_safe_ram_ptr(ram_addr_t addr)
QLIST_FOREACH(block, &ram_list.blocks, next) {
if (addr - block->offset < block->length) {
if (xen_mapcache_enabled()) {
/* We need to check if the requested address is in the RAM
* because we don't want to map the entire memory in QEMU.
*/
if (block->offset == 0) {
return qemu_map_cache(addr, 0, 1);
} else if (block->host == NULL) {
block->host = xen_map_block(block->offset, block->length);
}
}
return block->host + (addr - block->offset);
}
}
@ -3107,17 +3157,48 @@ void *qemu_safe_ram_ptr(ram_addr_t addr)
return NULL;
}
void qemu_put_ram_ptr(void *addr)
{
trace_qemu_put_ram_ptr(addr);
if (xen_mapcache_enabled()) {
RAMBlock *block;
QLIST_FOREACH(block, &ram_list.blocks, next) {
if (addr == block->host) {
break;
}
}
if (block && block->host) {
xen_unmap_block(block->host, block->length);
block->host = NULL;
} else {
qemu_map_cache_unlock(addr);
}
}
}
int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
{
RAMBlock *block;
uint8_t *host = ptr;
QLIST_FOREACH(block, &ram_list.blocks, next) {
/* This case append when the block is not mapped. */
if (block->host == NULL) {
continue;
}
if (host - block->host < block->length) {
*ram_addr = block->offset + (host - block->host);
return 0;
}
}
if (xen_mapcache_enabled()) {
*ram_addr = qemu_ram_addr_from_mapcache(ptr);
return 0;
}
return -1;
}
@ -3139,7 +3220,7 @@ static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
#endif
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 0, 0, 0, 1);
#endif
return 0;
@ -3150,7 +3231,7 @@ static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
#endif
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 0, 0, 0, 2);
#endif
return 0;
@ -3161,7 +3242,7 @@ static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
#endif
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 0, 0, 0, 4);
#endif
return 0;
@ -3172,7 +3253,7 @@ static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
#endif
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 1, 0, 0, 1);
#endif
}
@ -3182,7 +3263,7 @@ static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
#endif
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 1, 0, 0, 2);
#endif
}
@ -3192,7 +3273,7 @@ static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
#endif
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 1, 0, 0, 4);
#endif
}
@ -3812,6 +3893,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
cpu_physical_memory_set_dirty_flags(
addr1, (0xff & ~CODE_DIRTY_FLAG));
}
qemu_put_ram_ptr(ptr);
}
} else {
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
@ -3839,9 +3921,9 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
}
} else {
/* RAM case */
ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
(addr & ~TARGET_PAGE_MASK);
memcpy(buf, ptr, l);
ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK);
memcpy(buf, ptr + (addr & ~TARGET_PAGE_MASK), l);
qemu_put_ram_ptr(ptr);
}
}
len -= l;
@ -3882,6 +3964,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
/* ROM/RAM case */
ptr = qemu_get_ram_ptr(addr1);
memcpy(ptr, buf, l);
qemu_put_ram_ptr(ptr);
}
len -= l;
buf += l;
@ -4023,6 +4106,15 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
access_len -= l;
}
}
if (xen_mapcache_enabled()) {
uint8_t *buffer1 = buffer;
uint8_t *end_buffer = buffer + len;
while (buffer1 < end_buffer) {
qemu_put_ram_ptr(buffer1);
buffer1 += TARGET_PAGE_SIZE;
}
}
return;
}
if (is_write) {

View File

@ -1,540 +0,0 @@
/* Native implementation of soft float functions. Only a single status
context is supported */
#include "softfloat.h"
#include <math.h>
#if defined(CONFIG_SOLARIS)
#include <fenv.h>
#endif
void set_float_rounding_mode(int val STATUS_PARAM)
{
STATUS(float_rounding_mode) = val;
#if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) || \
(defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
fpsetround(val);
#else
fesetround(val);
#endif
}
#ifdef FLOATX80
void set_floatx80_rounding_precision(int val STATUS_PARAM)
{
STATUS(floatx80_rounding_precision) = val;
}
#endif
#if defined(CONFIG_BSD) || \
(defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
#define lrint(d) ((int32_t)rint(d))
#define llrint(d) ((int64_t)rint(d))
#define lrintf(f) ((int32_t)rint(f))
#define llrintf(f) ((int64_t)rint(f))
#define sqrtf(f) ((float)sqrt(f))
#define remainderf(fa, fb) ((float)remainder(fa, fb))
#define rintf(f) ((float)rint(f))
#if !defined(__sparc__) && \
(defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
extern long double rintl(long double);
extern long double scalbnl(long double, int);
long long
llrintl(long double x) {
return ((long long) rintl(x));
}
long
lrintl(long double x) {
return ((long) rintl(x));
}
long double
ldexpl(long double x, int n) {
return (scalbnl(x, n));
}
#endif
#endif
#if defined(_ARCH_PPC)
/* correct (but slow) PowerPC rint() (glibc version is incorrect) */
static double qemu_rint(double x)
{
double y = 4503599627370496.0;
if (fabs(x) >= y)
return x;
if (x < 0)
y = -y;
y = (x + y) - y;
if (y == 0.0)
y = copysign(y, x);
return y;
}
#define rint qemu_rint
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE integer-to-floating-point conversion routines.
*----------------------------------------------------------------------------*/
float32 int32_to_float32(int v STATUS_PARAM)
{
return (float32)v;
}
float32 uint32_to_float32(unsigned int v STATUS_PARAM)
{
return (float32)v;
}
float64 int32_to_float64(int v STATUS_PARAM)
{
return (float64)v;
}
float64 uint32_to_float64(unsigned int v STATUS_PARAM)
{
return (float64)v;
}
#ifdef FLOATX80
floatx80 int32_to_floatx80(int v STATUS_PARAM)
{
return (floatx80)v;
}
#endif
float32 int64_to_float32( int64_t v STATUS_PARAM)
{
return (float32)v;
}
float32 uint64_to_float32( uint64_t v STATUS_PARAM)
{
return (float32)v;
}
float64 int64_to_float64( int64_t v STATUS_PARAM)
{
return (float64)v;
}
float64 uint64_to_float64( uint64_t v STATUS_PARAM)
{
return (float64)v;
}
#ifdef FLOATX80
floatx80 int64_to_floatx80( int64_t v STATUS_PARAM)
{
return (floatx80)v;
}
#endif
/* XXX: this code implements the x86 behaviour, not the IEEE one. */
#if HOST_LONG_BITS == 32
static inline int long_to_int32(long a)
{
return a;
}
#else
static inline int long_to_int32(long a)
{
if (a != (int32_t)a)
a = 0x80000000;
return a;
}
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision conversion routines.
*----------------------------------------------------------------------------*/
int float32_to_int32( float32 a STATUS_PARAM)
{
return long_to_int32(lrintf(a));
}
int float32_to_int32_round_to_zero( float32 a STATUS_PARAM)
{
return (int)a;
}
int64_t float32_to_int64( float32 a STATUS_PARAM)
{
return llrintf(a);
}
int64_t float32_to_int64_round_to_zero( float32 a STATUS_PARAM)
{
return (int64_t)a;
}
float64 float32_to_float64( float32 a STATUS_PARAM)
{
return a;
}
#ifdef FLOATX80
floatx80 float32_to_floatx80( float32 a STATUS_PARAM)
{
return a;
}
#endif
unsigned int float32_to_uint32( float32 a STATUS_PARAM)
{
int64_t v;
unsigned int res;
v = llrintf(a);
if (v < 0) {
res = 0;
} else if (v > 0xffffffff) {
res = 0xffffffff;
} else {
res = v;
}
return res;
}
unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM)
{
int64_t v;
unsigned int res;
v = (int64_t)a;
if (v < 0) {
res = 0;
} else if (v > 0xffffffff) {
res = 0xffffffff;
} else {
res = v;
}
return res;
}
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision operations.
*----------------------------------------------------------------------------*/
float32 float32_round_to_int( float32 a STATUS_PARAM)
{
return rintf(a);
}
float32 float32_rem( float32 a, float32 b STATUS_PARAM)
{
return remainderf(a, b);
}
float32 float32_sqrt( float32 a STATUS_PARAM)
{
return sqrtf(a);
}
int float32_compare( float32 a, float32 b STATUS_PARAM )
{
if (a < b) {
return float_relation_less;
} else if (a == b) {
return float_relation_equal;
} else if (a > b) {
return float_relation_greater;
} else {
return float_relation_unordered;
}
}
int float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
{
if (isless(a, b)) {
return float_relation_less;
} else if (a == b) {
return float_relation_equal;
} else if (isgreater(a, b)) {
return float_relation_greater;
} else {
return float_relation_unordered;
}
}
int float32_is_signaling_nan( float32 a1)
{
float32u u;
uint32_t a;
u.f = a1;
a = u.i;
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
}
int float32_is_quiet_nan( float32 a1 )
{
float32u u;
uint64_t a;
u.f = a1;
a = u.i;
return ( 0xFF800000 < ( a<<1 ) );
}
int float32_is_any_nan( float32 a1 )
{
float32u u;
uint32_t a;
u.f = a1;
a = u.i;
return (a & ~(1 << 31)) > 0x7f800000U;
}
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
int float64_to_int32( float64 a STATUS_PARAM)
{
return long_to_int32(lrint(a));
}
int float64_to_int32_round_to_zero( float64 a STATUS_PARAM)
{
return (int)a;
}
int64_t float64_to_int64( float64 a STATUS_PARAM)
{
return llrint(a);
}
int64_t float64_to_int64_round_to_zero( float64 a STATUS_PARAM)
{
return (int64_t)a;
}
float32 float64_to_float32( float64 a STATUS_PARAM)
{
return a;
}
#ifdef FLOATX80
floatx80 float64_to_floatx80( float64 a STATUS_PARAM)
{
return a;
}
#endif
#ifdef FLOAT128
float128 float64_to_float128( float64 a STATUS_PARAM)
{
return a;
}
#endif
unsigned int float64_to_uint32( float64 a STATUS_PARAM)
{
int64_t v;
unsigned int res;
v = llrint(a);
if (v < 0) {
res = 0;
} else if (v > 0xffffffff) {
res = 0xffffffff;
} else {
res = v;
}
return res;
}
unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM)
{
int64_t v;
unsigned int res;
v = (int64_t)a;
if (v < 0) {
res = 0;
} else if (v > 0xffffffff) {
res = 0xffffffff;
} else {
res = v;
}
return res;
}
uint64_t float64_to_uint64 (float64 a STATUS_PARAM)
{
int64_t v;
v = llrint(a + (float64)INT64_MIN);
return v - INT64_MIN;
}
uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
{
int64_t v;
v = (int64_t)(a + (float64)INT64_MIN);
return v - INT64_MIN;
}
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision operations.
*----------------------------------------------------------------------------*/
#if defined(__sun__) && \
(defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10)
static inline float64 trunc(float64 x)
{
return x < 0 ? -floor(-x) : floor(x);
}
#endif
float64 float64_trunc_to_int( float64 a STATUS_PARAM )
{
return trunc(a);
}
float64 float64_round_to_int( float64 a STATUS_PARAM )
{
return rint(a);
}
float64 float64_rem( float64 a, float64 b STATUS_PARAM)
{
return remainder(a, b);
}
float64 float64_sqrt( float64 a STATUS_PARAM)
{
return sqrt(a);
}
int float64_compare( float64 a, float64 b STATUS_PARAM )
{
if (a < b) {
return float_relation_less;
} else if (a == b) {
return float_relation_equal;
} else if (a > b) {
return float_relation_greater;
} else {
return float_relation_unordered;
}
}
int float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
{
if (isless(a, b)) {
return float_relation_less;
} else if (a == b) {
return float_relation_equal;
} else if (isgreater(a, b)) {
return float_relation_greater;
} else {
return float_relation_unordered;
}
}
int float64_is_signaling_nan( float64 a1)
{
float64u u;
uint64_t a;
u.f = a1;
a = u.i;
return
( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
&& ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
}
int float64_is_quiet_nan( float64 a1 )
{
float64u u;
uint64_t a;
u.f = a1;
a = u.i;
return ( LIT64( 0xFFF0000000000000 ) < (uint64_t) ( a<<1 ) );
}
int float64_is_any_nan( float64 a1 )
{
float64u u;
uint64_t a;
u.f = a1;
a = u.i;
return (a & ~(1ULL << 63)) > LIT64 (0x7FF0000000000000 );
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision conversion routines.
*----------------------------------------------------------------------------*/
int floatx80_to_int32( floatx80 a STATUS_PARAM)
{
return long_to_int32(lrintl(a));
}
int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM)
{
return (int)a;
}
int64_t floatx80_to_int64( floatx80 a STATUS_PARAM)
{
return llrintl(a);
}
int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM)
{
return (int64_t)a;
}
float32 floatx80_to_float32( floatx80 a STATUS_PARAM)
{
return a;
}
float64 floatx80_to_float64( floatx80 a STATUS_PARAM)
{
return a;
}
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision operations.
*----------------------------------------------------------------------------*/
floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM)
{
return rintl(a);
}
floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM)
{
return remainderl(a, b);
}
floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM)
{
return sqrtl(a);
}
int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
{
if (a < b) {
return float_relation_less;
} else if (a == b) {
return float_relation_equal;
} else if (a > b) {
return float_relation_greater;
} else {
return float_relation_unordered;
}
}
int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
{
if (isless(a, b)) {
return float_relation_less;
} else if (a == b) {
return float_relation_equal;
} else if (isgreater(a, b)) {
return float_relation_greater;
} else {
return float_relation_unordered;
}
}
int floatx80_is_signaling_nan( floatx80 a1)
{
floatx80u u;
uint64_t aLow;
u.f = a1;
aLow = u.i.low & ~ LIT64( 0x4000000000000000 );
return
( ( u.i.high & 0x7FFF ) == 0x7FFF )
&& (uint64_t) ( aLow<<1 )
&& ( u.i.low == aLow );
}
int floatx80_is_quiet_nan( floatx80 a1 )
{
floatx80u u;
u.f = a1;
return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (uint64_t) ( u.i.low<<1 );
}
int floatx80_is_any_nan( floatx80 a1 )
{
floatx80u u;
u.f = a1;
return ((u.i.high & 0x7FFF) == 0x7FFF) && ( u.i.low<<1 );
}
#endif

View File

@ -1,531 +0,0 @@
/* Native implementation of soft float functions */
#include <math.h>
#if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) \
|| defined(CONFIG_SOLARIS)
#include <ieeefp.h>
#define fabsf(f) ((float)fabs(f))
#else
#include <fenv.h>
#endif
#if defined(__OpenBSD__) || defined(__NetBSD__)
#include <sys/param.h>
#endif
/*
* Define some C99-7.12.3 classification macros and
* some C99-.12.4 for Solaris systems OS less than 10,
* or Solaris 10 systems running GCC 3.x or less.
* Solaris 10 with GCC4 does not need these macros as they
* are defined in <iso/math_c99.h> with a compiler directive
*/
#if defined(CONFIG_SOLARIS) && \
((CONFIG_SOLARIS_VERSION <= 9 ) || \
((CONFIG_SOLARIS_VERSION == 10) && (__GNUC__ < 4))) \
|| (defined(__OpenBSD__) && (OpenBSD < 200811))
/*
* C99 7.12.3 classification macros
* and
* C99 7.12.14 comparison macros
*
* ... do not work on Solaris 10 using GNU CC 3.4.x.
* Try to workaround the missing / broken C99 math macros.
*/
#if defined(__OpenBSD__)
#define unordered(x, y) (isnan(x) || isnan(y))
#endif
#ifdef __NetBSD__
#ifndef isgreater
#define isgreater(x, y) __builtin_isgreater(x, y)
#endif
#ifndef isgreaterequal
#define isgreaterequal(x, y) __builtin_isgreaterequal(x, y)
#endif
#ifndef isless
#define isless(x, y) __builtin_isless(x, y)
#endif
#ifndef islessequal
#define islessequal(x, y) __builtin_islessequal(x, y)
#endif
#ifndef isunordered
#define isunordered(x, y) __builtin_isunordered(x, y)
#endif
#endif
#define isnormal(x) (fpclass(x) >= FP_NZERO)
#define isgreater(x, y) ((!unordered(x, y)) && ((x) > (y)))
#define isgreaterequal(x, y) ((!unordered(x, y)) && ((x) >= (y)))
#define isless(x, y) ((!unordered(x, y)) && ((x) < (y)))
#define islessequal(x, y) ((!unordered(x, y)) && ((x) <= (y)))
#define isunordered(x,y) unordered(x, y)
#endif
#if defined(__sun__) && !defined(CONFIG_NEEDS_LIBSUNMATH)
#ifndef isnan
# define isnan(x) \
(sizeof (x) == sizeof (long double) ? isnan_ld (x) \
: sizeof (x) == sizeof (double) ? isnan_d (x) \
: isnan_f (x))
static inline int isnan_f (float x) { return x != x; }
static inline int isnan_d (double x) { return x != x; }
static inline int isnan_ld (long double x) { return x != x; }
#endif
#ifndef isinf
# define isinf(x) \
(sizeof (x) == sizeof (long double) ? isinf_ld (x) \
: sizeof (x) == sizeof (double) ? isinf_d (x) \
: isinf_f (x))
static inline int isinf_f (float x) { return isnan (x - x); }
static inline int isinf_d (double x) { return isnan (x - x); }
static inline int isinf_ld (long double x) { return isnan (x - x); }
#endif
#endif
typedef float float32;
typedef double float64;
#ifdef FLOATX80
typedef long double floatx80;
#endif
typedef union {
float32 f;
uint32_t i;
} float32u;
typedef union {
float64 f;
uint64_t i;
} float64u;
#ifdef FLOATX80
typedef union {
floatx80 f;
struct {
uint64_t low;
uint16_t high;
} i;
} floatx80u;
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point rounding mode.
*----------------------------------------------------------------------------*/
#if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) \
|| defined(CONFIG_SOLARIS)
#if defined(__OpenBSD__)
#define FE_RM FP_RM
#define FE_RP FP_RP
#define FE_RZ FP_RZ
#endif
enum {
float_round_nearest_even = FP_RN,
float_round_down = FP_RM,
float_round_up = FP_RP,
float_round_to_zero = FP_RZ
};
#else
enum {
float_round_nearest_even = FE_TONEAREST,
float_round_down = FE_DOWNWARD,
float_round_up = FE_UPWARD,
float_round_to_zero = FE_TOWARDZERO
};
#endif
typedef struct float_status {
int float_rounding_mode;
#ifdef FLOATX80
int floatx80_rounding_precision;
#endif
} float_status;
void set_float_rounding_mode(int val STATUS_PARAM);
#ifdef FLOATX80
void set_floatx80_rounding_precision(int val STATUS_PARAM);
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE integer-to-floating-point conversion routines.
*----------------------------------------------------------------------------*/
float32 int32_to_float32( int STATUS_PARAM);
float32 uint32_to_float32( unsigned int STATUS_PARAM);
float64 int32_to_float64( int STATUS_PARAM);
float64 uint32_to_float64( unsigned int STATUS_PARAM);
#ifdef FLOATX80
floatx80 int32_to_floatx80( int STATUS_PARAM);
#endif
#ifdef FLOAT128
float128 int32_to_float128( int STATUS_PARAM);
#endif
float32 int64_to_float32( int64_t STATUS_PARAM);
float32 uint64_to_float32( uint64_t STATUS_PARAM);
float64 int64_to_float64( int64_t STATUS_PARAM);
float64 uint64_to_float64( uint64_t v STATUS_PARAM);
#ifdef FLOATX80
floatx80 int64_to_floatx80( int64_t STATUS_PARAM);
#endif
#ifdef FLOAT128
float128 int64_to_float128( int64_t STATUS_PARAM);
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision conversion constants.
*----------------------------------------------------------------------------*/
#define float32_zero (0.0)
#define float32_one (1.0)
#define float32_ln2 (0.6931471)
#define float32_pi (3.1415926)
#define float32_half (0.5)
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision conversion routines.
*----------------------------------------------------------------------------*/
int float32_to_int32( float32 STATUS_PARAM);
int float32_to_int32_round_to_zero( float32 STATUS_PARAM);
unsigned int float32_to_uint32( float32 a STATUS_PARAM);
unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM);
int64_t float32_to_int64( float32 STATUS_PARAM);
int64_t float32_to_int64_round_to_zero( float32 STATUS_PARAM);
float64 float32_to_float64( float32 STATUS_PARAM);
#ifdef FLOATX80
floatx80 float32_to_floatx80( float32 STATUS_PARAM);
#endif
#ifdef FLOAT128
float128 float32_to_float128( float32 STATUS_PARAM);
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision operations.
*----------------------------------------------------------------------------*/
float32 float32_round_to_int( float32 STATUS_PARAM);
INLINE float32 float32_add( float32 a, float32 b STATUS_PARAM)
{
return a + b;
}
INLINE float32 float32_sub( float32 a, float32 b STATUS_PARAM)
{
return a - b;
}
INLINE float32 float32_mul( float32 a, float32 b STATUS_PARAM)
{
return a * b;
}
INLINE float32 float32_div( float32 a, float32 b STATUS_PARAM)
{
return a / b;
}
float32 float32_rem( float32, float32 STATUS_PARAM);
float32 float32_sqrt( float32 STATUS_PARAM);
INLINE int float32_eq_quiet( float32 a, float32 b STATUS_PARAM)
{
return a == b;
}
INLINE int float32_le( float32 a, float32 b STATUS_PARAM)
{
return a <= b;
}
INLINE int float32_lt( float32 a, float32 b STATUS_PARAM)
{
return a < b;
}
INLINE int float32_eq( float32 a, float32 b STATUS_PARAM)
{
return a <= b && a >= b;
}
INLINE int float32_le_quiet( float32 a, float32 b STATUS_PARAM)
{
return islessequal(a, b);
}
INLINE int float32_lt_quiet( float32 a, float32 b STATUS_PARAM)
{
return isless(a, b);
}
INLINE int float32_unordered( float32 a, float32 b STATUS_PARAM)
{
return isunordered(a, b);
}
INLINE int float32_unordered_quiet( float32 a, float32 b STATUS_PARAM)
{
return isunordered(a, b);
}
int float32_compare( float32, float32 STATUS_PARAM );
int float32_compare_quiet( float32, float32 STATUS_PARAM );
int float32_is_signaling_nan( float32 );
int float32_is_quiet_nan( float32 );
int float32_is_any_nan( float32 );
INLINE float32 float32_abs(float32 a)
{
return fabsf(a);
}
INLINE float32 float32_chs(float32 a)
{
return -a;
}
INLINE float32 float32_is_infinity(float32 a)
{
return fpclassify(a) == FP_INFINITE;
}
INLINE float32 float32_is_neg(float32 a)
{
float32u u;
u.f = a;
return u.i >> 31;
}
INLINE float32 float32_is_zero(float32 a)
{
return fpclassify(a) == FP_ZERO;
}
INLINE float32 float32_scalbn(float32 a, int n STATUS_PARAM)
{
return scalbnf(a, n);
}
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion constants.
*----------------------------------------------------------------------------*/
#define float64_zero (0.0)
#define float64_one (1.0)
#define float64_ln2 (0.693147180559945)
#define float64_pi (3.141592653589793)
#define float64_half (0.5)
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
int float64_to_int32( float64 STATUS_PARAM );
int float64_to_int32_round_to_zero( float64 STATUS_PARAM );
unsigned int float64_to_uint32( float64 STATUS_PARAM );
unsigned int float64_to_uint32_round_to_zero( float64 STATUS_PARAM );
int64_t float64_to_int64( float64 STATUS_PARAM );
int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM );
uint64_t float64_to_uint64( float64 STATUS_PARAM );
uint64_t float64_to_uint64_round_to_zero( float64 STATUS_PARAM );
float32 float64_to_float32( float64 STATUS_PARAM );
#ifdef FLOATX80
floatx80 float64_to_floatx80( float64 STATUS_PARAM );
#endif
#ifdef FLOAT128
float128 float64_to_float128( float64 STATUS_PARAM );
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision operations.
*----------------------------------------------------------------------------*/
float64 float64_round_to_int( float64 STATUS_PARAM );
float64 float64_trunc_to_int( float64 STATUS_PARAM );
INLINE float64 float64_add( float64 a, float64 b STATUS_PARAM)
{
return a + b;
}
INLINE float64 float64_sub( float64 a, float64 b STATUS_PARAM)
{
return a - b;
}
INLINE float64 float64_mul( float64 a, float64 b STATUS_PARAM)
{
return a * b;
}
INLINE float64 float64_div( float64 a, float64 b STATUS_PARAM)
{
return a / b;
}
float64 float64_rem( float64, float64 STATUS_PARAM );
float64 float64_sqrt( float64 STATUS_PARAM );
INLINE int float64_eq_quiet( float64 a, float64 b STATUS_PARAM)
{
return a == b;
}
INLINE int float64_le( float64 a, float64 b STATUS_PARAM)
{
return a <= b;
}
INLINE int float64_lt( float64 a, float64 b STATUS_PARAM)
{
return a < b;
}
INLINE int float64_eq( float64 a, float64 b STATUS_PARAM)
{
return a <= b && a >= b;
}
INLINE int float64_le_quiet( float64 a, float64 b STATUS_PARAM)
{
return islessequal(a, b);
}
INLINE int float64_lt_quiet( float64 a, float64 b STATUS_PARAM)
{
return isless(a, b);
}
INLINE int float64_unordered( float64 a, float64 b STATUS_PARAM)
{
return isunordered(a, b);
}
INLINE int float64_unordered_quiet( float64 a, float64 b STATUS_PARAM)
{
return isunordered(a, b);
}
int float64_compare( float64, float64 STATUS_PARAM );
int float64_compare_quiet( float64, float64 STATUS_PARAM );
int float64_is_signaling_nan( float64 );
int float64_is_any_nan( float64 );
int float64_is_quiet_nan( float64 );
INLINE float64 float64_abs(float64 a)
{
return fabs(a);
}
INLINE float64 float64_chs(float64 a)
{
return -a;
}
INLINE float64 float64_is_infinity(float64 a)
{
return fpclassify(a) == FP_INFINITE;
}
INLINE float64 float64_is_neg(float64 a)
{
float64u u;
u.f = a;
return u.i >> 63;
}
INLINE float64 float64_is_zero(float64 a)
{
return fpclassify(a) == FP_ZERO;
}
INLINE float64 float64_scalbn(float64 a, int n STATUS_PARAM)
{
return scalbn(a, n);
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision conversion constants.
*----------------------------------------------------------------------------*/
#define floatx80_zero (0.0L)
#define floatx80_one (1.0L)
#define floatx80_ln2 (0.69314718055994530943L)
#define floatx80_pi (3.14159265358979323851L)
#define floatx80_half (0.5L)
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision conversion routines.
*----------------------------------------------------------------------------*/
int floatx80_to_int32( floatx80 STATUS_PARAM );
int floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM );
int64_t floatx80_to_int64( floatx80 STATUS_PARAM);
int64_t floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM);
float32 floatx80_to_float32( floatx80 STATUS_PARAM );
float64 floatx80_to_float64( floatx80 STATUS_PARAM );
#ifdef FLOAT128
float128 floatx80_to_float128( floatx80 STATUS_PARAM );
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision operations.
*----------------------------------------------------------------------------*/
floatx80 floatx80_round_to_int( floatx80 STATUS_PARAM );
INLINE floatx80 floatx80_add( floatx80 a, floatx80 b STATUS_PARAM)
{
return a + b;
}
INLINE floatx80 floatx80_sub( floatx80 a, floatx80 b STATUS_PARAM)
{
return a - b;
}
INLINE floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM)
{
return a * b;
}
INLINE floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM)
{
return a / b;
}
floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
INLINE int floatx80_eq_quiet( floatx80 a, floatx80 b STATUS_PARAM)
{
return a == b;
}
INLINE int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM)
{
return a <= b;
}
INLINE int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM)
{
return a < b;
}
INLINE int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM)
{
return a <= b && a >= b;
}
INLINE int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM)
{
return islessequal(a, b);
}
INLINE int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM)
{
return isless(a, b);
}
INLINE int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM)
{
return isunordered(a, b);
}
INLINE int floatx80_unordered_quiet( floatx80 a, floatx80 b STATUS_PARAM)
{
return isunordered(a, b);
}
int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_is_signaling_nan( floatx80 );
int floatx80_is_quiet_nan( floatx80 );
int floatx80_is_any_nan( floatx80 );
INLINE floatx80 floatx80_abs(floatx80 a)
{
return fabsl(a);
}
INLINE floatx80 floatx80_chs(floatx80 a)
{
return -a;
}
INLINE floatx80 floatx80_is_infinity(floatx80 a)
{
return fpclassify(a) == FP_INFINITE;
}
INLINE floatx80 floatx80_is_neg(floatx80 a)
{
floatx80u u;
u.f = a;
return u.i.high >> 15;
}
INLINE floatx80 floatx80_is_zero(floatx80 a)
{
return fpclassify(a) == FP_ZERO;
}
INLINE floatx80 floatx80_scalbn(floatx80 a, int n STATUS_PARAM)
{
return scalbnl(a, n);
}
#endif

View File

@ -523,8 +523,6 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
}
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is a
| quiet NaN; otherwise returns 0. This slightly differs from the same
@ -681,10 +679,6 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
}
}
#endif
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
| NaN; otherwise returns 0.
@ -820,4 +814,3 @@ static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
}
}
#endif

View File

@ -64,12 +64,10 @@ void set_float_exception_flags(int val STATUS_PARAM)
STATUS(float_exception_flags) = val;
}
#ifdef FLOATX80
void set_floatx80_rounding_precision(int val STATUS_PARAM)
{
STATUS(floatx80_rounding_precision) = val;
}
#endif
/*----------------------------------------------------------------------------
| Returns the fraction bits of the half-precision floating-point value `a'.
@ -341,7 +339,10 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, uint32_t zSig STATUS
return packFloat32( zSign, 0xFF, - ( roundIncrement == 0 ));
}
if ( zExp < 0 ) {
if ( STATUS(flush_to_zero) ) return packFloat32( zSign, 0, 0 );
if (STATUS(flush_to_zero)) {
float_raise(float_flag_output_denormal STATUS_VAR);
return packFloat32(zSign, 0, 0);
}
isTiny =
( STATUS(float_detect_tininess) == float_tininess_before_rounding )
|| ( zExp < -1 )
@ -520,7 +521,10 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, uint64_t zSig STATUS
return packFloat64( zSign, 0x7FF, - ( roundIncrement == 0 ));
}
if ( zExp < 0 ) {
if ( STATUS(flush_to_zero) ) return packFloat64( zSign, 0, 0 );
if (STATUS(flush_to_zero)) {
float_raise(float_flag_output_denormal STATUS_VAR);
return packFloat64(zSign, 0, 0);
}
isTiny =
( STATUS(float_detect_tininess) == float_tininess_before_rounding )
|| ( zExp < -1 )
@ -558,8 +562,6 @@ static float64
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Returns the fraction bits of the extended double-precision floating-point
| value `a'.
@ -699,7 +701,10 @@ static floatx80
goto overflow;
}
if ( zExp <= 0 ) {
if ( STATUS(flush_to_zero) ) return packFloatx80( zSign, 0, 0 );
if (STATUS(flush_to_zero)) {
float_raise(float_flag_output_denormal STATUS_VAR);
return packFloatx80(zSign, 0, 0);
}
isTiny =
( STATUS(float_detect_tininess) == float_tininess_before_rounding )
|| ( zExp < 0 )
@ -842,10 +847,6 @@ static floatx80
}
#endif
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Returns the least-significant 64 fraction bits of the quadruple-precision
| floating-point value `a'.
@ -1030,7 +1031,10 @@ static float128
return packFloat128( zSign, 0x7FFF, 0, 0 );
}
if ( zExp < 0 ) {
if ( STATUS(flush_to_zero) ) return packFloat128( zSign, 0, 0, 0 );
if (STATUS(flush_to_zero)) {
float_raise(float_flag_output_denormal STATUS_VAR);
return packFloat128(zSign, 0, 0, 0);
}
isTiny =
( STATUS(float_detect_tininess) == float_tininess_before_rounding )
|| ( zExp < -1 )
@ -1106,8 +1110,6 @@ static float128
}
#endif
/*----------------------------------------------------------------------------
| Returns the result of converting the 32-bit two's complement integer `a'
| to the single-precision floating-point format. The conversion is performed
@ -1147,8 +1149,6 @@ float64 int32_to_float64( int32 a STATUS_PARAM )
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Returns the result of converting the 32-bit two's complement integer `a'
| to the extended double-precision floating-point format. The conversion
@ -1172,10 +1172,6 @@ floatx80 int32_to_floatx80( int32 a STATUS_PARAM )
}
#endif
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Returns the result of converting the 32-bit two's complement integer `a' to
| the quadruple-precision floating-point format. The conversion is performed
@ -1198,8 +1194,6 @@ float128 int32_to_float128( int32 a STATUS_PARAM )
}
#endif
/*----------------------------------------------------------------------------
| Returns the result of converting the 64-bit two's complement integer `a'
| to the single-precision floating-point format. The conversion is performed
@ -1279,8 +1273,6 @@ float64 uint64_to_float64( uint64 a STATUS_PARAM )
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Returns the result of converting the 64-bit two's complement integer `a'
| to the extended double-precision floating-point format. The conversion
@ -1302,10 +1294,6 @@ floatx80 int64_to_floatx80( int64 a STATUS_PARAM )
}
#endif
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Returns the result of converting the 64-bit two's complement integer `a' to
| the quadruple-precision floating-point format. The conversion is performed
@ -1339,8 +1327,6 @@ float128 int64_to_float128( int64 a STATUS_PARAM )
}
#endif
/*----------------------------------------------------------------------------
| Returns the result of converting the single-precision floating-point value
| `a' to the 32-bit two's complement integer format. The conversion is
@ -1578,8 +1564,6 @@ float64 float32_to_float64( float32 a STATUS_PARAM )
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Returns the result of converting the single-precision floating-point value
| `a' to the extended double-precision floating-point format. The conversion
@ -1610,10 +1594,6 @@ floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
}
#endif
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Returns the result of converting the single-precision floating-point value
| `a' to the double-precision floating-point format. The conversion is
@ -1644,8 +1624,6 @@ float128 float32_to_float128( float32 a STATUS_PARAM )
}
#endif
/*----------------------------------------------------------------------------
| Rounds the single-precision floating-point value `a' to an integer, and
| returns the result as a single-precision floating-point value. The
@ -1761,7 +1739,12 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
return a;
}
if ( aExp == 0 ) {
if ( STATUS(flush_to_zero) ) return packFloat32( zSign, 0, 0 );
if (STATUS(flush_to_zero)) {
if (aSig | bSig) {
float_raise(float_flag_output_denormal STATUS_VAR);
}
return packFloat32(zSign, 0, 0);
}
return packFloat32( zSign, 0, ( aSig + bSig )>>6 );
}
zSig = 0x40000000 + aSig + bSig;
@ -2922,8 +2905,6 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
return packFloat16(aSign, aExp + 14, aSig >> 13);
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Returns the result of converting the double-precision floating-point value
| `a' to the extended double-precision floating-point format. The conversion
@ -2955,10 +2936,6 @@ floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
}
#endif
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Returns the result of converting the double-precision floating-point value
| `a' to the quadruple-precision floating-point format. The conversion is
@ -2990,8 +2967,6 @@ float128 float64_to_float128( float64 a STATUS_PARAM )
}
#endif
/*----------------------------------------------------------------------------
| Rounds the double-precision floating-point value `a' to an integer, and
| returns the result as a double-precision floating-point value. The
@ -3120,7 +3095,12 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
return a;
}
if ( aExp == 0 ) {
if ( STATUS(flush_to_zero) ) return packFloat64( zSign, 0, 0 );
if (STATUS(flush_to_zero)) {
if (aSig | bSig) {
float_raise(float_flag_output_denormal STATUS_VAR);
}
return packFloat64(zSign, 0, 0);
}
return packFloat64( zSign, 0, ( aSig + bSig )>>9 );
}
zSig = LIT64( 0x4000000000000000 ) + aSig + bSig;
@ -3794,8 +3774,6 @@ int float64_unordered_quiet( float64 a, float64 b STATUS_PARAM )
return 0;
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Returns the result of converting the extended double-precision floating-
| point value `a' to the 32-bit two's complement integer format. The
@ -4008,8 +3986,6 @@ float64 floatx80_to_float64( floatx80 a STATUS_PARAM )
}
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Returns the result of converting the extended double-precision floating-
| point value `a' to the quadruple-precision floating-point format. The
@ -4034,8 +4010,6 @@ float128 floatx80_to_float128( floatx80 a STATUS_PARAM )
}
#endif
/*----------------------------------------------------------------------------
| Rounds the extended double-precision floating-point value `a' to an integer,
| and returns the result as an extended quadruple-precision floating-point
@ -4827,10 +4801,6 @@ int floatx80_unordered_quiet( floatx80 a, floatx80 b STATUS_PARAM )
return 0;
}
#endif
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Returns the result of converting the quadruple-precision floating-point
| value `a' to the 32-bit two's complement integer format. The conversion
@ -5080,8 +5050,6 @@ float64 float128_to_float64( float128 a STATUS_PARAM )
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Returns the result of converting the quadruple-precision floating-point
| value `a' to the extended double-precision floating-point format. The
@ -5117,8 +5085,6 @@ floatx80 float128_to_floatx80( float128 a STATUS_PARAM )
}
#endif
/*----------------------------------------------------------------------------
| Rounds the quadruple-precision floating-point value `a' to an integer, and
| returns the result as a quadruple-precision floating-point value. The
@ -5282,7 +5248,12 @@ static float128 addFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM
}
add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
if ( aExp == 0 ) {
if ( STATUS(flush_to_zero) ) return packFloat128( zSign, 0, 0, 0 );
if (STATUS(flush_to_zero)) {
if (zSig0 | zSig1) {
float_raise(float_flag_output_denormal STATUS_VAR);
}
return packFloat128(zSign, 0, 0, 0);
}
return packFloat128( zSign, 0, zSig0, zSig1 );
}
zSig2 = 0;
@ -5993,8 +5964,6 @@ int float128_unordered_quiet( float128 a, float128 b STATUS_PARAM )
return 0;
}
#endif
/* misc functions */
float32 uint32_to_float32( unsigned int a STATUS_PARAM )
{
@ -6396,7 +6365,6 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
return normalizeRoundAndPackFloat64( aSign, aExp, aSig STATUS_VAR );
}
#ifdef FLOATX80
floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
{
flag aSign;
@ -6427,9 +6395,7 @@ floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
return normalizeRoundAndPackFloatx80( STATUS(floatx80_rounding_precision),
aSign, aExp, aSig, 0 STATUS_VAR );
}
#endif
#ifdef FLOAT128
float128 float128_scalbn( float128 a, int n STATUS_PARAM )
{
flag aSign;
@ -6462,4 +6428,3 @@ float128 float128_scalbn( float128 a, int n STATUS_PARAM )
STATUS_VAR );
}
#endif

View File

@ -74,24 +74,6 @@ typedef int64_t int64;
#define SNAN_BIT_IS_ONE 0
#endif
/*----------------------------------------------------------------------------
| The macro `FLOATX80' must be defined to enable the extended double-precision
| floating-point format `floatx80'. If this macro is not defined, the
| `floatx80' type will not be defined, and none of the functions that either
| input or output the `floatx80' type will be defined. The same applies to
| the `FLOAT128' macro and the quadruple-precision format `float128'.
*----------------------------------------------------------------------------*/
#ifdef CONFIG_SOFTFLOAT
/* bit exact soft float support */
#define FLOATX80
#define FLOAT128
#else
/* native float support */
#if (defined(__i386__) || defined(__x86_64__)) && !defined(CONFIG_BSD)
#define FLOATX80
#endif
#endif /* !CONFIG_SOFTFLOAT */
#define STATUS_PARAM , float_status *status
#define STATUS(field) status->field
#define STATUS_VAR , status
@ -106,7 +88,6 @@ enum {
float_relation_unordered = 2
};
#ifdef CONFIG_SOFTFLOAT
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point types.
*----------------------------------------------------------------------------*/
@ -149,14 +130,11 @@ typedef uint64_t float64;
#define const_float32(x) (x)
#define const_float64(x) (x)
#endif
#ifdef FLOATX80
typedef struct {
uint64_t low;
uint16_t high;
} floatx80;
#define make_floatx80(exp, mant) ((floatx80) { mant, exp })
#endif
#ifdef FLOAT128
typedef struct {
#ifdef HOST_WORDS_BIGENDIAN
uint64_t high, low;
@ -164,7 +142,6 @@ typedef struct {
uint64_t low, high;
#endif
} float128;
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point underflow tininess-detection mode.
@ -193,16 +170,15 @@ enum {
float_flag_overflow = 8,
float_flag_underflow = 16,
float_flag_inexact = 32,
float_flag_input_denormal = 64
float_flag_input_denormal = 64,
float_flag_output_denormal = 128
};
typedef struct float_status {
signed char float_detect_tininess;
signed char float_rounding_mode;
signed char float_exception_flags;
#ifdef FLOATX80
signed char floatx80_rounding_precision;
#endif
/* should denormalised results go to zero and set the inexact flag? */
flag flush_to_zero;
/* should denormalised inputs go to zero and set the input_denormal flag? */
@ -232,9 +208,7 @@ INLINE int get_float_exception_flags(float_status *status)
{
return STATUS(float_exception_flags);
}
#ifdef FLOATX80
void set_floatx80_rounding_precision(int val STATUS_PARAM);
#endif
/*----------------------------------------------------------------------------
| Routine to raise any or all of the software IEC/IEEE floating-point
@ -249,22 +223,14 @@ float32 int32_to_float32( int32 STATUS_PARAM );
float64 int32_to_float64( int32 STATUS_PARAM );
float32 uint32_to_float32( unsigned int STATUS_PARAM );
float64 uint32_to_float64( unsigned int STATUS_PARAM );
#ifdef FLOATX80
floatx80 int32_to_floatx80( int32 STATUS_PARAM );
#endif
#ifdef FLOAT128
float128 int32_to_float128( int32 STATUS_PARAM );
#endif
float32 int64_to_float32( int64 STATUS_PARAM );
float32 uint64_to_float32( uint64 STATUS_PARAM );
float64 int64_to_float64( int64 STATUS_PARAM );
float64 uint64_to_float64( uint64 STATUS_PARAM );
#ifdef FLOATX80
floatx80 int64_to_floatx80( int64 STATUS_PARAM );
#endif
#ifdef FLOAT128
float128 int64_to_float128( int64 STATUS_PARAM );
#endif
/*----------------------------------------------------------------------------
| Software half-precision conversion routines.
@ -302,12 +268,8 @@ uint32 float32_to_uint32_round_to_zero( float32 STATUS_PARAM );
int64 float32_to_int64( float32 STATUS_PARAM );
int64 float32_to_int64_round_to_zero( float32 STATUS_PARAM );
float64 float32_to_float64( float32 STATUS_PARAM );
#ifdef FLOATX80
floatx80 float32_to_floatx80( float32 STATUS_PARAM );
#endif
#ifdef FLOAT128
float128 float32_to_float128( float32 STATUS_PARAM );
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision operations.
@ -419,12 +381,8 @@ int64 float64_to_int64_round_to_zero( float64 STATUS_PARAM );
uint64 float64_to_uint64 (float64 a STATUS_PARAM);
uint64 float64_to_uint64_round_to_zero (float64 a STATUS_PARAM);
float32 float64_to_float32( float64 STATUS_PARAM );
#ifdef FLOATX80
floatx80 float64_to_floatx80( float64 STATUS_PARAM );
#endif
#ifdef FLOAT128
float128 float64_to_float128( float64 STATUS_PARAM );
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision operations.
@ -491,6 +449,11 @@ INLINE int float64_is_any_nan(float64 a)
return ((float64_val(a) & ~(1ULL << 63)) > 0x7ff0000000000000ULL);
}
INLINE int float64_is_zero_or_denormal(float64 a)
{
return (float64_val(a) & 0x7ff0000000000000LL) == 0;
}
INLINE float64 float64_set_sign(float64 a, int sign)
{
return make_float64((float64_val(a) & 0x7fffffffffffffffULL)
@ -517,8 +480,6 @@ INLINE float64 float64_set_sign(float64 a, int sign)
#define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
#endif
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision conversion routines.
*----------------------------------------------------------------------------*/
@ -528,9 +489,7 @@ int64 floatx80_to_int64( floatx80 STATUS_PARAM );
int64 floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM );
float32 floatx80_to_float32( floatx80 STATUS_PARAM );
float64 floatx80_to_float64( floatx80 STATUS_PARAM );
#ifdef FLOAT128
float128 floatx80_to_float128( floatx80 STATUS_PARAM );
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision operations.
@ -584,6 +543,11 @@ INLINE int floatx80_is_zero(floatx80 a)
return (a.high & 0x7fff) == 0 && a.low == 0;
}
INLINE int floatx80_is_zero_or_denormal(floatx80 a)
{
return (a.high & 0x7fff) == 0;
}
INLINE int floatx80_is_any_nan(floatx80 a)
{
return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
@ -609,10 +573,6 @@ INLINE int floatx80_is_any_nan(floatx80 a)
#define floatx80_default_nan_low LIT64( 0xC000000000000000 )
#endif
#endif
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Software IEC/IEEE quadruple-precision conversion routines.
*----------------------------------------------------------------------------*/
@ -622,9 +582,7 @@ int64 float128_to_int64( float128 STATUS_PARAM );
int64 float128_to_int64_round_to_zero( float128 STATUS_PARAM );
float32 float128_to_float32( float128 STATUS_PARAM );
float64 float128_to_float64( float128 STATUS_PARAM );
#ifdef FLOATX80
floatx80 float128_to_floatx80( float128 STATUS_PARAM );
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE quadruple-precision operations.
@ -678,6 +636,11 @@ INLINE int float128_is_zero(float128 a)
return (a.high & 0x7fffffffffffffffLL) == 0 && a.low == 0;
}
INLINE int float128_is_zero_or_denormal(float128 a)
{
return (a.high & 0x7fff000000000000LL) == 0;
}
INLINE int float128_is_any_nan(float128 a)
{
return ((a.high >> 48) & 0x7fff) == 0x7fff &&
@ -696,12 +659,4 @@ INLINE int float128_is_any_nan(float128 a)
#define float128_default_nan_low LIT64( 0x0000000000000000 )
#endif
#endif
#else /* CONFIG_SOFTFLOAT */
#include "softfloat-native.h"
#endif /* !CONFIG_SOFTFLOAT */
#endif /* !SOFTFLOAT_H */

View File

@ -97,11 +97,4 @@ typedef struct FileOperations
void *opaque;
} FileOperations;
static inline const char *rpath(FsContext *ctx, const char *path)
{
/* FIXME: so wrong... */
static char buffer[4096];
snprintf(buffer, sizeof(buffer), "%s/%s", ctx->fs_root, path);
return buffer;
}
#endif

28
fsdev/qemu-fsdev-dummy.c Normal file
View File

@ -0,0 +1,28 @@
/*
* Virtio 9p
*
* Copyright IBM, Corp. 2010
*
* Authors:
* Gautham R Shenoy <ego@in.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
*/
#include <stdio.h>
#include <string.h>
#include "qemu-fsdev.h"
#include "qemu-config.h"
int qemu_fsdev_add(QemuOpts *opts)
{
return 0;
}
static void fsdev_register_config(void)
{
qemu_add_opts(&qemu_fsdev_opts);
qemu_add_opts(&qemu_virtfs_opts);
}
machine_init(fsdev_register_config);

View File

@ -1105,10 +1105,6 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
env->active_fpu.fcr31 = tmp & 0xFF83FFFF;
/* set rounding mode */
RESTORE_ROUNDING_MODE;
#ifndef CONFIG_SOFTFLOAT
/* no floating point exception for native float */
SET_FP_ENABLE(env->active_fpu.fcr31, 0);
#endif
break;
case 71: env->active_fpu.fcr0 = tmp; break;
}
@ -1436,7 +1432,11 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
/* XXX */
break;
case S390_PC_REGNUM: GET_REGL(env->psw.addr); break;
case S390_CC_REGNUM: GET_REG32(env->cc); break;
case S390_CC_REGNUM:
env->cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst,
env->cc_vr);
GET_REG32(env->cc_op);
break;
}
return 0;
@ -1462,7 +1462,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
/* XXX */
break;
case S390_PC_REGNUM: env->psw.addr = tmpl; break;
case S390_CC_REGNUM: env->cc = tmp32; r=4; break;
case S390_CC_REGNUM: env->cc_op = tmp32; r=4; break;
}
return r;

View File

@ -740,10 +740,11 @@ ETEXI
#if defined(TARGET_I386)
{
.name = "nmi",
.args_type = "cpu_index:i",
.params = "cpu",
.help = "inject an NMI on the given CPU",
.mhandler.cmd = do_inject_nmi,
.args_type = "",
.params = "",
.help = "inject an NMI on all guest's CPUs",
.user_print = monitor_user_noop,
.mhandler.cmd_new = do_inject_nmi,
},
#endif
STEXI

View File

@ -1645,7 +1645,7 @@ static const char *const fp_reg_names[] =
typedef unsigned int CORE_ADDR;
/* Get at various relevent fields of an instruction word. */
/* Get at various relevant fields of an instruction word. */
#define MASK_5 0x1f
#define MASK_10 0x3ff

View File

@ -10,8 +10,9 @@
* the COPYING file in the top-level directory.
*
*/
#include "virtio.h"
#include "pc.h"
#include "hw/virtio.h"
#include "hw/pc.h"
#include "virtio-9p.h"
#include "virtio-9p-debug.h"

173
hw/9pfs/virtio-9p-device.c Normal file
View File

@ -0,0 +1,173 @@
/*
* Virtio 9p backend
*
* Copyright IBM, Corp. 2010
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
*/
#include "hw/virtio.h"
#include "hw/pc.h"
#include "qemu_socket.h"
#include "hw/virtio-pci.h"
#include "virtio-9p.h"
#include "fsdev/qemu-fsdev.h"
#include "virtio-9p-xattr.h"
static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
{
features |= 1 << VIRTIO_9P_MOUNT_TAG;
return features;
}
static V9fsState *to_virtio_9p(VirtIODevice *vdev)
{
return (V9fsState *)vdev;
}
static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
{
struct virtio_9p_config *cfg;
V9fsState *s = to_virtio_9p(vdev);
cfg = qemu_mallocz(sizeof(struct virtio_9p_config) +
s->tag_len);
stw_raw(&cfg->tag_len, s->tag_len);
memcpy(cfg->tag, s->tag, s->tag_len);
memcpy(config, cfg, s->config_size);
qemu_free(cfg);
}
VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
{
V9fsState *s;
int i, len;
struct stat stat;
FsTypeEntry *fse;
s = (V9fsState *)virtio_common_init("virtio-9p",
VIRTIO_ID_9P,
sizeof(struct virtio_9p_config)+
MAX_TAG_LEN,
sizeof(V9fsState));
/* initialize pdu allocator */
QLIST_INIT(&s->free_list);
for (i = 0; i < (MAX_REQ - 1); i++) {
QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next);
}
s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output);
fse = get_fsdev_fsentry(conf->fsdev_id);
if (!fse) {
/* We don't have a fsdev identified by fsdev_id */
fprintf(stderr, "Virtio-9p device couldn't find fsdev with the "
"id = %s\n", conf->fsdev_id ? conf->fsdev_id : "NULL");
exit(1);
}
if (!fse->path || !conf->tag) {
/* we haven't specified a mount_tag or the path */
fprintf(stderr, "fsdev with id %s needs path "
"and Virtio-9p device needs mount_tag arguments\n",
conf->fsdev_id);
exit(1);
}
if (!strcmp(fse->security_model, "passthrough")) {
/* Files on the Fileserver set to client user credentials */
s->ctx.fs_sm = SM_PASSTHROUGH;
s->ctx.xops = passthrough_xattr_ops;
} else if (!strcmp(fse->security_model, "mapped")) {
/* Files on the fileserver are set to QEMU credentials.
* Client user credentials are saved in extended attributes.
*/
s->ctx.fs_sm = SM_MAPPED;
s->ctx.xops = mapped_xattr_ops;
} else if (!strcmp(fse->security_model, "none")) {
/*
* Files on the fileserver are set to QEMU credentials.
*/
s->ctx.fs_sm = SM_NONE;
s->ctx.xops = none_xattr_ops;
} else {
fprintf(stderr, "Default to security_model=none. You may want"
" enable advanced security model using "
"security option:\n\t security_model=passthrough\n\t "
"security_model=mapped\n");
s->ctx.fs_sm = SM_NONE;
s->ctx.xops = none_xattr_ops;
}
if (lstat(fse->path, &stat)) {
fprintf(stderr, "share path %s does not exist\n", fse->path);
exit(1);
} else if (!S_ISDIR(stat.st_mode)) {
fprintf(stderr, "share path %s is not a directory\n", fse->path);
exit(1);
}
s->ctx.fs_root = qemu_strdup(fse->path);
len = strlen(conf->tag);
if (len > MAX_TAG_LEN) {
len = MAX_TAG_LEN;
}
/* s->tag is non-NULL terminated string */
s->tag = qemu_malloc(len);
memcpy(s->tag, conf->tag, len);
s->tag_len = len;
s->ctx.uid = -1;
s->ops = fse->ops;
s->vdev.get_features = virtio_9p_get_features;
s->config_size = sizeof(struct virtio_9p_config) +
s->tag_len;
s->vdev.get_config = virtio_9p_get_config;
return &s->vdev;
}
static int virtio_9p_init_pci(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
VirtIODevice *vdev;
vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
vdev->nvectors = proxy->nvectors;
virtio_init_pci(proxy, vdev);
/* make the actual value visible */
proxy->nvectors = vdev->nvectors;
return 0;
}
static PCIDeviceInfo virtio_9p_info = {
.qdev.name = "virtio-9p-pci",
.qdev.size = sizeof(VirtIOPCIProxy),
.init = virtio_9p_init_pci,
.vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
.device_id = 0x1009,
.revision = VIRTIO_PCI_ABI_VERSION,
.class_id = 0x2,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
DEFINE_PROP_END_OF_LIST(),
}
};
static void virtio_9p_register_devices(void)
{
pci_qdev_register(&virtio_9p_info);
}
device_init(virtio_9p_register_devices)

View File

@ -10,7 +10,8 @@
* the COPYING file in the top-level directory.
*
*/
#include "virtio.h"
#include "hw/virtio.h"
#include "virtio-9p.h"
#include "virtio-9p-xattr.h"
#include <arpa/inet.h>
@ -24,7 +25,8 @@
static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf)
{
int err;
err = lstat(rpath(fs_ctx, path), stbuf);
char buffer[PATH_MAX];
err = lstat(rpath(fs_ctx, path, buffer), stbuf);
if (err) {
return err;
}
@ -34,19 +36,19 @@ static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf)
gid_t tmp_gid;
mode_t tmp_mode;
dev_t tmp_dev;
if (getxattr(rpath(fs_ctx, path), "user.virtfs.uid", &tmp_uid,
if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.uid", &tmp_uid,
sizeof(uid_t)) > 0) {
stbuf->st_uid = tmp_uid;
}
if (getxattr(rpath(fs_ctx, path), "user.virtfs.gid", &tmp_gid,
if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.gid", &tmp_gid,
sizeof(gid_t)) > 0) {
stbuf->st_gid = tmp_gid;
}
if (getxattr(rpath(fs_ctx, path), "user.virtfs.mode", &tmp_mode,
sizeof(mode_t)) > 0) {
if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.mode",
&tmp_mode, sizeof(mode_t)) > 0) {
stbuf->st_mode = tmp_mode;
}
if (getxattr(rpath(fs_ctx, path), "user.virtfs.rdev", &tmp_dev,
if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.rdev", &tmp_dev,
sizeof(dev_t)) > 0) {
stbuf->st_rdev = tmp_dev;
}
@ -91,10 +93,12 @@ static int local_set_xattr(const char *path, FsCred *credp)
static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
FsCred *credp)
{
if (chmod(rpath(fs_ctx, path), credp->fc_mode & 07777) < 0) {
char buffer[PATH_MAX];
if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) {
return -1;
}
if (lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid) < 0) {
if (lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
credp->fc_gid) < 0) {
/*
* If we fail to change ownership and if we are
* using security model none. Ignore the error
@ -110,9 +114,10 @@ static ssize_t local_readlink(FsContext *fs_ctx, const char *path,
char *buf, size_t bufsz)
{
ssize_t tsize = -1;
char buffer[PATH_MAX];
if (fs_ctx->fs_sm == SM_MAPPED) {
int fd;
fd = open(rpath(fs_ctx, path), O_RDONLY);
fd = open(rpath(fs_ctx, path, buffer), O_RDONLY);
if (fd == -1) {
return -1;
}
@ -123,7 +128,7 @@ static ssize_t local_readlink(FsContext *fs_ctx, const char *path,
return tsize;
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
(fs_ctx->fs_sm == SM_NONE)) {
tsize = readlink(rpath(fs_ctx, path), buf, bufsz);
tsize = readlink(rpath(fs_ctx, path, buffer), buf, bufsz);
}
return tsize;
}
@ -140,12 +145,14 @@ static int local_closedir(FsContext *ctx, DIR *dir)
static int local_open(FsContext *ctx, const char *path, int flags)
{
return open(rpath(ctx, path), flags);
char buffer[PATH_MAX];
return open(rpath(ctx, path, buffer), flags);
}
static DIR *local_opendir(FsContext *ctx, const char *path)
{
return opendir(rpath(ctx, path));
char buffer[PATH_MAX];
return opendir(rpath(ctx, path, buffer));
}
static void local_rewinddir(FsContext *ctx, DIR *dir)
@ -200,11 +207,12 @@ static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
static int local_chmod(FsContext *fs_ctx, const char *path, FsCred *credp)
{
char buffer[PATH_MAX];
if (fs_ctx->fs_sm == SM_MAPPED) {
return local_set_xattr(rpath(fs_ctx, path), credp);
return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
(fs_ctx->fs_sm == SM_NONE)) {
return chmod(rpath(fs_ctx, path), credp->fc_mode);
return chmod(rpath(fs_ctx, path, buffer), credp->fc_mode);
}
return -1;
}
@ -213,21 +221,24 @@ static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp)
{
int err = -1;
int serrno = 0;
char buffer[PATH_MAX];
/* Determine the security model */
if (fs_ctx->fs_sm == SM_MAPPED) {
err = mknod(rpath(fs_ctx, path), SM_LOCAL_MODE_BITS|S_IFREG, 0);
err = mknod(rpath(fs_ctx, path, buffer),
SM_LOCAL_MODE_BITS|S_IFREG, 0);
if (err == -1) {
return err;
}
local_set_xattr(rpath(fs_ctx, path), credp);
local_set_xattr(rpath(fs_ctx, path, buffer), credp);
if (err == -1) {
serrno = errno;
goto err_end;
}
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
(fs_ctx->fs_sm == SM_NONE)) {
err = mknod(rpath(fs_ctx, path), credp->fc_mode, credp->fc_rdev);
err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode,
credp->fc_rdev);
if (err == -1) {
return err;
}
@ -240,7 +251,7 @@ static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp)
return err;
err_end:
remove(rpath(fs_ctx, path));
remove(rpath(fs_ctx, path, buffer));
errno = serrno;
return err;
}
@ -249,22 +260,23 @@ static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp)
{
int err = -1;
int serrno = 0;
char buffer[PATH_MAX];
/* Determine the security model */
if (fs_ctx->fs_sm == SM_MAPPED) {
err = mkdir(rpath(fs_ctx, path), SM_LOCAL_DIR_MODE_BITS);
err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
if (err == -1) {
return err;
}
credp->fc_mode = credp->fc_mode|S_IFDIR;
err = local_set_xattr(rpath(fs_ctx, path), credp);
err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
if (err == -1) {
serrno = errno;
goto err_end;
}
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
(fs_ctx->fs_sm == SM_NONE)) {
err = mkdir(rpath(fs_ctx, path), credp->fc_mode);
err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode);
if (err == -1) {
return err;
}
@ -277,7 +289,7 @@ static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp)
return err;
err_end:
remove(rpath(fs_ctx, path));
remove(rpath(fs_ctx, path, buffer));
errno = serrno;
return err;
}
@ -318,23 +330,24 @@ static int local_open2(FsContext *fs_ctx, const char *path, int flags,
int fd = -1;
int err = -1;
int serrno = 0;
char buffer[PATH_MAX];
/* Determine the security model */
if (fs_ctx->fs_sm == SM_MAPPED) {
fd = open(rpath(fs_ctx, path), flags, SM_LOCAL_MODE_BITS);
fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
if (fd == -1) {
return fd;
}
credp->fc_mode = credp->fc_mode|S_IFREG;
/* Set cleint credentials in xattr */
err = local_set_xattr(rpath(fs_ctx, path), credp);
err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
if (err == -1) {
serrno = errno;
goto err_end;
}
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
(fs_ctx->fs_sm == SM_NONE)) {
fd = open(rpath(fs_ctx, path), flags, credp->fc_mode);
fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode);
if (fd == -1) {
return fd;
}
@ -348,7 +361,7 @@ static int local_open2(FsContext *fs_ctx, const char *path, int flags,
err_end:
close(fd);
remove(rpath(fs_ctx, path));
remove(rpath(fs_ctx, path, buffer));
errno = serrno;
return err;
}
@ -359,12 +372,13 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
{
int err = -1;
int serrno = 0;
char buffer[PATH_MAX];
/* Determine the security model */
if (fs_ctx->fs_sm == SM_MAPPED) {
int fd;
ssize_t oldpath_size, write_size;
fd = open(rpath(fs_ctx, newpath), O_CREAT|O_EXCL|O_RDWR,
fd = open(rpath(fs_ctx, newpath, buffer), O_CREAT|O_EXCL|O_RDWR,
SM_LOCAL_MODE_BITS);
if (fd == -1) {
return fd;
@ -384,18 +398,19 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
close(fd);
/* Set cleint credentials in symlink's xattr */
credp->fc_mode = credp->fc_mode|S_IFLNK;
err = local_set_xattr(rpath(fs_ctx, newpath), credp);
err = local_set_xattr(rpath(fs_ctx, newpath, buffer), credp);
if (err == -1) {
serrno = errno;
goto err_end;
}
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
(fs_ctx->fs_sm == SM_NONE)) {
err = symlink(oldpath, rpath(fs_ctx, newpath));
err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
if (err) {
return err;
}
err = lchown(rpath(fs_ctx, newpath), credp->fc_uid, credp->fc_gid);
err = lchown(rpath(fs_ctx, newpath, buffer), credp->fc_uid,
credp->fc_gid);
if (err == -1) {
/*
* If we fail to change ownership and if we are
@ -411,70 +426,45 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
return err;
err_end:
remove(rpath(fs_ctx, newpath));
remove(rpath(fs_ctx, newpath, buffer));
errno = serrno;
return err;
}
static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
{
char *tmp = qemu_strdup(rpath(ctx, oldpath));
int err, serrno = 0;
char buffer[PATH_MAX], buffer1[PATH_MAX];
if (tmp == NULL) {
return -ENOMEM;
}
err = link(tmp, rpath(ctx, newpath));
if (err == -1) {
serrno = errno;
}
qemu_free(tmp);
if (err == -1) {
errno = serrno;
}
return err;
return link(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
}
static int local_truncate(FsContext *ctx, const char *path, off_t size)
{
return truncate(rpath(ctx, path), size);
char buffer[PATH_MAX];
return truncate(rpath(ctx, path, buffer), size);
}
static int local_rename(FsContext *ctx, const char *oldpath,
const char *newpath)
{
char *tmp;
int err;
tmp = qemu_strdup(rpath(ctx, oldpath));
err = rename(tmp, rpath(ctx, newpath));
if (err == -1) {
int serrno = errno;
qemu_free(tmp);
errno = serrno;
} else {
qemu_free(tmp);
}
return err;
char buffer[PATH_MAX], buffer1[PATH_MAX];
return rename(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
}
static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
{
char buffer[PATH_MAX];
if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
(fs_ctx->fs_sm == SM_PASSTHROUGH)) {
return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
return lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
credp->fc_gid);
} else if (fs_ctx->fs_sm == SM_MAPPED) {
return local_set_xattr(rpath(fs_ctx, path), credp);
return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
(fs_ctx->fs_sm == SM_NONE)) {
return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
return lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
credp->fc_gid);
}
return -1;
}
@ -482,12 +472,15 @@ static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
static int local_utimensat(FsContext *s, const char *path,
const struct timespec *buf)
{
return qemu_utimensat(AT_FDCWD, rpath(s, path), buf, AT_SYMLINK_NOFOLLOW);
char buffer[PATH_MAX];
return qemu_utimensat(AT_FDCWD, rpath(s, path, buffer), buf,
AT_SYMLINK_NOFOLLOW);
}
static int local_remove(FsContext *ctx, const char *path)
{
return remove(rpath(ctx, path));
char buffer[PATH_MAX];
return remove(rpath(ctx, path, buffer));
}
static int local_fsync(FsContext *ctx, int fd, int datasync)
@ -501,7 +494,8 @@ static int local_fsync(FsContext *ctx, int fd, int datasync)
static int local_statfs(FsContext *s, const char *path, struct statfs *stbuf)
{
return statfs(rpath(s, path), stbuf);
char buffer[PATH_MAX];
return statfs(rpath(s, path, buffer), stbuf);
}
static ssize_t local_lgetxattr(FsContext *ctx, const char *path,

View File

@ -13,7 +13,7 @@
#include <sys/types.h>
#include <attr/xattr.h>
#include "virtio.h"
#include "hw/virtio.h"
#include "virtio-9p.h"
#include "fsdev/file-op-9p.h"
#include "virtio-9p-xattr.h"
@ -26,7 +26,8 @@
static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
const char *name, void *value, size_t size)
{
return lgetxattr(rpath(ctx, path), MAP_ACL_ACCESS, value, size);
char buffer[PATH_MAX];
return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value, size);
}
static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
@ -50,14 +51,17 @@ static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
void *value, size_t size, int flags)
{
return lsetxattr(rpath(ctx, path), MAP_ACL_ACCESS, value, size, flags);
char buffer[PATH_MAX];
return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value,
size, flags);
}
static int mp_pacl_removexattr(FsContext *ctx,
const char *path, const char *name)
{
int ret;
ret = lremovexattr(rpath(ctx, path), MAP_ACL_ACCESS);
char buffer[PATH_MAX];
ret = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS);
if (ret == -1 && errno == ENODATA) {
/*
* We don't get ENODATA error when trying to remove a
@ -73,7 +77,8 @@ static int mp_pacl_removexattr(FsContext *ctx,
static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
const char *name, void *value, size_t size)
{
return lgetxattr(rpath(ctx, path), MAP_ACL_DEFAULT, value, size);
char buffer[PATH_MAX];
return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value, size);
}
static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
@ -97,14 +102,17 @@ static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
void *value, size_t size, int flags)
{
return lsetxattr(rpath(ctx, path), MAP_ACL_DEFAULT, value, size, flags);
char buffer[PATH_MAX];
return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value,
size, flags);
}
static int mp_dacl_removexattr(FsContext *ctx,
const char *path, const char *name)
{
int ret;
ret = lremovexattr(rpath(ctx, path), MAP_ACL_DEFAULT);
char buffer[PATH_MAX];
ret = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT);
if (ret == -1 && errno == ENODATA) {
/*
* We don't get ENODATA error when trying to remove a

View File

@ -12,7 +12,7 @@
*/
#include <sys/types.h>
#include "virtio.h"
#include "hw/virtio.h"
#include "virtio-9p.h"
#include "fsdev/file-op-9p.h"
#include "virtio-9p-xattr.h"
@ -21,6 +21,7 @@
static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
const char *name, void *value, size_t size)
{
char buffer[PATH_MAX];
if (strncmp(name, "user.virtfs.", 12) == 0) {
/*
* Don't allow fetch of user.virtfs namesapce
@ -29,7 +30,7 @@ static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
errno = ENOATTR;
return -1;
}
return lgetxattr(rpath(ctx, path), name, value, size);
return lgetxattr(rpath(ctx, path, buffer), name, value, size);
}
static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
@ -67,6 +68,7 @@ static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
void *value, size_t size, int flags)
{
char buffer[PATH_MAX];
if (strncmp(name, "user.virtfs.", 12) == 0) {
/*
* Don't allow fetch of user.virtfs namesapce
@ -75,12 +77,13 @@ static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
errno = EACCES;
return -1;
}
return lsetxattr(rpath(ctx, path), name, value, size, flags);
return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags);
}
static int mp_user_removexattr(FsContext *ctx,
const char *path, const char *name)
{
char buffer[PATH_MAX];
if (strncmp(name, "user.virtfs.", 12) == 0) {
/*
* Don't allow fetch of user.virtfs namesapce
@ -89,7 +92,7 @@ static int mp_user_removexattr(FsContext *ctx,
errno = EACCES;
return -1;
}
return lremovexattr(rpath(ctx, path), name);
return lremovexattr(rpath(ctx, path, buffer), name);
}
XattrOperations mapped_user_xattr = {

View File

@ -11,7 +11,7 @@
*
*/
#include "virtio.h"
#include "hw/virtio.h"
#include "virtio-9p.h"
#include "fsdev/file-op-9p.h"
#include "virtio-9p-xattr.h"
@ -66,20 +66,21 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
void *value, size_t vsize)
{
ssize_t size = 0;
char buffer[PATH_MAX];
void *ovalue = value;
XattrOperations *xops;
char *orig_value, *orig_value_start;
ssize_t xattr_len, parsed_len = 0, attr_len;
/* Get the actual len */
xattr_len = llistxattr(rpath(ctx, path), value, 0);
xattr_len = llistxattr(rpath(ctx, path, buffer), value, 0);
if (xattr_len <= 0) {
return xattr_len;
}
/* Now fetch the xattr and find the actual size */
orig_value = qemu_malloc(xattr_len);
xattr_len = llistxattr(rpath(ctx, path), orig_value, xattr_len);
xattr_len = llistxattr(rpath(ctx, path, buffer), orig_value, xattr_len);
/* store the orig pointer */
orig_value_start = orig_value;

View File

@ -54,20 +54,23 @@ ssize_t pt_listxattr(FsContext *ctx, const char *path, char *name, void *value,
static inline ssize_t pt_getxattr(FsContext *ctx, const char *path,
const char *name, void *value, size_t size)
{
return lgetxattr(rpath(ctx, path), name, value, size);
char buffer[PATH_MAX];
return lgetxattr(rpath(ctx, path, buffer), name, value, size);
}
static inline int pt_setxattr(FsContext *ctx, const char *path,
const char *name, void *value,
size_t size, int flags)
{
return lsetxattr(rpath(ctx, path), name, value, size, flags);
char buffer[PATH_MAX];
return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags);
}
static inline int pt_removexattr(FsContext *ctx,
const char *path, const char *name)
{
return lremovexattr(rpath(ctx, path), name);
char buffer[PATH_MAX];
return lremovexattr(rpath(ctx, path, buffer), name);
}
static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path,

View File

@ -11,9 +11,10 @@
*
*/
#include "virtio.h"
#include "pc.h"
#include "hw/virtio.h"
#include "hw/pc.h"
#include "qemu_socket.h"
#include "hw/virtio-pci.h"
#include "virtio-9p.h"
#include "fsdev/qemu-fsdev.h"
#include "virtio-9p-debug.h"
@ -194,7 +195,6 @@ static int v9fs_do_open2(V9fsState *s, char *fullname, uid_t uid, gid_t gid,
cred.fc_uid = uid;
cred.fc_gid = gid;
cred.fc_mode = mode & 07777;
flags = flags;
return s->ops->open2(&s->ctx, fullname, flags, &cred);
}
@ -423,6 +423,22 @@ static void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
v9fs_string_sprintf(lhs, "%s", rhs->data);
}
/*
* Return TRUE if s1 is an ancestor of s2.
*
* E.g. "a/b" is an ancestor of "a/b/c" but not of "a/bc/d".
* As a special case, We treat s1 as ancestor of s2 if they are same!
*/
static int v9fs_path_is_ancestor(V9fsString *s1, V9fsString *s2)
{
if (!strncmp(s1->data, s2->data, s1->size)) {
if (s2->data[s1->size] == '\0' || s2->data[s1->size] == '/') {
return 1;
}
}
return 0;
}
static size_t v9fs_string_size(V9fsString *str)
{
return str->size;
@ -2805,13 +2821,13 @@ static int v9fs_complete_rename(V9fsState *s, V9fsRenameState *vs)
for (fidp = s->fid_list; fidp; fidp = fidp->next) {
if (vs->fidp == fidp) {
/*
* we replace name of this fid towards the end
* so that our below strcmp will work
* we replace name of this fid towards the end so
* that our below v9fs_path_is_ancestor check will
* work
*/
continue;
}
if (!strncmp(vs->fidp->path.data, fidp->path.data,
strlen(vs->fidp->path.data))) {
if (v9fs_path_is_ancestor(&vs->fidp->path, &fidp->path)) {
/* replace the name */
v9fs_fix_path(&fidp->path, &vs->name,
strlen(vs->fidp->path.data));
@ -3589,6 +3605,11 @@ static pdu_handler_t *pdu_handlers[] = {
[P9_TREMOVE] = v9fs_remove,
};
static void v9fs_op_not_supp(V9fsState *s, V9fsPDU *pdu)
{
complete_pdu(s, pdu, -EOPNOTSUPP);
}
static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
{
pdu_handler_t *handler;
@ -3596,16 +3617,16 @@ static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
if (debug_9p_pdu) {
pprint_pdu(pdu);
}
BUG_ON(pdu->id >= ARRAY_SIZE(pdu_handlers));
handler = pdu_handlers[pdu->id];
BUG_ON(handler == NULL);
if (pdu->id >= ARRAY_SIZE(pdu_handlers) ||
(pdu_handlers[pdu->id] == NULL)) {
handler = v9fs_op_not_supp;
} else {
handler = pdu_handlers[pdu->id];
}
handler(s, pdu);
}
static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
{
V9fsState *s = (V9fsState *)vdev;
V9fsPDU *pdu;
@ -3629,119 +3650,3 @@ static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
free_pdu(s, pdu);
}
static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
{
features |= 1 << VIRTIO_9P_MOUNT_TAG;
return features;
}
static V9fsState *to_virtio_9p(VirtIODevice *vdev)
{
return (V9fsState *)vdev;
}
static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
{
struct virtio_9p_config *cfg;
V9fsState *s = to_virtio_9p(vdev);
cfg = qemu_mallocz(sizeof(struct virtio_9p_config) +
s->tag_len);
stw_raw(&cfg->tag_len, s->tag_len);
memcpy(cfg->tag, s->tag, s->tag_len);
memcpy(config, cfg, s->config_size);
qemu_free(cfg);
}
VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
{
V9fsState *s;
int i, len;
struct stat stat;
FsTypeEntry *fse;
s = (V9fsState *)virtio_common_init("virtio-9p",
VIRTIO_ID_9P,
sizeof(struct virtio_9p_config)+
MAX_TAG_LEN,
sizeof(V9fsState));
/* initialize pdu allocator */
QLIST_INIT(&s->free_list);
for (i = 0; i < (MAX_REQ - 1); i++) {
QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next);
}
s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output);
fse = get_fsdev_fsentry(conf->fsdev_id);
if (!fse) {
/* We don't have a fsdev identified by fsdev_id */
fprintf(stderr, "Virtio-9p device couldn't find fsdev with the "
"id = %s\n", conf->fsdev_id ? conf->fsdev_id : "NULL");
exit(1);
}
if (!fse->path || !conf->tag) {
/* we haven't specified a mount_tag or the path */
fprintf(stderr, "fsdev with id %s needs path "
"and Virtio-9p device needs mount_tag arguments\n",
conf->fsdev_id);
exit(1);
}
if (!strcmp(fse->security_model, "passthrough")) {
/* Files on the Fileserver set to client user credentials */
s->ctx.fs_sm = SM_PASSTHROUGH;
s->ctx.xops = passthrough_xattr_ops;
} else if (!strcmp(fse->security_model, "mapped")) {
/* Files on the fileserver are set to QEMU credentials.
* Client user credentials are saved in extended attributes.
*/
s->ctx.fs_sm = SM_MAPPED;
s->ctx.xops = mapped_xattr_ops;
} else if (!strcmp(fse->security_model, "none")) {
/*
* Files on the fileserver are set to QEMU credentials.
*/
s->ctx.fs_sm = SM_NONE;
s->ctx.xops = none_xattr_ops;
} else {
fprintf(stderr, "Default to security_model=none. You may want"
" enable advanced security model using "
"security option:\n\t security_model=passthrough \n\t "
"security_model=mapped\n");
s->ctx.fs_sm = SM_NONE;
s->ctx.xops = none_xattr_ops;
}
if (lstat(fse->path, &stat)) {
fprintf(stderr, "share path %s does not exist\n", fse->path);
exit(1);
} else if (!S_ISDIR(stat.st_mode)) {
fprintf(stderr, "share path %s is not a directory \n", fse->path);
exit(1);
}
s->ctx.fs_root = qemu_strdup(fse->path);
len = strlen(conf->tag);
if (len > MAX_TAG_LEN) {
len = MAX_TAG_LEN;
}
/* s->tag is non-NULL terminated string */
s->tag = qemu_malloc(len);
memcpy(s->tag, conf->tag, len);
s->tag_len = len;
s->ctx.uid = -1;
s->ops = fse->ops;
s->vdev.get_features = virtio_9p_get_features;
s->config_size = sizeof(struct virtio_9p_config) +
s->tag_len;
s->vdev.get_config = virtio_9p_get_config;
return &s->vdev;
}

View File

@ -101,6 +101,11 @@ enum p9_proto_version {
#define P9_NOTAG (u16)(~0)
#define P9_NOFID (u32)(~0)
#define P9_MAXWELEM 16
static inline const char *rpath(FsContext *ctx, const char *path, char *buffer)
{
snprintf(buffer, PATH_MAX, "%s/%s", ctx->fs_root, path);
return buffer;
}
/*
* ample room for Twrite/Rread header
@ -504,4 +509,6 @@ static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
return pdu_packunpack(dst, sg, sg_count, offset, size, 0);
}
extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq);
#endif

View File

@ -1001,8 +1001,6 @@ static int write_audio (AC97LinkState *s, AC97BusMasterRegs *r,
static void write_bup (AC97LinkState *s, int elapsed)
{
int written = 0;
dolog ("write_bup\n");
if (!(s->bup_flag & BUP_SET)) {
if (s->bup_flag & BUP_LAST) {
@ -1026,7 +1024,6 @@ static void write_bup (AC97LinkState *s, int elapsed)
return;
temp -= copied;
elapsed -= copied;
written += copied;
}
}
}
@ -1069,7 +1066,7 @@ static int read_audio (AC97LinkState *s, AC97BusMasterRegs *r,
static void transfer_audio (AC97LinkState *s, int index, int elapsed)
{
AC97BusMasterRegs *r = &s->bm_regs[index];
int written = 0, stop = 0;
int stop = 0;
if (s->invalid_freq[index]) {
AUD_log ("ac97", "attempt to use voice %d with invalid frequency %d\n",
@ -1114,7 +1111,6 @@ static void transfer_audio (AC97LinkState *s, int index, int elapsed)
switch (index) {
case PO_INDEX:
temp = write_audio (s, r, elapsed, &stop);
written += temp;
elapsed -= temp;
r->picb -= (temp >> 1);
break;

View File

@ -471,11 +471,13 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
BusState *bus = opaque;
DeviceState *qdev, *next;
PCIDevice *dev;
PCIDeviceInfo *info;
int slot = ffs(val) - 1;
QLIST_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
dev = DO_UPCAST(PCIDevice, qdev, qdev);
if (PCI_SLOT(dev->devfn) == slot) {
info = container_of(qdev->info, PCIDeviceInfo, qdev);
if (PCI_SLOT(dev->devfn) == slot && !info->no_hotplug) {
qdev_free(qdev);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -38,7 +38,8 @@ typedef enum bitbang_i2c_state {
RECEIVING_BIT2,
RECEIVING_BIT1,
RECEIVING_BIT0,
SENDING_ACK
SENDING_ACK,
SENT_NACK
} bitbang_i2c_state;
struct bitbang_i2c_interface {
@ -115,6 +116,7 @@ int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level)
}
switch (i2c->state) {
case STOPPED:
case SENT_NACK:
return bitbang_i2c_ret(i2c, 1);
case SENDING_BIT7 ... SENDING_BIT0:
@ -155,6 +157,7 @@ int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level)
i2c->state = RECEIVING_BIT7;
if (data != 0) {
DPRINTF("NACKED\n");
i2c->state = SENT_NACK;
i2c_nack(i2c->bus);
} else {
DPRINTF("ACKED\n");

View File

@ -27,6 +27,7 @@ typedef struct QEMUMachine {
no_cdrom:1,
no_sdcard:1;
int is_default;
const char *default_machine_opts;
GlobalProperty *compat_props;
struct QEMUMachine *next;
} QEMUMachine;

View File

@ -323,7 +323,7 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s,
break;
}
s->proto = parameter;
s->usbdev->info->handle_control(s->usbdev, SET_PROTOCOL, s->proto, 0, 0,
s->usbdev->info->handle_control(s->usbdev, NULL, SET_PROTOCOL, s->proto, 0, 0,
NULL);
ret = BT_HS_SUCCESSFUL;
break;
@ -333,7 +333,7 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s,
ret = BT_HS_ERR_INVALID_PARAMETER;
break;
}
s->usbdev->info->handle_control(s->usbdev, GET_IDLE, 0, 0, 1,
s->usbdev->info->handle_control(s->usbdev, NULL, GET_IDLE, 0, 0, 1,
s->control->sdu_out(s->control, 1));
s->control->sdu_submit(s->control);
break;
@ -346,7 +346,7 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s,
/* We don't need to know about the Idle Rate here really,
* so just pass it on to the device. */
ret = s->usbdev->info->handle_control(s->usbdev,
ret = s->usbdev->info->handle_control(s->usbdev, NULL,
SET_IDLE, data[1], 0, 0, NULL) ?
BT_HS_SUCCESSFUL : BT_HS_ERR_INVALID_PARAMETER;
/* XXX: Does this generate a handshake? */

View File

@ -1441,7 +1441,7 @@ typedef struct {
#define EVT_FLUSH_OCCURRED 0x11
typedef struct {
uint16_t handle;
} __attribute__ ((packed)) evt_flush_occured;
} __attribute__ ((packed)) evt_flush_occurred;
#define EVT_FLUSH_OCCURRED_SIZE 2
#define EVT_ROLE_CHANGE 0x12

View File

@ -1112,7 +1112,7 @@ static void eepro100_write_eeprom(eeprom_t * eeprom, uint8_t val)
{
TRACE(EEPROM, logout("val=0x%02x\n", val));
/* mask unwriteable bits */
/* mask unwritable bits */
#if 0
val = SET_MASKED(val, 0x31, eeprom->value);
#endif

View File

@ -75,7 +75,7 @@ struct _eeprom_t {
uint8_t tick;
uint8_t address;
uint8_t command;
uint8_t writeable;
uint8_t writable;
uint8_t eecs;
uint8_t eesk;
@ -130,7 +130,7 @@ static const VMStateDescription vmstate_eeprom = {
VMSTATE_UINT8(tick, eeprom_t),
VMSTATE_UINT8(address, eeprom_t),
VMSTATE_UINT8(command, eeprom_t),
VMSTATE_UINT8(writeable, eeprom_t),
VMSTATE_UINT8(writable, eeprom_t),
VMSTATE_UINT8(eecs, eeprom_t),
VMSTATE_UINT8(eesk, eeprom_t),
@ -165,7 +165,7 @@ void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi)
address = 0x0;
} else if (eeprom->eecs && ! eecs) {
/* End chip select cycle. This triggers write / erase. */
if (eeprom->writeable) {
if (eeprom->writable) {
uint8_t subcommand = address >> (eeprom->addrbits - 2);
if (command == 0 && subcommand == 2) {
/* Erase all. */
@ -232,7 +232,7 @@ void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi)
switch (address >> (eeprom->addrbits - 2)) {
case 0:
logout("write disable command\n");
eeprom->writeable = 0;
eeprom->writable = 0;
break;
case 1:
logout("write all command\n");
@ -242,7 +242,7 @@ void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi)
break;
case 3:
logout("write enable command\n");
eeprom->writeable = 1;
eeprom->writable = 1;
break;
}
} else {

119
hw/esp.c
View File

@ -61,10 +61,11 @@ struct ESPState {
int32_t ti_size;
uint32_t ti_rptr, ti_wptr;
uint8_t ti_buf[TI_BUFSZ];
uint32_t sense;
uint32_t status;
uint32_t dma;
SCSIBus bus;
SCSIDevice *current_dev;
SCSIRequest *current_req;
uint8_t cmdbuf[TI_BUFSZ];
uint32_t cmdlen;
uint32_t do_cmd;
@ -187,6 +188,17 @@ static void esp_dma_enable(void *opaque, int irq, int level)
}
}
static void esp_request_cancelled(SCSIRequest *req)
{
ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
if (req == s->current_req) {
scsi_req_unref(s->current_req);
s->current_req = NULL;
s->current_dev = NULL;
}
}
static uint32_t get_cmd(ESPState *s, uint8_t *buf)
{
uint32_t dmalen;
@ -209,7 +221,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
if (s->current_dev) {
/* Started a new command before the old one finished. Cancel it. */
s->current_dev->info->cancel_io(s->current_dev, 0);
scsi_req_cancel(s->current_req);
s->async_len = 0;
}
@ -232,7 +244,8 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
DPRINTF("do_busid_cmd: busid 0x%x\n", busid);
lun = busid & 7;
datalen = s->current_dev->info->send_command(s->current_dev, 0, buf, lun);
s->current_req = scsi_req_new(s->current_dev, 0, lun);
datalen = scsi_req_enqueue(s->current_req, buf);
s->ti_size = datalen;
if (datalen != 0) {
s->rregs[ESP_RSTAT] = STAT_TC;
@ -240,11 +253,10 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
s->dma_counter = 0;
if (datalen > 0) {
s->rregs[ESP_RSTAT] |= STAT_DI;
s->current_dev->info->read_data(s->current_dev, 0);
} else {
s->rregs[ESP_RSTAT] |= STAT_DO;
s->current_dev->info->write_data(s->current_dev, 0);
}
scsi_req_continue(s->current_req);
}
s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
s->rregs[ESP_RSEQ] = SEQ_CD;
@ -306,8 +318,8 @@ static void handle_satn_stop(ESPState *s)
static void write_response(ESPState *s)
{
DPRINTF("Transfer status (sense=%d)\n", s->sense);
s->ti_buf[0] = s->sense;
DPRINTF("Transfer status (status=%d)\n", s->status);
s->ti_buf[0] = s->status;
s->ti_buf[1] = 0;
if (s->dma) {
s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
@ -370,53 +382,56 @@ static void esp_do_dma(ESPState *s)
else
s->ti_size -= len;
if (s->async_len == 0) {
if (to_device) {
// ti_size is negative
s->current_dev->info->write_data(s->current_dev, 0);
} else {
s->current_dev->info->read_data(s->current_dev, 0);
/* If there is still data to be read from the device then
complete the DMA operation immediately. Otherwise defer
until the scsi layer has completed. */
if (s->dma_left == 0 && s->ti_size > 0) {
esp_dma_done(s);
}
scsi_req_continue(s->current_req);
/* If there is still data to be read from the device then
complete the DMA operation immediately. Otherwise defer
until the scsi layer has completed. */
if (to_device || s->dma_left != 0 || s->ti_size == 0) {
return;
}
} else {
/* Partially filled a scsi buffer. Complete immediately. */
esp_dma_done(s);
}
/* Partially filled a scsi buffer. Complete immediately. */
esp_dma_done(s);
}
static void esp_command_complete(SCSIRequest *req, uint32_t status)
{
ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
DPRINTF("SCSI Command complete\n");
if (s->ti_size != 0) {
DPRINTF("SCSI command completed unexpectedly\n");
}
s->ti_size = 0;
s->dma_left = 0;
s->async_len = 0;
if (status) {
DPRINTF("Command failed\n");
}
s->status = status;
s->rregs[ESP_RSTAT] = STAT_ST;
esp_dma_done(s);
if (s->current_req) {
scsi_req_unref(s->current_req);
s->current_req = NULL;
s->current_dev = NULL;
}
}
static void esp_command_complete(SCSIBus *bus, int reason, uint32_t tag,
uint32_t arg)
static void esp_transfer_data(SCSIRequest *req, uint32_t len)
{
ESPState *s = DO_UPCAST(ESPState, busdev.qdev, bus->qbus.parent);
ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
if (reason == SCSI_REASON_DONE) {
DPRINTF("SCSI Command complete\n");
if (s->ti_size != 0)
DPRINTF("SCSI command completed unexpectedly\n");
s->ti_size = 0;
s->dma_left = 0;
s->async_len = 0;
if (arg)
DPRINTF("Command failed\n");
s->sense = arg;
s->rregs[ESP_RSTAT] = STAT_ST;
DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
s->async_len = len;
s->async_buf = scsi_req_get_buf(req);
if (s->dma_left) {
esp_do_dma(s);
} else if (s->dma_counter != 0 && s->ti_size <= 0) {
/* If this was the last part of a DMA transfer then the
completion interrupt is deferred to here. */
esp_dma_done(s);
s->current_dev = NULL;
} else {
DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
s->async_len = arg;
s->async_buf = s->current_dev->info->get_buf(s->current_dev, 0);
if (s->dma_left) {
esp_do_dma(s);
} else if (s->dma_counter != 0 && s->ti_size <= 0) {
/* If this was the last part of a DMA transfer then the
completion interrupt is deferred to here. */
esp_dma_done(s);
}
}
}
@ -678,7 +693,7 @@ static const VMStateDescription vmstate_esp = {
VMSTATE_UINT32(ti_rptr, ESPState),
VMSTATE_UINT32(ti_wptr, ESPState),
VMSTATE_BUFFER(ti_buf, ESPState),
VMSTATE_UINT32(sense, ESPState),
VMSTATE_UINT32(status, ESPState),
VMSTATE_UINT32(dma, ESPState),
VMSTATE_BUFFER(cmdbuf, ESPState),
VMSTATE_UINT32(cmdlen, ESPState),
@ -714,6 +729,12 @@ void esp_init(target_phys_addr_t espaddr, int it_shift,
*dma_enable = qdev_get_gpio_in(dev, 1);
}
static const struct SCSIBusOps esp_scsi_ops = {
.transfer_data = esp_transfer_data,
.complete = esp_command_complete,
.cancel = esp_request_cancelled
};
static int esp_init1(SysBusDevice *dev)
{
ESPState *s = FROM_SYSBUS(ESPState, dev);
@ -728,7 +749,7 @@ static int esp_init1(SysBusDevice *dev)
qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, esp_command_complete);
scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, &esp_scsi_ops);
return scsi_bus_legacy_handle_cmdline(&s->bus);
}

View File

@ -884,8 +884,31 @@ static int handle_cmd(AHCIState *s, int port, int slot)
}
if (ide_state->drive_kind != IDE_CD) {
ide_set_sector(ide_state, (cmd_fis[6] << 16) | (cmd_fis[5] << 8) |
cmd_fis[4]);
/*
* We set the sector depending on the sector defined in the FIS.
* Unfortunately, the spec isn't exactly obvious on this one.
*
* Apparently LBA48 commands set fis bytes 10,9,8,6,5,4 to the
* 48 bit sector number. ATA_CMD_READ_DMA_EXT is an example for
* such a command.
*
* Non-LBA48 commands however use 7[lower 4 bits],6,5,4 to define a
* 28-bit sector number. ATA_CMD_READ_DMA is an example for such
* a command.
*
* Since the spec doesn't explicitly state what each field should
* do, I simply assume non-used fields as reserved and OR everything
* together, independent of the command.
*/
ide_set_sector(ide_state, ((uint64_t)cmd_fis[10] << 40)
| ((uint64_t)cmd_fis[9] << 32)
/* This is used for LBA48 commands */
| ((uint64_t)cmd_fis[8] << 24)
/* This is used for non-LBA48 commands */
| ((uint64_t)(cmd_fis[7] & 0xf) << 24)
| ((uint64_t)cmd_fis[6] << 16)
| ((uint64_t)cmd_fis[5] << 8)
| cmd_fis[4]);
}
/* Copy the ACMD field (ATAPI packet, if any) from the AHCI command
@ -1066,9 +1089,11 @@ static int ahci_dma_set_inactive(IDEDMA *dma)
ad->dma_cb = NULL;
/* maybe we still have something to process, check later */
ad->check_bh = qemu_bh_new(ahci_check_cmd_bh, ad);
qemu_bh_schedule(ad->check_bh);
if (!ad->check_bh) {
/* maybe we still have something to process, check later */
ad->check_bh = qemu_bh_new(ahci_check_cmd_bh, ad);
qemu_bh_schedule(ad->check_bh);
}
return 0;
}

View File

@ -430,7 +430,6 @@ void ide_dma_error(IDEState *s)
s->error = ABRT_ERR;
s->status = READY_STAT | ERR_STAT;
ide_set_inactive(s);
s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT);
ide_set_irq(s->bus);
}
@ -500,8 +499,11 @@ handle_rw_error:
n = s->nsector;
s->io_buffer_index = 0;
s->io_buffer_size = n * 512;
if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->is_read) == 0)
if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->is_read) == 0) {
/* The PRDs were too short. Reset the Active bit, but don't raise an
* interrupt. */
goto eot;
}
#ifdef DEBUG_AIO
printf("ide_dma_cb: sector_num=%" PRId64 " n=%d, is_read=%d\n",
@ -523,7 +525,6 @@ handle_rw_error:
return;
eot:
s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT);
ide_set_inactive(s);
}
@ -1592,13 +1593,15 @@ void ide_bus_reset(IDEBus *bus)
bus->dma->ops->reset(bus->dma);
}
int ide_init_drive(IDEState *s, BlockDriverState *bs,
int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
const char *version, const char *serial)
{
int cylinders, heads, secs;
uint64_t nb_sectors;
s->bs = bs;
s->drive_kind = kind;
bdrv_get_geometry(bs, &nb_sectors);
bdrv_guess_geometry(bs, &cylinders, &heads, &secs);
if (cylinders < 1 || cylinders > 16383) {
@ -1623,8 +1626,7 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs,
s->smart_autosave = 1;
s->smart_errors = 0;
s->smart_selftest_count = 0;
if (bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM) {
s->drive_kind = IDE_CD;
if (kind == IDE_CD) {
bdrv_set_change_cb(bs, cdrom_change_cb, s);
bs->buffer_alignment = 2048;
} else {
@ -1729,7 +1731,8 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
dinfo = i == 0 ? hd0 : hd1;
ide_init1(bus, i);
if (dinfo) {
if (ide_init_drive(&bus->ifs[i], dinfo->bdrv, NULL,
if (ide_init_drive(&bus->ifs[i], dinfo->bdrv,
dinfo->media_cd ? IDE_CD : IDE_HD, NULL,
*dinfo->serial ? dinfo->serial : NULL) < 0) {
error_report("Can't set up IDE drive %s", dinfo->id);
exit(1);

View File

@ -90,12 +90,12 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
qemu_register_reset(ahci_reset, d);
/* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
pci_register_bar_simple(&d->card, 5, 0x1000, 0, d->ahci.mem);
msi_init(dev, 0x50, 1, true, false);
d->ahci.irq = d->card.irq[0];
/* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
pci_register_bar_simple(&d->card, 5, 0x1000, 0, d->ahci.mem);
return 0;
}

View File

@ -558,7 +558,7 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr);
void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
uint32_t ide_data_readl(void *opaque, uint32_t addr);
int ide_init_drive(IDEState *s, BlockDriverState *bs,
int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
const char *version, const char *serial);
void ide_init2(IDEBus *bus, qemu_irq irq);
void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,

View File

@ -296,12 +296,8 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
*/
if (bm->bus->dma->aiocb) {
qemu_aio_flush();
#ifdef DEBUG_IDE
if (bm->bus->dma->aiocb)
printf("ide_dma_cancel: aiocb still pending");
if (bm->status & BM_STATUS_DMAING)
printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
#endif
assert(bm->bus->dma->aiocb == NULL);
assert((bm->status & BM_STATUS_DMAING) == 0);
}
} else {
bm->cur_addr = bm->addr;

View File

@ -98,7 +98,7 @@ IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
{
DeviceState *dev;
dev = qdev_create(&bus->qbus, "ide-drive");
dev = qdev_create(&bus->qbus, drive->media_cd ? "ide-cd" : "ide-hd");
qdev_prop_set_uint32(dev, "unit", unit);
qdev_prop_set_drive_nofail(dev, "drive", drive->bdrv);
qdev_init_nofail(dev);
@ -118,7 +118,7 @@ typedef struct IDEDrive {
IDEDevice dev;
} IDEDrive;
static int ide_drive_initfn(IDEDevice *dev)
static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
{
IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
IDEState *s = bus->ifs + dev->unit;
@ -134,7 +134,7 @@ static int ide_drive_initfn(IDEDevice *dev)
}
}
if (ide_init_drive(s, dev->conf.bs, dev->version, serial) < 0) {
if (ide_init_drive(s, dev->conf.bs, kind, dev->version, serial) < 0) {
return -1;
}
@ -151,22 +151,69 @@ static int ide_drive_initfn(IDEDevice *dev)
return 0;
}
static IDEDeviceInfo ide_drive_info = {
.qdev.name = "ide-drive",
.qdev.fw_name = "drive",
.qdev.size = sizeof(IDEDrive),
.init = ide_drive_initfn,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("unit", IDEDrive, dev.unit, -1),
DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf),
DEFINE_PROP_STRING("ver", IDEDrive, dev.version),
DEFINE_PROP_STRING("serial", IDEDrive, dev.serial),
DEFINE_PROP_END_OF_LIST(),
static int ide_hd_initfn(IDEDevice *dev)
{
return ide_dev_initfn(dev, IDE_HD);
}
static int ide_cd_initfn(IDEDevice *dev)
{
return ide_dev_initfn(dev, IDE_CD);
}
static int ide_drive_initfn(IDEDevice *dev)
{
DriveInfo *dinfo = drive_get_by_blockdev(dev->conf.bs);
return ide_dev_initfn(dev, dinfo->media_cd ? IDE_CD : IDE_HD);
}
#define DEFINE_IDE_DEV_PROPERTIES() \
DEFINE_PROP_UINT32("unit", IDEDrive, dev.unit, -1), \
DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf), \
DEFINE_PROP_STRING("ver", IDEDrive, dev.version), \
DEFINE_PROP_STRING("serial", IDEDrive, dev.serial)
static IDEDeviceInfo ide_dev_info[] = {
{
.qdev.name = "ide-hd",
.qdev.fw_name = "drive",
.qdev.desc = "virtual IDE disk",
.qdev.size = sizeof(IDEDrive),
.init = ide_hd_initfn,
.qdev.props = (Property[]) {
DEFINE_IDE_DEV_PROPERTIES(),
DEFINE_PROP_END_OF_LIST(),
}
},{
.qdev.name = "ide-cd",
.qdev.fw_name = "drive",
.qdev.desc = "virtual IDE CD-ROM",
.qdev.size = sizeof(IDEDrive),
.init = ide_cd_initfn,
.qdev.props = (Property[]) {
DEFINE_IDE_DEV_PROPERTIES(),
DEFINE_PROP_END_OF_LIST(),
}
},{
.qdev.name = "ide-drive", /* legacy -device ide-drive */
.qdev.fw_name = "drive",
.qdev.desc = "virtual IDE disk or CD-ROM (legacy)",
.qdev.size = sizeof(IDEDrive),
.init = ide_drive_initfn,
.qdev.props = (Property[]) {
DEFINE_IDE_DEV_PROPERTIES(),
DEFINE_PROP_END_OF_LIST(),
}
}
};
static void ide_drive_register(void)
static void ide_dev_register(void)
{
ide_qdev_register(&ide_drive_info);
int i;
for (i = 0; i < ARRAY_SIZE(ide_dev_info); i++) {
ide_qdev_register(&ide_dev_info[i]);
}
}
device_init(ide_drive_register);
device_init(ide_dev_register);

View File

@ -721,7 +721,7 @@ static void do_phy_write(lan9118_state *s, int reg, uint32_t val)
break;
}
s->phy_control = val & 0x7980;
/* Complete autonegotiation imediately. */
/* Complete autonegotiation immediately. */
if (val & 0x1000) {
s->phy_status |= 0x0020;
}

View File

@ -174,6 +174,7 @@ do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0)
#define LSI_TAG_VALID (1 << 16)
typedef struct lsi_request {
SCSIRequest *req;
uint32_t tag;
uint32_t dma_len;
uint8_t *dma_buf;
@ -189,7 +190,7 @@ typedef struct {
uint32_t script_ram_base;
int carry; /* ??? Should this be an a visible register somewhere? */
int sense;
int status;
/* Action to take at the end of a MSG IN phase.
0 = COMMAND, 1 = disconnect, 2 = DATA OUT, 3 = DATA IN. */
int msg_action;
@ -567,11 +568,9 @@ static void lsi_do_dma(LSIState *s, int out)
s->csbc += count;
s->dnad += count;
s->dbc -= count;
if (s->current->dma_buf == NULL) {
s->current->dma_buf = dev->info->get_buf(dev, s->current->tag);
if (s->current->dma_buf == NULL) {
s->current->dma_buf = scsi_req_get_buf(s->current->req);
}
/* ??? Set SFBR to first data byte. */
if (out) {
cpu_physical_memory_read(addr, s->current->dma_buf, count);
@ -581,13 +580,7 @@ static void lsi_do_dma(LSIState *s, int out)
s->current->dma_len -= count;
if (s->current->dma_len == 0) {
s->current->dma_buf = NULL;
if (out) {
/* Write the data. */
dev->info->write_data(dev, s->current->tag);
} else {
/* Request any remaining data. */
dev->info->read_data(dev, s->current->tag);
}
scsi_req_continue(s->current->req);
} else {
s->current->dma_buf += count;
lsi_resume_script(s);
@ -652,82 +645,123 @@ static void lsi_reselect(LSIState *s, lsi_request *p)
}
}
/* Record that data is available for a queued command. Returns zero if
the device was reselected, nonzero if the IO is deferred. */
static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t arg)
static lsi_request *lsi_find_by_tag(LSIState *s, uint32_t tag)
{
lsi_request *p;
QTAILQ_FOREACH(p, &s->queue, next) {
if (p->tag == tag) {
if (p->pending) {
BADF("Multiple IO pending for tag %d\n", tag);
}
p->pending = arg;
/* Reselect if waiting for it, or if reselection triggers an IRQ
and the bus is free.
Since no interrupt stacking is implemented in the emulation, it
is also required that there are no pending interrupts waiting
for service from the device driver. */
if (s->waiting == 1 ||
(lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON) &&
!(s->istat0 & (LSI_ISTAT0_SIP | LSI_ISTAT0_DIP)))) {
/* Reselect device. */
lsi_reselect(s, p);
return 0;
} else {
DPRINTF("Queueing IO tag=0x%x\n", tag);
p->pending = arg;
return 1;
}
return p;
}
}
BADF("IO with unknown tag %d\n", tag);
return 1;
return NULL;
}
/* Callback to indicate that the SCSI layer has completed a transfer. */
static void lsi_command_complete(SCSIBus *bus, int reason, uint32_t tag,
uint32_t arg)
static void lsi_request_cancelled(SCSIRequest *req)
{
LSIState *s = DO_UPCAST(LSIState, dev.qdev, bus->qbus.parent);
LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
lsi_request *p;
if (s->current && req == s->current->req) {
scsi_req_unref(req);
qemu_free(s->current);
s->current = NULL;
return;
}
p = lsi_find_by_tag(s, req->tag);
if (p) {
QTAILQ_REMOVE(&s->queue, p, next);
scsi_req_unref(req);
qemu_free(p);
}
}
/* Record that data is available for a queued command. Returns zero if
the device was reselected, nonzero if the IO is deferred. */
static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t len)
{
lsi_request *p;
p = lsi_find_by_tag(s, tag);
if (!p) {
BADF("IO with unknown tag %d\n", tag);
return 1;
}
if (p->pending) {
BADF("Multiple IO pending for tag %d\n", tag);
}
p->pending = len;
/* Reselect if waiting for it, or if reselection triggers an IRQ
and the bus is free.
Since no interrupt stacking is implemented in the emulation, it
is also required that there are no pending interrupts waiting
for service from the device driver. */
if (s->waiting == 1 ||
(lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON) &&
!(s->istat0 & (LSI_ISTAT0_SIP | LSI_ISTAT0_DIP)))) {
/* Reselect device. */
lsi_reselect(s, p);
return 0;
} else {
DPRINTF("Queueing IO tag=0x%x\n", tag);
p->pending = len;
return 1;
}
}
/* Callback to indicate that the SCSI layer has completed a command. */
static void lsi_command_complete(SCSIRequest *req, uint32_t status)
{
LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
int out;
out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
if (reason == SCSI_REASON_DONE) {
DPRINTF("Command complete sense=%d\n", (int)arg);
s->sense = arg;
s->command_complete = 2;
if (s->waiting && s->dbc != 0) {
/* Raise phase mismatch for short transfers. */
lsi_bad_phase(s, out, PHASE_ST);
} else {
lsi_set_phase(s, PHASE_ST);
}
DPRINTF("Command complete status=%d\n", (int)status);
s->status = status;
s->command_complete = 2;
if (s->waiting && s->dbc != 0) {
/* Raise phase mismatch for short transfers. */
lsi_bad_phase(s, out, PHASE_ST);
} else {
lsi_set_phase(s, PHASE_ST);
}
if (s->current && req == s->current->req) {
scsi_req_unref(s->current->req);
qemu_free(s->current);
s->current = NULL;
lsi_resume_script(s);
return;
}
lsi_resume_script(s);
}
if (s->waiting == 1 || !s->current || tag != s->current->tag ||
/* Callback to indicate that the SCSI layer has completed a transfer. */
static void lsi_transfer_data(SCSIRequest *req, uint32_t len)
{
LSIState *s = DO_UPCAST(LSIState, dev.qdev, req->bus->qbus.parent);
int out;
if (s->waiting == 1 || !s->current || req->tag != s->current->tag ||
(lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON))) {
if (lsi_queue_tag(s, tag, arg))
if (lsi_queue_tag(s, req->tag, len)) {
return;
}
}
out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
/* host adapter (re)connected */
DPRINTF("Data ready tag=0x%x len=%d\n", tag, arg);
s->current->dma_len = arg;
DPRINTF("Data ready tag=0x%x len=%d\n", req->tag, len);
s->current->dma_len = len;
s->command_complete = 1;
if (!s->waiting)
return;
if (s->waiting == 1 || s->dbc == 0) {
lsi_resume_script(s);
} else {
lsi_do_dma(s, out);
if (s->waiting) {
if (s->waiting == 1 || s->dbc == 0) {
lsi_resume_script(s);
} else {
lsi_do_dma(s, out);
}
}
}
@ -755,16 +789,17 @@ static void lsi_do_command(LSIState *s)
assert(s->current == NULL);
s->current = qemu_mallocz(sizeof(lsi_request));
s->current->tag = s->select_tag;
s->current->req = scsi_req_new(dev, s->current->tag, s->current_lun);
n = dev->info->send_command(dev, s->current->tag, buf, s->current_lun);
if (n > 0) {
lsi_set_phase(s, PHASE_DI);
dev->info->read_data(dev, s->current->tag);
} else if (n < 0) {
lsi_set_phase(s, PHASE_DO);
dev->info->write_data(dev, s->current->tag);
n = scsi_req_enqueue(s->current->req, buf);
if (n) {
if (n > 0) {
lsi_set_phase(s, PHASE_DI);
} else if (n < 0) {
lsi_set_phase(s, PHASE_DO);
}
scsi_req_continue(s->current->req);
}
if (!s->command_complete) {
if (n) {
/* Command did not complete immediately so disconnect. */
@ -783,14 +818,14 @@ static void lsi_do_command(LSIState *s)
static void lsi_do_status(LSIState *s)
{
uint8_t sense;
DPRINTF("Get status len=%d sense=%d\n", s->dbc, s->sense);
uint8_t status;
DPRINTF("Get status len=%d status=%d\n", s->dbc, s->status);
if (s->dbc != 1)
BADF("Bad Status move\n");
s->dbc = 1;
sense = s->sense;
s->sfbr = sense;
cpu_physical_memory_write(s->dnad, &sense, 1);
status = s->status;
s->sfbr = status;
cpu_physical_memory_write(s->dnad, &status, 1);
lsi_set_phase(s, PHASE_MI);
s->msg_action = 1;
lsi_add_msg_byte(s, 0); /* COMMAND COMPLETE */
@ -855,13 +890,15 @@ static void lsi_do_msgout(LSIState *s)
int len;
uint32_t current_tag;
SCSIDevice *current_dev;
lsi_request *p, *p_next;
lsi_request *current_req, *p, *p_next;
int id;
if (s->current) {
current_tag = s->current->tag;
current_req = s->current;
} else {
current_tag = s->select_tag;
current_req = lsi_find_by_tag(s, current_tag);
}
id = (current_tag >> 8) & 0xf;
current_dev = s->bus.devs[id];
@ -913,7 +950,9 @@ static void lsi_do_msgout(LSIState *s)
case 0x0d:
/* The ABORT TAG message clears the current I/O process only. */
DPRINTF("MSG: ABORT TAG tag=0x%x\n", current_tag);
current_dev->info->cancel_io(current_dev, current_tag);
if (current_req) {
scsi_req_cancel(current_req->req);
}
lsi_disconnect(s);
break;
case 0x06:
@ -936,7 +975,9 @@ static void lsi_do_msgout(LSIState *s)
}
/* clear the current I/O process */
current_dev->info->cancel_io(current_dev, current_tag);
if (s->current) {
scsi_req_cancel(s->current->req);
}
/* As the current implemented devices scsi_disk and scsi_generic
only support one LUN, we don't need to keep track of LUNs.
@ -948,8 +989,7 @@ static void lsi_do_msgout(LSIState *s)
id = current_tag & 0x0000ff00;
QTAILQ_FOREACH_SAFE(p, &s->queue, next, p_next) {
if ((p->tag & 0x0000ff00) == id) {
current_dev->info->cancel_io(current_dev, p->tag);
QTAILQ_REMOVE(&s->queue, p, next);
scsi_req_cancel(p->req);
}
}
@ -2122,7 +2162,7 @@ static const VMStateDescription vmstate_lsi_scsi = {
VMSTATE_PCI_DEVICE(dev, LSIState),
VMSTATE_INT32(carry, LSIState),
VMSTATE_INT32(sense, LSIState),
VMSTATE_INT32(status, LSIState),
VMSTATE_INT32(msg_action, LSIState),
VMSTATE_INT32(msg_len, LSIState),
VMSTATE_BUFFER(msg, LSIState),
@ -2205,6 +2245,12 @@ static int lsi_scsi_uninit(PCIDevice *d)
return 0;
}
static const struct SCSIBusOps lsi_scsi_ops = {
.transfer_data = lsi_transfer_data,
.complete = lsi_command_complete,
.cancel = lsi_request_cancelled
};
static int lsi_scsi_init(PCIDevice *dev)
{
LSIState *s = DO_UPCAST(LSIState, dev, dev);
@ -2232,7 +2278,7 @@ static int lsi_scsi_init(PCIDevice *dev)
PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_ram_mapfunc);
QTAILQ_INIT(&s->queue);
scsi_bus_new(&s->bus, &dev->qdev, 1, LSI_MAX_DEVS, lsi_command_complete);
scsi_bus_new(&s->bus, &dev->qdev, 1, LSI_MAX_DEVS, &lsi_scsi_ops);
if (!dev->qdev.hotplugged) {
return scsi_bus_legacy_handle_cmdline(&s->bus);
}

View File

@ -155,7 +155,7 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
pci_set_word(dev->wmask + msi_data_off(dev, msi64bit), 0xffff);
if (msi_per_vector_mask) {
/* Make mask bits 0 to nr_vectors - 1 writeable. */
/* Make mask bits 0 to nr_vectors - 1 writable. */
pci_set_long(dev->wmask + msi_mask_off(dev, msi64bit),
0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors));
}

View File

@ -76,7 +76,7 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries,
pci_set_long(config + PCI_MSIX_PBA, (bar_size + MSIX_PAGE_PENDING) |
bar_nr);
pdev->msix_cap = config_offset;
/* Make flags bit writeable. */
/* Make flags bit writable. */
pdev->wmask[config_offset + MSIX_CONTROL_OFFSET] |= MSIX_ENABLE_MASK |
MSIX_MASKALL_MASK;
return 0;

View File

@ -154,7 +154,7 @@ mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
case MST_MSCRD:
s->mscrd = value;
break;
case MST_INTMSKENA: /* Mask interupt */
case MST_INTMSKENA: /* Mask interrupt */
s->intmskena = (value & 0xFEEFF);
qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
break;

View File

@ -307,7 +307,7 @@ int load_multiboot(void *fw_cfg,
| MULTIBOOT_FLAGS_MMAP);
stl_p(bootinfo + MBI_MEM_LOWER, 640);
stl_p(bootinfo + MBI_MEM_UPPER, (ram_size / 1024) - 1024);
stl_p(bootinfo + MBI_BOOT_DEVICE, 0x8001ffff); /* XXX: use the -boot switch? */
stl_p(bootinfo + MBI_BOOT_DEVICE, 0x8000ffff); /* XXX: use the -boot switch? */
stl_p(bootinfo + MBI_MMAP_ADDR, ADDR_E820_MAP);
mb_debug("multiboot: mh_entry_addr = %#x\n", mh_entry_addr);

37
hw/pc.c
View File

@ -957,29 +957,18 @@ void pc_cpus_init(const char *cpu_model)
}
}
void pc_memory_init(ram_addr_t ram_size,
const char *kernel_filename,
void pc_memory_init(const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename,
ram_addr_t *below_4g_mem_size_p,
ram_addr_t *above_4g_mem_size_p)
ram_addr_t below_4g_mem_size,
ram_addr_t above_4g_mem_size)
{
char *filename;
int ret, linux_boot, i;
ram_addr_t ram_addr, bios_offset, option_rom_offset;
ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
int bios_size, isa_bios_size;
void *fw_cfg;
if (ram_size >= 0xe0000000 ) {
above_4g_mem_size = ram_size - 0xe0000000;
below_4g_mem_size = 0xe0000000;
} else {
below_4g_mem_size = ram_size;
}
*above_4g_mem_size_p = above_4g_mem_size;
*below_4g_mem_size_p = below_4g_mem_size;
linux_boot = (kernel_filename != NULL);
/* allocate RAM */
@ -1081,6 +1070,15 @@ void pc_vga_init(PCIBus *pci_bus)
isa_vga_init();
}
}
/*
* sga does not suppress normal vga output. So a machine can have both a
* vga card and sga manually enabled. Output will be seen on both.
* For nographic case, sga is enabled at all times
*/
if (display_type == DT_NOGRAPHIC) {
isa_create_simple("sga");
}
}
static void cpu_request_exit(void *opaque, int irq, int level)
@ -1093,7 +1091,8 @@ static void cpu_request_exit(void *opaque, int irq, int level)
}
void pc_basic_device_init(qemu_irq *isa_irq,
ISADevice **rtc_state)
ISADevice **rtc_state,
bool no_vmport)
{
int i;
DriveInfo *fd[MAX_FD];
@ -1138,8 +1137,12 @@ void pc_basic_device_init(qemu_irq *isa_irq,
a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
i8042 = isa_create_simple("i8042");
i8042_setup_a20_line(i8042, &a20_line[0]);
vmport_init();
vmmouse = isa_try_create("vmmouse");
if (!no_vmport) {
vmport_init();
vmmouse = isa_try_create("vmmouse");
} else {
vmmouse = NULL;
}
if (vmmouse) {
qdev_prop_set_ptr(&vmmouse->qdev, "ps2_mouse", i8042);
qdev_init_nofail(&vmmouse->qdev);

11
hw/pc.h
View File

@ -129,16 +129,16 @@ void pc_cmos_set_s3_resume(void *opaque, int irq, int level);
void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
void pc_cpus_init(const char *cpu_model);
void pc_memory_init(ram_addr_t ram_size,
const char *kernel_filename,
void pc_memory_init(const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename,
ram_addr_t *below_4g_mem_size_p,
ram_addr_t *above_4g_mem_size_p);
ram_addr_t below_4g_mem_size,
ram_addr_t above_4g_mem_size);
qemu_irq *pc_allocate_cpu_irq(void);
void pc_vga_init(PCIBus *pci_bus);
void pc_basic_device_init(qemu_irq *isa_irq,
ISADevice **rtc_state);
ISADevice **rtc_state,
bool no_vmport);
void pc_init_ne2k_isa(NICInfo *nd);
void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
const char *boot_device,
@ -176,6 +176,7 @@ struct PCII440FXState;
typedef struct PCII440FXState PCII440FXState;
PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic, ram_addr_t ram_size);
PCIBus *i440fx_xen_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *pic, ram_addr_t ram_size);
void i440fx_init_memory_mappings(PCII440FXState *d);
/* piix4.c */

View File

@ -38,6 +38,10 @@
#include "arch_init.h"
#include "blockdev.h"
#include "smbus.h"
#include "xen.h"
#ifdef CONFIG_XEN
# include <xen/hvm/hvm_info_table.h>
#endif
#define MAX_IDE_BUS 2
@ -92,12 +96,26 @@ static void pc_init1(ram_addr_t ram_size,
kvmclock_create();
}
/* allocate ram and load rom/bios */
pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
&below_4g_mem_size, &above_4g_mem_size);
if (ram_size >= 0xe0000000 ) {
above_4g_mem_size = ram_size - 0xe0000000;
below_4g_mem_size = 0xe0000000;
} else {
above_4g_mem_size = 0;
below_4g_mem_size = ram_size;
}
cpu_irq = pc_allocate_cpu_irq();
i8259 = i8259_init(cpu_irq[0]);
/* allocate ram and load rom/bios */
if (!xen_enabled()) {
pc_memory_init(kernel_filename, kernel_cmdline, initrd_filename,
below_4g_mem_size, above_4g_mem_size);
}
if (!xen_enabled()) {
cpu_irq = pc_allocate_cpu_irq();
i8259 = i8259_init(cpu_irq[0]);
} else {
i8259 = xen_interrupt_controller_init();
}
isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
isa_irq_state->i8259 = i8259;
if (pci_enabled) {
@ -106,7 +124,11 @@ static void pc_init1(ram_addr_t ram_size,
isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
if (pci_enabled) {
pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
if (!xen_enabled()) {
pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
} else {
pci_bus = i440fx_xen_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
}
} else {
pci_bus = NULL;
i440fx_state = NULL;
@ -119,7 +141,7 @@ static void pc_init1(ram_addr_t ram_size,
pc_vga_init(pci_enabled? pci_bus: NULL);
/* init basic PC hardware */
pc_basic_device_init(isa_irq, &rtc_state);
pc_basic_device_init(isa_irq, &rtc_state, xen_enabled());
for(i = 0; i < nb_nics; i++) {
NICInfo *nd = &nd_table[i];
@ -157,7 +179,11 @@ static void pc_init1(ram_addr_t ram_size,
if (pci_enabled && acpi_enabled) {
i2c_bus *smbus;
cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
if (!xen_enabled()) {
cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
} else {
cmos_s3 = qemu_allocate_irqs(xen_cmos_set_s3_resume, rtc_state, 1);
}
smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
/* TODO: Populate SPD eeprom data. */
smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
@ -213,6 +239,24 @@ static void pc_init_isa(ram_addr_t ram_size,
initrd_filename, cpu_model, 0, 1);
}
#ifdef CONFIG_XEN
static void pc_xen_hvm_init(ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename,
const char *cpu_model)
{
if (xen_hvm_init() != 0) {
hw_error("xen hardware virtual machine initialisation failed");
}
pc_init_pci_no_kvmclock(ram_size, boot_device,
kernel_filename, kernel_cmdline,
initrd_filename, cpu_model);
xen_vcpu_init();
}
#endif
static QEMUMachine pc_machine = {
.name = "pc-0.14",
.alias = "pc",
@ -425,6 +469,16 @@ static QEMUMachine isapc_machine = {
.max_cpus = 1,
};
#ifdef CONFIG_XEN
static QEMUMachine xenfv_machine = {
.name = "xenfv",
.desc = "Xen Fully-virtualized PC",
.init = pc_xen_hvm_init,
.max_cpus = HVM_MAX_VCPUS,
.default_machine_opts = "accel=xen",
};
#endif
static void pc_machine_init(void)
{
qemu_register_machine(&pc_machine);
@ -433,6 +487,9 @@ static void pc_machine_init(void)
qemu_register_machine(&pc_machine_v0_11);
qemu_register_machine(&pc_machine_v0_10);
qemu_register_machine(&isapc_machine);
#ifdef CONFIG_XEN
qemu_register_machine(&xenfv_machine);
#endif
}
machine_init(pc_machine_init);

View File

@ -168,7 +168,7 @@ void pci_device_reset(PCIDevice *dev)
dev->irq_state = 0;
pci_update_irq_status(dev);
pci_device_deassert_intx(dev);
/* Clear all writeable bits */
/* Clear all writable bits */
pci_word_test_and_clear_mask(dev->config + PCI_COMMAND,
pci_get_word(dev->wmask + PCI_COMMAND) |
pci_get_word(dev->w1cmask + PCI_COMMAND));
@ -891,7 +891,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
wmask = ~(size - 1);
addr = pci_bar(pci_dev, region_num);
if (region_num == PCI_ROM_SLOT) {
/* ROM enable bit is writeable */
/* ROM enable bit is writable */
wmask |= PCI_ROM_ADDRESS_ENABLE;
}
pci_set_long(pci_dev->config + addr, type);
@ -1940,6 +1940,8 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
pci_patch_ids(pdev, ptr, size);
}
qemu_put_ram_ptr(ptr);
pci_register_bar(pdev, PCI_ROM_SLOT, size,
0, pci_map_option_rom);
@ -1993,7 +1995,7 @@ void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size)
if (!offset)
return;
pdev->config[prev] = pdev->config[offset + PCI_CAP_LIST_NEXT];
/* Make capability writeable again */
/* Make capability writable again */
memset(pdev->wmask + offset, 0xff, size);
memset(pdev->w1cmask + offset, 0, size);
/* Clear cmask as device-specific registers can't be checked */

View File

@ -132,7 +132,7 @@ struct PCIDevice {
/* PCI config space */
uint8_t *config;
/* Used to enable config checks on load. Note that writeable bits are
/* Used to enable config checks on load. Note that writable bits are
* never checked even if set in cmask. */
uint8_t *cmask;

View File

@ -100,6 +100,7 @@
#define PCI_VENDOR_ID_INTEL 0x8086
#define PCI_DEVICE_ID_INTEL_82441 0x1237
#define PCI_DEVICE_ID_INTEL_82801AA_5 0x2415
#define PCI_DEVICE_ID_INTEL_82801D 0x24CD
#define PCI_DEVICE_ID_INTEL_ESB_9 0x25ab
#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010

Some files were not shown because too many files have changed in this diff Show More