Re: [Qemu-devel] [PATCHv5 05/12] qxl: add io_port_to_string
Hi, +switch (io_port) { +case QXL_IO_NOTIFY_CMD: +return "QXL_IO_NOTIFY_CMD"; Wasn't the plan to make this an array? cheers, Gerd
Re: [Qemu-devel] [RFC] New thread for the VM migration
On 07/14/2011 06:07 PM, Avi Kivity wrote: Maybe we can do this via a magic subsection whose contents are the hotplug event. What about making the device list just another "thing" that has to be migrated live, together with block and ram? Paolo
Re: [Qemu-devel] [PATCHv5 09/12] qxl: async io support using new spice api
case QXL_IO_DESTROY_PRIMARY: if (val != 0) { -qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY: val != 0"); -break; +qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY (async=%d): val != 0", + async); +goto cancel_async; +} +dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (async=%d) (%s)\n", async, + qxl_mode_to_string(d->mode)); +qxl_destroy_primary(d, async); +#if SPICE_INTERFACE_QXL_MINOR>= 1 +if (d->mode == QXL_MODE_UNDEFINED&& async == QXL_ASYNC) { +dprint(d, 1, "QXL_IO_DESTROY_PRIMARY_ASYNC in %s, ignored\n", +qxl_mode_to_string(d->mode)); +qxl_send_events(d, QXL_INTERRUPT_IO_CMD); +goto cancel_async; } Hmm? Why this is needed? default: fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, io_port); abort(); } +return; +cancel_async: +#if SPICE_INTERFACE_QXL_MINOR>= 1 +if (async) { +qemu_mutex_lock(&d->async_lock); +d->current_async = QXL_UNDEFINED_IO; +qemu_mutex_unlock(&d->async_lock); Add "qxl_send_events(d, QXL_INTERRUPT_IO_CMD)" here? typedef struct PCIQXLDevice { PCIDevice pci; SimpleSpiceDisplay ssd; @@ -30,6 +32,11 @@ typedef struct PCIQXLDevice { int32_tnum_memslots; int32_tnum_surfaces; +#if SPICE_INTERFACE_QXL_MINOR>= 1 +uint32_t current_async; +QemuMutex async_lock; +#endif No need to ifdef this. cheers, Gerd
Re: [Qemu-devel] [PATCHv5 10/12] qxl: add QXL_IO_FLUSH_{SURFACES, RELEASE} for guest S3&S4 support
+#if SPICE_INTERFACE_QXL_MINOR>= 1 +case QXL_IO_FLUSH_RELEASE: { +QXLReleaseRing *ring =&d->ram->release_ring; +if (ring->prod - ring->cons + 1 == ring->num_items) { +fprintf(stderr, +"ERROR: no flush, full release ring [p%d,%dc]\n", +ring->prod, ring->cons); +} +qxl_push_free_res(d, 1 /* flush */); +dprint(d, 1, "QXL_IO_FLUSH_RELEASE exit (%s, s#=%d, res#=%d,%p)\n", +qxl_mode_to_string(d->mode), d->guest_surfaces.count, +d->num_free_res, d->last_release); +break; +} +case QXL_IO_FLUSH_SURFACES_ASYNC: +dprint(d, 1, "QXL_IO_FLUSH_SURFACES_ASYNC (%d) (%s, s#=%d, res#=%d)\n", + val, qxl_mode_to_string(d->mode), d->guest_surfaces.count, + d->num_free_res); +qxl_spice_flush_surfaces_async(d); +#endif +break; The last two lines should be swapped I guess. Doesn't harm, but looks a bit odd ... cheers, Gerd
Re: [Qemu-devel] [PATCHv5 11/12] qxl: bump pci rev
+#if SPICE_INTERFACE_QXL_MINOR>= 1 +#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V10 +#else +#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V06 +#endif Does that actually build with old spice-protocol? I don't think so ... cheers, Gerd
Re: [Qemu-devel] [PATCHv5 09/12] qxl: async io support using new spice api
On 07/14/11 21:13, Alon Levy wrote: Some of the QXL port i/o commands are waiting for the spice server to complete certain actions. Add async versions for these commands, so we don't block the vcpu while the spice server processses the command. Instead the qxl device will raise an IRQ when done. The async command processing relies on an added QXLInterface::async_complete and added QXLWorker::*_async additions, in spice server qxl>= 3.1 Applying: qxl: async io support using new spice api === checkpatch complains === WARNING: labels should not be indented #320: FILE: hw/qxl.c:1207: +async_common: total: 0 errors, 1 warnings, 574 lines checked cheers, Gerd
Re: [Qemu-devel] [PATCHv5 12/12] qxl: use QXL_REVISION_*
Hi, +#if SPICE_INTERFACE_QXL_MINOR>= 1 +qemu_mutex_init(&qxl->async_lock); +qxl->current_async = QXL_UNDEFINED_IO; +#endif That surely belongs into another patch ... +case QXL_REVISION_STABLE_V04: /* spice 0.4 -- qxl-1 */ +case QXL_REVISION_STABLE_V06: /* spice 0.6 -- qxl-2 */ I think we should just not use these defines for now. In a year or so when the new bits are in widespread use we can raise the minimum required spice-server+spice-protocol versions, cleanup the ifdef mess and also use QXL_REVISION_STABLE_V04. cheers, Gerd
Re: [Qemu-devel] [PATCHv5 05/12] qxl: add io_port_to_string
On Fri, Jul 15, 2011 at 09:59:21AM +0200, Gerd Hoffmann wrote: > Hi, > > >+switch (io_port) { > >+case QXL_IO_NOTIFY_CMD: > >+return "QXL_IO_NOTIFY_CMD"; > > Wasn't the plan to make this an array? > yes. Somehow I sent the wrong patch. No idea how I managed to do that. > cheers, > Gerd >
Re: [Qemu-devel] [PATCHv5 09/12] qxl: async io support using new spice api
On Fri, Jul 15, 2011 at 10:19:27AM +0200, Gerd Hoffmann wrote: > On 07/14/11 21:13, Alon Levy wrote: > >Some of the QXL port i/o commands are waiting for the spice server to > >complete certain actions. Add async versions for these commands, so we > >don't block the vcpu while the spice server processses the command. > >Instead the qxl device will raise an IRQ when done. > > > >The async command processing relies on an added QXLInterface::async_complete > >and added QXLWorker::*_async additions, in spice server qxl>= 3.1 > > Applying: qxl: async io support using new spice api > === checkpatch complains === > WARNING: labels should not be indented > #320: FILE: hw/qxl.c:1207: > +async_common: > thanks, my bad, did this after the checkpatch (obviously). I'll go add it to the commit hook. > total: 0 errors, 1 warnings, 574 lines checked > > cheers, > Gerd
Re: [Qemu-devel] [PATCHv5 09/12] qxl: async io support using new spice api
On Fri, Jul 15, 2011 at 10:12:14AM +0200, Gerd Hoffmann wrote: > > case QXL_IO_DESTROY_PRIMARY: > > if (val != 0) { > >-qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY: val != 0"); > >-break; > >+qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY (async=%d): val != 0", > >+ async); > >+goto cancel_async; > >+} > >+dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (async=%d) (%s)\n", async, > >+ qxl_mode_to_string(d->mode)); > >+qxl_destroy_primary(d, async); > >+#if SPICE_INTERFACE_QXL_MINOR>= 1 > >+if (d->mode == QXL_MODE_UNDEFINED&& async == QXL_ASYNC) { > >+dprint(d, 1, "QXL_IO_DESTROY_PRIMARY_ASYNC in %s, ignored\n", > >+qxl_mode_to_string(d->mode)); > >+qxl_send_events(d, QXL_INTERRUPT_IO_CMD); > >+goto cancel_async; > > } > > Hmm? Why this is needed? In this case we don't do any operation (i.e. qxl_destroy_primary is a nop, it checkes d->mode == QXL_MODE_UNDEFINED too) so there will never be an async_complete, so there will never be a qxl_send_events, so we need to send it now. > > > default: > > fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, > > io_port); > > abort(); > > } > >+return; > >+cancel_async: > >+#if SPICE_INTERFACE_QXL_MINOR>= 1 > >+if (async) { > >+qemu_mutex_lock(&d->async_lock); > >+d->current_async = QXL_UNDEFINED_IO; > >+qemu_mutex_unlock(&d->async_lock); > > Add "qxl_send_events(d, QXL_INTERRUPT_IO_CMD)" here? no, we want that wen the command is actually complete, on async_complete, where it is already done. > > > typedef struct PCIQXLDevice { > > PCIDevice pci; > > SimpleSpiceDisplay ssd; > >@@ -30,6 +32,11 @@ typedef struct PCIQXLDevice { > > int32_tnum_memslots; > > int32_tnum_surfaces; > > > >+#if SPICE_INTERFACE_QXL_MINOR>= 1 > >+uint32_t current_async; > >+QemuMutex async_lock; > >+#endif > > No need to ifdef this. > missed it. > cheers, > Gerd
Re: [Qemu-devel] [PATCHv5 11/12] qxl: bump pci rev
On Fri, Jul 15, 2011 at 10:20:08AM +0200, Gerd Hoffmann wrote: > >+#if SPICE_INTERFACE_QXL_MINOR>= 1 > >+#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V10 > >+#else > >+#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V06 > >+#endif > > Does that actually build with old spice-protocol? I don't think so ... > no, it won't. /me wonders how I did the compilations. I'll use 2 and 3. > cheers, > Gerd >
Re: [Qemu-devel] [PATCHv5 10/12] qxl: add QXL_IO_FLUSH_{SURFACES, RELEASE} for guest S3&S4 support
On Fri, Jul 15, 2011 at 10:15:26AM +0200, Gerd Hoffmann wrote: > >+#if SPICE_INTERFACE_QXL_MINOR>= 1 > >+case QXL_IO_FLUSH_RELEASE: { > >+QXLReleaseRing *ring =&d->ram->release_ring; > >+if (ring->prod - ring->cons + 1 == ring->num_items) { > >+fprintf(stderr, > >+"ERROR: no flush, full release ring [p%d,%dc]\n", > >+ring->prod, ring->cons); > >+} > >+qxl_push_free_res(d, 1 /* flush */); > >+dprint(d, 1, "QXL_IO_FLUSH_RELEASE exit (%s, s#=%d, res#=%d,%p)\n", > >+qxl_mode_to_string(d->mode), d->guest_surfaces.count, > >+d->num_free_res, d->last_release); > >+break; > >+} > >+case QXL_IO_FLUSH_SURFACES_ASYNC: > >+dprint(d, 1, "QXL_IO_FLUSH_SURFACES_ASYNC (%d) (%s, s#=%d, > >res#=%d)\n", > >+ val, qxl_mode_to_string(d->mode), d->guest_surfaces.count, > >+ d->num_free_res); > >+qxl_spice_flush_surfaces_async(d); > >+#endif > >+break; > > The last two lines should be swapped I guess. > Doesn't harm, but looks a bit odd ... yep. thanks, will fix. > > cheers, > Gerd >
Re: [Qemu-devel] [PATCHv5 12/12] qxl: use QXL_REVISION_*
On Fri, Jul 15, 2011 at 10:23:39AM +0200, Gerd Hoffmann wrote: > Hi, > > >+#if SPICE_INTERFACE_QXL_MINOR>= 1 > >+qemu_mutex_init(&qxl->async_lock); > >+qxl->current_async = QXL_UNDEFINED_IO; > >+#endif > > That surely belongs into another patch ... yes. > > >+case QXL_REVISION_STABLE_V04: /* spice 0.4 -- qxl-1 */ > >+case QXL_REVISION_STABLE_V06: /* spice 0.6 -- qxl-2 */ > > I think we should just not use these defines for now. > > In a year or so when the new bits are in widespread use we can raise > the minimum required spice-server+spice-protocol versions, cleanup > the ifdef mess and also use QXL_REVISION_STABLE_V04. > ok. I'll drop this patch (at least the bits fitting the patch header). > cheers, > Gerd >
Re: [Qemu-devel] [PATCH v5 06/10] trace-state: add "-trace events" argument to control initial state
On Tue, Jun 28, 2011 at 06:53:34PM +0200, Lluís wrote: > diff --git a/docs/tracing.txt b/docs/tracing.txt > index 017ff59..8f6e5c9 100644 > --- a/docs/tracing.txt > +++ b/docs/tracing.txt > @@ -129,6 +129,9 @@ This functionality is also provided through monitor > commands: > * trace-event NAME on|off >Enable/disable a given trace event. > > +The "-trace events=" command line argument can be used to enable the > +events listed in from the very beginning of the program. Please document the syntax of the file: one event name per line. > --- a/qemu-options.hx > +++ b/qemu-options.hx > @@ -2394,17 +2394,29 @@ Normally QEMU loads a configuration file from > @var{sysconfdir}/qemu.conf and > option will prevent QEMU from loading these configuration files at startup. > ETEXI > DEF("trace", HAS_ARG, QEMU_OPTION_trace, > -"-trace\n" > -"Specify a trace file to log traces to\n", > +"-trace [events=][,file=]\n" > +"specify tracing options\n", > QEMU_ARCH_ALL) > STEXI > -HXCOMM This line is not accurate, as the option is backend-specific but HX > does > -HXCOMM not support conditional compilation of text. > -@item -trace > +HXCOMM This line is not accurate, as some sub-options are backend-specific > but > +HXCOMM HX does not support conditional compilation of text. > +@item -trace [events=@var{file}][,file=@var{file}] > @findex -trace > -Specify a trace file to log output traces to. > + > +Specify tracing options. > + > +@table @option > +@item events=@var{file} > +Immediately enable events listed in @var{file}. > +The file must contain one event name (as listed in the @var{trace-events} > file) > +per line. > + > +This option is not available when using the @var{nop} tracing backend. > +@item file=@var{file} This option is only available when using the @var{simple} tracing backend. (nop, ust, dtrace, stderr don't support it) Stefan
Re: [Qemu-devel] [PATCH v5 04/10] trace-state: separate trace event control and query routines from the simple backend
On Tue, Jun 28, 2011 at 06:53:21PM +0200, Lluís wrote: > Move the 'st_print_trace_events' and 'st_change_trace_event_state' into > backend-agnostic 'trace_print_events' and 'trace_event_set_state' > (respectively) > in the "trace/control.c" file. Renaming the functions makes sense but moving their implementations out into control.c inside an #ifdef is not clean. Why not keep their implementations in simple.c? Just renaming them to the generic name should be enough. Let the linker do the #ifdef (we only link in simple.o or we link in another trace backend). There's no need for control.c. Stefan
Re: [Qemu-devel] [PATCH v5 00/10] trace-state: make the behaviour of "disable" consistent across all backends
On Tue, Jun 28, 2011 at 06:52:55PM +0200, Lluís wrote: > This patch defines the "disable" trace event state to always use the "nop" > backend. > > As a side-effect, all events are now enabled (without "disable") by default, > as > all backends (except "stderr") have programmatic support for dynamically > (de)activating each trace event. > > In order to make this true, the "simple" backend now has a "-trace > events=" argument to let the user select which events must be enabled > from > the very beginning. > > NOTES: > * Parsing of -trace arguments is not done in the OS-specific frontends. > > Signed-off-by: Lluís Vilanova > --- > > Changes in v5: > > * Fix a variable name typo in configure. > * Rebase on qemu.git/master (c24a9c6ef946ec1b5b280061d4f7b579aaac6707). > > Changes in v4: > > * Fix a couple of minor errors. > > Changes in v3: > > * Rebase on qemu.git/master (642cfd4d31241c0fc65c520cb1e703659af66236). > * Remove already-merged patches. > * Remove code styling patches. > * Generalize programmatic interface for trace event state control. > > Changes in v2: > > * Documentation fixes. > * Seggregate whitespace/indentation changes. > * Minor code beautifications. > * Make all -trace suboptions explicit. > * Fix minor comments from Stefan. > * Minor trace-events format fixes. > * Integrate changes from Fabien. > * Rebase on qemu.git/master (c8f930c0eeb696d638f4d4bf654e955fa44ff40f). > > Lluís Vilanova (10): > trace: move backend-specific code into the trace/ directory > trace: avoid conditional code compilation during option parsing > trace: generalize the "property" concept in the trace-events file > trace-state: separate trace event control and query routines from the > simple backend > trace-state: always compile support for controlling and querying trace > event states > trace-state: add "-trace events" argument to control initial state > trace-state: always use the "nop" backend on events with the "disable" > keyword > trace-state: [simple] disable all trace points by default > trace-state: [stderr] add support for dynamically enabling/disabling > events > trace: enable all events > > > .gitignore|2 > Makefile |1 > Makefile.objs |5 > configure |7 + > docs/tracing.txt | 64 +++--- > hmp-commands.hx |9 + > monitor.c | 19 +- > qemu-config.c |7 - > qemu-options.hx | 26 ++ > scripts/tracetool | 116 +-- > simpletrace.c | 355 - > simpletrace.h | 48 > trace-events | 569 > ++--- > trace/control.c | 66 ++ > trace/control.h | 16 + > trace/simple.c| 332 +++ > trace/simple.h| 46 > trace/stderr.h| 11 + > vl.c | 21 +- > 19 files changed, 914 insertions(+), 806 deletions(-) > delete mode 100644 simpletrace.c > delete mode 100644 simpletrace.h > create mode 100644 trace/control.c > create mode 100644 trace/control.h > create mode 100644 trace/simple.c > create mode 100644 trace/simple.h > create mode 100644 trace/stderr.h Nice! Now both stderr and simple are unified in terms of user interface. -trace events= can be used to set the enabled trace events on startup. I did leave some comments, mainly #ifdef reduction. But let's merge the next version. Stefan
Re: [Qemu-devel] [PATCH v5 01/10] trace: move backend-specific code into the trace/ directory
On Tue, Jun 28, 2011 at 06:53:01PM +0200, Lluís wrote: > Signed-off-by: Lluís Vilanova > --- > .gitignore|2 > Makefile |1 > Makefile.objs |4 - > scripts/tracetool |2 > simpletrace.c | 355 > - > simpletrace.h | 48 --- > trace/simple.c| 355 > + > trace/simple.h| 48 +++ > vl.c |2 > 9 files changed, 410 insertions(+), 407 deletions(-) > delete mode 100644 simpletrace.c > delete mode 100644 simpletrace.h > create mode 100644 trace/simple.c > create mode 100644 trace/simple.h > > diff --git a/.gitignore b/.gitignore > index 08013fc..b1db525 100644 > --- a/.gitignore > +++ b/.gitignore > @@ -2,6 +2,8 @@ config-devices.* > config-all-devices.* > config-host.* > config-target.* > +trace/*.d > +trace/*.o These are not needed, the *.d and *.o rules already cover them. > trace.h > trace.c > trace-dtrace.h > diff --git a/Makefile b/Makefile > index b3ffbe2..fe01145 100644 > --- a/Makefile > +++ b/Makefile > @@ -170,6 +170,7 @@ clean: > rm -Rf .libs > 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/*.o trace/*.d > rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp > rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp > rm -f trace-dtrace.h trace-dtrace.h-timestamp > diff --git a/Makefile.objs b/Makefile.objs > index cea15e4..9a67374 100644 > --- a/Makefile.objs > +++ b/Makefile.objs > @@ -355,14 +355,14 @@ trace-dtrace.lo: trace-dtrace.dtrace > $(call quiet-command,libtool --mode=compile --tag=CC dtrace -o $@ -G -s > $<, " lt GEN trace-dtrace.o") > endif > > -simpletrace.o: simpletrace.c $(GENERATED_HEADERS) > +trace/simple.o: trace/simple.c $(GENERATED_HEADERS) > > ifeq ($(TRACE_BACKEND),dtrace) > trace-obj-y = trace-dtrace.o > else > trace-obj-y = trace.o > ifeq ($(TRACE_BACKEND),simple) > -trace-obj-y += simpletrace.o > +trace-obj-y += trace/simple.o Once more files are added into trace/ it will be useful to use the "nested" approach that the makefiles use elsewhere (e.g. block-nested-y). It avoids having to specify "trace/" for each object file in the directory. Stefan
Re: [Qemu-devel] [PATCH v5 02/10] trace: avoid conditional code compilation during option parsing
On Tue, Jun 28, 2011 at 06:53:08PM +0200, Lluís wrote: > diff --git a/vl.c b/vl.c > index b2f41fd..b766dc7 100644 > --- a/vl.c > +++ b/vl.c > @@ -2861,14 +2861,23 @@ int main(int argc, char **argv, char **envp) > } > xen_mode = XEN_ATTACH; > break; > -#ifdef CONFIG_SIMPLE_TRACE > case QEMU_OPTION_trace: > opts = qemu_opts_parse(qemu_find_opts("trace"), optarg, 0); > -if (opts) { > -trace_file = qemu_opt_get(opts, "file"); > +if (!opts) { > +exit(1); > } > -break; > +#if defined(CONFIG_TRACE_NOP) > +fprintf(stderr, "qemu: option \"-%s\" is not supported by > this tracing backend\n", popt->name); > +exit(1); > #endif > +trace_file = qemu_opt_get(opts, "file"); > +#if !defined(CONFIG_SIMPLE_TRACE) > +if (trace_file) { > +fprintf(stderr, "qemu: suboption \"-%s file\" is not > supported by this tracing backend\n", popt->name); > +exit(1); > +} > +#endif This doesn't account for other trace backends. For example with dtrace or ust the option would be compiled in and not rejected at runtime. Instead of checking all possible trace backend CONFIG_* we could always compile the -trace option in. Specific backends can validate their options (if used). This approach will not reject unused options but it's simple and doesn't use #ifdefs. Stefan
Re: [Qemu-devel] [Bug 810588] [NEW] Unexpected crash of qemu-kvm with SCSI disk emulation.
On Thu, Jul 14, 2011 at 5:43 PM, Constantine Chernov <810...@bugs.launchpad.net> wrote: > Virual machine with MS windows 2003 installed on the virtual scsi disk > (-drive > file=/my/path/myimage.qcow2.img,boot=on,if=scsi,media=disk,bus=0,unit=1) > unexpectedly crashes without core dump. When the image is connected as an ide > disk (-hda ) vm flies normally. > Qemu-kvm version: 0.12.5 > Os/distr.: Debian squeeze, x86_64 Please post your full QEMU command-line. Did you enable core dumps before launch QEMU? Do "ulimit -c unlimited" in the same shell before running the QEMU command-line. If it is exiting instead of crashing I suggest launching QEMU from gdb and catching the exit: 1. Install qemu-kvm-dbg to get the debuginfo for useful backtraces 2. Start gdb with QEMU and its usual command-line arguments: gdb --args qemu-kvm ... 3. Set breakpoints on exit(3) and abort(2): b exit b abort 4. Run the VM and reproduce the exit: r 5. When it exits you will hopefully be at an exit/abort breakpoint and can print the stack trace: bt Please post the backtrace so we have more information on how the exit happens. Thanks, Stefan
Re: [Qemu-devel] [PATCH] xen: introduce xen_change_state_handler
I have just realized that I wrote the reply to this email long ago but I have never sent it, it was sitting in my Draft mbox. On Thu, 30 Jun 2011, Alexander Graf wrote: > On 06/29/2011 01:16 PM, stefano.stabell...@eu.citrix.com wrote: > > From: Anthony PERARD > > > > Remove the call to xenstore_record_dm_state from xen_main_loop_prepare > > that is HVM specific. > > Add a new vm_change_state_handler shared between xen_pv and xen_hvm > > machines to record the VM state to xenstore. > > > > Signed-off-by: Anthony PERARD > > Signed-off-by: Stefano Stabellini > > --- > > xen-all.c | 25 ++--- > > 1 files changed, 18 insertions(+), 7 deletions(-) > > > > diff --git a/xen-all.c b/xen-all.c > > index 3fd04ef..e8da35f 100644 > > --- a/xen-all.c > > +++ b/xen-all.c > > @@ -797,12 +797,17 @@ void xenstore_store_pv_console_info(int i, > > CharDriverState *chr) > > } > > } > > > > -static void xenstore_record_dm_state(XenIOState *s, const char *state) > > +static void xenstore_record_dm_state(struct xs_handle *xs, const char > > *state) > > { > > char path[50]; > > > > +if (xs == NULL) { > > +fprintf(stderr, "xenstore connection not initialized\n"); > > +exit(1); > > +} > > /studio/tmp/agraf/xen-all.c: In function ‘xenstore_record_dm_state’: > /studio/tmp/agraf/xen-all.c:744: error: ‘xs’ undeclared (first use in > this function) > /studio/tmp/agraf/xen-all.c:744: error: (Each undeclared identifier is > reported only once > /studio/tmp/agraf/xen-all.c:744: error: for each function it appears in.) I think you had some conflicts applying the patch, I'll post it again rebased on your xen-next branch.
Re: [Qemu-devel] [PATCH v3] xen: implement unplug protocol in xen_platform
On Fri, 1 Jul 2011, Stefano Stabellini wrote: > On Fri, 1 Jul 2011, Kevin Wolf wrote: > > Am 30.06.2011 16:16, schrieb Stefano Stabellini: > > > On Thu, 30 Jun 2011, Kevin Wolf wrote: > > >>> +static int pci_piix3_xen_ide_unplug(DeviceState *dev) > > >>> +{ > > >>> +PCIDevice *pci_dev; > > >>> +PCIIDEState *pci_ide; > > >>> +DriveInfo *di; > > >>> +int i = 0; > > >>> + > > >>> +pci_dev = DO_UPCAST(PCIDevice, qdev, dev); > > >>> +pci_ide = DO_UPCAST(PCIIDEState, dev, pci_dev); > > >>> + > > >>> +for (; i < 3; i++) { > > >>> +di = drive_get_by_index(IF_IDE, i); > > >>> +if (di != NULL && di->bdrv != NULL && !di->bdrv->removable) { > > >>> +DeviceState *ds = bdrv_get_attached(di->bdrv); > > >>> +if (ds) { > > >>> +bdrv_detach(di->bdrv, ds); > > >>> +} > > >>> +bdrv_close(di->bdrv); > > >>> +pci_ide->bus[di->bus].ifs[di->unit].bs = NULL; > > >> > > >> Have you tested if this is enough if the guest tries to continue using > > >> the device? I don't know of any case where it's not sufficient, just > > >> trying to make sure that it's really true in practice. > > > > > > The purpose of this is to "hide" the disk from the guest. The unplug is > > > supposed to happen *before* the guest enumerates the IDE disks; it is > > > responsibility of the guest to make sure of it. > > > I tested it with Linux PV on HVM drivers, and Linux doesn't see the > > > emulated disk after the unplug, as it should be. > > > > Yeah. What I meant is that we should make sure that a misbehaving guest, > > which just keeps on playing with the IDE ports anyway, can't crash qemu. > > A quick review suggests that it is the case, but testing it anyway would > > be better. > > I see what you mean: I tested it, a guest cannot crash Qemu. > ping?
[Qemu-devel] [PATCH][REPOST] xen: introduce xen_change_state_handler
From: Anthony PERARD Remove the call to xenstore_record_dm_state from xen_main_loop_prepare that is HVM specific. Add a new vm_change_state_handler shared between xen_pv and xen_hvm machines to record the VM state to xenstore. Signed-off-by: Anthony PERARD Signed-off-by: Stefano Stabellini --- xen-all.c | 25 ++--- 1 files changed, 18 insertions(+), 7 deletions(-) diff --git a/xen-all.c b/xen-all.c index 8105c83..5fa92ae 100644 --- a/xen-all.c +++ b/xen-all.c @@ -797,12 +797,17 @@ void xenstore_store_pv_console_info(int i, CharDriverState *chr) } } -static void xenstore_record_dm_state(XenIOState *s, const char *state) +static void xenstore_record_dm_state(struct xs_handle *xs, const char *state) { char path[50]; +if (xs == NULL) { +fprintf(stderr, "xenstore connection not initialized\n"); +exit(1); +} + snprintf(path, sizeof (path), "/local/domain/0/device-model/%u/state", xen_domid); -if (!xs_write(s->xenstore, XBT_NULL, path, state, strlen(state))) { +if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) { fprintf(stderr, "error recording dm state\n"); exit(1); } @@ -823,15 +828,20 @@ static void xen_main_loop_prepare(XenIOState *state) if (evtchn_fd != -1) { qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state); } - -/* record state running */ -xenstore_record_dm_state(state, "running"); } /* Initialise Xen */ -static void xen_vm_change_state_handler(void *opaque, int running, int reason) +static void xen_change_state_handler(void *opaque, int running, int reason) +{ +if (running) { +/* record state running */ +xenstore_record_dm_state(xenstore, "running"); +} +} + +static void xen_hvm_change_state_handler(void *opaque, int running, int reason) { XenIOState *state = opaque; if (running) { @@ -854,6 +864,7 @@ int xen_init(void) xen_be_printf(NULL, 0, "can't open xen interface\n"); return -1; } +qemu_add_vm_change_state_handler(xen_change_state_handler, NULL); return 0; } @@ -915,7 +926,7 @@ int xen_hvm_init(void) xen_map_cache_init(); xen_ram_init(ram_size); -qemu_add_vm_change_state_handler(xen_vm_change_state_handler, state); +qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state); state->client = xen_cpu_phys_memory_client; QLIST_INIT(&state->physmap); -- 1.7.2.3
Re: [Qemu-devel] [PATCH v3] xen: implement unplug protocol in xen_platform
Am 15.07.2011 12:34, schrieb Stefano Stabellini: > On Fri, 1 Jul 2011, Stefano Stabellini wrote: >> On Fri, 1 Jul 2011, Kevin Wolf wrote: >>> Am 30.06.2011 16:16, schrieb Stefano Stabellini: On Thu, 30 Jun 2011, Kevin Wolf wrote: >> +static int pci_piix3_xen_ide_unplug(DeviceState *dev) >> +{ >> +PCIDevice *pci_dev; >> +PCIIDEState *pci_ide; >> +DriveInfo *di; >> +int i = 0; >> + >> +pci_dev = DO_UPCAST(PCIDevice, qdev, dev); >> +pci_ide = DO_UPCAST(PCIIDEState, dev, pci_dev); >> + >> +for (; i < 3; i++) { >> +di = drive_get_by_index(IF_IDE, i); >> +if (di != NULL && di->bdrv != NULL && !di->bdrv->removable) { >> +DeviceState *ds = bdrv_get_attached(di->bdrv); >> +if (ds) { >> +bdrv_detach(di->bdrv, ds); >> +} >> +bdrv_close(di->bdrv); >> +pci_ide->bus[di->bus].ifs[di->unit].bs = NULL; > > Have you tested if this is enough if the guest tries to continue using > the device? I don't know of any case where it's not sufficient, just > trying to make sure that it's really true in practice. The purpose of this is to "hide" the disk from the guest. The unplug is supposed to happen *before* the guest enumerates the IDE disks; it is responsibility of the guest to make sure of it. I tested it with Linux PV on HVM drivers, and Linux doesn't see the emulated disk after the unplug, as it should be. >>> >>> Yeah. What I meant is that we should make sure that a misbehaving guest, >>> which just keeps on playing with the IDE ports anyway, can't crash qemu. >>> A quick review suggests that it is the case, but testing it anyway would >>> be better. >> >> I see what you mean: I tested it, a guest cannot crash Qemu. >> > > ping? I thought Alex had already merged it. I'm pretty sure that I stated somewhere that the patch is okay for me now. In case I didn't: Acked-by: Kevin Wolf
Re: [Qemu-devel] [PATCHv5 09/12] qxl: async io support using new spice api
Hi, +qxl_destroy_primary(d, async); +#if SPICE_INTERFACE_QXL_MINOR>= 1 +if (d->mode == QXL_MODE_UNDEFINED&& async == QXL_ASYNC) { +dprint(d, 1, "QXL_IO_DESTROY_PRIMARY_ASYNC in %s, ignored\n", +qxl_mode_to_string(d->mode)); +qxl_send_events(d, QXL_INTERRUPT_IO_CMD); +goto cancel_async; } Hmm? Why this is needed? In this case we don't do any operation (i.e. qxl_destroy_primary is a nop, it checkes d->mode == QXL_MODE_UNDEFINED too) so there will never be an async_complete, so there will never be a qxl_send_events, so we need to send it now. Ok. Maybe make qxl_destroy_primary return an error in case there is no primary to destroy, then catch this here? Makes more clear what is going on here. default: fprintf(stderr, "%s: ioport=0x%x, abort()\n", __FUNCTION__, io_port); abort(); } +return; +cancel_async: +#if SPICE_INTERFACE_QXL_MINOR>= 1 +if (async) { +qemu_mutex_lock(&d->async_lock); +d->current_async = QXL_UNDEFINED_IO; +qemu_mutex_unlock(&d->async_lock); Add "qxl_send_events(d, QXL_INTERRUPT_IO_CMD)" here? no, we want that wen the command is actually complete, on async_complete, where it is already done. That is the cancel code path, i.e. the guest did a async request but we don't submit one to the spice-server because some sanity check failed, so we never get a complete callback. Thats why I think we should raise the QXL_INTERRUPT_IO_CMD interrupt here instead. cheers, Gerd
[Qemu-devel] [PATCH v6 01/11] spice: add worker wrapper functions.
From: Gerd Hoffmann Add wrapper functions for all spice worker calls. Signed-off-by: Gerd Hoffmann --- hw/qxl-render.c|4 +- hw/qxl.c | 32 +- ui/spice-display.c | 95 --- ui/spice-display.h | 22 4 files changed, 129 insertions(+), 24 deletions(-) diff --git a/hw/qxl-render.c b/hw/qxl-render.c index 1316066..bef5f14 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -124,8 +124,8 @@ void qxl_render_update(PCIQXLDevice *qxl) update.bottom = qxl->guest_primary.surface.height; memset(dirty, 0, sizeof(dirty)); -qxl->ssd.worker->update_area(qxl->ssd.worker, 0, &update, - dirty, ARRAY_SIZE(dirty), 1); +qemu_spice_update_area(&qxl->ssd, 0, &update, + dirty, ARRAY_SIZE(dirty), 1); for (i = 0; i < ARRAY_SIZE(dirty); i++) { if (qemu_spice_rect_is_empty(dirty+i)) { diff --git a/hw/qxl.c b/hw/qxl.c index 919ec91..545074d 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -690,8 +690,8 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm) dprint(d, 1, "%s: start%s\n", __FUNCTION__, loadvm ? " (loadvm)" : ""); -d->ssd.worker->reset_cursor(d->ssd.worker); -d->ssd.worker->reset_image_cache(d->ssd.worker); +qemu_spice_reset_cursor(&d->ssd); +qemu_spice_reset_image_cache(&d->ssd); qxl_reset_surfaces(d); qxl_reset_memslots(d); @@ -796,7 +796,7 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta) __FUNCTION__, memslot.slot_id, memslot.virt_start, memslot.virt_end); -d->ssd.worker->add_memslot(d->ssd.worker, &memslot); +qemu_spice_add_memslot(&d->ssd, &memslot); d->guest_slots[slot_id].ptr = (void*)memslot.virt_start; d->guest_slots[slot_id].size = memslot.virt_end - memslot.virt_start; d->guest_slots[slot_id].delta = delta; @@ -806,14 +806,14 @@ static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta) static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id) { dprint(d, 1, "%s: slot %d\n", __FUNCTION__, slot_id); -d->ssd.worker->del_memslot(d->ssd.worker, MEMSLOT_GROUP_HOST, slot_id); +qemu_spice_del_memslot(&d->ssd, MEMSLOT_GROUP_HOST, slot_id); d->guest_slots[slot_id].active = 0; } static void qxl_reset_memslots(PCIQXLDevice *d) { dprint(d, 1, "%s:\n", __FUNCTION__); -d->ssd.worker->reset_memslots(d->ssd.worker); +qemu_spice_reset_memslots(&d->ssd); memset(&d->guest_slots, 0, sizeof(d->guest_slots)); } @@ -821,7 +821,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d) { dprint(d, 1, "%s:\n", __FUNCTION__); d->mode = QXL_MODE_UNDEFINED; -d->ssd.worker->destroy_surfaces(d->ssd.worker); +qemu_spice_destroy_surfaces(&d->ssd); memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds)); } @@ -875,7 +875,7 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm) qxl->mode = QXL_MODE_NATIVE; qxl->cmdflags = 0; -qxl->ssd.worker->create_primary_surface(qxl->ssd.worker, 0, &surface); +qemu_spice_create_primary_surface(&qxl->ssd, 0, &surface); /* for local rendering */ qxl_render_resize(qxl); @@ -890,7 +890,7 @@ static void qxl_destroy_primary(PCIQXLDevice *d) dprint(d, 1, "%s\n", __FUNCTION__); d->mode = QXL_MODE_UNDEFINED; -d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0); +qemu_spice_destroy_primary_surface(&d->ssd, 0); } static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm) @@ -962,15 +962,15 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) case QXL_IO_UPDATE_AREA: { QXLRect update = d->ram->update_area; -d->ssd.worker->update_area(d->ssd.worker, d->ram->update_surface, - &update, NULL, 0, 0); +qemu_spice_update_area(&d->ssd, d->ram->update_surface, + &update, NULL, 0, 0); break; } case QXL_IO_NOTIFY_CMD: -d->ssd.worker->wakeup(d->ssd.worker); +qemu_spice_wakeup(&d->ssd); break; case QXL_IO_NOTIFY_CURSOR: -d->ssd.worker->wakeup(d->ssd.worker); +qemu_spice_wakeup(&d->ssd); break; case QXL_IO_UPDATE_IRQ: qxl_set_irq(d); @@ -984,7 +984,7 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) break; } d->oom_running = 1; -d->ssd.worker->oom(d->ssd.worker); +qemu_spice_oom(&d->ssd); d->oom_running = 0; break; case QXL_IO_SET_MODE: @@ -1022,10 +1022,10 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) qxl_destroy_primary(d); break; case QXL_IO_DESTROY_SURFACE_WAIT: -d->ssd.worker->destroy_surface_wait(d->ssd.worker, val); +qemu_spice_destroy_surface_wait(&d->ssd, val);
[Qemu-devel] [PATCH v6 03/11] spice/qxl: move worker wrappers
From: Gerd Hoffmann Move the wrapper functions which are used by qxl only to qxl.c. Rename them from qemu_spice_* to qxl_spice_*. Also pass in a qxl state pointer instead of a SimpleSpiceDisplay pointer. Signed-off-by: Gerd Hoffmann --- hw/qxl-render.c|4 +- hw/qxl.c | 67 --- hw/qxl.h | 13 ++ ui/spice-display.c | 46 --- ui/spice-display.h | 12 - 5 files changed, 72 insertions(+), 70 deletions(-) diff --git a/hw/qxl-render.c b/hw/qxl-render.c index bef5f14..60b822d 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -124,8 +124,8 @@ void qxl_render_update(PCIQXLDevice *qxl) update.bottom = qxl->guest_primary.surface.height; memset(dirty, 0, sizeof(dirty)); -qemu_spice_update_area(&qxl->ssd, 0, &update, - dirty, ARRAY_SIZE(dirty), 1); +qxl_spice_update_area(qxl, 0, &update, + dirty, ARRAY_SIZE(dirty), 1); for (i = 0; i < ARRAY_SIZE(dirty); i++) { if (qemu_spice_rect_is_empty(dirty+i)) { diff --git a/hw/qxl.c b/hw/qxl.c index 2d46814..29094a9 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -125,6 +125,53 @@ static void qxl_reset_memslots(PCIQXLDevice *d); static void qxl_reset_surfaces(PCIQXLDevice *d); static void qxl_ring_set_dirty(PCIQXLDevice *qxl); + +void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, + struct QXLRect *area, struct QXLRect *dirty_rects, + uint32_t num_dirty_rects, + uint32_t clear_dirty_region) +{ +qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area, dirty_rects, + num_dirty_rects, clear_dirty_region); +} + +void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id) +{ +qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id); +} + +void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, + uint32_t count) +{ +qxl->ssd.worker->loadvm_commands(qxl->ssd.worker, ext, count); +} + +void qxl_spice_oom(PCIQXLDevice *qxl) +{ +qxl->ssd.worker->oom(qxl->ssd.worker); +} + +void qxl_spice_reset_memslots(PCIQXLDevice *qxl) +{ +qxl->ssd.worker->reset_memslots(qxl->ssd.worker); +} + +void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl) +{ +qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker); +} + +void qxl_spice_reset_image_cache(PCIQXLDevice *qxl) +{ +qxl->ssd.worker->reset_image_cache(qxl->ssd.worker); +} + +void qxl_spice_reset_cursor(PCIQXLDevice *qxl) +{ +qxl->ssd.worker->reset_cursor(qxl->ssd.worker); +} + + static inline uint32_t msb_mask(uint32_t val) { uint32_t mask; @@ -690,8 +737,8 @@ static void qxl_hard_reset(PCIQXLDevice *d, int loadvm) dprint(d, 1, "%s: start%s\n", __FUNCTION__, loadvm ? " (loadvm)" : ""); -qemu_spice_reset_cursor(&d->ssd); -qemu_spice_reset_image_cache(&d->ssd); +qxl_spice_reset_cursor(d); +qxl_spice_reset_image_cache(d); qxl_reset_surfaces(d); qxl_reset_memslots(d); @@ -813,7 +860,7 @@ static void qxl_del_memslot(PCIQXLDevice *d, uint32_t slot_id) static void qxl_reset_memslots(PCIQXLDevice *d) { dprint(d, 1, "%s:\n", __FUNCTION__); -qemu_spice_reset_memslots(&d->ssd); +qxl_spice_reset_memslots(d); memset(&d->guest_slots, 0, sizeof(d->guest_slots)); } @@ -821,7 +868,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d) { dprint(d, 1, "%s:\n", __FUNCTION__); d->mode = QXL_MODE_UNDEFINED; -qemu_spice_destroy_surfaces(&d->ssd); +qxl_spice_destroy_surfaces(d); memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds)); } @@ -962,8 +1009,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) case QXL_IO_UPDATE_AREA: { QXLRect update = d->ram->update_area; -qemu_spice_update_area(&d->ssd, d->ram->update_surface, - &update, NULL, 0, 0); +qxl_spice_update_area(d, d->ram->update_surface, + &update, NULL, 0, 0); break; } case QXL_IO_NOTIFY_CMD: @@ -984,7 +1031,7 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) break; } d->oom_running = 1; -qemu_spice_oom(&d->ssd); +qxl_spice_oom(d); d->oom_running = 0; break; case QXL_IO_SET_MODE: @@ -1022,10 +1069,10 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) qxl_destroy_primary(d); break; case QXL_IO_DESTROY_SURFACE_WAIT: -qemu_spice_destroy_surface_wait(&d->ssd, val); +qxl_spice_destroy_surface_wait(d, val); break; case QXL_IO_DESTROY_ALL_SURFACES: -qemu_spice_destroy_surfaces(&d->ssd); +qxl_spice_destroy_surfaces(d); break; default: fprintf(stderr,
[Qemu-devel] [PATCH v6 10/11] qxl: add QXL_IO_FLUSH_{SURFACES, RELEASE} for guest S3&S4 support
Add two new IOs. QXL_IO_FLUSH_SURFACES - equivalent to update area for all surfaces, used to reduce vmexits from NumSurfaces to 1 on guest S3, S4 and resolution change (windows driver implementation is such that this is done on each of those occasions). QXL_IO_FLUSH_RELEASE - used to ensure anything on last_release is put on the release ring for the client to free. Cc: Yonit Halperin Signed-off-by: Alon Levy --- hw/qxl.c | 30 ++ 1 files changed, 30 insertions(+), 0 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 7c4c520..6d21171 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -185,6 +185,13 @@ static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id, } } +#if SPICE_INTERFACE_QXL_MINOR >= 1 +static void qxl_spice_flush_surfaces_async(PCIQXLDevice *qxl) +{ +qxl->ssd.worker->flush_surfaces_async(qxl->ssd.worker, 0); +} +#endif + void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, uint32_t count) { @@ -1190,6 +1197,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) goto async_common; case QXL_IO_DESTROY_ALL_SURFACES_ASYNC: io_port = QXL_IO_DESTROY_ALL_SURFACES; +goto async_common; +case QXL_IO_FLUSH_SURFACES_ASYNC: async_common: async = QXL_ASYNC; qemu_mutex_lock(&d->async_lock); @@ -1302,6 +1311,27 @@ async_common: } qxl_spice_destroy_surface_wait(d, val, async); break; +#if SPICE_INTERFACE_QXL_MINOR >= 1 +case QXL_IO_FLUSH_RELEASE: { +QXLReleaseRing *ring = &d->ram->release_ring; +if (ring->prod - ring->cons + 1 == ring->num_items) { +fprintf(stderr, +"ERROR: no flush, full release ring [p%d,%dc]\n", +ring->prod, ring->cons); +} +qxl_push_free_res(d, 1 /* flush */); +dprint(d, 1, "QXL_IO_FLUSH_RELEASE exit (%s, s#=%d, res#=%d,%p)\n", +qxl_mode_to_string(d->mode), d->guest_surfaces.count, +d->num_free_res, d->last_release); +break; +} +case QXL_IO_FLUSH_SURFACES_ASYNC: +dprint(d, 1, "QXL_IO_FLUSH_SURFACES_ASYNC (%d) (%s, s#=%d, res#=%d)\n", + val, qxl_mode_to_string(d->mode), d->guest_surfaces.count, + d->num_free_res); +qxl_spice_flush_surfaces_async(d); +break; +#endif case QXL_IO_DESTROY_ALL_SURFACES: d->mode = QXL_MODE_UNDEFINED; qxl_spice_destroy_surfaces(d, async); -- 1.7.6
[Qemu-devel] [PATCH v6 05/11] qxl: add io_port_to_string
Signed-off-by: Alon Levy --- hw/qxl.c | 40 +++- 1 files changed, 39 insertions(+), 1 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index e832d00..7d8b312 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -409,6 +409,43 @@ static const char *qxl_mode_to_string(int mode) return "INVALID"; } +static const char *io_port_to_string(uint32_t io_port) +{ +if (io_port >= QXL_IO_RANGE_SIZE) { +return "out of range"; +} +static const char *io_port_to_string[QXL_IO_RANGE_SIZE + 1] = { +[QXL_IO_NOTIFY_CMD] = "QXL_IO_NOTIFY_CMD", +[QXL_IO_NOTIFY_CURSOR] = "QXL_IO_NOTIFY_CURSOR", +[QXL_IO_UPDATE_AREA]= "QXL_IO_UPDATE_AREA", +[QXL_IO_UPDATE_IRQ] = "QXL_IO_UPDATE_IRQ", +[QXL_IO_NOTIFY_OOM] = "QXL_IO_NOTIFY_OOM", +[QXL_IO_RESET] = "QXL_IO_RESET", +[QXL_IO_SET_MODE] = "QXL_IO_SET_MODE", +[QXL_IO_LOG]= "QXL_IO_LOG", +[QXL_IO_MEMSLOT_ADD]= "QXL_IO_MEMSLOT_ADD", +[QXL_IO_MEMSLOT_DEL]= "QXL_IO_MEMSLOT_DEL", +[QXL_IO_DETACH_PRIMARY] = "QXL_IO_DETACH_PRIMARY", +[QXL_IO_ATTACH_PRIMARY] = "QXL_IO_ATTACH_PRIMARY", +[QXL_IO_CREATE_PRIMARY] = "QXL_IO_CREATE_PRIMARY", +[QXL_IO_DESTROY_PRIMARY]= "QXL_IO_DESTROY_PRIMARY", +[QXL_IO_DESTROY_SURFACE_WAIT] = "QXL_IO_DESTROY_SURFACE_WAIT", +[QXL_IO_DESTROY_ALL_SURFACES] = "QXL_IO_DESTROY_ALL_SURFACES", +#if SPICE_INTERFACE_QXL_MINOR >= 1 +[QXL_IO_UPDATE_AREA_ASYNC] = "QXL_IO_UPDATE_AREA_ASYNC", +[QXL_IO_MEMSLOT_ADD_ASYNC] = "QXL_IO_MEMSLOT_ADD_ASYNC", +[QXL_IO_CREATE_PRIMARY_ASYNC] = "QXL_IO_CREATE_PRIMARY_ASYNC", +[QXL_IO_DESTROY_PRIMARY_ASYNC] = "QXL_IO_DESTROY_PRIMARY_ASYNC", +[QXL_IO_DESTROY_SURFACE_ASYNC] = "QXL_IO_DESTROY_SURFACE_ASYNC", +[QXL_IO_DESTROY_ALL_SURFACES_ASYNC] += "QXL_IO_DESTROY_ALL_SURFACES_ASYNC", +[QXL_IO_FLUSH_SURFACES_ASYNC] = "QXL_IO_FLUSH_SURFACES_ASYNC", +[QXL_IO_FLUSH_RELEASE] = "QXL_IO_FLUSH_RELEASE", +#endif +}; +return io_port_to_string[io_port]; +} + /* called from spice server thread context only */ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) { @@ -1011,7 +1048,8 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) default: if (d->mode == QXL_MODE_NATIVE || d->mode == QXL_MODE_COMPAT) break; -dprint(d, 1, "%s: unexpected port 0x%x in vga mode\n", __FUNCTION__, io_port); +dprint(d, 1, "%s: unexpected port 0x%x (%s) in vga mode\n", +__func__, io_port, io_port_to_string(io_port)); return; } -- 1.7.6
[Qemu-devel] [PATCH v6 00/11] async + suspend reworked
v5->v6: really use array in io_port_to_string undo merged "async io support" to revision change remove QXL_REVISION_* defines usage move qxl_send_event to async_cancel fix async_cancel label per patchcheck Alon Levy (5): qxl: add io_port_to_string qxl: make qxl_guest_bug take variable arguments qxl: only disallow specific io's in vga mode qxl: async io support using new spice api qxl: add QXL_IO_FLUSH_{SURFACES,RELEASE} for guest S3&S4 support Gerd Hoffmann (6): spice: add worker wrapper functions. spice: add qemu_spice_display_init_common spice/qxl: move worker wrappers qxl: fix surface tracking & locking qxl: error handling fixes and cleanups. qxl: bump pci rev hw/qxl-render.c|4 +- hw/qxl.c | 440 +--- hw/qxl.h | 34 - ui/spice-display.c | 93 ++-- ui/spice-display.h | 28 5 files changed, 529 insertions(+), 70 deletions(-) -- 1.7.6
[Qemu-devel] [PATCH v6 09/11] qxl: async io support using new spice api
Some of the QXL port i/o commands are waiting for the spice server to complete certain actions. Add async versions for these commands, so we don't block the vcpu while the spice server processses the command. Instead the qxl device will raise an IRQ when done. The async command processing relies on an added QXLInterface::async_complete and added QXLWorker::*_async additions, in spice server qxl >= 3.1 Signed-off-by: Gerd Hoffmann Signed-off-by: Alon Levy --- hw/qxl-render.c|2 +- hw/qxl.c | 240 hw/qxl.h | 16 +++- ui/spice-display.c | 47 -- ui/spice-display.h | 23 +- 5 files changed, 274 insertions(+), 54 deletions(-) diff --git a/hw/qxl-render.c b/hw/qxl-render.c index 60b822d..643ff2d 100644 --- a/hw/qxl-render.c +++ b/hw/qxl-render.c @@ -125,7 +125,7 @@ void qxl_render_update(PCIQXLDevice *qxl) memset(dirty, 0, sizeof(dirty)); qxl_spice_update_area(qxl, 0, &update, - dirty, ARRAY_SIZE(dirty), 1); + dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC); for (i = 0; i < ARRAY_SIZE(dirty); i++) { if (qemu_spice_rect_is_empty(dirty+i)) { diff --git a/hw/qxl.c b/hw/qxl.c index b946942..7c4c520 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -120,7 +120,7 @@ static QXLMode qxl_modes[] = { static PCIQXLDevice *qxl0; static void qxl_send_events(PCIQXLDevice *d, uint32_t events); -static void qxl_destroy_primary(PCIQXLDevice *d); +static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async); static void qxl_reset_memslots(PCIQXLDevice *d); static void qxl_reset_surfaces(PCIQXLDevice *d); static void qxl_ring_set_dirty(PCIQXLDevice *qxl); @@ -144,22 +144,47 @@ void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, struct QXLRect *area, struct QXLRect *dirty_rects, uint32_t num_dirty_rects, - uint32_t clear_dirty_region) + uint32_t clear_dirty_region, + qxl_async_io async) { -qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area, dirty_rects, - num_dirty_rects, clear_dirty_region); +if (async == QXL_SYNC) { +qxl->ssd.worker->update_area(qxl->ssd.worker, surface_id, area, +dirty_rects, num_dirty_rects, clear_dirty_region); +} else { +#if SPICE_INTERFACE_QXL_MINOR >= 1 +qxl->ssd.worker->update_area_async(qxl->ssd.worker, surface_id, area, + clear_dirty_region, 0); +#else +abort(); +#endif +} } -void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id) +static void qxl_spice_destroy_surface_wait_complete(PCIQXLDevice *qxl, +uint32_t id) { qemu_mutex_lock(&qxl->track_lock); -PANIC_ON(id >= NUM_SURFACES); -qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id); qxl->guest_surfaces.cmds[id] = 0; qxl->guest_surfaces.count--; qemu_mutex_unlock(&qxl->track_lock); } +static void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id, + qxl_async_io async) +{ +if (async) { +#if SPICE_INTERFACE_QXL_MINOR < 1 +abort(); +#else +qxl->ssd.worker->destroy_surface_wait_async(qxl->ssd.worker, id, +(uint64_t)id); +#endif +} else { +qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id); +qxl_spice_destroy_surface_wait_complete(qxl, id); +} +} + void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, uint32_t count) { @@ -176,15 +201,28 @@ void qxl_spice_reset_memslots(PCIQXLDevice *qxl) qxl->ssd.worker->reset_memslots(qxl->ssd.worker); } -void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl) +static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl) { qemu_mutex_lock(&qxl->track_lock); -qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker); memset(&qxl->guest_surfaces.cmds, 0, sizeof(qxl->guest_surfaces.cmds)); qxl->guest_surfaces.count = 0; qemu_mutex_unlock(&qxl->track_lock); } +static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async) +{ +if (async) { +#if SPICE_INTERFACE_QXL_MINOR < 1 +abort(); +#else +qxl->ssd.worker->destroy_surfaces_async(qxl->ssd.worker, 0); +#endif +} else { +qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker); +qxl_spice_destroy_surfaces_complete(qxl); +} +} + void qxl_spice_reset_image_cache(PCIQXLDevice *qxl) { qxl->ssd.worker->reset_image_cache(qxl->ssd.worker); @@ -689,6 +727,38 @@ static int interface_flush_resources(QXLInstance *sin) return ret; } +static void q
[Qemu-devel] [PATCH v6 08/11] qxl: only disallow specific io's in vga mode
Since the driver is still in operation even after moving to UNDEFINED, i.e. by destroying primary in any way. Signed-off-by: Alon Levy --- hw/qxl.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index d645c87..b946942 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1061,8 +1061,9 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) case QXL_IO_LOG: break; default: -if (d->mode == QXL_MODE_NATIVE || d->mode == QXL_MODE_COMPAT) +if (d->mode != QXL_MODE_VGA) { break; +} dprint(d, 1, "%s: unexpected port 0x%x (%s) in vga mode\n", __func__, io_port, io_port_to_string(io_port)); return; -- 1.7.6
[Qemu-devel] [PATCH v6 04/11] qxl: fix surface tracking & locking
From: Gerd Hoffmann Surface tracking needs proper locking since it is used from vcpu and spice worker threads, add it. Also reset the surface counter when zapping all surfaces. Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 13 - hw/qxl.h |2 ++ 2 files changed, 14 insertions(+), 1 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 29094a9..e832d00 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -137,7 +137,12 @@ void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, void qxl_spice_destroy_surface_wait(PCIQXLDevice *qxl, uint32_t id) { +qemu_mutex_lock(&qxl->track_lock); +PANIC_ON(id >= NUM_SURFACES); qxl->ssd.worker->destroy_surface_wait(qxl->ssd.worker, id); +qxl->guest_surfaces.cmds[id] = 0; +qxl->guest_surfaces.count--; +qemu_mutex_unlock(&qxl->track_lock); } void qxl_spice_loadvm_commands(PCIQXLDevice *qxl, struct QXLCommandExt *ext, @@ -158,7 +163,11 @@ void qxl_spice_reset_memslots(PCIQXLDevice *qxl) void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl) { +qemu_mutex_lock(&qxl->track_lock); qxl->ssd.worker->destroy_surfaces(qxl->ssd.worker); +memset(&qxl->guest_surfaces.cmds, 0, sizeof(qxl->guest_surfaces.cmds)); +qxl->guest_surfaces.count = 0; +qemu_mutex_unlock(&qxl->track_lock); } void qxl_spice_reset_image_cache(PCIQXLDevice *qxl) @@ -317,6 +326,7 @@ static void qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext) QXLSurfaceCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); uint32_t id = le32_to_cpu(cmd->surface_id); PANIC_ON(id >= NUM_SURFACES); +qemu_mutex_lock(&qxl->track_lock); if (cmd->type == QXL_SURFACE_CMD_CREATE) { qxl->guest_surfaces.cmds[id] = ext->cmd.data; qxl->guest_surfaces.count++; @@ -327,6 +337,7 @@ static void qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext) qxl->guest_surfaces.cmds[id] = 0; qxl->guest_surfaces.count--; } +qemu_mutex_unlock(&qxl->track_lock); break; } case QXL_CMD_CURSOR: @@ -869,7 +880,6 @@ static void qxl_reset_surfaces(PCIQXLDevice *d) dprint(d, 1, "%s:\n", __FUNCTION__); d->mode = QXL_MODE_UNDEFINED; qxl_spice_destroy_surfaces(d); -memset(&d->guest_surfaces.cmds, 0, sizeof(d->guest_surfaces.cmds)); } /* called from spice server thread context only */ @@ -1289,6 +1299,7 @@ static int qxl_init_common(PCIQXLDevice *qxl) qxl->generation = 1; qxl->num_memslots = NUM_MEMSLOTS; qxl->num_surfaces = NUM_SURFACES; +qemu_mutex_init(&qxl->track_lock); switch (qxl->revision) { case 1: /* spice 0.4 -- qxl-1 */ diff --git a/hw/qxl.h b/hw/qxl.h index e62b9d0..5d0e85e 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -55,6 +55,8 @@ typedef struct PCIQXLDevice { } guest_surfaces; QXLPHYSICALguest_cursor; +QemuMutex track_lock; + /* thread signaling */ pthread_t main; intpipe[2]; -- 1.7.6
[Qemu-devel] [PATCH v6 11/11] qxl: bump pci rev
From: Gerd Hoffmann Inform guest drivers about the new features I/O commands we have now (async commands, S3 support) if building with newer spice, i.e. if SPICE_INTERFACE_QXL_MINOR >= 1. sneaked in some 81+ column line spliting. Signed-off-by: Gerd Hoffmann Signed-off-by: Alon Levy --- hw/qxl.c | 25 ++--- hw/qxl.h |6 ++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 6d21171..dcdd0df 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1572,9 +1572,14 @@ static int qxl_init_common(PCIQXLDevice *qxl) pci_device_rev = QXL_REVISION_STABLE_V04; break; case 2: /* spice 0.6 -- qxl-2 */ -default: pci_device_rev = QXL_REVISION_STABLE_V06; break; +#if SPICE_INTERFACE_QXL_MINOR >= 1 +case 3: /* qxl-3 */ +#endif +default: +pci_device_rev = QXL_DEFAULT_REVISION; +break; } pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev); @@ -1836,9 +1841,12 @@ static PCIDeviceInfo qxl_info_primary = { .device_id= QXL_DEVICE_ID_STABLE, .class_id = PCI_CLASS_DISPLAY_VGA, .qdev.props = (Property[]) { -DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024), -DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024), -DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, 2), +DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, + 64 * 1024 * 1024), +DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, + 64 * 1024 * 1024), +DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, + QXL_DEFAULT_REVISION), DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0), DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0), DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0), @@ -1857,9 +1865,12 @@ static PCIDeviceInfo qxl_info_secondary = { .device_id= QXL_DEVICE_ID_STABLE, .class_id = PCI_CLASS_DISPLAY_OTHER, .qdev.props = (Property[]) { -DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, 64 * 1024 * 1024), -DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, 64 * 1024 * 1024), -DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, 2), +DEFINE_PROP_UINT32("ram_size", PCIQXLDevice, vga.vram_size, + 64 * 1024 * 1024), +DEFINE_PROP_UINT32("vram_size", PCIQXLDevice, vram_size, + 64 * 1024 * 1024), +DEFINE_PROP_UINT32("revision", PCIQXLDevice, revision, + QXL_DEFAULT_REVISION), DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0), DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0), DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0), diff --git a/hw/qxl.h b/hw/qxl.h index 1046205..4bcf7e1 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -102,6 +102,12 @@ typedef struct PCIQXLDevice { } \ } while (0) +#if SPICE_INTERFACE_QXL_MINOR >= 1 +#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V10 +#else +#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V06 +#endif + /* qxl.c */ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id); void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...); -- 1.7.6
[Qemu-devel] [PATCH v6 07/11] qxl: make qxl_guest_bug take variable arguments
Signed-off-by: Alon Levy --- hw/qxl.c |9 +++-- hw/qxl.h |2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 68ce409..d645c87 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -125,13 +125,18 @@ static void qxl_reset_memslots(PCIQXLDevice *d); static void qxl_reset_surfaces(PCIQXLDevice *d); static void qxl_ring_set_dirty(PCIQXLDevice *qxl); -void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg) +void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) { #if SPICE_INTERFACE_QXL_MINOR >= 1 qxl_send_events(qxl, QXL_INTERRUPT_ERROR); #endif if (qxl->guestdebug) { -fprintf(stderr, "qxl-%d: guest bug: %s\n", qxl->id, msg); +va_list ap; +va_start(ap, msg); +fprintf(stderr, "qxl-%d: guest bug: ", qxl->id); +vfprintf(stderr, msg, ap); +fprintf(stderr, "\n"); +va_end(ap); } } diff --git a/hw/qxl.h b/hw/qxl.h index 5db9aae..32ca5a0 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -99,7 +99,7 @@ typedef struct PCIQXLDevice { /* qxl.c */ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id); -void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg); +void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg, ...); void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, struct QXLRect *area, struct QXLRect *dirty_rects, -- 1.7.6
[Qemu-devel] [PATCH v6 02/11] spice: add qemu_spice_display_init_common
From: Gerd Hoffmann Factor out SimpleSpiceDisplay initialization into qemu_spice_display_init_common() and call it from both qxl.c (for vga mode) and spice-display.c Signed-off-by: Gerd Hoffmann --- hw/qxl.c |7 +-- ui/spice-display.c | 17 +++-- ui/spice-display.h |1 + 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 545074d..2d46814 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -1321,12 +1321,7 @@ static int qxl_init_primary(PCIDevice *dev) vga->ds = graphic_console_init(qxl_hw_update, qxl_hw_invalidate, qxl_hw_screen_dump, qxl_hw_text_update, qxl); -qxl->ssd.ds = vga->ds; -qemu_mutex_init(&qxl->ssd.lock); -qxl->ssd.mouse_x = -1; -qxl->ssd.mouse_y = -1; -qxl->ssd.bufsize = (16 * 1024 * 1024); -qxl->ssd.buf = qemu_malloc(qxl->ssd.bufsize); +qemu_spice_display_init_common(&qxl->ssd, vga->ds); qxl0 = qxl; register_displaychangelistener(vga->ds, &display_listener); diff --git a/ui/spice-display.c b/ui/spice-display.c index 1e6a38f..93e25bf 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -286,6 +286,16 @@ void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason) ssd->running = running; } +void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds) +{ +ssd->ds = ds; +qemu_mutex_init(&ssd->lock); +ssd->mouse_x = -1; +ssd->mouse_y = -1; +ssd->bufsize = (16 * 1024 * 1024); +ssd->buf = qemu_malloc(ssd->bufsize); +} + /* display listener callbacks */ void qemu_spice_display_update(SimpleSpiceDisplay *ssd, @@ -499,12 +509,7 @@ static DisplayChangeListener display_listener = { void qemu_spice_display_init(DisplayState *ds) { assert(sdpy.ds == NULL); -sdpy.ds = ds; -qemu_mutex_init(&sdpy.lock); -sdpy.mouse_x = -1; -sdpy.mouse_y = -1; -sdpy.bufsize = (16 * 1024 * 1024); -sdpy.buf = qemu_malloc(sdpy.bufsize); +qemu_spice_display_init_common(&sdpy, ds); register_displaychangelistener(ds, &display_listener); sdpy.qxl.base.sif = &dpy_interface.base; diff --git a/ui/spice-display.h b/ui/spice-display.h index 5b06b11..eb7a573 100644 --- a/ui/spice-display.h +++ b/ui/spice-display.h @@ -75,6 +75,7 @@ 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_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds); void qemu_spice_display_update(SimpleSpiceDisplay *ssd, int x, int y, int w, int h); -- 1.7.6
[Qemu-devel] [PATCH v6 06/11] qxl: error handling fixes and cleanups.
From: Gerd Hoffmann Add qxl_guest_bug() function which is supposed to be called in case sanity checks of guest requests fail. It raises an error IRQ and logs a message in case guest debugging is enabled. Make PANIC_ON() abort instead of exit. That macro should be used for qemu bugs only, any guest-triggerable stuff should use the new qxl_guest_bug() function instead. Convert a few easy cases from PANIC_ON() to qxl_guest_bug() to show intended usage. Signed-off-by: Gerd Hoffmann --- hw/qxl.c | 34 ++ hw/qxl.h |3 ++- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/hw/qxl.c b/hw/qxl.c index 7d8b312..68ce409 100644 --- a/hw/qxl.c +++ b/hw/qxl.c @@ -125,6 +125,16 @@ static void qxl_reset_memslots(PCIQXLDevice *d); static void qxl_reset_surfaces(PCIQXLDevice *d); static void qxl_ring_set_dirty(PCIQXLDevice *qxl); +void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg) +{ +#if SPICE_INTERFACE_QXL_MINOR >= 1 +qxl_send_events(qxl, QXL_INTERRUPT_ERROR); +#endif +if (qxl->guestdebug) { +fprintf(stderr, "qxl-%d: guest bug: %s\n", qxl->id, msg); +} +} + void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, struct QXLRect *area, struct QXLRect *dirty_rects, @@ -1097,22 +1107,38 @@ static void ioport_write(void *opaque, uint32_t addr, uint32_t val) qxl_hard_reset(d, 0); break; case QXL_IO_MEMSLOT_ADD: -PANIC_ON(val >= NUM_MEMSLOTS); -PANIC_ON(d->guest_slots[val].active); +if (val >= NUM_MEMSLOTS) { +qxl_guest_bug(d, "QXL_IO_MEMSLOT_ADD: val out of range"); +break; +} +if (d->guest_slots[val].active) { +qxl_guest_bug(d, "QXL_IO_MEMSLOT_ADD: memory slot already active"); +break; +} d->guest_slots[val].slot = d->ram->mem_slot; qxl_add_memslot(d, val, 0); break; case QXL_IO_MEMSLOT_DEL: +if (val >= NUM_MEMSLOTS) { +qxl_guest_bug(d, "QXL_IO_MEMSLOT_DEL: val out of range"); +break; +} qxl_del_memslot(d, val); break; case QXL_IO_CREATE_PRIMARY: -PANIC_ON(val != 0); +if (val != 0) { +qxl_guest_bug(d, "QXL_IO_CREATE_PRIMARY: val != 0"); +break; +} dprint(d, 1, "QXL_IO_CREATE_PRIMARY\n"); d->guest_primary.surface = d->ram->create_surface; qxl_create_guest_primary(d, 0); break; case QXL_IO_DESTROY_PRIMARY: -PANIC_ON(val != 0); +if (val != 0) { +qxl_guest_bug(d, "QXL_IO_DESTROY_PRIMARY: val != 0"); +break; +} dprint(d, 1, "QXL_IO_DESTROY_PRIMARY (%s)\n", qxl_mode_to_string(d->mode)); qxl_destroy_primary(d); break; diff --git a/hw/qxl.h b/hw/qxl.h index 5d0e85e..5db9aae 100644 --- a/hw/qxl.h +++ b/hw/qxl.h @@ -86,7 +86,7 @@ typedef struct PCIQXLDevice { #define PANIC_ON(x) if ((x)) { \ printf("%s: PANIC %s failed\n", __FUNCTION__, #x); \ -exit(-1); \ +abort(); \ } #define dprint(_qxl, _level, _fmt, ...) \ @@ -99,6 +99,7 @@ typedef struct PCIQXLDevice { /* qxl.c */ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id); +void qxl_guest_bug(PCIQXLDevice *qxl, const char *msg); void qxl_spice_update_area(PCIQXLDevice *qxl, uint32_t surface_id, struct QXLRect *area, struct QXLRect *dirty_rects, -- 1.7.6
[Qemu-devel] [PATCH 1/5] xen: Fix xen_enabled().
Use the "host" CONFIG_ define instead of the "target" one. Signed-off-by: Anthony PERARD --- hw/xen.h |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/hw/xen.h b/hw/xen.h index e432705..43b95d6 100644 --- a/hw/xen.h +++ b/hw/xen.h @@ -24,7 +24,7 @@ extern int xen_allowed; static inline int xen_enabled(void) { -#ifdef CONFIG_XEN +#ifdef CONFIG_XEN_BACKEND return xen_allowed; #else return 0; -- Anthony PERARD
[Qemu-devel] [PATCH 0/5] Enable QEMU to handle more than 2GB with Xen.
Hi all, Xen is not limited by the QEMU's virtual address space for the allocation of the guest RAM. So even with a QEMU 32bits, a Xen guest can have more than 4 GB of RAM. With this serie, we will be able to run a guest with more than 4GB. The main point is to change ram_addr_t from ulong to uin64 when QEMU is configure with Xen. The second point is better register the memory in QEMU. Regards, Anthony PERARD (5): xen: Fix xen_enabled(). exec.c: Use ram_addr_t in cpu_physical_memory_rw(...). cpu-common: Have a ram_addr_t of uint64 with Xen. xen: Fix the memory registration to reflect of what is done by Xen. vl.c: Check the asked ram_size later. cpu-common.h |8 exec.c | 13 +++-- hw/xen.h |2 +- vl.c | 14 -- xen-all.c| 23 +++ 5 files changed, 39 insertions(+), 21 deletions(-) -- Anthony PERARD
[Qemu-devel] [PATCH 2/5] exec.c: Use ram_addr_t in cpu_physical_memory_rw(...).
As the variable pd and addr1 inside the function cpu_physical_memory_rw are mean to handle a RAM address, they should be of the ram_addr_t type instead of unsigned long. Signed-off-by: Anthony PERARD --- exec.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/exec.c b/exec.c index c0673c2..4220d45 100644 --- a/exec.c +++ b/exec.c @@ -3858,7 +3858,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, uint8_t *ptr; uint32_t val; target_phys_addr_t page; -unsigned long pd; +ram_addr_t pd; PhysPageDesc *p; while (len > 0) { @@ -3898,7 +3898,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, l = 1; } } else { -unsigned long addr1; +ram_addr_t addr1; addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); /* RAM case */ ptr = qemu_get_ram_ptr(addr1); -- Anthony PERARD
[Qemu-devel] [PATCH 3/5] cpu-common: Have a ram_addr_t of uint64 with Xen.
In Xen case, memory can be bigger than the host memory. that mean a 32bits host (and QEMU) should be able to handle a RAM address of 64bits. Signed-off-by: Anthony PERARD --- cpu-common.h |8 exec.c |9 + xen-all.c|2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/cpu-common.h b/cpu-common.h index e4fcded..e1b40fe 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -27,7 +27,15 @@ enum device_endian { }; /* address in the RAM (different from a physical address) */ +#ifndef CONFIG_XEN_BACKEND typedef unsigned long ram_addr_t; +# define RAM_ADDR_MAX ULONG_MAX +# define RAM_ADDR_FMT "%lx" +#else +typedef uint64_t ram_addr_t; +# define RAM_ADDR_MAX UINT64_MAX +# define RAM_ADDR_FMT "%" PRIx64 +#endif /* memory API */ diff --git a/exec.c b/exec.c index 4220d45..b671cfd 100644 --- a/exec.c +++ b/exec.c @@ -2863,13 +2863,13 @@ static void *file_ram_alloc(RAMBlock *block, static ram_addr_t find_ram_offset(ram_addr_t size) { RAMBlock *block, *next_block; -ram_addr_t offset = 0, mingap = ULONG_MAX; +ram_addr_t offset = 0, mingap = RAM_ADDR_MAX; if (QLIST_EMPTY(&ram_list.blocks)) return 0; QLIST_FOREACH(block, &ram_list.blocks, next) { -ram_addr_t end, next = ULONG_MAX; +ram_addr_t end, next = RAM_ADDR_MAX; end = block->offset + block->length; @@ -3081,7 +3081,8 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) #endif } if (area != vaddr) { -fprintf(stderr, "Could not remap addr: %lx@%lx\n", +fprintf(stderr, "Could not remap addr: " +RAM_ADDR_FMT "@" RAM_ADDR_FMT "\n", length, addr); exit(1); } @@ -4052,7 +4053,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, target_phys_addr_t page; unsigned long pd; PhysPageDesc *p; -ram_addr_t raddr = ULONG_MAX; +ram_addr_t raddr = RAM_ADDR_MAX; ram_addr_t rlen; void *ret; diff --git a/xen-all.c b/xen-all.c index 8105c83..2c0a62d 100644 --- a/xen-all.c +++ b/xen-all.c @@ -184,7 +184,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size) } if (xc_domain_populate_physmap_exact(xen_xc, xen_domid, nr_pfn, 0, 0, pfn_list)) { -hw_error("xen: failed to populate ram at %lx", ram_addr); +hw_error("xen: failed to populate ram at " RAM_ADDR_FMT, ram_addr); } qemu_free(pfn_list); -- Anthony PERARD
[Qemu-devel] [PATCH 5/5] vl.c: Check the asked ram_size later.
As a Xen guest can have more than 2GB of RAM on a 32bit host, we move the conditions after than we now if we run one Xen or not. Signed-off-by: Anthony PERARD --- vl.c | 14 -- 1 files changed, 8 insertions(+), 6 deletions(-) diff --git a/vl.c b/vl.c index fcd7395..c2efedf 100644 --- a/vl.c +++ b/vl.c @@ -2433,11 +2433,6 @@ int main(int argc, char **argv, char **envp) exit(1); } -/* On 32-bit hosts, QEMU is limited by virtual address space */ -if (value > (2047 << 20) && HOST_LONG_BITS == 32) { -fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n"); -exit(1); -} if (value != (uint64_t)(ram_addr_t)value) { fprintf(stderr, "qemu: ram size too large\n"); exit(1); @@ -3091,8 +3086,15 @@ int main(int argc, char **argv, char **envp) exit(1); /* init the memory */ -if (ram_size == 0) +if (ram_size == 0) { ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; +} else if (!xen_enabled()) { +/* On 32-bit hosts, QEMU is limited by virtual address space */ +if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) { +fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n"); +exit(1); +} +} /* init the dynamic translator */ cpu_exec_init_all(tb_size * 1024 * 1024); -- Anthony PERARD
[Qemu-devel] [PATCH 4/5] xen: Fix the memory registration to reflect of what is done by Xen.
A Xen guest memory is allocated by libxc. But this memory is not allocated continuously, instead, it leaves the VGA IO memory space not allocated, same for the MMIO space (at HVM_BELOW_4G_MMIO_START of size HVM_BELOW_4G_MMIO_LENGTH). So to reflect that, we do not register the physical memory for this two holes. But we still keep only one RAMBlock for the all RAM as it is more easier than have two separate blocks (1 above 4G). Also this prevent QEMU from use the MMIO space for a ROM. Signed-off-by: Anthony PERARD --- xen-all.c | 21 ++--- 1 files changed, 14 insertions(+), 7 deletions(-) diff --git a/xen-all.c b/xen-all.c index 2c0a62d..76d5c5c 100644 --- a/xen-all.c +++ b/xen-all.c @@ -144,6 +144,12 @@ static void xen_ram_init(ram_addr_t ram_size) new_block->host = NULL; new_block->offset = 0; new_block->length = ram_size; +if (ram_size >= HVM_BELOW_4G_RAM_END) { +/* Xen does not allocate the memory continuously, and keep a hole at + * HVM_BELOW_4G_MMIO_START of HVM_BELOW_4G_MMIO_LENGTH + */ +new_block->length += HVM_BELOW_4G_MMIO_LENGTH; +} QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next); @@ -152,20 +158,21 @@ static void xen_ram_init(ram_addr_t ram_size) memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS), 0xff, new_block->length >> TARGET_PAGE_BITS); -if (ram_size >= 0xe000 ) { -above_4g_mem_size = ram_size - 0xe000; -below_4g_mem_size = 0xe000; +if (ram_size >= HVM_BELOW_4G_RAM_END) { +above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END; +below_4g_mem_size = HVM_BELOW_4G_RAM_END; } else { below_4g_mem_size = ram_size; } -cpu_register_physical_memory(0, below_4g_mem_size, new_block->offset); -#if TARGET_PHYS_ADDR_BITS > 32 +cpu_register_physical_memory(0, 0xa, 0); +/* Skip of the VGA IO memory space */ +cpu_register_physical_memory(0xc, below_4g_mem_size - 0xc, + 0xc); if (above_4g_mem_size > 0) { cpu_register_physical_memory(0x1ULL, above_4g_mem_size, - new_block->offset + below_4g_mem_size); + 0x1ULL); } -#endif } void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size) -- Anthony PERARD
Re: [Qemu-devel] [PATCH 2/5] exec.c: Use ram_addr_t in cpu_physical_memory_rw(...).
On 07/15/2011 04:32 PM, Anthony PERARD wrote: As the variable pd and addr1 inside the function cpu_physical_memory_rw are mean to handle a RAM address, they should be of the ram_addr_t type instead of unsigned long. Signed-off-by: Anthony PERARD --- exec.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/exec.c b/exec.c index c0673c2..4220d45 100644 --- a/exec.c +++ b/exec.c @@ -3858,7 +3858,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, uint8_t *ptr; uint32_t val; target_phys_addr_t page; -unsigned long pd; +ram_addr_t pd; PhysPageDesc *p; while (len> 0) { @@ -3898,7 +3898,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, l = 1; } } else { -unsigned long addr1; +ram_addr_t addr1; addr1 = (pd& TARGET_PAGE_MASK) + (addr& ~TARGET_PAGE_MASK); /* RAM case */ ptr = qemu_get_ram_ptr(addr1); Acked-by: Paolo Bonzini Paolo
Re: [Qemu-devel] [PATCH 1/5] xen: Fix xen_enabled().
On 07/15/2011 04:32 PM, Anthony PERARD wrote: Use the "host" CONFIG_ define instead of the "target" one. Signed-off-by: Anthony PERARD --- hw/xen.h |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/hw/xen.h b/hw/xen.h index e432705..43b95d6 100644 --- a/hw/xen.h +++ b/hw/xen.h @@ -24,7 +24,7 @@ extern int xen_allowed; static inline int xen_enabled(void) { -#ifdef CONFIG_XEN +#ifdef CONFIG_XEN_BACKEND return xen_allowed; #else return 0; Acked-by: Paolo Bonzini Paolo
Re: [Qemu-devel] [PATCH 5/5] vl.c: Check the asked ram_size later.
On 07/15/2011 04:32 PM, Anthony PERARD wrote: As a Xen guest can have more than 2GB of RAM on a 32bit host, we move the conditions after than we now if we run one Xen or not. Signed-off-by: Anthony PERARD --- vl.c | 14 -- 1 files changed, 8 insertions(+), 6 deletions(-) diff --git a/vl.c b/vl.c index fcd7395..c2efedf 100644 --- a/vl.c +++ b/vl.c @@ -2433,11 +2433,6 @@ int main(int argc, char **argv, char **envp) exit(1); } -/* On 32-bit hosts, QEMU is limited by virtual address space */ -if (value> (2047<< 20)&& HOST_LONG_BITS == 32) { -fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n"); -exit(1); -} if (value != (uint64_t)(ram_addr_t)value) { fprintf(stderr, "qemu: ram size too large\n"); exit(1); @@ -3091,8 +3086,15 @@ int main(int argc, char **argv, char **envp) exit(1); /* init the memory */ -if (ram_size == 0) +if (ram_size == 0) { ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; +} else if (!xen_enabled()) { +/* On 32-bit hosts, QEMU is limited by virtual address space */ +if (ram_size> (2047<< 20)&& HOST_LONG_BITS == 32) { +fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n"); +exit(1); +} +} /* init the dynamic translator */ cpu_exec_init_all(tb_size * 1024 * 1024); Acked-by: Paolo Bonzini Paolo
[Qemu-devel] [PATCH 00/12] bugfix and qdevify NAND and ONENAND devices
This patchseries is more goodies from the Meego tree. Specifically, various bug fixes to hw/nand and hw/onenand, plus conversion of both to sysbus. [An advance note on the next thing due to come out of the pipe: qdeving nand and onenand allows us to move to qdevification of omap_gpmc, which takes both of those (and other things) as 'downstream' devices. That change will make it accept arbitrary SysBus devices as its 'downstream' devices rather than the current setup of taking an opaque pointer and a pair of resize/unmap function pointers. (There are also patches which add NAND support so you can tell omap_gpmc "this is a NAND device" and it then uses the nand_setpins/nand_getpins/nand_setio interface.) The rationale for using SysBus there rather than defining some new kind of bus is that you want to be able to plug any random thing into it; for instance the Overo board has a lan9118 ethernet controller hanging off the GPMC. ] A note on dependencies: * This patch depends on the omap gpio patchset (although more textually than seriously semantically) * the six nand patches and the six onenand patches are broadly independent of each other Juha Riihimäki (9): hw/nand: Support large NAND devices hw/nand: Support devices wider than 8 bits hw/nand: Support multiple reads following READ STATUS hw/nand: qdevify onenand: Handle various ID fields separately onenand: Ignore zero writes to boot command space hw/onenand: program actions can only clear bits hw/sysbus: Add sysbus_mmio_unmap() for unmapping a region hw/onenand: qdevify Peter Maydell (3): hw/nand: Pass block device state to init function hw/nand: Writing to NAND can only clear bits onenand: Pass BlockDriverState to init function hw/axis_dev88.c |8 +- hw/flash.h | 19 ++-- hw/nand.c | 345 --- hw/nseries.c| 13 ++- hw/onenand.c| 373 +++ hw/spitz.c |6 +- hw/sysbus.c | 17 +++ hw/sysbus.h |1 + hw/tc6393xb.c |7 +- 9 files changed, 561 insertions(+), 228 deletions(-)
Re: [Qemu-devel] [PATCH 4/5] xen: Fix the memory registration to reflect of what is done by Xen.
On 07/15/2011 04:32 PM, Anthony PERARD wrote: A Xen guest memory is allocated by libxc. But this memory is not allocated continuously, instead, it leaves the VGA IO memory space not allocated, same for the MMIO space (at HVM_BELOW_4G_MMIO_START of size HVM_BELOW_4G_MMIO_LENGTH). So to reflect that, we do not register the physical memory for this two holes. But we still keep only one RAMBlock for the all RAM as it is more easier than have two separate blocks (1 above 4G). Also this prevent QEMU from use the MMIO space for a ROM. Signed-off-by: Anthony PERARD --- xen-all.c | 21 ++--- 1 files changed, 14 insertions(+), 7 deletions(-) diff --git a/xen-all.c b/xen-all.c index 2c0a62d..76d5c5c 100644 --- a/xen-all.c +++ b/xen-all.c @@ -144,6 +144,12 @@ static void xen_ram_init(ram_addr_t ram_size) new_block->host = NULL; new_block->offset = 0; new_block->length = ram_size; +if (ram_size>= HVM_BELOW_4G_RAM_END) { +/* Xen does not allocate the memory continuously, and keep a hole at + * HVM_BELOW_4G_MMIO_START of HVM_BELOW_4G_MMIO_LENGTH + */ +new_block->length += HVM_BELOW_4G_MMIO_LENGTH; +} QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next); @@ -152,20 +158,21 @@ static void xen_ram_init(ram_addr_t ram_size) memset(ram_list.phys_dirty + (new_block->offset>> TARGET_PAGE_BITS), 0xff, new_block->length>> TARGET_PAGE_BITS); -if (ram_size>= 0xe000 ) { -above_4g_mem_size = ram_size - 0xe000; -below_4g_mem_size = 0xe000; +if (ram_size>= HVM_BELOW_4G_RAM_END) { +above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END; +below_4g_mem_size = HVM_BELOW_4G_RAM_END; } else { below_4g_mem_size = ram_size; } -cpu_register_physical_memory(0, below_4g_mem_size, new_block->offset); -#if TARGET_PHYS_ADDR_BITS> 32 +cpu_register_physical_memory(0, 0xa, 0); +/* Skip of the VGA IO memory space */ +cpu_register_physical_memory(0xc, below_4g_mem_size - 0xc, + 0xc); if (above_4g_mem_size> 0) { cpu_register_physical_memory(0x1ULL, above_4g_mem_size, - new_block->offset + below_4g_mem_size); + 0x1ULL); } -#endif } void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size) Acked-by: Paolo Bonzini Paolo
[Qemu-devel] [PATCH 08/12] onenand: Handle various ID fields separately
From: Juha Riihimäki Handle the manufacturer, device and version IDs separately rather than smooshing them all together into a single uint32_t. Note that the ID registers are actually 16 bit, even though typically the top bits are 0 and the Read Identification Data command only returns the bottom 8 bits. Signed-off-by: Juha Riihimäki [Riku Voipio: Fixes and restructuring patchset] Signed-off-by: Riku Voipio [Peter Maydell: More fixes and cleanups for upstream submission] Signed-off-by: Peter Maydell --- hw/flash.h |3 ++- hw/nseries.c |5 +++-- hw/onenand.c | 29 ++--- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/hw/flash.h b/hw/flash.h index 1aae43d..1064fd0 100644 --- a/hw/flash.h +++ b/hw/flash.h @@ -38,7 +38,8 @@ uint32_t nand_getbuswidth(DeviceState *dev); /* onenand.c */ void onenand_base_update(void *opaque, target_phys_addr_t new); void onenand_base_unmap(void *opaque); -void *onenand_init(BlockDriverState *bdrv, uint32_t id, +void *onenand_init(BlockDriverState *bdrv, + uint16_t man_id, uint16_t dev_id, uint16_t ver_id, int regshift, qemu_irq irq); void *onenand_raw_otp(void *opaque); diff --git a/hw/nseries.c b/hw/nseries.c index 4fef05d..9b8d338 100644 --- a/hw/nseries.c +++ b/hw/nseries.c @@ -167,8 +167,9 @@ static void n8x0_nand_setup(struct n800_s *s) DriveInfo *dinfo; dinfo = drive_get(IF_MTD, 0, 0); -/* Either ec40xx or ec48xx are OK for the ID */ -s->nand = onenand_init(dinfo ? dinfo->bdrv : 0, 0xec4800, 1, +/* Either 0x40 or 0x48 are OK for the device ID */ +s->nand = onenand_init(dinfo ? dinfo->bdrv : 0, + NAND_MFR_SAMSUNG, 0x48, 0, 1, qdev_get_gpio_in(s->cpu->gpio, N8X0_ONENAND_GPIO)); omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, 0, onenand_base_update, onenand_base_unmap, s->nand); diff --git a/hw/onenand.c b/hw/onenand.c index 3a19d7f..9f02736 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -31,7 +31,11 @@ #define BLOCK_SHIFT(PAGE_SHIFT + 6) typedef struct { -uint32_t id; +struct { +uint16_t man; +uint16_t dev; +uint16_t ver; +} id; int shift; target_phys_addr_t base; qemu_irq intr; @@ -453,12 +457,12 @@ static uint32_t onenand_read(void *opaque, target_phys_addr_t addr) return lduw_le_p(s->boot[0] + addr); case 0xf000: /* Manufacturer ID */ -return (s->id >> 16) & 0xff; +return s->id.man; case 0xf001: /* Device ID */ -return (s->id >> 8) & 0xff; -/* TODO: get the following values from a real chip! */ +return s->id.dev; case 0xf002: /* Version ID */ -return (s->id >> 0) & 0xff; +return s->id.ver; +/* TODO: get the following values from a real chip! */ case 0xf003: /* Data Buffer size */ return 1 << PAGE_SHIFT; case 0xf004: /* Boot Buffer size */ @@ -541,8 +545,8 @@ static void onenand_write(void *opaque, target_phys_addr_t addr, case 0x0090: /* Read Identification Data */ memset(s->boot[0], 0, 3 << s->shift); -s->boot[0][0 << s->shift] = (s->id >> 16) & 0xff; -s->boot[0][1 << s->shift] = (s->id >> 8) & 0xff; +s->boot[0][0 << s->shift] = s->id.man & 0xff; +s->boot[0][1 << s->shift] = s->id.dev & 0xff; s->boot[0][2 << s->shift] = s->wpstatus & 0xff; break; @@ -615,21 +619,24 @@ static CPUWriteMemoryFunc * const onenand_writefn[] = { onenand_write, }; -void *onenand_init(BlockDriverState *bdrv, uint32_t id, +void *onenand_init(BlockDriverState *bdrv, + uint16_t man_id, uint16_t dev_id, uint16_t ver_id, int regshift, qemu_irq irq) { OneNANDState *s = (OneNANDState *) qemu_mallocz(sizeof(*s)); -uint32_t size = 1 << (24 + ((id >> 12) & 7)); +uint32_t size = 1 << (24 + ((dev_id >> 4) & 7)); void *ram; s->shift = regshift; s->intr = irq; s->rdy = NULL; -s->id = id; +s->id.man = man_id; +s->id.dev = dev_id; +s->id.ver = ver_id; s->blocks = size >> BLOCK_SHIFT; s->secs = size >> 9; s->blockwp = qemu_malloc(s->blocks); -s->density_mask = (id & (1 << 11)) ? (1 << (6 + ((id >> 12) & 7))) : 0; +s->density_mask = (dev_id & 0x08) ? (1 << (6 + ((dev_id >> 4) & 7))) : 0; s->iomemtype = cpu_register_io_memory(onenand_readfn, onenand_writefn, s, DEVICE_NATIVE_ENDIAN); s->bdrv = bdrv; -- 1.7.1
[Qemu-devel] [PATCH 10/12] hw/onenand: program actions can only clear bits
From: Juha Riihimäki The program actions onenand_prog_main() and onenand_prog_spare() can only set bits. This implies a rewrite of onenand_erase() to not use the program functions, since erase does need to set bits. Signed-off-by: Juha Riihimäki [Riku Voipio: Fixes and restructuring patchset] Signed-off-by: Riku Voipio [Peter Maydell: More fixes and cleanups for upstream submission] Signed-off-by: Peter Maydell --- hw/onenand.c | 135 + 1 files changed, 106 insertions(+), 29 deletions(-) diff --git a/hw/onenand.c b/hw/onenand.c index 0edcfe2..981d23c 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -179,14 +179,39 @@ static inline int onenand_load_main(OneNANDState *s, int sec, int secn, static inline int onenand_prog_main(OneNANDState *s, int sec, int secn, void *src) { -if (s->bdrv_cur) -return bdrv_write(s->bdrv_cur, sec, src, secn) < 0; -else if (sec + secn > s->secs_cur) -return 1; - -memcpy(s->current + (sec << 9), src, secn << 9); +int result = 0; + +if (secn > 0) { +uint32_t size = (uint32_t)secn * 512; +const uint8_t *sp = (const uint8_t *)src; +uint8_t *dp = 0; +if (s->bdrv_cur) { +dp = qemu_malloc(size); +if (!dp || bdrv_read(s->bdrv_cur, sec, dp, secn) < 0) { +result = 1; +} +} else { +if (sec + secn > s->secs_cur) { +result = 1; +} else { +dp = (uint8_t *)s->current + (sec << 9); +} +} +if (!result) { +uint32_t i; +for (i = 0; i < size; i++) { +dp[i] &= sp[i]; +} +if (s->bdrv_cur) { +result = bdrv_write(s->bdrv_cur, sec, dp, secn) < 0; +} +} +if (dp && s->bdrv_cur) { +qemu_free(dp); +} +} -return 0; +return result; } static inline int onenand_load_spare(OneNANDState *s, int sec, int secn, @@ -209,35 +234,87 @@ static inline int onenand_load_spare(OneNANDState *s, int sec, int secn, static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn, void *src) { -uint8_t buf[512]; - -if (s->bdrv_cur) { -if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0) -return 1; -memcpy(buf + ((sec & 31) << 4), src, secn << 4); -return bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0; -} else if (sec + secn > s->secs_cur) -return 1; - -memcpy(s->current + (s->secs_cur << 9) + (sec << 4), src, secn << 4); - -return 0; +int result = 0; +if (secn > 0) { +const uint8_t *sp = (const uint8_t *)src; +uint8_t *dp = 0, *dpp = 0; +if (s->bdrv_cur) { +dp = qemu_malloc(512); +if (!dp || bdrv_read(s->bdrv_cur, + s->secs_cur + (sec >> 5), + dp, 1) < 0) { +result = 1; +} else { +dpp = dp + ((sec & 31) << 4); +} +} else { +if (sec + secn > s->secs_cur) { +result = 1; +} else { +dpp = s->current + (s->secs_cur << 9) + (sec << 4); +} +} +if (!result) { +uint32_t i; +for (i = 0; i < (secn << 4); i++) { +dpp[i] &= sp[i]; +} +if (s->bdrv_cur) { +result = bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5), +dp, 1) < 0; +} +} +if (dp) { +qemu_free(dp); +} +} +return result; } static inline int onenand_erase(OneNANDState *s, int sec, int num) { -/* TODO: optimise */ -uint8_t buf[512]; - -memset(buf, 0xff, sizeof(buf)); -for (; num > 0; num --, sec ++) { -if (onenand_prog_main(s, sec, 1, buf)) -return 1; -if (onenand_prog_spare(s, sec, 1, buf)) -return 1; +uint8_t *blankbuf, *tmpbuf; +blankbuf = qemu_malloc(512); +if (!blankbuf) { +return 1; +} +tmpbuf = qemu_malloc(512); +if (!tmpbuf) { +qemu_free(blankbuf); +return 1; +} +memset(blankbuf, 0xff, 512); +for (; num > 0; num--, sec++) { +if (s->bdrv_cur) { +int erasesec = s->secs_cur + (sec >> 5); +if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1)) { +goto fail; +} +if (bdrv_read(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) { +goto fail; +} +memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4); +if (bdrv_write(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) { +goto fail; +} +} else { +if (sec + 1 > s->secs_cur) { +goto f
[Qemu-devel] [PATCH 06/12] hw/nand: qdevify
From: Juha Riihimäki Qdevify the NAND device. Signed-off-by: Juha Riihimäki [Riku Voipio: Fixes and restructuring patchset] Signed-off-by: Riku Voipio [Peter Maydell: More fixes and cleanups for upstream submission] Signed-off-by: Peter Maydell --- hw/axis_dev88.c |2 +- hw/flash.h | 14 ++--- hw/nand.c | 164 +++ hw/spitz.c |2 +- hw/tc6393xb.c |2 +- 5 files changed, 102 insertions(+), 82 deletions(-) diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c index de1f5a5..e0a8c14 100644 --- a/hw/axis_dev88.c +++ b/hw/axis_dev88.c @@ -37,7 +37,7 @@ struct nand_state_t { -NANDFlashState *nand; +DeviceState *nand; unsigned int rdy:1; unsigned int ale:1; unsigned int cle:1; diff --git a/hw/flash.h b/hw/flash.h index 132ad29..43260ce 100644 --- a/hw/flash.h +++ b/hw/flash.h @@ -18,15 +18,13 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, int be); /* nand.c */ -typedef struct NANDFlashState NANDFlashState; -NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id); -void nand_done(NANDFlashState *s); -void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale, +DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id); +void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale, uint8_t ce, uint8_t wp, uint8_t gnd); -void nand_getpins(NANDFlashState *s, int *rb); -void nand_setio(NANDFlashState *s, uint32_t value); -uint32_t nand_getio(NANDFlashState *s); -uint32_t nand_getbuswidth(NANDFlashState *s); +void nand_getpins(DeviceState *dev, int *rb); +void nand_setio(DeviceState *dev, uint32_t value); +uint32_t nand_getio(DeviceState *dev); +uint32_t nand_getbuswidth(DeviceState *dev); #define NAND_MFR_TOSHIBA 0x98 #define NAND_MFR_SAMSUNG 0xec diff --git a/hw/nand.c b/hw/nand.c index d068eb6..2f5a40e 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -18,6 +18,7 @@ # include "hw.h" # include "flash.h" # include "blockdev.h" +# include "sysbus.h" # define NAND_CMD_READ00x00 # define NAND_CMD_READ10x01 @@ -47,7 +48,9 @@ # define MAX_PAGE 0x800 # define MAX_OOB 0x40 +typedef struct NANDFlashState NANDFlashState; struct NANDFlashState { +SysBusDevice busdev; uint8_t manf_id, chip_id; uint8_t buswidth; /* in BYTES */ int size, pages; @@ -215,8 +218,9 @@ static const struct { [0xc5] = { 2048, 16, 0, 0, LP_OPTIONS16 }, }; -static void nand_reset(NANDFlashState *s) +static void nand_reset(DeviceState *dev) { +NANDFlashState *s = FROM_SYSBUS(NANDFlashState, sysbus_from_qdev(dev)); s->cmd = NAND_CMD_READ0; s->addr = 0; s->addrlen = 0; @@ -270,7 +274,7 @@ static void nand_command(NANDFlashState *s) break; case NAND_CMD_RESET: -nand_reset(s); +nand_reset(&s->busdev.qdev); break; case NAND_CMD_PAGEPROGRAM1: @@ -354,15 +358,84 @@ static const VMStateDescription vmstate_nand = { } }; +static int nand_device_init(SysBusDevice *dev) +{ +int pagesize; +NANDFlashState *s = FROM_SYSBUS(NANDFlashState, dev); +s->buswidth = nand_flash_ids[s->chip_id].width >> 3; +s->size = nand_flash_ids[s->chip_id].size << 20; +if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) { +s->page_shift = 11; +s->erase_shift = 6; +} else { +s->page_shift = nand_flash_ids[s->chip_id].page_shift; +s->erase_shift = nand_flash_ids[s->chip_id].erase_shift; +} + +switch (1 << s->page_shift) { +case 256: +nand_init_256(s); +break; +case 512: +nand_init_512(s); +break; +case 2048: +nand_init_2048(s); +break; +default: +hw_error("%s: Unsupported NAND block size.\n", __func__); +} + +pagesize = 1 << s->oob_shift; +s->mem_oob = 1; +if (s->bdrv && bdrv_getlength(s->bdrv) >= +(s->pages << s->page_shift) + (s->pages << s->oob_shift)) { +pagesize = 0; +s->mem_oob = 0; +} + +if (!s->bdrv) { +pagesize += 1 << s->page_shift; +} +if (pagesize) { +s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize), +0xff, s->pages * pagesize); +} +/* Give s->ioaddr a sane value in case we save state before it is used. */ +s->ioaddr = s->io; + +return 0; +} + +static SysBusDeviceInfo nand_info = { +.init = nand_device_init, +.qdev.name = "nand", +.qdev.size = sizeof(NANDFlashState), +.qdev.reset = nand_reset, +.qdev.vmsd = &vmstate_nand, +.qdev.props = (Property[]) { +DEFINE_PROP_UINT8("manufacturer_id", NANDFlashState, manf_id, 0), +DEFINE_PROP_UINT8("chip_id", NANDFlashState, chip_id, 0), +DEFINE_PROP_DRIVE("drive", NANDFlashState, bdrv), +DEFINE_
[Qemu-devel] [PATCH 09/12] onenand: Ignore zero writes to boot command space
From: Juha Riihimäki Ignore zero writes to the boot command space; Linux will issue these in the powerdown/reset sequence. Signed-off-by: Juha Riihimäki [Riku Voipio: Fixes and restructuring patchset] Signed-off-by: Riku Voipio [Peter Maydell: More fixes and cleanups for upstream submission] Signed-off-by: Peter Maydell --- hw/onenand.c |7 +++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/hw/onenand.c b/hw/onenand.c index 9f02736..0edcfe2 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -550,6 +550,13 @@ static void onenand_write(void *opaque, target_phys_addr_t addr, s->boot[0][2 << s->shift] = s->wpstatus & 0xff; break; +case 0x: +/* ignore zero writes without error messages, + * linux omap2/3 kernel will issue these upon + * powerdown/reset sequence. + */ +break; + default: fprintf(stderr, "%s: unknown OneNAND boot command %x\n", __FUNCTION__, value); -- 1.7.1
[Qemu-devel] [PATCH 11/12] hw/sysbus: Add sysbus_mmio_unmap() for unmapping a region
From: Juha Riihimäki Add support for unmapping a SysBus device's mmio region, via a new function sysbus_mmio_unmap(). This simply reverses the effect of sysbus_mmio_map(). Signed-off-by: Juha Riihimäki Signed-off-by: Peter Maydell --- hw/sysbus.c | 17 + hw/sysbus.h |1 + 2 files changed, 18 insertions(+), 0 deletions(-) diff --git a/hw/sysbus.c b/hw/sysbus.c index 2e22be7..021c653 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -39,6 +39,23 @@ void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) } } +void sysbus_mmio_unmap(SysBusDevice *dev, int n) +{ +assert(n >= 0 && n < dev->num_mmio); + +if (dev->mmio[n].addr == (target_phys_addr_t)-1) { +/* region already unmapped */ +return; +} +if (dev->mmio[n].cb) { +dev->mmio[n].cb(dev, (target_phys_addr_t)-1); +} else { +cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size, + IO_MEM_UNASSIGNED); +} +dev->mmio[n].addr = (target_phys_addr_t)-1; +} + void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr) { assert(n >= 0 && n < dev->num_mmio); diff --git a/hw/sysbus.h b/hw/sysbus.h index 4e8cb16..4f93b70 100644 --- a/hw/sysbus.h +++ b/hw/sysbus.h @@ -53,6 +53,7 @@ void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size); void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq); void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr); +void sysbus_mmio_unmap(SysBusDevice *dev, int n); /* Legacy helper function for creating devices. */ DeviceState *sysbus_create_varargs(const char *name, -- 1.7.1
[Qemu-devel] [PATCH 05/12] hw/nand: Writing to NAND can only clear bits
Writing to a NAND device cannot set bits, it can only clear them; implement this rather than simply copying the data. Signed-off-by: Peter Maydell --- hw/nand.c | 17 + 1 files changed, 13 insertions(+), 4 deletions(-) diff --git a/hw/nand.c b/hw/nand.c index e6c551d..d068eb6 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -75,6 +75,15 @@ struct NANDFlashState { uint32_t ioaddr_vmstate; }; +static void mem_and(uint8_t *dest, const uint8_t *src, size_t n) +{ +/* Like memcpy() but we logical-AND the data into the destination */ +int i; +for (i = 0; i < n; i++) { +dest[i] &= src[i]; +} +} + # define NAND_NO_AUTOINCR 0x0001 # define NAND_BUSWIDTH_16 0x0002 # define NAND_NO_PADDING 0x0004 @@ -595,7 +604,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) return; if (!s->bdrv) { -memcpy(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) + +mem_and(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset, s->io, s->iolen); } else if (s->mem_oob) { sector = SECTOR(s->addr); @@ -606,10 +615,10 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) return; } -memcpy(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off)); +mem_and(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off)); if (off + s->iolen > PAGE_SIZE) { page = PAGE(s->addr); -memcpy(s->storage + (page << OOB_SHIFT), s->io + PAGE_SIZE - off, +mem_and(s->storage + (page << OOB_SHIFT), s->io + PAGE_SIZE - off, MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE)); } @@ -624,7 +633,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) return; } -memcpy(iobuf + soff, s->io, s->iolen); +mem_and(iobuf + soff, s->io, s->iolen); if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1) printf("%s: write error in sector %" PRIu64 "\n", __func__, sector); -- 1.7.1
[Qemu-devel] [PATCH 02/12] hw/nand: Support large NAND devices
From: Juha Riihimäki Add support for NAND devices of over 1Gb. Signed-off-by: Juha Riihimäki [Riku Voipio: Fixes and restructuring patchset] Signed-off-by: Riku Voipio [Peter Maydell: More fixes and cleanups for upstream submission] Signed-off-by: Peter Maydell --- hw/nand.c | 48 +++- 1 files changed, 27 insertions(+), 21 deletions(-) diff --git a/hw/nand.c b/hw/nand.c index d6204d9..18aa226 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -6,6 +6,10 @@ * Copyright (c) 2006 Openedhand Ltd. * Written by Andrzej Zaborowski * + * Support for additional features based on "MT29F2G16ABCWP 2Gx16" + * datasheet from Micron Technology and "NAND02G-B2C" datasheet + * from ST Microelectronics. + * * This code is licensed under the GNU GPL v2. */ @@ -57,14 +61,15 @@ struct NANDFlashState { uint8_t *ioaddr; int iolen; -uint32_t cmd, addr; +uint32_t cmd; +uint64_t addr; int addrlen; int status; int offset; void (*blk_write)(NANDFlashState *s); void (*blk_erase)(NANDFlashState *s); -void (*blk_load)(NANDFlashState *s, uint32_t addr, int offset); +void (*blk_load)(NANDFlashState *s, uint64_t addr, int offset); uint32_t ioaddr_vmstate; }; @@ -318,7 +323,7 @@ static const VMStateDescription vmstate_nand = { VMSTATE_UINT32(ioaddr_vmstate, NANDFlashState), VMSTATE_INT32(iolen, NANDFlashState), VMSTATE_UINT32(cmd, NANDFlashState), -VMSTATE_UINT32(addr, NANDFlashState), +VMSTATE_UINT64(addr, NANDFlashState), VMSTATE_INT32(addrlen, NANDFlashState), VMSTATE_INT32(status, NANDFlashState), VMSTATE_INT32(offset, NANDFlashState), @@ -432,7 +437,7 @@ uint8_t nand_getio(NANDFlashState *s) /* Allow sequential reading */ if (!s->iolen && s->cmd == NAND_CMD_READ0) { -offset = (s->addr & ((1 << s->addr_shift) - 1)) + s->offset; +offset = (int)(s->addr & ((1 << s->addr_shift) - 1)) + s->offset; s->offset = 0; s->blk_load(s, s->addr, offset); @@ -526,7 +531,7 @@ void nand_done(NANDFlashState *s) /* Program a single page */ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) { -uint32_t off, page, sector, soff; +uint64_t off, page, sector, soff; uint8_t iobuf[(PAGE_SECTORS + 2) * 0x200]; if (PAGE(s->addr) >= s->pages) return; @@ -539,7 +544,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) off = (s->addr & PAGE_MASK) + s->offset; soff = SECTOR_OFFSET(s->addr); if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1) { -printf("%s: read error in sector %i\n", __FUNCTION__, sector); +printf("%s: read error in sector %" PRIu64 "\n", __func__, sector); return; } @@ -551,20 +556,20 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) } if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1) -printf("%s: write error in sector %i\n", __FUNCTION__, sector); +printf("%s: write error in sector %" PRIu64 "\n", __func__, sector); } else { off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset; sector = off >> 9; soff = off & 0x1ff; if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1) { -printf("%s: read error in sector %i\n", __FUNCTION__, sector); +printf("%s: read error in sector %" PRIu64 "\n", __func__, sector); return; } memcpy(iobuf + soff, s->io, s->iolen); if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1) -printf("%s: write error in sector %i\n", __FUNCTION__, sector); +printf("%s: write error in sector %" PRIu64 "\n", __func__, sector); } s->offset = 0; } @@ -572,7 +577,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) /* Erase a single block */ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s) { -uint32_t i, page, addr; +uint64_t i, page, addr; uint8_t iobuf[0x200] = { [0 ... 0x1ff] = 0xff, }; addr = s->addr & ~((1 << (ADDR_SHIFT + s->erase_shift)) - 1); @@ -589,34 +594,35 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s) page = SECTOR(addr + (ADDR_SHIFT + s->erase_shift)); for (; i < page; i ++) if (bdrv_write(s->bdrv, i, iobuf, 1) == -1) -printf("%s: write error in sector %i\n", __FUNCTION__, i); +printf("%s: write error in sector %" PRIu64 "\n", __func__, i); } else { addr = PAGE_START(addr); page = addr >> 9; if (bdrv_read(s->bdrv, page, iobuf, 1) == -1) -printf("%s: read error in sector %i\n", __FUNCTION__, page); +printf("%s: read error in sector %" PRIu64 "\n", __func__, page); memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0
[Qemu-devel] live snapshot wiki updated
Hi, I have been updating the live snapshot wiki for qemu to try and cover the commands we will want for async snapshot handling too. http://wiki.qemu.org/Features/Snapshots Cheers, Jes
[Qemu-devel] [PATCH 04/12] hw/nand: Support multiple reads following READ STATUS
From: Juha Riihimäki After receiving READ STATUS command all subsequent IO reads should return the status register value until another command is issued. Signed-off-by: Juha Riihimäki [Riku Voipio: Fixes and restructuring patchset] Signed-off-by: Riku Voipio [Peter Maydell: More fixes and cleanups for upstream submission] Signed-off-by: Peter Maydell --- hw/nand.c | 11 --- 1 files changed, 8 insertions(+), 3 deletions(-) diff --git a/hw/nand.c b/hw/nand.c index 2e98f25..e6c551d 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -496,9 +496,14 @@ uint32_t nand_getio(NANDFlashState *s) for (offset = s->buswidth; offset--;) { x |= s->ioaddr[offset] << (offset << 3); } -s->addr += s->buswidth; -s->ioaddr += s->buswidth; -s->iolen -= s->buswidth; +/* after receiving READ STATUS command all subsequent reads will + * return the status register value until another command is issued + */ +if (s->cmd != NAND_CMD_READSTATUS) { +s->addr += s->buswidth; +s->ioaddr += s->buswidth; +s->iolen -= s->buswidth; +} return x; } -- 1.7.1
[Qemu-devel] [PATCH 12/12] hw/onenand: qdevify
From: Juha Riihimäki Qdevify the ONENAND device. Signed-off-by: Juha Riihimäki [Riku Voipio: Fixes and restructuring patchset] Signed-off-by: Riku Voipio [Peter Maydell: More fixes and cleanups for upstream submission] Signed-off-by: Peter Maydell --- hw/flash.h |8 +- hw/onenand.c | 208 +- 2 files changed, 167 insertions(+), 49 deletions(-) diff --git a/hw/flash.h b/hw/flash.h index 1064fd0..bbf397a 100644 --- a/hw/flash.h +++ b/hw/flash.h @@ -38,10 +38,10 @@ uint32_t nand_getbuswidth(DeviceState *dev); /* onenand.c */ void onenand_base_update(void *opaque, target_phys_addr_t new); void onenand_base_unmap(void *opaque); -void *onenand_init(BlockDriverState *bdrv, - uint16_t man_id, uint16_t dev_id, uint16_t ver_id, - int regshift, qemu_irq irq); -void *onenand_raw_otp(void *opaque); +DeviceState *onenand_init(BlockDriverState *bdrv, + uint16_t man_id, uint16_t dev_id, uint16_t ver_id, + int regshift, qemu_irq irq); +void *onenand_raw_otp(DeviceState *onenand_device); /* ecc.c */ typedef struct { diff --git a/hw/onenand.c b/hw/onenand.c index 981d23c..16fd29a 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -23,6 +23,7 @@ #include "flash.h" #include "irq.h" #include "blockdev.h" +#include "sysbus.h" /* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */ #define PAGE_SHIFT 11 @@ -31,6 +32,7 @@ #define BLOCK_SHIFT(PAGE_SHIFT + 6) typedef struct { +SysBusDevice busdev; struct { uint16_t man; uint16_t dev; @@ -45,6 +47,7 @@ typedef struct { uint8_t *image; uint8_t *otp; uint8_t *current; +uint8_t current_direction; ram_addr_t ram; uint8_t *boot[2]; uint8_t *data[2][2]; @@ -100,31 +103,45 @@ enum { ONEN_LOCK_UNLOCKED = 1 << 2, }; -void onenand_base_update(void *opaque, target_phys_addr_t new) +static void onenand_base_updatefn(SysBusDevice *dev, target_phys_addr_t new) { -OneNANDState *s = (OneNANDState *) opaque; +OneNANDState *s = (OneNANDState *)dev; +if (s->base != new) { +if (s->base != (target_phys_addr_t)-1) { +cpu_register_physical_memory(s->base, 0x1 << s->shift, + IO_MEM_UNASSIGNED); +} +if (new != (target_phys_addr_t)-1) { +/* XXX: We should use IO_MEM_ROMD but we broke it earlier... + * Both 0x ... 0x01ff and 0x8000 ... 0x800f can be used to + * write boot commands. Also take note of the BWPS bit. */ +cpu_register_physical_memory(new + (0x << s->shift), + 0x0200 << s->shift, s->iomemtype); +cpu_register_physical_memory(new + (0x0200 << s->shift), + 0xbe00 << s->shift, + (s->ram + (0x0200 << s->shift)) + | IO_MEM_RAM); +if (s->iomemtype) { +cpu_register_physical_memory_offset(new + (0xc000 << s->shift), +0x4000 << s->shift, +s->iomemtype, +(0xc000 << s->shift)); +} +} +s->base = new; +} +} -s->base = new; - -/* XXX: We should use IO_MEM_ROMD but we broke it earlier... - * Both 0x ... 0x01ff and 0x8000 ... 0x800f can be used to - * write boot commands. Also take note of the BWPS bit. */ -cpu_register_physical_memory(s->base + (0x << s->shift), -0x0200 << s->shift, s->iomemtype); -cpu_register_physical_memory(s->base + (0x0200 << s->shift), -0xbe00 << s->shift, -(s->ram +(0x0200 << s->shift)) | IO_MEM_RAM); -if (s->iomemtype) -cpu_register_physical_memory_offset(s->base + (0xc000 << s->shift), -0x4000 << s->shift, s->iomemtype, (0xc000 << s->shift)); +/* This wrapper can go away as soon as omap_gpmc is qdevified */ +void onenand_base_update(void *opaque, target_phys_addr_t new) +{ +onenand_base_updatefn(opaque, new); } +/* Also only needed for pre-qdev omap_gpmc */ void onenand_base_unmap(void *opaque) { -OneNANDState *s = (OneNANDState *) opaque; - -cpu_register_physical_memory(s->base, -0x1 << s->shift, IO_MEM_UNASSIGNED); +sysbus_mmio_unmap(sysbus_from_qdev((DeviceState *)opaque), 0); } static void onenand_intr_update(OneNANDState *s) @@ -132,6 +149,67 @@ static void onenand_intr_update(OneNANDState *s) qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1); } +static void onenand_pre_save(void *opaque) +{ +OneNANDState *s = opaque; +if (s->current == s->otp) { +s->current_direction = 1;
[Qemu-devel] [PATCH 03/12] hw/nand: Support devices wider than 8 bits
From: Juha Riihimäki Support NAND devices which are wider than 8 bits. Signed-off-by: Juha Riihimäki [Riku Voipio: Fixes and restructuring patchset] Signed-off-by: Riku Voipio [Peter Maydell: More fixes and cleanups for upstream submission] Signed-off-by: Peter Maydell --- hw/flash.h |5 ++- hw/nand.c | 119 +++- 2 files changed, 89 insertions(+), 35 deletions(-) diff --git a/hw/flash.h b/hw/flash.h index a992bb8..132ad29 100644 --- a/hw/flash.h +++ b/hw/flash.h @@ -24,8 +24,9 @@ void nand_done(NANDFlashState *s); void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale, uint8_t ce, uint8_t wp, uint8_t gnd); void nand_getpins(NANDFlashState *s, int *rb); -void nand_setio(NANDFlashState *s, uint8_t value); -uint8_t nand_getio(NANDFlashState *s); +void nand_setio(NANDFlashState *s, uint32_t value); +uint32_t nand_getio(NANDFlashState *s); +uint32_t nand_getbuswidth(NANDFlashState *s); #define NAND_MFR_TOSHIBA 0x98 #define NAND_MFR_SAMSUNG 0xec diff --git a/hw/nand.c b/hw/nand.c index 18aa226..2e98f25 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -49,6 +49,7 @@ struct NANDFlashState { uint8_t manf_id, chip_id; +uint8_t buswidth; /* in BYTES */ int size, pages; int page_shift, oob_shift, erase_shift, addr_shift; uint8_t *storage; @@ -215,6 +216,14 @@ static void nand_reset(NANDFlashState *s) s->status &= NAND_IOSTATUS_UNPROTCT; } +static inline void nand_pushio_byte(NANDFlashState *s, uint8_t value) +{ +s->ioaddr[s->iolen++] = value; +for (value = s->buswidth; --value;) { +s->ioaddr[s->iolen++] = 0; +} +} + static void nand_command(NANDFlashState *s) { unsigned int offset; @@ -224,15 +233,19 @@ static void nand_command(NANDFlashState *s) break; case NAND_CMD_READID: -s->io[0] = s->manf_id; -s->io[1] = s->chip_id; -s->io[2] = 'Q';/* Don't-care byte (often 0xa5) */ -if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) -s->io[3] = 0x15; /* Page Size, Block Size, Spare Size.. */ -else -s->io[3] = 0xc0; /* Multi-plane */ s->ioaddr = s->io; -s->iolen = 4; +s->iolen = 0; +nand_pushio_byte(s, s->manf_id); +nand_pushio_byte(s, s->chip_id); +nand_pushio_byte(s, 'Q'); /* Don't-care byte (often 0xa5) */ +if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) { +/* Page Size, Block Size, Spare Size; bit 6 indicates + * 8 vs 16 bit width NAND. + */ +nand_pushio_byte(s, (s->buswidth == 2) ? 0x55 : 0x15); +} else { +nand_pushio_byte(s, 0xc0); /* Multi-plane */ +} break; case NAND_CMD_RANDOMREAD2: @@ -277,9 +290,9 @@ static void nand_command(NANDFlashState *s) break; case NAND_CMD_READSTATUS: -s->io[0] = s->status; s->ioaddr = s->io; -s->iolen = 1; +s->iolen = 0; +nand_pushio_byte(s, s->status); break; default: @@ -357,8 +370,10 @@ void nand_getpins(NANDFlashState *s, int *rb) *rb = 1; } -void nand_setio(NANDFlashState *s, uint8_t value) +void nand_setio(NANDFlashState *s, uint32_t value) { +int i; + if (!s->ce && s->cle) { if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) { if (s->cmd == NAND_CMD_READ0 && value == NAND_CMD_LPREAD2) @@ -404,36 +419,64 @@ void nand_setio(NANDFlashState *s, uint8_t value) s->addr = (s->addr & mask) | v; s->addrlen ++; -if (s->addrlen == 1 && s->cmd == NAND_CMD_READID) -nand_command(s); - -if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) && -s->addrlen == 3 && ( -s->cmd == NAND_CMD_READ0 || -s->cmd == NAND_CMD_PAGEPROGRAM1)) -nand_command(s); -if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) && - s->addrlen == 4 && ( -s->cmd == NAND_CMD_READ0 || -s->cmd == NAND_CMD_PAGEPROGRAM1)) -nand_command(s); +switch (s->addrlen) { +case 1: +if (s->cmd == NAND_CMD_READID) { +nand_command(s); +} +break; +case 2: /* fix cache address as a byte address */ +s->addr <<= (s->buswidth - 1); +break; +case 3: +if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) +&& (s->cmd == NAND_CMD_READ0 +|| s->cmd == NAND_CMD_PAGEPROGRAM1)) { +nand_command(s); +} +break; +case 4: +if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) +&& nand_flash_ids[s->chip_id].size < 256 /* 1Gb or less */ +&& (s->cmd == NAND_CMD_READ0 || +
[Qemu-devel] [PATCH 07/12] onenand: Pass BlockDriverState to init function
Pass the BlockDriverState to the onenand init function so it doesn't need to look up the drive itself. Signed-off-by: Peter Maydell --- hw/flash.h |3 ++- hw/nseries.c | 10 ++ hw/onenand.c | 14 -- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/hw/flash.h b/hw/flash.h index 43260ce..1aae43d 100644 --- a/hw/flash.h +++ b/hw/flash.h @@ -38,7 +38,8 @@ uint32_t nand_getbuswidth(DeviceState *dev); /* onenand.c */ void onenand_base_update(void *opaque, target_phys_addr_t new); void onenand_base_unmap(void *opaque); -void *onenand_init(uint32_t id, int regshift, qemu_irq irq); +void *onenand_init(BlockDriverState *bdrv, uint32_t id, + int regshift, qemu_irq irq); void *onenand_raw_otp(void *opaque); /* ecc.c */ diff --git a/hw/nseries.c b/hw/nseries.c index 32f2f53..4fef05d 100644 --- a/hw/nseries.c +++ b/hw/nseries.c @@ -31,6 +31,7 @@ #include "hw.h" #include "bt.h" #include "loader.h" +#include "blockdev.h" /* Nokia N8x0 support */ struct n800_s { @@ -163,13 +164,14 @@ static const uint8_t n8x0_cal_bt_id[] = { static void n8x0_nand_setup(struct n800_s *s) { char *otp_region; +DriveInfo *dinfo; +dinfo = drive_get(IF_MTD, 0, 0); /* Either ec40xx or ec48xx are OK for the ID */ +s->nand = onenand_init(dinfo ? dinfo->bdrv : 0, 0xec4800, 1, + qdev_get_gpio_in(s->cpu->gpio, N8X0_ONENAND_GPIO)); omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, 0, onenand_base_update, -onenand_base_unmap, -(s->nand = onenand_init(0xec4800, 1, -qdev_get_gpio_in(s->cpu->gpio, -N8X0_ONENAND_GPIO; + onenand_base_unmap, s->nand); otp_region = onenand_raw_otp(s->nand); memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac)); diff --git a/hw/onenand.c b/hw/onenand.c index 71c1ab4..3a19d7f 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -615,10 +615,10 @@ static CPUWriteMemoryFunc * const onenand_writefn[] = { onenand_write, }; -void *onenand_init(uint32_t id, int regshift, qemu_irq irq) +void *onenand_init(BlockDriverState *bdrv, uint32_t id, + int regshift, qemu_irq irq) { OneNANDState *s = (OneNANDState *) qemu_mallocz(sizeof(*s)); -DriveInfo *dinfo = drive_get(IF_MTD, 0, 0); uint32_t size = 1 << (24 + ((id >> 12) & 7)); void *ram; @@ -632,11 +632,13 @@ void *onenand_init(uint32_t id, int regshift, qemu_irq irq) s->density_mask = (id & (1 << 11)) ? (1 << (6 + ((id >> 12) & 7))) : 0; s->iomemtype = cpu_register_io_memory(onenand_readfn, onenand_writefn, s, DEVICE_NATIVE_ENDIAN); -if (!dinfo) +s->bdrv = bdrv; +if (!s->bdrv) { s->image = memset(qemu_malloc(size + (size >> 5)), -0xff, size + (size >> 5)); -else -s->bdrv = dinfo->bdrv; + 0xff, size + (size >> 5)); +} else { +s->bdrv_cur = s->bdrv; +} s->otp = memset(qemu_malloc((64 + 2) << PAGE_SHIFT), 0xff, (64 + 2) << PAGE_SHIFT); s->ram = qemu_ram_alloc(NULL, "onenand.ram", 0xc000 << s->shift); -- 1.7.1
[Qemu-devel] [PATCH 01/12] hw/nand: Pass block device state to init function
Pass the BlockDeviceState to the nand_init() function rather than having it look it up via drive_get() itself. Signed-off-by: Peter Maydell --- hw/axis_dev88.c |6 +- hw/flash.h |2 +- hw/nand.c |8 ++-- hw/spitz.c |4 +++- hw/tc6393xb.c |5 - 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c index 0e2135a..de1f5a5 100644 --- a/hw/axis_dev88.c +++ b/hw/axis_dev88.c @@ -30,6 +30,7 @@ #include "loader.h" #include "elf.h" #include "cris-boot.h" +#include "blockdev.h" #define D(x) #define DNAND(x) @@ -251,6 +252,7 @@ void axisdev88_init (ram_addr_t ram_size, CPUState *env; DeviceState *dev; SysBusDevice *s; +DriveInfo *nand; qemu_irq irq[30], nmi[2], *cpu_irq; void *etraxfs_dmac; struct etraxfs_dma_client *eth[2] = {NULL, NULL}; @@ -278,7 +280,9 @@ void axisdev88_init (ram_addr_t ram_size, /* Attach a NAND flash to CS1. */ -nand_state.nand = nand_init(NAND_MFR_STMICRO, 0x39); +nand = drive_get(IF_MTD, 0, 0); +nand_state.nand = nand_init(nand ? nand->bdrv : NULL, +NAND_MFR_STMICRO, 0x39); nand_regs = cpu_register_io_memory(nand_read, nand_write, &nand_state, DEVICE_NATIVE_ENDIAN); cpu_register_physical_memory(0x1000, 0x0500, nand_regs); diff --git a/hw/flash.h b/hw/flash.h index c22e1a9..a992bb8 100644 --- a/hw/flash.h +++ b/hw/flash.h @@ -19,7 +19,7 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, /* nand.c */ typedef struct NANDFlashState NANDFlashState; -NANDFlashState *nand_init(int manf_id, int chip_id); +NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id); void nand_done(NANDFlashState *s); void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale, uint8_t ce, uint8_t wp, uint8_t gnd); diff --git a/hw/nand.c b/hw/nand.c index 37e51d7..d6204d9 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -14,7 +14,6 @@ # include "hw.h" # include "flash.h" # include "blockdev.h" -/* FIXME: Pass block device as an argument. */ # define NAND_CMD_READ00x00 # define NAND_CMD_READ10x01 @@ -451,20 +450,17 @@ uint8_t nand_getio(NANDFlashState *s) return *(s->ioaddr ++); } -NANDFlashState *nand_init(int manf_id, int chip_id) +NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id) { int pagesize; NANDFlashState *s; -DriveInfo *dinfo; if (nand_flash_ids[chip_id].size == 0) { hw_error("%s: Unsupported NAND chip ID.\n", __FUNCTION__); } s = (NANDFlashState *) qemu_mallocz(sizeof(NANDFlashState)); -dinfo = drive_get(IF_MTD, 0, 0); -if (dinfo) -s->bdrv = dinfo->bdrv; +s->bdrv = bdrv; s->manf_id = manf_id; s->chip_id = chip_id; s->size = nand_flash_ids[s->chip_id].size << 20; diff --git a/hw/spitz.c b/hw/spitz.c index 006f7a9..78e9c34 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -169,11 +169,13 @@ static void sl_flash_register(PXA2xxState *cpu, int size) static int sl_nand_init(SysBusDevice *dev) { int iomemtype; SLNANDState *s; +DriveInfo *nand; s = FROM_SYSBUS(SLNANDState, dev); s->ctl = 0; -s->nand = nand_init(s->manf_id, s->chip_id); +nand = drive_get(IF_MTD, 0, 0); +s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id); iomemtype = cpu_register_io_memory(sl_readfn, sl_writefn, s, DEVICE_NATIVE_ENDIAN); diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c index ed49e94..4de0819 100644 --- a/hw/tc6393xb.c +++ b/hw/tc6393xb.c @@ -12,6 +12,7 @@ #include "flash.h" #include "console.h" #include "pixel_ops.h" +#include "blockdev.h" #define IRQ_TC6393_NAND0 #define IRQ_TC6393_MMC 1 @@ -566,6 +567,7 @@ TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq) { int iomemtype; TC6393xbState *s; +DriveInfo *nand; CPUReadMemoryFunc * const tc6393xb_readfn[] = { tc6393xb_readb, tc6393xb_readw, @@ -586,7 +588,8 @@ TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq) s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS); -s->flash = nand_init(NAND_MFR_TOSHIBA, 0x76); +nand = drive_get(IF_MTD, 0, 0); +s->flash = nand_init(nand ? nand->bdrv : NULL, NAND_MFR_TOSHIBA, 0x76); iomemtype = cpu_register_io_memory(tc6393xb_readfn, tc6393xb_writefn, s, DEVICE_NATIVE_ENDIAN); -- 1.7.1
Re: [Qemu-devel] [PATCH] v6 revamp acpitable parsing and allow to specify complete (headerful) table
Is there something I can do to help take this patch the rest of the way? I'd hate to see it die because of a style issue and a compiler warning. -John On 06/15/2011 02:19 PM, Blue Swirl wrote: On Sat, Jun 11, 2011 at 1:29 AM, Michael Tokarev wrote: I've given up on this one. Personally I don't need this stuff for my win7 guests since I can hack either bios or the O/S loader to include all the necessary verifications for the win7 activation to work. I tried to make this process to be legal (no hacks or "cracks" needed) and easy for others, but since noone is interested in this after 6 versions and 5 resends, I wont continue - what I am trying to achieve by pushing this so hard, after all? Thanks to everyone who gave (mostly code style) comments - at least I know the changes has been read by someone. Frustrated, Sorry about that. I get this error: /src/qemu/hw/acpi.c: In function 'acpi_table_add': /src/qemu/hw/acpi.c:167: error: format '%u' expects type 'unsigned int', but argument 4 has type 'size_t' /mjt 12.05.2011 18:44, Michael Tokarev wrote: This patch almost rewrites acpi_table_add() function (but still leaves it using old get_param_value() interface). The result is that it's now possible to specify whole table (together with a header) in an external file, instead of just data portion, with a new file= parameter, but at the same time it's still possible to specify header fields as before. Now with the checkpatch.pl formatting fixes, thanks to Stefan Hajnoczi for suggestions, with changes from Isaku Yamahata, and with my further refinements. v5: rediffed against current qemu/master. v6: fix one "} else {" coding style defect (noted by Blue Swirl) Signed-off-by: Michael Tokarev --- hw/acpi.c | 292 --- qemu-options.hx |7 +- 2 files changed, 175 insertions(+), 124 deletions(-) diff --git a/hw/acpi.c b/hw/acpi.c index ad40fb4..4316189 100644 --- a/hw/acpi.c +++ b/hw/acpi.c @@ -22,17 +22,29 @@ struct acpi_table_header { -char signature [4];/* ACPI signature (4 ASCII characters) */ +uint16_t _length; /* our length, not actual part of the hdr */ + /* XXX why we have 2 length fields here? */ +char sig[4]; /* ACPI signature (4 ASCII characters) */ uint32_t length; /* Length of table, in bytes, including header */ uint8_t revision; /* ACPI Specification minor version # */ uint8_t checksum; /* To make sum of entire table == 0 */ -char oem_id [6]; /* OEM identification */ -char oem_table_id [8]; /* OEM table identification */ +char oem_id[6]; /* OEM identification */ +char oem_table_id[8]; /* OEM table identification */ uint32_t oem_revision;/* OEM revision number */ -char asl_compiler_id [4]; /* ASL compiler vendor ID */ +char asl_compiler_id[4]; /* ASL compiler vendor ID */ uint32_t asl_compiler_revision; /* ASL compiler revision number */ } __attribute__((packed)); +#define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header) +#define ACPI_TABLE_PFX_SIZE sizeof(uint16_t) /* size of the extra prefix */ + +static const char dfl_hdr[ACPI_TABLE_HDR_SIZE] = +"\0\0" /* fake _length (2) */ +"QEMU\0\0\0\0\1\0" /* sig (4), len(4), revno (1), csum (1) */ +"QEMUQEQEMUQEMU\1\0\0\0" /* OEM id (6), table (8), revno (4) */ +"QEMU\1\0\0\0" /* ASL compiler ID (4), version (4) */ +; + char *acpi_tables; size_t acpi_tables_len; @@ -45,158 +57,192 @@ static int acpi_checksum(const uint8_t *data, int len) return (-sum)& 0xff; } +/* like strncpy() but zero-fills the tail of destination */ +static void strzcpy(char *dst, const char *src, size_t size) +{ +size_t len = strlen(src); +if (len>= size) { +len = size; +} else { + memset(dst + len, 0, size - len); +} +memcpy(dst, src, len); +} + +/* XXX fixme: this function uses obsolete argument parsing interface */ int acpi_table_add(const char *t) { -static const char *dfl_id = "QEMUQEMU"; char buf[1024], *p, *f; -struct acpi_table_header acpi_hdr; unsigned long val; -uint32_t length; -struct acpi_table_header *acpi_hdr_p; -size_t off; +size_t len, start, allen; +bool has_header; +int changed; +int r; +struct acpi_table_header hdr; + +r = 0; +r |= get_param_value(buf, sizeof(buf), "data", t) ? 1 : 0; +r |= get_param_value(buf, sizeof(buf), "file", t) ? 2 : 0; +switch (r) { +case 0: +buf[0] = '\0'; Missing 'break' or comment about fall through. +case 1: +has_header = false; +break; +case 2: +has_header = true; +break; +default: +fprintf(stderr, "acpitable: both data and file are specified\n"); +return -1; +} + +if (!acpi_tables) { +allen = sizeof(uint16_t); +
[Qemu-devel] [PATCH] report serial devices created with -device in the PIIX4 config space
Serial and parallel devices created with -device are not reported in the PIIX4 configuration space, and are hence not picked up by the DSDT. This upsets Windows, which hides them altogether from the guest. To avoid this, check at the end of machine initialization whether the corresponding I/O ports have been registered. The new function in ioport.c does this; this also requires a tweak to isa_unassign_ioport. I left the comment in piix4_pm_initfn since the registers I moved do seem to match the 82371AB datasheet. There are some quirks though. We are setting this bit: "Device 8 EIO Enable (EIO_EN_DEV8)—R/W. 1=Enable PCI access to the device 8 enabled I/O ranges to be claimed by PIIX4 and forwarded to the ISA/EIO bus. 0=Disable. The LPT_MON_EN must be set to enable the decode." but not LPT_MON_EN (bit 18 at 50h): LPT Port Enable (LPT_MON_EN)—R/W. 1=Enable accesses to parallel port address range (LPT_DEC_SEL) to generate a device 8 (parallel port) decode event. 0=Disable. We're also setting the LPT_DEC_SEL field (that's the 0x60 written to 63h) to 11, which means reserved, rather than to 01 (378h-37Fh). Likewise we're not setting SA_MON_EN, SB_MON_EN (respectively bit 14 and bit 16 at address 50h) for the serial ports. However, we're setting COMA_DEC_SEL and COMB_DEC_SEL correctly, unlike the corresponding register for the parallel port. All these fields are left as they are, since they are probably only meant to be used in the DSDT. Signed-off-by: Paolo Bonzini --- hw/acpi_piix4.c | 23 ++- ioport.c| 19 +-- ioport.h|2 +- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 350558b..03de3ad 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -23,6 +23,7 @@ #include "acpi.h" #include "sysemu.h" #include "range.h" +#include "ioport.h" //#define DEBUG @@ -63,6 +64,7 @@ typedef struct PIIX4PMState { qemu_irq irq; qemu_irq smi_irq; int kvm_enabled; +Notifier machine_ready; /* for pci hotplug */ ACPIGPE gpe; @@ -311,6 +313,19 @@ static void piix4_powerdown(void *opaque, int irq, int power_failing) acpi_pm1_evt_power_down(pm1a, tmr); } +static void piix4_pm_machine_ready(struct Notifier* n) +{ +PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready); +uint8_t *pci_conf; + +pci_conf = s->dev.config; +pci_conf[0x5f] = (isa_is_ioport_assigned(0x378) ? 0x80 : 0) | 0x10; +pci_conf[0x63] = 0x60; +pci_conf[0x67] = (isa_is_ioport_assigned(0x3f8) ? 0x08 : 0) | + (isa_is_ioport_assigned(0x2f8) ? 0x90 : 0); + +} + static int piix4_pm_initfn(PCIDevice *dev) { PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, dev); @@ -337,11 +352,6 @@ static int piix4_pm_initfn(PCIDevice *dev) /* XXX: which specification is used ? The i82731AB has different mappings */ -pci_conf[0x5f] = (parallel_hds[0] != NULL ? 0x80 : 0) | 0x10; -pci_conf[0x63] = 0x60; -pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) | - (serial_hds[1] != NULL ? 0x90 : 0); - pci_conf[0x90] = s->smb_io_base | 1; pci_conf[0x91] = s->smb_io_base >> 8; pci_conf[0xd2] = 0x09; @@ -354,12 +364,14 @@ static int piix4_pm_initfn(PCIDevice *dev) qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1); pm_smbus_init(&s->dev.qdev, &s->smb); +s->machine_ready.notify = piix4_pm_machine_ready; +qemu_add_machine_init_done_notifier(&s->machine_ready); qemu_register_reset(piix4_reset, s); piix4_acpi_system_hot_add_init(dev->bus, s); return 0; } i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq cmos_s3, qemu_irq smi_irq, int kvm_enabled) diff --git a/ioport.c b/ioport.c index 2e971fa..0d2611d 100644 --- a/ioport.c +++ b/ioport.c @@ -245,18 +245,25 @@ void isa_unassign_ioport(pio_addr_t start, int length) int i; for(i = start; i < start + length; i++) { -ioport_read_table[0][i] = default_ioport_readb; -ioport_read_table[1][i] = default_ioport_readw; -ioport_read_table[2][i] = default_ioport_readl; +ioport_read_table[0][i] = NULL; +ioport_read_table[1][i] = NULL; +ioport_read_table[2][i] = NULL; -ioport_write_table[0][i] = default_ioport_writeb; -ioport_write_table[1][i] = default_ioport_writew; -ioport_write_table[2][i] = default_ioport_writel; +ioport_write_table[0][i] = NULL; +ioport_write_table[1][i] = NULL; +ioport_write_table[2][i] = NULL; ioport_opaque[i] = NULL; } } +bool isa_is_ioport_assigned(pio_addr_t start) +{ +return (ioport_read_table[0][start] || ioport_write_table[0][start] || + ioport_read_table[1][start] || ioport_write_table[1][start] || + ioport_read_table[2][start] || ioport_write_table[2]
Re: [Qemu-devel] [QAPI+QGA 3/3] QEMU Guest Agent (virtagent) v7
On Fri, 15 Jul 2011 09:15:18 +0800 Zhi Yong Wu wrote: > On Fri, Jul 15, 2011 at 4:00 AM, Michael Roth > wrote: > > This is Set 3/3 of the QAPI+QGA patchsets. > > > > These patches apply on top of qapi-backport-set2-v6, and can also be > > obtained from: > > git://repo.or.cz/qemu/mdroth.git qapi-backport-set3-v7 > > > > (Set1+2 are a backport of some of the QAPI-related work from Anthony's > > glib tree. The main goal is to get the basic code generation infrastructure > > in > > place so that it can be used by the guest agent to implement a QMP-like > > guest > > interface, and so that future work regarding the QMP conversion to QAPI can > > be > > decoupled from the infrastructure bits. Set3 is the Qemu Guest Agent > > (virtagent), rebased on the new code QAPI code generation infrastructure. > > This > > is the first user of QAPI, QMP will follow.) > > ___ > > > > CHANGES SINCE V6: > > - Made "/dev/virtio-ports/org.qemu.guest_agent.0" default device path for > > agent > > - Consolidated uneeded fcntl() calls into qemu_open() > > - JSON/QMP parse errors now propagated to client > > - Replaced non-assertion uses of g_error() with exit() > > - Added guest-file-flush > > - Removed limit on max read size for guest-file-read > > - 'count' parameters to guest-file-read/guest-file-write are now optional > > (default to 4KB and size of provided buffer, base64-decoded, respectively) > > - Removed redundant 'file_' and 'shutdown_' prefixes from > > guest-file-*/guest-shutdown commands, switched to "-" in place of "_" in > > parameter names, renamed guest-file-read's "buf" param to "buf-b64" and > > guest-file-write's "data_b64" param to "buf-b64" for consistency. > > - guest-fsfreeze-freeze now returns error objects on error rather as part > > of it's integer return values, and on error will unfreeze previously frozen > > filesystems. > > - GUEST_FSFREEZE_STATUS_INPROGRESS removed, GUEST_FSFREEZE_STATUS_ERROR > > now serves the explicit purpose of noting a failure to find a previously > > mounted filesytem/directory after initial freeze, or failure to unfreeze 1 > > or more filesystems. > > - -c/--channel option to qemu-ga is now -m/--method > > > > CHANGES SINCE V5: > > - switched to using qemu malloc/list functions where possible > > - removed unused proxy_path field in struct GAState > > - pid file now opened write-only, removed lockf() in favor of O_EXCL, > > added SIGINT/SIGTERM signal handlers to handle cleanup > > - cleaned up error-handling, switched to asserts where appropriate, > > removed unecessary gotos and NULL checks for qemu_free()/qobject_decref() > > - refactored send_payload() using helper functions > > - fixed improper handling of pidfile fd==0 > > - changed guest-shutdown's "shutdown_mode" param to "mode" > > - switched to using kernel-generated FDs for guest-file-open rather than > > an autoincrement value > > - add maximum chunk size of guest-file-read/guest-file-write > > - added checks to avoid guest-file-write from writing data beyond the > > provided data buffer > > - made logging best-effort, removed handling of failures to log as errors > > - guest-shutdown exec errors now logged to guest syslog, clarified > > shutdown's asynchronous, no gauruntee nature in schema. > > > > CHANGES SINCE V4: > > - Removed timeout mechanism via worker thread/pthread_cancel due to > > potential memory leak. Will re-introduce guest-side timeout support in > > future version. > > - Fixed up fsfreeze code to use enums specified within the guest agent's > > qapi schema. > > - Fixed memory leak due to a log statement, and added missing cleanup > > functions for heap-allocated g_error objects. > > - Made "mode" param to guest-file-open optional, defaults to "r" > > (read-only) > > > > CHANGES SINCE V3: > > - Fixed error-handling issues in fsfreeze commands leading to certain > > mounted directories causing freeze/thaw operations to fail > > - Added cleanup hook to thaw filesystems on graceful guest agent exit > > - Removed unused enum values and added additional details to schema > > documentation > > - Fixed build issue that was missed due to deprecated files in source > > tree, removed unused includes > > > > CHANGES SINCE V2: > > - Rebased on new QAPI code generation framework > > - Dropped ability for QMP to act as a proxy for the guest agent, will be > > added when new QMP server is backported from Anthony's glib tree > > - Replaced negotiation/control events with a simple 2-way handshake > > implemented by a standard RPC (guest-sync) > > - Removed enforcement of "pristine" sessions, state is now > > global/persistant across multiple clients/connections > > - Fixed segfault in logging code > > - Added Jes' filesystem freeze patches > > - General cleanups > > > > CHANGES SINCE V1: > > - Added guest agent worker thread to execute RPCs in the guest. With this > > in place we have a reliable timeout mechanism for hung commands, currently
[Qemu-devel] [RFC][PATCH 3/9] block: Add bdrv_co_readv/writev emulation
In order to be able to call bdrv_co_readv/writev for drivers that don't implement the functions natively, add an emulation that uses the AIO functions to implement them. Signed-off-by: Kevin Wolf --- block.c | 86 +++-- trace-events |1 + 2 files changed, 78 insertions(+), 9 deletions(-) diff --git a/block.c b/block.c index 79a5008..fc1712f 100644 --- a/block.c +++ b/block.c @@ -64,6 +64,12 @@ static BlockDriverAIOCB *bdrv_co_aio_readv_em(BlockDriverState *bs, static BlockDriverAIOCB *bdrv_co_aio_writev_em(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque); +static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, + QEMUIOVector *iov); +static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, + QEMUIOVector *iov); static QTAILQ_HEAD(, BlockDriverState) bdrv_states = QTAILQ_HEAD_INITIALIZER(bdrv_states); @@ -182,14 +188,19 @@ void bdrv_register(BlockDriver *bdrv) bdrv->bdrv_aio_writev = bdrv_co_aio_writev_em; bdrv->bdrv_read = bdrv_read_em; bdrv->bdrv_write = bdrv_write_em; - } else if (!bdrv->bdrv_aio_readv) { -/* add AIO emulation layer */ -bdrv->bdrv_aio_readv = bdrv_aio_readv_em; -bdrv->bdrv_aio_writev = bdrv_aio_writev_em; -} else if (!bdrv->bdrv_read) { -/* add synchronous IO emulation layer */ -bdrv->bdrv_read = bdrv_read_em; -bdrv->bdrv_write = bdrv_write_em; + } else { +bdrv->bdrv_co_readv = bdrv_co_readv_em; +bdrv->bdrv_co_writev = bdrv_co_writev_em; + +if (!bdrv->bdrv_aio_readv) { +/* add AIO emulation layer */ +bdrv->bdrv_aio_readv = bdrv_aio_readv_em; +bdrv->bdrv_aio_writev = bdrv_aio_writev_em; +} else if (!bdrv->bdrv_read) { +/* add synchronous IO emulation layer */ +bdrv->bdrv_read = bdrv_read_em; +bdrv->bdrv_write = bdrv_write_em; +} } if (!bdrv->bdrv_aio_flush) @@ -2652,7 +2663,7 @@ static void coroutine_fn bdrv_co_rw(void *opaque) BlockDriverAIOCBCoroutine *acb = opaque; BlockDriverState *bs = acb->common.bs; -if (acb->is_write) { +if (!acb->is_write) { acb->req.error = bs->drv->bdrv_co_readv(bs, acb->req.sector, acb->req.nb_sectors, acb->req.qiov); } else { @@ -2849,6 +2860,63 @@ void qemu_aio_release(void *p) } /**/ +/* Coroutine block device emulation */ + +typedef struct CoroutineIOCompletion { +Coroutine *coroutine; +int ret; +} CoroutineIOCompletion; + +static void bdrv_co_io_em_complete(void *opaque, int ret) +{ +CoroutineIOCompletion *co = opaque; + +co->ret = ret; +qemu_coroutine_enter(co->coroutine, NULL); +} + +static int coroutine_fn bdrv_co_io_em(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, QEMUIOVector *iov, + bool is_write) +{ +CoroutineIOCompletion co = { +.coroutine = qemu_coroutine_self(), +.ret = -EINPROGRESS, +}; +BlockDriverAIOCB *acb; + +if (is_write) { +acb = bdrv_aio_writev(bs, sector_num, iov, nb_sectors, + bdrv_co_io_em_complete, &co); +} else { +acb = bdrv_aio_readv(bs, sector_num, iov, nb_sectors, + bdrv_co_io_em_complete, &co); +} + +trace_bdrv_co_io(is_write, acb); +if (!acb) { +return -EIO; +} +qemu_coroutine_yield(); + +return co.ret; +} + +static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, + QEMUIOVector *iov) +{ +return bdrv_co_io_em(bs, sector_num, nb_sectors, iov, false); +} + +static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, + QEMUIOVector *iov) +{ +return bdrv_co_io_em(bs, sector_num, nb_sectors, iov, true); +} + +/**/ /* removable device support */ /** diff --git a/trace-events b/trace-events index 3cd9118..b835c61 100644 --- a/trace-events +++ b/trace-events @@ -57,6 +57,7 @@ disable bdrv_aio_writev(void *bs, int64_t sector_num, int nb_sectors, void *opaq disable bdrv_set_locked(void *bs, int locked) "bs %p locked %d" disable bdrv_co_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d" disable bdrv_co_write
Re: [Qemu-devel] [PATCH v7 4/4] guest agent: add guest agent RPCs/commands
On Thu, 14 Jul 2011 15:00:34 -0500 Michael Roth wrote: > This adds the initial set of QMP/QAPI commands provided by the guest > agent: > > guest-sync > guest-ping > guest-info > guest-shutdown > guest-file-open > guest-file-read > guest-file-write > guest-file-seek > guest-file-flush > guest-file-close > guest-fsfreeze-freeze > guest-fsfreeze-thaw > guest-fsfreeze-status > > The input/output specification for these commands are documented in the > schema. > > Example usage: > > host: > qemu -device virtio-serial \ > -chardev socket,path=/tmp/vs0.sock,server,nowait,id=qga0 \ > -device virtserialport,chardev=qga0,name=org.qemu.quest_agent.0 > ... > > echo "{'execute':'guest-info'}" | socat stdio unix-connect:/tmp/qga0.sock > > guest: > qemu-ga -m virtio-serial -p /dev/virtio-ports/org.qemu.guest_agent.0 \ > -p /var/run/qemu-guest-agent.pid -d > > Signed-off-by: Michael Roth > --- > Makefile | 15 ++- > qapi-schema-guest.json | 217 +++ > qemu-ga.c |4 + > qerror.c |8 + > qerror.h |6 + > qga/guest-agent-commands.c | 512 > > qga/guest-agent-core.h |2 + > 7 files changed, 762 insertions(+), 2 deletions(-) > create mode 100644 qapi-schema-guest.json > create mode 100644 qga/guest-agent-commands.c > > diff --git a/Makefile b/Makefile > index b2e8593..f98e127 100644 > --- a/Makefile > +++ b/Makefile > @@ -175,15 +175,26 @@ $(qapi-dir)/test-qmp-commands.h: > $(qapi-dir)/test-qmp-marshal.c > $(qapi-dir)/test-qmp-marshal.c: $(SRC_PATH)/qapi-schema-test.json > $(SRC_PATH)/scripts/qapi-commands.py > $(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py -o > "$(qapi-dir)" -p "test-" < $<, " GEN $@") > > +$(qapi-dir)/qga-qapi-types.c: $(qapi-dir)/qga-qapi-types.h > +$(qapi-dir)/qga-qapi-types.h: $(SRC_PATH)/qapi-schema-guest.json > $(SRC_PATH)/scripts/qapi-types.py > + $(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py -o > "$(qapi-dir)" -p "qga-" < $<, " GEN $@") > +$(qapi-dir)/qga-qapi-visit.c: $(qapi-dir)/qga-qapi-visit.h > +$(qapi-dir)/qga-qapi-visit.h: $(SRC_PATH)/qapi-schema-guest.json > $(SRC_PATH)/scripts/qapi-visit.py > + $(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py -o > "$(qapi-dir)" -p "qga-" < $<, " GEN $@") > +$(qapi-dir)/qga-qmp-marshal.c: $(SRC_PATH)/qapi-schema-guest.json > $(SRC_PATH)/scripts/qapi-commands.py > + $(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py -o > "$(qapi-dir)" -p "qga-" < $<, " GEN $@") > + > test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c > test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) > test-visitor: test-visitor.o qfloat.o qint.o qdict.o qstring.o qlist.o > qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o > json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o > $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o > > test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c > test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c > test-qmp-commands.h) > test-qmp-commands: test-qmp-commands.o qfloat.o qint.o qdict.o qstring.o > qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) > qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o > qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o > $(qapi-dir)/test-qmp-marshal.o module.o > > -QGALIB=qga/guest-agent-command-state.o > +QGALIB=qga/guest-agent-command-state.o qga/guest-agent-commands.o > + > +qemu-ga.o: $(qapi-dir)/qga-qapi-types.c $(qapi-dir)/qga-qapi-types.h > $(qapi-dir)/qga-qapi-visit.c $(qapi-dir)/qga-qmp-marshal.c > > -qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o > $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) > $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o > qapi/qmp-dispatch.o qapi/qmp-registry.o > +qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o > $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) > $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o > qapi/qmp-dispatch.o qapi/qmp-registry.o $(qapi-dir)/qga-qapi-visit.o > $(qapi-dir)/qga-qapi-types.o $(qapi-dir)/qga-qmp-marshal.o > > QEMULIBS=libhw32 libhw64 libuser libdis libdis-user > > diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json > new file mode 100644 > index 000..a18d6f8 > --- /dev/null > +++ b/qapi-schema-guest.json > @@ -0,0 +1,217 @@ > +# *-*- Mode: Python -*-* > + > +## > +# @guest-sync: > +# > +# Echo back a unique integer value > +# > +# This is used by clients talking to the guest agent over the > +# wire to ensure the stream is in sync and doesn't contain stale > +# data from previous clie
[Qemu-devel] [RFC][PATCH 1/9] block: Add bdrv_co_readv/writev
Add new block driver callbacks bdrv_co_readv/writev, which work on a QEMUIOVector like bdrv_aio_*, but don't need a callback. The function may only be called inside a coroutine, so a block driver implementing this interface can yield instead of blocking during I/O. Signed-off-by: Kevin Wolf --- Makefile.objs |2 +- block.c | 46 ++ block.h |5 + block_int.h |6 ++ trace-events |2 ++ 5 files changed, 60 insertions(+), 1 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index d9ade62..170a656 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -25,6 +25,7 @@ coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o async.o block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o qemu-sockets.o +block-obj-y += $(coroutine-obj-y) block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o @@ -79,7 +80,6 @@ common-obj-y += readline.o console.o cursor.o qemu-error.o common-obj-y += $(oslib-obj-y) common-obj-$(CONFIG_WIN32) += os-win32.o common-obj-$(CONFIG_POSIX) += os-posix.o -common-obj-y += $(coroutine-obj-y) common-obj-y += tcg-runtime.o host-utils.o common-obj-y += irq.o ioport.o input.o diff --git a/block.c b/block.c index 24a25d5..a57d168 100644 --- a/block.c +++ b/block.c @@ -1121,6 +1121,52 @@ int bdrv_write_sync(BlockDriverState *bs, int64_t sector_num, buf, BDRV_SECTOR_SIZE * nb_sectors); } +int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num, +int nb_sectors, QEMUIOVector *qiov) +{ +BlockDriver *drv = bs->drv; + +trace_bdrv_co_readv(bs, sector_num, nb_sectors); + +if (!drv) { +return -ENOMEDIUM; +} +if (bdrv_check_request(bs, sector_num, nb_sectors)) { +return -EIO; +} + +return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov); +} + +int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num, +int nb_sectors, QEMUIOVector *qiov) +{ +BlockDriver *drv = bs->drv; + +trace_bdrv_co_writev(bs, sector_num, nb_sectors); + +if (!bs->drv) { +return -ENOMEDIUM; +} +if (bs->read_only) { +return -EACCES; +} +if (bdrv_check_request(bs, sector_num, nb_sectors)) { +return -EIO; +} + +if (bs->dirty_bitmap) { +set_dirty_bitmap(bs, sector_num, nb_sectors, 1); +} + +if (bs->wr_highest_sector < sector_num + nb_sectors - 1) { +bs->wr_highest_sector = sector_num + nb_sectors - 1; +} + +return drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov); +} + + /** * Truncate file to 'offset' bytes (needed only for file protocols) */ diff --git a/block.h b/block.h index 859d1d9..413dd4b 100644 --- a/block.h +++ b/block.h @@ -4,6 +4,7 @@ #include "qemu-aio.h" #include "qemu-common.h" #include "qemu-option.h" +#include "qemu-coroutine.h" #include "qobject.h" /* block.c */ @@ -87,6 +88,10 @@ int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset, const void *buf, int count); int bdrv_write_sync(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors); +int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num, +int nb_sectors, QEMUIOVector *qiov); +int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num, +int nb_sectors, QEMUIOVector *qiov); int bdrv_truncate(BlockDriverState *bs, int64_t offset); int64_t bdrv_getlength(BlockDriverState *bs); void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); diff --git a/block_int.h b/block_int.h index 1e265d2..6fe6369 100644 --- a/block_int.h +++ b/block_int.h @@ -27,6 +27,7 @@ #include "block.h" #include "qemu-option.h" #include "qemu-queue.h" +#include "qemu-coroutine.h" #define BLOCK_FLAG_ENCRYPT 1 #define BLOCK_FLAG_COMPAT6 4 @@ -76,6 +77,11 @@ struct BlockDriver { int (*bdrv_discard)(BlockDriverState *bs, int64_t sector_num, int nb_sectors); +int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs, +int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); +int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs, +int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); + int (*bdrv_aio_multiwrite)(BlockDriverState *bs, BlockRequest *reqs, int num_reqs); int (*bdrv_merge_requests)(BlockDriverState *bs, BlockRequest* a, diff --git a/trace-events b/trace-events index ebe4df9..3cd9118 100644 --- a/trace-events +++ b/trace-events @@ -55,6 +55,8 @@ disable bdrv_aio_flush(void *bs, void *opaque) "bs %p opaque %p" 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" disabl
[Qemu-devel] [RFC][PATCH 8/9] coroutines: Use one global bottom half for CoQueue
Now that AsyncContexts don't exist any more, we can use one global bottom half for restarting coroutines instead of allocating a new one every time (before removing AsyncContexts, the problem with having a global BH was that it had to belong to a single AsyncContexts and wouldn't be executed in a different one - which leads to deadlocks) Signed-off-by: Kevin Wolf --- qemu-coroutine-lock.c | 19 ++- 1 files changed, 6 insertions(+), 13 deletions(-) diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c index abaa1f7..a80f437 100644 --- a/qemu-coroutine-lock.c +++ b/qemu-coroutine-lock.c @@ -30,14 +30,10 @@ static QTAILQ_HEAD(, Coroutine) unlock_bh_queue = QTAILQ_HEAD_INITIALIZER(unlock_bh_queue); - -struct unlock_bh { -QEMUBH *bh; -}; +static QEMUBH* unlock_bh; static void qemu_co_queue_next_bh(void *opaque) { -struct unlock_bh *unlock_bh = opaque; Coroutine *next; trace_qemu_co_queue_next_bh(); @@ -45,14 +41,15 @@ static void qemu_co_queue_next_bh(void *opaque) QTAILQ_REMOVE(&unlock_bh_queue, next, co_queue_next); qemu_coroutine_enter(next, NULL); } - -qemu_bh_delete(unlock_bh->bh); -qemu_free(unlock_bh); } void qemu_co_queue_init(CoQueue *queue) { QTAILQ_INIT(&queue->entries); + +if (!unlock_bh) { +unlock_bh = qemu_bh_new(qemu_co_queue_next_bh, NULL); +} } void coroutine_fn qemu_co_queue_wait(CoQueue *queue) @@ -65,7 +62,6 @@ void coroutine_fn qemu_co_queue_wait(CoQueue *queue) bool qemu_co_queue_next(CoQueue *queue) { -struct unlock_bh *unlock_bh; Coroutine *next; next = QTAILQ_FIRST(&queue->entries); @@ -73,10 +69,7 @@ bool qemu_co_queue_next(CoQueue *queue) QTAILQ_REMOVE(&queue->entries, next, co_queue_next); QTAILQ_INSERT_TAIL(&unlock_bh_queue, next, co_queue_next); trace_qemu_co_queue_next(next); - -unlock_bh = qemu_malloc(sizeof(*unlock_bh)); -unlock_bh->bh = qemu_bh_new(qemu_co_queue_next_bh, unlock_bh); -qemu_bh_schedule(unlock_bh->bh); +qemu_bh_schedule(unlock_bh); } return (next != NULL); -- 1.7.6
[Qemu-devel] [RFC][PATCH 4/9] coroutines: Locks
Signed-off-by: Kevin Wolf --- Makefile.objs |2 +- qemu-coroutine-int.h |1 + qemu-coroutine-lock.c | 124 + qemu-coroutine.h | 62 trace-events |8 +++ 5 files changed, 196 insertions(+), 1 deletions(-) create mode 100644 qemu-coroutine-lock.c diff --git a/Makefile.objs b/Makefile.objs index 170a656..9d838dd 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -12,7 +12,7 @@ oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o ### # coroutines -coroutine-obj-y = qemu-coroutine.o +coroutine-obj-y = qemu-coroutine.o qemu-coroutine-lock.o ifeq ($(CONFIG_UCONTEXT_COROUTINE),y) coroutine-obj-$(CONFIG_POSIX) += coroutine-ucontext.o else diff --git a/qemu-coroutine-int.h b/qemu-coroutine-int.h index 64915c2..d495615 100644 --- a/qemu-coroutine-int.h +++ b/qemu-coroutine-int.h @@ -38,6 +38,7 @@ struct Coroutine { void *entry_arg; Coroutine *caller; QLIST_ENTRY(Coroutine) pool_next; +QTAILQ_ENTRY(Coroutine) co_queue_next; }; Coroutine *qemu_coroutine_new(void); diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c new file mode 100644 index 000..abaa1f7 --- /dev/null +++ b/qemu-coroutine-lock.c @@ -0,0 +1,124 @@ +/* + * coroutine queues and locks + * + * Copyright (c) 2011 Kevin Wolf + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu-common.h" +#include "qemu-coroutine.h" +#include "qemu-coroutine-int.h" +#include "qemu-queue.h" +#include "trace.h" + +static QTAILQ_HEAD(, Coroutine) unlock_bh_queue = +QTAILQ_HEAD_INITIALIZER(unlock_bh_queue); + +struct unlock_bh { +QEMUBH *bh; +}; + +static void qemu_co_queue_next_bh(void *opaque) +{ +struct unlock_bh *unlock_bh = opaque; +Coroutine *next; + +trace_qemu_co_queue_next_bh(); +while ((next = QTAILQ_FIRST(&unlock_bh_queue))) { +QTAILQ_REMOVE(&unlock_bh_queue, next, co_queue_next); +qemu_coroutine_enter(next, NULL); +} + +qemu_bh_delete(unlock_bh->bh); +qemu_free(unlock_bh); +} + +void qemu_co_queue_init(CoQueue *queue) +{ +QTAILQ_INIT(&queue->entries); +} + +void coroutine_fn qemu_co_queue_wait(CoQueue *queue) +{ +Coroutine *self = qemu_coroutine_self(); +QTAILQ_INSERT_TAIL(&queue->entries, self, co_queue_next); +qemu_coroutine_yield(); +assert(qemu_in_coroutine()); +} + +bool qemu_co_queue_next(CoQueue *queue) +{ +struct unlock_bh *unlock_bh; +Coroutine *next; + +next = QTAILQ_FIRST(&queue->entries); +if (next) { +QTAILQ_REMOVE(&queue->entries, next, co_queue_next); +QTAILQ_INSERT_TAIL(&unlock_bh_queue, next, co_queue_next); +trace_qemu_co_queue_next(next); + +unlock_bh = qemu_malloc(sizeof(*unlock_bh)); +unlock_bh->bh = qemu_bh_new(qemu_co_queue_next_bh, unlock_bh); +qemu_bh_schedule(unlock_bh->bh); +} + +return (next != NULL); +} + +bool qemu_co_queue_empty(CoQueue *queue) +{ +return (QTAILQ_FIRST(&queue->entries) == NULL); +} + +void qemu_co_mutex_init(CoMutex *mutex) +{ +memset(mutex, 0, sizeof(*mutex)); +qemu_co_queue_init(&mutex->queue); +} + +void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex) +{ +Coroutine *self = qemu_coroutine_self(); + +trace_qemu_co_mutex_lock_entry(mutex, self); + +while (mutex->locked) { +qemu_co_queue_wait(&mutex->queue); +} + +mutex->locked = true; + +trace_qemu_co_mutex_lock_return(mutex, self); +} + +void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex) +{ +Coroutine *self = qemu_coroutine_self(); + +trace_qemu_co_mutex_unlock_entry(mutex, self); + +assert(mutex->locked == true); +assert(qemu_in_coroutine()); + +mutex->locked = false; +qemu_co_queue_next(&mutex->queue); + +trace_qemu_co_mutex_unlock_return(mutex, self); +} diff --git a/qemu-corout
[Qemu-devel] [RFC][PATCH 0/9] Use coroutines in the block layer
Based on Stefan's latest coroutine patches. This series makes qcow and qcow2 take advantage of the new coroutine infrastructure. Both formats used synchronous operations for accessing their metadata and blocked the guest CPU during that time. With coroutines, the I/O will happen asynchronously in the background and the CPU won't be blocked any more. Kevin Wolf (9): block: Add bdrv_co_readv/writev block: Emulate AIO functions with bdrv_co_readv/writev block: Add bdrv_co_readv/writev emulation coroutines: Locks qcow2: Use coroutines qcow: Use coroutines async: Remove AsyncContext coroutines: Use one global bottom half for CoQueue block: Use bdrv_co_* instead of synchronous versions in coroutines Makefile.objs |4 +- async.c | 98 ++- block.c | 271 ++-- block.h |5 + block/qcow.c | 180 +++- block/qcow2-cluster.c | 26 ++--- block/qcow2.c | 240 block/qcow2.h |5 +- block/qed-table.c | 14 --- block/qed.c |4 - block_int.h |6 + linux-aio.c | 24 + posix-aio-compat.c| 11 -- qemu-common.h |4 - qemu-coroutine-int.h |1 + qemu-coroutine-lock.c | 117 + qemu-coroutine.h | 62 +++ trace-events | 11 ++ 18 files changed, 636 insertions(+), 447 deletions(-) create mode 100644 qemu-coroutine-lock.c -- 1.7.6
Re: [Qemu-devel] [PATCH] v6 revamp acpitable parsing and allow to specify complete (headerful) table
On Fri, Jul 15, 2011 at 6:18 PM, John Baboval wrote: > Is there something I can do to help take this patch the rest of the way? > > I'd hate to see it die because of a style issue and a compiler warning. There's also suspicious missing 'break' statement. How about fixing the issues and submitting the patch? > -John > > On 06/15/2011 02:19 PM, Blue Swirl wrote: >> >> On Sat, Jun 11, 2011 at 1:29 AM, Michael Tokarev wrote: >>> >>> I've given up on this one. Personally I don't need >>> this stuff for my win7 guests since I can hack either >>> bios or the O/S loader to include all the necessary >>> verifications for the win7 activation to work. I >>> tried to make this process to be legal (no hacks >>> or "cracks" needed) and easy for others, but since >>> noone is interested in this after 6 versions and 5 >>> resends, I wont continue - what I am trying to achieve >>> by pushing this so hard, after all? >>> >>> Thanks to everyone who gave (mostly code style) comments - >>> at least I know the changes has been read by someone. >>> >>> Frustrated, >> >> Sorry about that. I get this error: >> /src/qemu/hw/acpi.c: In function 'acpi_table_add': >> /src/qemu/hw/acpi.c:167: error: format '%u' expects type 'unsigned >> int', but argument 4 has type 'size_t' >> >>> /mjt >>> >>> 12.05.2011 18:44, Michael Tokarev wrote: This patch almost rewrites acpi_table_add() function (but still leaves it using old get_param_value() interface). The result is that it's now possible to specify whole table (together with a header) in an external file, instead of just data portion, with a new file= parameter, but at the same time it's still possible to specify header fields as before. Now with the checkpatch.pl formatting fixes, thanks to Stefan Hajnoczi for suggestions, with changes from Isaku Yamahata, and with my further refinements. v5: rediffed against current qemu/master. v6: fix one "} else {" coding style defect (noted by Blue Swirl) Signed-off-by: Michael Tokarev --- hw/acpi.c | 292 --- qemu-options.hx | 7 +- 2 files changed, 175 insertions(+), 124 deletions(-) diff --git a/hw/acpi.c b/hw/acpi.c index ad40fb4..4316189 100644 --- a/hw/acpi.c +++ b/hw/acpi.c @@ -22,17 +22,29 @@ struct acpi_table_header { - char signature [4]; /* ACPI signature (4 ASCII characters) */ + uint16_t _length; /* our length, not actual part of the hdr */ + /* XXX why we have 2 length fields here? */ + char sig[4]; /* ACPI signature (4 ASCII characters) */ uint32_t length; /* Length of table, in bytes, including header */ uint8_t revision; /* ACPI Specification minor version # */ uint8_t checksum; /* To make sum of entire table == 0 */ - char oem_id [6]; /* OEM identification */ - char oem_table_id [8]; /* OEM table identification */ + char oem_id[6]; /* OEM identification */ + char oem_table_id[8]; /* OEM table identification */ uint32_t oem_revision; /* OEM revision number */ - char asl_compiler_id [4]; /* ASL compiler vendor ID */ + char asl_compiler_id[4]; /* ASL compiler vendor ID */ uint32_t asl_compiler_revision; /* ASL compiler revision number */ } __attribute__((packed)); +#define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header) +#define ACPI_TABLE_PFX_SIZE sizeof(uint16_t) /* size of the extra prefix */ + +static const char dfl_hdr[ACPI_TABLE_HDR_SIZE] = + "\0\0" /* fake _length (2) */ + "QEMU\0\0\0\0\1\0" /* sig (4), len(4), revno (1), csum (1) */ + "QEMUQEQEMUQEMU\1\0\0\0" /* OEM id (6), table (8), revno (4) */ + "QEMU\1\0\0\0" /* ASL compiler ID (4), version (4) */ + ; + char *acpi_tables; size_t acpi_tables_len; @@ -45,158 +57,192 @@ static int acpi_checksum(const uint8_t *data, int len) return (-sum)& 0xff; } +/* like strncpy() but zero-fills the tail of destination */ +static void strzcpy(char *dst, const char *src, size_t size) +{ + size_t len = strlen(src); + if (len>= size) { + len = size; + } else { + memset(dst + len, 0, size - len); + } + memcpy(dst, src, len); +} + +/* XXX fixme: this function uses obsolete argument parsing interface */ int acpi_table_add(const char *t) { - static const char *dfl_id = "QEMUQEMU"; char buf[1024], *p, *f; - struct acpi_table_header acpi_hdr; unsigned long val; - uint32_t length; - struct acpi_table_header *acpi_hdr_p;
[Qemu-devel] [RFC][PATCH 5/9] qcow2: Use coroutines
Signed-off-by: Kevin Wolf --- block/qcow2-cluster.c | 26 +++--- block/qcow2.c | 240 ++--- block/qcow2.h |5 +- 3 files changed, 102 insertions(+), 169 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 882f50a..81cf77d 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -697,12 +697,12 @@ err: * m->depends_on is set to NULL and the other fields in m are meaningless. * * If the cluster is newly allocated, m->nb_clusters is set to the number of - * contiguous clusters that have been allocated. This may be 0 if the request - * conflict with another write request in flight; in this case, m->depends_on - * is set and the remaining fields of m are meaningless. + * contiguous clusters that have been allocated. In this case, the other + * fields of m are valid and contain information about the first allocated + * cluster. * - * If m->nb_clusters is non-zero, the other fields of m are valid and contain - * information about the first allocated cluster. + * If the request conflicts with another write request in flight, the coroutine + * is queued and will be reentered when the dependency has completed. * * Return 0 on success and -errno in error cases */ @@ -721,6 +721,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, return ret; } +again: nb_clusters = size_to_clusters(s, n_end << 9); nb_clusters = MIN(nb_clusters, s->l2_size - l2_index); @@ -792,12 +793,12 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, } if (nb_clusters == 0) { -/* Set dependency and wait for a callback */ -m->depends_on = old_alloc; -m->nb_clusters = 0; -*num = 0; - -goto out_wait_dependency; +/* Wait for the dependency to complete. We need to recheck + * the free/allocated clusters when we continue. */ +qemu_co_mutex_unlock(&s->lock); +qemu_co_queue_wait(&old_alloc->dependent_requests); +qemu_co_mutex_lock(&s->lock); +goto again; } } } @@ -834,9 +835,6 @@ out: return 0; -out_wait_dependency: -return qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); - fail: qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); fail_put: diff --git a/block/qcow2.c b/block/qcow2.c index 48e1b95..f07d550 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -276,6 +276,9 @@ static int qcow2_open(BlockDriverState *bs, int flags) goto fail; } +/* Initialise locks */ +qemu_co_mutex_init(&s->lock); + #ifdef DEBUG_ALLOC qcow2_check_refcounts(bs); #endif @@ -379,7 +382,6 @@ typedef struct QCowAIOCB { uint64_t cluster_offset; uint8_t *cluster_data; bool is_write; -BlockDriverAIOCB *hd_aiocb; QEMUIOVector hd_qiov; QEMUBH *bh; QCowL2Meta l2meta; @@ -389,8 +391,6 @@ typedef struct QCowAIOCB { static void qcow2_aio_cancel(BlockDriverAIOCB *blockacb) { QCowAIOCB *acb = container_of(blockacb, QCowAIOCB, common); -if (acb->hd_aiocb) -bdrv_aio_cancel(acb->hd_aiocb); qemu_aio_release(acb); } @@ -399,46 +399,16 @@ static AIOPool qcow2_aio_pool = { .cancel = qcow2_aio_cancel, }; -static void qcow2_aio_read_cb(void *opaque, int ret); -static void qcow2_aio_write_cb(void *opaque, int ret); - -static void qcow2_aio_rw_bh(void *opaque) -{ -QCowAIOCB *acb = opaque; -qemu_bh_delete(acb->bh); -acb->bh = NULL; - -if (acb->is_write) { -qcow2_aio_write_cb(opaque, 0); -} else { -qcow2_aio_read_cb(opaque, 0); -} -} - -static int qcow2_schedule_bh(QEMUBHFunc *cb, QCowAIOCB *acb) -{ -if (acb->bh) -return -EIO; - -acb->bh = qemu_bh_new(cb, acb); -if (!acb->bh) -return -EIO; - -qemu_bh_schedule(acb->bh); - -return 0; -} - -static void qcow2_aio_read_cb(void *opaque, int ret) +/* + * Returns 0 when the request is completed successfully, 1 when there is still + * a part left to do and -errno in error cases. + */ +static int qcow2_aio_read_cb(QCowAIOCB *acb) { -QCowAIOCB *acb = opaque; BlockDriverState *bs = acb->common.bs; BDRVQcowState *s = bs->opaque; int index_in_cluster, n1; - -acb->hd_aiocb = NULL; -if (ret < 0) -goto done; +int ret; /* post process the read buffer */ if (!acb->cluster_offset) { @@ -463,8 +433,7 @@ static void qcow2_aio_read_cb(void *opaque, int ret) if (acb->remaining_sectors == 0) { /* request completed */ -ret = 0; -goto done; +return 0; } /* prepare next AIO request */ @@ -477,7 +446,7 @@ static void qcow2_aio_read_cb(void *opaque, int ret) ret = qcow2_get_cluster_offset(bs, acb->sector_num << 9, &acb->cur_nr_sect
[Qemu-devel] [RFC][PATCH 2/9] block: Emulate AIO functions with bdrv_co_readv/writev
Use the bdrv_co_readv/writev callbacks to implement bdrv_aio_readv/writev and bdrv_read/write if a driver provides the coroutine version instead of the synchronous or AIO version. Signed-off-by: Kevin Wolf --- block.c | 98 ++- 1 files changed, 97 insertions(+), 1 deletions(-) diff --git a/block.c b/block.c index a57d168..79a5008 100644 --- a/block.c +++ b/block.c @@ -28,6 +28,7 @@ #include "block_int.h" #include "module.h" #include "qemu-objects.h" +#include "qemu-coroutine.h" #ifdef CONFIG_BSD #include @@ -57,6 +58,12 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors); static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors); +static BlockDriverAIOCB *bdrv_co_aio_readv_em(BlockDriverState *bs, +int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, +BlockDriverCompletionFunc *cb, void *opaque); +static BlockDriverAIOCB *bdrv_co_aio_writev_em(BlockDriverState *bs, +int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, +BlockDriverCompletionFunc *cb, void *opaque); static QTAILQ_HEAD(, BlockDriverState) bdrv_states = QTAILQ_HEAD_INITIALIZER(bdrv_states); @@ -169,7 +176,13 @@ void path_combine(char *dest, int dest_size, void bdrv_register(BlockDriver *bdrv) { -if (!bdrv->bdrv_aio_readv) { +if (bdrv->bdrv_co_readv) { +/* Emulate AIO by coroutines, and sync by AIO */ +bdrv->bdrv_aio_readv = bdrv_co_aio_readv_em; +bdrv->bdrv_aio_writev = bdrv_co_aio_writev_em; +bdrv->bdrv_read = bdrv_read_em; +bdrv->bdrv_write = bdrv_write_em; + } else if (!bdrv->bdrv_aio_readv) { /* add AIO emulation layer */ bdrv->bdrv_aio_readv = bdrv_aio_readv_em; bdrv->bdrv_aio_writev = bdrv_aio_writev_em; @@ -2607,6 +2620,89 @@ static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs, return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1); } + +typedef struct BlockDriverAIOCBCoroutine { +BlockDriverAIOCB common; +BlockRequest req; +bool is_write; +QEMUBH* bh; +} BlockDriverAIOCBCoroutine; + +static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb) +{ +qemu_aio_flush(); +} + +static AIOPool bdrv_em_co_aio_pool = { +.aiocb_size = sizeof(BlockDriverAIOCBCoroutine), +.cancel = bdrv_aio_co_cancel_em, +}; + +static void bdrv_co_rw_bh(void *opaque) +{ +BlockDriverAIOCBCoroutine *acb = opaque; + +acb->common.cb(acb->common.opaque, acb->req.error); +qemu_bh_delete(acb->bh); +qemu_aio_release(acb); +} + +static void coroutine_fn bdrv_co_rw(void *opaque) +{ +BlockDriverAIOCBCoroutine *acb = opaque; +BlockDriverState *bs = acb->common.bs; + +if (acb->is_write) { +acb->req.error = bs->drv->bdrv_co_readv(bs, acb->req.sector, +acb->req.nb_sectors, acb->req.qiov); +} else { +acb->req.error = bs->drv->bdrv_co_writev(bs, acb->req.sector, +acb->req.nb_sectors, acb->req.qiov); +} + +acb->bh = qemu_bh_new(bdrv_co_rw_bh, acb); +qemu_bh_schedule(acb->bh); +} + +static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, + int nb_sectors, + BlockDriverCompletionFunc *cb, + void *opaque, + bool is_write) +{ +Coroutine *co; +BlockDriverAIOCBCoroutine *acb; + +acb = qemu_aio_get(&bdrv_em_co_aio_pool, bs, cb, opaque); +acb->req.sector = sector_num; +acb->req.nb_sectors = nb_sectors; +acb->req.qiov = qiov; +acb->is_write = is_write; + +co = qemu_coroutine_create(bdrv_co_rw); +qemu_coroutine_enter(co, acb); + +return &acb->common; +} + +static BlockDriverAIOCB *bdrv_co_aio_readv_em(BlockDriverState *bs, +int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, +BlockDriverCompletionFunc *cb, void *opaque) +{ +return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, + false); +} + +static BlockDriverAIOCB *bdrv_co_aio_writev_em(BlockDriverState *bs, +int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, +BlockDriverCompletionFunc *cb, void *opaque) +{ +return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, + true); +} + static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { -- 1.7.6
[Qemu-devel] [RFC][PATCH 6/9] qcow: Use coroutines
The old qcow format is another user of the AsyncContext infrastructure. Converting it to coroutines (and therefore CoMutexes) allows to remove AsyncContexts. Signed-off-by: Kevin Wolf --- block/qcow.c | 180 -- 1 files changed, 62 insertions(+), 118 deletions(-) diff --git a/block/qcow.c b/block/qcow.c index 227b104..6f7973c 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -73,6 +73,7 @@ typedef struct BDRVQcowState { uint32_t crypt_method_header; AES_KEY aes_encrypt_key; AES_KEY aes_decrypt_key; +CoMutex lock; } BDRVQcowState; static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset); @@ -517,11 +518,11 @@ static AIOPool qcow_aio_pool = { static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, -BlockDriverCompletionFunc *cb, void *opaque, int is_write) +int is_write) { QCowAIOCB *acb; -acb = qemu_aio_get(&qcow_aio_pool, bs, cb, opaque); +acb = qemu_aio_get(&qcow_aio_pool, bs, NULL, NULL); if (!acb) return NULL; acb->hd_aiocb = NULL; @@ -542,48 +543,15 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs, return acb; } -static void qcow_aio_read_cb(void *opaque, int ret); -static void qcow_aio_write_cb(void *opaque, int ret); - -static void qcow_aio_rw_bh(void *opaque) -{ -QCowAIOCB *acb = opaque; -qemu_bh_delete(acb->bh); -acb->bh = NULL; - -if (acb->is_write) { -qcow_aio_write_cb(opaque, 0); -} else { -qcow_aio_read_cb(opaque, 0); -} -} - -static int qcow_schedule_bh(QEMUBHFunc *cb, QCowAIOCB *acb) -{ -if (acb->bh) { -return -EIO; -} - -acb->bh = qemu_bh_new(cb, acb); -if (!acb->bh) { -return -EIO; -} - -qemu_bh_schedule(acb->bh); - -return 0; -} - -static void qcow_aio_read_cb(void *opaque, int ret) +static int qcow_aio_read_cb(void *opaque) { QCowAIOCB *acb = opaque; BlockDriverState *bs = acb->common.bs; BDRVQcowState *s = bs->opaque; int index_in_cluster; +int ret; acb->hd_aiocb = NULL; -if (ret < 0) -goto done; redo: /* post process the read buffer */ @@ -605,8 +573,8 @@ static void qcow_aio_read_cb(void *opaque, int ret) if (acb->nb_sectors == 0) { /* request completed */ -ret = 0; -goto done; +qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size); +return 0; } /* prepare next AIO request */ @@ -623,11 +591,12 @@ static void qcow_aio_read_cb(void *opaque, int ret) acb->hd_iov.iov_base = (void *)acb->buf; acb->hd_iov.iov_len = acb->n * 512; qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1); -acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num, -&acb->hd_qiov, acb->n, qcow_aio_read_cb, acb); -if (acb->hd_aiocb == NULL) { -ret = -EIO; -goto done; +qemu_co_mutex_unlock(&s->lock); +ret = bdrv_co_readv(bs->backing_hd, acb->sector_num, +acb->n, &acb->hd_qiov); +qemu_co_mutex_lock(&s->lock); +if (ret < 0) { +return -EIO; } } else { /* Note: in this case, no need to wait */ @@ -637,64 +606,55 @@ static void qcow_aio_read_cb(void *opaque, int ret) } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) { /* add AIO support for compressed blocks ? */ if (decompress_cluster(bs, acb->cluster_offset) < 0) { -ret = -EIO; -goto done; +return -EIO; } memcpy(acb->buf, s->cluster_cache + index_in_cluster * 512, 512 * acb->n); goto redo; } else { if ((acb->cluster_offset & 511) != 0) { -ret = -EIO; -goto done; +return -EIO; } acb->hd_iov.iov_base = (void *)acb->buf; acb->hd_iov.iov_len = acb->n * 512; qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1); -acb->hd_aiocb = bdrv_aio_readv(bs->file, +qemu_co_mutex_unlock(&s->lock); +ret = bdrv_co_readv(bs->file, (acb->cluster_offset >> 9) + index_in_cluster, -&acb->hd_qiov, acb->n, qcow_aio_read_cb, acb); -if (acb->hd_aiocb == NULL) { -ret = -EIO; -goto done; +acb->n, &acb->hd_qiov); +qemu_co_mutex_lock(&s->lock); +if (ret < 0) { +return ret; } } -return; - -done: -if (acb->qiov->niov > 1) { -qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size); -qemu_vfree(acb->orig_buf); -} -acb->common.cb(acb->common.opaque, ret); -qemu_aio_release(acb); +return 1; } -stati
Re: [Qemu-devel] [PATCH v7 4/4] guest agent: add guest agent RPCs/commands
On 07/15/2011 11:23 AM, Luiz Capitulino wrote: On Thu, 14 Jul 2011 15:00:34 -0500 Michael Roth wrote: This adds the initial set of QMP/QAPI commands provided by the guest agent: guest-sync guest-ping guest-info guest-shutdown guest-file-open guest-file-read guest-file-write guest-file-seek guest-file-flush guest-file-close guest-fsfreeze-freeze guest-fsfreeze-thaw guest-fsfreeze-status The input/output specification for these commands are documented in the schema. Example usage: host: qemu -device virtio-serial \ -chardev socket,path=/tmp/vs0.sock,server,nowait,id=qga0 \ -device virtserialport,chardev=qga0,name=org.qemu.quest_agent.0 ... echo "{'execute':'guest-info'}" | socat stdio unix-connect:/tmp/qga0.sock guest: qemu-ga -m virtio-serial -p /dev/virtio-ports/org.qemu.guest_agent.0 \ -p /var/run/qemu-guest-agent.pid -d Signed-off-by: Michael Roth --- Makefile | 15 ++- qapi-schema-guest.json | 217 +++ qemu-ga.c |4 + qerror.c |8 + qerror.h |6 + qga/guest-agent-commands.c | 512 qga/guest-agent-core.h |2 + 7 files changed, 762 insertions(+), 2 deletions(-) create mode 100644 qapi-schema-guest.json create mode 100644 qga/guest-agent-commands.c diff --git a/Makefile b/Makefile index b2e8593..f98e127 100644 --- a/Makefile +++ b/Makefile @@ -175,15 +175,26 @@ $(qapi-dir)/test-qmp-commands.h: $(qapi-dir)/test-qmp-marshal.c $(qapi-dir)/test-qmp-marshal.c: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py $(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "test-"< $<, " GEN $@") +$(qapi-dir)/qga-qapi-types.c: $(qapi-dir)/qga-qapi-types.h +$(qapi-dir)/qga-qapi-types.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-types.py + $(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "qga-"< $<, " GEN $@") +$(qapi-dir)/qga-qapi-visit.c: $(qapi-dir)/qga-qapi-visit.h +$(qapi-dir)/qga-qapi-visit.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-visit.py + $(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "qga-"< $<, " GEN $@") +$(qapi-dir)/qga-qmp-marshal.c: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-commands.py + $(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "qga-"< $<, " GEN $@") + test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) test-visitor: test-visitor.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c test-qmp-commands.h) test-qmp-commands: test-qmp-commands.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o -QGALIB=qga/guest-agent-command-state.o +QGALIB=qga/guest-agent-command-state.o qga/guest-agent-commands.o + +qemu-ga.o: $(qapi-dir)/qga-qapi-types.c $(qapi-dir)/qga-qapi-types.h $(qapi-dir)/qga-qapi-visit.c $(qapi-dir)/qga-qmp-marshal.c -qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o qapi/qmp-dispatch.o qapi/qmp-registry.o +qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o qapi/qmp-dispatch.o qapi/qmp-registry.o $(qapi-dir)/qga-qapi-visit.o $(qapi-dir)/qga-qapi-types.o $(qapi-dir)/qga-qmp-marshal.o QEMULIBS=libhw32 libhw64 libuser libdis libdis-user diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json new file mode 100644 index 000..a18d6f8 --- /dev/null +++ b/qapi-schema-guest.json @@ -0,0 +1,217 @@ +# *-*- Mode: Python -*-* + +## +# @guest-sync: +# +# Echo back a unique integer value +# +# This is used by clients talking to the guest agent over the +# wire to ensure the stream is in sync and doesn't contain stale +# data from previous client. All guest agent responses should be +# ignored until the provided unique integer value is returned, +# and it is up to the client to handle stale whole or +# partially-d
[Qemu-devel] [RFC][PATCH 9/9] block: Use bdrv_co_* instead of synchronous versions in coroutines
If we're already in a coroutine, there is no reason to use the synchronous version of block layer functions when a coroutine one exists. This makes bdrv_read/write/flush use bdrv_co_* when used inside a coroutine. Signed-off-by: Kevin Wolf --- block.c | 43 +++ 1 files changed, 43 insertions(+), 0 deletions(-) diff --git a/block.c b/block.c index 18d1197..a4990b4 100644 --- a/block.c +++ b/block.c @@ -70,6 +70,7 @@ static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs, static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *iov); +static int coroutine_fn bdrv_co_flush_em(BlockDriverState *bs); static QTAILQ_HEAD(, BlockDriverState) bdrv_states = QTAILQ_HEAD_INITIALIZER(bdrv_states); @@ -950,6 +951,17 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num, { BlockDriver *drv = bs->drv; +if (qemu_in_coroutine()) { +QEMUIOVector qiov; +struct iovec iov = { +.iov_base = (void *)buf, +.iov_len = nb_sectors * BDRV_SECTOR_SIZE, +}; + +qemu_iovec_init_external(&qiov, &iov, 1); +return bdrv_co_readv(bs, sector_num, nb_sectors, &qiov); +} + if (!drv) return -ENOMEDIUM; if (bdrv_check_request(bs, sector_num, nb_sectors)) @@ -996,6 +1008,18 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors) { BlockDriver *drv = bs->drv; + +if (qemu_in_coroutine()) { +QEMUIOVector qiov; +struct iovec iov = { +.iov_base = (void *)buf, +.iov_len = nb_sectors * BDRV_SECTOR_SIZE, +}; + +qemu_iovec_init_external(&qiov, &iov, 1); +return bdrv_co_writev(bs, sector_num, nb_sectors, &qiov); +} + if (!bs->drv) return -ENOMEDIUM; if (bs->read_only) @@ -1642,6 +1666,10 @@ int bdrv_flush(BlockDriverState *bs) return 0; } +if (qemu_in_coroutine()) { +return bdrv_co_flush_em(bs); +} + if (bs->drv && bs->drv->bdrv_flush) { return bs->drv->bdrv_flush(bs); } @@ -2910,6 +2938,21 @@ static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs, return bdrv_co_io_em(bs, sector_num, nb_sectors, iov, true); } +static int coroutine_fn bdrv_co_flush_em(BlockDriverState *bs) +{ +CoroutineIOCompletion co = { +.coroutine = qemu_coroutine_self(), +}; +BlockDriverAIOCB *acb; + +acb = bdrv_aio_flush(bs, bdrv_co_io_em_complete, &co); +if (!acb) { +return -EIO; +} +qemu_coroutine_yield(); +return co.ret; +} + /**/ /* removable device support */ -- 1.7.6
[Qemu-devel] [RFC][PATCH 7/9] async: Remove AsyncContext
The purpose of AsyncContexts was to protect qcow and qcow2 against reentrancy during an emulated bdrv_read/write (which includes a qemu_aio_wait() call and can run AIO callbacks of different requests if it weren't for AsyncContexts). Now both qcow and qcow2 are protected by CoMutexes and AsyncContexts can be removed. Signed-off-by: Kevin Wolf --- async.c| 98 block.c|6 --- block/qed-table.c | 14 --- block/qed.c|4 -- linux-aio.c| 24 + posix-aio-compat.c | 11 -- qemu-common.h |4 -- 7 files changed, 9 insertions(+), 152 deletions(-) diff --git a/async.c b/async.c index fd313df..3fe70b9 100644 --- a/async.c +++ b/async.c @@ -25,92 +25,8 @@ #include "qemu-common.h" #include "qemu-aio.h" -/* - * An AsyncContext protects the callbacks of AIO requests and Bottom Halves - * against interfering with each other. A typical example is qcow2 that accepts - * asynchronous requests, but relies for manipulation of its metadata on - * synchronous bdrv_read/write that doesn't trigger any callbacks. - * - * However, these functions are often emulated using AIO which means that AIO - * callbacks must be run - but at the same time we must not run callbacks of - * other requests as they might start to modify metadata and corrupt the - * internal state of the caller of bdrv_read/write. - * - * To achieve the desired semantics we switch into a new AsyncContext. - * Callbacks must only be run if they belong to the current AsyncContext. - * Otherwise they need to be queued until their own context is active again. - * This is how you can make qemu_aio_wait() wait only for your own callbacks. - * - * The AsyncContexts form a stack. When you leave a AsyncContexts, you always - * return to the old ("parent") context. - */ -struct AsyncContext { -/* Consecutive number of the AsyncContext (position in the stack) */ -int id; - -/* Anchor of the list of Bottom Halves belonging to the context */ -struct QEMUBH *first_bh; - -/* Link to parent context */ -struct AsyncContext *parent; -}; - -/* The currently active AsyncContext */ -static struct AsyncContext *async_context = &(struct AsyncContext) { 0 }; - -/* - * Enter a new AsyncContext. Already scheduled Bottom Halves and AIO callbacks - * won't be called until this context is left again. - */ -void async_context_push(void) -{ -struct AsyncContext *new = qemu_mallocz(sizeof(*new)); -new->parent = async_context; -new->id = async_context->id + 1; -async_context = new; -} - -/* Run queued AIO completions and destroy Bottom Half */ -static void bh_run_aio_completions(void *opaque) -{ -QEMUBH **bh = opaque; -qemu_bh_delete(*bh); -qemu_free(bh); -qemu_aio_process_queue(); -} -/* - * Leave the currently active AsyncContext. All Bottom Halves belonging to the - * old context are executed before changing the context. - */ -void async_context_pop(void) -{ -struct AsyncContext *old = async_context; -QEMUBH **bh; - -/* Flush the bottom halves, we don't want to lose them */ -while (qemu_bh_poll()); - -/* Switch back to the parent context */ -async_context = async_context->parent; -qemu_free(old); - -if (async_context == NULL) { -abort(); -} - -/* Schedule BH to run any queued AIO completions as soon as possible */ -bh = qemu_malloc(sizeof(*bh)); -*bh = qemu_bh_new(bh_run_aio_completions, bh); -qemu_bh_schedule(*bh); -} - -/* - * Returns the ID of the currently active AsyncContext - */ -int get_async_context_id(void) -{ -return async_context->id; -} +/* Anchor of the list of Bottom Halves belonging to the context */ +static struct QEMUBH *first_bh; /***/ /* bottom halves (can be seen as timers which expire ASAP) */ @@ -130,8 +46,8 @@ QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque) bh = qemu_mallocz(sizeof(QEMUBH)); bh->cb = cb; bh->opaque = opaque; -bh->next = async_context->first_bh; -async_context->first_bh = bh; +bh->next = first_bh; +first_bh = bh; return bh; } @@ -141,7 +57,7 @@ int qemu_bh_poll(void) int ret; ret = 0; -for (bh = async_context->first_bh; bh; bh = next) { +for (bh = first_bh; bh; bh = next) { next = bh->next; if (!bh->deleted && bh->scheduled) { bh->scheduled = 0; @@ -153,7 +69,7 @@ int qemu_bh_poll(void) } /* remove deleted bhs */ -bhp = &async_context->first_bh; +bhp = &first_bh; while (*bhp) { bh = *bhp; if (bh->deleted) { @@ -199,7 +115,7 @@ void qemu_bh_update_timeout(int *timeout) { QEMUBH *bh; -for (bh = async_context->first_bh; bh; bh = bh->next) { +for (bh = first_bh; bh; bh = bh->next) { if (!bh->deleted && bh->scheduled) { if (bh->idle) { /* idle bottom halves
Re: [Qemu-devel] [PATCH 4/5] xen: Fix the memory registration to reflect of what is done by Xen.
On Fri, 15 Jul 2011, Anthony PERARD wrote: > A Xen guest memory is allocated by libxc. But this memory is not > allocated continuously, instead, it leaves the VGA IO memory space not > allocated, same for the MMIO space (at HVM_BELOW_4G_MMIO_START of size > HVM_BELOW_4G_MMIO_LENGTH). > > So to reflect that, we do not register the physical memory for this two > holes. But we still keep only one RAMBlock for the all RAM as it is more > easier than have two separate blocks (1 above 4G). Also this prevent QEMU > from use the MMIO space for a ROM. > > Signed-off-by: Anthony PERARD > --- > xen-all.c | 21 ++--- > 1 files changed, 14 insertions(+), 7 deletions(-) > > diff --git a/xen-all.c b/xen-all.c > index 2c0a62d..76d5c5c 100644 > --- a/xen-all.c > +++ b/xen-all.c > @@ -144,6 +144,12 @@ static void xen_ram_init(ram_addr_t ram_size) > new_block->host = NULL; > new_block->offset = 0; > new_block->length = ram_size; > +if (ram_size >= HVM_BELOW_4G_RAM_END) { > +/* Xen does not allocate the memory continuously, and keep a hole at > + * HVM_BELOW_4G_MMIO_START of HVM_BELOW_4G_MMIO_LENGTH > + */ > +new_block->length += HVM_BELOW_4G_MMIO_LENGTH; > +} > > QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next); > > @@ -152,20 +158,21 @@ static void xen_ram_init(ram_addr_t ram_size) > memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS), > 0xff, new_block->length >> TARGET_PAGE_BITS); > > -if (ram_size >= 0xe000 ) { > -above_4g_mem_size = ram_size - 0xe000; > -below_4g_mem_size = 0xe000; > +if (ram_size >= HVM_BELOW_4G_RAM_END) { > +above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END; > +below_4g_mem_size = HVM_BELOW_4G_RAM_END; > } else { > below_4g_mem_size = ram_size; > } > > -cpu_register_physical_memory(0, below_4g_mem_size, new_block->offset); > -#if TARGET_PHYS_ADDR_BITS > 32 > +cpu_register_physical_memory(0, 0xa, 0); > +/* Skip of the VGA IO memory space */ > +cpu_register_physical_memory(0xc, below_4g_mem_size - 0xc, > + 0xc); Shouldn't we avoid registering any memory for the whole video ram area? I mean: 0xa - 0x10
Re: [Qemu-devel] [PATCH 0/5] Enable QEMU to handle more than 2GB with Xen.
On Fri, 15 Jul 2011, Anthony PERARD wrote: > Hi all, > > Xen is not limited by the QEMU's virtual address space for the allocation of > the guest RAM. So even with a QEMU 32bits, a Xen guest can have more than 4 GB > of RAM. > > With this serie, we will be able to run a guest with more than 4GB. The main > point is to change ram_addr_t from ulong to uin64 when QEMU is configure with > Xen. The second point is better register the memory in QEMU. > > Regards, > > > Anthony PERARD (5): > xen: Fix xen_enabled(). > exec.c: Use ram_addr_t in cpu_physical_memory_rw(...). > cpu-common: Have a ram_addr_t of uint64 with Xen. > xen: Fix the memory registration to reflect of what is done by Xen. > vl.c: Check the asked ram_size later. > > cpu-common.h |8 > exec.c | 13 +++-- > hw/xen.h |2 +- > vl.c | 14 -- > xen-all.c| 23 +++ > 5 files changed, 39 insertions(+), 21 deletions(-) All the patches look good to me, just a comment on the 4th patch.
Re: [Qemu-devel] Wiki spam
Am 04.07.2011 10:05, schrieb Stefan Hajnoczi: On Mon, Jul 4, 2011 at 8:27 AM, Brad Hards wrote: On Mon, 4 Jul 2011 03:15:06 PM Stefan Hajnoczi wrote: Thanks. I have a regular wiki account so I checked the Recent Changes page and undid the spam changes that I saw: http://wiki.qemu.org/Special:RecentChanges Is there a way to completely remove it? There is still spam on the wiki showing at: http://wiki.qemu.org/index.php?title=Special:DeadendPages&limit=500&offset=0 I'd prefer not to have it in the history at all if thats possible. Only an administrator can delete pages: http://www.mediawiki.org/wiki/Help:Deleting_a_page Stefan Wiki spammers are still very active on qemu.org (see http://wiki.qemu.org/Special:RecentChanges). The QEMU wiki needs more technical protection against spam and also more administrators who can remove spam pages (I can't, so I simply emptied the pages I just found). Cheers, Stefan Weil
Re: [Qemu-devel] [Xen-devel] Re: [PATCH 4/5] xen: Fix the memory registration to reflect of what is done by Xen.
On Fri, Jul 15, 2011 at 18:05, Stefano Stabellini wrote: > Shouldn't we avoid registering any memory for the whole video ram area? > I mean: > > 0xa - 0x10 No, because SeaBIOS load the Options ROM (VGA Bios, PXE) to the area between 0xc and 0x10, and this go through QEMU. The area between 0xa and 0xc is registred later by the cirrus_vga bits, as IO. -- Anthony PERARD
Re: [Qemu-devel] [PATCH v7 4/4] guest agent: add guest agent RPCs/commands
On Fri, 15 Jul 2011 12:21:55 -0500 Michael Roth wrote: > On 07/15/2011 11:23 AM, Luiz Capitulino wrote: > > On Thu, 14 Jul 2011 15:00:34 -0500 > > Michael Roth wrote: > > > >> This adds the initial set of QMP/QAPI commands provided by the guest > >> agent: > >> > >> guest-sync > >> guest-ping > >> guest-info > >> guest-shutdown > >> guest-file-open > >> guest-file-read > >> guest-file-write > >> guest-file-seek > >> guest-file-flush > >> guest-file-close > >> guest-fsfreeze-freeze > >> guest-fsfreeze-thaw > >> guest-fsfreeze-status > >> > >> The input/output specification for these commands are documented in the > >> schema. > >> > >> Example usage: > >> > >>host: > >> qemu -device virtio-serial \ > >> -chardev socket,path=/tmp/vs0.sock,server,nowait,id=qga0 \ > >> -device virtserialport,chardev=qga0,name=org.qemu.quest_agent.0 > >> ... > >> > >> echo "{'execute':'guest-info'}" | socat stdio > >> unix-connect:/tmp/qga0.sock > >> > >>guest: > >> qemu-ga -m virtio-serial -p /dev/virtio-ports/org.qemu.guest_agent.0 \ > >> -p /var/run/qemu-guest-agent.pid -d > >> > >> Signed-off-by: Michael Roth > >> --- > >> Makefile | 15 ++- > >> qapi-schema-guest.json | 217 +++ > >> qemu-ga.c |4 + > >> qerror.c |8 + > >> qerror.h |6 + > >> qga/guest-agent-commands.c | 512 > >> > >> qga/guest-agent-core.h |2 + > >> 7 files changed, 762 insertions(+), 2 deletions(-) > >> create mode 100644 qapi-schema-guest.json > >> create mode 100644 qga/guest-agent-commands.c > >> > >> diff --git a/Makefile b/Makefile > >> index b2e8593..f98e127 100644 > >> --- a/Makefile > >> +++ b/Makefile > >> @@ -175,15 +175,26 @@ $(qapi-dir)/test-qmp-commands.h: > >> $(qapi-dir)/test-qmp-marshal.c > >> $(qapi-dir)/test-qmp-marshal.c: $(SRC_PATH)/qapi-schema-test.json > >> $(SRC_PATH)/scripts/qapi-commands.py > >>$(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py -o > >> "$(qapi-dir)" -p "test-"< $<, " GEN $@") > >> > >> +$(qapi-dir)/qga-qapi-types.c: $(qapi-dir)/qga-qapi-types.h > >> +$(qapi-dir)/qga-qapi-types.h: $(SRC_PATH)/qapi-schema-guest.json > >> $(SRC_PATH)/scripts/qapi-types.py > >> + $(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py -o > >> "$(qapi-dir)" -p "qga-"< $<, " GEN $@") > >> +$(qapi-dir)/qga-qapi-visit.c: $(qapi-dir)/qga-qapi-visit.h > >> +$(qapi-dir)/qga-qapi-visit.h: $(SRC_PATH)/qapi-schema-guest.json > >> $(SRC_PATH)/scripts/qapi-visit.py > >> + $(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py -o > >> "$(qapi-dir)" -p "qga-"< $<, " GEN $@") > >> +$(qapi-dir)/qga-qmp-marshal.c: $(SRC_PATH)/qapi-schema-guest.json > >> $(SRC_PATH)/scripts/qapi-commands.py > >> + $(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py -o > >> "$(qapi-dir)" -p "qga-"< $<, " GEN $@") > >> + > >> test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c > >> test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) > >> test-visitor: test-visitor.o qfloat.o qint.o qdict.o qstring.o qlist.o > >> qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o > >> json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o > >> qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o > >> > >> test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c > >> test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c > >> test-qmp-commands.h) > >> test-qmp-commands: test-qmp-commands.o qfloat.o qint.o qdict.o qstring.o > >> qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) > >> qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o > >> qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o > >> $(qapi-dir)/test-qmp-marshal.o module.o > >> > >> -QGALIB=qga/guest-agent-command-state.o > >> +QGALIB=qga/guest-agent-command-state.o qga/guest-agent-commands.o > >> + > >> +qemu-ga.o: $(qapi-dir)/qga-qapi-types.c $(qapi-dir)/qga-qapi-types.h > >> $(qapi-dir)/qga-qapi-visit.c $(qapi-dir)/qga-qmp-marshal.c > >> > >> -qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o > >> $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) > >> $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o > >> qapi/qmp-dispatch.o qapi/qmp-registry.o > >> +qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o > >> $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) > >> $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o > >> qapi/qmp-dispatch.o qapi/qmp-registry.o $(qapi-dir)/qga-qapi-visit.o > >> $(qapi-dir)/qga-qapi-types.o $(qapi-dir)/qga-qmp-marshal.o > >> > >> QEMULIBS=libhw32 libhw64 libuser libdis libdis-user > >> > >>
Re: [Qemu-devel] [PATCHv2 0/3] ds1225y: qdev-ification (used in MIPS Jazz)
Ping ? Hervé Poussineau a écrit : This patchset qdev-ifies the ds1225y device, used in MIPS Jazz emulation. Changes since v1: - rebased - split into multiple patches as per Markus advice Hervé Poussineau (3): ds1225y: Remove protection stuff, which doesn't belong to this device ds1225y: use trace framework ds1225y: convert to qdev device, and use it in MIPS Jazz emulation hw/ds1225y.c | 152 --- hw/mips.h |4 -- hw/mips_jazz.c | 11 +++- trace-events |4 ++ 4 files changed, 90 insertions(+), 81 deletions(-)
[Qemu-devel] [RELEASE] LTTng-UST 0.15 (Qemu support & tutorial)
LTTng-UST, the Linux Trace Toolkit Next Generation Userspace Tracer, is port of the low-overhead tracing capabilities of the LTTng kernel tracer to user-space. The library "libust" enables tracing of applications and libraries. Changelog: * Add backward compability for tracepoint API (still planned for deprecation, but should make the transition smoother). The API transition will happen when UST 2.0 is ready. There is no point in making multiple API breakage when unneeded. tracing qemu-kvm with UST is now working again with UST 0.15 (0.14 did break it). Project website: http://lttng.org/ust/ Download link: http://lttng.org/files/ust/releases/ (please refer to the UST Manual for installation instructions) A quick walkthrough for tracing kvm-qemu with UST: git clone git://git.lttng.org/userspace-rcu.git (install: see README) git clone git://git.lttng.org/ust.git (install: see README) In my case, I enabled qemu_malloc, qemu_realloc, qemu_free, qemu_memalign, qemu_vmalloc, qemu_vfree by editing the "trace-events" file in the toplevel source directory (this file is qemu-specific, not the usual interface UST provides): # qemu-malloc.c qemu_malloc(size_t size, void *ptr) "size %zu ptr %p" qemu_realloc(void *ptr, size_t size, void *newptr) "ptr %p size %zu newptr %p" qemu_free(void *ptr) "ptr %p" # osdep.c qemu_memalign(size_t alignment, size_t size, void *ptr) "alignment %zu size %zu ptr %p" qemu_vmalloc(size_t size, void *ptr) "size %zu ptr %p" qemu_vfree(void *ptr) "ptr %p" ./configure --enable-trace-backend=ust make ldd x86_64-softmmu/qemu-system-x86_64 ... libust.so.0 => /usr/local/lib/libust.so.0 (0x7fa39fc74000) (it's linked with libust) usttrace x86_64-softmmu/qemu-system-x86_64 ... stop it (ctrl-c) See resulting trace in: $HOME/.usttraces/hostname-timestamp UST 0.15 traces can be viewed with lttv: git clone git://git.lttng.org/lttv.git (install: view README) To view the trace (e.g.): % lttv -m textDump -t % /home/compudj/.usttraces/ok-20110715144748823020811/32575_5629652727107472206 ... ust.qemu_free: 1552840.525993542 (/home/compudj/.usttraces/ok-20110715144748823020811/32575_5629652727107472206/ust_6), 0, 0, , , 0, 0x0, MODE_UNKNOWN { ptr = 0x1187680 } ust.qemu_free: 1552840.525994061 (/home/compudj/.usttraces/ok-20110715144748823020811/32575_5629652727107472206/ust_6), 0, 0, , , 0, 0x0, MODE_UNKNOWN { ptr = 0x1187660 } -- Mathieu Desnoyers Operating System Efficiency R&D Consultant EfficiOS Inc. http://www.efficios.com
[Qemu-devel] [PATCH 2/3] w64: Add definition of FMT_pid
For mingw-w64, pid_t is _pid_t which is __int64, so this platform needs its own definition of FMT_pid. Signed-off-by: Stefan Weil --- osdep.h |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/osdep.h b/osdep.h index a817017..252d050 100644 --- a/osdep.h +++ b/osdep.h @@ -130,6 +130,8 @@ int qemu_madvise(void *addr, size_t len, int advice); #if defined(__HAIKU__) && defined(__i386__) #define FMT_pid "%ld" +#elif defined(WIN64) +#define FMT_pid "%" PRId64 #else #define FMT_pid "%d" #endif -- 1.7.2.5
[Qemu-devel] [PATCH 3/3] w32: Fix format string regression
Commit 953ffe0f935f40c0d6061d69e76e0339393b54f8 introduced FMT_pid which is wrong for w32 and w64 getpid(): those getpid() implementations always return an int value. Signed-off-by: Stefan Weil --- os-win32.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/os-win32.c b/os-win32.c index b6652af..e153058 100644 --- a/os-win32.c +++ b/os-win32.c @@ -258,7 +258,7 @@ int qemu_create_pidfile(const char *filename) if (file == INVALID_HANDLE_VALUE) { return -1; } -len = snprintf(buffer, sizeof(buffer), FMT_pid "\n", getpid()); +len = snprintf(buffer, sizeof(buffer), "%d\n", getpid()); ret = WriteFileEx(file, (LPCVOID)buffer, (DWORD)len, &overlap, NULL); if (ret == 0) { -- 1.7.2.5
[Qemu-devel] New patches for w32, w64
Here are some small patches needed for the w32 and w64 platforms. [PATCH 1/3] Fix conversions from pointer to tcg_target_long [PATCH 2/3] w64: Add definition of FMT_pid [PATCH 3/3] w32: Fix format string regression Kind regards, Stefan
[Qemu-devel] [PATCH 1/3] Fix conversions from pointer to tcg_target_long
tcg_gen_exit_tb takes a parameter of type tcg_target_long, so the type casts of pointer to long should be replaced by type casts of pointer to tcg_target_long. These changes are needed for build environments where sizeof(long) != sizeof(void *), especially for w64. See 4b4a72e55660abf7efe85aca78762dcfea5519ad which fixed the same issue for the other targets. Cc: Alexander Graf Cc: Guan Xuetao Signed-off-by: Stefan Weil --- target-s390x/translate.c |2 +- target-unicore32/translate.c |2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 77fb448..6a22fde 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -830,7 +830,7 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc) /* jump to same page: we can use a direct jump */ tcg_gen_goto_tb(tb_num); tcg_gen_movi_i64(psw_addr, pc); -tcg_gen_exit_tb((long)tb + tb_num); +tcg_gen_exit_tb((tcg_target_long)tb + tb_num); } else { /* jump to another page: currently not optimized */ tcg_gen_movi_i64(psw_addr, pc); diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index a15e42d..4ecb0f1 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -1056,7 +1056,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest) if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { tcg_gen_goto_tb(n); gen_set_pc_im(dest); -tcg_gen_exit_tb((long)tb + n); +tcg_gen_exit_tb((tcg_target_long)tb + n); } else { gen_set_pc_im(dest); tcg_gen_exit_tb(0); -- 1.7.2.5
Re: [Qemu-devel] [PATCH] Avoid CPU endian memory accesses in devices
On Fri, Jul 15, 2011 at 12:56 AM, Alexander Graf wrote: > > > > > Am 14.07.2011 um 21:34 schrieb Blue Swirl : > >> Don't compile virtio.c in hwlib, it depends on memory accesses >> performed in CPU endianness. >> >> Make loads and stores in CPU endianness unavailable to devices >> and poison them to avoid further bugs. > > Very nice :). Couldn't test execute it, but: > > Acked-by: Alexander Graf By the way, another way would be to change virtio to always use LE accesses. This would need changes to KVM on PPC and s390x. Would that be possible?
Re: [Qemu-devel] [PATCH 2/3] w64: Add definition of FMT_pid
Am 15.07.2011 um 21:38 schrieb Stefan Weil: For mingw-w64, pid_t is _pid_t which is __int64, so this platform needs its own definition of FMT_pid. Signed-off-by: Stefan Weil Ah, that's probably lld then and thus different from the existing definitions. Reviewed-by: Andreas Färber Andreas --- osdep.h |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/osdep.h b/osdep.h index a817017..252d050 100644 --- a/osdep.h +++ b/osdep.h @@ -130,6 +130,8 @@ int qemu_madvise(void *addr, size_t len, int advice); #if defined(__HAIKU__) && defined(__i386__) #define FMT_pid "%ld" +#elif defined(WIN64) +#define FMT_pid "%" PRId64 #else #define FMT_pid "%d" #endif -- 1.7.2.5
Re: [Qemu-devel] [PATCH 3/3] w32: Fix format string regression
Am 15.07.2011 um 21:38 schrieb Stefan Weil: Commit 953ffe0f935f40c0d6061d69e76e0339393b54f8 introduced FMT_pid which is wrong for w32 and w64 getpid(): those getpid() implementations always return an int value. Where is __int64 FMT_pid used then if not for the returned pid? Andreas Signed-off-by: Stefan Weil --- os-win32.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/os-win32.c b/os-win32.c index b6652af..e153058 100644 --- a/os-win32.c +++ b/os-win32.c @@ -258,7 +258,7 @@ int qemu_create_pidfile(const char *filename) if (file == INVALID_HANDLE_VALUE) { return -1; } -len = snprintf(buffer, sizeof(buffer), FMT_pid "\n", getpid()); +len = snprintf(buffer, sizeof(buffer), "%d\n", getpid()); ret = WriteFileEx(file, (LPCVOID)buffer, (DWORD)len, &overlap, NULL); if (ret == 0) { -- 1.7.2.5
Re: [Qemu-devel] [PATCH] Avoid CPU endian memory accesses in devices
On 07/15/2011 10:02 PM, Blue Swirl wrote: On Fri, Jul 15, 2011 at 12:56 AM, Alexander Graf wrote: Am 14.07.2011 um 21:34 schrieb Blue Swirl: Don't compile virtio.c in hwlib, it depends on memory accesses performed in CPU endianness. Make loads and stores in CPU endianness unavailable to devices and poison them to avoid further bugs. Very nice :). Couldn't test execute it, but: Acked-by: Alexander Graf By the way, another way would be to change virtio to always use LE accesses. This would need changes to KVM on PPC and s390x. Would that be possible? The code is already in Linux for quite a while, other OSs started implementing it (Solaris) and the spec is pretty specific on fields being in target endianness. The virtio v2 spec will hopefully fix this, but that should end up in a different module then :) Alex
Re: [Qemu-devel] Wiki spam
On 07/15/2011 12:24 PM, Stefan Weil wrote: Wiki spammers are still very active on qemu.org (see http://wiki.qemu.org/Special:RecentChanges). The QEMU wiki needs more technical protection against spam and also more administrators who can remove spam pages (I can't, so I simply emptied the pages I just found). There's no simple solution to spam. Even captcha's are limited as many spammers are just using mechanical turks plus OCR to defeat captchas. recaptcha had some problems recently so I had to disable it on the wiki which led to an influx of spam. It seems to be working fine again so I've reenabled it. Hopefully the spam activity will dramatically drop again. Regards, Anthony Liguori Cheers, Stefan Weil
Re: [Qemu-devel] [PATCH] report serial devices created with -device in the PIIX4 config space
Am 15.07.2011 um 17:10 schrieb Paolo Bonzini: Serial and parallel devices created with -device are not reported in the PIIX4 configuration space, and are hence not picked up by the DSDT. This upsets Windows, which hides them altogether from the guest. To avoid this, check at the end of machine initialization whether the corresponding I/O ports have been registered. The new function in ioport.c does this; this also requires a tweak to isa_unassign_ioport. I left the comment in piix4_pm_initfn since the registers I moved do seem to match the 82371AB datasheet. There are some quirks though. We are setting this bit: "Device 8 EIO Enable (EIO_EN_DEV8)—R/W. 1=Enable PCI access to the device 8 enabled I/O ranges to be claimed by PIIX4 and forwarded to the ISA/EIO bus. 0=Disable. The LPT_MON_EN must be set to enable the decode." but not LPT_MON_EN (bit 18 at 50h): LPT Port Enable (LPT_MON_EN)—R/W. 1=Enable accesses to parallel port address range (LPT_DEC_SEL) to generate a device 8 (parallel port) decode event. 0=Disable. We're also setting the LPT_DEC_SEL field (that's the 0x60 written to 63h) to 11, which means reserved, rather than to 01 (378h-37Fh). Likewise we're not setting SA_MON_EN, SB_MON_EN (respectively bit 14 and bit 16 at address 50h) for the serial ports. However, we're setting COMA_DEC_SEL and COMB_DEC_SEL correctly, unlike the corresponding register for the parallel port. All these fields are left as they are, since they are probably only meant to be used in the DSDT. Signed-off-by: Paolo Bonzini --- hw/acpi_piix4.c | 23 ++- ioport.c| 19 +-- ioport.h|2 +- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 350558b..03de3ad 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -311,6 +313,19 @@ static void piix4_powerdown(void *opaque, int irq, int power_failing) acpi_pm1_evt_power_down(pm1a, tmr); } +static void piix4_pm_machine_ready(struct Notifier* n) +{ +PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready); DO_UPCAST()? I assume we have it for a reason. diff --git a/ioport.c b/ioport.c index 2e971fa..0d2611d 100644 --- a/ioport.c +++ b/ioport.c @@ -245,18 +245,25 @@ void isa_unassign_ioport(pio_addr_t start, int length) int i; for(i = start; i < start + length; i++) { -ioport_read_table[0][i] = default_ioport_readb; -ioport_read_table[1][i] = default_ioport_readw; -ioport_read_table[2][i] = default_ioport_readl; +ioport_read_table[0][i] = NULL; +ioport_read_table[1][i] = NULL; +ioport_read_table[2][i] = NULL; -ioport_write_table[0][i] = default_ioport_writeb; -ioport_write_table[1][i] = default_ioport_writew; -ioport_write_table[2][i] = default_ioport_writel; +ioport_write_table[0][i] = NULL; +ioport_write_table[1][i] = NULL; +ioport_write_table[2][i] = NULL; Does this make a change as to whether unhandled I/O ports are reported in debug mode? What do you think of Gleb's recent request to convert all ioports to IORanges? I briefly looked into it but feared that needlessly using uint64_t for all parameters might damage performance on 32-bit hosts. The ioport changes look okay otherwise. Andreas
Re: [Qemu-devel] [RFC] New thread for the VM migration
On 07/15/2011 02:59 AM, Paolo Bonzini wrote: On 07/14/2011 06:07 PM, Avi Kivity wrote: Maybe we can do this via a magic subsection whose contents are the hotplug event. What about making the device list just another "thing" that has to be migrated live, together with block and ram? In an ideal world, you would only create the backends on the destination node and all of the devices would be created through the migration process. Regards, Anthony Liguori Paolo
Re: [Qemu-devel] [PATCH v4] hw/pc: Support system flash memory with -pflash parameter
Hi all, Are there any concerns with this patch? I haven't heard much feedback, except: * Jes Sorensen - March 28 - code style * Aurelien Jarno - April 18 - Reviewed-by Thanks, -Jordan On Fri, Jul 8, 2011 at 12:37, Jordan Justen wrote: > If -pflash is specified and -bios is specified then pflash will > be mapped just below the system rom using hw/pflash_cfi01.c. > > If -pflash is specified on the command line, but -bios is > not specified, then 'bios.bin' will NOT be loaded, and > instead the -pflash flash image will be mapped just below > 4GB in place of the normal rom image. > > Signed-off-by: Jordan Justen > Reviewed-by: Aurelien Jarno > --- > default-configs/i386-softmmu.mak | 1 + > default-configs/x86_64-softmmu.mak | 1 + > hw/pc.c | 161 > +++- > 3 files changed, 125 insertions(+), 38 deletions(-) > > diff --git a/default-configs/i386-softmmu.mak > b/default-configs/i386-softmmu.mak > index 55589fa..8697cd4 100644 > --- a/default-configs/i386-softmmu.mak > +++ b/default-configs/i386-softmmu.mak > @@ -21,3 +21,4 @@ CONFIG_PIIX_PCI=y > CONFIG_SOUND=y > CONFIG_HPET=y > CONFIG_APPLESMC=y > +CONFIG_PFLASH_CFI01=y > diff --git a/default-configs/x86_64-softmmu.mak > b/default-configs/x86_64-softmmu.mak > index 8895028..eca9284 100644 > --- a/default-configs/x86_64-softmmu.mak > +++ b/default-configs/x86_64-softmmu.mak > @@ -21,3 +21,4 @@ CONFIG_PIIX_PCI=y > CONFIG_SOUND=y > CONFIG_HPET=y > CONFIG_APPLESMC=y > +CONFIG_PFLASH_CFI01=y > diff --git a/hw/pc.c b/hw/pc.c > index a3e8539..e25354f 100644 > --- a/hw/pc.c > +++ b/hw/pc.c > @@ -41,6 +41,7 @@ > #include "sysemu.h" > #include "blockdev.h" > #include "ui/qemu-spice.h" > +#include "flash.h" > > /* output Bochs bios info messages */ > //#define DEBUG_BIOS > @@ -957,70 +958,154 @@ void pc_cpus_init(const char *cpu_model) > } > } > > -void pc_memory_init(const char *kernel_filename, > - const char *kernel_cmdline, > - const char *initrd_filename, > - ram_addr_t below_4g_mem_size, > - ram_addr_t above_4g_mem_size) > +static void pc_isa_bios_init(ram_addr_t ram_offset, int ram_size) > { > - char *filename; > - int ret, linux_boot, i; > - ram_addr_t ram_addr, bios_offset, option_rom_offset; > - int bios_size, isa_bios_size; > - void *fw_cfg; > - > - linux_boot = (kernel_filename != NULL); > + int isa_bios_size; > > - /* allocate RAM */ > - ram_addr = qemu_ram_alloc(NULL, "pc.ram", > - below_4g_mem_size + above_4g_mem_size); > - cpu_register_physical_memory(0, 0xa, ram_addr); > - cpu_register_physical_memory(0x10, > - below_4g_mem_size - 0x10, > - ram_addr + 0x10); > - if (above_4g_mem_size > 0) { > - cpu_register_physical_memory(0x1ULL, above_4g_mem_size, > - ram_addr + below_4g_mem_size); > + /* map the last 128KB of the BIOS in ISA space */ > + isa_bios_size = ram_size; > + if (isa_bios_size > (128 * 1024)) { > + isa_bios_size = 128 * 1024; > } > + ram_offset = ram_offset + ram_size - isa_bios_size; > + cpu_register_physical_memory(0x10 - isa_bios_size, > + isa_bios_size, > + ram_offset | IO_MEM_ROM); > +} > + > +static int pc_system_rom_init(void) > +{ > + int ret; > + int bios_size; > + ram_addr_t bios_offset; > + char *filename; > > /* BIOS load */ > - if (bios_name == NULL) > + if (bios_name == NULL) { > bios_name = BIOS_FILENAME; > + } > filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); > if (filename) { > bios_size = get_image_size(filename); > } else { > bios_size = -1; > } > - if (bios_size <= 0 || > - (bios_size % 65536) != 0) { > - goto bios_error; > + > + if (bios_size <= 0 || (bios_size % 65536) != 0) { > + ret = -1; > + } else { > + bios_offset = qemu_ram_alloc(NULL, "pc.bios", bios_size); > + ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1); > } > - bios_offset = qemu_ram_alloc(NULL, "pc.bios", bios_size); > - ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1); > + > if (ret != 0) { > - bios_error: > fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name); > exit(1); > } > + > if (filename) { > qemu_free(filename); > } > - /* map the last 128KB of the BIOS in ISA space */ > - isa_bios_size = bios_size; > - if (isa_bios_size > (128 * 1024)) > - isa_bios_size = 128 * 1024; > - cpu_register_physical_memory(0x10 - isa_bios_size, > - isa_bios_size, > - (bios_offset + bios_size - isa_bios_size) | > IO_MEM_ROM); > > - option_rom_offset