aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS1
-rw-r--r--Makefile15
-rw-r--r--Makefile.objs2
-rw-r--r--Makefile.target2
-rw-r--r--block/vmdk.c2
-rw-r--r--cache-utils.h3
-rwxr-xr-xconfigure28
-rw-r--r--console.h3
-rw-r--r--cpu-all.h2
-rw-r--r--cursor.c3
-rw-r--r--docs/libcacard.txt26
-rw-r--r--docs/tracing.txt48
-rw-r--r--gdbstub.c2
-rw-r--r--hw/cuda.c2
-rw-r--r--hw/exynos4210_mct.c2
-rw-r--r--hw/i8254.c281
-rw-r--r--hw/i8254.h11
-rw-r--r--hw/i8254_common.c311
-rw-r--r--hw/i8254_internal.h85
-rw-r--r--hw/ide/ahci.c4
-rw-r--r--hw/ide/cmd646.c6
-rw-r--r--hw/ide/macio.c2
-rw-r--r--hw/ide/piix.c2
-rw-r--r--hw/ide/via.c2
-rw-r--r--hw/kvm/i8254.c254
-rw-r--r--hw/mipsnet.c2
-rw-r--r--hw/opencores_eth.c4
-rw-r--r--hw/pc.c14
-rw-r--r--hw/qdev-properties.c4
-rw-r--r--hw/sh7750.c2
-rw-r--r--hw/sh_intc.c2
-rw-r--r--hw/spapr_pci.c2
-rw-r--r--hw/usb-ccid.c2
-rw-r--r--hw/usb-ehci.c204
-rw-r--r--hw/usb-ohci.c2
-rw-r--r--hw/usb-uhci.c2
-rw-r--r--hw/usb-xhci.c15
-rw-r--r--hw/usb.c73
-rw-r--r--hw/usb.h14
-rw-r--r--hw/vga.c2
-rw-r--r--hw/zynq_slcr.c4
-rw-r--r--include/qemu/object.h6
-rw-r--r--kvm-all.c14
-rw-r--r--kvm-stub.c5
-rw-r--r--kvm.h1
-rw-r--r--libcacard/vcardt.h4
-rw-r--r--libcacard/vscclient.c22
-rw-r--r--linux-user/signal.c2
-rw-r--r--osdep.h3
-rw-r--r--qapi-schema.json16
-rw-r--r--qemu-common.h8
-rw-r--r--qemu-file.h2
-rw-r--r--qjson.h1
-rw-r--r--qom/object.c7
-rwxr-xr-xscripts/tracetool13
-rw-r--r--sysconfigs/target/target-x86_64.conf28
-rw-r--r--target-i386/cpu.h1
-rw-r--r--target-i386/cpuid.c2
-rw-r--r--target-i386/helper.c13
-rw-r--r--target-i386/kvm.c6
-rw-r--r--target-mips/op_helper.c2
-rw-r--r--tcg/hppa/tcg-target.c8
-rw-r--r--tcg/i386/tcg-target.c8
-rw-r--r--tcg/sparc/tcg-target.c6
-rw-r--r--tcg/tcg.c6
-rw-r--r--test-qmp-output-visitor.c4
-rw-r--r--trace-events7
-rw-r--r--trace/simple.c2
-rw-r--r--ui/vnc-enc-hextile-template.h1
-rw-r--r--ui/vnc.c5
-rw-r--r--usb-linux.c15
-rw-r--r--usb-redir.c21
-rw-r--r--vl.c20
73 files changed, 1178 insertions, 528 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index d249947d12..f83d07c2c4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -548,6 +548,7 @@ Tracing
M: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
S: Maintained
F: trace/
+F: docs/tracing.txt
T: git://github.com/stefanha/qemu.git tracing
Checkpatch
diff --git a/Makefile b/Makefile
index 49c775b82d..408065e0b1 100644
--- a/Makefile
+++ b/Makefile
@@ -3,13 +3,7 @@
# Always point to the root of the build tree (needs GNU make).
BUILD_DIR=$(CURDIR)
-GENERATED_HEADERS = config-host.h trace.h qemu-options.def
-ifeq ($(TRACE_BACKEND),dtrace)
-GENERATED_HEADERS += trace-dtrace.h
-endif
-GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
-GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
-
+# All following code might depend on configuration variables
ifneq ($(wildcard config-host.mak),)
# Put the all: rule here so that config-host.mak can contain dependencies.
all: build-all
@@ -24,6 +18,13 @@ config-host.mak:
@exit 1
endif
+GENERATED_HEADERS = config-host.h trace.h qemu-options.def
+ifeq ($(TRACE_BACKEND),dtrace)
+GENERATED_HEADERS += trace-dtrace.h
+endif
+GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
+GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
+
# Don't try to regenerate Makefile or configure
# We don't generate any of them
Makefile: ;
diff --git a/Makefile.objs b/Makefile.objs
index 808de6a250..b39d76cbb6 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -210,7 +210,7 @@ hw-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
hw-obj-$(CONFIG_SERIAL) += serial.o
hw-obj-$(CONFIG_PARALLEL) += parallel.o
-hw-obj-$(CONFIG_I8254) += i8254.o
+hw-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
hw-obj-$(CONFIG_PCSPK) += pcspk.o
hw-obj-$(CONFIG_PCKBD) += pckbd.o
hw-obj-$(CONFIG_USB_UHCI) += usb-uhci.o
diff --git a/Makefile.target b/Makefile.target
index 5f3fc40fe5..1bd25a89ad 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -244,7 +244,7 @@ obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
obj-i386-y += debugcon.o multiboot.o
obj-i386-y += pc_piix.o
obj-i386-y += pc_sysfw.o
-obj-i386-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o kvm/i8259.o kvm/ioapic.o
+obj-i386-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o kvm/i8259.o kvm/ioapic.o kvm/i8254.o
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
# shared objects
diff --git a/block/vmdk.c b/block/vmdk.c
index 5623ac10cd..45c003a0f1 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -453,7 +453,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
}
l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
* le64_to_cpu(header.granularity);
- if (l1_entry_sectors <= 0) {
+ if (l1_entry_sectors == 0) {
return -EINVAL;
}
l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1)
diff --git a/cache-utils.h b/cache-utils.h
index 04a6e2e9c9..2c57f78fc1 100644
--- a/cache-utils.h
+++ b/cache-utils.h
@@ -2,6 +2,9 @@
#define QEMU_CACHE_UTILS_H
#if defined(_ARCH_PPC)
+
+#include <stdint.h> /* uintptr_t */
+
struct qemu_cache_conf {
unsigned long dcache_bsize;
unsigned long icache_bsize;
diff --git a/configure b/configure
index a5eb8323e9..39d2b54519 100755
--- a/configure
+++ b/configure
@@ -22,7 +22,9 @@ rm -f config.log
# Print a helpful header at the top of config.log
echo "# QEMU configure log $(date)" >> config.log
-echo "# produced by $0 $*" >> config.log
+printf "# Configured with:" >> config.log
+printf " '%s'" "$0" "$@" >> config.log
+echo >> config.log
echo "#" >> config.log
compile_object() {
@@ -232,7 +234,7 @@ for opt do
done
# OS specific
# Using uname is really, really broken. Once we have the right set of checks
-# we can eliminate it's usage altogether
+# we can eliminate its usage altogether.
cc="${CC-${cross_prefix}gcc}"
ar="${AR-${cross_prefix}ar}"
@@ -509,7 +511,13 @@ if test "$mingw32" = "yes" ; then
QEMU_CFLAGS="-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS"
# enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later)
QEMU_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $QEMU_CFLAGS"
- LIBS="-lwinmm -lws2_32 -liberty -liphlpapi $LIBS"
+ LIBS="-lwinmm -lws2_32 -liphlpapi $LIBS"
+cat > $TMPC << EOF
+int main(void) { return 0; }
+EOF
+ if compile_prog "" "-liberty" ; then
+ LIBS="-liberty $LIBS"
+ fi
prefix="c:/Program Files/Qemu"
mandir="\${prefix}"
datadir="\${prefix}"
@@ -2524,17 +2532,6 @@ if test "$darwin" != "yes" -a "$mingw32" != "yes" -a "$solaris" != yes -a \
fi
##########################################
-# check if the compiler defines offsetof
-
-need_offsetof=yes
-cat > $TMPC << EOF
-#include <stddef.h>
-int main(void) { struct s { int f; }; return offsetof(struct s, f); }
-EOF
-if compile_prog "" "" ; then
- need_offsetof=no
-fi
-
# spice probe
if test "$spice" != "no" ; then
cat > $TMPC << EOF
@@ -3199,9 +3196,6 @@ fi
if test "$tcg_interpreter" = "yes" ; then
echo "CONFIG_TCG_INTERPRETER=y" >> $config_host_mak
fi
-if test "$need_offsetof" = "yes" ; then
- echo "CONFIG_NEED_OFFSETOF=y" >> $config_host_mak
-fi
if test "$fdatasync" = "yes" ; then
echo "CONFIG_FDATASYNC=y" >> $config_host_mak
fi
diff --git a/console.h b/console.h
index a95b5812eb..4334db5ca5 100644
--- a/console.h
+++ b/console.h
@@ -5,6 +5,7 @@
#include "qdict.h"
#include "notify.h"
#include "monitor.h"
+#include "trace.h"
/* keyboard/mouse support */
@@ -202,11 +203,13 @@ static inline DisplaySurface* qemu_create_displaysurface(DisplayState *ds, int w
static inline DisplaySurface* qemu_resize_displaysurface(DisplayState *ds, int width, int height)
{
+ trace_displaysurface_resize(ds, ds->surface, width, height);
return ds->allocator->resize_displaysurface(ds->surface, width, height);
}
static inline void qemu_free_displaysurface(DisplayState *ds)
{
+ trace_displaysurface_free(ds, ds->surface);
ds->allocator->free_displaysurface(ds->surface);
}
diff --git a/cpu-all.h b/cpu-all.h
index b87f2ce5d5..f7f6e7acd3 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -197,7 +197,7 @@ extern unsigned long reserved_va;
#endif
/* All direct uses of g2h and h2g need to go away for usermode softmmu. */
-#define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE))
+#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + GUEST_BASE))
#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
#define h2g_valid(x) 1
diff --git a/cursor.c b/cursor.c
index efc5917029..76e262caf7 100644
--- a/cursor.c
+++ b/cursor.c
@@ -15,7 +15,8 @@ static QEMUCursor *cursor_parse_xpm(const char *xpm[])
uint8_t idx;
/* parse header line: width, height, #colors, #chars */
- if (sscanf(xpm[line], "%d %d %d %d", &width, &height, &colors, &chars) != 4) {
+ if (sscanf(xpm[line], "%u %u %u %u",
+ &width, &height, &colors, &chars) != 4) {
fprintf(stderr, "%s: header parse error: \"%s\"\n",
__FUNCTION__, xpm[line]);
return NULL;
diff --git a/docs/libcacard.txt b/docs/libcacard.txt
index f7d7519f3a..8db421d3a9 100644
--- a/docs/libcacard.txt
+++ b/docs/libcacard.txt
@@ -10,7 +10,7 @@ such as signing, card removal/insertion, etc. are mapped to real, physical
cards which are shared with the client machine the emulator is running on, or
the cards could be pure software constructs.
-The emulator is structured to allow multiple replacable or additional pieces,
+The emulator is structured to allow multiple replaceable or additional pieces,
so it can be easily modified for future requirements. The primary envisioned
modifications are:
@@ -32,7 +32,7 @@ be emulated as well, including PIV, newer versions of CAC, PKCS #15, etc.
--------------------
Replacing the Socket Based Virtual Reader Interface.
-The current implementation contains a replacable module vscclient.c. The
+The current implementation contains a replaceable module vscclient.c. The
current vscclient.c implements a sockets interface to the virtual ccid reader
on the guest. CCID commands that are pertinent to emulation are passed
across the socket, and their responses are passed back along that same socket.
@@ -42,7 +42,7 @@ implements a program with a main entry. It also handles argument parsing for
the emulator.
An application that wants to use the virtual reader can replace vscclient.c
-with it's own implementation that connects to it's own CCID reader. The calls
+with its own implementation that connects to its own CCID reader. The calls
that the CCID reader can call are:
VReaderList * vreader_get_reader_list();
@@ -72,12 +72,12 @@ that the CCID reader can call are:
VReader * vreader_list_get_reader(VReaderListEntry *)
This function returns the reader stored in the reader List entry. Caller gets
- a new reference to a reader. The caller must free it's reference when it is
+ a new reference to a reader. The caller must free its reference when it is
finished with vreader_free().
void vreader_free(VReader *reader);
- This function frees a reference to a reader. Reader's are reference counted
+ This function frees a reference to a reader. Readers are reference counted
and are automatically deleted when the last reference is freed.
void vreader_list_delete(VReaderList *list);
@@ -87,7 +87,7 @@ that the CCID reader can call are:
VReaderStatus vreader_power_on(VReader *reader, char *atr, int *len);
- This functions simulates a card power on. Virtual cards do not care about
+ This function simulates a card power on. A virtual card does not care about
the actual voltage and other physical parameters, but it does care that the
card is actually on or off. Cycling the card causes the card to reset. If
the caller provides enough space, vreader_power_on will return the ATR of
@@ -104,7 +104,7 @@ that the CCID reader can call are:
unsigned char *receive_buf,
int receive_buf_len);
- This functions send a raw apdu to a card and returns the card's response.
+ This function sends a raw apdu to a card and returns the card's response.
The CCID front end should return the response back. Most of the emulation
is driven from these APDUs.
@@ -217,10 +217,10 @@ the card using the following functions:
VCardStatus vcard_add_applet(VCard *card, VCardApplet *applet);
Add an applet onto the list of applets attached to the card. Once an applet
- has been added, it can be selected by it's aid, and then commands will be
- routed to it VCardProcessAPDU function. This function adopts the applet the
- passed int applet. Note: 2 applets with the same AID should not be added to
- the same card. It's permissible to add more than one applet. Multiple applets
+ has been added, it can be selected by its AID, and then commands will be
+ routed to it VCardProcessAPDU function. This function adopts the applet that
+ is passed into it. Note: 2 applets with the same AID should not be added to
+ the same card. It is permissible to add more than one applet. Multiple applets
may have the same VCardPRocessAPDU entry point.
The certs and keys should be attached to private data associated with one or
@@ -335,7 +335,7 @@ and applet.
VCard7816Status vcard_emul_login(VCard *card, unsigned char *pin,
int pin_len);
- This function logins into the card and return the standard 7816 status
+ This function logs into the card and returns the standard 7816 status
word depending on the success or failure of the call.
void vcard_emul_delete_key(VCardKey *key);
@@ -424,7 +424,7 @@ functions:
cert_len, and keys are all arrays of length cert_count. These are the
the same of the parameters xxxx_card_init() accepts.
- Finally the card is associated with it's reader by the call:
+ Finally the card is associated with its reader by the call:
VReaderStatus vreader_insert_card(VReader *vreader, VCard *vcard);
diff --git a/docs/tracing.txt b/docs/tracing.txt
index ea29f2c222..c541133368 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -9,7 +9,7 @@ for debugging, profiling, and observing execution.
1. Build with the 'simple' trace backend:
- ./configure --trace-backend=simple
+ ./configure --enable-trace-backend=simple
make
2. Create a file with the events you want to trace:
@@ -98,12 +98,6 @@ respectively. This ensures portability between 32- and 64-bit platforms.
4. Name trace events after their function. If there are multiple trace events
in one function, append a unique distinguisher at the end of the name.
-5. If specific trace events are going to be called a huge number of times, this
- might have a noticeable performance impact even when the trace events are
- programmatically disabled. In this case you should declare the trace event
- with the "disable" property, which will effectively disable it at compile
- time (using the "nop" backend).
-
== Generic interface and monitor commands ==
You can programmatically query and control the dynamic state of trace events
@@ -234,3 +228,43 @@ probes:
--target-type system \
--target-arch x86_64 \
<trace-events >qemu.stp
+
+== Trace event properties ==
+
+Each event in the "trace-events" file can be prefixed with a space-separated
+list of zero or more of the following event properties.
+
+=== "disable" ===
+
+If a specific trace event is going to be invoked a huge number of times, this
+might have a noticeable performance impact even when the event is
+programmatically disabled.
+
+In this case you should declare such event with the "disable" property. This
+will effectively disable the event at compile time (by using the "nop" backend),
+thus having no performance impact at all on regular builds (i.e., unless you
+edit the "trace-events" file).
+
+In addition, there might be cases where relatively complex computations must be
+performed to generate values that are only used as arguments for a trace
+function. In these cases you can use the macro 'TRACE_${EVENT_NAME}_ENABLED' to
+guard such computations and avoid its compilation when the event is disabled:
+
+ #include "trace.h" /* needed for trace event prototype */
+
+ void *qemu_vmalloc(size_t size)
+ {
+ void *ptr;
+ size_t align = QEMU_VMALLOC_ALIGN;
+
+ if (size < align) {
+ align = getpagesize();
+ }
+ ptr = qemu_memalign(align, size);
+ if (TRACE_QEMU_VMALLOC_ENABLED) { /* preprocessor macro */
+ void *complex;
+ /* some complex computations to produce the 'complex' value */
+ trace_qemu_vmalloc(size, ptr, complex);
+ }
+ return ptr;
+ }
diff --git a/gdbstub.c b/gdbstub.c
index 7d470b608e..ef95ac29ba 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2062,9 +2062,11 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
goto unknown_command;
}
case 'k':
+#ifdef CONFIG_USER_ONLY
/* Kill the target */
fprintf(stderr, "\nQEMU: Terminated via GDBstub\n");
exit(0);
+#endif
case 'D':
/* Detach packet */
gdb_breakpoint_remove_all();
diff --git a/hw/cuda.c b/hw/cuda.c
index 40774360df..233ab666da 100644
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -634,7 +634,7 @@ static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr)
return 0;
}
-static MemoryRegionOps cuda_ops = {
+static const MemoryRegionOps cuda_ops = {
.old_mmio = {
.write = {
cuda_writeb,
diff --git a/hw/exynos4210_mct.c b/hw/exynos4210_mct.c
index 01e3fb8a3b..7474fcf802 100644
--- a/hw/exynos4210_mct.c
+++ b/hw/exynos4210_mct.c
@@ -888,7 +888,7 @@ static void exynos4210_ltick_event(void *opaque)
static uint64_t time2[2] = {0};
#endif
- /* Call tick_timer event handler, it will update it's tcntb and icntb */
+ /* Call tick_timer event handler, it will update its tcntb and icntb. */
exynos4210_ltick_timer_event(&s->tick_timer);
/* get tick_timer cnt */
diff --git a/hw/i8254.c b/hw/i8254.c
index f30396af88..77bd5e8222 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -26,6 +26,7 @@
#include "isa.h"
#include "qemu-timer.h"
#include "i8254.h"
+#include "i8254_internal.h"
//#define DEBUG_PIT
@@ -34,34 +35,6 @@
#define RW_STATE_WORD0 3
#define RW_STATE_WORD1 4
-typedef struct PITChannelState {
- int count; /* can be 65536 */
- uint16_t latched_count;
- uint8_t count_latched;
- uint8_t status_latched;
- uint8_t status;
- uint8_t read_state;
- uint8_t write_state;
- uint8_t write_latch;
- uint8_t rw_mode;
- uint8_t mode;
- uint8_t bcd; /* not supported */
- uint8_t gate; /* timer start */
- int64_t count_load_time;
- /* irq handling */
- int64_t next_transition_time;
- QEMUTimer *irq_timer;
- qemu_irq irq;
- uint32_t irq_disabled;
-} PITChannelState;
-
-typedef struct PITState {
- ISADevice dev;
- MemoryRegion ioports;
- uint32_t iobase;
- PITChannelState channels[3];
-} PITState;
-
static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
static int pit_get_count(PITChannelState *s)
@@ -89,99 +62,11 @@ static int pit_get_count(PITChannelState *s)
return counter;
}
-/* get pit output bit */
-static int pit_get_out(PITChannelState *s, int64_t current_time)
-{
- uint64_t d;
- int out;
-
- d = muldiv64(current_time - s->count_load_time, PIT_FREQ,
- get_ticks_per_sec());
- switch(s->mode) {
- default:
- case 0:
- out = (d >= s->count);
- break;
- case 1:
- out = (d < s->count);
- break;
- case 2:
- if ((d % s->count) == 0 && d != 0)
- out = 1;
- else
- out = 0;
- break;
- case 3:
- out = (d % s->count) < ((s->count + 1) >> 1);
- break;
- case 4:
- case 5:
- out = (d == s->count);
- break;
- }
- return out;
-}
-
-/* return -1 if no transition will occur. */
-static int64_t pit_get_next_transition_time(PITChannelState *s,
- int64_t current_time)
-{
- uint64_t d, next_time, base;
- int period2;
-
- d = muldiv64(current_time - s->count_load_time, PIT_FREQ,
- get_ticks_per_sec());
- switch(s->mode) {
- default:
- case 0:
- case 1:
- if (d < s->count)
- next_time = s->count;
- else
- return -1;
- break;
- case 2:
- base = (d / s->count) * s->count;
- if ((d - base) == 0 && d != 0)
- next_time = base + s->count;
- else
- next_time = base + s->count + 1;
- break;
- case 3:
- base = (d / s->count) * s->count;
- period2 = ((s->count + 1) >> 1);
- if ((d - base) < period2)
- next_time = base + period2;
- else
- next_time = base + s->count;
- break;
- case 4:
- case 5:
- if (d < s->count)
- next_time = s->count;
- else if (d == s->count)
- next_time = s->count + 1;
- else
- return -1;
- break;
- }
- /* convert to timer units */
- next_time = s->count_load_time + muldiv64(next_time, get_ticks_per_sec(),
- PIT_FREQ);
- /* fix potential rounding problems */
- /* XXX: better solution: use a clock at PIT_FREQ Hz */
- if (next_time <= current_time)
- next_time = current_time + 1;
- return next_time;
-}
-
/* val must be 0 or 1 */
-void pit_set_gate(ISADevice *dev, int channel, int val)
+static void pit_set_channel_gate(PITCommonState *s, PITChannelState *sc,
+ int val)
{
- PITState *pit = DO_UPCAST(PITState, dev, dev);
- PITChannelState *s = &pit->channels[channel];
-
- switch(s->mode) {
+ switch (sc->mode) {
default:
case 0:
case 4:
@@ -189,34 +74,23 @@ void pit_set_gate(ISADevice *dev, int channel, int val)
break;
case 1:
case 5:
- if (s->gate < val) {
+ if (sc->gate < val) {
/* restart counting on rising edge */
- s->count_load_time = qemu_get_clock_ns(vm_clock);
- pit_irq_timer_update(s, s->count_load_time);
+ sc->count_load_time = qemu_get_clock_ns(vm_clock);
+ pit_irq_timer_update(sc, sc->count_load_time);
}
break;
case 2:
case 3:
- if (s->gate < val) {
+ if (sc->gate < val) {
/* restart counting on rising edge */
- s->count_load_time = qemu_get_clock_ns(vm_clock);
- pit_irq_timer_update(s, s->count_load_time);
+ sc->count_load_time = qemu_get_clock_ns(vm_clock);
+ pit_irq_timer_update(sc, sc->count_load_time);
}
/* XXX: disable/enable counting */
break;
}
- s->gate = val;
-}
-
-void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info)
-{
- PITState *pit = DO_UPCAST(PITState, dev, dev);
- PITChannelState *s = &pit->channels[channel];
-
- info->gate = s->gate;
- info->mode = s->mode;
- info->initial_count = s->count;
- info->out = pit_get_out(s, qemu_get_clock_ns(vm_clock));
+ sc->gate = val;
}
static inline void pit_load_count(PITChannelState *s, int val)
@@ -239,7 +113,7 @@ static void pit_latch_count(PITChannelState *s)
static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
- PITState *pit = opaque;
+ PITCommonState *pit = opaque;
int channel, access;
PITChannelState *s;
@@ -306,7 +180,7 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
{
- PITState *pit = opaque;
+ PITCommonState *pit = opaque;
int ret, count;
PITChannelState *s;
@@ -387,94 +261,16 @@ static void pit_irq_timer(void *opaque)
pit_irq_timer_update(s, s->next_transition_time);
}
-static const VMStateDescription vmstate_pit_channel = {
- .name = "pit channel",
- .version_id = 2,
- .minimum_version_id = 2,
- .minimum_version_id_old = 2,
- .fields = (VMStateField []) {
- VMSTATE_INT32(count, PITChannelState),
- VMSTATE_UINT16(latched_count, PITChannelState),
- VMSTATE_UINT8(count_latched, PITChannelState),
- VMSTATE_UINT8(status_latched, PITChannelState),
- VMSTATE_UINT8(status, PITChannelState),
- VMSTATE_UINT8(read_state, PITChannelState),
- VMSTATE_UINT8(write_state, PITChannelState),
- VMSTATE_UINT8(write_latch, PITChannelState),
- VMSTATE_UINT8(rw_mode, PITChannelState),
- VMSTATE_UINT8(mode, PITChannelState),
- VMSTATE_UINT8(bcd, PITChannelState),
- VMSTATE_UINT8(gate, PITChannelState),
- VMSTATE_INT64(count_load_time, PITChannelState),
- VMSTATE_INT64(next_transition_time, PITChannelState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static int pit_load_old(QEMUFile *f, void *opaque, int version_id)
+static void pit_reset(DeviceState *dev)
{
- PITState *pit = opaque;
+ PITCommonState *pit = DO_UPCAST(PITCommonState, dev.qdev, dev);
PITChannelState *s;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- for(i = 0; i < 3; i++) {
- s = &pit->channels[i];
- s->count=qemu_get_be32(f);
- qemu_get_be16s(f, &s->latched_count);
- qemu_get_8s(f, &s->count_latched);
- qemu_get_8s(f, &s->status_latched);
- qemu_get_8s(f, &s->status);
- qemu_get_8s(f, &s->read_state);
- qemu_get_8s(f, &s->write_state);
- qemu_get_8s(f, &s->write_latch);
- qemu_get_8s(f, &s->rw_mode);
- qemu_get_8s(f, &s->mode);
- qemu_get_8s(f, &s->bcd);
- qemu_get_8s(f, &s->gate);
- s->count_load_time=qemu_get_be64(f);
- s->irq_disabled = 0;
- if (s->irq_timer) {
- s->next_transition_time=qemu_get_be64(f);
- qemu_get_timer(f, s->irq_timer);
- }
- }
- return 0;
-}
-static const VMStateDescription vmstate_pit = {
- .name = "i8254",
- .version_id = 3,
- .minimum_version_id = 2,
- .minimum_version_id_old = 1,
- .load_state_old = pit_load_old,
- .fields = (VMStateField []) {
- VMSTATE_UINT32_V(channels[0].irq_disabled, PITState, 3),
- VMSTATE_STRUCT_ARRAY(channels, PITState, 3, 2, vmstate_pit_channel, PITChannelState),
- VMSTATE_TIMER(channels[0].irq_timer, PITState),
- VMSTATE_END_OF_LIST()
- }
-};
+ pit_reset_common(pit);
-static void pit_reset(DeviceState *dev)
-{
- PITState *pit = container_of(dev, PITState, dev.qdev);
- PITChannelState *s;
- int i;
-
- for(i = 0;i < 3; i++) {
- s = &pit->channels[i];
- s->mode = 3;
- s->gate = (i != 2);
- s->count_load_time = qemu_get_clock_ns(vm_clock);
- s->count = 0x10000;
- if (i == 0 && !s->irq_disabled) {
- s->next_transition_time =
- pit_get_next_transition_time(s, s->count_load_time);
- qemu_mod_timer(s->irq_timer, s->next_transition_time);
- }
+ s = &pit->channels[0];
+ if (!s->irq_disabled) {
+ qemu_mod_timer(s->irq_timer, s->next_transition_time);
}
}
@@ -482,7 +278,7 @@ static void pit_reset(DeviceState *dev)
* reenable it when legacy mode is left again. */
static void pit_irq_control(void *opaque, int n, int enable)
{
- PITState *pit = opaque;
+ PITCommonState *pit = opaque;
PITChannelState *s = &pit->channels[0];
if (enable) {
@@ -504,46 +300,55 @@ static const MemoryRegionOps pit_ioport_ops = {
.old_portio = pit_portio
};
-static int pit_initfn(ISADevice *dev)
+static void pit_post_load(PITCommonState *s)
+{
+ PITChannelState *sc = &s->channels[0];
+
+ if (sc->next_transition_time != -1) {
+ qemu_mod_timer(sc->irq_timer, sc->next_transition_time);
+ } else {
+ qemu_del_timer(sc->irq_timer);
+ }
+}
+
+static int pit_initfn(PITCommonState *pit)
{
- PITState *pit = DO_UPCAST(PITState, dev, dev);
PITChannelState *s;
s = &pit->channels[0];
/* the timer 0 is connected to an IRQ */
s->irq_timer = qemu_new_timer_ns(vm_clock, pit_irq_timer, s);
- qdev_init_gpio_out(&dev->qdev, &s->irq, 1);
+ qdev_init_gpio_out(&pit->dev.qdev, &s->irq, 1);
memory_region_init_io(&pit->ioports, &pit_ioport_ops, pit, "pit", 4);
- isa_register_ioport(dev, &pit->ioports, pit->iobase);
- qdev_init_gpio_in(&dev->qdev, pit_irq_control, 1);
-
- qdev_set_legacy_instance_id(&dev->qdev, pit->iobase, 2);
+ qdev_init_gpio_in(&pit->dev.qdev, pit_irq_control, 1);
return 0;
}
static Property pit_properties[] = {
- DEFINE_PROP_HEX32("iobase", PITState, iobase, -1),
+ DEFINE_PROP_HEX32("iobase", PITCommonState, iobase, -1),
DEFINE_PROP_END_OF_LIST(),
};
static void pit_class_initfn(ObjectClass *klass, void *data)
{
+ PITCommonClass *k = PIT_COMMON_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
- ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
- ic->init = pit_initfn;
- dc->no_user = 1;
+
+ k->init = pit_initfn;
+ k->set_channel_gate = pit_set_channel_gate;
+ k->get_channel_info = pit_get_channel_info_common;
+ k->post_load = pit_post_load;
dc->reset = pit_reset;
- dc->vmsd = &vmstate_pit;
dc->props = pit_properties;
}
static TypeInfo pit_info = {
.name = "isa-pit",
- .parent = TYPE_ISA_DEVICE,
- .instance_size = sizeof(PITState),
+ .parent = TYPE_PIT_COMMON,
+ .instance_size = sizeof(PITCommonState),
.class_init = pit_class_initfn,
};
diff --git a/hw/i8254.h b/hw/i8254.h
index a1d2e9835b..ba6b598a99 100644
--- a/hw/i8254.h
+++ b/hw/i8254.h
@@ -51,6 +51,17 @@ static inline ISADevice *pit_init(ISABus *bus, int base, int isa_irq,
return dev;
}
+static inline ISADevice *kvm_pit_init(ISABus *bus, int base)
+{
+ ISADevice *dev;
+
+ dev = isa_create(bus, "kvm-pit");
+ qdev_prop_set_uint32(&dev->qdev, "iobase", base);
+ qdev_init_nofail(&dev->qdev);
+
+ return dev;
+}
+
void pit_set_gate(ISADevice *dev, int channel, int val);
void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info);
diff --git a/hw/i8254_common.c b/hw/i8254_common.c
new file mode 100644
index 0000000000..a03d7cd458
--- /dev/null
+++ b/hw/i8254_common.c
@@ -0,0 +1,311 @@
+/*
+ * QEMU 8253/8254 - common bits of emulated and KVM kernel model
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2012 Jan Kiszka, Siemens AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw.h"
+#include "pc.h"
+#include "isa.h"
+#include "qemu-timer.h"
+#include "i8254.h"
+#include "i8254_internal.h"
+
+/* val must be 0 or 1 */
+void pit_set_gate(ISADevice *dev, int channel, int val)
+{
+ PITCommonState *pit = PIT_COMMON(dev);
+ PITChannelState *s = &pit->channels[channel];
+ PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
+
+ c->set_channel_gate(pit, s, val);
+}
+
+/* get pit output bit */
+int pit_get_out(PITChannelState *s, int64_t current_time)
+{
+ uint64_t d;
+ int out;
+
+ d = muldiv64(current_time - s->count_load_time, PIT_FREQ,
+ get_ticks_per_sec());
+ switch (s->mode) {
+ default:
+ case 0:
+ out = (d >= s->count);
+ break;
+ case 1:
+ out = (d < s->count);
+ break;
+ case 2:
+ if ((d % s->count) == 0 && d != 0) {
+ out = 1;
+ } else {
+ out = 0;
+ }
+ break;
+ case 3:
+ out = (d % s->count) < ((s->count + 1) >> 1);
+ break;
+ case 4:
+ case 5:
+ out = (d == s->count);
+ break;
+ }
+ return out;
+}
+
+/* return -1 if no transition will occur. */
+int64_t pit_get_next_transition_time(PITChannelState *s, int64_t current_time)
+{
+ uint64_t d, next_time, base;
+ int period2;
+
+ d = muldiv64(current_time - s->count_load_time, PIT_FREQ,
+ get_ticks_per_sec());
+ switch (s->mode) {
+ default:
+ case 0:
+ case 1:
+ if (d < s->count) {
+ next_time = s->count;
+ } else {
+ return -1;
+ }
+ break;
+ case 2:
+ base = (d / s->count) * s->count;
+ if ((d - base) == 0 && d != 0) {
+ next_time = base + s->count;
+ } else {
+ next_time = base + s->count + 1;
+ }
+ break;
+ case 3:
+ base = (d / s->count) * s->count;
+ period2 = ((s->count + 1) >> 1);
+ if ((d - base) < period2) {
+ next_time = base + period2;
+ } else {
+ next_time = base + s->count;
+ }
+ break;
+ case 4:
+ case 5:
+ if (d < s->count) {
+ next_time = s->count;
+ } else if (d == s->count) {
+ next_time = s->count + 1;
+ } else {
+ return -1;
+ }
+ break;
+ }
+ /* convert to timer units */
+ next_time = s->count_load_time + muldiv64(next_time, get_ticks_per_sec(),
+ PIT_FREQ);
+ /* fix potential rounding problems */
+ /* XXX: better solution: use a clock at PIT_FREQ Hz */
+ if (next_time <= current_time) {
+ next_time = current_time + 1;
+ }
+ return next_time;
+}
+
+void pit_get_channel_info_common(PITCommonState *s, PITChannelState *sc,
+ PITChannelInfo *info)
+{
+ info->gate = sc->gate;
+ info->mode = sc->mode;
+ info->initial_count = sc->count;
+ info->out = pit_get_out(sc, qemu_get_clock_ns(vm_clock));
+}
+
+void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info)
+{
+ PITCommonState *pit = PIT_COMMON(dev);
+ PITChannelState *s = &pit->channels[channel];
+ PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
+
+ c->get_channel_info(pit, s, info);
+}
+
+void pit_reset_common(PITCommonState *pit)
+{
+ PITChannelState *s;
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ s = &pit->channels[i];
+ s->mode = 3;
+ s->gate = (i != 2);
+ s->count_load_time = qemu_get_clock_ns(vm_clock);
+ s->count = 0x10000;
+ if (i == 0 && !s->irq_disabled) {
+ s->next_transition_time =
+ pit_get_next_transition_time(s, s->count_load_time);
+ }
+ }
+}
+
+static int pit_init_common(ISADevice *dev)
+{
+ PITCommonState *pit = PIT_COMMON(dev);
+ PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
+ int ret;
+
+ ret = c->init(pit);
+ if (ret < 0) {
+ return ret;
+ }
+
+ isa_register_ioport(dev, &pit->ioports, pit->iobase);
+
+ qdev_set_legacy_instance_id(&dev->qdev, pit->iobase, 2);
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_pit_channel = {
+ .name = "pit channel",
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(count, PITChannelState),
+ VMSTATE_UINT16(latched_count, PITChannelState),
+ VMSTATE_UINT8(count_latched, PITChannelState),
+ VMSTATE_UINT8(status_latched, PITChannelState),
+ VMSTATE_UINT8(status, PITChannelState),
+ VMSTATE_UINT8(read_state, PITChannelState),
+ VMSTATE_UINT8(write_state, PITChannelState),
+ VMSTATE_UINT8(write_latch, PITChannelState),
+ VMSTATE_UINT8(rw_mode, PITChannelState),
+ VMSTATE_UINT8(mode, PITChannelState),
+ VMSTATE_UINT8(bcd, PITChannelState),
+ VMSTATE_UINT8(gate, PITChannelState),
+ VMSTATE_INT64(count_load_time, PITChannelState),
+ VMSTATE_INT64(next_transition_time, PITChannelState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static int pit_load_old(QEMUFile *f, void *opaque, int version_id)
+{
+ PITCommonState *pit = opaque;
+ PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
+ PITChannelState *s;
+ int i;
+
+ if (version_id != 1) {
+ return -EINVAL;
+ }
+
+ for (i = 0; i < 3; i++) {
+ s = &pit->channels[i];
+ s->count = qemu_get_be32(f);
+ qemu_get_be16s(f, &s->latched_count);
+ qemu_get_8s(f, &s->count_latched);
+ qemu_get_8s(f, &s->status_latched);
+ qemu_get_8s(f, &s->status);
+ qemu_get_8s(f, &s->read_state);
+ qemu_get_8s(f, &s->write_state);
+ qemu_get_8s(f, &s->write_latch);
+ qemu_get_8s(f, &s->rw_mode);
+ qemu_get_8s(f, &s->mode);
+ qemu_get_8s(f, &s->bcd);
+ qemu_get_8s(f, &s->gate);
+ s->count_load_time = qemu_get_be64(f);
+ s->irq_disabled = 0;
+ if (i == 0) {
+ s->next_transition_time = qemu_get_be64(f);
+ }
+ }
+ if (c->post_load) {
+ c->post_load(pit);
+ }
+ return 0;
+}
+
+static void pit_dispatch_pre_save(void *opaque)
+{
+ PITCommonState *s = opaque;
+ PITCommonClass *c = PIT_COMMON_GET_CLASS(s);
+
+ if (c->pre_save) {
+ c->pre_save(s);
+ }
+}
+
+static int pit_dispatch_post_load(void *opaque, int version_id)
+{
+ PITCommonState *s = opaque;
+ PITCommonClass *c = PIT_COMMON_GET_CLASS(s);
+
+ if (c->post_load) {
+ c->post_load(s);
+ }
+ return 0;
+}
+
+static const VMStateDescription vmstate_pit_common = {
+ .name = "i8254",
+ .version_id = 3,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 1,
+ .load_state_old = pit_load_old,
+ .pre_save = pit_dispatch_pre_save,
+ .post_load = pit_dispatch_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_V(channels[0].irq_disabled, PITCommonState, 3),
+ VMSTATE_STRUCT_ARRAY(channels, PITCommonState, 3, 2,
+ vmstate_pit_channel, PITChannelState),
+ VMSTATE_INT64(channels[0].next_transition_time,
+ PITCommonState), /* formerly irq_timer */
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void pit_common_class_init(ObjectClass *klass, void *data)
+{
+ ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ ic->init = pit_init_common;
+ dc->vmsd = &vmstate_pit_common;
+ dc->no_user = 1;
+}
+
+static TypeInfo pit_common_type = {
+ .name = TYPE_PIT_COMMON,
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(PITCommonState),
+ .class_size = sizeof(PITCommonClass),
+ .class_init = pit_common_class_init,
+ .abstract = true,
+};
+
+static void register_devices(void)
+{
+ type_register_static(&pit_common_type);
+}
+
+type_init(register_devices);
diff --git a/hw/i8254_internal.h b/hw/i8254_internal.h
new file mode 100644
index 0000000000..686f0c2ba9
--- /dev/null
+++ b/hw/i8254_internal.h
@@ -0,0 +1,85 @@
+/*
+ * QEMU 8253/8254 - internal interfaces
+ *
+ * Copyright (c) 2011 Jan Kiszka, Siemens AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef QEMU_I8254_INTERNAL_H
+#define QEMU_I8254_INTERNAL_H
+
+#include "hw.h"
+#include "pc.h"
+#include "isa.h"
+
+typedef struct PITChannelState {
+ int count; /* can be 65536 */
+ uint16_t latched_count;
+ uint8_t count_latched;
+ uint8_t status_latched;
+ uint8_t status;
+ uint8_t read_state;
+ uint8_t write_state;
+ uint8_t write_latch;
+ uint8_t rw_mode;
+ uint8_t mode;
+ uint8_t bcd; /* not supported */
+ uint8_t gate; /* timer start */
+ int64_t count_load_time;
+ /* irq handling */
+ int64_t next_transition_time;
+ QEMUTimer *irq_timer;
+ qemu_irq irq;
+ uint32_t irq_disabled;
+} PITChannelState;
+
+typedef struct PITCommonState {
+ ISADevice dev;
+ MemoryRegion ioports;
+ uint32_t iobase;
+ PITChannelState channels[3];
+} PITCommonState;
+
+#define TYPE_PIT_COMMON "pit-common"
+#define PIT_COMMON(obj) \
+ OBJECT_CHECK(PITCommonState, (obj), TYPE_PIT_COMMON)
+#define PIT_COMMON_CLASS(klass) \
+ OBJECT_CLASS_CHECK(PITCommonClass, (klass), TYPE_PIT_COMMON)
+#define PIT_COMMON_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(PITCommonClass, (obj), TYPE_PIT_COMMON)
+
+typedef struct PITCommonClass {
+ ISADeviceClass parent_class;
+
+ int (*init)(PITCommonState *s);
+ void (*set_channel_gate)(PITCommonState *s, PITChannelState *sc, int val);
+ void (*get_channel_info)(PITCommonState *s, PITChannelState *sc,
+ PITChannelInfo *info);
+ void (*pre_save)(PITCommonState *s);
+ void (*post_load)(PITCommonState *s);
+} PITCommonClass;
+
+int pit_get_out(PITChannelState *s, int64_t current_time);
+int64_t pit_get_next_transition_time(PITChannelState *s, int64_t current_time);
+void pit_get_channel_info_common(PITCommonState *s, PITChannelState *sc,
+ PITChannelInfo *info);
+void pit_reset_common(PITCommonState *s);
+
+#endif /* !QEMU_I8254_INTERNAL_H */
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 041ce1e89f..a883a920be 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -367,7 +367,7 @@ static void ahci_mem_write(void *opaque, target_phys_addr_t addr,
}
-static MemoryRegionOps ahci_mem_ops = {
+static const MemoryRegionOps ahci_mem_ops = {
.read = ahci_mem_read,
.write = ahci_mem_write,
.endianness = DEVICE_LITTLE_ENDIAN,
@@ -403,7 +403,7 @@ static void ahci_idp_write(void *opaque, target_phys_addr_t addr,
}
}
-static MemoryRegionOps ahci_idp_ops = {
+static const MemoryRegionOps ahci_idp_ops = {
.read = ahci_idp_read,
.write = ahci_idp_write,
.endianness = DEVICE_LITTLE_ENDIAN,
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 743ec02406..bf8ece4708 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -65,7 +65,7 @@ static void cmd646_cmd_write(void *opaque, target_phys_addr_t addr,
ide_cmd_write(cmd646bar->bus, addr + 2, data);
}
-static MemoryRegionOps cmd646_cmd_ops = {
+static const MemoryRegionOps cmd646_cmd_ops = {
.read = cmd646_cmd_read,
.write = cmd646_cmd_write,
.endianness = DEVICE_LITTLE_ENDIAN,
@@ -104,7 +104,7 @@ static void cmd646_data_write(void *opaque, target_phys_addr_t addr,
}
}
-static MemoryRegionOps cmd646_data_ops = {
+static const MemoryRegionOps cmd646_data_ops = {
.read = cmd646_data_read,
.write = cmd646_data_write,
.endianness = DEVICE_LITTLE_ENDIAN,
@@ -193,7 +193,7 @@ static void bmdma_write(void *opaque, target_phys_addr_t addr,
}
}
-static MemoryRegionOps cmd646_bmdma_ops = {
+static const MemoryRegionOps cmd646_bmdma_ops = {
.read = bmdma_read,
.write = bmdma_write,
};
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index abbc41b59e..a4df24406a 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -291,7 +291,7 @@ static uint32_t pmac_ide_readl (void *opaque,target_phys_addr_t addr)
return retval;
}
-static MemoryRegionOps pmac_ide_ops = {
+static const MemoryRegionOps pmac_ide_ops = {
.old_mmio = {
.write = {
pmac_ide_writeb,
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 1030fcc31c..bcaa400e2d 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -79,7 +79,7 @@ static void bmdma_write(void *opaque, target_phys_addr_t addr,
}
}
-static MemoryRegionOps piix_bmdma_ops = {
+static const MemoryRegionOps piix_bmdma_ops = {
.read = bmdma_read,
.write = bmdma_write,
};
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 2886bc6dfb..eec5136019 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -82,7 +82,7 @@ static void bmdma_write(void *opaque, target_phys_addr_t addr,
}
}
-static MemoryRegionOps via_bmdma_ops = {
+static const MemoryRegionOps via_bmdma_ops = {
.read = bmdma_read,
.write = bmdma_write,
};
diff --git a/hw/kvm/i8254.c b/hw/kvm/i8254.c
new file mode 100644
index 0000000000..bb5fe07d1e
--- /dev/null
+++ b/hw/kvm/i8254.c
@@ -0,0 +1,254 @@
+/*
+ * KVM in-kernel PIT (i8254) support
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2012 Jan Kiszka, Siemens AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu-timer.h"
+#include "hw/i8254.h"
+#include "hw/i8254_internal.h"
+#include "kvm.h"
+
+#define KVM_PIT_REINJECT_BIT 0
+
+typedef struct KVMPITState {
+ PITCommonState pit;
+ LostTickPolicy lost_tick_policy;
+} KVMPITState;
+
+static void kvm_pit_get(PITCommonState *s)
+{
+ struct kvm_pit_state2 kpit;
+ struct kvm_pit_channel_state *kchan;
+ struct PITChannelState *sc;
+ int i, ret;
+
+ if (kvm_has_pit_state2()) {
+ ret = kvm_vm_ioctl(kvm_state, KVM_GET_PIT2, &kpit);
+ if (ret < 0) {
+ fprintf(stderr, "KVM_GET_PIT2 failed: %s\n", strerror(ret));
+ abort();
+ }
+ s->channels[0].irq_disabled = kpit.flags & KVM_PIT_FLAGS_HPET_LEGACY;
+ } else {
+ /*
+ * kvm_pit_state2 is superset of kvm_pit_state struct,
+ * so we can use it for KVM_GET_PIT as well.
+ */
+ ret = kvm_vm_ioctl(kvm_state, KVM_GET_PIT, &kpit);
+ if (ret < 0) {
+ fprintf(stderr, "KVM_GET_PIT failed: %s\n", strerror(ret));
+ abort();
+ }
+ }
+ for (i = 0; i < 3; i++) {
+ kchan = &kpit.channels[i];
+ sc = &s->channels[i];
+ sc->count = kchan->count;
+ sc->latched_count = kchan->latched_count;
+ sc->count_latched = kchan->count_latched;
+ sc->status_latched = kchan->status_latched;
+ sc->status = kchan->status;
+ sc->read_state = kchan->read_state;
+ sc->write_state = kchan->write_state;
+ sc->write_latch = kchan->write_latch;
+ sc->rw_mode = kchan->rw_mode;
+ sc->mode = kchan->mode;
+ sc->bcd = kchan->bcd;
+ sc->gate = kchan->gate;
+ sc->count_load_time = kchan->count_load_time;
+ }
+
+ sc = &s->channels[0];
+ sc->next_transition_time =
+ pit_get_next_transition_time(sc, sc->count_load_time);
+}
+
+static void kvm_pit_put(PITCommonState *s)
+{
+ struct kvm_pit_state2 kpit;
+ struct kvm_pit_channel_state *kchan;
+ struct PITChannelState *sc;
+ int i, ret;
+
+ kpit.flags = s->channels[0].irq_disabled ? KVM_PIT_FLAGS_HPET_LEGACY : 0;
+ for (i = 0; i < 3; i++) {
+ kchan = &kpit.channels[i];
+ sc = &s->channels[i];
+ kchan->count = sc->count;
+ kchan->latched_count = sc->latched_count;
+ kchan->count_latched = sc->count_latched;
+ kchan->status_latched = sc->status_latched;
+ kchan->status = sc->status;
+ kchan->read_state = sc->read_state;
+ kchan->write_state = sc->write_state;
+ kchan->write_latch = sc->write_latch;
+ kchan->rw_mode = sc->rw_mode;
+ kchan->mode = sc->mode;
+ kchan->bcd = sc->bcd;
+ kchan->gate = sc->gate;
+ kchan->count_load_time = sc->count_load_time;
+ }
+
+ ret = kvm_vm_ioctl(kvm_state,
+ kvm_has_pit_state2() ? KVM_SET_PIT2 : KVM_SET_PIT,
+ &kpit);
+ if (ret < 0) {
+ fprintf(stderr, "%s failed: %s\n",
+ kvm_has_pit_state2() ? "KVM_SET_PIT2" : "KVM_SET_PIT",
+ strerror(ret));
+ abort();
+ }
+}
+
+static void kvm_pit_set_gate(PITCommonState *s, PITChannelState *sc, int val)
+{
+ kvm_pit_get(s);
+
+ switch (sc->mode) {
+ default:
+ case 0:
+ case 4:
+ /* XXX: just disable/enable counting */
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 5:
+ if (sc->gate < val) {
+ /* restart counting on rising edge */
+ sc->count_load_time = qemu_get_clock_ns(vm_clock);
+ }
+ break;
+ }
+ sc->gate = val;
+
+ kvm_pit_put(s);
+}
+
+static void kvm_pit_get_channel_info(PITCommonState *s, PITChannelState *sc,
+ PITChannelInfo *info)
+{
+ kvm_pit_get(s);
+
+ pit_get_channel_info_common(s, sc, info);
+}
+
+static void kvm_pit_reset(DeviceState *dev)
+{
+ PITCommonState *s = DO_UPCAST(PITCommonState, dev.qdev, dev);
+
+ pit_reset_common(s);
+
+ kvm_pit_put(s);
+}
+
+static void kvm_pit_irq_control(void *opaque, int n, int enable)
+{
+ PITCommonState *pit = opaque;
+ PITChannelState *s = &pit->channels[0];
+
+ kvm_pit_get(pit);
+
+ s->irq_disabled = !enable;
+
+ kvm_pit_put(pit);
+}
+
+static int kvm_pit_initfn(PITCommonState *pit)
+{
+ KVMPITState *s = DO_UPCAST(KVMPITState, pit, pit);
+ struct kvm_pit_config config = {
+ .flags = 0,
+ };
+ int ret;
+
+ if (kvm_check_extension(kvm_state, KVM_CAP_PIT2)) {
+ ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_PIT2, &config);
+ } else {
+ ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_PIT);
+ }
+ if (ret < 0) {
+ fprintf(stderr, "Create kernel PIC irqchip failed: %s\n",
+ strerror(ret));
+ return ret;
+ }
+ switch (s->lost_tick_policy) {
+ case LOST_TICK_DELAY:
+ break; /* enabled by default */
+ case LOST_TICK_DISCARD:
+ if (kvm_check_extension(kvm_state, KVM_CAP_REINJECT_CONTROL)) {
+ struct kvm_reinject_control control = { .pit_reinject = 0 };
+
+ ret = kvm_vm_ioctl(kvm_state, KVM_REINJECT_CONTROL, &control);
+ if (ret < 0) {
+ fprintf(stderr,
+ "Can't disable in-kernel PIT reinjection: %s\n",
+ strerror(ret));
+ return ret;
+ }
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ memory_region_init_reservation(&pit->ioports, "kvm-pit", 4);
+
+ qdev_init_gpio_in(&pit->dev.qdev, kvm_pit_irq_control, 1);
+
+ return 0;
+}
+
+static Property kvm_pit_properties[] = {
+ DEFINE_PROP_HEX32("iobase", KVMPITState, pit.iobase, -1),
+ DEFINE_PROP_LOSTTICKPOLICY("lost_tick_policy", KVMPITState,
+ lost_tick_policy, LOST_TICK_DELAY),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void kvm_pit_class_init(ObjectClass *klass, void *data)
+{
+ PITCommonClass *k = PIT_COMMON_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = kvm_pit_initfn;
+ k->set_channel_gate = kvm_pit_set_gate;
+ k->get_channel_info = kvm_pit_get_channel_info;
+ k->pre_save = kvm_pit_get;
+ k->post_load = kvm_pit_put;
+ dc->reset = kvm_pit_reset;
+ dc->props = kvm_pit_properties;
+}
+
+static TypeInfo kvm_pit_info = {
+ .name = "kvm-pit",
+ .parent = TYPE_PIT_COMMON,
+ .instance_size = sizeof(KVMPITState),
+ .class_init = kvm_pit_class_init,
+};
+
+static void kvm_pit_register(void)
+{
+ type_register_static(&kvm_pit_info);
+}
+
+type_init(kvm_pit_register)
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index 50d92f8f54..31072463f4 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -224,7 +224,7 @@ static NetClientInfo net_mipsnet_info = {
.cleanup = mipsnet_cleanup,
};
-static MemoryRegionOps mipsnet_ioport_ops = {
+static const MemoryRegionOps mipsnet_ioport_ops = {
.read = mipsnet_ioport_read,
.write = mipsnet_ioport_write,
.impl.min_access_size = 1,
diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c
index 9b036cb103..4c7696935f 100644
--- a/hw/opencores_eth.c
+++ b/hw/opencores_eth.c
@@ -692,12 +692,12 @@ static void open_eth_desc_write(void *opaque,
}
-static MemoryRegionOps open_eth_reg_ops = {
+static const MemoryRegionOps open_eth_reg_ops = {
.read = open_eth_reg_read,
.write = open_eth_reg_write,
};
-static MemoryRegionOps open_eth_desc_ops = {
+static const MemoryRegionOps open_eth_desc_ops = {
.read = open_eth_desc_read,
.write = open_eth_desc_write,
};
diff --git a/hw/pc.c b/hw/pc.c
index 12c02f2044..bb9867b070 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1096,7 +1096,13 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
- if (!no_hpet) {
+ /*
+ * Check if an HPET shall be created.
+ *
+ * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT
+ * when the HPET wants to take over. Thus we have to disable the latter.
+ */
+ if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) {
hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);
if (hpet) {
@@ -1112,7 +1118,11 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
qemu_register_boot_set(pc_boot_set, *rtc_state);
- pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
+ if (kvm_irqchip_in_kernel()) {
+ pit = kvm_pit_init(isa_bus, 0x40);
+ } else {
+ pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
+ }
if (hpet) {
/* connect PIT to output control line of the HPET */
qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 0423af1c31..bff9152df5 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -421,10 +421,6 @@ static void set_string(Object *obj, Visitor *v, void *opaque,
error_propagate(errp, local_err);
return;
}
- if (!*str) {
- g_free(str);
- str = NULL;
- }
if (*ptr) {
g_free(*ptr);
}
diff --git a/hw/sh7750.c b/hw/sh7750.c
index 4f4d8e7d05..e7129283d1 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -712,7 +712,7 @@ static void sh7750_mmct_write(void *opaque, target_phys_addr_t addr,
}
}
-static const struct MemoryRegionOps sh7750_mmct_ops = {
+static const MemoryRegionOps sh7750_mmct_ops = {
.read = sh7750_mmct_read,
.write = sh7750_mmct_write,
.endianness = DEVICE_NATIVE_ENDIAN,
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index b24ec77582..7d31ced858 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -283,7 +283,7 @@ static void sh_intc_write(void *opaque, target_phys_addr_t offset,
#endif
}
-static const struct MemoryRegionOps sh_intc_ops = {
+static const MemoryRegionOps sh_intc_ops = {
.read = sh_intc_read,
.write = sh_intc_write,
.endianness = DEVICE_NATIVE_ENDIAN,
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index cfdd9ddd41..374dcf8be7 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -281,7 +281,7 @@ static void spapr_io_write(void *opaque, target_phys_addr_t addr,
assert(0);
}
-static MemoryRegionOps spapr_io_ops = {
+static const MemoryRegionOps spapr_io_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
.read = spapr_io_read,
.write = spapr_io_write
diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
index ce01e343c6..ced687f288 100644
--- a/hw/usb-ccid.c
+++ b/hw/usb-ccid.c
@@ -5,7 +5,7 @@
*
* Written by Alon Levy, with contributions from Robert Relyea.
*
- * Based on usb-serial.c, see it's copyright and attributions below.
+ * Based on usb-serial.c, see its copyright and attributions below.
*
* This work is licensed under the terms of the GNU GPL, version 2.1 or later.
* See the COPYING file in the top-level directory.
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index afc8ccf458..df742f7f02 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -347,7 +347,6 @@ enum async_state {
struct EHCIQueue {
EHCIState *ehci;
QTAILQ_ENTRY(EHCIQueue) next;
- bool async_schedule;
uint32_t seen;
uint64_t ts;
@@ -367,6 +366,8 @@ struct EHCIQueue {
int usb_status;
};
+typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead;
+
struct EHCIState {
PCIDevice dev;
USBBus bus;
@@ -410,7 +411,8 @@ struct EHCIState {
USBPort ports[NB_PORTS];
USBPort *companion_ports[NB_PORTS];
uint32_t usbsts_pending;
- QTAILQ_HEAD(, EHCIQueue) queues;
+ EHCIQueueHead aqueues;
+ EHCIQueueHead pqueues;
uint32_t a_fetch_addr; // which address to look at next
uint32_t p_fetch_addr; // which address to look at next
@@ -660,31 +662,34 @@ static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q;
q = g_malloc0(sizeof(*q));
q->ehci = ehci;
- q->async_schedule = async;
- QTAILQ_INSERT_HEAD(&ehci->queues, q, next);
+ QTAILQ_INSERT_HEAD(head, q, next);
trace_usb_ehci_queue_action(q, "alloc");
return q;
}
-static void ehci_free_queue(EHCIQueue *q)
+static void ehci_free_queue(EHCIQueue *q, int async)
{
+ EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues;
trace_usb_ehci_queue_action(q, "free");
if (q->async == EHCI_ASYNC_INFLIGHT) {
usb_cancel_packet(&q->packet);
}
- QTAILQ_REMOVE(&q->ehci->queues, q, next);
+ QTAILQ_REMOVE(head, q, next);
g_free(q);
}
-static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr)
+static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
+ int async)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q;
- QTAILQ_FOREACH(q, &ehci->queues, next) {
+ QTAILQ_FOREACH(q, head, next) {
if (addr == q->qhaddr) {
return q;
}
@@ -692,43 +697,46 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr)
return NULL;
}
-static void ehci_queues_rip_unused(EHCIState *ehci)
+static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q, *tmp;
- QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
+ QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
if (q->seen) {
q->seen = 0;
q->ts = ehci->last_run_ns;
continue;
}
- if (ehci->last_run_ns < q->ts + 250000000) {
+ if (!flush && ehci->last_run_ns < q->ts + 250000000) {
/* allow 0.25 sec idle */
continue;
}
- ehci_free_queue(q);
+ ehci_free_queue(q, async);
}
}
-static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev)
+static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q, *tmp;
- QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
+ QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
if (!usb_packet_is_inflight(&q->packet) ||
q->packet.ep->dev != dev) {
continue;
}
- ehci_free_queue(q);
+ ehci_free_queue(q, async);
}
}
-static void ehci_queues_rip_all(EHCIState *ehci)
+static void ehci_queues_rip_all(EHCIState *ehci, int async)
{
+ EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q, *tmp;
- QTAILQ_FOREACH_SAFE(q, &ehci->queues, next, tmp) {
- ehci_free_queue(q);
+ QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
+ ehci_free_queue(q, async);
}
}
@@ -773,7 +781,8 @@ static void ehci_detach(USBPort *port)
return;
}
- ehci_queues_rip_device(s, port->dev);
+ ehci_queues_rip_device(s, port->dev, 0);
+ ehci_queues_rip_device(s, port->dev, 1);
*portsc &= ~(PORTSC_CONNECT|PORTSC_PED);
*portsc |= PORTSC_CSC;
@@ -793,7 +802,8 @@ static void ehci_child_detach(USBPort *port, USBDevice *child)
return;
}
- ehci_queues_rip_device(s, child);
+ ehci_queues_rip_device(s, child, 0);
+ ehci_queues_rip_device(s, child, 1);
}
static void ehci_wakeup(USBPort *port)
@@ -911,7 +921,8 @@ static void ehci_reset(void *opaque)
usb_device_reset(devs[i]);
}
}
- ehci_queues_rip_all(s);
+ ehci_queues_rip_all(s, 0);
+ ehci_queues_rip_all(s, 1);
qemu_del_timer(s->frame_timer);
}
@@ -1065,7 +1076,8 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
if (!(val & USBCMD_RUNSTOP) && (s->usbcmd & USBCMD_RUNSTOP)) {
qemu_del_timer(s->frame_timer);
- // TODO - should finish out some stuff before setting halt
+ ehci_queues_rip_all(s, 0);
+ ehci_queues_rip_all(s, 1);
ehci_set_usbsts(s, USBSTS_HALT);
}
@@ -1279,8 +1291,6 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
static void ehci_execute_complete(EHCIQueue *q)
{
- int c_err, reload;
-
assert(q->async != EHCI_ASYNC_INFLIGHT);
q->async = EHCI_ASYNC_NONE;
@@ -1288,15 +1298,11 @@ static void ehci_execute_complete(EHCIQueue *q)
q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status);
if (q->usb_status < 0) {
-err:
- /* TO-DO: put this is in a function that can be invoked below as well */
- c_err = get_field(q->qh.token, QTD_TOKEN_CERR);
- c_err--;
- set_field(&q->qh.token, c_err, QTD_TOKEN_CERR);
-
switch(q->usb_status) {
+ case USB_RET_IOERROR:
case USB_RET_NODEV:
q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
+ set_field(&q->qh.token, 0, QTD_TOKEN_CERR);
ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
break;
case USB_RET_STALL:
@@ -1304,16 +1310,8 @@ err:
ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
break;
case USB_RET_NAK:
- /* 4.10.3 */
- reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
- if ((q->pid == USB_TOKEN_IN) && reload) {
- int nakcnt = get_field(q->qh.altnext_qtd, QH_ALTNEXT_NAKCNT);
- nakcnt--;
- set_field(&q->qh.altnext_qtd, nakcnt, QH_ALTNEXT_NAKCNT);
- } else if (!reload) {
- return;
- }
- break;
+ set_field(&q->qh.altnext_qtd, 0, QH_ALTNEXT_NAKCNT);
+ return; /* We're not done yet with this transaction */
case USB_RET_BABBLE:
q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
@@ -1324,15 +1322,13 @@ err:
assert(0);
break;
}
+ } else if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
+ q->usb_status = USB_RET_BABBLE;
+ q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
+ ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
} else {
- // DPRINTF("Short packet condition\n");
// TODO check 4.12 for splits
- if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
- q->usb_status = USB_RET_BABBLE;
- goto err;
- }
-
if (q->tbytes && q->pid == USB_TOKEN_IN) {
q->tbytes -= q->usb_status;
} else {
@@ -1348,7 +1344,7 @@ err:
q->qh.token ^= QTD_TOKEN_DTOGGLE;
q->qh.token &= ~QTD_TOKEN_ACTIVE;
- if ((q->usb_status >= 0) && (q->qh.token & QTD_TOKEN_IOC)) {
+ if (q->qh.token & QTD_TOKEN_IOC) {
ehci_record_interrupt(q->ehci, USBSTS_INT);
}
}
@@ -1471,24 +1467,12 @@ static int ehci_process_itd(EHCIState *ehci,
}
qemu_sglist_destroy(&ehci->isgl);
- if (ret == USB_RET_NAK) {
- /* no data for us, so do a zero-length transfer */
- ret = 0;
- }
-
- if (ret >= 0) {
- if (!dir) {
- /* OUT */
- set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH);
- } else {
- /* IN */
- set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
- }
- } else {
+ if (ret < 0) {
switch (ret) {
default:
fprintf(stderr, "Unexpected iso usb result: %d\n", ret);
/* Fall through */
+ case USB_RET_IOERROR:
case USB_RET_NODEV:
/* 3.3.2: XACTERR is only allowed on IN transactions */
if (dir) {
@@ -1500,6 +1484,19 @@ static int ehci_process_itd(EHCIState *ehci,
itd->transact[i] |= ITD_XACT_BABBLE;
ehci_record_interrupt(ehci, USBSTS_ERRINT);
break;
+ case USB_RET_NAK:
+ /* no data for us, so do a zero-length transfer */
+ ret = 0;
+ break;
+ }
+ }
+ if (ret >= 0) {
+ if (!dir) {
+ /* OUT */
+ set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH);
+ } else {
+ /* IN */
+ set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
}
}
if (itd->transact[i] & ITD_XACT_IOC) {
@@ -1526,7 +1523,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci, int async)
ehci_set_usbsts(ehci, USBSTS_REC);
}
- ehci_queues_rip_unused(ehci);
+ ehci_queues_rip_unused(ehci, async, 0);
/* Find the head of the list (4.9.1.1) */
for(i = 0; i < MAX_QH; i++) {
@@ -1568,8 +1565,7 @@ static int ehci_state_fetchentry(EHCIState *ehci, int async)
int again = 0;
uint32_t entry = ehci_get_fetch_addr(ehci, async);
- if (entry < 0x1000) {
- DPRINTF("fetchentry: entry invalid (0x%08x)\n", entry);
+ if (NLPTR_TBIT(entry)) {
ehci_set_state(ehci, async, EST_ACTIVE);
goto out;
}
@@ -1611,10 +1607,9 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
{
uint32_t entry;
EHCIQueue *q;
- int reload;
entry = ehci_get_fetch_addr(ehci, async);
- q = ehci_find_queue_by_qh(ehci, entry);
+ q = ehci_find_queue_by_qh(ehci, entry, async);
if (NULL == q) {
q = ehci_alloc_queue(ehci, async);
}
@@ -1669,15 +1664,11 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
}
#endif
- reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
- if (reload) {
- set_field(&q->qh.altnext_qtd, reload, QH_ALTNEXT_NAKCNT);
- }
-
if (q->qh.token & QTD_TOKEN_HALT) {
ehci_set_state(ehci, async, EST_HORIZONTALQH);
- } else if ((q->qh.token & QTD_TOKEN_ACTIVE) && (q->qh.current_qtd > 0x1000)) {
+ } else if ((q->qh.token & QTD_TOKEN_ACTIVE) &&
+ (NLPTR_TBIT(q->qh.current_qtd) == 0)) {
q->qtdaddr = q->qh.current_qtd;
ehci_set_state(ehci, async, EST_FETCHQTD);
@@ -1756,7 +1747,6 @@ static int ehci_state_advqueue(EHCIQueue *q, int async)
* want data and alt-next qTD is valid
*/
if (((q->qh.token & QTD_TOKEN_TBYTES_MASK) != 0) &&
- (q->qh.altnext_qtd > 0x1000) &&
(NLPTR_TBIT(q->qh.altnext_qtd) == 0)) {
q->qtdaddr = q->qh.altnext_qtd;
ehci_set_state(q->ehci, async, EST_FETCHQTD);
@@ -1764,8 +1754,7 @@ static int ehci_state_advqueue(EHCIQueue *q, int async)
/*
* next qTD is valid
*/
- } else if ((q->qh.next_qtd > 0x1000) &&
- (NLPTR_TBIT(q->qh.next_qtd) == 0)) {
+ } else if (NLPTR_TBIT(q->qh.next_qtd) == 0) {
q->qtdaddr = q->qh.next_qtd;
ehci_set_state(q->ehci, async, EST_FETCHQTD);
@@ -1834,25 +1823,11 @@ static void ehci_flush_qh(EHCIQueue *q)
static int ehci_state_execute(EHCIQueue *q, int async)
{
int again = 0;
- int reload, nakcnt;
- int smask;
if (ehci_qh_do_overlay(q) != 0) {
return -1;
}
- smask = get_field(q->qh.epcap, QH_EPCAP_SMASK);
-
- if (!smask) {
- reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
- nakcnt = get_field(q->qh.altnext_qtd, QH_ALTNEXT_NAKCNT);
- if (reload && !nakcnt) {
- ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
- again = 1;
- goto out;
- }
- }
-
// TODO verify enough time remains in the uframe as in 4.4.1.1
// TODO write back ptr to async list when done or out of time
// TODO Windows does not seem to ever set the MULT field
@@ -1894,7 +1869,6 @@ out:
static int ehci_state_executing(EHCIQueue *q, int async)
{
int again = 0;
- int reload, nakcnt;
ehci_execute_complete(q);
if (q->usb_status == USB_RET_ASYNC) {
@@ -1914,21 +1888,8 @@ static int ehci_state_executing(EHCIQueue *q, int async)
// counter decrements to 0
}
- reload = get_field(q->qh.epchar, QH_EPCHAR_RL);
- if (reload) {
- nakcnt = get_field(q->qh.altnext_qtd, QH_ALTNEXT_NAKCNT);
- if (q->usb_status == USB_RET_NAK) {
- if (nakcnt) {
- nakcnt--;
- }
- } else {
- nakcnt = reload;
- }
- set_field(&q->qh.altnext_qtd, nakcnt, QH_ALTNEXT_NAKCNT);
- }
-
/* 4.10.5 */
- if ((q->usb_status == USB_RET_NAK) || (q->qh.token & QTD_TOKEN_ACTIVE)) {
+ if (q->usb_status == USB_RET_NAK) {
ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
} else {
ehci_set_state(q->ehci, async, EST_WRITEBACK);
@@ -2066,7 +2027,7 @@ static void ehci_advance_state(EHCIState *ehci,
static void ehci_advance_async_state(EHCIState *ehci)
{
- int async = 1;
+ const int async = 1;
switch(ehci_get_state(ehci, async)) {
case EST_INACTIVE:
@@ -2079,23 +2040,13 @@ static void ehci_advance_async_state(EHCIState *ehci)
case EST_ACTIVE:
if ( !(ehci->usbcmd & USBCMD_ASE)) {
+ ehci_queues_rip_all(ehci, async);
ehci_clear_usbsts(ehci, USBSTS_ASS);
ehci_set_state(ehci, async, EST_INACTIVE);
break;
}
- /* If the doorbell is set, the guest wants to make a change to the
- * schedule. The host controller needs to release cached data.
- * (section 4.8.2)
- */
- if (ehci->usbcmd & USBCMD_IAAD) {
- DPRINTF("ASYNC: doorbell request acknowledged\n");
- ehci->usbcmd &= ~USBCMD_IAAD;
- ehci_set_interrupt(ehci, USBSTS_IAA);
- break;
- }
-
- /* make sure guest has acknowledged */
+ /* make sure guest has acknowledged the doorbell interrupt */
/* TO-DO: is this really needed? */
if (ehci->usbsts & USBSTS_IAA) {
DPRINTF("IAA status bit still set.\n");
@@ -2109,6 +2060,18 @@ static void ehci_advance_async_state(EHCIState *ehci)
ehci_set_state(ehci, async, EST_WAITLISTHEAD);
ehci_advance_state(ehci, async);
+
+ /* If the doorbell is set, the guest wants to make a change to the
+ * schedule. The host controller needs to release cached data.
+ * (section 4.8.2)
+ */
+ if (ehci->usbcmd & USBCMD_IAAD) {
+ /* Remove all unseen qhs from the async qhs queue */
+ ehci_queues_rip_unused(ehci, async, 1);
+ DPRINTF("ASYNC: doorbell request acknowledged\n");
+ ehci->usbcmd &= ~USBCMD_IAAD;
+ ehci_set_interrupt(ehci, USBSTS_IAA);
+ }
break;
default:
@@ -2123,7 +2086,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
{
uint32_t entry;
uint32_t list;
- int async = 0;
+ const int async = 0;
// 4.6
@@ -2138,6 +2101,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
case EST_ACTIVE:
if ( !(ehci->frindex & 7) && !(ehci->usbcmd & USBCMD_PSE)) {
+ ehci_queues_rip_all(ehci, async);
ehci_clear_usbsts(ehci, USBSTS_PSS);
ehci_set_state(ehci, async, EST_INACTIVE);
break;
@@ -2158,6 +2122,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
ehci_set_fetch_addr(ehci, async,entry);
ehci_set_state(ehci, async, EST_FETCHENTRY);
ehci_advance_state(ehci, async);
+ ehci_queues_rip_unused(ehci, async, 0);
break;
default:
@@ -2356,7 +2321,8 @@ static int usb_ehci_initfn(PCIDevice *dev)
}
s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s);
- QTAILQ_INIT(&s->queues);
+ QTAILQ_INIT(&s->aqueues);
+ QTAILQ_INIT(&s->pqueues);
qemu_register_reset(ehci_reset, s);
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 7aa19fe781..20aaa74250 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -837,6 +837,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
OHCI_CC_DATAUNDERRUN);
} else {
switch (ret) {
+ case USB_RET_IOERROR:
case USB_RET_NODEV:
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
OHCI_CC_DEVICENOTRESPONDING);
@@ -1052,6 +1053,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN);
} else {
switch (ret) {
+ case USB_RET_IOERROR:
case USB_RET_NODEV:
OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
case USB_RET_NAK:
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 70e3881321..304b84b831 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -765,6 +765,7 @@ out:
break;
return 1;
+ case USB_RET_IOERROR:
case USB_RET_NODEV:
default:
break;
@@ -950,7 +951,6 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
UHCI_TD ptd;
int ret;
- fprintf(stderr, "%s: -- %x\n", __func__, token);
while (is_valid(plink)) {
pci_dma_read(&s->dev, plink & ~0xf, &ptd, sizeof(ptd));
le32_to_cpus(&ptd.link);
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index fc5b542d99..e8f1b6e3a5 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -1470,8 +1470,8 @@ static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr)
static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
{
XHCITRB *trb_setup, *trb_status;
- uint8_t bmRequestType, bRequest;
- uint16_t wValue, wLength, wIndex;
+ uint8_t bmRequestType;
+ uint16_t wLength;
XHCIPort *port;
USBDevice *dev;
int ret;
@@ -1508,9 +1508,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
}
bmRequestType = trb_setup->parameter;
- bRequest = trb_setup->parameter >> 8;
- wValue = trb_setup->parameter >> 16;
- wIndex = trb_setup->parameter >> 32;
wLength = trb_setup->parameter >> 48;
if (xfer->data && xfer->data_alloced < wLength) {
@@ -1537,12 +1534,12 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
xfer->iso_xfer = false;
xhci_setup_packet(xfer, dev);
+ xfer->packet.parameter = trb_setup->parameter;
if (!xfer->in_xfer) {
xhci_xfer_data(xfer, xfer->data, wLength, 0, 1, 0);
}
- ret = usb_device_handle_control(dev, &xfer->packet,
- (bmRequestType << 8) | bRequest,
- wValue, wIndex, wLength, xfer->data);
+
+ ret = usb_handle_packet(dev, &xfer->packet);
xhci_complete_packet(xfer, ret);
if (!xfer->running_async && !xfer->running_retry) {
@@ -2282,7 +2279,7 @@ static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach)
int nr = port->port.index + 1;
port->portsc = PORTSC_PP;
- if (port->port.dev && !is_detach) {
+ if (port->port.dev && port->port.dev->attached && !is_detach) {
port->portsc |= PORTSC_CCS;
switch (port->port.dev->speed) {
case USB_SPEED_LOW:
diff --git a/hw/usb.c b/hw/usb.c
index 57fc5e3cfd..1ec2e90ef7 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -95,6 +95,7 @@ void usb_wakeup(USBEndpoint *ep)
#define SETUP_STATE_SETUP 1
#define SETUP_STATE_DATA 2
#define SETUP_STATE_ACK 3
+#define SETUP_STATE_PARAM 4
static int do_token_setup(USBDevice *s, USBPacket *p)
{
@@ -226,6 +227,50 @@ static int do_token_out(USBDevice *s, USBPacket *p)
}
}
+static int do_parameter(USBDevice *s, USBPacket *p)
+{
+ int request, value, index;
+ int i, ret = 0;
+
+ for (i = 0; i < 8; i++) {
+ s->setup_buf[i] = p->parameter >> (i*8);
+ }
+
+ s->setup_state = SETUP_STATE_PARAM;
+ s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
+ s->setup_index = 0;
+
+ request = (s->setup_buf[0] << 8) | s->setup_buf[1];
+ value = (s->setup_buf[3] << 8) | s->setup_buf[2];
+ index = (s->setup_buf[5] << 8) | s->setup_buf[4];
+
+ if (s->setup_len > sizeof(s->data_buf)) {
+ fprintf(stderr,
+ "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
+ s->setup_len, sizeof(s->data_buf));
+ return USB_RET_STALL;
+ }
+
+ if (p->pid == USB_TOKEN_OUT) {
+ usb_packet_copy(p, s->data_buf, s->setup_len);
+ }
+
+ ret = usb_device_handle_control(s, p, request, value, index,
+ s->setup_len, s->data_buf);
+ if (ret < 0) {
+ return ret;
+ }
+
+ if (ret < s->setup_len) {
+ s->setup_len = ret;
+ }
+ if (p->pid == USB_TOKEN_IN) {
+ usb_packet_copy(p, s->data_buf, s->setup_len);
+ }
+
+ return ret;
+}
+
/* ctrl complete function for devices which use usb_generic_handle_packet and
may return USB_RET_ASYNC from their handle_control callback. Device code
which does this *must* call this function instead of the normal
@@ -250,6 +295,16 @@ void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
p->result = 0;
break;
+ case SETUP_STATE_PARAM:
+ if (p->result < s->setup_len) {
+ s->setup_len = p->result;
+ }
+ if (p->pid == USB_TOKEN_IN) {
+ p->result = 0;
+ usb_packet_copy(p, s->data_buf, s->setup_len);
+ }
+ break;
+
default:
break;
}
@@ -292,6 +347,9 @@ static int usb_process_one(USBPacket *p)
if (p->ep->nr == 0) {
/* control pipe */
+ if (p->parameter) {
+ return do_parameter(dev, p);
+ }
switch (p->pid) {
case USB_TOKEN_SETUP:
return do_token_setup(dev, p);
@@ -323,7 +381,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
assert(p->state == USB_PACKET_SETUP);
assert(p->ep != NULL);
- if (QTAILQ_EMPTY(&p->ep->queue)) {
+ if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) {
ret = usb_process_one(p);
if (ret == USB_RET_ASYNC) {
usb_packet_set_state(p, USB_PACKET_ASYNC);
@@ -356,6 +414,9 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
while (!QTAILQ_EMPTY(&ep->queue)) {
p = QTAILQ_FIRST(&ep->queue);
+ if (p->state == USB_PACKET_ASYNC) {
+ break;
+ }
assert(p->state == USB_PACKET_QUEUED);
ret = usb_process_one(p);
if (ret == USB_RET_ASYNC) {
@@ -413,6 +474,7 @@ void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep)
p->pid = pid;
p->ep = ep;
p->result = 0;
+ p->parameter = 0;
qemu_iovec_reset(&p->iov);
usb_packet_set_state(p, USB_PACKET_SETUP);
}
@@ -465,6 +527,7 @@ void usb_ep_init(USBDevice *dev)
dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
dev->ep_ctl.ifnum = 0;
dev->ep_ctl.dev = dev;
+ dev->ep_ctl.pipeline = false;
QTAILQ_INIT(&dev->ep_ctl.queue);
for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
dev->ep_in[ep].nr = ep + 1;
@@ -477,6 +540,8 @@ void usb_ep_init(USBDevice *dev)
dev->ep_out[ep].ifnum = 0;
dev->ep_in[ep].dev = dev;
dev->ep_out[ep].dev = dev;
+ dev->ep_in[ep].pipeline = false;
+ dev->ep_out[ep].pipeline = false;
QTAILQ_INIT(&dev->ep_in[ep].queue);
QTAILQ_INIT(&dev->ep_out[ep].queue);
}
@@ -590,3 +655,9 @@ int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep)
struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
return uep->max_packet_size;
}
+
+void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled)
+{
+ struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+ uep->pipeline = enabled;
+}
diff --git a/hw/usb.h b/hw/usb.h
index 8e83697fb7..d60d03df9c 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -39,11 +39,12 @@
#define USB_TOKEN_IN 0x69 /* device -> host */
#define USB_TOKEN_OUT 0xe1 /* host -> device */
-#define USB_RET_NODEV (-1)
-#define USB_RET_NAK (-2)
-#define USB_RET_STALL (-3)
-#define USB_RET_BABBLE (-4)
-#define USB_RET_ASYNC (-5)
+#define USB_RET_NODEV (-1)
+#define USB_RET_NAK (-2)
+#define USB_RET_STALL (-3)
+#define USB_RET_BABBLE (-4)
+#define USB_RET_IOERROR (-5)
+#define USB_RET_ASYNC (-6)
#define USB_SPEED_LOW 0
#define USB_SPEED_FULL 1
@@ -176,6 +177,7 @@ struct USBEndpoint {
uint8_t type;
uint8_t ifnum;
int max_packet_size;
+ bool pipeline;
USBDevice *dev;
QTAILQ_HEAD(, USBPacket) queue;
};
@@ -325,6 +327,7 @@ struct USBPacket {
int pid;
USBEndpoint *ep;
QEMUIOVector iov;
+ uint64_t parameter; /* control transfers */
int result; /* transfer length or USB_RET_* status code */
/* Internal use by the USB layer. */
USBPacketState state;
@@ -363,6 +366,7 @@ void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum);
void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep,
uint16_t raw);
int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep);
+void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled);
void usb_attach(USBPort *port);
void usb_detach(USBPort *port);
diff --git a/hw/vga.c b/hw/vga.c
index 5994f43b75..6dc98f6c2a 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -30,6 +30,7 @@
#include "pixel_ops.h"
#include "qemu-timer.h"
#include "xen.h"
+#include "trace.h"
//#define DEBUG_VGA
//#define DEBUG_VGA_MEM
@@ -2372,6 +2373,7 @@ int ppm_save(const char *filename, struct DisplaySurface *ds)
int ret;
char *linebuf, *pbuf;
+ trace_ppm_save(filename, ds);
f = fopen(filename, "wb");
if (!f)
return -1;
diff --git a/hw/zynq_slcr.c b/hw/zynq_slcr.c
index b785f0441c..4f97575770 100644
--- a/hw/zynq_slcr.c
+++ b/hw/zynq_slcr.c
@@ -311,7 +311,7 @@ static inline uint32_t zynq_slcr_read_imp(void *opaque,
case 0xA50:
return s->dmac_ram;
case 0xA60 ... 0xA8C:
- return s->afi[0][(offset - 0x700) / 4];
+ return s->afi[0][(offset - 0xA60) / 4];
case 0xA90 ... 0xA98:
return s->ocm[(offset - 0xA90) / 4];
case 0xAA0:
@@ -454,7 +454,7 @@ static void zynq_slcr_write(void *opaque, target_phys_addr_t offset,
s->dmac_ram = val;
break;
case 0xA60 ... 0xA8C:
- s->afi[0][(offset - 0x700) / 4] = val;
+ s->afi[0][(offset - 0xA60) / 4] = val;
break;
case 0xA90:
s->ocm[0] = val;
diff --git a/include/qemu/object.h b/include/qemu/object.h
index 69e4b7b282..ec2d2943c2 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -124,7 +124,7 @@ typedef struct InterfaceInfo InterfaceInfo;
*
* Once all of the parent classes have been initialized, #TypeInfo::class_init
* is called to let the class being instantiated provide default initialize for
- * it's virtual functions. Here is how the above example might be modified
+ * its virtual functions. Here is how the above example might be modified
* to introduce an overridden virtual function:
*
* <example>
@@ -288,7 +288,7 @@ struct Object
* implementing an explicit class type if they are not adding additional
* virtual functions.
* @class_init: This function is called after all parent class initialization
- * has occured to allow a class to set its default virtual method pointers.
+ * has occurred to allow a class to set its default virtual method pointers.
* This is also the function to use to override virtual methods from a parent
* class.
* @class_finalize: This function is called during class destruction and is
@@ -527,7 +527,7 @@ Type type_register_static(const TypeInfo *info);
* type_register:
* @info: The #TypeInfo of the new type
*
- * Unlike type_register_static(), this call does not require @info or it's
+ * Unlike type_register_static(), this call does not require @info or its
* string members to continue to exist after the call returns.
*
* Returns: 0 on failure, the new #Type on success.
diff --git a/kvm-all.c b/kvm-all.c
index 77eadf608f..3c6b4f0808 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -35,7 +35,7 @@
#include <sys/eventfd.h>
#endif
-/* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
+/* KVM uses PAGE_SIZE in its definition of COALESCED_MMIO_MAX */
#define PAGE_SIZE TARGET_PAGE_SIZE
//#define DEBUG_KVM
@@ -76,6 +76,7 @@ struct KVMState
struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
#endif
int pit_in_kernel;
+ int pit_state2;
int xsave, xcrs;
int many_ioeventfds;
int irqchip_inject_ioctl;
@@ -447,6 +448,7 @@ int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
zone.addr = start;
zone.size = size;
+ zone.pad = 0;
ret = kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone);
}
@@ -464,6 +466,7 @@ int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
zone.addr = start;
zone.size = size;
+ zone.pad = 0;
ret = kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone);
}
@@ -1058,6 +1061,10 @@ int kvm_init(void)
s->xcrs = kvm_check_extension(s, KVM_CAP_XCRS);
#endif
+#ifdef KVM_CAP_PIT_STATE2
+ s->pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2);
+#endif
+
ret = kvm_arch_init(s);
if (ret < 0) {
goto err;
@@ -1390,6 +1397,11 @@ int kvm_has_xcrs(void)
return kvm_state->xcrs;
}
+int kvm_has_pit_state2(void)
+{
+ return kvm_state->pit_state2;
+}
+
int kvm_has_many_ioeventfds(void)
{
if (!kvm_enabled()) {
diff --git a/kvm-stub.c b/kvm-stub.c
index f63a0d2c81..1f1c6861ed 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -78,6 +78,11 @@ int kvm_allows_irq0_override(void)
return 1;
}
+int kvm_has_pit_state2(void)
+{
+ return 0;
+}
+
void kvm_setup_guest_memory(void *start, size_t size)
{
}
diff --git a/kvm.h b/kvm.h
index f9f1dc86b3..8ef44767af 100644
--- a/kvm.h
+++ b/kvm.h
@@ -54,6 +54,7 @@ int kvm_has_robust_singlestep(void);
int kvm_has_debugregs(void);
int kvm_has_xsave(void);
int kvm_has_xcrs(void);
+int kvm_has_pit_state2(void);
int kvm_has_many_ioeventfds(void);
int kvm_has_gsi_routing(void);
diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
index d4d8e2ed18..d3e9522774 100644
--- a/libcacard/vcardt.h
+++ b/libcacard/vcardt.h
@@ -26,8 +26,8 @@ typedef struct VCardEmulStruct VCardEmul;
#define MAX_CHANNEL 4
/* create an ATR with appropriate historical bytes */
-#define VCARD_ATR_PREFIX(size) (0x3b, 0x68+(size), 0x00, 0xff, \
- 'V', 'C', 'A', 'R', 'D', '_')
+#define VCARD_ATR_PREFIX(size) 0x3b, 0x68+(size), 0x00, 0xff, \
+ 'V', 'C', 'A', 'R', 'D', '_'
typedef enum {
diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
index e317a25faf..b64c93dd69 100644
--- a/libcacard/vscclient.c
+++ b/libcacard/vscclient.c
@@ -66,7 +66,7 @@ send_msg(
qemu_mutex_lock(&write_lock);
if (verbose > 10) {
- printf("sending type=%d id=%d, len =%d (0x%x)\n",
+ printf("sending type=%d id=%u, len =%u (0x%x)\n",
type, reader_id, length, length);
}
@@ -129,7 +129,7 @@ event_thread(void *arg)
vevent_delete(event);
continue;
}
- /* this reader hasn't been told it's status from qemu yet, wait for
+ /* this reader hasn't been told its status from qemu yet, wait for
* that status */
while (pending_reader != NULL) {
qemu_cond_wait(&pending_reader_condition, &pending_reader_lock);
@@ -167,7 +167,7 @@ event_thread(void *arg)
case VEVENT_READER_REMOVE:
/* future, tell qemu that an old CCID reader has been removed */
if (verbose > 10) {
- printf(" READER REMOVE: %d\n", reader_id);
+ printf(" READER REMOVE: %u\n", reader_id);
}
send_msg(VSC_ReaderRemove, reader_id, NULL, 0);
break;
@@ -178,7 +178,7 @@ event_thread(void *arg)
vreader_power_on(event->reader, atr, &atr_len);
/* ATR call functions as a Card Insert event */
if (verbose > 10) {
- printf(" CARD INSERT %d: ", reader_id);
+ printf(" CARD INSERT %u: ", reader_id);
print_byte_array(atr, atr_len);
}
send_msg(VSC_ATR, reader_id, atr, atr_len);
@@ -186,7 +186,7 @@ event_thread(void *arg)
case VEVENT_CARD_REMOVE:
/* Card removed */
if (verbose > 10) {
- printf(" CARD REMOVE %d:\n", reader_id);
+ printf(" CARD REMOVE %u:\n", reader_id);
}
send_msg(VSC_CardRemove, reader_id, NULL, 0);
break;
@@ -256,7 +256,7 @@ do_command(void)
reader ? vreader_get_name(reader)
: "invalid reader", error);
} else {
- printf("no reader by id %d found\n", reader_id);
+ printf("no reader by id %u found\n", reader_id);
}
} else if (strncmp(string, "remove", 6) == 0) {
if (string[6] == ' ') {
@@ -269,7 +269,7 @@ do_command(void)
reader ? vreader_get_name(reader)
: "invalid reader", error);
} else {
- printf("no reader by id %d found\n", reader_id);
+ printf("no reader by id %u found\n", reader_id);
}
} else if (strncmp(string, "select", 6) == 0) {
if (string[6] == ' ') {
@@ -280,11 +280,11 @@ do_command(void)
reader = vreader_get_reader_by_id(reader_id);
}
if (reader) {
- printf("Selecting reader %d, %s\n", reader_id,
+ printf("Selecting reader %u, %s\n", reader_id,
vreader_get_name(reader));
default_reader_id = reader_id;
} else {
- printf("Reader with id %d not found\n", reader_id);
+ printf("Reader with id %u not found\n", reader_id);
}
} else if (strncmp(string, "debug", 5) == 0) {
if (string[5] == ' ') {
@@ -303,7 +303,7 @@ do_command(void)
if (reader_id == -1) {
continue;
}
- printf("%3d %s %s\n", reader_id,
+ printf("%3u %s %s\n", reader_id,
vreader_card_is_present(reader) == VREADER_OK ?
"CARD_PRESENT" : " ",
vreader_get_name(reader));
@@ -563,7 +563,7 @@ main(
mhHeader.reader_id = ntohl(mhHeader.reader_id);
mhHeader.length = ntohl(mhHeader.length);
if (verbose) {
- printf("Header: type=%d, reader_id=%d length=%d (0x%x)\n",
+ printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
mhHeader.type, mhHeader.reader_id, mhHeader.length,
mhHeader.length);
}
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 79a39dcd7f..cefd2ff3ce 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -2700,7 +2700,7 @@ get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
sp = regs->active_tc.gpr[29];
/*
- * FPU emulator may have it's own trampoline active just
+ * FPU emulator may have its own trampoline active just
* above the user stack, 16-bytes before the next lowest
* 16 byte boundary. Try to avoid trashing it.
*/
diff --git a/osdep.h b/osdep.h
index 432b91ea72..0350383711 100644
--- a/osdep.h
+++ b/osdep.h
@@ -26,9 +26,6 @@
#define unlikely(x) __builtin_expect(!!(x), 0)
#endif
-#ifdef CONFIG_NEED_OFFSETOF
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER)
-#endif
#ifndef container_of
#define container_of(ptr, type, member) ({ \
const typeof(((type *) 0)->member) *__mptr = (ptr); \
diff --git a/qapi-schema.json b/qapi-schema.json
index 5f293c4403..dd9e0e5434 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -616,11 +616,12 @@
# @connection-id: SPICE connection id number. All channels with the same id
# belong to the same SPICE session.
#
-# @connection-type: SPICE channel type number. "1" is the main control channel,
-# filter for this one if you want track spice sessions only
+# @connection-type: SPICE channel type number. "1" is the main control
+# channel, filter for this one if you want to track spice
+# sessions only
#
-# @channel-id: SPICE channel ID number. Usually "0", might be different needed
-# when multiple channels of the same type exist, such as multiple
+# @channel-id: SPICE channel ID number. Usually "0", might be different when
+# multiple channels of the same type exist, such as multiple
# display channels in a multihead setup
#
# @tls: true if the channel is encrypted, false otherwise.
@@ -649,8 +650,9 @@
# @tls-port: #optional The SPICE server's TLS port number.
#
# @auth: #optional the current authentication type used by the server
-# 'none' if no authentication is being used
-# 'spice' (TODO: describe)
+# 'none' if no authentication is being used
+# 'spice' uses SASL or direct TLS authentication, depending on command
+# line options
#
# @channels: a list of @SpiceChannel for each active spice channel
#
@@ -1254,7 +1256,7 @@
{ 'command': 'migrate_set_speed', 'data': {'value': 'int'} }
##
-# @DevicePropertyInfo:
+# @ObjectPropertyInfo:
#
# @name: the name of the property
#
diff --git a/qemu-common.h b/qemu-common.h
index dbfce6f4c6..b0fdf5c2b4 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -93,9 +93,13 @@ typedef int (*fprintf_function)(FILE *f, const char *fmt, ...)
#ifdef _WIN32
#define fsync _commit
-#define lseek _lseeki64
+#if !defined(lseek)
+# define lseek _lseeki64
+#endif
int qemu_ftruncate64(int, int64_t);
-#define ftruncate qemu_ftruncate64
+#if !defined(ftruncate)
+# define ftruncate qemu_ftruncate64
+#endif
static inline char *realpath(const char *path, char *resolved_path)
{
diff --git a/qemu-file.h b/qemu-file.h
index 8da10213d9..31b83f6bb3 100644
--- a/qemu-file.h
+++ b/qemu-file.h
@@ -47,7 +47,7 @@ typedef int (QEMUFileGetBufferFunc)(void *opaque, uint8_t *buf,
*/
typedef int (QEMUFileCloseFunc)(void *opaque);
-/* Called to determine if the file has exceeded it's bandwidth allocation. The
+/* Called to determine if the file has exceeded its bandwidth allocation. The
* bandwidth capping is a soft limit, not a hard limit.
*/
typedef int (QEMUFileRateLimit)(void *opaque);
diff --git a/qjson.h b/qjson.h
index 65b10ea369..1190d8a86c 100644
--- a/qjson.h
+++ b/qjson.h
@@ -15,6 +15,7 @@
#define QJSON_H
#include <stdarg.h>
+#include "compiler.h"
#include "qobject.h"
#include "qstring.h"
diff --git a/qom/object.c b/qom/object.c
index aa037d299f..39cbcb9b75 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -304,12 +304,9 @@ static void object_property_del_child(Object *obj, Object *child, Error **errp)
ObjectProperty *prop;
QTAILQ_FOREACH(prop, &obj->properties, node) {
- if (!strstart(prop->type, "child<", NULL)) {
- continue;
- }
-
- if (prop->opaque == child) {
+ if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
object_property_del(obj, prop->name, errp);
+ break;
}
}
}
diff --git a/scripts/tracetool b/scripts/tracetool
index 4c9951d0aa..65bd0a1b4c 100755
--- a/scripts/tracetool
+++ b/scripts/tracetool
@@ -415,9 +415,7 @@ linetoh_dtrace()
# Define an empty function for the trace event
cat <<EOF
static inline void trace_$name($args) {
- if (QEMU_${nameupper}_ENABLED()) {
- QEMU_${nameupper}($argnames);
- }
+ QEMU_${nameupper}($argnames);
}
EOF
}
@@ -519,7 +517,7 @@ linetostap_end_dtrace()
# Process stdin by calling begin, line, and end functions for the backend
convert()
{
- local begin process_line end str disable
+ local begin process_line end str name NAME enabled
begin="lineto$1_begin_$backend"
process_line="lineto$1_$backend"
end="lineto$1_end_$backend"
@@ -534,8 +532,15 @@ convert()
# Process the line. The nop backend handles disabled lines.
if has_property "$str" "disable"; then
"lineto$1_nop" "$str"
+ enabled=0
else
"$process_line" "$str"
+ enabled=1
+ fi
+ if [ "$1" = "h" ]; then
+ name=$(get_name "$str")
+ NAME=$(echo $name | tr '[:lower:]' '[:upper:]')
+ echo "#define TRACE_${NAME}_ENABLED ${enabled}"
fi
done
diff --git a/sysconfigs/target/target-x86_64.conf b/sysconfigs/target/target-x86_64.conf
index d0503804c2..cee0ea9e55 100644
--- a/sysconfigs/target/target-x86_64.conf
+++ b/sysconfigs/target/target-x86_64.conf
@@ -57,6 +57,20 @@
model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)"
[cpudef]
+ name = "SandyBridge"
+ level = "0xd"
+ vendor = "GenuineIntel"
+ family = "6"
+ model = "42"
+ stepping = "1"
+ feature_edx = " sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu"
+ feature_ecx = "avx xsave aes tsc-deadline popcnt x2apic sse4.2 sse4.1 cx16 ssse3 pclmulqdq sse3"
+ extfeature_edx = "i64 rdtscp nx syscall "
+ extfeature_ecx = "lahf_lm"
+ xlevel = "0x8000000A"
+ model_id = "Intel Xeon E312xx (Sandy Bridge)"
+
+[cpudef]
name = "Opteron_G1"
level = "5"
vendor = "AuthenticAMD"
@@ -98,3 +112,17 @@
xlevel = "0x80000008"
model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)"
+[cpudef]
+ name = "Opteron_G4"
+ level = "0xd"
+ vendor = "AuthenticAMD"
+ family = "21"
+ model = "1"
+ stepping = "2"
+ feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu"
+ feature_ecx = "avx xsave aes popcnt sse4.2 sse4.1 cx16 ssse3 pclmulqdq sse3"
+ extfeature_edx = "lm rdtscp pdpe1gb fxsr mmx nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de fpu"
+ extfeature_ecx = " fma4 xop 3dnowprefetch misalignsse sse4a abm svm lahf_lm"
+ xlevel = "0x8000001A"
+ model_id = "AMD Opteron 62xx class CPU"
+
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 196b0c5c40..36e3d29ea0 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -241,6 +241,7 @@
#define PG_DIRTY_MASK (1 << PG_DIRTY_BIT)
#define PG_PSE_MASK (1 << PG_PSE_BIT)
#define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT)
+#define PG_HI_USER_MASK 0x7ff0000000000000LL
#define PG_NX_MASK (1LL << PG_NX_BIT)
#define PG_ERROR_W_BIT 1
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index c2edb646fe..465ea15f45 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -50,7 +50,7 @@ static const char *ext_feature_name[] = {
"fma", "cx16", "xtpr", "pdcm",
NULL, NULL, "dca", "sse4.1|sse4_1",
"sse4.2|sse4_2", "x2apic", "movbe", "popcnt",
- NULL, "aes", "xsave", "osxsave",
+ "tsc-deadline", "aes", "xsave", "osxsave",
"avx", NULL, NULL, "hypervisor",
};
static const char *ext2_feature_name[] = {
diff --git a/target-i386/helper.c b/target-i386/helper.c
index af6bba2680..f4f3c2726a 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -885,8 +885,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
if (!(pml4e & PG_PRESENT_MASK))
return -1;
- pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
- env->a20_mask;
+ pdpe_addr = ((pml4e & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
+ (((addr >> 30) & 0x1ff) << 3)) & env->a20_mask;
pdpe = ldq_phys(pdpe_addr);
if (!(pdpe & PG_PRESENT_MASK))
return -1;
@@ -900,8 +900,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
return -1;
}
- pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
- env->a20_mask;
+ pde_addr = ((pdpe & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
+ (((addr >> 21) & 0x1ff) << 3)) & env->a20_mask;
pde = ldq_phys(pde_addr);
if (!(pde & PG_PRESENT_MASK)) {
return -1;
@@ -912,11 +912,12 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
} else {
/* 4 KB page */
- pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
- env->a20_mask;
+ pte_addr = ((pde & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
+ (((addr >> 12) & 0x1ff) << 3)) & env->a20_mask;
page_size = 4096;
pte = ldq_phys(pte_addr);
}
+ pte &= ~(PG_NX_MASK | PG_HI_USER_MASK);
if (!(pte & PG_PRESENT_MASK))
return -1;
} else {
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 9a732078f3..619d773114 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -555,6 +555,7 @@ int kvm_arch_init_vcpu(CPUState *env)
qemu_add_vm_change_state_handler(cpu_update_state, env);
+ cpuid_data.cpuid.padding = 0;
r = kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data);
if (r) {
return r;
@@ -740,6 +741,7 @@ static void set_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
lhs->g = (flags & DESC_G_MASK) != 0;
lhs->avl = (flags & DESC_AVL_MASK) != 0;
lhs->unusable = 0;
+ lhs->padding = 0;
}
static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs)
@@ -919,8 +921,10 @@ static int kvm_put_sregs(CPUState *env)
sregs.idt.limit = env->idt.limit;
sregs.idt.base = env->idt.base;
+ memset(sregs.idt.padding, 0, sizeof sregs.idt.padding);
sregs.gdt.limit = env->gdt.limit;
sregs.gdt.base = env->gdt.base;
+ memset(sregs.gdt.padding, 0, sizeof sregs.gdt.padding);
sregs.cr0 = env->cr[0];
sregs.cr2 = env->cr[2];
@@ -1392,6 +1396,7 @@ static int kvm_put_vcpu_events(CPUState *env, int level)
events.exception.nr = env->exception_injected;
events.exception.has_error_code = env->has_error_code;
events.exception.error_code = env->error_code;
+ events.exception.pad = 0;
events.interrupt.injected = (env->interrupt_injected >= 0);
events.interrupt.nr = env->interrupt_injected;
@@ -1400,6 +1405,7 @@ static int kvm_put_vcpu_events(CPUState *env, int level)
events.nmi.injected = env->nmi_injected;
events.nmi.pending = env->nmi_pending;
events.nmi.masked = !!(env->hflags2 & HF2_NMI_MASK);
+ events.nmi.pad = 0;
events.sipi_vector = env->sipi_vector;
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index c51b9cb6f0..87e9799ba3 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1930,7 +1930,7 @@ target_ulong helper_evpe(void)
do {
if (other_cpu != env
- /* If the VPE is WFI, dont distrub it's sleep. */
+ /* If the VPE is WFI, don't disturb its sleep. */
&& !mips_vpe_is_wfi(other_cpu)) {
/* Enable the VPE. */
other_cpu->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 59d4d12ba6..71f4a8a6b2 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -1052,7 +1052,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
/* TLB Miss. */
/* label1: */
- tcg_out_label(s, lab1, (tcg_target_long)s->code_ptr);
+ tcg_out_label(s, lab1, s->code_ptr);
argreg = TCG_REG_R26;
tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrlo_reg);
@@ -1089,7 +1089,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
}
/* label2: */
- tcg_out_label(s, lab2, (tcg_target_long)s->code_ptr);
+ tcg_out_label(s, lab2, s->code_ptr);
#else
tcg_out_qemu_ld_direct(s, datalo_reg, datahi_reg, addrlo_reg,
(GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_R0), opc);
@@ -1171,7 +1171,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
/* TLB Miss. */
/* label1: */
- tcg_out_label(s, lab1, (tcg_target_long)s->code_ptr);
+ tcg_out_label(s, lab1, s->code_ptr);
argreg = TCG_REG_R26;
tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrlo_reg);
@@ -1215,7 +1215,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
tcg_out_call(s, qemu_st_helpers[opc]);
/* label2: */
- tcg_out_label(s, lab2, (tcg_target_long)s->code_ptr);
+ tcg_out_label(s, lab2, s->code_ptr);
#else
/* There are no indexed stores, so if GUEST_BASE is set we must do the add
explicitly. Careful to avoid R20, which is used for the bswaps to follow. */
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index dc81572c09..1dbe2408ad 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -875,7 +875,7 @@ static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
default:
tcg_abort();
}
- tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
+ tcg_out_label(s, label_next, s->code_ptr);
}
#endif
@@ -917,10 +917,10 @@ static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
tcg_out_jxx(s, JCC_JMP, label_over, 1);
- tcg_out_label(s, label_true, (tcg_target_long)s->code_ptr);
+ tcg_out_label(s, label_true, s->code_ptr);
tcg_out_movi(s, TCG_TYPE_I32, args[0], 1);
- tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
+ tcg_out_label(s, label_over, s->code_ptr);
} else {
/* When the destination does not overlap one of the arguments,
clear the destination first, jump if cond false, and emit an
@@ -934,7 +934,7 @@ static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
tcg_out_brcond2(s, new_args, const_args+1, 1);
tgen_arithi(s, ARITH_ADD, args[0], 1, 0);
- tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
+ tcg_out_label(s, label_over, s->code_ptr);
}
}
#endif
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 5cd5a3b6f6..4461fb4d13 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -582,7 +582,7 @@ static void tcg_out_brcond2_i32(TCGContext *s, TCGCond cond,
}
tcg_out_nop(s);
- tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
+ tcg_out_label(s, label_next, s->code_ptr);
}
#endif
@@ -628,7 +628,7 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGArg ret,
tcg_out_branch_i32(s, INSN_COND(tcg_cond_to_bcond[cond], 1), t);
tcg_out_movi_imm13(s, ret, 1);
tcg_out_movi_imm13(s, ret, 0);
- tcg_out_label(s, t, (tcg_target_long)s->code_ptr);
+ tcg_out_label(s, t, s->code_ptr);
#endif
return;
}
@@ -683,7 +683,7 @@ static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret,
tcg_out_setcond_i32(s, tcg_unsigned_cond(cond), ret, al, bl, blconst);
- tcg_out_label(s, lab, (tcg_target_long)s->code_ptr);
+ tcg_out_label(s, lab, s->code_ptr);
break;
}
}
diff --git a/tcg/tcg.c b/tcg/tcg.c
index cd2db3cb50..531db55f5d 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -128,11 +128,11 @@ static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
}
}
-static void tcg_out_label(TCGContext *s, int label_index,
- tcg_target_long value)
+static void tcg_out_label(TCGContext *s, int label_index, void *ptr)
{
TCGLabel *l;
TCGRelocation *r;
+ tcg_target_long value = (tcg_target_long)ptr;
l = &s->labels[label_index];
if (l->has_value)
@@ -2123,7 +2123,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
break;
case INDEX_op_set_label:
tcg_reg_alloc_bb_end(s, s->reserved_regs);
- tcg_out_label(s, args[0], (long)s->code_ptr);
+ tcg_out_label(s, args[0], s->code_ptr);
break;
case INDEX_op_call:
dead_args = s->op_dead_args[op_index];
diff --git a/test-qmp-output-visitor.c b/test-qmp-output-visitor.c
index c94c208125..5452cd43bc 100644
--- a/test-qmp-output-visitor.c
+++ b/test-qmp-output-visitor.c
@@ -221,8 +221,8 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
QObject *obj;
QDict *qdict, *dict1, *dict2, *dict3, *userdef;
const char *string = "user def string";
- const char *strings[] = { "fourty two", "fourty three", "fourty four",
- "fourty five" };
+ const char *strings[] = { "forty two", "forty three", "forty four",
+ "forty five" };
ud2 = g_malloc0(sizeof(*ud2));
ud2->string0 = g_strdup(strings[0]);
diff --git a/trace-events b/trace-events
index c5d0f0f547..dfe28ed42b 100644
--- a/trace-events
+++ b/trace-events
@@ -658,3 +658,10 @@ dma_aio_cancel(void *dbs) "dbs=%p"
dma_complete(void *dbs, int ret, void *cb) "dbs=%p ret=%d cb=%p"
dma_bdrv_cb(void *dbs, int ret) "dbs=%p ret=%d"
dma_map_wait(void *dbs) "dbs=%p"
+
+# console.h
+displaysurface_free(void *display_state, void *display_surface) "state=%p surface=%p"
+displaysurface_resize(void *display_state, void *display_surface, int width, int height) "state=%p surface=%p %dx%d"
+
+# vga.c
+ppm_save(const char *filename, void *display_surface) "%s surface=%p"
diff --git a/trace/simple.c b/trace/simple.c
index bbc99302b9..33ae48696d 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -363,7 +363,7 @@ static GThread *trace_thread_create(GThreadFunc fn)
sigfillset(&set);
pthread_sigmask(SIG_SETMASK, &set, &oldset);
#endif
- thread = g_thread_create(writeout_thread, NULL, FALSE, NULL);
+ thread = g_thread_create(fn, NULL, FALSE, NULL);
#ifndef _WIN32
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
#endif
diff --git a/ui/vnc-enc-hextile-template.h b/ui/vnc-enc-hextile-template.h
index b9f9f5ef89..a7310e1947 100644
--- a/ui/vnc-enc-hextile-template.h
+++ b/ui/vnc-enc-hextile-template.h
@@ -175,6 +175,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
/* we really don't have to invalidate either the bg or fg
but we've lost the old values. oh well. */
}
+ break;
default:
break;
}
diff --git a/ui/vnc.c b/ui/vnc.c
index 8ee39bc030..bdec33a470 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1936,7 +1936,10 @@ static void pixel_format_message (VncState *vs) {
static void vnc_dpy_setdata(DisplayState *ds)
{
- /* We don't have to do anything */
+ VncDisplay *vd = ds->opaque;
+
+ *(vd->guest.ds) = *(ds->surface);
+ vnc_dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
}
static void vnc_colordepth(VncState *vs)
diff --git a/usb-linux.c b/usb-linux.c
index 47994f3ceb..90919c242a 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -364,8 +364,12 @@ static void async_complete(void *opaque)
p->result = USB_RET_STALL;
break;
+ case -EOVERFLOW:
+ p->result = USB_RET_BABBLE;
+ break;
+
default:
- p->result = USB_RET_NAK;
+ p->result = USB_RET_IOERROR;
break;
}
@@ -722,8 +726,10 @@ static int urb_status_to_usb_ret(int status)
switch (status) {
case -EPIPE:
return USB_RET_STALL;
+ case -EOVERFLOW:
+ return USB_RET_BABBLE;
default:
- return USB_RET_NAK;
+ return USB_RET_IOERROR;
}
}
@@ -759,7 +765,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
} else if (aurb[i].urb.iso_frame_desc[j].actual_length
> p->iov.size) {
printf("husb: received iso data is larger then packet\n");
- len = USB_RET_NAK;
+ len = USB_RET_BABBLE;
/* All good copy data over */
} else {
len = aurb[i].urb.iso_frame_desc[j].actual_length;
@@ -1186,6 +1192,9 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
USB_ENDPOINT_XFER_INVALID);
usb_ep_set_type(&s->dev, pid, ep, type);
usb_ep_set_ifnum(&s->dev, pid, ep, interface);
+ if (type == USB_ENDPOINT_XFER_BULK) {
+ usb_ep_set_pipeline(&s->dev, pid, ep, true);
+ }
epd = get_endp(s, pid, ep);
epd->halted = 0;
diff --git a/usb-redir.c b/usb-redir.c
index 755492f379..8e9f175dbb 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -431,7 +431,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
/* Check iso_error for stream errors, otherwise its an underrun */
status = dev->endpoint[EP2I(ep)].iso_error;
dev->endpoint[EP2I(ep)].iso_error = 0;
- return status ? USB_RET_NAK : 0;
+ return status ? USB_RET_IOERROR : 0;
}
DPRINTF2("iso-token-in ep %02X status %d len %d queue-size: %d\n", ep,
isop->status, isop->len, dev->endpoint[EP2I(ep)].bufpq_size);
@@ -439,7 +439,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
status = isop->status;
if (status != usb_redir_success) {
bufp_free(dev, isop, ep);
- return USB_RET_NAK;
+ return USB_RET_IOERROR;
}
len = isop->len;
@@ -447,7 +447,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
ERROR("received iso data is larger then packet ep %02X (%d > %d)\n",
ep, len, (int)p->iov.size);
bufp_free(dev, isop, ep);
- return USB_RET_NAK;
+ return USB_RET_BABBLE;
}
usb_packet_copy(p, isop->data, len);
bufp_free(dev, isop, ep);
@@ -566,7 +566,7 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
if (len > p->iov.size) {
ERROR("received int data is larger then packet ep %02X\n", ep);
bufp_free(dev, intp, ep);
- return USB_RET_NAK;
+ return USB_RET_BABBLE;
}
usb_packet_copy(p, intp->data, len);
bufp_free(dev, intp, ep);
@@ -1018,11 +1018,14 @@ static int usbredir_handle_status(USBRedirDevice *dev,
return USB_RET_STALL;
case usb_redir_cancelled:
WARNING("returning cancelled packet to HC?\n");
+ return USB_RET_NAK;
case usb_redir_inval:
+ WARNING("got invalid param error from usb-host?\n");
+ return USB_RET_NAK;
case usb_redir_ioerror:
case usb_redir_timeout:
default:
- return USB_RET_NAK;
+ return USB_RET_IOERROR;
}
}
@@ -1122,6 +1125,7 @@ static void usbredir_device_disconnect(void *priv)
for (i = 0; i < MAX_ENDPOINTS; i++) {
QTAILQ_INIT(&dev->endpoint[i].bufpq);
}
+ usb_ep_init(&dev->dev);
dev->interface_info.interface_count = 0;
}
@@ -1148,6 +1152,7 @@ static void usbredir_ep_info(void *priv,
struct usb_redir_ep_info_header *ep_info)
{
USBRedirDevice *dev = priv;
+ struct USBEndpoint *usb_ep;
int i;
for (i = 0; i < MAX_ENDPOINTS; i++) {
@@ -1172,7 +1177,13 @@ static void usbredir_ep_info(void *priv,
default:
ERROR("Received invalid endpoint type\n");
usbredir_device_disconnect(dev);
+ return;
}
+ usb_ep = usb_ep_get(&dev->dev,
+ (i & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT,
+ i & 0x0f);
+ usb_ep->type = dev->endpoint[i].type;
+ usb_ep->ifnum = dev->endpoint[i].interface;
}
}
diff --git a/vl.c b/vl.c
index 97ab2b9c1a..65f11f200d 100644
--- a/vl.c
+++ b/vl.c
@@ -2359,7 +2359,6 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
}
- cpudef_init();
/* second pass of option parsing */
optind = 1;
@@ -2382,12 +2381,7 @@ int main(int argc, char **argv, char **envp)
break;
case QEMU_OPTION_cpu:
/* hw initialization will check this */
- if (*optarg == '?') {
- list_cpus(stdout, &fprintf, optarg);
- exit(0);
- } else {
- cpu_model = optarg;
- }
+ cpu_model = optarg;
break;
case QEMU_OPTION_hda:
{
@@ -3191,6 +3185,18 @@ int main(int argc, char **argv, char **envp)
}
loc_set_none();
+ /* Init CPU def lists, based on config
+ * - Must be called after all the qemu_read_config_file() calls
+ * - Must be called before list_cpus()
+ * - Must be called before machine->init()
+ */
+ cpudef_init();
+
+ if (cpu_model && *cpu_model == '?') {
+ list_cpus(stdout, &fprintf, optarg);
+ exit(0);
+ }
+
/* Open the logfile at this point, if necessary. We can't open the logfile
* when encountering either of the logging options (-d or -D) because the
* other one may be encountered later on the command line, changing the