mirror of https://gitee.com/openkylin/qemu.git
Merge remote-tracking branch 'origin/master' into pci
Conflicts: hw/virtio-pci.c
This commit is contained in:
commit
befeac45d4
|
@ -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).
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
7
Makefile
7
Makefile
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
54
QMP/qmp.py
54
QMP/qmp.py
|
@ -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 @@ def __get_sock(self):
|
|||
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 @@ def __json_read(self):
|
|||
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 @@ def connect(self):
|
|||
@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 @@ def cmd(self, name, args=None, id=None):
|
|||
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 @@ def get_events(self):
|
|||
# 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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -709,6 +709,11 @@ int audio_available(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
int tcg_available(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int kvm_available(void)
|
||||
{
|
||||
#ifdef CONFIG_KVM
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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, ...)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
49
block.c
|
@ -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];
|
||||
|
|
5
block.h
5
block.h
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
129
block/qed.c
129
block/qed.c
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
912
block/rbd.c
912
block/rbd.c
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
22
block/vmdk.c
22
block/vmdk.c
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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`"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
67
cpu-all.h
67
cpu-all.h
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
676
cpu-exec.c
676
cpu-exec.c
|
@ -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) */
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
# Default configuration for s390x-linux-user
|
|
@ -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
|
||||
|
|
2
disas.c
2
disas.c
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
128
exec.c
|
@ -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) {
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
103
fpu/softfloat.c
103
fpu/softfloat.c
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
12
gdbstub.c
12
gdbstub.c
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
1048
hw/alpha_palcode.c
1048
hw/alpha_palcode.c
File diff suppressed because it is too large
Load Diff
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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? */
|
||||
|
|
2
hw/bt.h
2
hw/bt.h
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
119
hw/esp.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
214
hw/lsi53c895a.c
214
hw/lsi53c895a.c
|
@ -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);
|
||||
}
|
||||
|
|
2
hw/msi.c
2
hw/msi.c
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
37
hw/pc.c
|
@ -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
11
hw/pc.h
|
@ -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 */
|
||||
|
|
73
hw/pc_piix.c
73
hw/pc_piix.c
|
@ -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);
|
||||
|
|
8
hw/pci.c
8
hw/pci.c
|
@ -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 */
|
||||
|
|
2
hw/pci.h
2
hw/pci.h
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue