diff options
67 files changed, 1337 insertions, 410 deletions
diff --git a/.gitignore b/.gitignore index 7fb8e0c7e..172579ebf 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ config-host.* config-target.* trace.h trace.c +*-timestamp *-softmmu *-darwin-user *-linux-user @@ -153,7 +153,7 @@ clean: rm -f *.o *.d *.a $(TOOLS) TAGS cscope.* *.pod *~ */*~ rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d rm -f qemu-img-cmds.h - rm -f trace.c trace.h + rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp $(MAKE) -C tests clean for d in $(ALL_SUBDIRS) libhw32 libhw64 libuser libdis libdis-user; do \ if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \ @@ -176,7 +176,7 @@ common de-ch es fo fr-ca hu ja mk nl-be pt sl tr ifdef INSTALL_BLOBS BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \ -video.x openbios-sparc32 openbios-sparc64 openbios-ppc \ +openbios-sparc32 openbios-sparc64 openbios-ppc \ gpxe-eepro100-80861209.rom \ gpxe-eepro100-80861229.rom \ pxe-e1000.bin \ @@ -262,7 +262,7 @@ TEXIFLAG=$(if $(V),,--quiet) qemu-options.texi: $(SRC_PATH)/qemu-options.hx $(call quiet-command,sh $(SRC_PATH)/hxtool -t < $< > $@," GEN $@") -qemu-monitor.texi: $(SRC_PATH)/qemu-monitor.hx +qemu-monitor.texi: $(SRC_PATH)/hmp-commands.hx $(call quiet-command,sh $(SRC_PATH)/hxtool -t < $< > $@," GEN $@") QMP/qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx @@ -330,7 +330,6 @@ tarbin: $(datadir)/vgabios.bin \ $(datadir)/vgabios-cirrus.bin \ $(datadir)/ppc_rom.bin \ - $(datadir)/video.x \ $(datadir)/openbios-sparc32 \ $(datadir)/openbios-sparc64 \ $(datadir)/openbios-ppc \ diff --git a/Makefile.objs b/Makefile.objs index 71d0e4521..ca2d2d057 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -91,6 +91,8 @@ common-obj-$(CONFIG_BRLAPI) += baum.o common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o common-obj-$(CONFIG_WIN32) += version.o +common-obj-$(CONFIG_SPICE) += ui/spice-core.o ui/spice-input.o ui/spice-display.o + audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o audio-obj-$(CONFIG_SDL) += sdlaudio.o audio-obj-$(CONFIG_OSS) += ossaudio.o diff --git a/Makefile.target b/Makefile.target index c054a7e82..536455519 100644 --- a/Makefile.target +++ b/Makefile.target @@ -340,7 +340,7 @@ endif main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS) -monitor.o: qemu-monitor.h qmp-commands.h +monitor.o: hmp-commands.h qmp-commands.h $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS) @@ -361,7 +361,7 @@ $(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y) gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/feature_to_c.sh $(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@") -qemu-monitor.h: $(SRC_PATH)/qemu-monitor.hx +hmp-commands.h: $(SRC_PATH)/hmp-commands.hx $(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@") qmp-commands.h: $(SRC_PATH)/qmp-commands.hx @@ -370,7 +370,7 @@ qmp-commands.h: $(SRC_PATH)/qmp-commands.hx clean: rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o rm -f *.d */*.d tcg/*.o ide/*.o - rm -f qemu-monitor.h qmp-commands.h gdbstub-xml.c + rm -f hmp-commands.h qmp-commands.h gdbstub-xml.c install: all ifneq ($(PROGS),) diff --git a/QMP/README b/QMP/README index 7e2b51a9b..80503f2d7 100644 --- a/QMP/README +++ b/QMP/README @@ -88,4 +88,4 @@ doing any code change. This is so because: Homepage -------- -http://www.linux-kvm.org/page/MonitorProtocol +http://wiki.qemu.org/QMP diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index f0171f984..07412030c 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -843,11 +843,15 @@ static int alsa_init_out (HWVoiceOut *hw, struct audsettings *as) return 0; } -static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int pause) +#define VOICE_CTL_PAUSE 0 +#define VOICE_CTL_PREPARE 1 +#define VOICE_CTL_START 2 + +static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int ctl) { int err; - if (pause) { + if (ctl == VOICE_CTL_PAUSE) { err = snd_pcm_drop (handle); if (err < 0) { alsa_logerr (err, "Could not stop %s\n", typ); @@ -860,6 +864,13 @@ static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int pause) alsa_logerr (err, "Could not prepare handle for %s\n", typ); return -1; } + if (ctl == VOICE_CTL_START) { + err = snd_pcm_start(handle); + if (err < 0) { + alsa_logerr (err, "Could not start handle for %s\n", typ); + return -1; + } + } } return 0; @@ -884,12 +895,16 @@ static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...) poll_mode = 0; } hw->poll_mode = poll_mode; - return alsa_voice_ctl (alsa->handle, "playback", 0); + return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PREPARE); } case VOICE_DISABLE: ldebug ("disabling voice\n"); - return alsa_voice_ctl (alsa->handle, "playback", 1); + if (hw->poll_mode) { + hw->poll_mode = 0; + alsa_fini_poll (&alsa->pollhlp); + } + return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PAUSE); } return -1; @@ -1102,7 +1117,7 @@ static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...) } hw->poll_mode = poll_mode; - return alsa_voice_ctl (alsa->handle, "capture", 0); + return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_START); } case VOICE_DISABLE: @@ -1111,7 +1126,7 @@ static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...) hw->poll_mode = 0; alsa_fini_poll (&alsa->pollhlp); } - return alsa_voice_ctl (alsa->handle, "capture", 1); + return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_PAUSE); } return -1; @@ -1983,6 +1983,8 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num, BlockDriver *drv = bs->drv; BlockDriverAIOCB *ret; + trace_bdrv_aio_readv(bs, sector_num, nb_sectors, opaque); + if (!drv) return NULL; if (bdrv_check_request(bs, sector_num, nb_sectors)) @@ -2007,6 +2009,8 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, BlockDriver *drv = bs->drv; BlockDriverAIOCB *ret; + trace_bdrv_aio_writev(bs, sector_num, nb_sectors, opaque); + if (!drv) return NULL; if (bs->read_only) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 7082601f5..0efb6760c 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -551,6 +551,7 @@ fail: if (ret < 0) { int dummy; dummy = update_refcount(bs, offset, cluster_offset - offset, -addend); + (void)dummy; } return ret; diff --git a/bsd-user/main.c b/bsd-user/main.c index aff9f13b1..6b12f8bba 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -795,6 +795,12 @@ int main(int argc, char **argv) r = argv[optind++]; if (envlist_setenv(envlist, r) != 0) usage(); + } else if (!strcmp(r, "ignore-environment")) { + envlist_free(envlist); + if ((envlist = envlist_create()) == NULL) { + (void) fprintf(stderr, "Unable to allocate envlist\n"); + exit(1); + } } else if (!strcmp(r, "U")) { r = argv[optind++]; if (envlist_unsetenv(envlist, r) != 0) @@ -1364,6 +1364,7 @@ if test "$vnc_png" != "no" ; then cat > $TMPC <<EOF //#include <stdio.h> #include <png.h> +#include <stddef.h> int main(void) { png_structp png_ptr; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); @@ -1548,6 +1549,7 @@ if test "$brlapi" != "no" ; then brlapi_libs="-lbrlapi" cat > $TMPC << EOF #include <brlapi.h> +#include <stddef.h> int main( void ) { return brlapi__openConnection (NULL, NULL, NULL); } EOF if compile_prog "" "$brlapi_libs" ; then @@ -1868,6 +1870,7 @@ if test "$linux_aio" != "no" ; then cat > $TMPC <<EOF #include <libaio.h> #include <sys/eventfd.h> +#include <stddef.h> int main(void) { io_setup(0, NULL); io_set_eventfd(NULL, 0); eventfd(0, 0); return 0; } EOF if compile_prog "" "-laio" ; then @@ -2009,7 +2012,6 @@ fi utimens=no cat > $TMPC << EOF #define _ATFILE_SOURCE -#define _GNU_SOURCE #include <stddef.h> #include <fcntl.h> @@ -2027,7 +2029,6 @@ fi # check if pipe2 is there pipe2=no cat > $TMPC << EOF -#define _GNU_SOURCE #include <unistd.h> #include <fcntl.h> @@ -2045,7 +2046,6 @@ fi # check if accept4 is there accept4=no cat > $TMPC << EOF -#define _GNU_SOURCE #include <sys/socket.h> #include <stddef.h> @@ -2062,7 +2062,6 @@ fi # check if tee/splice is there. vmsplice was added same time. splice=no cat > $TMPC << EOF -#define _GNU_SOURCE #include <unistd.h> #include <fcntl.h> #include <limits.h> @@ -2229,7 +2228,7 @@ int main(void) { spice_server_new(); return 0; } EOF spice_cflags=$($pkgconfig --cflags spice-protocol spice-server 2>/dev/null) spice_libs=$($pkgconfig --libs spice-protocol spice-server 2>/dev/null) - if $pkgconfig --atleast-version=0.5.3 spice-server &&\ + if $pkgconfig --atleast-version=0.5.3 spice-server >/dev/null 2>&1 && \ compile_prog "$spice_cflags" "$spice_libs" ; then spice="yes" libs_softmmu="$libs_softmmu $spice_libs" @@ -2263,6 +2262,7 @@ madvise=no cat > $TMPC << EOF #include <sys/types.h> #include <sys/mman.h> +#include <stddef.h> int main(void) { return madvise(NULL, 0, MADV_DONTNEED); } EOF if compile_prog "" "" ; then @@ -2275,6 +2275,7 @@ fi posix_madvise=no cat > $TMPC << EOF #include <sys/mman.h> +#include <stddef.h> int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); } EOF if compile_prog "" "" ; then @@ -3239,7 +3240,7 @@ if test "$source_path_used" = "yes" ; then FILES="Makefile tests/Makefile" FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit" FILES="$FILES tests/test-mmap.c" - FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps pc-bios/video.x" + FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps" FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile" for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do FILES="$FILES pc-bios/`basename $bios_file`" diff --git a/docs/migration.txt b/docs/migration.txt index 69d53837c..4848c1e52 100644 --- a/docs/migration.txt +++ b/docs/migration.txt @@ -1,21 +1,21 @@ = Migration = QEMU has code to load/save the state of the guest that it is running. -This are two complementary operations. Saving the state just does +These are two complementary operations. Saving the state just does that, saves the state for each device that the guest is running. Restoring a guest is just the opposite operation: we need to load the state of each device. -For this to work, QEMU has to be launch with the same arguments the +For this to work, QEMU has to be launched with the same arguments the two times. I.e. it can only restore the state in one guest that has the same devices that the one it was saved (this last requirement can -be relaxed a bit, but for now we can consider that configuration have +be relaxed a bit, but for now we can consider that configuration has to be exactly the same). Once that we are able to save/restore a guest, a new functionality is requested: migration. This means that QEMU is able to start in one -machine and being "migrated" to other machine. I.e. being moved to -other machine. +machine and being "migrated" to another machine. I.e. being moved to +another machine. Next was the "live migration" functionality. This is important because some guests run with a lot of state (specially RAM), and it @@ -24,7 +24,7 @@ migration allows the guest to continue running while the state is transferred. Only while the last part of the state is transferred has the guest to be stopped. Typically the time that the guest is unresponsive during live migration is the low hundred of milliseconds -(notice that this depends on lot of things). +(notice that this depends on a lot of things). === Types of migration === @@ -35,9 +35,9 @@ to do migration: - unix migration: do the migration using unix sockets - exec migration: do the migration using the stdin/stdout through a process. - fd migration: do the migration using an file descriptor that is - passed to QEMU. QEMU don't cares how this file descriptor is opened. + passed to QEMU. QEMU doesn't care how this file descriptor is opened. -All this four migration protocols use the same infrastructure to +All these four migration protocols use the same infrastructure to save/restore state devices. This infrastructure is shared with the savevm/loadvm functionality. @@ -49,21 +49,21 @@ This is used for RAM and block devices. It is not yet ported to vmstate. === What is the common infrastructure === QEMU uses a QEMUFile abstraction to be able to do migration. Any type -of migration that what to use QEMU infrastructure has to create a +of migration that wants to use QEMU infrastructure has to create a QEMUFile with: QEMUFile *qemu_fopen_ops(void *opaque, - QEMUFilePutBufferFunc *put_buffer, + QEMUFilePutBufferFunc *put_buffer, QEMUFileGetBufferFunc *get_buffer, QEMUFileCloseFunc *close, QEMUFileRateLimit *rate_limit, QEMUFileSetRateLimit *set_rate_limit, - QEMUFileGetRateLimit *get_rate_limit); + QEMUFileGetRateLimit *get_rate_limit); The functions have the following functionality: This function writes a chunk of data to a file at the given position. -The pos argument can be ignored if the file is only being used for +The pos argument can be ignored if the file is only used for streaming. The handler should try to write all of the data it can. typedef int (QEMUFilePutBufferFunc)(void *opaque, const uint8_t *buf, @@ -76,18 +76,18 @@ bytes actually read should be returned. typedef int (QEMUFileGetBufferFunc)(void *opaque, uint8_t *buf, int64_t pos, int size); -Close a file and return an error code +Close a file and return an error code. 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); Called to change the current bandwidth allocation. This function must return the new actual bandwidth. It should be new_rate if everything goes OK, and -the old rate otherwise +the old rate otherwise. typedef size_t (QEMUFileSetRateLimit)(void *opaque, size_t new_rate); typedef size_t (QEMUFileGetRateLimit)(void *opaque); @@ -111,8 +111,8 @@ version. When we migrate a device, we save/load the state as a series of fields. Some times, due to bugs or new functionality, we need to change the state to store more/different information. We use the version to identify each time that we do a change. Each version is -associated with a series of fields saved. The save_state always save -the state as the newer version. But load_state some times is able to +associated with a series of fields saved. The save_state always saves +the state as the newer version. But load_state sometimes is able to load state from an older version. === Legacy way === @@ -135,14 +135,14 @@ typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id); The important functions for the device state format are the save_state and load_state. Notice that load_state receives a version_id -parameter to know what state format is receiving. save_state don't -have a version_id parameter because it uses always the latest version. +parameter to know what state format is receiving. save_state doesn't +have a version_id parameter because it always uses the latest version. === VMState === The legacy way of saving/loading state of the device had the problem -that we have to maintain in sync two functions. If we did one change -in one of them and not on the other, we got a failed migration. +that we have to maintain two functions in sync. If we did one change +in one of them and not in the other, we would get a failed migration. VMState changed the way that state is saved/loaded. Instead of using a function to save the state and another to load it, it was changed to @@ -173,7 +173,7 @@ We registered this with: vmstate_register(NULL, 0, &vmstate_kbd, s); -Note: talk about how vmstate <-> qdev interact, and what the instance id's mean. +Note: talk about how vmstate <-> qdev interact, and what the instance ids mean. You can search for VMSTATE_* macros for lots of types used in QEMU in hw/hw.h. @@ -182,7 +182,7 @@ hw/hw.h. You can see that there are several version fields: -- version_id: the maximum version_id supported by VMState for that device +- version_id: the maximum version_id supported by VMState for that device. - minimum_version_id: the minimum version_id that VMState is able to understand for that device. - minimum_version_id_old: For devices that were not able to port to vmstate, we can @@ -195,7 +195,7 @@ deprecated and will be removed when no more users are left. === Massaging functions === -Some times, it is not enough to be able to save the state directly +Sometimes, it is not enough to be able to save the state directly from one structure, we need to fill the correct values there. One example is when we are using kvm. Before saving the cpu state, we need to ask kvm to copy to QEMU the state that it is using. And the @@ -227,14 +227,14 @@ makes very complicated to fix bugs in stable branches. If we need to add anything to the state to fix a bug, we have to disable migration to older versions that don't have that bug-fix (i.e. a new field). -But some time, that bug-fix is only needed sometimes, not always. For +But sometimes, that bug-fix is only needed sometimes, not always. For instance, if the device is in the middle of a DMA operation, it is using a specific functionality, .... It is impossible to create a way to make migration from any version to -any other version to work. But we can do better that only allowing +any other version to work. But we can do better than only allowing migration from older versions no newer ones. For that fields that are -only needed sometimes, we add the idea of subsections. a subsection +only needed sometimes, we add the idea of subsections. A subsection is "like" a device vmstate, but with a particularity, it has a Boolean function that tells if that values are needed to be sent or not. If this functions returns false, the subsection is not sent. @@ -266,7 +266,7 @@ const VMStateDescription vmstate_ide_drive_pio_state = { .fields = (VMStateField []) { VMSTATE_INT32(req_nb_sectors, IDEState), VMSTATE_VARRAY_INT32(io_buffer, IDEState, io_buffer_total_len, 1, - vmstate_info_uint8, uint8_t), + vmstate_info_uint8, uint8_t), VMSTATE_INT32(cur_io_buffer_offset, IDEState), VMSTATE_INT32(cur_io_buffer_len, IDEState), VMSTATE_UINT8(end_transfer_fn_idx, IDEState), diff --git a/docs/tracing.txt b/docs/tracing.txt index ae01ff137..550485085 100644 --- a/docs/tracing.txt +++ b/docs/tracing.txt @@ -72,6 +72,10 @@ Trace events should use types as follows: * For everything else, use primitive scalar types (char, int, long) with the appropriate signedness. +Format strings should reflect the types defined in the trace event. Take +special care to use PRId64 and PRIu64 for int64_t and uint64_t types, +respectively. This ensures portability between 32- and 64-bit platforms. + === Hints for adding new trace events === 1. Trace state changes in the code. Interesting points in the code usually diff --git a/qemu-monitor.hx b/hmp-commands.hx index 940649695..940649695 100644 --- a/qemu-monitor.hx +++ b/hmp-commands.hx @@ -164,7 +164,7 @@ int acpi_table_add(const char *t) /* off < length is necessary because file size can be changed under our foot */ - while(s.st_size && off < length); { + while(s.st_size && off < length) { int r; r = read(fd, p + off, s.st_size); if (r > 0) { diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index efa7a42f5..a580b5783 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -281,63 +281,63 @@ static void cirrus_bitblt_fill_nop(CirrusVGAState *s, } #define ROP_NAME 0 -#define ROP_OP(d, s) d = 0 +#define ROP_FN(d, s) 0 #include "cirrus_vga_rop.h" #define ROP_NAME src_and_dst -#define ROP_OP(d, s) d = (s) & (d) +#define ROP_FN(d, s) (s) & (d) #include "cirrus_vga_rop.h" #define ROP_NAME src_and_notdst -#define ROP_OP(d, s) d = (s) & (~(d)) +#define ROP_FN(d, s) (s) & (~(d)) #include "cirrus_vga_rop.h" #define ROP_NAME notdst -#define ROP_OP(d, s) d = ~(d) +#define ROP_FN(d, s) ~(d) #include "cirrus_vga_rop.h" #define ROP_NAME src -#define ROP_OP(d, s) d = s +#define ROP_FN(d, s) s #include "cirrus_vga_rop.h" #define ROP_NAME 1 -#define ROP_OP(d, s) d = ~0 +#define ROP_FN(d, s) ~0 #include "cirrus_vga_rop.h" #define ROP_NAME notsrc_and_dst -#define ROP_OP(d, s) d = (~(s)) & (d) +#define ROP_FN(d, s) (~(s)) & (d) #include "cirrus_vga_rop.h" #define ROP_NAME src_xor_dst -#define ROP_OP(d, s) d = (s) ^ (d) +#define ROP_FN(d, s) (s) ^ (d) #include "cirrus_vga_rop.h" #define ROP_NAME src_or_dst -#define ROP_OP(d, s) d = (s) | (d) +#define ROP_FN(d, s) (s) | (d) #include "cirrus_vga_rop.h" #define ROP_NAME notsrc_or_notdst -#define ROP_OP(d, s) d = (~(s)) | (~(d)) +#define ROP_FN(d, s) (~(s)) | (~(d)) #include "cirrus_vga_rop.h" #define ROP_NAME src_notxor_dst -#define ROP_OP(d, s) d = ~((s) ^ (d)) +#define ROP_FN(d, s) ~((s) ^ (d)) #include "cirrus_vga_rop.h" #define ROP_NAME src_or_notdst -#define ROP_OP(d, s) d = (s) | (~(d)) +#define ROP_FN(d, s) (s) | (~(d)) #include "cirrus_vga_rop.h" #define ROP_NAME notsrc -#define ROP_OP(d, s) d = (~(s)) +#define ROP_FN(d, s) (~(s)) #include "cirrus_vga_rop.h" #define ROP_NAME notsrc_or_dst -#define ROP_OP(d, s) d = (~(s)) | (d) +#define ROP_FN(d, s) (~(s)) | (d) #include "cirrus_vga_rop.h" #define ROP_NAME notsrc_and_notdst -#define ROP_OP(d, s) d = (~(s)) & (~(d)) +#define ROP_FN(d, s) (~(s)) & (~(d)) #include "cirrus_vga_rop.h" static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = { diff --git a/hw/cirrus_vga_rop.h b/hw/cirrus_vga_rop.h index 39a7b7285..9c7bb0928 100644 --- a/hw/cirrus_vga_rop.h +++ b/hw/cirrus_vga_rop.h @@ -22,6 +22,26 @@ * THE SOFTWARE. */ +static inline void glue(rop_8_,ROP_NAME)(uint8_t *dst, uint8_t src) +{ + *dst = ROP_FN(*dst, src); +} + +static inline void glue(rop_16_,ROP_NAME)(uint16_t *dst, uint16_t src) +{ + *dst = ROP_FN(*dst, src); +} + +static inline void glue(rop_32_,ROP_NAME)(uint32_t *dst, uint32_t src) +{ + *dst = ROP_FN(*dst, src); +} + +#define ROP_OP(d, s) glue(rop_8_,ROP_NAME)(d, s) +#define ROP_OP_16(d, s) glue(rop_16_,ROP_NAME)(d, s) +#define ROP_OP_32(d, s) glue(rop_32_,ROP_NAME)(d, s) +#undef ROP_FN + static void glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, uint8_t *dst,const uint8_t *src, @@ -39,7 +59,7 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x++) { - ROP_OP(*dst, *src); + ROP_OP(dst, *src); dst++; src++; } @@ -59,7 +79,7 @@ glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s, srcpitch += bltwidth; for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x++) { - ROP_OP(*dst, *src); + ROP_OP(dst, *src); dst--; src--; } @@ -81,7 +101,7 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x++) { p = *dst; - ROP_OP(p, *src); + ROP_OP(&p, *src); if (p != s->vga.gr[0x34]) *dst = p; dst++; src++; @@ -104,7 +124,7 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x++) { p = *dst; - ROP_OP(p, *src); + ROP_OP(&p, *src); if (p != s->vga.gr[0x34]) *dst = p; dst--; src--; @@ -128,8 +148,8 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, for (x = 0; x < bltwidth; x+=2) { p1 = *dst; p2 = *(dst+1); - ROP_OP(p1, *src); - ROP_OP(p2, *(src+1)); + ROP_OP(&p1, *src); + ROP_OP(&p2, *(src + 1)); if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) { *dst = p1; *(dst+1) = p2; @@ -156,8 +176,8 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, for (x = 0; x < bltwidth; x+=2) { p1 = *(dst-1); p2 = *dst; - ROP_OP(p1, *(src-1)); - ROP_OP(p2, *src); + ROP_OP(&p1, *(src - 1)); + ROP_OP(&p2, *src); if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) { *(dst-1) = p1; *dst = p2; @@ -184,3 +204,5 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, #undef ROP_NAME #undef ROP_OP +#undef ROP_OP_16 +#undef ROP_OP_32 diff --git a/hw/cirrus_vga_rop2.h b/hw/cirrus_vga_rop2.h index 81a5b398e..d28bcc6f2 100644 --- a/hw/cirrus_vga_rop2.h +++ b/hw/cirrus_vga_rop2.h @@ -23,15 +23,15 @@ */ #if DEPTH == 8 -#define PUTPIXEL() ROP_OP(d[0], col) +#define PUTPIXEL() ROP_OP(&d[0], col) #elif DEPTH == 16 -#define PUTPIXEL() ROP_OP(((uint16_t *)d)[0], col); +#define PUTPIXEL() ROP_OP_16((uint16_t *)&d[0], col) #elif DEPTH == 24 -#define PUTPIXEL() ROP_OP(d[0], col); \ - ROP_OP(d[1], (col >> 8)); \ - ROP_OP(d[2], (col >> 16)) +#define PUTPIXEL() ROP_OP(&d[0], col); \ + ROP_OP(&d[1], (col >> 8)); \ + ROP_OP(&d[2], (col >> 16)) #elif DEPTH == 32 -#define PUTPIXEL() ROP_OP(((uint32_t *)d)[0], col) +#define PUTPIXEL() ROP_OP_32(((uint32_t *)&d[0]), col) #else #error unsupported DEPTH #endif diff --git a/hw/eepro100.c b/hw/eepro100.c index 5f6dcb6e6..218472df3 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -1290,7 +1290,7 @@ static void eepro100_write_port(EEPRO100State * s, uint32_t val) static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr) { - uint8_t val; + uint8_t val = 0; if (addr <= sizeof(s->mem) - sizeof(val)) { memcpy(&val, &s->mem[addr], sizeof(val)); } @@ -1333,7 +1333,7 @@ static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr) static uint16_t eepro100_read2(EEPRO100State * s, uint32_t addr) { - uint16_t val; + uint16_t val = 0; if (addr <= sizeof(s->mem) - sizeof(val)) { memcpy(&val, &s->mem[addr], sizeof(val)); } @@ -1356,7 +1356,7 @@ static uint16_t eepro100_read2(EEPRO100State * s, uint32_t addr) static uint32_t eepro100_read4(EEPRO100State * s, uint32_t addr) { - uint32_t val; + uint32_t val = 0; if (addr <= sizeof(s->mem) - sizeof(val)) { memcpy(&val, &s->mem[addr], sizeof(val)); } diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 5eaf69ed3..f97335eaa 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -864,6 +864,7 @@ static void lsi_do_msgout(LSIState *s) case 0x01: len = lsi_get_msgbyte(s); msg = lsi_get_msgbyte(s); + (void)len; /* avoid a warning about unused variable*/ DPRINTF("Extended message 0x%x (len %d)\n", msg, len); switch (msg) { case 1: diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c index df80ef6c2..f9723f559 100644 --- a/hw/mips_fulong2e.c +++ b/hw/mips_fulong2e.c @@ -265,13 +265,11 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device, qemu_irq *cpu_exit_irq; int via_devfn; PCIBus *pci_bus; - ISADevice *isa_dev; uint8_t *eeprom_buf; i2c_bus *smbus; int i; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; DeviceState *eeprom; - ISADevice *rtc_state; CPUState *env; /* init CPUs */ @@ -378,9 +376,9 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device, DMA_init(0, cpu_exit_irq); /* Super I/O */ - isa_dev = isa_create_simple("i8042"); + isa_create_simple("i8042"); - rtc_state = rtc_init(2000, NULL); + rtc_init(2000, NULL); for(i = 0; i < MAX_SERIAL_PORTS; i++) { if (serial_hds[i]) { diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 096908943..80260714e 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -784,11 +784,7 @@ void mips_malta_init (ram_addr_t ram_size, target_long bios_size; int64_t kernel_entry; PCIBus *pci_bus; - ISADevice *isa_dev; CPUState *env; - ISADevice *rtc_state; - FDCtrl *floppy_controller; - MaltaFPGAState *malta_fpga; qemu_irq *i8259; qemu_irq *cpu_exit_irq; int piix4_devfn; @@ -851,7 +847,7 @@ void mips_malta_init (ram_addr_t ram_size, be = 0; #endif /* FPGA */ - malta_fpga = malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]); + malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]); /* Load firmware in flash / BIOS unless we boot directly into a kernel. */ if (kernel_filename) { @@ -957,9 +953,9 @@ void mips_malta_init (ram_addr_t ram_size, DMA_init(0, cpu_exit_irq); /* Super I/O */ - isa_dev = isa_create_simple("i8042"); - - rtc_state = rtc_init(2000, NULL); + isa_create_simple("i8042"); + + rtc_init(2000, NULL); serial_isa_init(0, serial_hds[0]); serial_isa_init(1, serial_hds[1]); if (parallel_hds[0]) @@ -967,7 +963,7 @@ void mips_malta_init (ram_addr_t ram_size, for(i = 0; i < MAX_FD; i++) { fd[i] = drive_get(IF_FLOPPY, 0, i); } - floppy_controller = fdctrl_init_isa(fd); + fdctrl_init_isa(fd); /* Sound card */ audio_init(pci_bus); diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index ca61431ee..aa348904a 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -167,7 +167,6 @@ void mips_r4k_init (ram_addr_t ram_size, int bios_size; CPUState *env; ResetData *reset_info; - ISADevice *rtc_state; int i; qemu_irq *i8259; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; @@ -268,7 +267,7 @@ void mips_r4k_init (ram_addr_t ram_size, isa_bus_new(NULL); isa_bus_irqs(i8259); - rtc_state = rtc_init(2000, NULL); + rtc_init(2000, NULL); /* Register 64 KB of ISA IO space at 0x14000000 */ #ifdef TARGET_WORDS_BIGENDIAN @@ -685,7 +685,7 @@ static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev) } /* - * multifuction bit is interpreted in two ways as follows. + * multifunction bit is interpreted in two ways as follows. * - all functions must set the bit to 1. * Example: Intel X53 * - function 0 must set the bit, but the rest function (> 0) diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c index db8e5ecb7..c5897a9d4 100644 --- a/hw/ppc405_boards.c +++ b/hw/ppc405_boards.c @@ -501,7 +501,6 @@ static void taihu_405ep_init(ram_addr_t ram_size, const char *cpu_model) { char *filename; - CPUPPCState *env; qemu_irq *pic; ram_addr_t bios_offset; target_phys_addr_t ram_bases[2], ram_sizes[2]; @@ -521,8 +520,8 @@ static void taihu_405ep_init(ram_addr_t ram_size, #ifdef DEBUG_BOARD_INIT printf("%s: register cpu\n", __func__); #endif - env = ppc405ep_init(ram_bases, ram_sizes, 33333333, &pic, - kernel_filename == NULL ? 0 : 1); + ppc405ep_init(ram_bases, ram_sizes, 33333333, &pic, + kernel_filename == NULL ? 0 : 1); /* allocate and load BIOS */ #ifdef DEBUG_BOARD_INIT printf("%s: register BIOS\n", __func__); diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index b884ea5fb..360073741 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -630,18 +630,11 @@ struct ppc405_dma_t { static uint32_t dcr_read_dma (void *opaque, int dcrn) { - ppc405_dma_t *dma; - - dma = opaque; - return 0; } static void dcr_write_dma (void *opaque, int dcrn, uint32_t val) { - ppc405_dma_t *dma; - - dma = opaque; } static void ppc405_dma_reset (void *opaque) @@ -739,9 +732,6 @@ struct ppc405_gpio_t { static uint32_t ppc405_gpio_readb (void *opaque, target_phys_addr_t addr) { - ppc405_gpio_t *gpio; - - gpio = opaque; #ifdef DEBUG_GPIO printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); #endif @@ -752,9 +742,6 @@ static uint32_t ppc405_gpio_readb (void *opaque, target_phys_addr_t addr) static void ppc405_gpio_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) { - ppc405_gpio_t *gpio; - - gpio = opaque; #ifdef DEBUG_GPIO printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, value); @@ -763,9 +750,6 @@ static void ppc405_gpio_writeb (void *opaque, static uint32_t ppc405_gpio_readw (void *opaque, target_phys_addr_t addr) { - ppc405_gpio_t *gpio; - - gpio = opaque; #ifdef DEBUG_GPIO printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); #endif @@ -776,9 +760,6 @@ static uint32_t ppc405_gpio_readw (void *opaque, target_phys_addr_t addr) static void ppc405_gpio_writew (void *opaque, target_phys_addr_t addr, uint32_t value) { - ppc405_gpio_t *gpio; - - gpio = opaque; #ifdef DEBUG_GPIO printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, value); @@ -787,9 +768,6 @@ static void ppc405_gpio_writew (void *opaque, static uint32_t ppc405_gpio_readl (void *opaque, target_phys_addr_t addr) { - ppc405_gpio_t *gpio; - - gpio = opaque; #ifdef DEBUG_GPIO printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); #endif @@ -800,9 +778,6 @@ static uint32_t ppc405_gpio_readl (void *opaque, target_phys_addr_t addr) static void ppc405_gpio_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { - ppc405_gpio_t *gpio; - - gpio = opaque; #ifdef DEBUG_GPIO printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr, value); @@ -823,9 +798,6 @@ static CPUWriteMemoryFunc * const ppc405_gpio_write[] = { static void ppc405_gpio_reset (void *opaque) { - ppc405_gpio_t *gpio; - - gpio = opaque; } static void ppc405_gpio_init(target_phys_addr_t base) diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h index 89f96bbc3..ea8759324 100644 --- a/hw/ppc_mac.h +++ b/hw/ppc_mac.h @@ -30,7 +30,6 @@ #define BIOS_SIZE (1024 * 1024) #define BIOS_FILENAME "ppc_rom.bin" -#define VGABIOS_FILENAME "video.x" #define NVRAM_SIZE 0x2000 #define PROM_FILENAME "openbios-ppc" #define PROM_ADDR 0xfff00000 diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index fb07c8316..4369337b2 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -69,7 +69,6 @@ #include "blockdev.h" #define MAX_IDE_BUS 2 -#define VGA_BIOS_SIZE 65536 #define CFG_ADDR 0xf0000510 /* debug UniNorth */ @@ -129,25 +128,24 @@ static void ppc_core99_init (ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model) { - CPUState *env = NULL, *envs[MAX_CPUS]; + CPUState *env = NULL; char *filename; qemu_irq *pic, **openpic_irqs; int unin_memory; int linux_boot, i; - ram_addr_t ram_offset, bios_offset, vga_bios_offset; + ram_addr_t ram_offset, bios_offset; uint32_t kernel_base, initrd_base; long kernel_size, initrd_size; PCIBus *pci_bus; MacIONVRAMState *nvr; int nvram_mem_index; - int vga_bios_size, bios_size; + int bios_size; int pic_mem_index, dbdma_mem_index, cuda_mem_index, escc_mem_index; int ide_mem_index[3]; int ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; void *dbdma; - uint8_t *vga_bios_ptr; int machine_arch; linux_boot = (kernel_filename != NULL); @@ -167,11 +165,7 @@ static void ppc_core99_init (ram_addr_t ram_size, } /* Set time-base frequency to 100 Mhz */ cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL); -#if 0 - env->osi_call = vga_osi_call; -#endif qemu_register_reset((QEMUResetHandler*)&cpu_reset, env); - envs[i] = env; } /* allocate RAM */ @@ -199,36 +193,6 @@ static void ppc_core99_init (ram_addr_t ram_size, exit(1); } - /* allocate and load VGA BIOS */ - vga_bios_offset = qemu_ram_alloc(NULL, "ppc_core99.vbios", VGA_BIOS_SIZE); - vga_bios_ptr = qemu_get_ram_ptr(vga_bios_offset); - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, VGABIOS_FILENAME); - if (filename) { - vga_bios_size = load_image(filename, vga_bios_ptr + 8); - qemu_free(filename); - } else { - vga_bios_size = -1; - } - if (vga_bios_size < 0) { - /* if no bios is present, we can still work */ - fprintf(stderr, "qemu: warning: could not load VGA bios '%s'\n", - VGABIOS_FILENAME); - vga_bios_size = 0; - } else { - /* set a specific header (XXX: find real Apple format for NDRV - drivers) */ - vga_bios_ptr[0] = 'N'; - vga_bios_ptr[1] = 'D'; - vga_bios_ptr[2] = 'R'; - vga_bios_ptr[3] = 'V'; - cpu_to_be32w((uint32_t *)(vga_bios_ptr + 4), vga_bios_size); - vga_bios_size += 8; - - /* Round to page boundary */ - vga_bios_size = (vga_bios_size + TARGET_PAGE_SIZE - 1) & - TARGET_PAGE_MASK; - } - if (linux_boot) { uint64_t lowaddr = 0; int bswap_needed; @@ -352,7 +316,7 @@ static void ppc_core99_init (ram_addr_t ram_size, machine_arch = ARCH_MAC99; } /* init basic PC hardware */ - pci_vga_init(pci_bus, vga_bios_offset, vga_bios_size); + pci_vga_init(pci_bus, 0, 0); escc_mem_index = escc_init(0x80013000, pic[0x25], pic[0x24], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index a12a81297..a2f9ddf73 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -1,3 +1,4 @@ + /* * QEMU OldWorld PowerMac (currently ~G3 Beige) hardware System Emulator * @@ -44,79 +45,8 @@ #include "blockdev.h" #define MAX_IDE_BUS 2 -#define VGA_BIOS_SIZE 65536 #define CFG_ADDR 0xf0000510 -/* temporary frame buffer OSI calls for the video.x driver. The right - solution is to modify the driver to use VGA PCI I/Os */ -/* XXX: to be removed. This is no way related to emulation */ -static int vga_osi_call (CPUState *env) -{ - static int vga_vbl_enabled; - int linesize; - -#if 0 - printf("osi_call R5=%016" PRIx64 "\n", ppc_dump_gpr(env, 5)); -#endif - - /* same handler as PearPC, coming from the original MOL video - driver. */ - switch(env->gpr[5]) { - case 4: - break; - case 28: /* set_vmode */ - if (env->gpr[6] != 1 || env->gpr[7] != 0) - env->gpr[3] = 1; - else - env->gpr[3] = 0; - break; - case 29: /* get_vmode_info */ - if (env->gpr[6] != 0) { - if (env->gpr[6] != 1 || env->gpr[7] != 0) { - env->gpr[3] = 1; - break; - } - } - env->gpr[3] = 0; - env->gpr[4] = (1 << 16) | 1; /* num_vmodes, cur_vmode */ - env->gpr[5] = (1 << 16) | 0; /* num_depths, cur_depth_mode */ - env->gpr[6] = (graphic_width << 16) | graphic_height; /* w, h */ - env->gpr[7] = 85 << 16; /* refresh rate */ - env->gpr[8] = (graphic_depth + 7) & ~7; /* depth (round to byte) */ - linesize = ((graphic_depth + 7) >> 3) * graphic_width; - linesize = (linesize + 3) & ~3; - env->gpr[9] = (linesize << 16) | 0; /* row_bytes, offset */ - break; - case 31: /* set_video power */ - env->gpr[3] = 0; - break; - case 39: /* video_ctrl */ - if (env->gpr[6] == 0 || env->gpr[6] == 1) - vga_vbl_enabled = env->gpr[6]; - env->gpr[3] = 0; - break; - case 47: - break; - case 59: /* set_color */ - /* R6 = index, R7 = RGB */ - env->gpr[3] = 0; - break; - case 64: /* get color */ - /* R6 = index */ - env->gpr[3] = 0; - break; - case 116: /* set hwcursor */ - /* R6 = x, R7 = y, R8 = visible, R9 = data */ - break; - default: - fprintf(stderr, "unsupported OSI call R5=%016" PRIx64 "\n", - ppc_dump_gpr(env, 5)); - break; - } - - return 1; /* osi_call handled */ -} - static int fw_cfg_boot_set(void *opaque, const char *boot_device) { fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); @@ -136,23 +66,22 @@ static void ppc_heathrow_init (ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model) { - CPUState *env = NULL, *envs[MAX_CPUS]; + CPUState *env = NULL; char *filename; qemu_irq *pic, **heathrow_irqs; int linux_boot, i; - ram_addr_t ram_offset, bios_offset, vga_bios_offset; + ram_addr_t ram_offset, bios_offset; uint32_t kernel_base, initrd_base; int32_t kernel_size, initrd_size; PCIBus *pci_bus; MacIONVRAMState *nvr; - int vga_bios_size, bios_size; + int bios_size; int pic_mem_index, nvram_mem_index, dbdma_mem_index, cuda_mem_index; int escc_mem_index, ide_mem_index[2]; uint16_t ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; void *dbdma; - uint8_t *vga_bios_ptr; linux_boot = (kernel_filename != NULL); @@ -167,9 +96,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, } /* Set time-base frequency to 16.6 Mhz */ cpu_ppc_tb_init(env, 16600000UL); - env->osi_call = vga_osi_call; qemu_register_reset((QEMUResetHandler*)&cpu_reset, env); - envs[i] = env; } /* allocate RAM */ @@ -203,36 +130,6 @@ static void ppc_heathrow_init (ram_addr_t ram_size, exit(1); } - /* allocate and load VGA BIOS */ - vga_bios_offset = qemu_ram_alloc(NULL, "ppc_heathrow.vbios", VGA_BIOS_SIZE); - vga_bios_ptr = qemu_get_ram_ptr(vga_bios_offset); - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, VGABIOS_FILENAME); - if (filename) { - vga_bios_size = load_image(filename, vga_bios_ptr + 8); - qemu_free(filename); - } else { - vga_bios_size = -1; - } - if (vga_bios_size < 0) { - /* if no bios is present, we can still work */ - fprintf(stderr, "qemu: warning: could not load VGA bios '%s'\n", - VGABIOS_FILENAME); - vga_bios_size = 0; - } else { - /* set a specific header (XXX: find real Apple format for NDRV - drivers) */ - vga_bios_ptr[0] = 'N'; - vga_bios_ptr[1] = 'D'; - vga_bios_ptr[2] = 'R'; - vga_bios_ptr[3] = 'V'; - cpu_to_be32w((uint32_t *)(vga_bios_ptr + 4), vga_bios_size); - vga_bios_size += 8; - - /* Round to page boundary */ - vga_bios_size = (vga_bios_size + TARGET_PAGE_SIZE - 1) & - TARGET_PAGE_MASK; - } - if (linux_boot) { uint64_t lowaddr = 0; int bswap_needed; @@ -330,7 +227,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, } pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs); pci_bus = pci_grackle_init(0xfec00000, pic); - pci_vga_init(pci_bus, vga_bios_offset, vga_bios_size); + pci_vga_init(pci_bus, 0, 0); escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index 0e5b88ce7..a6915f7e6 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -565,7 +565,7 @@ static void ppc_prep_init (ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model) { - CPUState *env = NULL, *envs[MAX_CPUS]; + CPUState *env = NULL; char *filename; nvram_t nvram; M48t59State *m48t59; @@ -602,7 +602,6 @@ static void ppc_prep_init (ram_addr_t ram_size, cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL); } qemu_register_reset((QEMUResetHandler*)&cpu_reset, env); - envs[i] = env; } /* allocate RAM */ diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 4eb9bec00..f40a076b8 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -177,7 +177,6 @@ static void mpc8544ds_init(ram_addr_t ram_size, int i=0; unsigned int pci_irq_nrs[4] = {1, 2, 3, 4}; qemu_irq *irqs, *mpic, *pci_irqs; - SerialState * serial[2]; /* Setup CPU */ env = cpu_ppc_init("e500v2_v30"); @@ -201,15 +200,15 @@ static void mpc8544ds_init(ram_addr_t ram_size, /* Serial */ if (serial_hds[0]) { - serial[0] = serial_mm_init(MPC8544_SERIAL0_REGS_BASE, - 0, mpic[12+26], 399193, - serial_hds[0], 1, 1); + serial_mm_init(MPC8544_SERIAL0_REGS_BASE, + 0, mpic[12+26], 399193, + serial_hds[0], 1, 1); } if (serial_hds[1]) { - serial[0] = serial_mm_init(MPC8544_SERIAL1_REGS_BASE, - 0, mpic[12+26], 399193, - serial_hds[0], 1, 1); + serial_mm_init(MPC8544_SERIAL1_REGS_BASE, + 0, mpic[12+26], 399193, + serial_hds[0], 1, 1); } /* PCI */ diff --git a/hw/tc6393xb_template.h b/hw/tc6393xb_template.h index 37bf8336b..1ccf6e8df 100644 --- a/hw/tc6393xb_template.h +++ b/hw/tc6393xb_template.h @@ -38,12 +38,10 @@ static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s) { int i; - int w_display; uint16_t *data_buffer; uint8_t *data_display; data_buffer = s->vram_ptr; - w_display = s->scr_width * BITS / 8; data_display = ds_get_data(s->ds); for(i = 0; i < s->scr_height; i++) { #if (BITS == 16) diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c index c5bbedac7..fa605158e 100644 --- a/hw/virtex_ml507.c +++ b/hw/virtex_ml507.c @@ -85,7 +85,6 @@ static CPUState *ppc440_init_xilinx(ram_addr_t *ram_size, uint32_t sysclk) { CPUState *env; - qemu_irq *pic; qemu_irq *irqs; env = cpu_init(cpu_model); @@ -106,7 +105,7 @@ static CPUState *ppc440_init_xilinx(ram_addr_t *ram_size, irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB); irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT]; irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT]; - pic = ppcuic_init(env, irqs, 0x0C0, 0, 1); + ppcuic_init(env, irqs, 0x0C0, 0, 1); return env; } @@ -236,13 +235,11 @@ static void virtex_init(ram_addr_t ram_size, if (kernel_filename) { uint64_t entry, low, high; - uint32_t base32; target_phys_addr_t boot_offset; /* Boots a kernel elf binary. */ kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, &low, &high, 1, ELF_MACHINE, 0); - base32 = entry; boot_info.bootstrap_pc = entry & 0x00ffffff; if (kernel_size < 0) { diff --git a/hw/wm8750.c b/hw/wm8750.c index ce43c234a..c9c674451 100644 --- a/hw/wm8750.c +++ b/hw/wm8750.c @@ -171,7 +171,6 @@ static void wm8750_set_format(WM8750State *s) int i; struct audsettings in_fmt; struct audsettings out_fmt; - struct audsettings monoout_fmt; wm8750_out_flush(s); @@ -212,10 +211,6 @@ static void wm8750_set_format(WM8750State *s) out_fmt.nchannels = 2; out_fmt.freq = s->dac_hz; out_fmt.fmt = AUD_FMT_S16; - monoout_fmt.endianness = 0; - monoout_fmt.nchannels = 1; - monoout_fmt.freq = s->rate->dac_hz; - monoout_fmt.fmt = AUD_FMT_S16; s->dac_voice[0] = AUD_open_out(&s->card, s->dac_voice[0], CODEC ".speaker", s, wm8750_audio_out_cb, &out_fmt); diff --git a/linux-user/m68k-sim.c b/linux-user/m68k-sim.c index 64d3b23d6..d5926eec4 100644 --- a/linux-user/m68k-sim.c +++ b/linux-user/m68k-sim.c @@ -38,7 +38,7 @@ #define SYS_ISATTY 29 #define SYS_LSEEK 199 -struct m86k_sim_stat { +struct m68k_sim_stat { uint16_t sim_st_dev; uint16_t sim_st_ino; uint32_t sim_st_mode; @@ -138,10 +138,10 @@ void do_m68k_simcall(CPUM68KState *env, int nr) { struct stat s; int rc; - struct m86k_sim_stat *p; + struct m68k_sim_stat *p; rc = check_err(env, fstat(ARG(0), &s)); if (rc == 0) { - p = (struct m86k_sim_stat *)(unsigned long)ARG(1); + p = (struct m68k_sim_stat *)(unsigned long)ARG(1); p->sim_st_dev = tswap16(s.st_dev); p->sim_st_ino = tswap16(s.st_ino); p->sim_st_mode = tswap32(s.st_mode); diff --git a/linux-user/main.c b/linux-user/main.c index 69d050f91..dbba8befe 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2790,6 +2790,12 @@ int main(int argc, char **argv, char **envp) r = argv[optind++]; if (envlist_setenv(envlist, r) != 0) usage(); + } else if (!strcmp(r, "ignore-environment")) { + envlist_free(envlist); + if ((envlist = envlist_create()) == NULL) { + (void) fprintf(stderr, "Unable to allocate envlist\n"); + exit(1); + } } else if (!strcmp(r, "U")) { r = argv[optind++]; if (envlist_unsetenv(envlist, r) != 0) @@ -332,21 +332,16 @@ static int GCC_FMT_ATTR(2, 3) monitor_fprintf(FILE *stream, static void monitor_user_noop(Monitor *mon, const QObject *data) { } -static inline int monitor_handler_ported(const mon_cmd_t *cmd) +static inline int handler_is_qobject(const mon_cmd_t *cmd) { return cmd->user_print != NULL; } -static inline bool monitor_handler_is_async(const mon_cmd_t *cmd) +static inline bool handler_is_async(const mon_cmd_t *cmd) { return cmd->flags & MONITOR_CMD_ASYNC; } -static inline bool monitor_cmd_user_only(const mon_cmd_t *cmd) -{ - return (cmd->flags & MONITOR_CMD_USER_ONLY); -} - static inline int monitor_has_error(const Monitor *mon) { return mon->error != NULL; @@ -555,7 +550,11 @@ static void do_change_trace_event_state(Monitor *mon, const QDict *qdict) { const char *tp_name = qdict_get_str(qdict, "name"); bool new_state = qdict_get_bool(qdict, "option"); - st_change_trace_event_state(tp_name, new_state); + int ret = st_change_trace_event_state(tp_name, new_state); + + if (!ret) { + monitor_printf(mon, "unknown event name \"%s\"\n", tp_name); + } } static void do_trace_file(Monitor *mon, const QDict *qdict) @@ -659,9 +658,9 @@ static void do_info(Monitor *mon, const QDict *qdict) goto help; } - if (monitor_handler_is_async(cmd)) { + if (handler_is_async(cmd)) { user_async_info_handler(mon, cmd); - } else if (monitor_handler_ported(cmd)) { + } else if (handler_is_qobject(cmd)) { QObject *info_data = NULL; cmd->mhandler.info_new(mon, &info_data); @@ -2367,11 +2366,11 @@ int monitor_get_fd(Monitor *mon, const char *fdname) } static const mon_cmd_t mon_cmds[] = { -#include "qemu-monitor.h" +#include "hmp-commands.h" { NULL, NULL, }, }; -/* Please update qemu-monitor.hx when adding or changing commands */ +/* Please update hmp-commands.hx when adding or changing commands */ static const mon_cmd_t info_cmds[] = { { .name = "version", @@ -3915,29 +3914,6 @@ static void handler_audit(Monitor *mon, const mon_cmd_t *cmd, int ret) } } -static void monitor_call_handler(Monitor *mon, const mon_cmd_t *cmd, - const QDict *params) -{ - int ret; - QObject *data = NULL; - - mon_print_count_init(mon); - - ret = cmd->mhandler.cmd_new(mon, params, &data); - handler_audit(mon, cmd, ret); - - if (monitor_ctrl_mode(mon)) { - /* Monitor Protocol */ - monitor_protocol_emitter(mon, data); - } else { - /* User Protocol */ - if (data) - cmd->user_print(mon, data); - } - - qobject_decref(data); -} - static void handle_user_command(Monitor *mon, const char *cmdline) { QDict *qdict; @@ -3949,10 +3925,18 @@ static void handle_user_command(Monitor *mon, const char *cmdline) if (!cmd) goto out; - if (monitor_handler_is_async(cmd)) { + if (handler_is_async(cmd)) { user_async_cmd_handler(mon, cmd, qdict); - } else if (monitor_handler_ported(cmd)) { - monitor_call_handler(mon, cmd, qdict); + } else if (handler_is_qobject(cmd)) { + QObject *data = NULL; + + /* XXX: ignores the error code */ + cmd->mhandler.cmd_new(mon, qdict, &data); + assert(!monitor_has_error(mon)); + if (data) { + cmd->user_print(mon, data); + qobject_decref(data); + } } else { cmd->mhandler.cmd(mon, qdict); } @@ -4446,7 +4430,7 @@ static void qmp_call_query_cmd(Monitor *mon, const mon_cmd_t *cmd) { QObject *ret_data = NULL; - if (monitor_handler_is_async(cmd)) { + if (handler_is_async(cmd)) { qmp_async_info_handler(mon, cmd); if (monitor_has_error(mon)) { monitor_protocol_emitter(mon, NULL); @@ -4460,6 +4444,20 @@ static void qmp_call_query_cmd(Monitor *mon, const mon_cmd_t *cmd) } } +static void qmp_call_cmd(Monitor *mon, const mon_cmd_t *cmd, + const QDict *params) +{ + int ret; + QObject *data = NULL; + + mon_print_count_init(mon); + + ret = cmd->mhandler.cmd_new(mon, params, &data); + handler_audit(mon, cmd, ret); + monitor_protocol_emitter(mon, data); + qobject_decref(data); +} + static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) { int err; @@ -4520,14 +4518,14 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) if (query_cmd) { qmp_call_query_cmd(mon, cmd); - } else if (monitor_handler_is_async(cmd)) { + } else if (handler_is_async(cmd)) { err = qmp_async_cmd_handler(mon, cmd, args); if (err) { /* emit the error response */ goto err_out; } } else { - monitor_call_handler(mon, cmd, args); + qmp_call_cmd(mon, cmd, args); } goto out; @@ -18,7 +18,6 @@ extern Monitor *default_mon; /* flags for monitor commands */ #define MONITOR_CMD_ASYNC 0x0001 -#define MONITOR_CMD_USER_ONLY 0x0002 /* QMP events */ typedef enum MonitorEvent { diff --git a/net/tap-win32.c b/net/tap-win32.c index 9fe4fcd5f..081904e8d 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -579,7 +579,6 @@ static int tap_win32_open(tap_win32_overlapped_t **phandle, } version; DWORD version_len; DWORD idThread; - HANDLE hThread; if (prefered_name != NULL) snprintf(name_buffer, sizeof(name_buffer), "%s", prefered_name); @@ -623,8 +622,8 @@ static int tap_win32_open(tap_win32_overlapped_t **phandle, *phandle = &tap_overlapped; - hThread = CreateThread(NULL, 0, tap_win32_thread_entry, - (LPVOID)&tap_overlapped, 0, &idThread); + CreateThread(NULL, 0, tap_win32_thread_entry, + (LPVOID)&tap_overlapped, 0, &idThread); return 0; } diff --git a/os-win32.c b/os-win32.c index dd46bf459..3c6f50fa9 100644 --- a/os-win32.c +++ b/os-win32.c @@ -221,6 +221,12 @@ char *os_find_datadir(const char *argv0) return NULL; } +void os_set_line_buffering(void) +{ + setbuf(stdout, NULL); + setbuf(stderr, NULL); +} + /* * Parse OS specific command line options. * return 0 if option handled, -1 otherwise diff --git a/pc-bios/README b/pc-bios/README index ec5e2e1c8..3172cf789 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -7,10 +7,6 @@ - The PowerPC Open Hack'Ware Open Firmware Compatible BIOS is available at http://perso.magic.fr/l_indien/OpenHackWare/index.htm. -- video.x is a PowerMac NDRV compatible driver for a VGA frame - buffer. It comes from the Mac-on-Linux project - (http://www.maconlinux.org/). - - OpenBIOS (http://www.openbios.org/) is a free (GPL v2) portable firmware implementation. The goal is to implement a 100% IEEE 1275-1994 (referred to as Open Firmware) compliant firmware. diff --git a/pc-bios/video.x b/pc-bios/video.x Binary files differdeleted file mode 100644 index 761aa0c9d..000000000 --- a/pc-bios/video.x +++ /dev/null diff --git a/posix-aio-compat.c b/posix-aio-compat.c index 09306ddaf..3025c0b28 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -129,7 +129,7 @@ static ssize_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb) /* * This looks weird, but the aio code only consideres a request - * successfull if it has written the number full number of bytes. + * successful if it has written the number full number of bytes. * * Now we overload aio_nbytes as aio_ioctl_cmd for the ioctl command, * so in fact we return the ioctl command here to make posix_aio_read() diff --git a/qemu-config.c b/qemu-config.c index e8e3b2266..69aeb1799 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -358,6 +358,24 @@ static QemuOptsList qemu_cpudef_opts = { }, }; +QemuOptsList qemu_spice_opts = { + .name = "spice", + .head = QTAILQ_HEAD_INITIALIZER(qemu_spice_opts.head), + .desc = { + { + .name = "port", + .type = QEMU_OPT_NUMBER, + },{ + .name = "password", + .type = QEMU_OPT_STRING, + },{ + .name = "disable-ticketing", + .type = QEMU_OPT_BOOL, + }, + { /* end if list */ } + }, +}; + static QemuOptsList *vm_config_groups[32] = { &qemu_drive_opts, &qemu_chardev_opts, diff --git a/qemu-config.h b/qemu-config.h index 533a04927..20d707fa1 100644 --- a/qemu-config.h +++ b/qemu-config.h @@ -3,6 +3,7 @@ extern QemuOptsList qemu_fsdev_opts; extern QemuOptsList qemu_virtfs_opts; +extern QemuOptsList qemu_spice_opts; QemuOptsList *qemu_find_opts(const char *group); void qemu_add_opts(QemuOptsList *list); diff --git a/qemu-doc.texi b/qemu-doc.texi index d7d760fed..c3765293d 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -2186,6 +2186,13 @@ Set the x86 elf interpreter prefix (default=/usr/local/qemu-i386) Set the x86 stack size in bytes (default=524288) @item -cpu model Select CPU model (-cpu ? for list and additional feature selection) +@item -ignore-environment +Start with an empty environment. Without this option, +the inital environment is a copy of the caller's environment. +@item -E @var{var}=@var{value} +Set environment @var{var} to @var{value}. +@item -U @var{var} +Remove @var{var} from the environment. @item -B offset Offset guest address by the specified number of bytes. This is useful when the address region required by guest applications is reserved on the host. @@ -2409,6 +2416,13 @@ Print the help Set the library root path (default=/) @item -s size Set the stack size in bytes (default=524288) +@item -ignore-environment +Start with an empty environment. Without this option, +the inital environment is a copy of the caller's environment. +@item -E @var{var}=@var{value} +Set environment @var{var} to @var{value}. +@item -U @var{var} +Remove @var{var} from the environment. @item -bsd type Set the type of the emulated BSD Operating system. Valid values are FreeBSD, NetBSD and OpenBSD (default). diff --git a/qemu-options.hx b/qemu-options.hx index 5e5676a04..1c9a1e575 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -672,6 +672,27 @@ STEXI Enable SDL. ETEXI +DEF("spice", HAS_ARG, QEMU_OPTION_spice, + "-spice <args> enable spice\n", QEMU_ARCH_ALL) +STEXI +@item -spice @var{option}[,@var{option}[,...]] +@findex -spice +Enable the spice remote desktop protocol. Valid options are + +@table @option + +@item port=<nr> +Set the TCP port spice is listening on. + +@item password=<secret> +Set the password you need to authenticate. + +@item disable-ticketing +Allow client connects without authentication. + +@end table +ETEXI + DEF("portrait", 0, QEMU_OPTION_portrait, "-portrait rotate graphical output 90 deg left (only PXA LCD)\n", QEMU_ARCH_ALL) diff --git a/qemu-os-win32.h b/qemu-os-win32.h index 2ff9f45a6..c63778d2f 100644 --- a/qemu-os-win32.h +++ b/qemu-os-win32.h @@ -45,8 +45,7 @@ void os_host_main_loop_wait(int *timeout); static inline void os_setup_signal_handling(void) {} static inline void os_daemonize(void) {} static inline void os_setup_post(void) {} -/* Win32 doesn't support line-buffering and requires size >= 2 */ -static inline void os_set_line_buffering(void) {} +void os_set_line_buffering(void); static inline void os_set_proc_name(const char *dummy) {} #if !defined(EPROTONOSUPPORT) @@ -1638,10 +1638,10 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, while (qemu_peek_byte(f) == QEMU_VM_SUBSECTION) { char idstr[256]; int ret; - uint8_t version_id, subsection, len; + uint8_t version_id, len; const VMStateDescription *sub_vmsd; - subsection = qemu_get_byte(f); + qemu_get_byte(f); /* subsection */ len = qemu_get_byte(f); qemu_get_buffer(f, (uint8_t *)idstr, len); idstr[len] = 0; diff --git a/simpletrace.c b/simpletrace.c index f849e4291..deb1e0742 100644 --- a/simpletrace.c +++ b/simpletrace.c @@ -246,12 +246,14 @@ static TraceEvent* find_trace_event_by_name(const char *tname) return NULL; /* indicates end of list reached without a match */ } -void st_change_trace_event_state(const char *tname, bool tstate) +bool st_change_trace_event_state(const char *tname, bool tstate) { TraceEvent *tp; tp = find_trace_event_by_name(tname); if (tp) { tp->state = tstate; + return true; } + return false; } diff --git a/simpletrace.h b/simpletrace.h index cf3589774..72614ec1d 100644 --- a/simpletrace.h +++ b/simpletrace.h @@ -31,7 +31,7 @@ void trace5(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t void trace6(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6); void st_print_trace(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)); void st_print_trace_events(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)); -void st_change_trace_event_state(const char *tname, bool tstate); +bool st_change_trace_event_state(const char *tname, bool tstate); void st_print_trace_file_status(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...)); void st_set_trace_file_enabled(bool enable); bool st_set_trace_file(const char *file); diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index a60da94f3..be9eb06fd 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -164,7 +164,9 @@ void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg) D_LOG("tlb flush vaddr=%x v=%d pc=%x\n", vaddr, tlb_v, env->pc); - tlb_flush_page(env, vaddr); + if (tlb_v) { + tlb_flush_page(env, vaddr); + } } } #endif diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c index 14e590da3..6944827a5 100644 --- a/target-cris/translate_v10.c +++ b/target-cris/translate_v10.c @@ -108,16 +108,15 @@ static unsigned int crisv10_post_memaddr(DisasContext *dc, unsigned int size) static int dec10_prep_move_m(DisasContext *dc, int s_ext, int memsize, TCGv dst) { - unsigned int rs, rd; + unsigned int rs; uint32_t imm; int is_imm; int insn_len = 0; rs = dc->src; - rd = dc->dst; is_imm = rs == 15 && !(dc->tb_flags & PFIX_FLAG); LOG_DIS("rs=%d rd=%d is_imm=%d mode=%d pfix=%d\n", - rs, rd, is_imm, dc->mode, dc->tb_flags & PFIX_FLAG); + rs, dc->dst, is_imm, dc->mode, dc->tb_flags & PFIX_FLAG); /* Load [$rs] onto T1. */ if (is_imm) { diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c index ec6b3e938..43fbd0c77 100644 --- a/target-i386/op_helper.c +++ b/target-i386/op_helper.c @@ -349,6 +349,10 @@ static void switch_tss(int tss_selector, new_segs[R_GS] = 0; new_trap = 0; } + /* XXX: avoid a compiler warning, see + http://support.amd.com/us/Processor_TechDocs/24593.pdf + chapters 12.2.5 and 13.2.4 on how to implement TSS Trap bit */ + (void)new_trap; /* NOTE: we must avoid memory exceptions during the task switch, so we make dummy accesses before */ diff --git a/target-mips/translate.c b/target-mips/translate.c index 20b66a8a5..d62c6158f 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1153,6 +1153,7 @@ static void gen_ld (CPUState *env, DisasContext *ctx, uint32_t opc, opn = "ll"; break; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); tcg_temp_free(t0); tcg_temp_free(t1); @@ -1212,6 +1213,7 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt, opn = "swr"; break; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); tcg_temp_free(t0); tcg_temp_free(t1); @@ -1247,6 +1249,7 @@ static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt, opn = "sc"; break; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); tcg_temp_free(t1); tcg_temp_free(t0); @@ -1312,6 +1315,7 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, generate_exception(ctx, EXCP_RI); goto out; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]); out: tcg_temp_free(t0); @@ -1412,6 +1416,7 @@ static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc, break; #endif } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm); } @@ -1454,6 +1459,7 @@ static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t opn = "lui"; break; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm); } @@ -1481,6 +1487,7 @@ static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t im opn = "sltiu"; break; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm); tcg_temp_free(t0); } @@ -1572,6 +1579,7 @@ static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc, break; #endif } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm); tcg_temp_free(t0); } @@ -1752,6 +1760,7 @@ static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc, opn = "mul"; break; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); } @@ -1789,6 +1798,7 @@ static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt) tcg_gen_movi_tl(cpu_gpr[rd], 0); gen_set_label(l1); + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); } @@ -1849,6 +1859,7 @@ static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt) opn = "xor"; break; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); } @@ -1878,6 +1889,7 @@ static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt) opn = "sltu"; break; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); tcg_temp_free(t0); tcg_temp_free(t1); @@ -1958,6 +1970,7 @@ static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc, break; #endif } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); tcg_temp_free(t0); tcg_temp_free(t1); @@ -1997,6 +2010,7 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg) opn = "mtlo"; break; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s", opn, regnames[reg]); } @@ -2229,6 +2243,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, generate_exception(ctx, EXCP_RI); goto out; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]); out: tcg_temp_free(t0); @@ -2308,6 +2323,7 @@ static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc, goto out; } gen_store_gpr(t0, rd); + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]); out: @@ -2348,6 +2364,7 @@ static void gen_cl (DisasContext *ctx, uint32_t opc, break; #endif } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]); tcg_temp_free(t0); } @@ -2561,6 +2578,7 @@ static void gen_loongson_integer (DisasContext *ctx, uint32_t opc, #endif } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]); tcg_temp_free(t0); tcg_temp_free(t1); @@ -3730,6 +3748,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s default: goto die; } + (void)rn; /* avoid a compiler warning */ LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel); return; @@ -4320,6 +4339,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s default: goto die; } + (void)rn; /* avoid a compiler warning */ LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel); /* For simplicity assume that all writes can cause interrupts. */ if (use_icount) { @@ -4892,6 +4912,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int default: goto die; } + (void)rn; /* avoid a compiler warning */ LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel); return; @@ -5483,6 +5504,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int default: goto die; } + (void)rn; /* avoid a compiler warning */ LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel); /* For simplicity assume that all writes can cause interrupts. */ if (use_icount) { @@ -5943,6 +5965,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int generate_exception(ctx, EXCP_RI); return; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd); } #endif /* !CONFIG_USER_ONLY */ @@ -6052,6 +6075,7 @@ static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op, generate_exception (ctx, EXCP_RI); goto out; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn, ctx->hflags, btarget); ctx->btarget = btarget; @@ -6281,6 +6305,7 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) generate_exception (ctx, EXCP_RI); goto out; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]); out: @@ -7608,6 +7633,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, generate_exception (ctx, EXCP_RI); return; } + (void)opn; /* avoid a compiler warning */ switch (optype) { case BINOP: MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]); @@ -7720,6 +7746,7 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, break; } tcg_temp_free(t0); + (void)opn; (void)store; /* avoid compiler warnings */ MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd], regnames[index], regnames[base]); } @@ -7993,6 +8020,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, generate_exception (ctx, EXCP_RI); return; } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr], fregnames[fs], fregnames[ft]); } @@ -9971,6 +9999,7 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, break; #endif } + (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]); tcg_temp_free(t0); tcg_temp_free(t1); diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 959f733e6..55c23b9db 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -701,9 +701,6 @@ struct CPUPPCState { int power_mode; int (*check_pow)(CPUPPCState *env); - /* temporary hack to handle OSI calls (only used if non NULL) */ - int (*osi_call)(struct CPUPPCState *env); - #if !defined(CONFIG_USER_ONLY) void *load_info; /* Holds boot loading state. */ #endif diff --git a/target-ppc/helper.c b/target-ppc/helper.c index e0299348f..23e318919 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -1173,9 +1173,7 @@ static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx, case 0x1: check_perms: /* Check from TLB entry */ - /* XXX: there is a problem here or in the TLB fill code... */ ctx->prot = tlb->prot; - ctx->prot |= PAGE_EXEC; ret = check_prot(ctx->prot, rw, access_type); if (ret == -2) env->spr[SPR_40x_ESR] = 0; @@ -2229,17 +2227,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) new_msr |= (target_ulong)MSR_HVB; goto store_current; case POWERPC_EXCP_SYSCALL: /* System call exception */ - /* NOTE: this is a temporary hack to support graphics OSI - calls from the MOL driver */ - /* XXX: To be removed */ - if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b && - env->osi_call) { - if (env->osi_call(env) != 0) { - env->exception_index = POWERPC_EXCP_NONE; - env->error_code = 0; - return; - } - } dump_syscall(env); lev = env->error_code; if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 3e6db85f1..f32a5fffd 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -348,15 +348,13 @@ void helper_dcbz_970(target_ulong addr) void helper_icbi(target_ulong addr) { - uint32_t tmp; - addr &= ~(env->dcache_line_size - 1); /* Invalidate one cache line : * PowerPC specification says this is to be treated like a load * (not a fetch) by the MMU. To be sure it will be so, * do the load "by hand". */ - tmp = ldl(addr); + ldl(addr); tb_invalidate_page_range(addr, addr + env->icache_line_size); } @@ -3814,6 +3812,7 @@ static void do_6xx_tlb (target_ulong new_EPN, int is_code) EPN = env->spr[SPR_DMISS]; } way = (env->spr[SPR_SRR1] >> 17) & 1; + (void)EPN; /* avoid a compiler warning */ LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP, RPN, way); @@ -3842,6 +3841,7 @@ static void do_74xx_tlb (target_ulong new_EPN, int is_code) CMP = env->spr[SPR_PTEHI]; EPN = env->spr[SPR_TLBMISS] & ~0x3; way = env->spr[SPR_TLBMISS] & 0x3; + (void)EPN; /* avoid a compiler warning */ LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP, RPN, way); @@ -3929,37 +3929,56 @@ static inline int booke_page_size_to_tlb(target_ulong page_size) } /* Helpers for 4xx TLB management */ -target_ulong helper_4xx_tlbre_lo (target_ulong entry) +#define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */ + +#define PPC4XX_TLBHI_V 0x00000040 +#define PPC4XX_TLBHI_E 0x00000020 +#define PPC4XX_TLBHI_SIZE_MIN 0 +#define PPC4XX_TLBHI_SIZE_MAX 7 +#define PPC4XX_TLBHI_SIZE_DEFAULT 1 +#define PPC4XX_TLBHI_SIZE_SHIFT 7 +#define PPC4XX_TLBHI_SIZE_MASK 0x00000007 + +#define PPC4XX_TLBLO_EX 0x00000200 +#define PPC4XX_TLBLO_WR 0x00000100 +#define PPC4XX_TLBLO_ATTR_MASK 0x000000FF +#define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00 + +target_ulong helper_4xx_tlbre_hi (target_ulong entry) { ppcemb_tlb_t *tlb; target_ulong ret; int size; - entry &= 0x3F; + entry &= PPC4XX_TLB_ENTRY_MASK; tlb = &env->tlb[entry].tlbe; ret = tlb->EPN; - if (tlb->prot & PAGE_VALID) - ret |= 0x400; + if (tlb->prot & PAGE_VALID) { + ret |= PPC4XX_TLBHI_V; + } size = booke_page_size_to_tlb(tlb->size); - if (size < 0 || size > 0x7) - size = 1; - ret |= size << 7; + if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) { + size = PPC4XX_TLBHI_SIZE_DEFAULT; + } + ret |= size << PPC4XX_TLBHI_SIZE_SHIFT; env->spr[SPR_40x_PID] = tlb->PID; return ret; } -target_ulong helper_4xx_tlbre_hi (target_ulong entry) +target_ulong helper_4xx_tlbre_lo (target_ulong entry) { ppcemb_tlb_t *tlb; target_ulong ret; - entry &= 0x3F; + entry &= PPC4XX_TLB_ENTRY_MASK; tlb = &env->tlb[entry].tlbe; ret = tlb->RPN; - if (tlb->prot & PAGE_EXEC) - ret |= 0x200; - if (tlb->prot & PAGE_WRITE) - ret |= 0x100; + if (tlb->prot & PAGE_EXEC) { + ret |= PPC4XX_TLBLO_EX; + } + if (tlb->prot & PAGE_WRITE) { + ret |= PPC4XX_TLBLO_WR; + } return ret; } @@ -3970,30 +3989,32 @@ void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val) LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry, val); - entry &= 0x3F; + entry &= PPC4XX_TLB_ENTRY_MASK; tlb = &env->tlb[entry].tlbe; /* Invalidate previous TLB (if it's valid) */ if (tlb->prot & PAGE_VALID) { end = tlb->EPN + tlb->size; LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end); - for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) + for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) { tlb_flush_page(env, page); + } } - tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7); + tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT) + & PPC4XX_TLBHI_SIZE_MASK); /* We cannot handle TLB size < TARGET_PAGE_SIZE. * If this ever occurs, one should use the ppcemb target instead * of the ppc or ppc64 one */ - if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) { + if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) { cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u " "are not supported (%d)\n", tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7)); } tlb->EPN = val & ~(tlb->size - 1); - if (val & 0x40) { + if (val & PPC4XX_TLBHI_V) { tlb->prot |= PAGE_VALID; - if (val & 0x20) { + if (val & PPC4XX_TLBHI_E) { /* XXX: TO BE FIXED */ cpu_abort(env, "Little-endian TLB entries are not supported by now\n"); @@ -4014,8 +4035,9 @@ void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val) end = tlb->EPN + tlb->size; LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end); - for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) + for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) { tlb_flush_page(env, page); + } } } @@ -4025,15 +4047,17 @@ void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val) LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry, val); - entry &= 0x3F; + entry &= PPC4XX_TLB_ENTRY_MASK; tlb = &env->tlb[entry].tlbe; - tlb->attr = val & 0xFF; - tlb->RPN = val & 0xFFFFFC00; + tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK; + tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK; tlb->prot = PAGE_READ; - if (val & 0x200) + if (val & PPC4XX_TLBLO_EX) { tlb->prot |= PAGE_EXEC; - if (val & 0x100) + } + if (val & PPC4XX_TLBLO_WR) { tlb->prot |= PAGE_WRITE; + } LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__, (int)entry, tlb->RPN, tlb->EPN, tlb->size, diff --git a/trace-events b/trace-events index f32c83fa2..4300178f1 100644 --- a/trace-events +++ b/trace-events @@ -51,14 +51,16 @@ disable multiwrite_cb(void *mcb, int ret) "mcb %p ret %d" disable bdrv_aio_multiwrite(void *mcb, int num_callbacks, int num_reqs) "mcb %p num_callbacks %d num_reqs %d" disable bdrv_aio_multiwrite_earlyfail(void *mcb) "mcb %p" disable bdrv_aio_multiwrite_latefail(void *mcb, int i) "mcb %p i %d" +disable bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p" +disable bdrv_aio_writev(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p" # hw/virtio-blk.c disable virtio_blk_req_complete(void *req, int status) "req %p status %d" disable virtio_blk_rw_complete(void *req, int ret) "req %p ret %d" -disable virtio_blk_handle_write(void *req, unsigned long sector, unsigned long nsectors) "req %p sector %lu nsectors %lu" +disable virtio_blk_handle_write(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu" # posix-aio-compat.c -disable paio_submit(void *acb, void *opaque, unsigned long sector_num, unsigned long nb_sectors, unsigned long type) "acb %p opaque %p sector_num %lu nb_sectors %lu type %lu" +disable paio_submit(void *acb, void *opaque, int64_t sector_num, int nb_sectors, int type) "acb %p opaque %p sector_num %"PRId64" nb_sectors %d type %d" # ioport.c disable cpu_in(unsigned int addr, unsigned int val) "addr %#x value %u" @@ -250,7 +250,7 @@ linetoh_ust() argnames=$(get_argnames "$1") cat <<EOF -DECLARE_TRACE(ust_$name, TPPROTO($args), TPARGS($argnames)); +DECLARE_TRACE(ust_$name, TP_PROTO($args), TP_ARGS($argnames)); #define trace_$name trace_ust_$name EOF } @@ -318,8 +318,7 @@ convert() while read -r str; do # Skip comments and empty lines - str=${str%%#*} - test -z "$str" && continue + test -z "${str%%#*}" && continue # Process the line. The nop backend handles disabled lines. disable=${str%%disable *} diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h new file mode 100644 index 000000000..063c7dc8c --- /dev/null +++ b/ui/qemu-spice.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef QEMU_SPICE_H +#define QEMU_SPICE_H + +#ifdef CONFIG_SPICE + +#include <spice.h> + +#include "qemu-option.h" +#include "qemu-config.h" + +extern int using_spice; + +void qemu_spice_init(void); +void qemu_spice_input_init(void); +void qemu_spice_display_init(DisplayState *ds); +int qemu_spice_add_interface(SpiceBaseInstance *sin); + +#else /* CONFIG_SPICE */ + +#define using_spice 0 + +#endif /* CONFIG_SPICE */ + +#endif /* QEMU_SPICE_H */ diff --git a/ui/spice-core.c b/ui/spice-core.c new file mode 100644 index 000000000..8b5e4a809 --- /dev/null +++ b/ui/spice-core.c @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <spice.h> +#include <spice-experimental.h> + +#include "qemu-common.h" +#include "qemu-spice.h" +#include "qemu-timer.h" +#include "qemu-queue.h" +#include "monitor.h" + +/* core bits */ + +static SpiceServer *spice_server; +int using_spice = 0; + +struct SpiceTimer { + QEMUTimer *timer; + QTAILQ_ENTRY(SpiceTimer) next; +}; +static QTAILQ_HEAD(, SpiceTimer) timers = QTAILQ_HEAD_INITIALIZER(timers); + +static SpiceTimer *timer_add(SpiceTimerFunc func, void *opaque) +{ + SpiceTimer *timer; + + timer = qemu_mallocz(sizeof(*timer)); + timer->timer = qemu_new_timer(rt_clock, func, opaque); + QTAILQ_INSERT_TAIL(&timers, timer, next); + return timer; +} + +static void timer_start(SpiceTimer *timer, uint32_t ms) +{ + qemu_mod_timer(timer->timer, qemu_get_clock(rt_clock) + ms); +} + +static void timer_cancel(SpiceTimer *timer) +{ + qemu_del_timer(timer->timer); +} + +static void timer_remove(SpiceTimer *timer) +{ + qemu_del_timer(timer->timer); + qemu_free_timer(timer->timer); + QTAILQ_REMOVE(&timers, timer, next); + qemu_free(timer); +} + +struct SpiceWatch { + int fd; + int event_mask; + SpiceWatchFunc func; + void *opaque; + QTAILQ_ENTRY(SpiceWatch) next; +}; +static QTAILQ_HEAD(, SpiceWatch) watches = QTAILQ_HEAD_INITIALIZER(watches); + +static void watch_read(void *opaque) +{ + SpiceWatch *watch = opaque; + watch->func(watch->fd, SPICE_WATCH_EVENT_READ, watch->opaque); +} + +static void watch_write(void *opaque) +{ + SpiceWatch *watch = opaque; + watch->func(watch->fd, SPICE_WATCH_EVENT_WRITE, watch->opaque); +} + +static void watch_update_mask(SpiceWatch *watch, int event_mask) +{ + IOHandler *on_read = NULL; + IOHandler *on_write = NULL; + + watch->event_mask = event_mask; + if (watch->event_mask & SPICE_WATCH_EVENT_READ) { + on_read = watch_read; + } + if (watch->event_mask & SPICE_WATCH_EVENT_WRITE) { + on_read = watch_write; + } + qemu_set_fd_handler(watch->fd, on_read, on_write, watch); +} + +static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque) +{ + SpiceWatch *watch; + + watch = qemu_mallocz(sizeof(*watch)); + watch->fd = fd; + watch->func = func; + watch->opaque = opaque; + QTAILQ_INSERT_TAIL(&watches, watch, next); + + watch_update_mask(watch, event_mask); + return watch; +} + +static void watch_remove(SpiceWatch *watch) +{ + watch_update_mask(watch, 0); + QTAILQ_REMOVE(&watches, watch, next); + qemu_free(watch); +} + +static SpiceCoreInterface core_interface = { + .base.type = SPICE_INTERFACE_CORE, + .base.description = "qemu core services", + .base.major_version = SPICE_INTERFACE_CORE_MAJOR, + .base.minor_version = SPICE_INTERFACE_CORE_MINOR, + + .timer_add = timer_add, + .timer_start = timer_start, + .timer_cancel = timer_cancel, + .timer_remove = timer_remove, + + .watch_add = watch_add, + .watch_update_mask = watch_update_mask, + .watch_remove = watch_remove, +}; + +/* functions for the rest of qemu */ + +void qemu_spice_init(void) +{ + QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head); + const char *password; + int port; + + if (!opts) { + return; + } + port = qemu_opt_get_number(opts, "port", 0); + if (!port) { + return; + } + password = qemu_opt_get(opts, "password"); + + spice_server = spice_server_new(); + spice_server_set_port(spice_server, port); + if (password) { + spice_server_set_ticket(spice_server, password, 0, 0, 0); + } + if (qemu_opt_get_bool(opts, "disable-ticketing", 0)) { + spice_server_set_noauth(spice_server); + } + + /* TODO: make configurable via cmdline */ + spice_server_set_image_compression(spice_server, SPICE_IMAGE_COMPRESS_AUTO_GLZ); + + spice_server_init(spice_server, &core_interface); + using_spice = 1; + + qemu_spice_input_init(); +} + +int qemu_spice_add_interface(SpiceBaseInstance *sin) +{ + return spice_server_add_interface(spice_server, sin); +} + +static void spice_register_config(void) +{ + qemu_add_opts(&qemu_spice_opts); +} +machine_init(spice_register_config); + +static void spice_initialize(void) +{ + qemu_spice_init(); +} +device_init(spice_initialize); diff --git a/ui/spice-display.c b/ui/spice-display.c new file mode 100644 index 000000000..6702dfd7e --- /dev/null +++ b/ui/spice-display.c @@ -0,0 +1,412 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <pthread.h> + +#include "qemu-common.h" +#include "qemu-spice.h" +#include "qemu-timer.h" +#include "qemu-queue.h" +#include "monitor.h" +#include "console.h" +#include "sysemu.h" + +#include "spice-display.h" + +static int debug = 0; + +static void __attribute__((format(printf,2,3))) +dprint(int level, const char *fmt, ...) +{ + va_list args; + + if (level <= debug) { + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + } +} + +int qemu_spice_rect_is_empty(const QXLRect* r) +{ + return r->top == r->bottom || r->left == r->right; +} + +void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r) +{ + if (qemu_spice_rect_is_empty(r)) { + return; + } + + if (qemu_spice_rect_is_empty(dest)) { + *dest = *r; + return; + } + + dest->top = MIN(dest->top, r->top); + dest->left = MIN(dest->left, r->left); + dest->bottom = MAX(dest->bottom, r->bottom); + dest->right = MAX(dest->right, r->right); +} + +/* + * Called from spice server thread context (via interface_get_command). + * We do *not* hold the global qemu mutex here, so extra care is needed + * when calling qemu functions. Qemu interfaces used: + * - pflib (is re-entrant). + * - qemu_malloc (underlying glibc malloc is re-entrant). + */ +SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) +{ + SimpleSpiceUpdate *update; + QXLDrawable *drawable; + QXLImage *image; + QXLCommand *cmd; + uint8_t *src, *dst; + int by, bw, bh; + + if (qemu_spice_rect_is_empty(&ssd->dirty)) { + return NULL; + }; + + pthread_mutex_lock(&ssd->lock); + dprint(2, "%s: lr %d -> %d, tb -> %d -> %d\n", __FUNCTION__, + ssd->dirty.left, ssd->dirty.right, + ssd->dirty.top, ssd->dirty.bottom); + + update = qemu_mallocz(sizeof(*update)); + drawable = &update->drawable; + image = &update->image; + cmd = &update->ext.cmd; + + bw = ssd->dirty.right - ssd->dirty.left; + bh = ssd->dirty.bottom - ssd->dirty.top; + update->bitmap = qemu_malloc(bw * bh * 4); + + drawable->bbox = ssd->dirty; + drawable->clip.type = SPICE_CLIP_TYPE_NONE; + drawable->effect = QXL_EFFECT_OPAQUE; + drawable->release_info.id = (intptr_t)update; + drawable->type = QXL_DRAW_COPY; + drawable->surfaces_dest[0] = -1; + drawable->surfaces_dest[1] = -1; + drawable->surfaces_dest[2] = -1; + + drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT; + drawable->u.copy.src_bitmap = (intptr_t)image; + drawable->u.copy.src_area.right = bw; + drawable->u.copy.src_area.bottom = bh; + + QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, ssd->unique++); + image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP; + image->bitmap.flags = QXL_BITMAP_DIRECT | QXL_BITMAP_TOP_DOWN; + image->bitmap.stride = bw * 4; + image->descriptor.width = image->bitmap.x = bw; + image->descriptor.height = image->bitmap.y = bh; + image->bitmap.data = (intptr_t)(update->bitmap); + image->bitmap.palette = 0; + image->bitmap.format = SPICE_BITMAP_FMT_32BIT; + + if (ssd->conv == NULL) { + PixelFormat dst = qemu_default_pixelformat(32); + ssd->conv = qemu_pf_conv_get(&dst, &ssd->ds->surface->pf); + assert(ssd->conv); + } + + src = ds_get_data(ssd->ds) + + ssd->dirty.top * ds_get_linesize(ssd->ds) + + ssd->dirty.left * ds_get_bytes_per_pixel(ssd->ds); + dst = update->bitmap; + for (by = 0; by < bh; by++) { + qemu_pf_conv_run(ssd->conv, dst, src, bw); + src += ds_get_linesize(ssd->ds); + dst += image->bitmap.stride; + } + + cmd->type = QXL_CMD_DRAW; + cmd->data = (intptr_t)drawable; + + memset(&ssd->dirty, 0, sizeof(ssd->dirty)); + pthread_mutex_unlock(&ssd->lock); + return update; +} + +/* + * Called from spice server thread context (via interface_release_ressource) + * We do *not* hold the global qemu mutex here, so extra care is needed + * when calling qemu functions. Qemu interfaces used: + * - qemu_free (underlying glibc free is re-entrant). + */ +void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update) +{ + qemu_free(update->bitmap); + qemu_free(update); +} + +void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd) +{ + QXLDevMemSlot memslot; + + dprint(1, "%s:\n", __FUNCTION__); + + memset(&memslot, 0, sizeof(memslot)); + memslot.slot_group_id = MEMSLOT_GROUP_HOST; + memslot.virt_end = ~0; + ssd->worker->add_memslot(ssd->worker, &memslot); +} + +void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) +{ + QXLDevSurfaceCreate surface; + + dprint(1, "%s: %dx%d\n", __FUNCTION__, + ds_get_width(ssd->ds), ds_get_height(ssd->ds)); + + surface.format = SPICE_SURFACE_FMT_32_xRGB; + surface.width = ds_get_width(ssd->ds); + surface.height = ds_get_height(ssd->ds); + surface.stride = -surface.width * 4; + surface.mouse_mode = true; + surface.flags = 0; + surface.type = 0; + surface.mem = (intptr_t)ssd->buf; + surface.group_id = MEMSLOT_GROUP_HOST; + ssd->worker->create_primary_surface(ssd->worker, 0, &surface); +} + +void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd) +{ + dprint(1, "%s:\n", __FUNCTION__); + + ssd->worker->destroy_primary_surface(ssd->worker, 0); +} + +void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason) +{ + SimpleSpiceDisplay *ssd = opaque; + + if (running) { + ssd->worker->start(ssd->worker); + } else { + ssd->worker->stop(ssd->worker); + } + ssd->running = running; +} + +/* display listener callbacks */ + +void qemu_spice_display_update(SimpleSpiceDisplay *ssd, + int x, int y, int w, int h) +{ + QXLRect update_area; + + dprint(2, "%s: x %d y %d w %d h %d\n", __FUNCTION__, x, y, w, h); + update_area.left = x, + update_area.right = x + w; + update_area.top = y; + update_area.bottom = y + h; + + pthread_mutex_lock(&ssd->lock); + if (qemu_spice_rect_is_empty(&ssd->dirty)) { + ssd->notify++; + } + qemu_spice_rect_union(&ssd->dirty, &update_area); + pthread_mutex_unlock(&ssd->lock); +} + +void qemu_spice_display_resize(SimpleSpiceDisplay *ssd) +{ + dprint(1, "%s:\n", __FUNCTION__); + + pthread_mutex_lock(&ssd->lock); + memset(&ssd->dirty, 0, sizeof(ssd->dirty)); + qemu_pf_conv_put(ssd->conv); + ssd->conv = NULL; + pthread_mutex_unlock(&ssd->lock); + + qemu_spice_destroy_host_primary(ssd); + qemu_spice_create_host_primary(ssd); + + pthread_mutex_lock(&ssd->lock); + memset(&ssd->dirty, 0, sizeof(ssd->dirty)); + ssd->notify++; + pthread_mutex_unlock(&ssd->lock); +} + +void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd) +{ + dprint(3, "%s:\n", __FUNCTION__); + vga_hw_update(); + if (ssd->notify) { + ssd->notify = 0; + ssd->worker->wakeup(ssd->worker); + dprint(2, "%s: notify\n", __FUNCTION__); + } +} + +/* spice display interface callbacks */ + +static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker) +{ + SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); + + dprint(1, "%s:\n", __FUNCTION__); + ssd->worker = qxl_worker; +} + +static void interface_set_compression_level(QXLInstance *sin, int level) +{ + dprint(1, "%s:\n", __FUNCTION__); + /* nothing to do */ +} + +static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time) +{ + dprint(3, "%s:\n", __FUNCTION__); + /* nothing to do */ +} + +static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info) +{ + SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); + + info->memslot_gen_bits = MEMSLOT_GENERATION_BITS; + info->memslot_id_bits = MEMSLOT_SLOT_BITS; + info->num_memslots = NUM_MEMSLOTS; + info->num_memslots_groups = NUM_MEMSLOTS_GROUPS; + info->internal_groupslot_id = 0; + info->qxl_ram_size = ssd->bufsize; + info->n_surfaces = NUM_SURFACES; +} + +static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) +{ + SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); + SimpleSpiceUpdate *update; + + dprint(3, "%s:\n", __FUNCTION__); + update = qemu_spice_create_update(ssd); + if (update == NULL) { + return false; + } + *ext = update->ext; + return true; +} + +static int interface_req_cmd_notification(QXLInstance *sin) +{ + dprint(1, "%s:\n", __FUNCTION__); + return 1; +} + +static void interface_release_resource(QXLInstance *sin, + struct QXLReleaseInfoExt ext) +{ + SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); + uintptr_t id; + + dprint(2, "%s:\n", __FUNCTION__); + id = ext.info->id; + qemu_spice_destroy_update(ssd, (void*)id); +} + +static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *ext) +{ + dprint(3, "%s:\n", __FUNCTION__); + return false; +} + +static int interface_req_cursor_notification(QXLInstance *sin) +{ + dprint(1, "%s:\n", __FUNCTION__); + return 1; +} + +static void interface_notify_update(QXLInstance *sin, uint32_t update_id) +{ + fprintf(stderr, "%s: abort()\n", __FUNCTION__); + abort(); +} + +static int interface_flush_resources(QXLInstance *sin) +{ + fprintf(stderr, "%s: abort()\n", __FUNCTION__); + abort(); + return 0; +} + +static const QXLInterface dpy_interface = { + .base.type = SPICE_INTERFACE_QXL, + .base.description = "qemu simple display", + .base.major_version = SPICE_INTERFACE_QXL_MAJOR, + .base.minor_version = SPICE_INTERFACE_QXL_MINOR, + + .attache_worker = interface_attach_worker, + .set_compression_level = interface_set_compression_level, + .set_mm_time = interface_set_mm_time, + .get_init_info = interface_get_init_info, + + /* the callbacks below are called from spice server thread context */ + .get_command = interface_get_command, + .req_cmd_notification = interface_req_cmd_notification, + .release_resource = interface_release_resource, + .get_cursor_command = interface_get_cursor_command, + .req_cursor_notification = interface_req_cursor_notification, + .notify_update = interface_notify_update, + .flush_resources = interface_flush_resources, +}; + +static SimpleSpiceDisplay sdpy; + +static void display_update(struct DisplayState *ds, int x, int y, int w, int h) +{ + qemu_spice_display_update(&sdpy, x, y, w, h); +} + +static void display_resize(struct DisplayState *ds) +{ + qemu_spice_display_resize(&sdpy); +} + +static void display_refresh(struct DisplayState *ds) +{ + qemu_spice_display_refresh(&sdpy); +} + +static DisplayChangeListener display_listener = { + .dpy_update = display_update, + .dpy_resize = display_resize, + .dpy_refresh = display_refresh, +}; + +void qemu_spice_display_init(DisplayState *ds) +{ + assert(sdpy.ds == NULL); + sdpy.ds = ds; + sdpy.bufsize = (16 * 1024 * 1024); + sdpy.buf = qemu_malloc(sdpy.bufsize); + pthread_mutex_init(&sdpy.lock, NULL); + register_displaychangelistener(ds, &display_listener); + + sdpy.qxl.base.sif = &dpy_interface.base; + qemu_spice_add_interface(&sdpy.qxl.base); + assert(sdpy.worker); + + qemu_add_vm_change_state_handler(qemu_spice_vm_change_state_handler, &sdpy); + qemu_spice_create_host_memslot(&sdpy); + qemu_spice_create_host_primary(&sdpy); +} diff --git a/ui/spice-display.h b/ui/spice-display.h new file mode 100644 index 000000000..e17671c12 --- /dev/null +++ b/ui/spice-display.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <spice/ipc_ring.h> +#include <spice/enums.h> +#include <spice/qxl_dev.h> + +#include "pflib.h" + +#define NUM_MEMSLOTS 8 +#define MEMSLOT_GENERATION_BITS 8 +#define MEMSLOT_SLOT_BITS 8 + +#define MEMSLOT_GROUP_HOST 0 +#define MEMSLOT_GROUP_GUEST 1 +#define NUM_MEMSLOTS_GROUPS 2 + +#define NUM_SURFACES 1024 + +typedef struct SimpleSpiceDisplay { + DisplayState *ds; + void *buf; + int bufsize; + QXLWorker *worker; + QXLInstance qxl; + uint32_t unique; + QemuPfConv *conv; + + pthread_mutex_t lock; + QXLRect dirty; + int notify; + int running; +} SimpleSpiceDisplay; + +typedef struct SimpleSpiceUpdate { + QXLDrawable drawable; + QXLImage image; + QXLCommandExt ext; + uint8_t *bitmap; +} SimpleSpiceUpdate; + +int qemu_spice_rect_is_empty(const QXLRect* r); +void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r); + +SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *sdpy); +void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update); +void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd); +void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd); +void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd); +void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason); + +void qemu_spice_display_update(SimpleSpiceDisplay *ssd, + int x, int y, int w, int h); +void qemu_spice_display_resize(SimpleSpiceDisplay *ssd); +void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd); diff --git a/ui/spice-input.c b/ui/spice-input.c new file mode 100644 index 000000000..37c8578a2 --- /dev/null +++ b/ui/spice-input.c @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include <string.h> + +#include <spice.h> +#include <spice/enums.h> + +#include "qemu-common.h" +#include "qemu-spice.h" +#include "console.h" + +/* keyboard bits */ + +typedef struct QemuSpiceKbd { + SpiceKbdInstance sin; + int ledstate; +} QemuSpiceKbd; + +static void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag); +static uint8_t kbd_get_leds(SpiceKbdInstance *sin); +static void kbd_leds(void *opaque, int l); + +static const SpiceKbdInterface kbd_interface = { + .base.type = SPICE_INTERFACE_KEYBOARD, + .base.description = "qemu keyboard", + .base.major_version = SPICE_INTERFACE_KEYBOARD_MAJOR, + .base.minor_version = SPICE_INTERFACE_KEYBOARD_MINOR, + .push_scan_freg = kbd_push_key, + .get_leds = kbd_get_leds, +}; + +static void kbd_push_key(SpiceKbdInstance *sin, uint8_t frag) +{ + kbd_put_keycode(frag); +} + +static uint8_t kbd_get_leds(SpiceKbdInstance *sin) +{ + QemuSpiceKbd *kbd = container_of(sin, QemuSpiceKbd, sin); + return kbd->ledstate; +} + +static void kbd_leds(void *opaque, int ledstate) +{ + QemuSpiceKbd *kbd = opaque; + + kbd->ledstate = 0; + if (ledstate & QEMU_SCROLL_LOCK_LED) { + kbd->ledstate |= SPICE_KEYBOARD_MODIFIER_FLAGS_SCROLL_LOCK; + } + if (ledstate & QEMU_NUM_LOCK_LED) { + kbd->ledstate |= SPICE_KEYBOARD_MODIFIER_FLAGS_NUM_LOCK; + } + if (ledstate & QEMU_CAPS_LOCK_LED) { + kbd->ledstate |= SPICE_KEYBOARD_MODIFIER_FLAGS_CAPS_LOCK; + } + spice_server_kbd_leds(&kbd->sin, ledstate); +} + +/* mouse bits */ + +typedef struct QemuSpicePointer { + SpiceMouseInstance mouse; + SpiceTabletInstance tablet; + int width, height, x, y; + Notifier mouse_mode; + bool absolute; +} QemuSpicePointer; + +static int map_buttons(int spice_buttons) +{ + int qemu_buttons = 0; + + /* + * Note: SPICE_MOUSE_BUTTON_* specifies the wire protocol but this + * isn't what we get passed in via interface callbacks for the + * middle and right button ... + */ + if (spice_buttons & SPICE_MOUSE_BUTTON_MASK_LEFT) { + qemu_buttons |= MOUSE_EVENT_LBUTTON; + } + if (spice_buttons & 0x04 /* SPICE_MOUSE_BUTTON_MASK_MIDDLE */) { + qemu_buttons |= MOUSE_EVENT_MBUTTON; + } + if (spice_buttons & 0x02 /* SPICE_MOUSE_BUTTON_MASK_RIGHT */) { + qemu_buttons |= MOUSE_EVENT_RBUTTON; + } + return qemu_buttons; +} + +static void mouse_motion(SpiceMouseInstance *sin, int dx, int dy, int dz, + uint32_t buttons_state) +{ + kbd_mouse_event(dx, dy, dz, map_buttons(buttons_state)); +} + +static void mouse_buttons(SpiceMouseInstance *sin, uint32_t buttons_state) +{ + kbd_mouse_event(0, 0, 0, map_buttons(buttons_state)); +} + +static const SpiceMouseInterface mouse_interface = { + .base.type = SPICE_INTERFACE_MOUSE, + .base.description = "mouse", + .base.major_version = SPICE_INTERFACE_MOUSE_MAJOR, + .base.minor_version = SPICE_INTERFACE_MOUSE_MINOR, + .motion = mouse_motion, + .buttons = mouse_buttons, +}; + +static void tablet_set_logical_size(SpiceTabletInstance* sin, int width, int height) +{ + QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet); + + if (height < 16) { + height = 16; + } + if (width < 16) { + width = 16; + } + pointer->width = width; + pointer->height = height; +} + +static void tablet_position(SpiceTabletInstance* sin, int x, int y, + uint32_t buttons_state) +{ + QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet); + + pointer->x = x * 0x7FFF / (pointer->width - 1); + pointer->y = y * 0x7FFF / (pointer->height - 1); + kbd_mouse_event(pointer->x, pointer->y, 0, map_buttons(buttons_state)); +} + + +static void tablet_wheel(SpiceTabletInstance* sin, int wheel, + uint32_t buttons_state) +{ + QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet); + + kbd_mouse_event(pointer->x, pointer->y, wheel, map_buttons(buttons_state)); +} + +static void tablet_buttons(SpiceTabletInstance *sin, + uint32_t buttons_state) +{ + QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet); + + kbd_mouse_event(pointer->x, pointer->y, 0, map_buttons(buttons_state)); +} + +static const SpiceTabletInterface tablet_interface = { + .base.type = SPICE_INTERFACE_TABLET, + .base.description = "tablet", + .base.major_version = SPICE_INTERFACE_TABLET_MAJOR, + .base.minor_version = SPICE_INTERFACE_TABLET_MINOR, + .set_logical_size = tablet_set_logical_size, + .position = tablet_position, + .wheel = tablet_wheel, + .buttons = tablet_buttons, +}; + +static void mouse_mode_notifier(Notifier *notifier) +{ + QemuSpicePointer *pointer = container_of(notifier, QemuSpicePointer, mouse_mode); + bool is_absolute = kbd_mouse_is_absolute(); + + if (pointer->absolute == is_absolute) { + return; + } + + if (is_absolute) { + qemu_spice_add_interface(&pointer->tablet.base); + } else { + spice_server_remove_interface(&pointer->tablet.base); + } + pointer->absolute = is_absolute; +} + +void qemu_spice_input_init(void) +{ + QemuSpiceKbd *kbd; + QemuSpicePointer *pointer; + + kbd = qemu_mallocz(sizeof(*kbd)); + kbd->sin.base.sif = &kbd_interface.base; + qemu_spice_add_interface(&kbd->sin.base); + qemu_add_led_event_handler(kbd_leds, kbd); + + pointer = qemu_mallocz(sizeof(*pointer)); + pointer->mouse.base.sif = &mouse_interface.base; + pointer->tablet.base.sif = &tablet_interface.base; + qemu_spice_add_interface(&pointer->mouse.base); + + pointer->absolute = false; + pointer->mouse_mode.notify = mouse_mode_notifier; + qemu_add_mouse_mode_change_notifier(&pointer->mouse_mode); + mouse_mode_notifier(&pointer->mouse_mode); +} diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 971bced93..af45edd87 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -641,7 +641,7 @@ DEFINE_GRADIENT_FILTER_FUNCTION(32) /* * Check if a rectangle is all of the same color. If needSameColor is * set to non-zero, then also check that its color equals to the - * *colorPtr value. The result is 1 if the test is successfull, and in + * *colorPtr value. The result is 1 if the test is successful, and in * that case new color will be stored in *colorPtr. */ @@ -214,13 +214,17 @@ static int vnc_server_info_put(QDict *qdict) static void vnc_client_cache_auth(VncState *client) { +#if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL) QDict *qdict; +#endif if (!client->info) { return; } +#if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL) qdict = qobject_to_qdict(client->info); +#endif #ifdef CONFIG_VNC_TLS if (client->tls.session && @@ -2523,7 +2527,9 @@ int vnc_display_open(DisplayState *ds, const char *display) int sasl = 0; int saslErr; #endif +#if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL) int acl = 0; +#endif int lock_key_sync = 1; if (!vnc_display) @@ -2581,8 +2587,10 @@ int vnc_display_open(DisplayState *ds, const char *display) return -1; } #endif +#if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL) } else if (strncmp(options, "acl", 3) == 0) { acl = 1; +#endif } else if (strncmp(options, "lossy", 5) == 0) { vs->lossy = true; } @@ -163,6 +163,8 @@ int main(int argc, char **argv) #include "cpus.h" #include "arch_init.h" +#include "ui/qemu-spice.h" + //#define DEBUG_NET //#define DEBUG_SLIRP @@ -2693,6 +2695,18 @@ int main(int argc, char **argv, char **envp) } break; } + case QEMU_OPTION_spice: + olist = qemu_find_opts("spice"); + if (!olist) { + fprintf(stderr, "spice is not supported by this qemu build.\n"); + exit(1); + } + opts = qemu_opts_parse(olist, optarg, 0); + if (!opts) { + fprintf(stderr, "parse error: %s\n", optarg); + exit(1); + } + break; case QEMU_OPTION_writeconfig: { FILE *fp; @@ -3000,6 +3014,8 @@ int main(int argc, char **argv, char **envp) /* just use the first displaystate for the moment */ ds = get_displaystate(); + if (using_spice) + display_remote++; if (display_type == DT_DEFAULT && !display_remote) { #if defined(CONFIG_SDL) || defined(CONFIG_COCOA) display_type = DT_SDL; @@ -3042,6 +3058,11 @@ int main(int argc, char **argv, char **envp) printf("VNC server running on `%s'\n", vnc_display_local_addr(ds)); } } +#ifdef CONFIG_SPICE + if (using_spice) { + qemu_spice_display_init(ds); + } +#endif /* display setup */ dpy_resize(ds); |