Re: [Qemu-devel] [PATCH 0/3] v4 Decouple block device removal from device removal
On Tue, Nov 02, 2010 at 03:23:38PM -0500, Ryan Harper wrote: * Michael S. Tsirkin m...@redhat.com [2010-11-02 14:18]: On Tue, Nov 02, 2010 at 02:01:08PM -0500, Ryan Harper wrote: I like the idea of disconnect; if part of the device_del method was to invoke a disconnect method, we could implement that for block, net, etc; I'd think we'd want to send the notification, then disconnect. Struggling with whether it's worth having some reasonable timeout between notification and disconnect. The problem with this is that it has no analog in real world. In real world, you can send some notifications to the guest, and you can remove the card. Tying them together is what created the problem in the first place. Timeouts can be implemented by management, maybe with a nice dialog being shown to the user. Very true. I'm fine with forcing a disconnect during the removal path prior to notification. Do we want a new disconnect method at the device level (pci)? or just use the existing removal callback and call that during the initial hotremov event? Not sure what you mean by that, but I don't see a device doing anything differently wrt surprise or ordered removal. So probably the existing callback should do. I don't think we need to talk about disconnect: since we decided we are emulating device removal, let's call it just that. Because current the removal process depends on the guest actually responding. What I'm suggesting is that, in Marcus's term, and what drive_unplug() implements, is to disconnect the host block device from the guest device to prevent any further access to it in the case the guest doesn't respond to the removal request made via ACPI. Very specifically, what we're suggesting instead of the drive_unplug() command so to complete the device removal operation without waiting for the guest to respond; that's what's going to happen if we invoke the response callback; it will appear as if the guest responded whether it did or not. What I was suggesting above was to instead of calling the callback for handing the guest response was to add a device function called disconnect which would remove any association of host resources from guest resources before we notified the guest. Thinking about it again I'm not sure this is useful, but if we're going to remove the device without the guests knowledge, I'm not sure how useful sending the removal requests via ACPI is in the first place. My feeling is that I'd like to have explicit control over the disconnect from host resources separate from the device removal *if* we're going to retain the guest notification. If we don't care to notify the guest, then we can just do device removal without notifying the guest and be done with it. I imagine management would typically want to do this: 1. notify guest 2. wait a bit 3. remove device Yes; but this argues for (1) being a separate command from (3) Yes. Long term I think we will want a way to do that. unless we require (3) to include (1) and (2) in the qemu implementation. Currently we implement: 1. device_del (attempt to remove device) 2. notify guest 3. if guest responds, remove device 4. disconnect host resource from device on destruction With my drive_unplug patch we do: 1. disconnect host resource from device This is what drive_unplug does, right? 2. device_del (attempt to remove device) 3. notify guest 4. if guest responds, remove device I think we're suggesting to instead do (if we keep disconnect as part of device_del) 1. device_del (attemp to remove device) 2. notify guest 3. invoke device destruction callback resulting in disconnect host resource from device 4. if guest responds, invoke device destruction path a second time. By response you mean eject? No, this is not what I was suggesting. I was really suggesting that your patch is fine :) Sorry about confusion. I was also saying that from what I hear, the pci express support will at some point need interfaces to - notify guest about device removal/addition - get eject from guest - remove device without talking to guest - add device without talking to guest - suppress device deletion on eject All this can be generic and can work through express configuration mechanisms or through acpi for pci. But this is completely separate from unplugging the host backend, which should be possible at any point. -- Ryan Harper Software Engineer; Linux Technology Center IBM Corp., Austin, Tx ry...@us.ibm.com
[Qemu-devel] Re: [PATCH v7 2/6] pcie/aer: helper functions for pcie aer capability
On Wed, Nov 03, 2010 at 10:24:30AM +0900, Isaku Yamahata wrote: On Tue, Nov 02, 2010 at 02:57:12PM +0200, Michael S. Tsirkin wrote: +static void pcie_aer_clear_error(PCIDevice *dev); +static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg); + so what exactly is the order of calls that makes removing the forward declarations impractical? Is there a recursive call? If yes I'd like to see it documented much better. Why do you think forward declaration is so bad? I don't see any such consensus and I don't think they aren't accused generally like goto. Can you please elaborate why you're trying so hard to prevent it? Well no, I do not claim they are that bad. In my opinion avoiding them just makes for a slightly better code usually: - They make for code duplication where if you change a function there's another place to edit. - Just generally add more code. - Avoiding forward declarations makes you put functions in some sensible order. - Also makes you avoid recursion where a loop will do. But all this doesn't always apply. I was trying to understand whether there's recursion here that I am missing. If there is a comment might be helpful. -- yamahata
[Qemu-devel] MSI broken?
Hi, What is the status if the recently merged MSI support? I'm trying to use it to add msi support to the intel-hda driver (current wip patch attached). Everything works fine up to the point where it comes to delivering the interrupt to the guest. msi_notify pretends to signal the guest: msi_notify:243 intel-hda:30 notify vector 0x0 address: 0xfee01008 data: 0x4151 The guest never ever receives this interrupt though: [r...@localhost ~]# grep hda /proc/interrupts 43: 0 PCI-MSI-edge hda_intel Ideas anyone? thanks, Gerd From b2ca133855b78e5b6cfc3e52220769a031485939 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann kra...@redhat.com Date: Wed, 3 Nov 2010 10:14:48 +0100 Subject: [PATCH] intel-hda: msi support [wip] --- hw/intel-hda.c | 30 -- 1 files changed, 28 insertions(+), 2 deletions(-) diff --git a/hw/intel-hda.c b/hw/intel-hda.c index 126cf54..63cccbe 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -19,6 +19,7 @@ #include hw.h #include pci.h +#include msi.h #include qemu-timer.h #include audiodev.h #include intel-hda.h @@ -188,6 +189,7 @@ struct IntelHDAState { /* properties */ uint32_t debug; +uint32_t msi; }; struct IntelHDAReg { @@ -268,6 +270,7 @@ static void intel_hda_update_int_sts(IntelHDAState *d) static void intel_hda_update_irq(IntelHDAState *d) { +int msi = d-msi msi_enabled(d-pci); int level; intel_hda_update_int_sts(d); @@ -276,8 +279,15 @@ static void intel_hda_update_irq(IntelHDAState *d) } else { level = 0; } -dprint(d, 2, %s: level %d\n, __FUNCTION__, level); -qemu_set_irq(d-pci.irq[0], level); +dprint(d, 2, %s: level %d [%s]\n, __FUNCTION__, + level, msi ? msi : intx); +if (msi) { +if (level) { +msi_notify(d-pci, 0); +} +} else { +qemu_set_irq(d-pci.irq[0], level); +} } static int intel_hda_send_command(IntelHDAState *d, uint32_t verb) @@ -1132,6 +1142,8 @@ static int intel_hda_init(PCIDevice *pci) intel_hda_mmio_write, d); pci_register_bar(d-pci, 0, 0x4000, PCI_BASE_ADDRESS_SPACE_MEMORY, intel_hda_map); +if (d-msi) +msi_init(d-pci, 0, 1, true, false); hda_codec_bus_init(d-pci.qdev, d-codecs, intel_hda_response, intel_hda_xfer); @@ -1143,10 +1155,22 @@ static int intel_hda_exit(PCIDevice *pci) { IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci); +if (d-msi) +msi_uninit(d-pci); cpu_unregister_io_memory(d-mmio_addr); return 0; } +static void intel_hda_write_config(PCIDevice *pci, uint32_t addr, + uint32_t val, int len) +{ +IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci); + +pci_default_write_config(pci, addr, val, len); +if (d-msi) +msi_write_config(pci, addr, val, len); +} + static int intel_hda_post_load(void *opaque, int version) { IntelHDAState* d = opaque; @@ -1230,8 +1254,10 @@ static PCIDeviceInfo intel_hda_info = { .qdev.reset = intel_hda_reset, .init = intel_hda_init, .exit = intel_hda_exit, +.config_write = intel_hda_write_config, .qdev.props = (Property[]) { DEFINE_PROP_UINT32(debug, IntelHDAState, debug, 0), +DEFINE_PROP_UINT32(msi, IntelHDAState, msi, 0), DEFINE_PROP_END_OF_LIST(), } }; -- 1.7.1
[Qemu-devel] [PATCH RESEND] Fixed default IRQ assignment for PL190 VIC.
Everywhere else vect_addr[16] is returned on a read of default vector address but updation is done only on default_addr in structure. Signed-off-by: Himanshu Chauhan hschau...@nulltrace.org --- hw/pl190.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/hw/pl190.c b/hw/pl190.c index a4bc9c1..7363b87 100644 --- a/hw/pl190.c +++ b/hw/pl190.c @@ -187,6 +187,7 @@ static void pl190_write(void *opaque, target_phys_addr_t offset, uint32_t val) break; case 13: /* DEFVECTADDR */ s-default_addr = val; +s-vect_addr[16] = val; break; case 0xc0: /* ITCR */ if (val) { -- 1.7.0.4 - End forwarded message -
[Qemu-devel] [PATCH v2] spice: add audio
Add support for the spice audio interface. With this patch applied audio can be forwarded over the network from/to the spice client. Both recording and playback is supported. The driver is first in the driver list, but the can_be_default flag is set only in case spice is active. So if you have the spice protocol enabled the spice audio driver is the default one, otherwise whatever comes first after spice in the list. Overriding the default using QEMU_AUDIO_DRV works in any case. [ v2: audio codestyle: add spaces before open parenthesis ] [ v2: add const to silence array ] Signed-off-by: Gerd Hoffmann kra...@redhat.com Cc: malc av1...@comtv.ru --- Makefile.objs |1 + audio/audio.c |3 + audio/audio_int.h |1 + audio/spiceaudio.c | 327 ui/qemu-spice.h|1 + ui/spice-core.c|1 + 6 files changed, 334 insertions(+), 0 deletions(-) create mode 100644 audio/spiceaudio.c diff --git a/Makefile.objs b/Makefile.objs index faf485e..15569af 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -102,6 +102,7 @@ common-obj-$(CONFIG_SPICE) += ui/spice-core.o ui/spice-input.o ui/spice-display. audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o audio-obj-$(CONFIG_SDL) += sdlaudio.o audio-obj-$(CONFIG_OSS) += ossaudio.o +audio-obj-$(CONFIG_SPICE) += spiceaudio.o audio-obj-$(CONFIG_COREAUDIO) += coreaudio.o audio-obj-$(CONFIG_ALSA) += alsaaudio.o audio-obj-$(CONFIG_DSOUND) += dsoundaudio.o diff --git a/audio/audio.c b/audio/audio.c index ad51077..ade342e 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -44,6 +44,9 @@ that we generate the list. */ static struct audio_driver *drvtab[] = { +#ifdef CONFIG_SPICE +spice_audio_driver, +#endif CONFIG_AUDIO_DRIVERS no_audio_driver, wav_audio_driver diff --git a/audio/audio_int.h b/audio/audio_int.h index d8560b6..d66f2c3 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -209,6 +209,7 @@ extern struct audio_driver coreaudio_audio_driver; extern struct audio_driver dsound_audio_driver; extern struct audio_driver esd_audio_driver; extern struct audio_driver pa_audio_driver; +extern struct audio_driver spice_audio_driver; extern struct audio_driver winwave_audio_driver; extern struct mixeng_volume nominal_volume; diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c new file mode 100644 index 000..51ba53a --- /dev/null +++ b/audio/spiceaudio.c @@ -0,0 +1,327 @@ +#include hw/hw.h +#include qemu-timer.h +#include ui/qemu-spice.h + +#define AUDIO_CAP spice +#include audio.h +#include audio_int.h + +#define LINE_IN_SAMPLES 1024 +#define LINE_OUT_SAMPLES 1024 + +typedef struct SpiceRateCtl { +int64_t start_ticks; +int64_t bytes_sent; +} SpiceRateCtl; + +typedef struct SpiceVoiceOut { +HWVoiceOuthw; +SpicePlaybackInstance sin; +SpiceRateCtl rate; +int active; +uint32_t *frame; +uint32_t *fpos; +uint32_t fsize; +} SpiceVoiceOut; + +typedef struct SpiceVoiceIn { +HWVoiceIn hw; +SpiceRecordInstance sin; +SpiceRateCtl rate; +int active; +uint32_t samples[LINE_IN_SAMPLES]; +} SpiceVoiceIn; + +static const SpicePlaybackInterface playback_sif = { +.base.type = SPICE_INTERFACE_PLAYBACK, +.base.description = playback, +.base.major_version = SPICE_INTERFACE_PLAYBACK_MAJOR, +.base.minor_version = SPICE_INTERFACE_PLAYBACK_MINOR, +}; + +static const SpiceRecordInterface record_sif = { +.base.type = SPICE_INTERFACE_RECORD, +.base.description = record, +.base.major_version = SPICE_INTERFACE_RECORD_MAJOR, +.base.minor_version = SPICE_INTERFACE_RECORD_MINOR, +}; + +static void *spice_audio_init (void) +{ +if (!using_spice) { +return NULL; +} +return spice_audio_init; +} + +static void spice_audio_fini (void *opaque) +{ +/* nothing */ +} + +static void rate_start (SpiceRateCtl *rate) +{ +memset (rate, 0, sizeof (*rate)); +rate-start_ticks = qemu_get_clock (vm_clock); +} + +static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate) +{ +int64_t now; +int64_t ticks; +int64_t bytes; +int64_t samples; + +now = qemu_get_clock (vm_clock); +ticks = now - rate-start_ticks; +bytes = muldiv64 (ticks, info-bytes_per_second, get_ticks_per_sec ()); +samples = (bytes - rate-bytes_sent) info-shift; +if (samples 0 || samples 65536) { +fprintf (stderr, Resetting rate control (% PRId64 samples)\n, samples); +rate_start (rate); +samples = 0; +} +rate-bytes_sent += samples info-shift; +return samples; +} + +/* playback */ + +static int line_out_init (HWVoiceOut *hw, struct audsettings *as) +{ +SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); +struct audsettings settings; +
[Qemu-devel] [RFC][PATCH v2 00/10] virtagent: host/guest RPC communication agent
This set of patches is meant to be applied on top of the Virtproxy v1 patchset, which was submitted a couple weeks ago and can also be obtained at: git://repo.or.cz/qemu/mdroth.git virtproxy_v1 OVERVIEW: There are a wide range of use cases motivating the need for a guest agent of some sort to extend the functionality/usability/control offered by QEMU. Some examples include graceful guest shutdown/reboot and notifications thereof, copy/paste syncing between host/guest, guest statistics gathering, file access, etc. Ideally these would all be served by a single, easilly extensible agent that can be deployed in a wide range of guests. Virtagent is an XMLRPC server integrated into the Virtproxy guest daemon and aimed at providing this type of functionality. CHANGES IN V2: - All RPC communication is now done using asynchronous/non-blocking read/write handlers - Previously fork()'d RPC server loop is now integrated into qemu-vp/virtproxy i/o loop - Cleanups/suggestions from previous RFC DESIGN: There are actually 2 RPC servers: 1) a server in the guest integrated into the Virtproxy guest daemon which handles RPC requests from QEMU 2) a server in the host (integrated into the Virtproxy host daemon, which we plan to integrate directly into qemu) to handle RPC requests sent by the guest agent (mainly for handling asynchronous events reported by the agent). At the Virtagent level, communication is done via standard RPCs (HTTP between host and guest). Virtproxy transparently handles transport over a network or isa/virtio serial channel, allowing the agent to be deployed on older guests which may not support virtio-serial. Currently there are only 2 RPCs implemented for the guest server (getfile and getdmesg), and 0 for the host. Additional RPCs can be added fairly easily, but are dependent on feedback from here and elsewhere. ping/status, shutdown, and reboot are likely candidates (although the latter 2 will likely require asynchronous notifications to the host RPC server to implement reliably). EXAMPLE USAGE: The commandline options are a little convoluted right now; this will addressed in later revisions. - Configure guest agent to talk to host via virtio-serial # start guest with virtio-serial. for example (RHEL6s13): qemu \ -device virtio-serial \ -chardev socket,path=/tmp/test0-virtioconsole.sock,server,nowait,id=test0 \ -device virtconsole,chardev=test0,name=test0 \ -chardev socket,path=/tmp/test1-virtio-serial.sock,server,nowait,id=test1 \ -device virtserialport,chardev=test1,name=test1 \ -chardev socket,path=/tmp/test2-virtio-serial.sock,server,nowait,id=test2 \ -device virtserialport,chardev=test2,name=test2 \ -monitor stdio ... # in the host: ./qemu-vp -c unix-connect:/tmp/test2-virtio-serial.sock:- \ -o virtagent:/tmp/virtagent-guest-client.sock:- # in the guest: ./qemu-vp -c virtserial-open:/dev/virtio-ports/test2:- -g ... # monitor commands (qemu) agent_viewdmesg [139311.710326] wlan0: deauthenticating from 00:30:bd:f7:12:d5 by local choice (reason=3) [139323.469857] wlan0: deauthenticating from 00:21:29:cd:41:ee by local choice (reason=3) ... [257683.375646] wlan0: authenticated [257683.375684] wlan0: associate with AP 00:30:bd:f7:12:d5 (try 1) [257683.377932] wlan0: RX AssocResp from 00:30:bd:f7:12:d5 (capab=0x411 status=0 aid=4) [257683.377940] wlan0: associated (qemu) agent_viewfile /proc/meminfo MemTotal:3985488 kB MemFree: 400524 kB Buffers: 220556 kB Cached: 2073160 kB SwapCached:0 kB ... Hugepagesize: 2048 kB DirectMap4k:8896 kB DirectMap2M: 4110336 kB KNOWN ISSUES/PLANS: - the client socket that qemu connects to send RPCs is a hardcoded filepath. This is unacceptable as the socket is channel/process specific and things will break when multiple guests are started. - capability negotiation will be needed to handle version/architecture differences. - proper channel negotiation is needed to avoid hung monitors and such when a guest reboots or the guest agent is stopped for whatever reason. additionally, a timeout may need to be imposed on the amount of time the http read handler can block the monitor. - additional host-to-guest RPCs as well as asynchronous notifications via guest-to-host RPCs for events such as shutdown/reboot/agent up/agent down Makefile|2 +- Makefile.target |2 +- configure | 25 +++ hmp-commands.hx | 32 monitor.c |1 + qemu-vp.c | 115 +- qerror.c|4 + qerror.h|3 + qmp-commands.hx | 68 virtagent-common.c | 431 +++ virtagent-common.h | 73 + virtagent-daemon.c | 253 ++
[Qemu-devel] [RFC][PATCH v2 05/10] virtagent: add getfile RPC
Add RPC to retrieve a guest file. A size limit of some sort will eventually be needed else we can block the monitor for arbitrarily long periods of time. This interface is intended for smaller reads like peeking at logs and /proc and such. Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtagent-daemon.c | 53 1 files changed, 53 insertions(+), 0 deletions(-) diff --git a/virtagent-daemon.c b/virtagent-daemon.c index 71a36d4..bf28be2 100644 --- a/virtagent-daemon.c +++ b/virtagent-daemon.c @@ -15,6 +15,57 @@ #include virtagent-daemon.h #include virtagent-common.h +/* RPC functions common to guest/host daemons */ + +static xmlrpc_value *getfile(xmlrpc_env *env, +xmlrpc_value *param, +void *user_data) +{ +const char *path; +char *file_contents = NULL; +char buf[VA_FILEBUF_LEN]; +int fd, ret, count = 0; +xmlrpc_value *result = NULL; + +/* parse argument array */ +xmlrpc_decompose_value(env, param, (s), path); +if (env-fault_occurred) { +return NULL; +} + +fd = open(path, O_RDONLY); +if (fd == -1) { +LOG(open failed: %s, strerror(errno)); +xmlrpc_faultf(env, open failed: %s, strerror(errno)); +return NULL; +} + +while ((ret = read(fd, buf, VA_FILEBUF_LEN)) 0) { +file_contents = qemu_realloc(file_contents, count + VA_FILEBUF_LEN); +memcpy(file_contents + count, buf, ret); +count += ret; +if (count VA_GETFILE_MAX) { +xmlrpc_faultf(env, max file size (%d bytes) exceeded, + VA_GETFILE_MAX); +goto EXIT_CLOSE_BAD; +} +} +if (ret == -1) { +LOG(read failed: %s, strerror(errno)); +xmlrpc_faultf(env, read failed: %s, strerror(errno)); +goto EXIT_CLOSE_BAD; +} + +result = xmlrpc_build_value(env, 6, file_contents, count); + +EXIT_CLOSE_BAD: +if (file_contents) { +qemu_free(file_contents); +} +close(fd); +return result; +} + static int va_accept(int listen_fd) { struct sockaddr_in saddr; struct sockaddr *addr; @@ -42,6 +93,8 @@ typedef struct RPCFunction { } RPCFunction; static RPCFunction guest_functions[] = { +{ .func = getfile, + .func_name = getfile }, { NULL, NULL } }; static RPCFunction host_functions[] = { -- 1.7.0.4
[Qemu-devel] [RFC][PATCH v2 09/10] virtagent: Makefile/configure changes to build virtagent bits
Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- Makefile|2 +- Makefile.target |2 +- configure | 25 + 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 2dd64a3..b513d33 100644 --- a/Makefile +++ b/Makefile @@ -135,7 +135,7 @@ qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-ob qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) -qemu-vp$(EXESUF): qemu-vp.o virtproxy.o qemu-tool.o qemu-error.o qemu-sockets.c $(block-obj-y) $(qobject-obj-y) +qemu-vp$(EXESUF): qemu-vp.o virtproxy.o virtagent-daemon.o virtagent-common.o qemu-tool.o qemu-error.o qemu-sockets.c $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx $(call quiet-command,sh $(SRC_PATH)/hxtool -h $ $@, GEN $@) diff --git a/Makefile.target b/Makefile.target index c48cbcc..f8f4c13 100644 --- a/Makefile.target +++ b/Makefile.target @@ -164,7 +164,7 @@ endif #CONFIG_BSD_USER # System emulator target ifdef CONFIG_SOFTMMU -obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o +obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o virtagent.o virtagent-common.o # virtio has to be here due to weird dependency between PCI and virtio-net. # need to fix this properly obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o diff --git a/configure b/configure index 27f92e0..cfddad7 100755 --- a/configure +++ b/configure @@ -1261,6 +1261,31 @@ EOF fi ## +# xmlrpc-c probe + +# Look for the xmlrpc-c config program +if test -n $cross_prefix has ${cross_prefix}xmlrpc-c-config; then + xmlrpccconfig=${cross_prefix}xmlrpc-c-config +elif has xmlrpc-c-config; then + xmlrpccconfig=xmlrpc-c-config +else + feature_not_found xmlrpc-c +fi + +cat $TMPC EOF +#include xmlrpc.h +int main(void) { xmlrpc_env env; xmlrpc_env_init(env); return 0; } +EOF +xmlrpc_cflags=`$xmlrpccconfig --cflags 2 /dev/null` +xmlrpc_libs=`$xmlrpccconfig client server-util --libs 2 /dev/null` +if compile_prog $xmlrpc_cflags $xmlrpc_libs; then + libs_softmmu=$xmlrpc_libs $libs_softmmu + libs_tools=$xmlrpc_libs $libs_tools +else + feature_not_found xmlrpc-c +fi + +## # VNC TLS detection if test $vnc_tls != no ; then cat $TMPC EOF -- 1.7.0.4
[Qemu-devel] [RFC][PATCH v2 04/10] virtagent: base RPC client definitions
Base skeleton and helpers for executing RPC commands. Monitor commands will result in a connect() being issued to the virtagent service socket, which will then be transported to the listening RPC server in the guest via the virtproxy layer, RPC requests are then sent/recieved via http over the resulting connection. Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- monitor.c |1 + qerror.c|4 +++ qerror.h|3 ++ virtagent.c | 88 +++ virtagent.h | 25 + 5 files changed, 121 insertions(+), 0 deletions(-) create mode 100644 virtagent.c create mode 100644 virtagent.h diff --git a/monitor.c b/monitor.c index 260cc02..6c99206 100644 --- a/monitor.c +++ b/monitor.c @@ -42,6 +42,7 @@ #include audio/audio.h #include disas.h #include balloon.h +#include virtagent.h #include qemu-timer.h #include migration.h #include kvm.h diff --git a/qerror.c b/qerror.c index ac2cdaf..2f111a9 100644 --- a/qerror.c +++ b/qerror.c @@ -200,6 +200,10 @@ static const QErrorStringTable qerror_table[] = { .error_fmt = QERR_VNC_SERVER_FAILED, .desc = Could not start VNC server on %(target), }, +{ +.error_fmt = QERR_RPC_FAILED, +.desc = An RPC error has occurred, +}, {} }; diff --git a/qerror.h b/qerror.h index 943a24b..43cce4a 100644 --- a/qerror.h +++ b/qerror.h @@ -165,4 +165,7 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_VNC_SERVER_FAILED \ { 'class': 'VNCServerFailed', 'data': { 'target': %s } } +#define QERR_RPC_FAILED \ +{ 'class': 'RPCFailed', 'data': { 'code': %i, 'message': %s } } + #endif /* QERROR_H */ diff --git a/virtagent.c b/virtagent.c new file mode 100644 index 000..84dcf3b --- /dev/null +++ b/virtagent.c @@ -0,0 +1,88 @@ +/* + * virt-agent - host/guest RPC client functions + * + * Copyright IBM Corp. 2010 + * + * Authors: + * Adam Litkeagli...@linux.vnet.ibm.com + * Michael Roth mdr...@linux.vnet.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include qemu_socket.h +#include virtagent-daemon.h +#include virtagent-common.h +#include virtagent.h + +static int rpc_has_error(xmlrpc_env *env) +{ +if (env-fault_occurred) { +LOG(An RPC error has occurred (%i): %s\n, env-fault_code, env-fault_string); +//qerror_report(QERR_RPC_FAILED, env-fault_code, env-fault_string); +return -1; +} +return 0; +} + +/* + * Get a connected socket that can be used to make an RPC call + * This interface will eventually return the connected virtproxy socket for the + * virt-agent channel + */ +static int get_transport_fd(void) +{ +/* TODO: eventually this will need a path that is unique to other + * instances of qemu-vp/qemu. for the integrated qemu-vp we should + * explore the possiblity of not requiring a unix socket under the + * covers, as well as having client init code set up the oforward + * for the service rather than qemu-vp + */ +int ret; +int fd = unix_connect(GUEST_AGENT_PATH_CLIENT); +if (fd 0) { +LOG(failed to connect to virtagent service); +} +ret = fcntl(fd, F_GETFL); +ret = fcntl(fd, F_SETFL, ret | O_NONBLOCK); +return fd; +} + +static int rpc_execute(xmlrpc_env *const env, const char *function, + xmlrpc_value *params, VARPCData *rpc_data) +{ +xmlrpc_mem_block *call_xml; +int fd, ret; + +fd = get_transport_fd(); +if (fd 0) { +LOG(invalid fd); +ret = -1; +goto out; +} + +call_xml = XMLRPC_MEMBLOCK_NEW(char, env, 0); +xmlrpc_serialize_call(env, call_xml, function, params); +if (rpc_has_error(env)) { +ret = -EREMOTE; +goto out_callxml; +} + +rpc_data-send_req_xml = call_xml; + +ret = va_rpc_send_request(rpc_data, fd); +if (ret != 0) { +ret = -1; +goto out_callxml; +} else { +ret = 0; +goto out; +} + +out_callxml: +XMLRPC_MEMBLOCK_FREE(char, call_xml); +out: +return ret; +} diff --git a/virtagent.h b/virtagent.h new file mode 100644 index 000..abdb32a --- /dev/null +++ b/virtagent.h @@ -0,0 +1,25 @@ +/* + * virt-agent - host/guest RPC client functions + * + * Copyright IBM Corp. 2010 + * + * Authors: + * Adam Litkeagli...@linux.vnet.ibm.com + * Michael Roth mdr...@linux.vnet.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef VIRTAGENT_H +#define VIRTAGENT_H + +#include monitor.h +#include virtagent-common.h + +#define GUEST_AGENT_PATH_CLIENT /tmp/virtagent-guest-client.sock +#define HOST_AGENT_PATH_CLIENT /tmp/virtagent-host-client.sock +#define VA_MAX_CHUNK_SIZE 4096 /* max bytes at a time for get/send file */ + +#endif
[Qemu-devel] [RFC][PATCH v2 06/10] virtagent: add agent_viewfile command
Utilize the getfile RPC to provide a means to view text files in the guest. Getfile can handle binary files as well but we don't advertise that here due to the special handling requiring to store it and provide it back to the user (base64 encoding it for instance). Hence the potentially confusing viewfile as opposed to getfile. Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- hmp-commands.hx | 16 + qmp-commands.hx | 33 ++ virtagent.c | 99 +++ virtagent.h |4 ++ 4 files changed, 152 insertions(+), 0 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index 81999aa..e9a7f4a 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1211,6 +1211,22 @@ show available trace events and their state ETEXI #endif +{ +.name = agent_viewfile, +.args_type = filepath:s, +.params = filepath, +.help = Echo a file from the guest filesystem, +.user_print = do_agent_viewfile_print, +.mhandler.cmd_async = do_agent_viewfile, +.flags = MONITOR_CMD_ASYNC, +}, + +STEXI +...@item agent_viewfile @var{filepath} +...@findex agent_viewfile +Echo the file identified by @var{filepath} on the guest filesystem +ETEXI + STEXI @end table ETEXI diff --git a/qmp-commands.hx b/qmp-commands.hx index 793cf1c..efa2137 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -738,6 +738,39 @@ Example: EQMP { +.name = agent_viewfile, +.args_type = filepath:s, +.params = filepath, +.help = Echo a file from the guest filesystem, +.user_print = monitor_user_noop, +.mhandler.cmd_async = do_agent_viewfile, +.flags = MONITOR_CMD_ASYNC, +}, + +STEXI +...@item agent_viewfile @var{filepath} +...@findex agent_viewfile +Echo the file identified by @var{filepath} on the guest filesystem +ETEXI +SQMP +agent_viewfile + + +Echo the file identified by @var{filepath} from the guest filesystem. + +Arguments: + +- filepath: Full guest path of the desired file + +Example: + +- { execute: agent_viewfile, +arguments: { filepath: /sys/kernel/kexec_loaded } } +- { return: { contents: 0 } } + +EQMP + +{ .name = qmp_capabilities, .args_type = , .params = , diff --git a/virtagent.c b/virtagent.c index 84dcf3b..187bb28 100644 --- a/virtagent.c +++ b/virtagent.c @@ -86,3 +86,102 @@ out_callxml: out: return ret; } + +void do_agent_viewfile_print(Monitor *mon, const QObject *data) +{ +QDict *qdict; +const char *contents = NULL; +int i; + +qdict = qobject_to_qdict(data); +if (!qdict_haskey(qdict, contents)) { +return; +} + +contents = qdict_get_str(qdict, contents); +if (contents != NULL) { + /* monitor_printf truncates so do it in chunks. also, file_contents + * may not be null-termed at proper location so explicitly calc + * last chunk sizes */ +for (i = 0; i strlen(contents); i += 1024) { +monitor_printf(mon, %.1024s, contents + i); +} +} +monitor_printf(mon, \n); +} + +static void do_agent_viewfile_cb(void *opaque) +{ +VARPCData *rpc_data = opaque; +xmlrpc_value *resp = NULL; +char *file_contents = NULL; +int file_size, ret; +xmlrpc_env env; +QDict *qdict = qdict_new(); + +if (rpc_data-status != VA_RPC_STATUS_OK) { +LOG(error handling RPC request); +goto out_no_resp; +} + +xmlrpc_env_init(env); +resp = xmlrpc_parse_response(env, rpc_data-resp_xml, + rpc_data-resp_xml_len); +if (rpc_has_error(env)) { +ret = -1; +goto out_no_resp; +} + +xmlrpc_parse_value(env, resp, 6, file_contents, file_size); +if (rpc_has_error(env)) { +ret = -1; +goto out; +} + +if (file_contents != NULL) { +qdict_put(qdict, contents, + qstring_from_substr(file_contents, 0, file_size-1)); +} + +out: +xmlrpc_DECREF(resp); +out_no_resp: +rpc_data-mon_cb(rpc_data-mon_data, QOBJECT(qdict)); +} + +/* + * do_agent_viewfile(): View a text file in the guest + */ +int do_agent_viewfile(Monitor *mon, const QDict *mon_params, + MonitorCompletion cb, void *opaque) +{ +xmlrpc_env env; +xmlrpc_value *params; +VARPCData *rpc_data; +const char *filepath; +int ret; + +filepath = qdict_get_str(mon_params, filepath); +xmlrpc_env_init(env); +params = xmlrpc_build_value(env, (s), filepath); +if (rpc_has_error(env)) { +return -1; +} + +rpc_data = qemu_mallocz(sizeof(VARPCData)); +rpc_data-cb = do_agent_viewfile_cb; +rpc_data-mon_cb = cb; +rpc_data-mon_data = opaque; + +ret = rpc_execute(env, getfile, params, rpc_data); +if (ret == -EREMOTE) { +monitor_printf(mon, RPC Failed (%i): %s\n,
[Qemu-devel] [RFC][PATCH v2 02/10] virtagent: base definitions for host/guest RPC daemon
Basic skeleton code for RPC daemon loop. This is shared by both the guest-side RPC server as well as the host-side one (the advertised RPCs for each by guest/host-specific arrays). Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtagent-daemon.c | 156 virtagent-daemon.h | 20 +++ 2 files changed, 176 insertions(+), 0 deletions(-) create mode 100644 virtagent-daemon.c create mode 100644 virtagent-daemon.h diff --git a/virtagent-daemon.c b/virtagent-daemon.c new file mode 100644 index 000..71a36d4 --- /dev/null +++ b/virtagent-daemon.c @@ -0,0 +1,156 @@ +/* + * virt-agent - host/guest RPC daemon functions + * + * Copyright IBM Corp. 2010 + * + * Authors: + * Adam Litkeagli...@linux.vnet.ibm.com + * Michael Roth mdr...@linux.vnet.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ +#include qemu_socket.h +#include virtagent-daemon.h +#include virtagent-common.h + +static int va_accept(int listen_fd) { +struct sockaddr_in saddr; +struct sockaddr *addr; +socklen_t len; +int fd; + +while (1) { +len = sizeof(saddr); +addr = (struct sockaddr *)saddr; +fd = qemu_accept(listen_fd, addr, len); +if (fd 0 errno != EINTR) { +LOG(accept() failed); +break; +} else if (fd = 0) { +TRACE(accepted connection); +break; +} +} +return fd; +} + +typedef struct RPCFunction { +xmlrpc_value *(*func)(xmlrpc_env *env, xmlrpc_value *param, void *unused); +const char *func_name; +} RPCFunction; + +static RPCFunction guest_functions[] = { +{ NULL, NULL } +}; +static RPCFunction host_functions[] = { +{ NULL, NULL } +}; + +static void va_register_functions(xmlrpc_env *env, xmlrpc_registry *registry, + RPCFunction *list) +{ +int i; +for (i = 0; list[i].func != NULL; ++i) { +TRACE(adding func: %s, list[i].func_name); +xmlrpc_registry_add_method(env, registry, NULL, list[i].func_name, + list[i].func, NULL); +} +} + +typedef struct VARPCServerState { +int listen_fd; +xmlrpc_env env; +xmlrpc_registry *registry; +} VARPCServerState; + +static void va_accept_handler(void *opaque); + +static void va_rpc_send_cb(void *opaque) +{ +VARPCData *rpc_data = opaque; +VARPCServerState *s = rpc_data-opaque; + +TRACE(called); +if (rpc_data-status != VA_RPC_STATUS_OK) { +LOG(error sending RPC response); +} else { +TRACE(RPC completed); +} + +TRACE(waiting for RPC request...); +vp_set_fd_handler(s-listen_fd, va_accept_handler, NULL, s); +} + +static void va_rpc_read_cb(void *opaque) +{ +VARPCData *rpc_data = opaque; +VARPCServerState *s = rpc_data-opaque; + +TRACE(called); +if (rpc_data-status != VA_RPC_STATUS_OK) { +LOG(error reading RPC request); +goto out_bad; +} + +rpc_data-send_resp_xml = +xmlrpc_registry_process_call(s-env, s-registry, NULL, + rpc_data-req_xml, rpc_data-req_xml_len); +if (rpc_data-send_resp_xml == NULL) { +LOG(error handling RPC request); +goto out_bad; +} + +rpc_data-cb = va_rpc_send_cb; +return; + +out_bad: +TRACE(waiting for RPC request...); +vp_set_fd_handler(s-listen_fd, va_accept_handler, NULL, s); +} + +static void va_accept_handler(void *opaque) +{ +VARPCServerState *s = opaque; +VARPCData *rpc_data; +int ret, fd; + +TRACE(called); +fd = va_accept(s-listen_fd); +if (fd 0) { +TRACE(connection error: %s, strerror(errno)); +return; +} +ret = fcntl(fd, F_GETFL); +ret = fcntl(fd, F_SETFL, ret | O_NONBLOCK); + +TRACE(RPC client connected, reading RPC request...); +rpc_data = qemu_mallocz(sizeof(VARPCData)); +rpc_data-cb = va_rpc_read_cb; +rpc_data-opaque = s; +ret = va_rpc_read_request(rpc_data, fd); +if (ret != 0) { +LOG(error setting up read handler); +qemu_free(rpc_data); +return; +} +vp_set_fd_handler(s-listen_fd, NULL, NULL, NULL); +} + +int va_server_start(int listen_fd, bool is_host) +{ +VARPCServerState *s; +RPCFunction *func_list = is_host ? host_functions : guest_functions; + +s = qemu_mallocz(sizeof(VARPCServerState)); +s-listen_fd = listen_fd; +xmlrpc_env_init(s-env); +s-registry = xmlrpc_registry_new(s-env); +va_register_functions(s-env, s-registry, func_list); + +TRACE(waiting for RPC request...); +vp_set_fd_handler(s-listen_fd, va_accept_handler, NULL, s); + +return 0; +} diff --git a/virtagent-daemon.h b/virtagent-daemon.h new file mode 100644 index 000..da926b3 --- /dev/null +++ b/virtagent-daemon.h @@ -0,0 +1,20 @@ +/* + * virt-agent - host/guest RPC daemon
[Qemu-devel] [RFC][PATCH v2 07/10] virtagent: add getdmesg RPC
Add RPC to view guest dmesg output. Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtagent-daemon.c | 44 virtagent-daemon.h |1 + 2 files changed, 45 insertions(+), 0 deletions(-) diff --git a/virtagent-daemon.c b/virtagent-daemon.c index bf28be2..181edac 100644 --- a/virtagent-daemon.c +++ b/virtagent-daemon.c @@ -66,6 +66,48 @@ EXIT_CLOSE_BAD: return result; } +/* getdmesg(): return dmesg output + * rpc return values: + * - dmesg output as a string + */ +static xmlrpc_value *getdmesg(xmlrpc_env *env, + xmlrpc_value *param, + void *user_data) +{ +char *dmesg_buf = NULL, cmd[256]; +int ret; +xmlrpc_value *result = NULL; +FILE *pipe; + +dmesg_buf = qemu_mallocz(VA_DMESG_LEN + 2048); +sprintf(cmd, dmesg -s %d, VA_DMESG_LEN); + +pipe = popen(cmd, r); +if (pipe == NULL) { +LOG(popen failed: %s, strerror(errno)); +xmlrpc_faultf(env, popen failed: %s, strerror(errno)); +goto EXIT_NOCLOSE; +} + +ret = fread(dmesg_buf, sizeof(char), VA_DMESG_LEN, pipe); +if (!ferror(pipe)) { +dmesg_buf[ret] = '\0'; +TRACE(dmesg:\n%s, dmesg_buf); +result = xmlrpc_build_value(env, s, dmesg_buf); +} else { +LOG(fread failed); +xmlrpc_faultf(env, popen failed: %s, strerror(errno)); +} + +pclose(pipe); +EXIT_NOCLOSE: +if (dmesg_buf) { +qemu_free(dmesg_buf); +} + +return result; +} + static int va_accept(int listen_fd) { struct sockaddr_in saddr; struct sockaddr *addr; @@ -95,6 +137,8 @@ typedef struct RPCFunction { static RPCFunction guest_functions[] = { { .func = getfile, .func_name = getfile }, +{ .func = getdmesg, + .func_name = getdmesg }, { NULL, NULL } }; static RPCFunction host_functions[] = { diff --git a/virtagent-daemon.h b/virtagent-daemon.h index da926b3..d19f8e3 100644 --- a/virtagent-daemon.h +++ b/virtagent-daemon.h @@ -16,5 +16,6 @@ #define HOST_AGENT_PATH /tmp/virtagent-host.sock #define VA_GETFILE_MAX 1 30 #define VA_FILEBUF_LEN 16384 +#define VA_DMESG_LEN 16384 int va_server_start(int listen_fd, bool is_host); -- 1.7.0.4
[Qemu-devel] [RFC][PATCH v2 10/10] virtproxy: add compat defs for linking against vl.c
Virtagent depends on basic qemu functions re-implemented by qemu-vp to allow it to be used in output of qemu (in particular, to allow the client code to be used for guest-to-host RPC calls). To build virtagent into qemu we need to define these in terms of the built-in qemu functions. Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- Makefile.target |2 +- virtproxy-builtin.c | 30 ++ 2 files changed, 31 insertions(+), 1 deletions(-) create mode 100644 virtproxy-builtin.c diff --git a/Makefile.target b/Makefile.target index f8f4c13..d72b2be 100644 --- a/Makefile.target +++ b/Makefile.target @@ -164,7 +164,7 @@ endif #CONFIG_BSD_USER # System emulator target ifdef CONFIG_SOFTMMU -obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o virtagent.o virtagent-common.o +obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o virtagent.o virtagent-common.o virtproxy-builtin.o # virtio has to be here due to weird dependency between PCI and virtio-net. # need to fix this properly obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o diff --git a/virtproxy-builtin.c b/virtproxy-builtin.c new file mode 100644 index 000..c3416b3 --- /dev/null +++ b/virtproxy-builtin.c @@ -0,0 +1,30 @@ +/* + * virt-proxy - host/guest communication layer builtin definitions + * + * Copyright IBM Corp. 2010 + * + * Authors: + * Adam Litkeagli...@linux.vnet.ibm.com + * Michael Roth mdr...@linux.vnet.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +/* the following are functions we define in terms of qemu when linked + * against qemu/vl.c. these will be added on an as-needed basis + */ + +#include qemu-char.h +#include virtproxy.h + +int vp_set_fd_handler(int fd, +IOHandler *fd_read, +IOHandler *fd_write, +void *opaque) +{ +return qemu_set_fd_handler(fd, fd_read, fd_write, opaque); +} + + -- 1.7.0.4
[Qemu-devel] [vgabios patch v2 03/11] - preparing for release 0.6c
From: Volker Ruppert i...@vruppert.de --- ChangeLog | 35 +++ README|6 ++ 2 files changed, 41 insertions(+), 0 deletions(-) diff --git a/ChangeLog b/ChangeLog index 75be5bd..35bf00a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +2009-01-25 16:46 vruppert + + * vbe.c (1.62), vbe.h (1.28), vbetables-gen.c (1.5): + + - added support for a lot more non-standard VBE modes (e.g. widescreen modes) + - requires latest Bochs VBE code (16 MB video memory, VBE_DISPI_ID5, VRAM size + in 64k pages stored in VBE register) + - check if VBE mode is supported with current VRAM size + +2009-01-24 11:02 vruppert + + * clext.c (1.14), vbe.c (1.61), vgabios.c (1.68): + + - use VBE LFB address from PCI base address if present (rewrite of the cirrus + specific function in main vgabios code) + - removed unnecessary spaces + +2008-12-14 09:29 vruppert + + * clext.c (1.13): + + - added DPMS support to cirrus vgabios (patch from Gleb Natapov) + +2008-05-30 17:28 vruppert + + * README (1.16): + + - updated for release 0.6b + +2008-05-22 12:55 vruppert + + * ChangeLog (1.27), README (1.15): + + - preparations for release 0.6b + 2008-05-11 08:40 vruppert * biossums.c (1.6): diff --git a/README b/README index 90141d4..ce67aeb 100644 --- a/README +++ b/README @@ -90,6 +90,12 @@ For any information on qemu, visit the website http://fabrice.bellard.free.fr/qe History --- +vgabios-0.6c : not yet released + - Volker +. added DPMS support to cirrus vgabios (patch from Gleb Natapov) +. use VBE LFB address from PCI base address if present +. added support for a lot more non-standard VBE modes (e.g. widescreen modes) + vgabios-0.6b : May 30 2008 - Volker . added PCI data structure for the Cirrus VGABIOS images -- 1.7.1
[Qemu-devel] [RFC][PATCH v2 01/10] virtagent: add common rpc transport defs
Common code for sending/recieving RPCs via http over virtproxy channel. All communication is done via asynchronous read/write handlers and using non-blocking reads/writes Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtagent-common.c | 431 virtagent-common.h | 73 + 2 files changed, 504 insertions(+), 0 deletions(-) create mode 100644 virtagent-common.c create mode 100644 virtagent-common.h diff --git a/virtagent-common.c b/virtagent-common.c new file mode 100644 index 000..cc58938 --- /dev/null +++ b/virtagent-common.c @@ -0,0 +1,431 @@ +/* + * virt-agent - common host/guest RPC functions + * + * Copyright IBM Corp. 2010 + * + * Authors: + * Adam Litkeagli...@linux.vnet.ibm.com + * Michael Roth mdr...@linux.vnet.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include virtagent-common.h + +#define VA_READ true +#define VA_SEND false + +enum va_rpc_type { +VA_RPC_REQUEST, +VA_RPC_RESPONSE, +}; + +typedef struct VARPCState { +char hdr[VA_HDR_LEN_MAX]; +int fd; +size_t hdr_len; +size_t hdr_pos; +enum { +VA_READ_START, +VA_READ_HDR, +VA_READ_BODY, +VA_SEND_START, +VA_SEND_HDR, +VA_SEND_BODY, +} state; +enum va_rpc_type rpc_type; +char *content; +size_t content_len; +size_t content_pos; +VARPCData *data; +} VARPCState; + +static void va_rpc_read_handler(void *opaque); +static void va_rpc_send_handler(void *opaque); + +static int end_of_header(char *buf, int end_pos) +{ +return !strncmp(buf+(end_pos-2), \n\r\n, 3); +} + +static void va_rpc_hdr_init(VARPCState *s) { +const char *preamble; + +TRACE(called); +/* essentially ignored in the context of virtagent, but might as well */ +if (s-rpc_type == VA_RPC_REQUEST) { +preamble = POST /RPC2 HTTP/1.1; +} else if (s-rpc_type == VA_RPC_RESPONSE) { +preamble = HTTP/1.1 200 OK; +} else { +s-hdr_len = 0; +return; +} + +s-hdr_len = sprintf(s-hdr, + %s EOL + Content-Type: text/xml EOL + Content-Length: %u EOL EOL, + preamble, + (uint32_t)s-content_len); +} + +static void va_rpc_parse_hdr(VARPCState *s) +{ +int i, line_pos = 0; +char line_buf[4096]; + +for (i = 0; i VA_HDR_LEN_MAX; ++i) { +if (s-hdr[i] != '\n') { +/* read line */ +line_buf[line_pos++] = s-hdr[i]; +} else { +/* process line */ +if (strncmp(line_buf, Content-Length: , 16) == 0) { +s-content_len = atoi(line_buf[16]); +return; +} +line_pos = 0; +} +} +} + +static VARPCState *va_rpc_state_new(VARPCData *data, int fd, +enum va_rpc_type rpc_type, bool read) +{ +VARPCState *s = qemu_mallocz(sizeof(VARPCState)); + +s-rpc_type = rpc_type; +s-fd = fd; +s-data = data; +if (s-data == NULL) { +goto EXIT_BAD; +} + +if (read) { +s-state = VA_READ_START; +s-content = NULL; +} else { +s-state = VA_SEND_START; +if (rpc_type == VA_RPC_REQUEST) { +s-content = XMLRPC_MEMBLOCK_CONTENTS(char, s-data-send_req_xml); +s-content_len = XMLRPC_MEMBLOCK_SIZE(char, s-data-send_req_xml); +} else if (rpc_type == VA_RPC_RESPONSE) { +s-content = XMLRPC_MEMBLOCK_CONTENTS(char, s-data-send_resp_xml); +s-content_len = XMLRPC_MEMBLOCK_SIZE(char, s-data-send_resp_xml); +} else { +LOG(unknown rcp type); +goto EXIT_BAD; +} +va_rpc_hdr_init(s); +if (s-hdr_len == 0) { +LOG(failed to initialize http header); +goto EXIT_BAD; +} +} + +return s; +EXIT_BAD: +qemu_free(s); +return NULL; +} + +/* called by va_rpc_read_handler after reading requests */ +static int va_rpc_send_response(VARPCData *data, int fd) +{ +VARPCState *s = va_rpc_state_new(data, fd, VA_RPC_RESPONSE, VA_SEND); + +TRACE(called); +if (s == NULL) { +LOG(failed to set up RPC state); +return -1; +} +TRACE(setting up send handler for RPC request); +vp_set_fd_handler(fd, NULL, va_rpc_send_handler, s); + +return 0; +} + +static void va_rpc_read_handler_completion(VARPCState *s) { +int ret; + +if (s-rpc_type == VA_RPC_REQUEST) { +/* server read request, call it's cb function then set up + * a send handler for the rpc response if there weren't any + * communication errors + */ +s-data-cb(s-data); +if (s-data-status == VA_RPC_STATUS_OK) { +ret = va_rpc_send_response(s-data, s-fd); +
[Qemu-devel] [vgabios patch v2 09/11] update pci_get_lfb_addr for vmware vga
vmware vga has the framebuffer at pci region 1 not 0. This patch makes pci_get_lfb_addr check region 1 too. It also gives names to the numbered labels to make the code more readable. Signed-off-by: Gerd Hoffmann kra...@redhat.com --- vgabios.c | 23 ++- 1 files changed, 14 insertions(+), 9 deletions(-) diff --git a/vgabios.c b/vgabios.c index 2e8b5d7..c1e312b 100644 --- a/vgabios.c +++ b/vgabios.c @@ -3852,26 +3852,31 @@ _pci_get_lfb_addr: mov dl, #0x00 call pci_read_reg cmp ax, #0x -jz pci_get_lfb_addr_5 - pci_get_lfb_addr_3: +jz pci_get_lfb_addr_fail + pci_get_lfb_addr_next_dev: mov dl, #0x00 call pci_read_reg cmp ax, bx ;; check vendor -jz pci_get_lfb_addr_4 +jz pci_get_lfb_addr_found add cx, #0x8 cmp cx, #0x200 ;; search bus #0 and #1 -jb pci_get_lfb_addr_3 - pci_get_lfb_addr_5: +jb pci_get_lfb_addr_next_dev + pci_get_lfb_addr_fail: xor dx, dx ;; no LFB -jmp pci_get_lfb_addr_6 - pci_get_lfb_addr_4: +jmp pci_get_lfb_addr_return + pci_get_lfb_addr_found: mov dl, #0x10 ;; I/O space #0 call pci_read_reg test ax, #0xfff1 -jnz pci_get_lfb_addr_5 +jz pci_get_lfb_addr_success +mov dl, #0x14 ;; I/O space #1 +call pci_read_reg +test ax, #0xfff1 +jnz pci_get_lfb_addr_fail + pci_get_lfb_addr_success: shr eax, #16 mov dx, ax ;; LFB address - pci_get_lfb_addr_6: + pci_get_lfb_addr_return: pop eax mov ax, dx pop dx -- 1.7.1
[Qemu-devel] [vgabios patch v2 10/11] Add qemu vmware vga pci bios
Add PCI vgabios for the qemu vmware vga (15ad:0405). Name it vgabios-vmware.bin. Signed-off-by: Gerd Hoffmann kra...@redhat.com --- Makefile | 10 +- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/Makefile b/Makefile index 58f064e..2a093e8 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ RELVERS = `pwd | sed s-.*/-- | sed s/vgabios// | sed s/-//` VGABIOS_DATE = -DVGABIOS_DATE=\$(RELDATE)\ -all: bios cirrus-bios stdvga-bios +all: bios cirrus-bios stdvga-bios vmware-bios bios: vgabios.bin vgabios.debug.bin @@ -22,6 +22,8 @@ cirrus-bios: vgabios-cirrus.bin vgabios-cirrus.debug.bin stdvga-bios: vgabios-stdvga.bin vgabios-stdvga.debug.bin +vmware-bios: vgabios-vmware.bin vgabios-vmware.debug.bin + clean: /bin/rm -f biossums vbetables-gen vbetables.h *.o *.s *.ld86 \ temp.awk.* vgabios*.orig _vgabios_* _vgabios-debug_* core vgabios*.bin vgabios*.txt $(RELEASE).bin *.bak @@ -39,6 +41,8 @@ vgabios-cirrus.bin : VGAFLAGS := -DCIRRUS -DPCIBIOS vgabios-cirrus.debug.bin : VGAFLAGS := -DCIRRUS -DPCIBIOS -DCIRRUS_DEBUG vgabios-stdvga.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x1234 -DPCI_DID=0x vgabios-stdvga.debug.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x1234 -DPCI_DID=0x -DDEBUG +vgabios-vmware.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x15ad -DPCI_DID=0x0405 +vgabios-vmware.debug.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x15ad -DPCI_DID=0x0405 -DDEBUG # dist names vgabios.bin : DISTNAME := VGABIOS-lgpl-latest.bin @@ -47,6 +51,8 @@ vgabios-cirrus.bin : DISTNAME := VGABIOS-lgpl-latest.cirrus.bin vgabios-cirrus.debug.bin : DISTNAME := VGABIOS-lgpl-latest.cirrus.debug.bin vgabios-stdvga.bin : DISTNAME := VGABIOS-lgpl-latest.stdvga.bin vgabios-stdvga.debug.bin : DISTNAME := VGABIOS-lgpl-latest.stdvga.debug.bin +vgabios-vmware.bin : DISTNAME := VGABIOS-lgpl-latest.vmware.bin +vgabios-vmware.debug.bin : DISTNAME := VGABIOS-lgpl-latest.vmware.debug.bin # dependencies vgabios.bin : $(VGA_FILES) $(VBE_FILES) biossums @@ -55,6 +61,8 @@ vgabios-cirrus.bin : $(VGA_FILES) clext.c biossums vgabios-cirrus.debug.bin : $(VGA_FILES) clext.c biossums vgabios-stdvga.bin : $(VGA_FILES) $(VBE_FILES) biossums vgabios-stdvga.debug.bin : $(VGA_FILES) $(VBE_FILES) biossums +vgabios-vmware.bin : $(VGA_FILES) $(VBE_FILES) biossums +vgabios-vmware.debug.bin : $(VGA_FILES) $(VBE_FILES) biossums # build rule %.bin: -- 1.7.1
[Qemu-devel] [vgabios patch v2 02/11] - added support for a lot more non-standard VBE modes (e.g. widescreen modes) - requires latest Bochs VBE code (16 MB video memory, VBE_DISPI_ID5, VRAM size in 64
From: Volker Ruppert i...@vruppert.de --- vbe.c | 31 ++-- vbe.h | 70 -- vbetables-gen.c | 43 + 3 files changed, 91 insertions(+), 53 deletions(-) diff --git a/vbe.c b/vbe.c index 92e3d0d..ecff90d 100644 --- a/vbe.c +++ b/vbe.c @@ -38,8 +38,6 @@ #include vbe.h #include vbetables.h -#define VBE_TOTAL_VIDEO_MEMORY_DIV_64K (VBE_DISPI_TOTAL_VIDEO_MEMORY_MB*1024/64) - // The current OEM Software Revision of this VBE Bios #define VBE_OEM_SOFTWARE_REV 0x0002; @@ -715,7 +713,7 @@ vbe_init: mov [bx], al pop bx pop ds - mov ax, # VBE_DISPI_ID4 + mov ax, # VBE_DISPI_ID5 call dispi_set_id no_vbe_interface: #if defined(USE_BX_INFO) || defined(DEBUG) @@ -742,7 +740,19 @@ no_vbe_flag: mov ds, ax mov si, #_no_vbebios_info_string jmp _display_string -ASM_END + +; helper function for memory size calculation + +lmulul: + and eax, #0x + shl ebx, #16 + or eax, ebx + SEG SS + mul eax, dword ptr [di] + mov ebx, eax + shr ebx, #16 + ret +ASM_END /** Function 00h - Return VBE Controller Information * @@ -765,6 +775,7 @@ Bit16u *AX;Bit16u ES;Bit16u DI; Bit16uvbe2_info; Bit16ucur_mode=0; Bit16ucur_ptr=34; +Bit16usize_64k; ModeInfoListItem *cur_info=mode_info_list; status = read_word(ss, AX); @@ -820,8 +831,9 @@ Bit16u *AX;Bit16u ES;Bit16u DI; vbe_info_block.VideoModePtr_Seg= ES ; vbe_info_block.VideoModePtr_Off= DI + 34; -// VBE Total Memory (in 64b blocks) -vbe_info_block.TotalMemory = VBE_TOTAL_VIDEO_MEMORY_DIV_64K; +// VBE Total Memory (in 64k blocks) +outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIDEO_MEMORY_64K); +vbe_info_block.TotalMemory = inw(VBE_DISPI_IOPORT_DATA); if (vbe2_info) { @@ -845,8 +857,11 @@ Bit16u *AX;Bit16u ES;Bit16u DI; do { +size_64k = (Bit16u)((Bit32u)cur_info-info.XResolution * cur_info-info.XResolution * cur_info-info.BitsPerPixel) 19; + if ((cur_info-info.XResolution = dispi_get_max_xres()) -(cur_info-info.BitsPerPixel = dispi_get_max_bpp())) { +(cur_info-info.BitsPerPixel = dispi_get_max_bpp()) +(size_64k = vbe_info_block.TotalMemory)) { #ifdef DEBUG printf(VBE found mode %x = %x\n, cur_info-mode,cur_mode); #endif @@ -855,7 +870,7 @@ Bit16u *AX;Bit16u ES;Bit16u DI; cur_ptr+=2; } else { #ifdef DEBUG - printf(VBE mode %x (xres=%x / bpp=%02x) not supported by display\n, cur_info-mode,cur_info-info.XResolution,cur_info-info.BitsPerPixel); + printf(VBE mode %x (xres=%x / bpp=%02x) not supported \n, cur_info-mode,cur_info-info.XResolution,cur_info-info.BitsPerPixel); #endif } cur_info++; diff --git a/vbe.h b/vbe.h index 60434ac..72cb045 100644 --- a/vbe.h +++ b/vbe.h @@ -275,39 +275,41 @@ typedef struct ModeInfoListItem //like 0xE000 - #define VBE_DISPI_BANK_ADDRESS 0xA - #define VBE_DISPI_BANK_SIZE_KB 64 - - #define VBE_DISPI_MAX_XRES 1024 - #define VBE_DISPI_MAX_YRES 768 - - #define VBE_DISPI_IOPORT_INDEX 0x01CE - #define VBE_DISPI_IOPORT_DATA 0x01CF - - #define VBE_DISPI_INDEX_ID 0x0 - #define VBE_DISPI_INDEX_XRES0x1 - #define VBE_DISPI_INDEX_YRES0x2 - #define VBE_DISPI_INDEX_BPP 0x3 - #define VBE_DISPI_INDEX_ENABLE 0x4 - #define VBE_DISPI_INDEX_BANK0x5 - #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 - #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 - #define VBE_DISPI_INDEX_X_OFFSET0x8 - #define VBE_DISPI_INDEX_Y_OFFSET0x9 - - #define VBE_DISPI_ID0 0xB0C0 - #define VBE_DISPI_ID1 0xB0C1 - #define VBE_DISPI_ID2 0xB0C2 - #define VBE_DISPI_ID3 0xB0C3 - #define VBE_DISPI_ID4 0xB0C4 - - #define VBE_DISPI_DISABLED 0x00 - #define VBE_DISPI_ENABLED 0x01 - #define VBE_DISPI_GETCAPS 0x02 - #define VBE_DISPI_8BIT_DAC 0x20 - #define VBE_DISPI_LFB_ENABLED 0x40 - #define VBE_DISPI_NOCLEARMEM0x80 - - #define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE000 + #define VBE_DISPI_BANK_ADDRESS 0xA + #define VBE_DISPI_BANK_SIZE_KB 64 + + #define VBE_DISPI_MAX_XRES 2560 + #define VBE_DISPI_MAX_YRES 1600 + + #define VBE_DISPI_IOPORT_INDEX 0x01CE + #define VBE_DISPI_IOPORT_DATA0x01CF + + #define VBE_DISPI_INDEX_ID 0x0 + #define VBE_DISPI_INDEX_XRES
[Qemu-devel] [RFC][PATCH v2 08/10] virtagent: add agent_viewdmesg command
Add commands to view guest dmesg output. Currently it is a 16K buffer. Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- hmp-commands.hx | 16 + qmp-commands.hx | 35 +++ virtagent.c | 99 +++ virtagent.h |3 ++ 4 files changed, 153 insertions(+), 0 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index e9a7f4a..0e7a6c9 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1227,6 +1227,22 @@ STEXI Echo the file identified by @var{filepath} on the guest filesystem ETEXI +{ +.name = agent_viewdmesg, +.args_type = , +.params = , +.help = View guest dmesg output, +.user_print = do_agent_viewdmesg_print, +.mhandler.cmd_async = do_agent_viewdmesg, +.flags = MONITOR_CMD_ASYNC, +}, + +STEXI +...@item agent_viewdmesg +...@findex agent_viewdmesg +View guest dmesg output +ETEXI + STEXI @end table ETEXI diff --git a/qmp-commands.hx b/qmp-commands.hx index efa2137..dc319b7 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -771,6 +771,41 @@ Example: EQMP { +.name = agent_viewdmesg, +.args_type = , +.params = , +.help = View guest dmesg output, +.user_print = do_agent_viewdmesg_print, +.mhandler.cmd_async = do_agent_viewdmesg, +.flags = MONITOR_CMD_ASYNC, +}, + +STEXI +...@item agent_viewdmesg +...@findex agent_viewdmesg +View guest dmesg output +ETEXI +SQMP +agent_viewdmesg + + +View guest dmesg output + +Arguments: + +(none) + +Example: + +- { execute: agent_viewdmesg } +- { return: { + contents: [353487.942215] usb 1-4: USB disconnect, address 9\n... + } + } + +EQMP + +{ .name = qmp_capabilities, .args_type = , .params = , diff --git a/virtagent.c b/virtagent.c index 187bb28..e1fceed 100644 --- a/virtagent.c +++ b/virtagent.c @@ -185,3 +185,102 @@ int do_agent_viewfile(Monitor *mon, const QDict *mon_params, return 0; } + +void do_agent_viewdmesg_print(Monitor *mon, const QObject *data) +{ +QDict *qdict; +const char *contents = NULL; +int i; + +qdict = qobject_to_qdict(data); +if (!qdict_haskey(qdict, contents)) { +goto out; +} + +contents = qdict_get_str(qdict, contents); +if (contents != NULL) { + /* monitor_printf truncates so do it in chunks. also, file_contents + * may not be null-termed at proper location so explicitly calc + * last chunk sizes */ +for (i = 0; i strlen(contents); i += 1024) { +monitor_printf(mon, %.1024s, contents + i); +} +} + +out: +monitor_printf(mon, \n); +} + +static void do_agent_viewdmesg_cb(void *opaque) +{ +VARPCData *rpc_data = opaque; +xmlrpc_value *resp = NULL; +char *dmesg = NULL; +int ret; +xmlrpc_env env; +QDict *qdict = qdict_new(); + +if (rpc_data-status != VA_RPC_STATUS_OK) { +LOG(error handling RPC request); +goto out_no_resp; +} + +xmlrpc_env_init(env); +resp = xmlrpc_parse_response(env, rpc_data-resp_xml, + rpc_data-resp_xml_len); +if (rpc_has_error(env)) { +ret = -1; +goto out_no_resp; +} + +xmlrpc_parse_value(env, resp, s, dmesg); +if (rpc_has_error(env)) { +ret = -1; +goto out; +} + +if (dmesg != NULL) { +qdict_put(qdict, contents, qstring_from_str(dmesg)); +} + +out: +xmlrpc_DECREF(resp); +out_no_resp: +rpc_data-mon_cb(rpc_data-mon_data, QOBJECT(qdict)); +} + +/* + * do_agent_viewdmesg(): View guest dmesg output + */ +int do_agent_viewdmesg(Monitor *mon, const QDict *mon_params, + MonitorCompletion cb, void *opaque) +{ +xmlrpc_env env; +xmlrpc_value *params; +VARPCData *rpc_data; +int ret; + +xmlrpc_env_init(env); + +params = xmlrpc_build_value(env, (n)); +if (rpc_has_error(env)) { +return -1; +} + +rpc_data = qemu_mallocz(sizeof(VARPCData)); +rpc_data-cb = do_agent_viewdmesg_cb; +rpc_data-mon_cb = cb; +rpc_data-mon_data = opaque; + +ret = rpc_execute(env, getdmesg, params, rpc_data); +if (ret == -EREMOTE) { +monitor_printf(mon, RPC Failed (%i): %s\n, env.fault_code, + env.fault_string); +return -1; +} else if (ret == -1) { +monitor_printf(mon, RPC communication error\n); +return -1; +} + +return 0; +} diff --git a/virtagent.h b/virtagent.h index d027eac..82a6924 100644 --- a/virtagent.h +++ b/virtagent.h @@ -25,5 +25,8 @@ void do_agent_viewfile_print(Monitor *mon, const QObject *qobject); int do_agent_viewfile(Monitor *mon, const QDict *mon_params, MonitorCompletion cb, void *opaque); +void do_agent_viewdmesg_print(Monitor *mon, const QObject *qobject); +int
[Qemu-devel] [vgabios patch v2 01/11] - use VBE LFB address from PCI base address if present (rewrite of the cirrus specific function in main vgabios code) - removed unnecessary spaces
From: Volker Ruppert i...@vruppert.de --- clext.c | 51 ++- vbe.c | 59 --- vgabios.c | 58 ++ 3 files changed, 92 insertions(+), 76 deletions(-) diff --git a/clext.c b/clext.c index c7a2ad0..b0b6834 100644 --- a/clext.c +++ b/clext.c @@ -948,7 +948,8 @@ cirrus_vesa_01h_3: ;; 32-bit LFB address xor ax, ax stosw - call cirrus_get_lfb_addr + mov ax, #0x1013 ;; vendor Cirrus + call _pci_get_lfb_addr stosw or ax, ax jz cirrus_vesa_01h_4 @@ -1293,54 +1294,6 @@ cgm_2: cgm_3: ret - ; get LFB address - ; out - ax:LFB address (high 16 bit) - ;; NOTE - may be called in protected mode -cirrus_get_lfb_addr: - push cx - push dx - push eax -xor cx, cx -mov dl, #0x00 -call cirrus_pci_read -cmp ax, #0x -jz cirrus_get_lfb_addr_5 - cirrus_get_lfb_addr_3: -mov dl, #0x00 -call cirrus_pci_read -cmp ax, #0x1013 ;; cirrus -jz cirrus_get_lfb_addr_4 -add cx, #0x8 -cmp cx, #0x200 ;; search bus #0 and #1 -jb cirrus_get_lfb_addr_3 - cirrus_get_lfb_addr_5: -xor dx, dx ;; no LFB -jmp cirrus_get_lfb_addr_6 - cirrus_get_lfb_addr_4: -mov dl, #0x10 ;; I/O space #0 -call cirrus_pci_read -test ax, #0xfff1 -jnz cirrus_get_lfb_addr_5 -shr eax, #16 -mov dx, ax ;; LFB address - cirrus_get_lfb_addr_6: - pop eax - mov ax, dx - pop dx - pop cx - ret - -cirrus_pci_read: - mov eax, #0x0080 - mov ax, cx - shl eax, #8 - mov al, dl - mov dx, #0xcf8 - out dx, eax - add dl, #4 - in eax, dx - ret - ;; out - al:bytes per pixel cirrus_get_bpp_bytes: push dx diff --git a/vbe.c b/vbe.c index 6173ca0..92e3d0d 100644 --- a/vbe.c +++ b/vbe.c @@ -766,9 +766,9 @@ Bit16u *AX;Bit16u ES;Bit16u DI; Bit16ucur_mode=0; Bit16ucur_ptr=34; ModeInfoListItem *cur_info=mode_info_list; - + status = read_word(ss, AX); - + #ifdef DEBUG printf(VBE vbe_biosfn_return_vbe_info ES%x DI%x AX%x\n,ES,DI,status); #endif @@ -784,7 +784,7 @@ Bit16u *AX;Bit16u ES;Bit16u DI; (vbe_info_block.VbeSignature[1] == 'B') (vbe_info_block.VbeSignature[2] == 'E') (vbe_info_block.VbeSignature[3] == '2')) || - + ((vbe_info_block.VbeSignature[0] == 'V') (vbe_info_block.VbeSignature[1] == 'E') (vbe_info_block.VbeSignature[2] == 'S') @@ -796,20 +796,20 @@ Bit16u *AX;Bit16u ES;Bit16u DI; #endif } #endif - + // VBE Signature vbe_info_block.VbeSignature[0] = 'V'; vbe_info_block.VbeSignature[1] = 'E'; vbe_info_block.VbeSignature[2] = 'S'; vbe_info_block.VbeSignature[3] = 'A'; - + // VBE Version supported vbe_info_block.VbeVersion = 0x0200; - + // OEM String vbe_info_block.OemStringPtr_Seg = 0xc000; vbe_info_block.OemStringPtr_Off = vbebios_copyright; - + // Capabilities vbe_info_block.Capabilities[0] = VBE_CAPABILITY_8BIT_DAC; vbe_info_block.Capabilities[1] = 0; @@ -824,7 +824,7 @@ Bit16u *AX;Bit16u ES;Bit16u DI; vbe_info_block.TotalMemory = VBE_TOTAL_VIDEO_MEMORY_DIV_64K; if (vbe2_info) - { +{ // OEM Stuff vbe_info_block.OemSoftwareRev = VBE_OEM_SOFTWARE_REV; vbe_info_block.OemVendorNamePtr_Seg = 0xc000; @@ -837,12 +837,12 @@ Bit16u *AX;Bit16u ES;Bit16u DI; // copy updates in vbe_info_block back memcpyb(ES, DI, ss, vbe_info_block, sizeof(vbe_info_block)); } - else - { +else +{ // copy updates in vbe_info_block back (VBE 1.x compatibility) memcpyb(ES, DI, ss, vbe_info_block, 256); - } - +} + do { if ((cur_info-info.XResolution = dispi_get_max_xres()) @@ -860,7 +860,7 @@ Bit16u *AX;Bit16u ES;Bit16u DI; } cur_info++; } while (cur_info-mode != VBE_VESA_MODE_END_OF_LIST); - + // Add vesa mode list terminator write_word(ES, DI + cur_ptr, cur_info-mode); @@ -888,32 +888,37 @@ Bit16u *AX;Bit16u CX; Bit16u ES;Bit16u DI; ModeInfoBlock info; ModeInfoListItem *cur_info; Boolean using_lfb; +Bit16ulfb_addr; #ifdef DEBUG printf(VBE vbe_biosfn_return_mode_information ES%x DI%x CX%x\n,ES,DI,CX); #endif using_lfb=((CX VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER); - + CX = (CX 0x1ff); - + cur_info = mode_info_find_mode(CX, using_lfb, cur_info); if (cur_info != 0) { #ifdef DEBUG
[Qemu-devel] [vgabios patch v2 04/11] - biosfn_write_teletype: fixed attribute when scrolling in text mode
From: Volker Ruppert i...@vruppert.de --- vgabios.c |6 -- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/vgabios.c b/vgabios.c index fbc3588..ea3aae8 100644 --- a/vgabios.c +++ b/vgabios.c @@ -2039,7 +2039,9 @@ Bit8u car;Bit8u page;Bit8u attr;Bit8u flag; { if(vga_modes[line].class==TEXT) { - biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP); + address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+(ycurs-1)*nbcols)*2; + attr=read_byte(vga_modes[line].sstart,address+1); + biosfn_scroll(0x01,attr,0,0,nbrows-1,nbcols-1,page,SCROLL_UP); } else { @@ -2047,7 +2049,7 @@ Bit8u car;Bit8u page;Bit8u attr;Bit8u flag; } ycurs-=1; } - + // Set the cursor for the page cursor=ycurs; cursor=8; cursor+=xcurs; biosfn_set_cursor_pos(page,cursor); -- 1.7.1
[Qemu-devel] [RFC][PATCH v2 03/10] virtagent: qemu-vp, integrate virtagent server
This allows the guest RPC server to be integrated into the qemu-vp/virtproxy i/o loop Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- qemu-vp.c | 115 - 1 files changed, 106 insertions(+), 9 deletions(-) diff --git a/qemu-vp.c b/qemu-vp.c index 0cc0e67..8944e68 100644 --- a/qemu-vp.c +++ b/qemu-vp.c @@ -37,6 +37,7 @@ #include qemu-option.h #include qemu_socket.h #include virtproxy.h +#include virtagent-daemon.h static bool verbose_enabled = 0; #define DEBUG_ENABLED @@ -246,14 +247,18 @@ static void usage(const char *cmd) [-o oforward_opts ...]\n QEMU virt-proxy communication channel\n \n - -c, --channelchannel options of the form:\n - method:addr:port[:channel_id]\n - -o, --oforward oforward options of the form:\n - service_id:addr:port[:channel_id]\n - -i, --iforward iforward options of the form:\n - service_id:addr:port[:channel_id]\n - -v, --verbosedisplay extra debugging information\n - -h, --help display this help and exit\n + -c, --channel channel options of the form:\n +method:addr:port[:channel_id]\n + -p, --host-agent host rpc server, options of the form:\n +[channel_id]\n + -g, --guest-agent guest rpc server, options of the form:\n +[channel_id]\n + -o, --oforwardoforward options of the form:\n +service_id:addr:port[:channel_id]\n + -i, --iforwardiforward options of the form:\n +service_id:addr:port[:channel_id]\n + -v, --verbose display extra debugging information\n + -h, --helpdisplay this help and exit\n \n channels are used to establish a data connection between 2 end-points in\n the host or the guest (connection method specified by method).\n @@ -527,13 +532,44 @@ static int init_iforwards(void) { return 0; } +static int init_agent(const VPData *agent_iforward, bool is_host) { +QemuOpts *opts = agent_iforward-opts; +int listen_fd, ret; + +INFO(initializing agent...); +if (verbose_enabled) { +qemu_opts_print(opts, NULL); +} + +/* create unix socket pair that agent http/rpc daemon will listen on */ +listen_fd = unix_listen_opts(agent_iforward-opts); +if (listen_fd 0) { +return -1; +} + +/* start RPC server */ +ret = va_server_start(listen_fd, is_host); +if (ret != 0) { +warnx(error starting RPC server); +goto err; +} + +return 0; + +err: +closesocket(listen_fd); +return -1; +} + int main(int argc, char **argv) { -const char *sopt = hVvi:o:c:; +const char *sopt = hVvi:o:c:g::p::; struct option lopt[] = { { help, 0, NULL, 'h' }, { version, 0, NULL, 'V' }, { verbose, 0, NULL, 'v' }, +{ host-agent, 0, NULL, 'p' }, +{ guest-agent, 0, NULL, 'g' }, { iforward, 0, NULL, 'i' }, { oforward, 0, NULL, 'o' }, { channel, 0, NULL, 'c' }, @@ -543,10 +579,13 @@ int main(int argc, char **argv) QTAILQ_INIT(iforwards); QTAILQ_INIT(oforwards); QTAILQ_INIT(channels); +VPData *guest_agent_iforward = NULL; +VPData *host_agent_iforward = NULL; while ((ch = getopt_long(argc, argv, sopt, lopt, opt_ind)) != -1) { QemuOpts *opts; VPData *data; +char optarg_tmp[VP_ARG_LEN]; switch (ch) { case 'i': opts = qemu_opts_create(vp_opts, NULL, 0); @@ -578,6 +617,50 @@ int main(int argc, char **argv) data-opts = opts; QTAILQ_INSERT_TAIL(channels, data, next); break; +case 'g': +/* create pre-baked iforward for guest agent */ +if (guest_agent_iforward) { +errx(EXIT_FAILURE, only one --guest-agent argument allowed); +} +opts = qemu_opts_create(vp_opts, NULL, 0); +if (optarg == 0) { +sprintf(optarg_tmp, %s:%s:-, GUEST_AGENT_SERVICE_ID, + GUEST_AGENT_PATH); +} else { +sprintf(optarg_tmp, %s:%s:-:%d, GUEST_AGENT_SERVICE_ID, + GUEST_AGENT_PATH, atoi(optarg)); +} +ret = vp_parse(opts, optarg_tmp, 0); +if (ret) { +errx(EXIT_FAILURE, error parsing arg: %s, optarg); +} +data = qemu_mallocz(sizeof(VPData)); +data-opts = opts; +QTAILQ_INSERT_TAIL(iforwards, data, next); +guest_agent_iforward = data; +break; +case 'p': +/* create pre-baked iforward for host agent */ +if (host_agent_iforward) { +errx(EXIT_FAILURE, only one --host-agent argument allowed); +} +opts = qemu_opts_create(vp_opts, NULL, 0); +if (optarg == 0) { +
[Qemu-devel] [vgabios patch v2 07/11] Add defines for PCI IDs.
This patch allows to set PCI vendor and device IDs using defines (PCI_VID and PCI_DID). Use it for vgabios.bin. Signed-off-by: Gerd Hoffmann kra...@redhat.com --- Makefile |4 ++-- vbe.c |6 +- vgabios.c |5 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index c3c744c..d440b93 100644 --- a/Makefile +++ b/Makefile @@ -31,8 +31,8 @@ VGA_FILES := vgabios.c vgabios.h vgafonts.h vgatables.h VBE_FILES := vbe.h vbe.c vbetables.h # build flags -vgabios.bin : VGAFLAGS := -DVBE -vgabios.debug.bin: VGAFLAGS := -DVBE -DDEBUG +vgabios.bin : VGAFLAGS := -DVBE -DPCI_VID=0x1234 +vgabios.debug.bin: VGAFLAGS := -DVBE -DPCI_VID=0x1234 -DDEBUG vgabios-cirrus.bin : VGAFLAGS := -DCIRRUS -DPCIBIOS vgabios-cirrus.debug.bin : VGAFLAGS := -DCIRRUS -DPCIBIOS -DCIRRUS_DEBUG diff --git a/vbe.c b/vbe.c index ecff90d..1fab2f9 100644 --- a/vbe.c +++ b/vbe.c @@ -925,7 +925,11 @@ Bit16u *AX;Bit16u CX; Bit16u ES;Bit16u DI; if (using_lfb) { info.NumberOfBanks = 1; } -lfb_addr = pci_get_lfb_addr(0x1234); // experimental vendor +#ifdef PCI_VID +lfb_addr = pci_get_lfb_addr(PCI_VID); +#else +lfb_addr = 0; +#endif if (lfb_addr 0) { info.PhysBasePtr = ((Bit32u)lfb_addr 16); } diff --git a/vgabios.c b/vgabios.c index ea3aae8..2e8b5d7 100644 --- a/vgabios.c +++ b/vgabios.c @@ -210,8 +210,13 @@ vgabios_pci_data: .word 0x1013 .word 0x00b8 // CLGD5446 #else +#ifdef PCI_VID +.word PCI_VID +.word PCI_DID +#else #error Unknown PCI vendor and device id #endif +#endif .word 0 // reserved .word 0x18 // dlen .byte 0 // revision -- 1.7.1
[Qemu-devel] [vgabios patch v2 11/11] Add qemu qxl vga pci bios
Add PCI vgabios for the qemu qxl vga (1b36:0100). Name it vgabios-qxl.bin. Signed-off-by: Gerd Hoffmann kra...@redhat.com --- Makefile | 10 +- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/Makefile b/Makefile index 2a093e8..578721a 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ RELVERS = `pwd | sed s-.*/-- | sed s/vgabios// | sed s/-//` VGABIOS_DATE = -DVGABIOS_DATE=\$(RELDATE)\ -all: bios cirrus-bios stdvga-bios vmware-bios +all: bios cirrus-bios stdvga-bios vmware-bios qxl-bios bios: vgabios.bin vgabios.debug.bin @@ -24,6 +24,8 @@ stdvga-bios: vgabios-stdvga.bin vgabios-stdvga.debug.bin vmware-bios: vgabios-vmware.bin vgabios-vmware.debug.bin +qxl-bios: vgabios-qxl.bin vgabios-qxl.debug.bin + clean: /bin/rm -f biossums vbetables-gen vbetables.h *.o *.s *.ld86 \ temp.awk.* vgabios*.orig _vgabios_* _vgabios-debug_* core vgabios*.bin vgabios*.txt $(RELEASE).bin *.bak @@ -43,6 +45,8 @@ vgabios-stdvga.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x1234 -DPCI_DI vgabios-stdvga.debug.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x1234 -DPCI_DID=0x -DDEBUG vgabios-vmware.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x15ad -DPCI_DID=0x0405 vgabios-vmware.debug.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x15ad -DPCI_DID=0x0405 -DDEBUG +vgabios-qxl.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x1b36 -DPCI_DID=0x0100 +vgabios-qxl.debug.bin: VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x1b36 -DPCI_DID=0x0100 -DDEBUG # dist names vgabios.bin : DISTNAME := VGABIOS-lgpl-latest.bin @@ -53,6 +57,8 @@ vgabios-stdvga.bin : DISTNAME := VGABIOS-lgpl-latest.stdvga.bin vgabios-stdvga.debug.bin : DISTNAME := VGABIOS-lgpl-latest.stdvga.debug.bin vgabios-vmware.bin : DISTNAME := VGABIOS-lgpl-latest.vmware.bin vgabios-vmware.debug.bin : DISTNAME := VGABIOS-lgpl-latest.vmware.debug.bin +vgabios-qxl.bin : DISTNAME := VGABIOS-lgpl-latest.qxl.bin +vgabios-qxl.debug.bin: DISTNAME := VGABIOS-lgpl-latest.qxl.debug.bin # dependencies vgabios.bin : $(VGA_FILES) $(VBE_FILES) biossums @@ -63,6 +69,8 @@ vgabios-stdvga.bin : $(VGA_FILES) $(VBE_FILES) biossums vgabios-stdvga.debug.bin : $(VGA_FILES) $(VBE_FILES) biossums vgabios-vmware.bin : $(VGA_FILES) $(VBE_FILES) biossums vgabios-vmware.debug.bin : $(VGA_FILES) $(VBE_FILES) biossums +vgabios-qxl.bin : $(VGA_FILES) $(VBE_FILES) biossums +vgabios-qxl.debug.bin: $(VGA_FILES) $(VBE_FILES) biossums # build rule %.bin: -- 1.7.1
[Qemu-devel] [vgabios patch v2 05/11] - updates for release 0.6c
From: Volker Ruppert i...@vruppert.de --- ChangeLog | 12 README|3 ++- 2 files changed, 14 insertions(+), 1 deletions(-) diff --git a/ChangeLog b/ChangeLog index 35bf00a..dbaed5d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2009-04-07 20:18 vruppert + + * vgabios.c (1.69): + + - biosfn_write_teletype: fixed attribute when scrolling in text mode + +2009-04-06 20:17 vruppert + + * ChangeLog (1.28), README (1.17): + + - preparing for release 0.6c + 2009-01-25 16:46 vruppert * vbe.c (1.62), vbe.h (1.28), vbetables-gen.c (1.5): diff --git a/README b/README index ce67aeb..c68b573 100644 --- a/README +++ b/README @@ -90,11 +90,12 @@ For any information on qemu, visit the website http://fabrice.bellard.free.fr/qe History --- -vgabios-0.6c : not yet released +vgabios-0.6c : Apr 08 2009 - Volker . added DPMS support to cirrus vgabios (patch from Gleb Natapov) . use VBE LFB address from PCI base address if present . added support for a lot more non-standard VBE modes (e.g. widescreen modes) +. minor bugfixes vgabios-0.6b : May 30 2008 - Volker -- 1.7.1
[Qemu-devel] [PATCH v3 1/4] Add new vgabios binaries to blobs list.
Signed-off-by: Gerd Hoffmann kra...@redhat.com --- Makefile |5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 02698e9..663d1a1 100644 --- a/Makefile +++ b/Makefile @@ -178,8 +178,9 @@ ar de en-us fi fr-be hr it lv nl pl ru th \ common de-ch es fo fr-ca hu ja mk nl-be pt sl tr ifdef INSTALL_BLOBS -BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \ -openbios-sparc32 openbios-sparc64 openbios-ppc \ +BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin \ +vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \ +ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \ gpxe-eepro100-80861209.rom \ gpxe-eepro100-80861229.rom \ pxe-e1000.bin \ -- 1.7.1
[Qemu-devel] [vgabios patch v2 06/11] Makefile cleanup
Use a single rule for building bios binaries. Use target specific variables to set compile flags. This makes it more obvious what the differences between the versions are. It also makes it easier to add new bios binaries with slightly different settings. Signed-off-by: Gerd Hoffmann kra...@redhat.com --- Makefile | 76 +++-- 1 files changed, 34 insertions(+), 42 deletions(-) diff --git a/Makefile b/Makefile index 00e8c66..c3c744c 100644 --- a/Makefile +++ b/Makefile @@ -16,8 +16,7 @@ VGABIOS_DATE = -DVGABIOS_DATE=\$(RELDATE)\ all: bios cirrus-bios - -bios: biossums vgabios.bin vgabios.debug.bin +bios: vgabios.bin vgabios.debug.bin cirrus-bios: vgabios-cirrus.bin vgabios-cirrus.debug.bin @@ -27,6 +26,39 @@ clean: dist-clean: clean +# source files +VGA_FILES := vgabios.c vgabios.h vgafonts.h vgatables.h +VBE_FILES := vbe.h vbe.c vbetables.h + +# build flags +vgabios.bin : VGAFLAGS := -DVBE +vgabios.debug.bin: VGAFLAGS := -DVBE -DDEBUG +vgabios-cirrus.bin : VGAFLAGS := -DCIRRUS -DPCIBIOS +vgabios-cirrus.debug.bin : VGAFLAGS := -DCIRRUS -DPCIBIOS -DCIRRUS_DEBUG + +# dist names +vgabios.bin : DISTNAME := VGABIOS-lgpl-latest.bin +vgabios.debug.bin: DISTNAME := VGABIOS-lgpl-latest.debug.bin +vgabios-cirrus.bin : DISTNAME := VGABIOS-lgpl-latest.cirrus.bin +vgabios-cirrus.debug.bin : DISTNAME := VGABIOS-lgpl-latest.cirrus.debug.bin + +# dependencies +vgabios.bin : $(VGA_FILES) $(VBE_FILES) biossums +vgabios.debug.bin: $(VGA_FILES) $(VBE_FILES) biossums +vgabios-cirrus.bin : $(VGA_FILES) clext.c biossums +vgabios-cirrus.debug.bin : $(VGA_FILES) clext.c biossums + +# build rule +%.bin: + $(GCC) -E -P vgabios.c $(VGABIOS_VERS) $(VGAFLAGS) $(VGABIOS_DATE) _$*_.c + $(BCC) -o $*.s -C-c -D__i86__ -S -0 _$*_.c + sed -e 's/^\.text//' -e 's/^\.data//' $*.s _$*_.s + $(AS86) _$*_.s -b $*.bin -u -w- -g -0 -j -O -l $*.txt + rm -f _$*_.s _$*_.c $*.s + mv $*.bin $(DISTNAME) + ./biossums $(DISTNAME) + ls -l $(DISTNAME) + release: VGABIOS_VERS=\-DVGABIOS_VERS=\\\$(RELVERS) make bios cirrus-bios /bin/rm -f *.o *.s *.ld86 \ @@ -37,46 +69,6 @@ release: cp VGABIOS-lgpl-latest.cirrus.debug.bin ../$(RELEASE).cirrus.debug.bin tar czvf ../$(RELEASE).tgz --exclude CVS -C .. $(RELEASE)/ -vgabios.bin: vgabios.c vgabios.h vgafonts.h vgatables.h vbe.h vbe.c vbetables.h - $(GCC) -E -P vgabios.c $(VGABIOS_VERS) -DVBE $(VGABIOS_DATE) _vgabios_.c - $(BCC) -o vgabios.s -C-c -D__i86__ -S -0 _vgabios_.c - sed -e 's/^\.text//' -e 's/^\.data//' vgabios.s _vgabios_.s - $(AS86) _vgabios_.s -b vgabios.bin -u -w- -g -0 -j -O -l vgabios.txt - rm -f _vgabios_.s _vgabios_.c vgabios.s - mv vgabios.bin VGABIOS-lgpl-latest.bin - ./biossums VGABIOS-lgpl-latest.bin - ls -l VGABIOS-lgpl-latest.bin - -vgabios.debug.bin: vgabios.c vgabios.h vgafonts.h vgatables.h vbe.h vbe.c vbetables.h - $(GCC) -E -P vgabios.c $(VGABIOS_VERS) -DVBE -DDEBUG $(VGABIOS_DATE) _vgabios-debug_.c - $(BCC) -o vgabios-debug.s -C-c -D__i86__ -S -0 _vgabios-debug_.c - sed -e 's/^\.text//' -e 's/^\.data//' vgabios-debug.s _vgabios-debug_.s - $(AS86) _vgabios-debug_.s -b vgabios.debug.bin -u -w- -g -0 -j -O -l vgabios.debug.txt - rm -f _vgabios-debug_.s _vgabios-debug_.c vgabios-debug.s - mv vgabios.debug.bin VGABIOS-lgpl-latest.debug.bin - ./biossums VGABIOS-lgpl-latest.debug.bin - ls -l VGABIOS-lgpl-latest.debug.bin - -vgabios-cirrus.bin: vgabios.c vgabios.h vgafonts.h vgatables.h clext.c - $(GCC) -E -P vgabios.c $(VGABIOS_VERS) -DCIRRUS -DPCIBIOS $(VGABIOS_DATE) _vgabios-cirrus_.c - $(BCC) -o vgabios-cirrus.s -C-c -D__i86__ -S -0 _vgabios-cirrus_.c - sed -e 's/^\.text//' -e 's/^\.data//' vgabios-cirrus.s _vgabios-cirrus_.s - $(AS86) _vgabios-cirrus_.s -b vgabios-cirrus.bin -u -w- -g -0 -j -O -l vgabios.cirrus.txt - rm -f _vgabios-cirrus_.s _vgabios-cirrus_.c vgabios-cirrus.s - mv vgabios-cirrus.bin VGABIOS-lgpl-latest.cirrus.bin - ./biossums VGABIOS-lgpl-latest.cirrus.bin - ls -l VGABIOS-lgpl-latest.cirrus.bin - -vgabios-cirrus.debug.bin: vgabios.c vgabios.h vgafonts.h vgatables.h clext.c - $(GCC) -E -P vgabios.c $(VGABIOS_VERS) -DCIRRUS -DCIRRUS_DEBUG -DPCIBIOS $(VGABIOS_DATE) _vgabios-cirrus-debug_.c - $(BCC) -o vgabios-cirrus-debug.s -C-c -D__i86__ -S -0 _vgabios-cirrus-debug_.c - sed -e 's/^\.text//' -e 's/^\.data//' vgabios-cirrus-debug.s _vgabios-cirrus-debug_.s - $(AS86) _vgabios-cirrus-debug_.s -b vgabios.cirrus.debug.bin -u -w- -g -0 -j -O -l vgabios.cirrus.debug.txt - rm -f _vgabios-cirrus-debug_.s _vgabios-cirrus-debug_.c vgabios-cirrus-debug.s - mv vgabios.cirrus.debug.bin VGABIOS-lgpl-latest.cirrus.debug.bin - ./biossums
[Qemu-devel] [PATCH v3 4/4] more stdvga cleanups.
video.x is gone now. It was the only user of the vga bios_offset + bios_size logic. Zap it. Signed-off-by: Gerd Hoffmann kra...@redhat.com --- hw/mips_malta.c |2 +- hw/pc.c |2 +- hw/pc.h |3 +-- hw/ppc_newworld.c |2 +- hw/ppc_oldworld.c |2 +- hw/ppc_prep.c |2 +- hw/sun4u.c|2 +- hw/vga-pci.c | 42 -- hw/vga.c |2 -- hw/vga_int.h |2 -- 10 files changed, 15 insertions(+), 46 deletions(-) diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 8026071..6be8aa7 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -977,7 +977,7 @@ void mips_malta_init (ram_addr_t ram_size, } else if (vmsvga_enabled) { pci_vmsvga_init(pci_bus); } else if (std_vga_enabled) { -pci_vga_init(pci_bus, 0, 0); +pci_vga_init(pci_bus); } } diff --git a/hw/pc.c b/hw/pc.c index 69b13bf..0e44df8 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -993,7 +993,7 @@ void pc_vga_init(PCIBus *pci_bus) fprintf(stderr, %s: vmware_vga: no PCI bus\n, __FUNCTION__); } else if (std_vga_enabled) { if (pci_bus) { -pci_vga_init(pci_bus, 0, 0); +pci_vga_init(pci_bus); } else { isa_vga_init(); } diff --git a/hw/pc.h b/hw/pc.h index 63b0249..6852790 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -154,8 +154,7 @@ enum vga_retrace_method { extern enum vga_retrace_method vga_retrace_method; int isa_vga_init(void); -int pci_vga_init(PCIBus *bus, - unsigned long vga_bios_offset, int vga_bios_size); +int pci_vga_init(PCIBus *bus); int isa_vga_mm_init(target_phys_addr_t vram_base, target_phys_addr_t ctrl_base, int it_shift); diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index 4369337..305b2d4 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -316,7 +316,7 @@ static void ppc_core99_init (ram_addr_t ram_size, machine_arch = ARCH_MAC99; } /* init basic PC hardware */ -pci_vga_init(pci_bus, 0, 0); +pci_vga_init(pci_bus); escc_mem_index = escc_init(0x80013000, pic[0x25], pic[0x24], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index a2f9ddf..5efc93d 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -227,7 +227,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, } pic = heathrow_pic_init(pic_mem_index, 1, heathrow_irqs); pci_bus = pci_grackle_init(0xfec0, pic); -pci_vga_init(pci_bus, 0, 0); +pci_vga_init(pci_bus); escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index a6915f7..b1f9cc7 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -694,7 +694,7 @@ static void ppc_prep_init (ram_addr_t ram_size, cpu_register_physical_memory(0x8000, 0x0080, PPC_io_memory); /* init basic PC hardware */ -pci_vga_init(pci_bus, 0, 0); +pci_vga_init(pci_bus); //openpic = openpic_init(0x, 0xF000, 1); //pit = pit_init(0x40, i8259[0]); rtc_init(2000, NULL); diff --git a/hw/sun4u.c b/hw/sun4u.c index 45a46d6..5292ac6 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -767,7 +767,7 @@ static void sun4uv_init(ram_addr_t RAM_size, pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, irq, pci_bus2, pci_bus3); isa_mem_base = APB_PCI_IO_BASE; -pci_vga_init(pci_bus, 0, 0); +pci_vga_init(pci_bus); // XXX Should be pci_bus3 pci_ebus_init(pci_bus, -1); diff --git a/hw/vga-pci.c b/hw/vga-pci.c index eef0e3c..b09789c 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -52,14 +52,11 @@ static void vga_map(PCIDevice *pci_dev, int region_num, { PCIVGAState *d = (PCIVGAState *)pci_dev; VGACommonState *s = d-vga; -if (region_num == PCI_ROM_SLOT) { -cpu_register_physical_memory(addr, s-bios_size, s-bios_offset); -} else { -cpu_register_physical_memory(addr, s-vram_size, s-vram_offset); -s-map_addr = addr; -s-map_end = addr + s-vram_size; -vga_dirty_log_start(s); -} + +cpu_register_physical_memory(addr, s-vram_size, s-vram_offset); +s-map_addr = addr; +s-map_end = addr + s-vram_size; +vga_dirty_log_start(s); } static void pci_vga_write_config(PCIDevice *d, @@ -95,31 +92,12 @@ static int pci_vga_initfn(PCIDevice *dev) pci_register_bar(d-dev, 0, VGA_RAM_SIZE, PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map); - if (s-bios_size) { -unsigned int bios_total_size; -/* must be a power of two */ -bios_total_size = 1; -while (bios_total_size s-bios_size) -bios_total_size = 1; -pci_register_bar(d-dev, PCI_ROM_SLOT, bios_total_size, -
[Qemu-devel] [vgabios patch v2 00/11] vgabios update
Hi, This patch series updates the vgabios, the patches are intended for the vgabios.git tree @ git.qemu.org The first five patches are taken from the vgabios cvs and update the vgabios.git tree @ qemu.org to vgabios release 0.6c. As this update depends on a newer bochs API it fully works on qemu 0.13 and master only. When using this vgabios version on qemu 0.12 vesa bios support will break. The last six patches cleanup the build system a bit, add a proper PCIROM header so seabios will happily load the roms from the PCI option rom bar and add vgabios binaries for all current and the upcoming qxl vga device. Changes in v2: * added proper signed-off to my patches. please pull, Gerd The following changes since commit 6e62666cfc19e7fd45dd0d7c3ad62fd8d0b5f67a: - added DPMS support to cirrus vgabios (patch from Gleb Natapov) (2008-12-14 08:29:48 +) are available in the git repository at: git://anongit.freedesktop.org/~kraxel/vgabios pcibios.2 Gerd Hoffmann (6): Makefile cleanup Add defines for PCI IDs. Add qemu stdvga pci bios update pci_get_lfb_addr for vmware vga Add qemu vmware vga pci bios Add qemu qxl vga pci bios Volker Ruppert (5): - use VBE LFB address from PCI base address if present (rewrite of the cirrus specific function in main vgabios code) - removed unnecessary spaces - added support for a lot more non-standard VBE modes (e.g. widescreen modes) - requires latest Bochs VBE code (16 MB video memory, VBE_DISPI_ID5, VRAM size in 64k pages stored in VBE register) - check if VBE mode is supported with current VRAM size - preparing for release 0.6c - biosfn_write_teletype: fixed attribute when scrolling in text mode - updates for release 0.6c ChangeLog | 47 + Makefile| 102 --- README |7 clext.c | 51 +-- vbe.c | 94 --- vbe.h | 70 +++-- vbetables-gen.c | 43 +-- vgabios.c | 74 ++- 8 files changed, 314 insertions(+), 174 deletions(-)
[Qemu-devel] [PATCH v3 3/4] switch vmware_vga to pci vgabios
Signed-off-by: Gerd Hoffmann kra...@redhat.com --- hw/vmware_vga.c |7 +-- 1 files changed, 1 insertions(+), 6 deletions(-) diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 3d25c14..9337fdb 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -114,14 +114,12 @@ struct pci_vmsvga_state_s { # define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT # define SVGA_IO_MUL 1 # define SVGA_FIFO_SIZE0x1 -# define SVGA_MEM_BASE 0xe000 # define SVGA_PCI_DEVICE_IDPCI_DEVICE_ID_VMWARE_SVGA2 #else # define SVGA_ID SVGA_ID_1 # define SVGA_IO_BASE SVGA_LEGACY_BASE_PORT # define SVGA_IO_MUL 4 # define SVGA_FIFO_SIZE0x1 -# define SVGA_MEM_BASE 0xe000 # define SVGA_PCI_DEVICE_IDPCI_DEVICE_ID_VMWARE_SVGA #endif @@ -1219,10 +1217,6 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size) vga_init(s-vga); vmstate_register(NULL, 0, vmstate_vga_common, s-vga); -vga_init_vbe(s-vga); - -rom_add_vga(VGABIOS_FILENAME); - vmsvga_reset(s); } @@ -1320,6 +1314,7 @@ static PCIDeviceInfo vmsvga_info = { .qdev.size= sizeof(struct pci_vmsvga_state_s), .qdev.vmsd= vmstate_vmware_vga, .init = pci_vmsvga_initfn, +.romfile = vgabios-vmware.bin, }; static void vmsvga_register(void) -- 1.7.1
[Qemu-devel] [PATCH v3 0/4] use new vgabios.
Hi, This patch series will put the new vgabios into use for stdvga and vmware_vga. The vgabios patches this patch series depends on have just been posted to the list. For obvious reasons it depends on the new vgabios binaries being present, i.e. vgabios patches being committed to vgabios.git, subtree being updated and vgabios binaries being recompiled + committed to qemu.git. Changes in v3: * rebase to master. * added proper signed-off. Changes in v2: * rebase to master, resolve video.x removal conflict. * add a new clean up patch, removes bits which where used by video.x code only. please pull, Gerd The following changes since commit 7d72e76228351d18a856f1e4f5365b59d3205dc3: intel-hda: documentation update (2010-11-02 00:41:04 +0300) are available in the git repository at: git://anongit.freedesktop.org/spice/qemu vgabios.3 Gerd Hoffmann (4): Add new vgabios binaries to blobs list. switch stdvga to pci vgabios switch vmware_vga to pci vgabios more stdvga cleanups. Makefile |5 +++-- hw/mips_malta.c |2 +- hw/pc.c |2 +- hw/pc.h |3 +-- hw/ppc_newworld.c |2 +- hw/ppc_oldworld.c |2 +- hw/ppc_prep.c |2 +- hw/sun4u.c|2 +- hw/vga-pci.c | 43 --- hw/vga.c |2 -- hw/vga_int.h |2 -- hw/vmware_vga.c |7 +-- 12 files changed, 19 insertions(+), 55 deletions(-)
[Qemu-devel] [vgabios patch v2 08/11] Add qemu stdvga pci bios
Add PCI vgabios for the qemu standard vga (1234:). Name it vgabios-stdvga.bin. Signed-off-by: Gerd Hoffmann kra...@redhat.com --- Makefile | 10 +- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/Makefile b/Makefile index d440b93..58f064e 100644 --- a/Makefile +++ b/Makefile @@ -14,12 +14,14 @@ RELVERS = `pwd | sed s-.*/-- | sed s/vgabios// | sed s/-//` VGABIOS_DATE = -DVGABIOS_DATE=\$(RELDATE)\ -all: bios cirrus-bios +all: bios cirrus-bios stdvga-bios bios: vgabios.bin vgabios.debug.bin cirrus-bios: vgabios-cirrus.bin vgabios-cirrus.debug.bin +stdvga-bios: vgabios-stdvga.bin vgabios-stdvga.debug.bin + clean: /bin/rm -f biossums vbetables-gen vbetables.h *.o *.s *.ld86 \ temp.awk.* vgabios*.orig _vgabios_* _vgabios-debug_* core vgabios*.bin vgabios*.txt $(RELEASE).bin *.bak @@ -35,18 +37,24 @@ vgabios.bin : VGAFLAGS := -DVBE -DPCI_VID=0x1234 vgabios.debug.bin: VGAFLAGS := -DVBE -DPCI_VID=0x1234 -DDEBUG vgabios-cirrus.bin : VGAFLAGS := -DCIRRUS -DPCIBIOS vgabios-cirrus.debug.bin : VGAFLAGS := -DCIRRUS -DPCIBIOS -DCIRRUS_DEBUG +vgabios-stdvga.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x1234 -DPCI_DID=0x +vgabios-stdvga.debug.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x1234 -DPCI_DID=0x -DDEBUG # dist names vgabios.bin : DISTNAME := VGABIOS-lgpl-latest.bin vgabios.debug.bin: DISTNAME := VGABIOS-lgpl-latest.debug.bin vgabios-cirrus.bin : DISTNAME := VGABIOS-lgpl-latest.cirrus.bin vgabios-cirrus.debug.bin : DISTNAME := VGABIOS-lgpl-latest.cirrus.debug.bin +vgabios-stdvga.bin : DISTNAME := VGABIOS-lgpl-latest.stdvga.bin +vgabios-stdvga.debug.bin : DISTNAME := VGABIOS-lgpl-latest.stdvga.debug.bin # dependencies vgabios.bin : $(VGA_FILES) $(VBE_FILES) biossums vgabios.debug.bin: $(VGA_FILES) $(VBE_FILES) biossums vgabios-cirrus.bin : $(VGA_FILES) clext.c biossums vgabios-cirrus.debug.bin : $(VGA_FILES) clext.c biossums +vgabios-stdvga.bin : $(VGA_FILES) $(VBE_FILES) biossums +vgabios-stdvga.debug.bin : $(VGA_FILES) $(VBE_FILES) biossums # build rule %.bin: -- 1.7.1
[Qemu-devel] [PATCH v3 2/4] switch stdvga to pci vgabios
Make stdvga provide the new vgabios binary (with pcibios support) using the PCI option rom bar. Seabios will happily load it from there. The new vga bios will also lookup the framebuffer address in pci config space, so the magic bochs lfb @ 0xe000 is not needed any more - zap it. Without the patch: # dmesg | grep framebuffer vesafb: framebuffer at 0xe000, mapped to 0xf7e8, using 1875k, total 8192k # lspci -vs2 00:02.0 VGA compatible controller: Technical Corp. Device (prog-if 00 [VGA controller]) Subsystem: Qumranet, Inc. Device 1100 Physical Slot: 2 Flags: fast devsel Memory at f000 (32-bit, prefetchable) [size=8M] Expansion ROM at unassigned [disabled] With patch applied: # dmesg | grep framebuffer vesafb: framebuffer at 0xf000, mapped to 0xf7e8, using 1875k, total 8192k # lspci -vs2 00:02.0 VGA compatible controller: Technical Corp. Device (prog-if 00 [VGA controller]) Subsystem: Qumranet, Inc. Device 1100 Physical Slot: 2 Flags: fast devsel Memory at f000 (32-bit, prefetchable) [size=8M] Expansion ROM at f080 [disabled] [size=64K] cheers, Gerd Signed-off-by: Gerd Hoffmann kra...@redhat.com --- hw/vga-pci.c |7 +++ 1 files changed, 3 insertions(+), 4 deletions(-) diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 2315f70..eef0e3c 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -103,11 +103,10 @@ static int pci_vga_initfn(PCIDevice *dev) bios_total_size = 1; pci_register_bar(d-dev, PCI_ROM_SLOT, bios_total_size, PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map); + } else { + if (dev-romfile == NULL) + dev-romfile = qemu_strdup(vgabios-stdvga.bin); } - -vga_init_vbe(s); - /* ROM BIOS */ - rom_add_vga(VGABIOS_FILENAME); return 0; } -- 1.7.1
Re: [Qemu-devel] [PATCH 0/3] v4 Decouple block device removal from device removal
* Michael S. Tsirkin m...@redhat.com [2010-11-03 02:22]: On Tue, Nov 02, 2010 at 03:23:38PM -0500, Ryan Harper wrote: * Michael S. Tsirkin m...@redhat.com [2010-11-02 14:18]: On Tue, Nov 02, 2010 at 02:01:08PM -0500, Ryan Harper wrote: I like the idea of disconnect; if part of the device_del method was to invoke a disconnect method, we could implement that for block, net, etc; I'd think we'd want to send the notification, then disconnect. Struggling with whether it's worth having some reasonable timeout between notification and disconnect. The problem with this is that it has no analog in real world. In real world, you can send some notifications to the guest, and you can remove the card. Tying them together is what created the problem in the first place. Timeouts can be implemented by management, maybe with a nice dialog being shown to the user. Very true. I'm fine with forcing a disconnect during the removal path prior to notification. Do we want a new disconnect method at the device level (pci)? or just use the existing removal callback and call that during the initial hotremov event? Not sure what you mean by that, but I don't see a device doing anything differently wrt surprise or ordered removal. So probably the existing callback should do. I don't think we need to talk about disconnect: since we decided we are emulating device removal, let's call it just that. Because current the removal process depends on the guest actually responding. What I'm suggesting is that, in Marcus's term, and what drive_unplug() implements, is to disconnect the host block device from the guest device to prevent any further access to it in the case the guest doesn't respond to the removal request made via ACPI. Very specifically, what we're suggesting instead of the drive_unplug() command so to complete the device removal operation without waiting for the guest to respond; that's what's going to happen if we invoke the response callback; it will appear as if the guest responded whether it did or not. What I was suggesting above was to instead of calling the callback for handing the guest response was to add a device function called disconnect which would remove any association of host resources from guest resources before we notified the guest. Thinking about it again I'm not sure this is useful, but if we're going to remove the device without the guests knowledge, I'm not sure how useful sending the removal requests via ACPI is in the first place. My feeling is that I'd like to have explicit control over the disconnect from host resources separate from the device removal *if* we're going to retain the guest notification. If we don't care to notify the guest, then we can just do device removal without notifying the guest and be done with it. I imagine management would typically want to do this: 1. notify guest 2. wait a bit 3. remove device Yes; but this argues for (1) being a separate command from (3) Yes. Long term I think we will want a way to do that. unless we require (3) to include (1) and (2) in the qemu implementation. Currently we implement: 1. device_del (attempt to remove device) 2. notify guest 3. if guest responds, remove device 4. disconnect host resource from device on destruction With my drive_unplug patch we do: 1. disconnect host resource from device This is what drive_unplug does, right? Correct. 2. device_del (attempt to remove device) 3. notify guest 4. if guest responds, remove device I think we're suggesting to instead do (if we keep disconnect as part of device_del) 1. device_del (attemp to remove device) 2. notify guest 3. invoke device destruction callback resulting in disconnect host resource from device 4. if guest responds, invoke device destruction path a second time. By response you mean eject? No, this is not what I was suggesting. I was really suggesting that your patch is fine :) Sorry about confusion. I don't mean eject; I mean responding to the ACPI event by writing a response to the PCI chipset which QEMU then in turn will invoke the qdev_unplug() path which ultimately kills the device and the Drive and BlockState objects. I was also saying that from what I hear, the pci express support will at some point need interfaces to - notify guest about device removal/addition - get eject from guest - remove device without talking to guest - add device without talking to guest - suppress device deletion on eject All this can be generic and can work through express configuration mechanisms or through acpi for pci. But this is
[Qemu-devel] [Bug 626781] Re: Live migration: bandwitdth calculation and rate limiting not working
Hi, I issued a bug report (626781) months ago. Any news on it? By the way, I think it is really a bug other than a question. Regards, eslay ** Changed in: qemu Status: New = Invalid ** Converted to question: https://answers.launchpad.net/qemu/+question/132364 -- Live migration: bandwitdth calculation and rate limiting not working https://bugs.launchpad.net/bugs/626781 You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. Status in QEMU: Invalid Bug description: I am using QEMU 0.12.5 to perform live migration between 2 Linux hosts. One Linux Host has 6 cores and 24G RAM, the other has 2 cores and 16G RAM. For each host, I have one Ethernet interface for NFS storage, another interface for live migration and a third interface for the VM to communicate to outside network. Each interface has 1G bandwidth. It is observed that programs like below (which generates dirty pages very quickly) will hang the live migration: #include stdio.h #include stdlib.h main() { unsigned char *array; long int i,j,k; unsigned char c; long int loop=0; array=malloc(1024*1024*1024); while(1) { for(i=0;i1024;i++) { c=0; for(j=0;j1024;j++) { c++; for(k=0;k1024;k++) { array[i*1024*1024+j*1024+k]=c; } } } loop++; if(loop%256==0) printf(%ld\n,loop); } } It is observed that the traffic down time (measured by ping -f from a 3rd host) has dependency on RAM size of the virtual machine: RAM SizeTraffic Down Time Total Migration Time 1024M 0.5s 33s 2048M 0.7s 34s 4096M 2.7s 39s 8912M 5.3s 45s 16384M 7.2s 61s Using the command migrate_set_downtime in QEMU console won't improve the problem. Function ram_save_live() in vl.c shows that live migration has three stages: Stage 1 is some preparation work. Stage 2 is to transfer VM RAM to target host and keep the VM alive at source host. In Stage 2, the realtime migration bandwidth is calculated (Line 3099~3117 in vl.c). At the end of Stage 2 (Line 3130), the expected left time of RAM transmission is calculated (Left RAM Size / Calculated Bandwidth). If the expected left time is less than the max migration down time, Stage 2 is ended and Stage 3 starts. Stage 3 is to stop the VM at the source host, transfer left RAM at full speed, and then start the VM at the target host. The period of Stage 3 is believed to be the period when the outside lost connection to the VM. This is how live migration is supposed to work. There is a parameter max_throttle in migration.c, which sets the max allowed bandwidth for rate limiting. The default value of this parameter is 32Mb/s (if not using command migrate_set_speed to change the value). But it does not matter because the rate limiting faction does not work anyway. There is another parameter max_downtime in migration.c, which sets the max allowed traffic down time for live migration.By default the value is set to 30ms (if not using command migrate_set_downtime to change the value). This value to way too small, so if using the source code above, live migration will hang. Stage 2 will never end since the expected left time would never be less than 30ms. However, changing the parameter to something like 1000ms will solve the hanging problem. After changing the default value of max_downtime, the long traffic down time problem still exits. The following faults are found: a) The bandwidth calculation in ram_save_live() (the first attachment) is wrong. The bandwidth should equal to data transferred divided by the period of transmission time. The period of transmission time should be the interval between two consecutive calls of function ram_save_live(), which is usually 100ms (There should be a timer interrupt to control this). However, what the code use is the execution time of the while loop between Line 3102 and 3109. That is usually 2~5ms! This will yield to unreasonable large bandwidth (6~12Gb/s), and in turn will make the estimated execution time of Stage 3 inaccurate. For example, if the estimated execution time of Stage 3 is 900ms, the actual execution time can be like10s! b) The rate limiting function (qemu_file_rate_limit() which calls buffered_rate_limit() in buffered_file.c) does not work at all. No matter what parameters are set, the rate limiting function behaves the same: in Stage 2, in most time the migration bandwidth is ~400 Mb/s. When a certain condition is fulfilled (I don't know exactly what condition but definitely not the number of iteration times), QEMU will read the VM RAM at full speed and throw everything to the Ethernet link. This stalls the CPU and
Re: [Qemu-devel] MSI broken?
On Wed, Nov 03, 2010 at 12:03:15PM +0100, Gerd Hoffmann wrote: Hi, What is the status if the recently merged MSI support? I'm trying to use it to add msi support to the intel-hda driver (current wip patch attached). Everything works fine up to the point where it comes to delivering the interrupt to the guest. msi_notify pretends to signal the guest: msi_notify:243 intel-hda:30 notify vector 0x0 address: 0xfee01008 data: 0x4151 The guest never ever receives this interrupt though: [r...@localhost ~]# grep hda /proc/interrupts 43: 0 PCI-MSI-edge hda_intel Ideas anyone? Let's track it down futher. Were acpi_mem_writel() and apic_send_msi() in hw/apic.c called or not? -- yamahata
Re: [Qemu-devel] MSI broken?
On 11/03/10 13:34, Isaku Yamahata wrote: On Wed, Nov 03, 2010 at 12:03:15PM +0100, Gerd Hoffmann wrote: Hi, What is the status if the recently merged MSI support? I'm trying to use it to add msi support to the intel-hda driver (current wip patch attached). Everything works fine up to the point where it comes to delivering the interrupt to the guest. msi_notify pretends to signal the guest: msi_notify:243 intel-hda:30 notify vector 0x0 address: 0xfee01008 data: 0x4151 The guest never ever receives this interrupt though: [r...@localhost ~]# grep hda /proc/interrupts 43: 0 PCI-MSI-edge hda_intel Ideas anyone? Let's track it down futher. Were acpi_mem_writel() and apic_send_msi() in hw/apic.c called or not? No such function in my tree (savannah/master). Looks like some bits needed for msi are not merged yet? cheers, Gerd
Re: [Qemu-devel] MSI broken?
On Wed, Nov 03, 2010 at 01:40:59PM +0100, Gerd Hoffmann wrote: On 11/03/10 13:34, Isaku Yamahata wrote: On Wed, Nov 03, 2010 at 12:03:15PM +0100, Gerd Hoffmann wrote: Hi, What is the status if the recently merged MSI support? I'm trying to use it to add msi support to the intel-hda driver (current wip patch attached). Everything works fine up to the point where it comes to delivering the interrupt to the guest. msi_notify pretends to signal the guest: msi_notify:243 intel-hda:30 notify vector 0x0 address: 0xfee01008 data: 0x4151 The guest never ever receives this interrupt though: [r...@localhost ~]# grep hda /proc/interrupts 43: 0 PCI-MSI-edge hda_intel Ideas anyone? Let's track it down futher. Were acpi_mem_writel() and apic_send_msi() in hw/apic.c called or not? No such function in my tree (savannah/master). Looks like some bits needed for msi are not merged yet? Sorry typo. s/acpi/apic/. I'm looking at 7d72e76228351d18a856f1e4f5365b59d3205dc3 of git://git.savannah.nongnu.org/qemu.git cheers, Gerd -- yamahata
Re: [Qemu-devel] [PATCHv2 4/8] Store IDE bus id in IDEBus structure for easy access.
Here's a generic answer to the question which of the device's buses is this? int qbus_index(BusState *bus) { BusState *b; int i, index; index = -1; i = 0; QLIST_FOREACH(b, bus-parent-child_bus, sibling) { if (b == bus) { index = i; } i++; } assert(0 = index index i); return i - 1 - index; } The bus created first has index 0. Note that the child_bus holds the children in reverse creation order, and we can't traverse it backwards. Same problem also visible with makes info qtree: dev: piix3-ide, id [...] bus: ide.1 type IDE bus: ide.0 type IDE
Re: [Qemu-devel] [PATCHv2 4/8] Store IDE bus id in IDEBus structure for easy access.
On Wed, Nov 03, 2010 at 02:39:52PM +0100, Markus Armbruster wrote: Here's a generic answer to the question which of the device's buses is this? int qbus_index(BusState *bus) { BusState *b; int i, index; index = -1; i = 0; QLIST_FOREACH(b, bus-parent-child_bus, sibling) { if (b == bus) { index = i; } i++; } assert(0 = index index i); return i - 1 - index; } The bus created first has index 0. Note that the child_bus holds the children in reverse creation order, and we can't traverse it backwards. Same problem also visible with makes info qtree: dev: piix3-ide, id [...] bus: ide.1 type IDE bus: ide.0 type IDE Isn't this too implementation dependant? Are you against adding bus_id to IDEBus? And will it work with ISA? I do not think IDEBus is added to bus-parent-child_bus in case of ISA otherwise why both IDEBuses have same name in isapc. Currently I have following patch queued. It should fix isapc case too. Fix isapc IDE bus creation Currently we create two ide buses with the same name, so it is impossible to use -device ide-drive,bus= to address all possible disks in the isapc machine. Fix that by giving different names to different ide buses. Also store IDE bus id in IDEBus structure for easy access. diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index ff80dd5..b2cbdbc 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -257,8 +257,8 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev) pci_conf[PCI_INTERRUPT_PIN] = 0x01; // interrupt on pin 1 irq = qemu_allocate_irqs(cmd646_set_irq, d, 2); -ide_bus_new(d-bus[0], d-dev.qdev); -ide_bus_new(d-bus[1], d-dev.qdev); +ide_bus_new(d-bus[0], d-dev.qdev, 0); +ide_bus_new(d-bus[1], d-dev.qdev, 1); ide_init2(d-bus[0], irq[0]); ide_init2(d-bus[1], irq[1]); diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 4165543..bde2664 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -448,6 +448,7 @@ struct IDEBus { IDEDevice *slave; BMDMAState *bmdma; IDEState ifs[2]; +uint8_t bus_id; uint8_t unit; uint8_t cmd; qemu_irq irq; @@ -564,7 +565,7 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, void ide_init_ioport(IDEBus *bus, int iobase, int iobase2); /* hw/ide/qdev.c */ -void ide_bus_new(IDEBus *idebus, DeviceState *dev); +void ide_bus_new(IDEBus *idebus, DeviceState *dev, uint8_t bus_id); IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive); #endif /* HW_IDE_INTERNAL_H */ diff --git a/hw/ide/isa.c b/hw/ide/isa.c index 9b94495..b000ab8 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -66,8 +66,9 @@ static const VMStateDescription vmstate_ide_isa = { static int isa_ide_initfn(ISADevice *dev) { ISAIDEState *s = DO_UPCAST(ISAIDEState, dev, dev); +static uint8_t bus_id = 0; -ide_bus_new(s-bus, s-dev.qdev); +ide_bus_new(s-bus, s-dev.qdev, bus_id++); ide_init_ioport(s-bus, s-iobase, s-iobase2); isa_init_irq(dev, s-irq, s-isairq); isa_init_ioport_range(dev, s-iobase, 8); diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 6206201..e56777f 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -129,8 +129,8 @@ static int pci_piix_ide_initfn(PCIIDEState *d) vmstate_register(d-dev.qdev, 0, vmstate_ide_pci, d); -ide_bus_new(d-bus[0], d-dev.qdev); -ide_bus_new(d-bus[1], d-dev.qdev); +ide_bus_new(d-bus[0], d-dev.qdev, 0); +ide_bus_new(d-bus[1], d-dev.qdev, 1); ide_init_ioport(d-bus[0], 0x1f0, 0x3f6); ide_init_ioport(d-bus[1], 0x170, 0x376); diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 336ffe1..220729e 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -29,9 +29,13 @@ static struct BusInfo ide_bus_info = { .size = sizeof(IDEBus), }; -void ide_bus_new(IDEBus *idebus, DeviceState *dev) +void ide_bus_new(IDEBus *idebus, DeviceState *dev, uint8_t bus_id) { -qbus_create_inplace(idebus-qbus, ide_bus_info, dev, NULL); +char name[10]; + +snprintf(name, sizeof(name), ide.%d, bus_id); +qbus_create_inplace(idebus-qbus, ide_bus_info, dev, name); +idebus-bus_id = bus_id; } static int ide_qdev_init(DeviceState *qdev, DeviceInfo *base) diff --git a/hw/ide/via.c b/hw/ide/via.c index b2c7cad..cc48b2b 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -158,8 +158,8 @@ static int vt82c686b_ide_initfn(PCIDevice *dev) vmstate_register(dev-qdev, 0, vmstate_ide_pci, d); -ide_bus_new(d-bus[0], d-dev.qdev); -ide_bus_new(d-bus[1], d-dev.qdev); +ide_bus_new(d-bus[0], d-dev.qdev, 0); +ide_bus_new(d-bus[1], d-dev.qdev, 1); ide_init2(d-bus[0], isa_reserve_irq(14)); ide_init2(d-bus[1], isa_reserve_irq(15)); ide_init_ioport(d-bus[0], 0x1f0, 0x3f6); diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 3d07ce5..cec6c9b 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -163,7 +163,7 @@ static void
[Qemu-devel] [PATCH] Delete IOHandlers after potentially running them
Since commit 4bed9837309e58d208183f81d8344996744292cf an .fd_read() handler that deletes its IOHandler is exposed to .fd_write() being called on the deleted IOHandler. This patch fixes deletion so that .fd_read() and .fd_write() are never called on an IOHandler that is marked for deletion. Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- vl.c | 15 --- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/vl.c b/vl.c index 7038952..6f56123 100644 --- a/vl.c +++ b/vl.c @@ -1252,17 +1252,18 @@ void main_loop_wait(int nonblocking) IOHandlerRecord *pioh; QLIST_FOREACH_SAFE(ioh, io_handlers, next, pioh) { -if (ioh-deleted) { -QLIST_REMOVE(ioh, next); -qemu_free(ioh); -continue; -} -if (ioh-fd_read FD_ISSET(ioh-fd, rfds)) { +if (!ioh-deleted ioh-fd_read FD_ISSET(ioh-fd, rfds)) { ioh-fd_read(ioh-opaque); } -if (ioh-fd_write FD_ISSET(ioh-fd, wfds)) { +if (!ioh-deleted ioh-fd_write FD_ISSET(ioh-fd, wfds)) { ioh-fd_write(ioh-opaque); } + +/* Do this last in case read/write handlers marked it for deletion */ +if (ioh-deleted) { +QLIST_REMOVE(ioh, next); +qemu_free(ioh); +} } } -- 1.7.2.3
[Qemu-devel] Re: [RFC][PATCH 1/3] Linux/Guest unmapped page cache control
On Fri, 29 Oct 2010, Balbir Singh wrote: A lot of the code is borrowed from zone_reclaim_mode logic for __zone_reclaim(). One might argue that the with ballooning and KSM this feature is not very useful, but even with ballooning, Interesting use of zone reclaim. I am having a difficult time reviewing the patch since you move and modify functions at the same time. Could you separate that out a bit? +#define UNMAPPED_PAGE_RATIO 16 Maybe come up with a scheme that allows better configuration of the mininum? I think in some setting we may want an absolute limit and in other a fraction of something (total zone size or working set?) +bool should_balance_unmapped_pages(struct zone *zone) +{ + if (unmapped_page_control + (zone_unmapped_file_pages(zone) + UNMAPPED_PAGE_RATIO * zone-min_unmapped_pages)) + return true; + return false; +}
[Qemu-devel] Re: [PATCH] Delete IOHandlers after potentially running them
Stefan Hajnoczi stefa...@linux.vnet.ibm.com wrote: Since commit 4bed9837309e58d208183f81d8344996744292cf an .fd_read() handler that deletes its IOHandler is exposed to .fd_write() being called on the deleted IOHandler. This patch fixes deletion so that .fd_read() and .fd_write() are never called on an IOHandler that is marked for deletion. Reviewed by: Juan Quintela quint...@redhat.com But once here, what (appart from networking) reads and writes to the same fd? And that removes the IOHandler on read while there are write stuff pending? Later, Juan. Signed-off-by: Stefan Hajnoczi stefa...@linux.vnet.ibm.com --- vl.c | 15 --- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/vl.c b/vl.c index 7038952..6f56123 100644 --- a/vl.c +++ b/vl.c @@ -1252,17 +1252,18 @@ void main_loop_wait(int nonblocking) IOHandlerRecord *pioh; QLIST_FOREACH_SAFE(ioh, io_handlers, next, pioh) { -if (ioh-deleted) { -QLIST_REMOVE(ioh, next); -qemu_free(ioh); -continue; -} -if (ioh-fd_read FD_ISSET(ioh-fd, rfds)) { +if (!ioh-deleted ioh-fd_read FD_ISSET(ioh-fd, rfds)) { ioh-fd_read(ioh-opaque); } -if (ioh-fd_write FD_ISSET(ioh-fd, wfds)) { +if (!ioh-deleted ioh-fd_write FD_ISSET(ioh-fd, wfds)) { ioh-fd_write(ioh-opaque); } + +/* Do this last in case read/write handlers marked it for deletion */ +if (ioh-deleted) { +QLIST_REMOVE(ioh, next); +qemu_free(ioh); +} } }
Re: [Qemu-devel] Re: [PATCH] Delete IOHandlers after potentially running them
On Wed, Nov 3, 2010 at 2:39 PM, Juan Quintela quint...@redhat.com wrote: Stefan Hajnoczi stefa...@linux.vnet.ibm.com wrote: Since commit 4bed9837309e58d208183f81d8344996744292cf an .fd_read() handler that deletes its IOHandler is exposed to .fd_write() being called on the deleted IOHandler. This patch fixes deletion so that .fd_read() and .fd_write() are never called on an IOHandler that is marked for deletion. Reviewed by: Juan Quintela quint...@redhat.com But once here, what (appart from networking) reads and writes to the same fd? And that removes the IOHandler on read while there are write stuff pending? VNC Stefan
Re: [Qemu-devel] [PATCH] Delete IOHandlers after potentially running them
On 11/03/2010 09:29 AM, Stefan Hajnoczi wrote: Since commit 4bed9837309e58d208183f81d8344996744292cf an .fd_read() handler that deletes its IOHandler is exposed to .fd_write() being called on the deleted IOHandler. This patch fixes deletion so that .fd_read() and .fd_write() are never called on an IOHandler that is marked for deletion. Signed-off-by: Stefan Hajnoczistefa...@linux.vnet.ibm.com --- vl.c | 15 --- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/vl.c b/vl.c index 7038952..6f56123 100644 --- a/vl.c +++ b/vl.c @@ -1252,17 +1252,18 @@ void main_loop_wait(int nonblocking) IOHandlerRecord *pioh; QLIST_FOREACH_SAFE(ioh,io_handlers, next, pioh) { -if (ioh-deleted) { -QLIST_REMOVE(ioh, next); -qemu_free(ioh); -continue; -} -if (ioh-fd_read FD_ISSET(ioh-fd,rfds)) { +if (!ioh-deleted ioh-fd_read FD_ISSET(ioh-fd,rfds)) { ioh-fd_read(ioh-opaque); } -if (ioh-fd_write FD_ISSET(ioh-fd,wfds)) { +if (!ioh-deleted ioh-fd_write FD_ISSET(ioh-fd,wfds)) { ioh-fd_write(ioh-opaque); } + +/* Do this last in case read/write handlers marked it for deletion */ +if (ioh-deleted) { +QLIST_REMOVE(ioh, next); +qemu_free(ioh); +} } This isn't enough. If you end up with a handler deleting the next pointer and the current pointer, you'll end up running off the end of the list. The original commit should be reverted. Regards, Anthony Liguori }
Re: [Qemu-devel] [PATCH] Delete IOHandlers after potentially running them
On 11/03/2010 09:29 AM, Stefan Hajnoczi wrote: Since commit 4bed9837309e58d208183f81d8344996744292cf an .fd_read() handler that deletes its IOHandler is exposed to .fd_write() being called on the deleted IOHandler. This patch fixes deletion so that .fd_read() and .fd_write() are never called on an IOHandler that is marked for deletion. Signed-off-by: Stefan Hajnoczistefa...@linux.vnet.ibm.com --- vl.c | 15 --- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/vl.c b/vl.c index 7038952..6f56123 100644 --- a/vl.c +++ b/vl.c @@ -1252,17 +1252,18 @@ void main_loop_wait(int nonblocking) IOHandlerRecord *pioh; QLIST_FOREACH_SAFE(ioh,io_handlers, next, pioh) { -if (ioh-deleted) { -QLIST_REMOVE(ioh, next); -qemu_free(ioh); -continue; -} -if (ioh-fd_read FD_ISSET(ioh-fd,rfds)) { +if (!ioh-deleted ioh-fd_read FD_ISSET(ioh-fd,rfds)) { ioh-fd_read(ioh-opaque); } -if (ioh-fd_write FD_ISSET(ioh-fd,wfds)) { +if (!ioh-deleted ioh-fd_write FD_ISSET(ioh-fd,wfds)) { ioh-fd_write(ioh-opaque); } + +/* Do this last in case read/write handlers marked it for deletion */ +if (ioh-deleted) { +QLIST_REMOVE(ioh, next); +qemu_free(ioh); +} Actually, on second thought, I think this is correct although I still think reverting is a better strategy. Regards, Anthony Liguori } }
[Qemu-devel] Re: [PATCH] Delete IOHandlers after potentially running them
Anthony Liguori anth...@codemonkey.ws wrote: On 11/03/2010 09:29 AM, Stefan Hajnoczi wrote: Since commit 4bed9837309e58d208183f81d8344996744292cf an .fd_read() handler that deletes its IOHandler is exposed to .fd_write() being called on the deleted IOHandler. This patch fixes deletion so that .fd_read() and .fd_write() are never called on an IOHandler that is marked for deletion. Signed-off-by: Stefan Hajnoczistefa...@linux.vnet.ibm.com --- vl.c | 15 --- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/vl.c b/vl.c index 7038952..6f56123 100644 --- a/vl.c +++ b/vl.c @@ -1252,17 +1252,18 @@ void main_loop_wait(int nonblocking) IOHandlerRecord *pioh; QLIST_FOREACH_SAFE(ioh,io_handlers, next, pioh) { -if (ioh-deleted) { -QLIST_REMOVE(ioh, next); -qemu_free(ioh); -continue; -} -if (ioh-fd_read FD_ISSET(ioh-fd,rfds)) { +if (!ioh-deleted ioh-fd_read FD_ISSET(ioh-fd,rfds)) { ioh-fd_read(ioh-opaque); } -if (ioh-fd_write FD_ISSET(ioh-fd,wfds)) { +if (!ioh-deleted ioh-fd_write FD_ISSET(ioh-fd,wfds)) { ioh-fd_write(ioh-opaque); } + +/* Do this last in case read/write handlers marked it for deletion */ +if (ioh-deleted) { +QLIST_REMOVE(ioh, next); +qemu_free(ioh); +} } This isn't enough. If you end up with a handler deleting the next pointer and the current pointer, you'll end up running off the end of the list. What is the point of that? That a handler can remove itself is ok. But that a handler can remove also the next in a list that is used for other things looks pretty insane to me. The original commit should be reverted. If that behaviour is expected, then I agree that we should revert it. But I would consider that behaviour wrong. Later, Juan. Regards, Anthony Liguori }
Re: [Qemu-devel] MSI broken?
Hi, Let's track it down futher. Were acpi_mem_writel() and apic_send_msi() in hw/apic.c called or not? No such function in my tree (savannah/master). Looks like some bits needed for msi are not merged yet? Sorry typo. s/acpi/apic/. The attached patch gives me: msi_notify:243 intel-hda:30 notify vector 0x0 address: 0xfee01008 data: 0x4151 apic_send_msi:775 dest 1 vector 81 dest_mode 0 trigger_mode 0 delivery 1 apic_find_dest:443 no apic found for dest 1 cheers, Gerd diff --git a/hw/apic.c b/hw/apic.c index 63d62c7..9b3ba10 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -439,6 +439,8 @@ static int apic_find_dest(uint8_t dest) return i; } +fprintf(stderr, %s:%d no apic found for dest %d\n, +__FUNCTION__, __LINE__, dest); return -1; } @@ -769,6 +771,8 @@ static void apic_send_msi(target_phys_addr_t addr, uint32 data) uint8_t trigger_mode = (data MSI_DATA_TRIGGER_SHIFT) 0x1; uint8_t delivery = (data MSI_DATA_DELIVERY_MODE_SHIFT) 0x7; /* XXX: Ignore redirection hint. */ +fprintf(stderr, %s:%d dest %d vector %d dest_mode %d trigger_mode %d delivery %d\n, +__FUNCTION__, __LINE__, dest, vector, dest_mode, trigger_mode, delivery); apic_deliver_irq(dest, dest_mode, delivery, vector, 0, trigger_mode); }
Re: [Qemu-devel] [PATCHv2 4/8] Store IDE bus id in IDEBus structure for easy access.
Gleb Natapov g...@redhat.com writes: On Wed, Nov 03, 2010 at 02:39:52PM +0100, Markus Armbruster wrote: Here's a generic answer to the question which of the device's buses is this? int qbus_index(BusState *bus) { BusState *b; int i, index; index = -1; i = 0; QLIST_FOREACH(b, bus-parent-child_bus, sibling) { if (b == bus) { index = i; } i++; } assert(0 = index index i); return i - 1 - index; } The bus created first has index 0. Note that the child_bus holds the children in reverse creation order, and we can't traverse it backwards. Same problem also visible with makes info qtree: dev: piix3-ide, id [...] bus: ide.1 type IDE bus: ide.0 type IDE Isn't this too implementation dependant? Well, it's the implementation depending on itself. Are you against adding bus_id to IDEBus? Against is too hard a word. If it's a general question, I'd prefer a general answer. And will it work with ISA? I do not think IDEBus is added to bus-parent-child_bus in case of ISA otherwise why both IDEBuses have same name in isapc. Currently I have following patch queued. It should fix isapc case too. You're right, it's not helpful there: two separate devices, both providing just one bus. Fix isapc IDE bus creation Currently we create two ide buses with the same name, so it is impossible to use -device ide-drive,bus= to address all possible disks in the isapc machine. Fix that by giving different names to different ide buses. Also store IDE bus id in IDEBus structure for easy access. Changing the name of the second default isa-ide device's bus to ide.1 is fine with me. But with that change in place, why do we need to store the bus number? Why can't we just use the name? Moreover, I think the meaning of bus number is unclear. See comments inline. diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index ff80dd5..b2cbdbc 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -257,8 +257,8 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev) pci_conf[PCI_INTERRUPT_PIN] = 0x01; // interrupt on pin 1 irq = qemu_allocate_irqs(cmd646_set_irq, d, 2); -ide_bus_new(d-bus[0], d-dev.qdev); -ide_bus_new(d-bus[1], d-dev.qdev); +ide_bus_new(d-bus[0], d-dev.qdev, 0); +ide_bus_new(d-bus[1], d-dev.qdev, 1); ide_init2(d-bus[0], irq[0]); ide_init2(d-bus[1], irq[1]); diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 4165543..bde2664 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -448,6 +448,7 @@ struct IDEBus { IDEDevice *slave; BMDMAState *bmdma; IDEState ifs[2]; +uint8_t bus_id; Why is this uint8_t? uint8_t unit; uint8_t cmd; qemu_irq irq; @@ -564,7 +565,7 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, void ide_init_ioport(IDEBus *bus, int iobase, int iobase2); /* hw/ide/qdev.c */ -void ide_bus_new(IDEBus *idebus, DeviceState *dev); +void ide_bus_new(IDEBus *idebus, DeviceState *dev, uint8_t bus_id); IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive); #endif /* HW_IDE_INTERNAL_H */ diff --git a/hw/ide/isa.c b/hw/ide/isa.c index 9b94495..b000ab8 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -66,8 +66,9 @@ static const VMStateDescription vmstate_ide_isa = { static int isa_ide_initfn(ISADevice *dev) { ISAIDEState *s = DO_UPCAST(ISAIDEState, dev, dev); +static uint8_t bus_id = 0; -ide_bus_new(s-bus, s-dev.qdev); +ide_bus_new(s-bus, s-dev.qdev, bus_id++); ide_init_ioport(s-bus, s-iobase, s-iobase2); isa_init_irq(dev, s-irq, s-isairq); isa_init_ioport_range(dev, s-iobase, 8); Works for any number of isa-ide devices. Each one provides one IDE bus, and the buses are numbered 0, ... in the order the isa-ide devices are created. diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 6206201..e56777f 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -129,8 +129,8 @@ static int pci_piix_ide_initfn(PCIIDEState *d) vmstate_register(d-dev.qdev, 0, vmstate_ide_pci, d); -ide_bus_new(d-bus[0], d-dev.qdev); -ide_bus_new(d-bus[1], d-dev.qdev); +ide_bus_new(d-bus[0], d-dev.qdev, 0); +ide_bus_new(d-bus[1], d-dev.qdev, 1); ide_init_ioport(d-bus[0], 0x1f0, 0x3f6); ide_init_ioport(d-bus[1], 0x170, 0x376); Each piix3-ide device provides two IDE buses numbered 0 and 1. If you create multiple IDE controller devices, then the IDE bus numbers and names clash, unless they're all isa-ide devices. What is the IDE bus number supposed to mean? Example: default piix3-ide plus a tertiary IDE channel -M pc -device isa-ide,iobase=0x1e8,iobase2=0x3ee,irq=11 diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 336ffe1..220729e 100644 --- a/hw/ide/qdev.c +++
[Qemu-devel] [RFC][RESEND][PATCH v1 00/15] virtproxy: host/guest communication layer
This set of patches is a prereq for the proposed guest agent (virtagent), so resending these to accompany this morning's virtagent v2 submission. OVERVIEW: Virtproxy proxies and multiplexes socket streams over a data channel between a host and a guest (currently network connections, emulated serial, or virtio-serial channels are supported). This allows for services such as guest data collection agents, host/guest file transfer, and event generation/handling to be implemented/deployed as basic socket-based daemons, independently of the actual data channel. This code is intended to provide a channel-independent abstraction layer for communicating with a QEMU-specific guest agent (in particular, the virtagent RPC guest agent which will follow this in a seperate patchset), but may have general utility beyond this (for instance: ssh/sftp/other guest agents/etc over isa/virtio serial), and so is submitted here as a seperate patchset. Currently this communication involves 2 daemons (common code): 1 in the guest, and 1 in the host. Each end multiplexes/demultiplexes/proxies connections from the other end. In the future we hope to integrate the host component directly into qemu as a chardev. BUILD/USAGE INFO: make qemu-vp ./qemu-vp -h EXAMPLE USAGE: - Proxy http and ssh connections from a host to a guest over a virtio-serial connection: # start guest with virtio-serial. for example (RHEL6s13): qemu \ -device virtio-serial \ -chardev socket,path=/tmp/test0-virtioconsole.sock,server,nowait,id=test0 \ -device virtconsole,chardev=test0,name=test0 \ -chardev socket,path=/tmp/test1-virtio-serial.sock,server,nowait,id=test1 \ -device virtserialport,chardev=test1,name=test1 \ -chardev socket,path=/tmp/test2-virtio-serial.sock,server,nowait,id=test2 \ -device virtserialport,chardev=test2,name=test2 \ ... # in the host: ./qemu-vp -c unix-connect:/tmp/test2-virtio-serial.sock:- -o http:127.0.0.1:9080 \ -o ssh:127.0.0.1:9022 # in the guest: ./qemu-vp -c virtserial-open:/dev/virtio-ports/test2:- -i http:127.0.0.1:80 \ -i ssh:127.0.0.1:22 # from host, access guest http server wget http://locahost:9080 # from host, access guest ssh server ssh localhost -p 9022 - Proxy http and ssh connections from a host to a guest over a network connection: # start guest with network connectivity to host # in the guest: ./qemu-vp -c tcp-listen:guest_ip:9000 -i http:127.0.0.1:80 \ -i ssh:127.0.0.1:22 # in the host: ./qemu-vp -c tcp-connect:guest_ip:9000 -o http:127.0.0.1:9080 \ -o ssh:127.0.0.1:9022 ... By specifying -i and -o options in the host and guest, respectively, the channel can also be used to establish connections from a guest to a host. KNOWN ISSUES: - Deadlocking the guest: In tests over isa-serial ports I've hit cases where the chardev (socket) on the host-side seem to fill up the buffer, likely due to qemu rate-limiting data in accordance with the port's baud rate (which may explain why i hadn't seen this with network-based or virtio-serial data channels. When qemu-vp reads data from client connections it puts it into a VPPacket and tries to send the packet in it's entirety back over the channel. In this particular case that write() blocks (or vp_send_all() spins if we set O_NONBLOCK on the client FD). In the meantime qemu fills up the other end of the socket buffer and ends up spinning in qemu-char:send_all(), basically causing a deadlock between qemu and qemu-vp, and causing the guest to freeze. Currently I'm planning on replacing vp_send_all() with a function that simply buffers write()'s, which would allow the use of non-blocking write()'s out to the channel/chardev socket while still retaining wholeness/fifo-ordering of the VPPackets. - Sync issues with virtio-serial: This may or may not be related to the issue above, but I noticed some cases where proxied ssh sessions from the guest to the host would lag by a few bytes. For instance typing top would result in to being displayed, and the p wouldn't show up till I hit another key. This could be related to how I'm handling the buffering, but I haven't been able to reproduce using a network-based channel. TODO: - Rework vp_send_all() to use buffering to avoid above-mentioned deadlock scenario - Integrate qemu-vp directly into qemu by adding a virtproxy chardev device. For example: ./qemu-vp -c unix-connect:/tmp/vp1-virtio-serial.sock:- -o ssh:127.0.0.1:9022 in the host, would be analogous to: qemu \ -device virtio-serial \ -chardev virtproxy,oforward=ssh:127.0.0.1:9022,id=vp1 \ -device virtserialport,chardev=vp1,name=vp1 - Better channel negotiation to gracefully handle guest reboots/disconnects/etc - Add monitor commands to add/remove virtproxy channels/oforwards/iforwards on the fly .gitignore |1 + Makefile|4 +-
[Qemu-devel] [RFC][RESEND][PATCH v1 01/15] virtproxy: base data structures and constants
Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtproxy.c | 134 +++ virtproxy.h | 34 +++ 2 files changed, 168 insertions(+), 0 deletions(-) create mode 100644 virtproxy.c create mode 100644 virtproxy.h diff --git a/virtproxy.c b/virtproxy.c new file mode 100644 index 000..f30b859 --- /dev/null +++ b/virtproxy.c @@ -0,0 +1,134 @@ +/* + * virt-proxy - host/guest communication layer + * + * Copyright IBM Corp. 2010 + * + * Authors: + * Michael Roth mdr...@linux.vnet.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include virtproxy.h + +#define VP_SERVICE_ID_LEN 32/* max length of service id string */ +#define VP_PKT_DATA_LEN 1024/* max proxied bytes per VPPacket */ +#define VP_CONN_DATA_LEN 1024 /* max bytes conns can send at a time */ +#define VP_MAGIC 0x1F374059 + +/* listening fd, one for each service we're forwarding to remote end */ +typedef struct VPOForward { +VPDriver *drv; +int listen_fd; +char service_id[VP_SERVICE_ID_LEN]; +QLIST_ENTRY(VPOForward) next; +} VPOForward; + +/* service_id-path/port mapping of each service forwarded from remote end */ +typedef struct VPIForward { +VPDriver *drv; +char service_id[VP_SERVICE_ID_LEN]; +QemuOpts *socket_opts; +QLIST_ENTRY(VPIForward) next; +} VPIForward; + +/* proxied client/server connected states */ +typedef struct VPConn { +VPDriver *drv; +int client_fd; +int server_fd; +enum { +VP_CONN_CLIENT = 1, +VP_CONN_SERVER, +} type; +enum { +VP_STATE_NEW = 1, /* accept()'d and registered fd */ +VP_STATE_INIT, /* sent init pkt to remote end, waiting for ack */ +VP_STATE_CONNECTED, /* client and server connected */ +} state; +QLIST_ENTRY(VPConn) next; +} VPConn; + +typedef struct VPControlMsg { +enum { +VP_CONTROL_CONNECT_INIT = 1, +VP_CONTROL_CONNECT_ACK, +VP_CONTROL_CLOSE, +} type; +union { +/* tell remote end connect to server and map client_fd to it */ +struct { +int client_fd; +char service_id[VP_SERVICE_ID_LEN]; +} connect_init; +/* tell remote end we've created the connection to the server, + * and give them the corresponding fd to use so we don't have + * to do a reverse lookup everytime + */ +struct { +int client_fd; +int server_fd; +} connect_ack; +/* tell remote end to close fd in question, presumably because + * connection was closed on our end + */ +struct { +int client_fd; +int server_fd; +} close; +} args; +} VPControlMsg; + +typedef struct VPPacket { +enum { +VP_PKT_CONTROL = 1, +VP_PKT_CLIENT, +VP_PKT_SERVER, +} type; +union { +VPControlMsg msg; +struct { +int client_fd; +int server_fd; +int bytes; +char data[VP_PKT_DATA_LEN]; +} proxied; +} payload; +int magic; +} __attribute__((__packed__)) VPPacket; + +struct VPDriver { +int channel_fd; +int listen_fd; +char buf[sizeof(VPPacket)]; +int buflen; +QLIST_HEAD(, VPOForward) oforwards; +QLIST_HEAD(, VPIForward) iforwards; +QLIST_HEAD(, VPConn) conns; +}; + +static QemuOptsList vp_socket_opts = { +.name = vp_socket_opts, +.head = QTAILQ_HEAD_INITIALIZER(vp_socket_opts.head), +.desc = { +{ +.name = path, +.type = QEMU_OPT_STRING, +},{ +.name = host, +.type = QEMU_OPT_STRING, +},{ +.name = port, +.type = QEMU_OPT_STRING, +},{ +.name = ipv4, +.type = QEMU_OPT_BOOL, +},{ +.name = ipv6, +.type = QEMU_OPT_BOOL, +}, +{ /* end if list */ } +}, +}; diff --git a/virtproxy.h b/virtproxy.h new file mode 100644 index 000..0203421 --- /dev/null +++ b/virtproxy.h @@ -0,0 +1,34 @@ +/* + * virt-proxy - host/guest communication layer + * + * Copyright IBM Corp. 2010 + * + * Authors: + * Michael Roth mdr...@linux.vnet.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef VIRTPROXY_H +#define VIRTPROXY_H + +#include qemu-common.h +#include qemu-queue.h + +typedef struct VPDriver VPDriver; + +/* wrappers for s/vp/qemu/ functions we need */ +int vp_send_all(int fd, const void *buf, int len1); +int vp_set_fd_handler2(int fd, + IOCanReadHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque); +int
[Qemu-devel] [RFC][RESEND][PATCH v1 08/15] virtproxy: interfaces to set/remove/handle VPOForwards
Functions to add listener FDs (oforwards) which set up proxied connections to associated service, and the corresponding handler function to process to new connections to said FDs and initialize new client connections to the associated remote server over the channel Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtproxy.c | 103 +++ virtproxy.h |1 + 2 files changed, 104 insertions(+), 0 deletions(-) diff --git a/virtproxy.c b/virtproxy.c index cc0ac9a..6c3611b 100644 --- a/virtproxy.c +++ b/virtproxy.c @@ -12,6 +12,7 @@ */ #include virtproxy.h +#include qemu_socket.h #define DEBUG_VP @@ -314,6 +315,70 @@ static void vp_channel_read(void *opaque) } } +/* handler to accept() and init new client connections */ +static void vp_oforward_accept(void *opaque) +{ +VPOForward *f = opaque; +VPDriver *drv = f-drv; + +struct sockaddr_in saddr; +struct sockaddr *addr; +socklen_t len; +int fd, ret; +VPConn *conn = NULL; +VPPacket pkt; +VPControlMsg msg; + +TRACE(called with opaque: %p, drv: %p, f, drv); + +for(;;) { +len = sizeof(saddr); +addr = (struct sockaddr *)saddr; +fd = qemu_accept(f-listen_fd, addr, len); + +if (fd 0 errno != EINTR) { +TRACE(accept() failed); +return; +} else if (fd = 0) { +TRACE(accepted connection); +break; +} +} + +if (drv-channel_fd == -1) { +TRACE(communication channel not open, closing connection); +closesocket(fd); +return; +} + +/* send init packet over channel */ +memset(msg, 0, sizeof(VPControlMsg)); +msg.type = VP_CONTROL_CONNECT_INIT; +msg.args.connect_init.client_fd = fd; +pstrcpy(msg.args.connect_init.service_id, VP_SERVICE_ID_LEN, f-service_id); + +memset(pkt, 0, sizeof(VPPacket)); +pkt.type = VP_PKT_CONTROL; +pkt.payload.msg = msg; +pkt.magic = VP_MAGIC; + +ret = vp_send_all(drv-channel_fd, pkt, sizeof(VPPacket)); +if (ret == -1) { +LOG(vp_send_all() failed); +return; +} + +/* create new VPConn for client */ +conn = qemu_mallocz(sizeof(VPConn)); +conn-drv = drv; +conn-client_fd = fd; +conn-type = VP_CONN_CLIENT; +conn-state = VP_STATE_NEW; +QLIST_INSERT_HEAD(drv-conns, conn, next); + +socket_set_nonblock(fd); +} + /* create/init VPDriver object */ VPDriver *vp_new(int fd, bool listen) { @@ -336,3 +401,41 @@ VPDriver *vp_new(int fd, bool listen) return drv; } + +/* set/modify/remove a service_id - net/unix listening socket mapping + * + * service_id is a user-defined id for the service. this is what the + * client end will tag it's connections with so that the remote end can + * route it to the proper socket on the remote end. + * + * fd is a listen()'ing socket we want virtproxy to listen for new + * connections of this service type on. set fd to -1 to remove the + * existing listening socket for this service_id + */ +int vp_set_oforward(VPDriver *drv, int fd, const char *service_id) +{ +VPOForward *f = get_oforward(drv, service_id); + +if (fd == -1) { +if (f != NULL) { +vp_set_fd_handler(f-listen_fd, NULL, NULL, NULL); +QLIST_REMOVE(f, next); +qemu_free(f); +} +return 0; +} + +if (f == NULL) { +f = qemu_mallocz(sizeof(VPOForward)); +f-drv = drv; +strncpy(f-service_id, service_id, VP_SERVICE_ID_LEN); +QLIST_INSERT_HEAD(drv-oforwards, f, next); +} else { +closesocket(f-listen_fd); +} + +f-listen_fd = fd; +vp_set_fd_handler(f-listen_fd, vp_oforward_accept, NULL, f); + +return 0; +} diff --git a/virtproxy.h b/virtproxy.h index 3df1691..39d5d40 100644 --- a/virtproxy.h +++ b/virtproxy.h @@ -33,5 +33,6 @@ int vp_set_fd_handler(int fd, /* virtproxy interface */ VPDriver *vp_new(int fd, bool listen); +int vp_set_oforward(VPDriver *drv, int fd, const char *service_id); #endif /* VIRTPROXY_H */ -- 1.7.0.4
[Qemu-devel] [RFC][RESEND][PATCH v1 02/15] virtproxy: qemu-vp, standalone daemon skeleton
Daemon to be run in guest, or on host in standalone mode. (re-)implements some qemu utility functions used by core virtproxy.c code via wrapper functions. For built-in virtproxy code we will define these wrapper functions in terms of qemu's built-in implementations. Main logic will come in a later patch. Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- qemu-vp.c | 151 + 1 files changed, 151 insertions(+), 0 deletions(-) create mode 100644 qemu-vp.c diff --git a/qemu-vp.c b/qemu-vp.c new file mode 100644 index 000..5075cdc --- /dev/null +++ b/qemu-vp.c @@ -0,0 +1,151 @@ +/* + * virt-proxy - host/guest communication daemon + * + * Copyright IBM Corp. 2010 + * + * Authors: + * Michael Roth mdr...@linux.vnet.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include virtproxy.h + +/* mirror qemu I/O-related code for standalone daemon */ +typedef struct IOHandlerRecord { +int fd; +IOCanReadHandler *fd_read_poll; +IOHandler *fd_read; +IOHandler *fd_write; +int deleted; +void *opaque; +/* temporary data */ +struct pollfd *ufd; +QLIST_ENTRY(IOHandlerRecord) next; +} IOHandlerRecord; + +static QLIST_HEAD(, IOHandlerRecord) io_handlers = +QLIST_HEAD_INITIALIZER(io_handlers); + +int vp_set_fd_handler2(int fd, + IOCanReadHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque) +{ +IOHandlerRecord *ioh; + +if (!fd_read !fd_write) { +QLIST_FOREACH(ioh, io_handlers, next) { +if (ioh-fd == fd) { +ioh-deleted = 1; +break; +} +} +} else { +QLIST_FOREACH(ioh, io_handlers, next) { +if (ioh-fd == fd) +goto found; +} +ioh = qemu_mallocz(sizeof(IOHandlerRecord)); +QLIST_INSERT_HEAD(io_handlers, ioh, next); +found: +ioh-fd = fd; +ioh-fd_read_poll = fd_read_poll; +ioh-fd_read = fd_read; +ioh-fd_write = fd_write; +ioh-opaque = opaque; +ioh-deleted = 0; +} +return 0; +} + +int vp_set_fd_handler(int fd, +IOHandler *fd_read, +IOHandler *fd_write, +void *opaque) +{ +return vp_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque); +} + +int vp_send_all(int fd, const void *buf, int len1) +{ +int ret, len; + +len = len1; +while (len 0) { +ret = write(fd, buf, len); +if (ret 0) { +if (errno != EINTR errno != EAGAIN) { +warn(write() failed); +return -1; +} +} else if (ret == 0) { +break; +} else { +buf += ret; +len -= ret; +} +} +return len1 - len; +} + +static void main_loop_wait(int nonblocking) +{ +IOHandlerRecord *ioh; +fd_set rfds, wfds, xfds; +int ret, nfds; +struct timeval tv; +int timeout = 1000; + +if (nonblocking) { +timeout = 0; +} + +/* poll any events */ +nfds = -1; +FD_ZERO(rfds); +FD_ZERO(wfds); +FD_ZERO(xfds); +QLIST_FOREACH(ioh, io_handlers, next) { +if (ioh-deleted) +continue; +if (ioh-fd_read +(!ioh-fd_read_poll || + ioh-fd_read_poll(ioh-opaque) != 0)) { +FD_SET(ioh-fd, rfds); +if (ioh-fd nfds) +nfds = ioh-fd; +} +if (ioh-fd_write) { +FD_SET(ioh-fd, wfds); +if (ioh-fd nfds) +nfds = ioh-fd; +} +} + +tv.tv_sec = timeout / 1000; +tv.tv_usec = (timeout % 1000) * 1000; + +ret = select(nfds + 1, rfds, wfds, xfds, tv); + +if (ret 0) { +IOHandlerRecord *pioh; + +QLIST_FOREACH_SAFE(ioh, io_handlers, next, pioh) { +if (ioh-deleted) { +QLIST_REMOVE(ioh, next); +qemu_free(ioh); +continue; +} +if (ioh-fd_read FD_ISSET(ioh-fd, rfds)) { +ioh-fd_read(ioh-opaque); +} +if (ioh-fd_write FD_ISSET(ioh-fd, wfds)) { +ioh-fd_write(ioh-opaque); +} +} +} +} -- 1.7.0.4
[Qemu-devel] [RFC][RESEND][PATCH v1 03/15] virtproxy: add debug functions for virtproxy core
Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtproxy.c | 17 + 1 files changed, 17 insertions(+), 0 deletions(-) diff --git a/virtproxy.c b/virtproxy.c index f30b859..2f8996c 100644 --- a/virtproxy.c +++ b/virtproxy.c @@ -13,6 +13,23 @@ #include virtproxy.h +#define DEBUG_VP + +#ifdef DEBUG_VP +#define TRACE(msg, ...) do { \ +fprintf(stderr, %s:%s():L%d: msg \n, \ +__FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \ +} while(0) +#else +#define TRACE(msg, ...) \ +do { } while (0) +#endif + +#define LOG(msg, ...) do { \ +fprintf(stderr, %s:%s(): msg \n, \ +__FILE__, __FUNCTION__, ## __VA_ARGS__); \ +} while(0) + #define VP_SERVICE_ID_LEN 32/* max length of service id string */ #define VP_PKT_DATA_LEN 1024/* max proxied bytes per VPPacket */ #define VP_CONN_DATA_LEN 1024 /* max bytes conns can send at a time */ -- 1.7.0.4
[Qemu-devel] [RFC][RESEND][PATCH v1 04/15] virtproxy: list look-up functions conns/oforwards/iforwards
Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtproxy.c | 44 1 files changed, 44 insertions(+), 0 deletions(-) diff --git a/virtproxy.c b/virtproxy.c index 2f8996c..fa17722 100644 --- a/virtproxy.c +++ b/virtproxy.c @@ -149,3 +149,47 @@ static QemuOptsList vp_socket_opts = { { /* end if list */ } }, }; + +/* get VPConn by fd, client denotes whether to look for client or server */ +static VPConn *get_conn(const VPDriver *drv, int fd, bool client) +{ +VPConn *c = NULL; +int cur_fd; + +QLIST_FOREACH(c, drv-conns, next) { +cur_fd = client ? c-client_fd : c-server_fd; +if (cur_fd == fd) { +return c; +} +} + +return NULL; +} + +/* get VPOForward by service_id */ +static VPOForward *get_oforward(const VPDriver *drv, const char *service_id) +{ +VPOForward *f = NULL; + +QLIST_FOREACH(f, drv-oforwards, next) { +if (strncmp(f-service_id, service_id, VP_SERVICE_ID_LEN) == 0) { +return f; +} +} + +return NULL; +} + +/* get VPIForward by service_id */ +static VPIForward *get_iforward(const VPDriver *drv, const char *service_id) +{ +VPIForward *f = NULL; + +QLIST_FOREACH(f, drv-iforwards, next) { +if (strncmp(f-service_id, service_id, VP_SERVICE_ID_LEN) == 0) { +return f; +} +} + +return NULL; +} -- 1.7.0.4
[Qemu-devel] [RFC][RESEND][PATCH v1 05/15] virtproxy: add accept handler for communication channel
This accept()'s connections to the socket we told virt-proxy to listen for the channel connection on and sets the appropriate read handler for the resulting FD. Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtproxy.c | 37 + 1 files changed, 37 insertions(+), 0 deletions(-) diff --git a/virtproxy.c b/virtproxy.c index fa17722..20532c2 100644 --- a/virtproxy.c +++ b/virtproxy.c @@ -166,6 +166,8 @@ static VPConn *get_conn(const VPDriver *drv, int fd, bool client) return NULL; } +static void vp_channel_accept(void *opaque); + /* get VPOForward by service_id */ static VPOForward *get_oforward(const VPDriver *drv, const char *service_id) { @@ -193,3 +195,38 @@ static VPIForward *get_iforward(const VPDriver *drv, const char *service_id) return NULL; } + +/* accept handler for communication channel + * + * accept()s connection to communication channel (for sockets), and sets + * up the read handler for resulting FD. + */ +static void vp_channel_accept(void *opaque) +{ +VPDriver *drv = opaque; +struct sockaddr_in saddr; +struct sockaddr *addr; +socklen_t len; +int fd; + +TRACE(called with opaque: %p, drv); + +for(;;) { +len = sizeof(saddr); +addr = (struct sockaddr *)saddr; +fd = qemu_accept(drv-listen_fd, addr, len); + +if (fd 0 errno != EINTR) { +TRACE(accept() failed); +return; +} else if (fd = 0) { +TRACE(accepted connection); +break; +} +} + +drv-channel_fd = fd; +vp_set_fd_handler(drv-channel_fd, vp_channel_read, NULL, drv); +/* dont accept anymore connections until channel_fd is closed */ +vp_set_fd_handler(drv-listen_fd, NULL, NULL, NULL); +} -- 1.7.0.4
[Qemu-devel] [RFC][RESEND][PATCH v1 06/15] virtproxy: add read handler for communication channel
Handle data coming in over the channel as VPPackets: Process control messages and forward data from remote client/server connections to the appropriate server/client FD on our end. Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtproxy.c | 83 +++ 1 files changed, 83 insertions(+), 0 deletions(-) diff --git a/virtproxy.c b/virtproxy.c index 20532c2..c9c3022 100644 --- a/virtproxy.c +++ b/virtproxy.c @@ -33,6 +33,7 @@ #define VP_SERVICE_ID_LEN 32/* max length of service id string */ #define VP_PKT_DATA_LEN 1024/* max proxied bytes per VPPacket */ #define VP_CONN_DATA_LEN 1024 /* max bytes conns can send at a time */ +#define VP_CHAN_DATA_LEN 4096 /* max bytes channel can send at a time */ #define VP_MAGIC 0x1F374059 /* listening fd, one for each service we're forwarding to remote end */ @@ -150,6 +151,8 @@ static QemuOptsList vp_socket_opts = { }, }; +static void vp_channel_read(void *opaque); + /* get VPConn by fd, client denotes whether to look for client or server */ static VPConn *get_conn(const VPDriver *drv, int fd, bool client) { @@ -230,3 +233,83 @@ static void vp_channel_accept(void *opaque) /* dont accept anymore connections until channel_fd is closed */ vp_set_fd_handler(drv-listen_fd, NULL, NULL, NULL); } + +/* read handler for communication channel + * + * de-multiplexes data coming in over the channel. for control messages + * we process them here, for data destined for a service or client we + * send it to the appropriate FD. + */ +static void vp_channel_read(void *opaque) +{ +VPDriver *drv = opaque; +VPPacket pkt; +int count, ret, buf_offset; +char buf[VP_CHAN_DATA_LEN]; +char *pkt_ptr, *buf_ptr; + +TRACE(called with opaque: %p, drv); + +count = read(drv-channel_fd, buf, sizeof(buf)); + +if (count == -1) { +LOG(read() failed: %s, strerror(errno)); +return; +} else if (count == 0) { +/* TODO: channel closed, this probably shouldn't happen for guest-side + * serial/virtio-serial connections, but need to confirm and consider + * what should happen in this case. as it stands this virtproxy instance + * is basically defunct at this point, same goes for client instances + * of virtproxy where the remote end has hung-up. + */ +LOG(channel connection closed); +vp_set_fd_handler(drv-channel_fd, NULL, NULL, drv); +drv-channel_fd = -1; +if (drv-listen_fd) { +vp_set_fd_handler(drv-listen_fd, vp_channel_accept, NULL, drv); +} +/* TODO: should close/remove/delete all existing VPConns here */ +} + +if (drv-buflen + count = sizeof(VPPacket)) { +TRACE(initial packet, drv-buflen: %d, drv-buflen); +pkt_ptr = (char *)pkt; +memcpy(pkt_ptr, drv-buf, drv-buflen); +pkt_ptr += drv-buflen; +memcpy(pkt_ptr, buf, sizeof(VPPacket) - drv-buflen); +/* handle first packet */ +ret = vp_handle_packet(drv, pkt); +if (ret != 0) { +LOG(error handling packet); +} +/* handle the rest of the buffer */ +buf_offset = sizeof(VPPacket) - drv-buflen; +drv-buflen = 0; +buf_ptr = buf + buf_offset; +count -= buf_offset; +while (count 0) { +if (count = sizeof(VPPacket)) { +/* handle full packet */ +TRACE(additional packet, drv-buflen: %d, drv-buflen); +memcpy((void *)pkt, buf_ptr, sizeof(VPPacket)); +ret = vp_handle_packet(drv, pkt); +if (ret != 0) { +LOG(error handling packet); +} +count -= sizeof(VPPacket); +buf_ptr += sizeof(VPPacket); +} else { +/* buffer the remainder */ +TRACE(buffering packet); +memcpy(drv-buf, buf_ptr, count); +drv-buflen = count; +break; +} +} +} else { +/* haven't got a full VPPacket yet, buffer for later */ +buf_ptr = drv-buf + drv-buflen; +memcpy(buf_ptr, buf, count); +drv-buflen += count; +} +} -- 1.7.0.4
[Qemu-devel] [RFC][RESEND][PATCH v1 14/15] virtproxy: Makefile/configure changes to build qemu-vp
Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- .gitignore |1 + Makefile |4 +++- configure |1 + 3 files changed, 5 insertions(+), 1 deletions(-) diff --git a/.gitignore b/.gitignore index a43e4d1..da307d2 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ qemu-img-cmds.texi qemu-img-cmds.h qemu-io qemu-monitor.texi +qemu-vp QMP/qmp-commands.txt .gdbinit *.a diff --git a/Makefile b/Makefile index 252c817..53b58d2 100644 --- a/Makefile +++ b/Makefile @@ -127,7 +127,7 @@ version-obj-$(CONFIG_WIN32) += version.o ## qemu-img.o: qemu-img-cmds.h -qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o: $(GENERATED_HEADERS) +qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o virtproxy.o: $(GENERATED_HEADERS) qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) @@ -135,6 +135,8 @@ qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-ob qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) +qemu-vp$(EXESUF): qemu-vp.o virtproxy.o qemu-tool.o qemu-error.o qemu-sockets.c $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) + qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx $(call quiet-command,sh $(SRC_PATH)/hxtool -h $ $@, GEN $@) diff --git a/configure b/configure index a079a49..27f92e0 100755 --- a/configure +++ b/configure @@ -2232,6 +2232,7 @@ if test $softmmu = yes ; then tools=qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools if [ $linux = yes -o $bsd = yes -o $solaris = yes ] ; then tools=qemu-nbd\$(EXESUF) $tools + tools=qemu-vp\$(EXESUF) $tools if [ $check_utests = yes ]; then tools=check-qint check-qstring check-qdict check-qlist $tools tools=check-qfloat check-qjson $tools -- 1.7.0.4
[Qemu-devel] [RFC][RESEND][PATCH v1 11/15] virtproxy: add vp_handle_packet()
Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtproxy.c | 23 +++ 1 files changed, 23 insertions(+), 0 deletions(-) diff --git a/virtproxy.c b/virtproxy.c index 4f56aba..5ec4e77 100644 --- a/virtproxy.c +++ b/virtproxy.c @@ -431,6 +431,29 @@ static int vp_handle_data_packet(void *drv, const VPPacket *pkt) return 0; } +static inline int vp_handle_packet(VPDriver *drv, const VPPacket *pkt) +{ +int ret; + +TRACE(called with drv: %p, drv); + +if (pkt-magic != VP_MAGIC) { +LOG(invalid packet magic field); +return -1; +} + +if (pkt-type == VP_PKT_CONTROL) { +ret = vp_handle_control_packet(drv, pkt); +} else if (pkt-type == VP_PKT_CLIENT || pkt-type == VP_PKT_SERVER) { +ret = vp_handle_data_packet(drv, pkt); +} else { +LOG(invalid packet type); +return -1; +} + +return ret; +} + /* read handler for communication channel * * de-multiplexes data coming in over the channel. for control messages -- 1.7.0.4
[Qemu-devel] [RFC][RESEND][PATCH v1 09/15] virtproxy: add handler for data packets
Process VPPackets coming in from channel and send them to the appropriate server/client connections. Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtproxy.c | 42 ++ 1 files changed, 42 insertions(+), 0 deletions(-) diff --git a/virtproxy.c b/virtproxy.c index 6c3611b..57ab2b0 100644 --- a/virtproxy.c +++ b/virtproxy.c @@ -235,6 +235,48 @@ static void vp_channel_accept(void *opaque) vp_set_fd_handler(drv-listen_fd, NULL, NULL, NULL); } +/* handle data packets + * + * process VPPackets containing data and send them to the corresponding + * FDs + */ +static int vp_handle_data_packet(void *drv, const VPPacket *pkt) +{ +int fd, ret; + +TRACE(called with drv: %p, drv); + +if (pkt-type == VP_PKT_CLIENT) { +TRACE(recieved client packet, client fd: %d, server fd: %d, + pkt-payload.proxied.client_fd, pkt-payload.proxied.server_fd); +fd = pkt-payload.proxied.server_fd; +} else if (pkt-type == VP_PKT_SERVER) { +TRACE(recieved server packet, client fd: %d, server fd: %d, + pkt-payload.proxied.client_fd, pkt-payload.proxied.server_fd); +fd = pkt-payload.proxied.client_fd; +} else { +TRACE(unknown packet type); +return -1; +} + +/* TODO: proxied in non-blocking mode can causes us to spin here + * for slow servers/clients. need to use write()'s and maintain + * a per-conn write queue that we clear out before sending any + * more data to the fd + */ +ret = vp_send_all(fd, (void *)pkt-payload.proxied.data, +pkt-payload.proxied.bytes); +if (ret == -1) { +LOG(error sending data over channel); +return -1; +} else if (ret != pkt-payload.proxied.bytes) { +TRACE(buffer full?); +return -1; +} + +return 0; +} + /* read handler for communication channel * * de-multiplexes data coming in over the channel. for control messages -- 1.7.0.4
[Qemu-devel] [RFC][RESEND][PATCH v1 13/15] virtproxy: add read handler for proxied connections
reads data from client/server connections as they become readable, then sends the data over the channel Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtproxy.c | 80 +++ 1 files changed, 80 insertions(+), 0 deletions(-) diff --git a/virtproxy.c b/virtproxy.c index 86a8e5b..f3f7f46 100644 --- a/virtproxy.c +++ b/virtproxy.c @@ -200,6 +200,86 @@ static VPIForward *get_iforward(const VPDriver *drv, const char *service_id) return NULL; } +/* read handler for proxied connections */ +static void vp_conn_read(void *opaque) +{ +VPConn *conn = opaque; +VPDriver *drv = conn-drv; +VPPacket pkt; +char buf[VP_CONN_DATA_LEN]; +int fd, count, ret; +bool client; + +TRACE(called with opaque: %p, drv: %p, opaque, drv); + +if (conn-state != VP_STATE_CONNECTED) { +LOG(invalid connection state); +return; +} + +if (conn-type != VP_CONN_CLIENT conn-type != VP_CONN_SERVER) { +LOG(invalid connection type); +return; +} + +/* TODO: all fields should be explicitly set so we shouldn't + * need to memset. this might hurt if we beef up VPPacket size + */ +memset(pkt, 0, sizeof(VPPacket)); +pkt.magic = VP_MAGIC; + +if (conn-type == VP_CONN_CLIENT) { +client = true; +fd = conn-client_fd; +} else { +client = false; +fd = conn-server_fd; +} + +count = read(fd, buf, VP_CONN_DATA_LEN); +if (count == -1) { +LOG(read() failed: %s, strerror(errno)); +return; +} else if (count == 0) { +/* connection closed, tell remote end to clean up */ +TRACE(connection closed); +pkt.type = VP_PKT_CONTROL; +pkt.payload.msg.type = VP_CONTROL_CLOSE; +if (client) { +/* we're closing the client, have remote close the server conn */ +TRACE(closing connection for client fd %d, conn-client_fd); +pkt.payload.msg.args.close.client_fd = -1; +pkt.payload.msg.args.close.server_fd = conn-server_fd; +} else { +TRACE(closing connection for server fd %d, conn-server_fd); +pkt.payload.msg.args.close.server_fd = -1; +pkt.payload.msg.args.close.client_fd = conn-client_fd;; +} +/* clean up things on our end */ +closesocket(fd); +vp_set_fd_handler(fd, NULL, NULL, NULL); +QLIST_REMOVE(conn, next); +qemu_free(conn); +} else { +TRACE(data read); +pkt.type = client ? VP_PKT_CLIENT : VP_PKT_SERVER; +pkt.payload.proxied.client_fd = conn-client_fd; +pkt.payload.proxied.server_fd = conn-server_fd; +memcpy(pkt.payload.proxied.data, buf, count); +pkt.payload.proxied.bytes = count; +} + +ret = vp_send_all(drv-channel_fd, (void *)pkt, sizeof(VPPacket)); +if (ret == -1) { +LOG(error sending data over channel); +return; +} +if (ret != sizeof(VPPacket)) { +TRACE(buffer full?); +return; +} +} + /* accept handler for communication channel * * accept()s connection to communication channel (for sockets), and sets -- 1.7.0.4
[Qemu-devel] [RFC][RESEND][PATCH v1 15/15] virtproxy: qemu-vp, main logic
Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- Makefile |2 +- qemu-vp.c | 469 - 2 files changed, 469 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 53b58d2..2dd64a3 100644 --- a/Makefile +++ b/Makefile @@ -135,7 +135,7 @@ qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-ob qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) -qemu-vp$(EXESUF): qemu-vp.o virtproxy.o qemu-tool.o qemu-error.o qemu-sockets.c $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) +qemu-vp$(EXESUF): qemu-vp.o virtproxy.o qemu-tool.o qemu-error.o qemu-sockets.c $(block-obj-y) $(qobject-obj-y) qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx $(call quiet-command,sh $(SRC_PATH)/hxtool -h $ $@, GEN $@) diff --git a/qemu-vp.c b/qemu-vp.c index 5075cdc..0cc0e67 100644 --- a/qemu-vp.c +++ b/qemu-vp.c @@ -9,10 +9,54 @@ * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. * + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * 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 getopt.h +#include err.h +#include qemu-option.h +#include qemu_socket.h #include virtproxy.h +static bool verbose_enabled = 0; +#define DEBUG_ENABLED + +#ifdef DEBUG_ENABLED +#define DEBUG(msg, ...) do { \ +fprintf(stderr, %s:%s():L%d: msg \n, \ +__FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \ +} while(0) +#else +#define DEBUG(msg, ...) do {} while (0) +#endif + +#define INFO(msg, ...) do { \ +if (!verbose_enabled) { \ +break; \ +} \ +warnx(msg, ## __VA_ARGS__); \ +} while(0) + /* mirror qemu I/O-related code for standalone daemon */ typedef struct IOHandlerRecord { int fd; @@ -98,7 +142,7 @@ static void main_loop_wait(int nonblocking) fd_set rfds, wfds, xfds; int ret, nfds; struct timeval tv; -int timeout = 1000; +int timeout = 10; if (nonblocking) { timeout = 0; @@ -149,3 +193,426 @@ static void main_loop_wait(int nonblocking) } } } + +#define VP_ARG_LEN 256 + +static QemuOptsList vp_opts = { +.name = vpargs, +.head = QTAILQ_HEAD_INITIALIZER(vp_opts.head), +.desc = { +{ +.name = service_id, +.type = QEMU_OPT_STRING, +},{ +.name = channel_method, +.type = QEMU_OPT_STRING, +},{ +.name = index, +.type = QEMU_OPT_NUMBER, +},{ +.name = path, +.type = QEMU_OPT_STRING, +},{ +.name = host, +.type = QEMU_OPT_STRING, +},{ +.name = port, +.type = QEMU_OPT_STRING, +},{ +.name = ipv4, +.type = QEMU_OPT_BOOL, +},{ +.name = ipv6, +.type = QEMU_OPT_BOOL, +}, +{ /* end if list */ } +}, +}; + +typedef struct VPData { +QemuOpts *opts; +void *opaque; +QTAILQ_ENTRY(VPData) next; +} VPData; + +static QTAILQ_HEAD(, VPData) iforwards; +static QTAILQ_HEAD(, VPData) oforwards; +static QTAILQ_HEAD(, VPData) channels; + +static void usage(const char *cmd) +{ +printf( +Usage: %s -c channel_opts [-c ... ] [-i iforward_opts ...] +[-o oforward_opts ...]\n +QEMU virt-proxy communication channel\n +\n + -c, --channelchannel options of the form:\n + method:addr:port[:channel_id]\n + -o, --oforward oforward options of the form:\n + service_id:addr:port[:channel_id]\n + -i, --iforward iforward options of the form:\n + service_id:addr:port[:channel_id]\n + -v, --verbosedisplay extra debugging information\n + -h, --help display this help and exit\n +\n +
[Qemu-devel] [RFC][RESEND][PATCH v1 12/15] virtproxy: interfaces to set/remove VPIForwards
Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtproxy.c | 59 +++ virtproxy.h |2 ++ 2 files changed, 61 insertions(+), 0 deletions(-) diff --git a/virtproxy.c b/virtproxy.c index 5ec4e77..86a8e5b 100644 --- a/virtproxy.c +++ b/virtproxy.c @@ -658,3 +658,62 @@ int vp_set_oforward(VPDriver *drv, int fd, const char *service_id) return 0; } + +/* add/modify a service_id - net/unix socket mapping + * + * service_id is a user-defined id for the service. this is what the + * remote end will use to proxy connections to a specific service on + * our end. + * + * if port is NULL, addr is the address of the net socket the + * service is running on. otherwise, addr is the path to the unix socket + * the service is running on. + * + * if port AND addr are NULL, find and remove the current iforward + * for this service_id if it exists. + * + * ipv6 is a bool denoting whether or not to use ipv6 + */ +int vp_set_iforward(VPDriver *drv, const char *service_id, const char *addr, +const char *port, bool ipv6) +{ +VPIForward *f = get_iforward(drv, service_id); + +if (addr == NULL port == NULL) { +if (f != NULL) { +qemu_opts_del(f-socket_opts); +QLIST_REMOVE(f, next); +qemu_free(f); +} +return 0; +} + +if (f == NULL) { +f = qemu_mallocz(sizeof(VPIForward)); +f-drv = drv; +strncpy(f-service_id, service_id, VP_SERVICE_ID_LEN); +QLIST_INSERT_HEAD(drv-iforwards, f, next); +} else { +qemu_opts_del(f-socket_opts); +} + +/* stick socket-related options in a QemuOpts so we can + * utilize qemu socket utility functions directly + */ +f-socket_opts = qemu_opts_create(vp_socket_opts, NULL, 0); +if (port == NULL) { +/* no port given, assume unix path */ +qemu_opt_set(f-socket_opts, path, addr); +} else { +qemu_opt_set(f-socket_opts, host, addr); +qemu_opt_set(f-socket_opts, port, port); +} + +if (ipv6) { +qemu_opt_set(f-socket_opts, ipv6, on); +} else { +qemu_opt_set(f-socket_opts, ipv4, on); +} + +return 0; +} diff --git a/virtproxy.h b/virtproxy.h index 39d5d40..d2522b3 100644 --- a/virtproxy.h +++ b/virtproxy.h @@ -34,5 +34,7 @@ int vp_set_fd_handler(int fd, /* virtproxy interface */ VPDriver *vp_new(int fd, bool listen); int vp_set_oforward(VPDriver *drv, int fd, const char *service_id); +int vp_set_iforward(VPDriver *drv, const char *service_id, const char *addr, +const char *port, bool ipv6); #endif /* VIRTPROXY_H */ -- 1.7.0.4
[Qemu-devel] [RFC][RESEND][PATCH v1 10/15] virtproxy: add handler for control packet
Process control packets coming in over the channel. This entails setting up/tearing down connections to local services initiated from the other end of the channel. Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtproxy.c | 154 +++ 1 files changed, 154 insertions(+), 0 deletions(-) diff --git a/virtproxy.c b/virtproxy.c index 57ab2b0..4f56aba 100644 --- a/virtproxy.c +++ b/virtproxy.c @@ -235,6 +235,160 @@ static void vp_channel_accept(void *opaque) vp_set_fd_handler(drv-listen_fd, NULL, NULL, NULL); } +/* handle control packets + * + * process VPPackets containing control messages + */ +static int vp_handle_control_packet(VPDriver *drv, const VPPacket *pkt) +{ +const VPControlMsg *msg = pkt-payload.msg; +int ret; + +TRACE(called with drv: %p, drv); + +switch (msg-type) { +case VP_CONTROL_CONNECT_INIT: { +int client_fd = msg-args.connect_init.client_fd; +int server_fd; +char service_id[VP_SERVICE_ID_LEN]; +VPPacket resp_pkt; +VPConn *new_conn; +VPIForward *iforward; + +pstrcpy(service_id, VP_SERVICE_ID_LEN, + msg-args.connect_init.service_id); +TRACE(setting up connection for service id %s, service_id); + +/* create server connection on behalf of remote end */ +iforward = get_iforward(drv, service_id); +if (iforward == NULL) { +LOG(no forwarder configured for service id); +return -1; +} + +qemu_opts_print(iforward-socket_opts, NULL); +if (qemu_opt_get(iforward-socket_opts, host) != NULL) { +server_fd = inet_connect_opts(iforward-socket_opts); +} else if (qemu_opt_get(iforward-socket_opts, path) != NULL) { +server_fd = unix_connect_opts(iforward-socket_opts); +} else { +LOG(unable to find listening socket host/addr info); +return -1; +} + +if (server_fd == -1) { +LOG(failed to create connection to service with id %s, +service_id); +} +TRACE(server_fd: %d, server_fd); + +new_conn = qemu_mallocz(sizeof(VPConn)); +if (!new_conn) { +LOG(memory allocation failed); +return -1; +} + +/* send a connect_ack back over the channel */ +/* TODO: all fields should be explicitly set so we shouldn't + * need to memset. this might hurt if we beef up VPPacket size + */ +memset(resp_pkt, 0, sizeof(resp_pkt)); +resp_pkt.type = VP_PKT_CONTROL; +resp_pkt.payload.msg.type = VP_CONTROL_CONNECT_ACK; +resp_pkt.payload.msg.args.connect_ack.server_fd = server_fd; +resp_pkt.payload.msg.args.connect_ack.client_fd = client_fd; +resp_pkt.magic = VP_MAGIC; + +/* TODO: can this potentially block or cause a deadlock with + * the remote end? need to look into potentially buffering these + * if it looks like the remote end is waiting for us to read data + * off the channel. + */ +if (drv-channel_fd == -1) { +TRACE(channel no longer connected, ignoring packet); +return -1; +} + +ret = vp_send_all(drv-channel_fd, (void *)resp_pkt, sizeof(resp_pkt)); +if (ret == -1) { +LOG(error sending data over channel); +return -1; +} +if (ret != sizeof(resp_pkt)) { +TRACE(buffer full? %d bytes remaining, ret); +return -1; +} + +/* add new VPConn to list and set a read handler for it */ +new_conn-drv = drv; +new_conn-client_fd = client_fd; +new_conn-server_fd = server_fd; +new_conn-type = VP_CONN_SERVER; +new_conn-state = VP_STATE_CONNECTED; +QLIST_INSERT_HEAD(drv-conns, new_conn, next); +vp_set_fd_handler(server_fd, vp_conn_read, NULL, new_conn); + +break; +} +case VP_CONTROL_CONNECT_ACK: { +int client_fd = msg-args.connect_ack.client_fd; +int server_fd = msg-args.connect_ack.server_fd; +VPConn *conn; + +TRACE(recieved ack from remote end for client fd %d, client_fd); + +if (server_fd = 0) { +LOG(remote end sent invalid server fd); +return -1; +} + +conn = get_conn(drv, client_fd, true); + +if (conn == NULL) { +LOG(failed to find connection with client_fd %d, client_fd); +return -1; +} + +conn-server_fd = server_fd; +conn-state = VP_STATE_CONNECTED; +vp_set_fd_handler(client_fd, vp_conn_read, NULL, conn); + +break; +} +case VP_CONTROL_CLOSE: { +int fd; +VPConn *conn; + +TRACE(closing connection on behalf of remote end); + +if (msg-args.close.client_fd = 0) { +fd = msg-args.close.client_fd; +TRACE(recieved
[Qemu-devel] [RFC][RESEND][PATCH v1 07/15] virtproxy: add vp_new() VPDriver constructor
Signed-off-by: Michael Roth mdr...@linux.vnet.ibm.com --- virtproxy.c | 23 +++ virtproxy.h |3 +++ 2 files changed, 26 insertions(+), 0 deletions(-) diff --git a/virtproxy.c b/virtproxy.c index c9c3022..cc0ac9a 100644 --- a/virtproxy.c +++ b/virtproxy.c @@ -313,3 +313,26 @@ static void vp_channel_read(void *opaque) drv-buflen += count; } } + +/* create/init VPDriver object */ +VPDriver *vp_new(int fd, bool listen) +{ +VPDriver *drv = NULL; + +drv = qemu_mallocz(sizeof(VPDriver)); +drv-listen_fd = -1; +drv-channel_fd = -1; +QLIST_INIT(drv-oforwards); +QLIST_INIT(drv-conns); + +if (listen) { +/* provided FD is to be listened on for channel connection */ +drv-listen_fd = fd; +vp_set_fd_handler(drv-listen_fd, vp_channel_accept, NULL, drv); +} else { +drv-channel_fd = fd; +vp_set_fd_handler(drv-channel_fd, vp_channel_read, NULL, drv); +} + +return drv; +} diff --git a/virtproxy.h b/virtproxy.h index 0203421..3df1691 100644 --- a/virtproxy.h +++ b/virtproxy.h @@ -31,4 +31,7 @@ int vp_set_fd_handler(int fd, IOHandler *fd_write, void *opaque); +/* virtproxy interface */ +VPDriver *vp_new(int fd, bool listen); + #endif /* VIRTPROXY_H */ -- 1.7.0.4
[Qemu-devel] [Bug 611142] Re: seabios should have native scsi support
Just a comment, the commands in the summary will boot the first time, but a reboot will (possibly) fail. bug 615529 has more info on that. -- seabios should have native scsi support https://bugs.launchpad.net/bugs/611142 You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. Status in QEMU: New Status in “qemu-kvm” package in Ubuntu: New Status in “seabios” package in Ubuntu: New Bug description: Binary package hint: seabios Currently when a grub multiboot image is booted with 'kvm -kernel' and 'biosdisk' module, it will see block devices of type IDE or virtio. It will not see scsi devices. To demonstrate this: $ qemu-img create -f qcow2 disk.img 1G $ grub-mkrescue --output=rescue.iso $ grub-mkimage -O i386-pc --output=grub-mb.img biosdisk minicmd part_msdos An 'ls' inside the grub prompt will show hard disks (hd0) on if: a.) -drive uses interface of virtio or scsi or b.) kvm boots boot from a cdrom or floppy For example, with these commands, grub will see a '(hd0)' $ kvm -drive file=disk.img,if=scsi,boot=on -cdrom rescue.iso -boot d $ kvm -drive file=disk.img,if=scsi,boot=on -floppy rescue.iso -boot a $ kvm -drive file=disk.img,if=virtio,boot=on -cdrom rescue.iso -boot d $ kvm -drive file=disk.img,if=ide,boot=on -cdrom rescue.iso -boot d $ kvm -drive file=disk.img,if=virtio,boot=on -kernel grub-mb.img $ kvm -drive file=disk.img,if=ide,boot=on -kernel grub-mb.img But the following will not: $ kvm -drive file=disk.img,if=scsi,boot=on -kernel grub-mb.img ProblemType: Bug DistroRelease: Ubuntu 10.10 Package: seabios 0.6.0-0ubuntu1 ProcVersionSignature: User Name 2.6.32-305.9-ec2 2.6.32.11+drm33.2 Uname: Linux 2.6.32-305-ec2 i686 Architecture: i386 Date: Thu Jul 29 03:21:21 2010 Dependencies: Ec2AMI: ami-e930db80 Ec2AMIManifest: ubuntu-images-testing-us/ubuntu-maverick-daily-i386-server-20100727.manifest.xml Ec2AvailabilityZone: us-east-1b Ec2InstanceType: m1.small Ec2Kernel: aki-407d9529 Ec2Ramdisk: unavailable PackageArchitecture: all ProcEnviron: PATH=(custom, user) LANG=en_US.UTF-8 SHELL=/bin/bash SourcePackage: seabios
Re: [Qemu-devel] [PATCH 0/3] v4 Decouple block device removal from device removal
Ryan Harper ry...@us.ibm.com writes: * Michael S. Tsirkin m...@redhat.com [2010-11-03 02:22]: On Tue, Nov 02, 2010 at 03:23:38PM -0500, Ryan Harper wrote: * Michael S. Tsirkin m...@redhat.com [2010-11-02 14:18]: On Tue, Nov 02, 2010 at 02:01:08PM -0500, Ryan Harper wrote: I like the idea of disconnect; if part of the device_del method was to invoke a disconnect method, we could implement that for block, net, etc; I'd think we'd want to send the notification, then disconnect. Struggling with whether it's worth having some reasonable timeout between notification and disconnect. The problem with this is that it has no analog in real world. In real world, you can send some notifications to the guest, and you can remove the card. Tying them together is what created the problem in the first place. Timeouts can be implemented by management, maybe with a nice dialog being shown to the user. Very true. I'm fine with forcing a disconnect during the removal path prior to notification. Do we want a new disconnect method at the device level (pci)? or just use the existing removal callback and call that during the initial hotremov event? Not sure what you mean by that, but I don't see a device doing anything differently wrt surprise or ordered removal. So probably the existing callback should do. I don't think we need to talk about disconnect: since we decided we are emulating device removal, let's call it just that. Because current the removal process depends on the guest actually responding. What I'm suggesting is that, in Marcus's term, and what drive_unplug() implements, is to disconnect the host block device from the guest device to prevent any further access to it in the case the guest doesn't respond to the removal request made via ACPI. Very specifically, what we're suggesting instead of the drive_unplug() command so to complete the device removal operation without waiting for the guest to respond; that's what's going to happen if we invoke the response callback; it will appear as if the guest responded whether it did or not. What I was suggesting above was to instead of calling the callback for handing the guest response was to add a device function called disconnect which would remove any association of host resources from guest resources before we notified the guest. Thinking about it again I'm not sure this is useful, but if we're going to remove the device without the guests knowledge, I'm not sure how useful sending the removal requests via ACPI is in the first place. My feeling is that I'd like to have explicit control over the disconnect from host resources separate from the device removal *if* we're going to retain the guest notification. If we don't care to notify the guest, then we can just do device removal without notifying the guest and be done with it. I imagine management would typically want to do this: 1. notify guest 2. wait a bit 3. remove device Yes; but this argues for (1) being a separate command from (3) Yes. Long term I think we will want a way to do that. unless we require (3) to include (1) and (2) in the qemu implementation. Currently we implement: 1. device_del (attempt to remove device) 2. notify guest 3. if guest responds, remove device 4. disconnect host resource from device on destruction With my drive_unplug patch we do: 1. disconnect host resource from device This is what drive_unplug does, right? Correct. 2. device_del (attempt to remove device) 3. notify guest 4. if guest responds, remove device I think we're suggesting to instead do (if we keep disconnect as part of device_del) 1. device_del (attemp to remove device) 2. notify guest 3. invoke device destruction callback resulting in disconnect host resource from device 4. if guest responds, invoke device destruction path a second time. By response you mean eject? No, this is not what I was suggesting. I was really suggesting that your patch is fine :) Sorry about confusion. I don't mean eject; I mean responding to the ACPI event by writing a response to the PCI chipset which QEMU then in turn will invoke the qdev_unplug() path which ultimately kills the device and the Drive and BlockState objects. I was also saying that from what I hear, the pci express support will at some point need interfaces to - notify guest about device removal/addition - get eject from guest - remove device without talking to guest - add device without talking to guest - suppress device deletion on eject All this can be generic and can work through express
Re: [Qemu-devel] [PATCHv2 4/8] Store IDE bus id in IDEBus structure for easy access.
On Wed, Nov 03, 2010 at 04:18:18PM +0100, Markus Armbruster wrote: Gleb Natapov g...@redhat.com writes: On Wed, Nov 03, 2010 at 02:39:52PM +0100, Markus Armbruster wrote: Here's a generic answer to the question which of the device's buses is this? int qbus_index(BusState *bus) { BusState *b; int i, index; index = -1; i = 0; QLIST_FOREACH(b, bus-parent-child_bus, sibling) { if (b == bus) { index = i; } i++; } assert(0 = index index i); return i - 1 - index; } The bus created first has index 0. Note that the child_bus holds the children in reverse creation order, and we can't traverse it backwards. Same problem also visible with makes info qtree: dev: piix3-ide, id [...] bus: ide.1 type IDE bus: ide.0 type IDE Isn't this too implementation dependant? Well, it's the implementation depending on itself. In a sense yes, but we expose internal qdev state in upper layer of the stack. Look like leaking abstraction problem to me. What if we will change qdev to store child buses in hash instead of list? Are you against adding bus_id to IDEBus? Against is too hard a word. If it's a general question, I'd prefer a general answer. It is as general as what pci slot/func of a pci device. We store those in PCIDevice. And will it work with ISA? I do not think IDEBus is added to bus-parent-child_bus in case of ISA otherwise why both IDEBuses have same name in isapc. Currently I have following patch queued. It should fix isapc case too. You're right, it's not helpful there: two separate devices, both providing just one bus. Fix isapc IDE bus creation Currently we create two ide buses with the same name, so it is impossible to use -device ide-drive,bus= to address all possible disks in the isapc machine. Fix that by giving different names to different ide buses. Also store IDE bus id in IDEBus structure for easy access. Changing the name of the second default isa-ide device's bus to ide.1 is fine with me. But with that change in place, why do we need to store the bus number? Why can't we just use the name? This name has no meaning outside of qemu internals. I can derive bus number from bus name by parsing the string, but I don't see why is it better than storing bus_id (that was used to create this bus name in the first place) for easy access. Moreover, I think the meaning of bus number is unclear. See comments inline. diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index ff80dd5..b2cbdbc 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -257,8 +257,8 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev) pci_conf[PCI_INTERRUPT_PIN] = 0x01; // interrupt on pin 1 irq = qemu_allocate_irqs(cmd646_set_irq, d, 2); -ide_bus_new(d-bus[0], d-dev.qdev); -ide_bus_new(d-bus[1], d-dev.qdev); +ide_bus_new(d-bus[0], d-dev.qdev, 0); +ide_bus_new(d-bus[1], d-dev.qdev, 1); ide_init2(d-bus[0], irq[0]); ide_init2(d-bus[1], irq[1]); diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 4165543..bde2664 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -448,6 +448,7 @@ struct IDEBus { IDEDevice *slave; BMDMAState *bmdma; IDEState ifs[2]; +uint8_t bus_id; Why is this uint8_t? I do not expect to have more then 255 ide buses provided by one device :) uint8_t unit; uint8_t cmd; qemu_irq irq; @@ -564,7 +565,7 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, void ide_init_ioport(IDEBus *bus, int iobase, int iobase2); /* hw/ide/qdev.c */ -void ide_bus_new(IDEBus *idebus, DeviceState *dev); +void ide_bus_new(IDEBus *idebus, DeviceState *dev, uint8_t bus_id); IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive); #endif /* HW_IDE_INTERNAL_H */ diff --git a/hw/ide/isa.c b/hw/ide/isa.c index 9b94495..b000ab8 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -66,8 +66,9 @@ static const VMStateDescription vmstate_ide_isa = { static int isa_ide_initfn(ISADevice *dev) { ISAIDEState *s = DO_UPCAST(ISAIDEState, dev, dev); +static uint8_t bus_id = 0; -ide_bus_new(s-bus, s-dev.qdev); +ide_bus_new(s-bus, s-dev.qdev, bus_id++); ide_init_ioport(s-bus, s-iobase, s-iobase2); isa_init_irq(dev, s-irq, s-isairq); isa_init_ioport_range(dev, s-iobase, 8); Works for any number of isa-ide devices. Each one provides one IDE bus, and the buses are numbered 0, ... in the order the isa-ide devices are created. Except that we use those names to address device on command line. And this is very unfortunate since now we can't address all ide devices in isapc case and in the future we
[Qemu-devel] Re: [RFC][PATCH 1/3] Linux/Guest unmapped page cache control
* Christoph Lameter c...@linux.com [2010-11-03 09:35:33]: On Fri, 29 Oct 2010, Balbir Singh wrote: A lot of the code is borrowed from zone_reclaim_mode logic for __zone_reclaim(). One might argue that the with ballooning and KSM this feature is not very useful, but even with ballooning, Interesting use of zone reclaim. I am having a difficult time reviewing the patch since you move and modify functions at the same time. Could you separate that out a bit? Sure, I'll split it out into more readable bits and repost the mm versions first. +#define UNMAPPED_PAGE_RATIO 16 Maybe come up with a scheme that allows better configuration of the mininum? I think in some setting we may want an absolute limit and in other a fraction of something (total zone size or working set?) Are you suggesting a sysctl or computation based on zone size and limit, etc? I understand it to be the latter. +bool should_balance_unmapped_pages(struct zone *zone) +{ + if (unmapped_page_control + (zone_unmapped_file_pages(zone) + UNMAPPED_PAGE_RATIO * zone-min_unmapped_pages)) + return true; + return false; +} Thanks for your review. -- Three Cheers, Balbir
Re: [Qemu-devel] [PATCHv2 4/8] Store IDE bus id in IDEBus structure for easy access.
Gleb Natapov g...@redhat.com writes: On Wed, Nov 03, 2010 at 04:18:18PM +0100, Markus Armbruster wrote: Gleb Natapov g...@redhat.com writes: On Wed, Nov 03, 2010 at 02:39:52PM +0100, Markus Armbruster wrote: Here's a generic answer to the question which of the device's buses is this? int qbus_index(BusState *bus) { BusState *b; int i, index; index = -1; i = 0; QLIST_FOREACH(b, bus-parent-child_bus, sibling) { if (b == bus) { index = i; } i++; } assert(0 = index index i); return i - 1 - index; } The bus created first has index 0. Note that the child_bus holds the children in reverse creation order, and we can't traverse it backwards. Same problem also visible with makes info qtree: dev: piix3-ide, id [...] bus: ide.1 type IDE bus: ide.0 type IDE Isn't this too implementation dependant? Well, it's the implementation depending on itself. In a sense yes, but we expose internal qdev state in upper layer of the stack. Look like leaking abstraction problem to me. What if we will change qdev to store child buses in hash instead of list? The function is defined in terms of the qdev interface: it depends only on the order in which the parent device's buses are created. The fact that my implementation happens to depend on how we store child buses doesn't change that. Are you against adding bus_id to IDEBus? Against is too hard a word. If it's a general question, I'd prefer a general answer. It is as general as what pci slot/func of a pci device. We store those in PCIDevice. It's actually more general than that :) PCI slot.function is the address of a PCI device on its parent bus. It's specific to PCI buses. The bus number is the address of a bus on its parent device. It's the same regardless of the device. And will it work with ISA? I do not think IDEBus is added to bus-parent-child_bus in case of ISA otherwise why both IDEBuses have same name in isapc. Currently I have following patch queued. It should fix isapc case too. You're right, it's not helpful there: two separate devices, both providing just one bus. Fix isapc IDE bus creation Currently we create two ide buses with the same name, so it is impossible to use -device ide-drive,bus= to address all possible disks in the isapc machine. Fix that by giving different names to different ide buses. Also store IDE bus id in IDEBus structure for easy access. Changing the name of the second default isa-ide device's bus to ide.1 is fine with me. But with that change in place, why do we need to store the bus number? Why can't we just use the name? This name has no meaning outside of qemu internals. I can derive bus number from bus name by parsing the string, but I don't see why is it better than storing bus_id (that was used to create this bus name in the first place) for easy access. Moreover, I think the meaning of bus number is unclear. See comments inline. diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index ff80dd5..b2cbdbc 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -257,8 +257,8 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev) pci_conf[PCI_INTERRUPT_PIN] = 0x01; // interrupt on pin 1 irq = qemu_allocate_irqs(cmd646_set_irq, d, 2); -ide_bus_new(d-bus[0], d-dev.qdev); -ide_bus_new(d-bus[1], d-dev.qdev); +ide_bus_new(d-bus[0], d-dev.qdev, 0); +ide_bus_new(d-bus[1], d-dev.qdev, 1); ide_init2(d-bus[0], irq[0]); ide_init2(d-bus[1], irq[1]); diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 4165543..bde2664 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -448,6 +448,7 @@ struct IDEBus { IDEDevice *slave; BMDMAState *bmdma; IDEState ifs[2]; +uint8_t bus_id; Why is this uint8_t? I do not expect to have more then 255 ide buses provided by one device :) Bah, let's make it an int. uint8_t unit; uint8_t cmd; qemu_irq irq; @@ -564,7 +565,7 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, void ide_init_ioport(IDEBus *bus, int iobase, int iobase2); /* hw/ide/qdev.c */ -void ide_bus_new(IDEBus *idebus, DeviceState *dev); +void ide_bus_new(IDEBus *idebus, DeviceState *dev, uint8_t bus_id); IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive); #endif /* HW_IDE_INTERNAL_H */ diff --git a/hw/ide/isa.c b/hw/ide/isa.c index 9b94495..b000ab8 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -66,8 +66,9 @@ static const VMStateDescription vmstate_ide_isa = { static int isa_ide_initfn(ISADevice *dev) { ISAIDEState *s = DO_UPCAST(ISAIDEState, dev, dev); +static uint8_t bus_id = 0; -
Re: [Qemu-devel] [PATCH 0/3] v4 Decouple block device removal from device removal
* Markus Armbruster arm...@redhat.com [2010-11-03 11:42]: Ryan Harper ry...@us.ibm.com writes: * Michael S. Tsirkin m...@redhat.com [2010-11-03 02:22]: On Tue, Nov 02, 2010 at 03:23:38PM -0500, Ryan Harper wrote: * Michael S. Tsirkin m...@redhat.com [2010-11-02 14:18]: On Tue, Nov 02, 2010 at 02:01:08PM -0500, Ryan Harper wrote: I like the idea of disconnect; if part of the device_del method was to invoke a disconnect method, we could implement that for block, net, etc; I'd think we'd want to send the notification, then disconnect. Struggling with whether it's worth having some reasonable timeout between notification and disconnect. The problem with this is that it has no analog in real world. In real world, you can send some notifications to the guest, and you can remove the card. Tying them together is what created the problem in the first place. Timeouts can be implemented by management, maybe with a nice dialog being shown to the user. Very true. I'm fine with forcing a disconnect during the removal path prior to notification. Do we want a new disconnect method at the device level (pci)? or just use the existing removal callback and call that during the initial hotremov event? Not sure what you mean by that, but I don't see a device doing anything differently wrt surprise or ordered removal. So probably the existing callback should do. I don't think we need to talk about disconnect: since we decided we are emulating device removal, let's call it just that. Because current the removal process depends on the guest actually responding. What I'm suggesting is that, in Marcus's term, and what drive_unplug() implements, is to disconnect the host block device from the guest device to prevent any further access to it in the case the guest doesn't respond to the removal request made via ACPI. Very specifically, what we're suggesting instead of the drive_unplug() command so to complete the device removal operation without waiting for the guest to respond; that's what's going to happen if we invoke the response callback; it will appear as if the guest responded whether it did or not. What I was suggesting above was to instead of calling the callback for handing the guest response was to add a device function called disconnect which would remove any association of host resources from guest resources before we notified the guest. Thinking about it again I'm not sure this is useful, but if we're going to remove the device without the guests knowledge, I'm not sure how useful sending the removal requests via ACPI is in the first place. My feeling is that I'd like to have explicit control over the disconnect from host resources separate from the device removal *if* we're going to retain the guest notification. If we don't care to notify the guest, then we can just do device removal without notifying the guest and be done with it. I imagine management would typically want to do this: 1. notify guest 2. wait a bit 3. remove device Yes; but this argues for (1) being a separate command from (3) Yes. Long term I think we will want a way to do that. unless we require (3) to include (1) and (2) in the qemu implementation. Currently we implement: 1. device_del (attempt to remove device) 2. notify guest 3. if guest responds, remove device 4. disconnect host resource from device on destruction With my drive_unplug patch we do: 1. disconnect host resource from device This is what drive_unplug does, right? Correct. 2. device_del (attempt to remove device) 3. notify guest 4. if guest responds, remove device I think we're suggesting to instead do (if we keep disconnect as part of device_del) 1. device_del (attemp to remove device) 2. notify guest 3. invoke device destruction callback resulting in disconnect host resource from device 4. if guest responds, invoke device destruction path a second time. By response you mean eject? No, this is not what I was suggesting. I was really suggesting that your patch is fine :) Sorry about confusion. I don't mean eject; I mean responding to the ACPI event by writing a response to the PCI chipset which QEMU then in turn will invoke the qdev_unplug() path which ultimately kills the device and the Drive and BlockState objects. I was also saying that from what I hear, the pci express support will at some point need interfaces to - notify guest
[Qemu-devel] Re: [PATCH] Delete IOHandlers after potentially running them
On 11/03/2010 10:12 AM, Juan Quintela wrote: Anthony Liguorianth...@codemonkey.ws wrote: On 11/03/2010 09:29 AM, Stefan Hajnoczi wrote: Since commit 4bed9837309e58d208183f81d8344996744292cf an .fd_read() handler that deletes its IOHandler is exposed to .fd_write() being called on the deleted IOHandler. This patch fixes deletion so that .fd_read() and .fd_write() are never called on an IOHandler that is marked for deletion. Signed-off-by: Stefan Hajnoczistefa...@linux.vnet.ibm.com --- vl.c | 15 --- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/vl.c b/vl.c index 7038952..6f56123 100644 --- a/vl.c +++ b/vl.c @@ -1252,17 +1252,18 @@ void main_loop_wait(int nonblocking) IOHandlerRecord *pioh; QLIST_FOREACH_SAFE(ioh,io_handlers, next, pioh) { -if (ioh-deleted) { -QLIST_REMOVE(ioh, next); -qemu_free(ioh); -continue; -} -if (ioh-fd_read FD_ISSET(ioh-fd,rfds)) { +if (!ioh-deleted ioh-fd_read FD_ISSET(ioh-fd,rfds)) { ioh-fd_read(ioh-opaque); } -if (ioh-fd_write FD_ISSET(ioh-fd,wfds)) { +if (!ioh-deleted ioh-fd_write FD_ISSET(ioh-fd,wfds)) { ioh-fd_write(ioh-opaque); } + +/* Do this last in case read/write handlers marked it for deletion */ +if (ioh-deleted) { +QLIST_REMOVE(ioh, next); +qemu_free(ioh); +} } This isn't enough. If you end up with a handler deleting the next pointer and the current pointer, you'll end up running off the end of the list. What is the point of that? That a handler can remove itself is ok. But that a handler can remove also the next in a list that is used for other things looks pretty insane to me. If you have multiple file descriptors registered for something and you get an EOF on one of the file descriptors, your clean-up action that happens as a result of closing the session may involve deleting more than one file descriptor callback. Regards, Anthony Liguori The original commit should be reverted. If that behaviour is expected, then I agree that we should revert it. But I would consider that behaviour wrong. Later, Juan. Regards, Anthony Liguori }
Re: [Qemu-devel] Re: [PATCH] Implement a virtio GPU transport
On 01/11/10 15:57, Anthony Liguori wrote: It very much is. It supports fully visually integrated rendering (no overlay windows) and even compositing GL window managers work fine, even if running 3D apps under them. Does the kernel track userspace pid and pass that information to qemu? Yes. And the qemu code tracks the PIDs and keeps multiple queues (one per pid). -Ian
Re: [Qemu-devel] Re: [PATCH] Implement a virtio GPU transport
On 29/10/10 12:18, Rusty Russell wrote: On Wed, 27 Oct 2010 11:30:31 pm Ian Molton wrote: On 19/10/10 11:39, Avi Kivity wrote: On 10/19/2010 12:31 PM, Ian Molton wrote: 2. should start with a patch to the virtio-pci spec to document what you're doing Where can I find that spec? http://ozlabs.org/~rusty/virtio-spec/ Ok, but I'm not patching that until theres been some review. Fair enough; it's a bit of a PITA to patch, so it makes sense to get the details nailed down first. I thought so :) Fixed - updated patch tested and attached. OK. FWIW, I think this is an awesome idea. I understand others are skeptical, but this seems simple and if it works and you're happy to maintain it I'm happy to let you do it :) Awesoe, thanks Rusty :)
[Qemu-devel] Re: [RFC][PATCH 1/3] Linux/Guest unmapped page cache control
On Wed, 3 Nov 2010, Balbir Singh wrote: +#define UNMAPPED_PAGE_RATIO 16 Maybe come up with a scheme that allows better configuration of the mininum? I think in some setting we may want an absolute limit and in other a fraction of something (total zone size or working set?) Are you suggesting a sysctl or computation based on zone size and limit, etc? I understand it to be the latter. Do a computation based on zone size on startup and then allow the user to modify the absolute size of the page cache? Hmmm.. That would have to be per zone/node or somehow distributed over all zones/nodes.
Re: [Qemu-devel] [PATCH 0/3] v4 Decouple block device removal from device removal
On Wed, Nov 03, 2010 at 12:29:10PM -0500, Ryan Harper wrote: * Markus Armbruster arm...@redhat.com [2010-11-03 11:42]: Ryan Harper ry...@us.ibm.com writes: * Michael S. Tsirkin m...@redhat.com [2010-11-03 02:22]: On Tue, Nov 02, 2010 at 03:23:38PM -0500, Ryan Harper wrote: * Michael S. Tsirkin m...@redhat.com [2010-11-02 14:18]: On Tue, Nov 02, 2010 at 02:01:08PM -0500, Ryan Harper wrote: I like the idea of disconnect; if part of the device_del method was to invoke a disconnect method, we could implement that for block, net, etc; I'd think we'd want to send the notification, then disconnect. Struggling with whether it's worth having some reasonable timeout between notification and disconnect. The problem with this is that it has no analog in real world. In real world, you can send some notifications to the guest, and you can remove the card. Tying them together is what created the problem in the first place. Timeouts can be implemented by management, maybe with a nice dialog being shown to the user. Very true. I'm fine with forcing a disconnect during the removal path prior to notification. Do we want a new disconnect method at the device level (pci)? or just use the existing removal callback and call that during the initial hotremov event? Not sure what you mean by that, but I don't see a device doing anything differently wrt surprise or ordered removal. So probably the existing callback should do. I don't think we need to talk about disconnect: since we decided we are emulating device removal, let's call it just that. Because current the removal process depends on the guest actually responding. What I'm suggesting is that, in Marcus's term, and what drive_unplug() implements, is to disconnect the host block device from the guest device to prevent any further access to it in the case the guest doesn't respond to the removal request made via ACPI. Very specifically, what we're suggesting instead of the drive_unplug() command so to complete the device removal operation without waiting for the guest to respond; that's what's going to happen if we invoke the response callback; it will appear as if the guest responded whether it did or not. What I was suggesting above was to instead of calling the callback for handing the guest response was to add a device function called disconnect which would remove any association of host resources from guest resources before we notified the guest. Thinking about it again I'm not sure this is useful, but if we're going to remove the device without the guests knowledge, I'm not sure how useful sending the removal requests via ACPI is in the first place. My feeling is that I'd like to have explicit control over the disconnect from host resources separate from the device removal *if* we're going to retain the guest notification. If we don't care to notify the guest, then we can just do device removal without notifying the guest and be done with it. I imagine management would typically want to do this: 1. notify guest 2. wait a bit 3. remove device Yes; but this argues for (1) being a separate command from (3) Yes. Long term I think we will want a way to do that. unless we require (3) to include (1) and (2) in the qemu implementation. Currently we implement: 1. device_del (attempt to remove device) 2. notify guest 3. if guest responds, remove device 4. disconnect host resource from device on destruction With my drive_unplug patch we do: 1. disconnect host resource from device This is what drive_unplug does, right? Correct. 2. device_del (attempt to remove device) 3. notify guest 4. if guest responds, remove device I think we're suggesting to instead do (if we keep disconnect as part of device_del) 1. device_del (attemp to remove device) 2. notify guest 3. invoke device destruction callback resulting in disconnect host resource from device 4. if guest responds, invoke device destruction path a second time. By response you mean eject? No, this is not what I was suggesting. I was really suggesting that your patch is fine :) Sorry about confusion. I don't mean eject; I mean responding to the ACPI event by writing a response to the PCI chipset which QEMU then in
Re: [Qemu-devel] Re: [PATCH] Implement a virtio GPU transport
On 01/11/10 13:28, Anthony Liguori wrote: On 11/01/2010 06:53 AM, Alon Levy wrote: While we (speaking as part of the SPICE developers) want to have the same support in our virtual GPU for 3d as we have for 2d, we just don't at this point of time. Would it be helpful to you to have /something/ that works in the interim? I'm happy to work with you guys so that we dont need to reinvent the wheel ;-) Yes, but I think the point is that are two general approaches to supporting 3d that are being proposed. One approach is to an RPC layer at the OpenGL level which essentially passes through the host OpenGL stack. That's what virtio-gl is. This has existed for quite a while and there are multiple transports for it. Well, sort of. this version is heavily modified and only the virtio transport is supported in it. Its quite a large code cleanup. It supports serial ports, TCP sockets, a custom ISA extension for x86, The custom ISA idea is cut too since it fails to play nice with KVM. Virtio-gl offers better security too. Another approach would be to have a virtual GPU and to implement GPU-level commands for 3d. I have been repeated told that much of the complexity of Spice is absolutely needed for 3d and that that's a major part of the design. I've not seen any implementations of this type that are even close to useable. GPU-level support for 3d operations has a number of advantages mainly that it's more reasonably portable to things like Windows since the 3d commands can be a superset of both OpenGL and Direct3d. Agreed. Also, Spice has an abstraction layer that doesn't simply passthrough graphics commands, but translates/sanitizes them first. That's another advantage over OpenGL passthrough. I'm not sure that thats actually needed if you are careful about what commands you implement on the virtual GPU (and how) Without a layer to sanitize commands, a guest can do funky things with the host or other guests. It shouldnt be possible for the guest to hurt other guests actual GL rendering (or the hosts) as each PID is handed a context (or contexts) of its own. It is possible for the guest to cause the host problems though. this is a design flaw in the whole idea of GL RPC. It *isnt* reasonable to make it secure, but it certainly is useful right now since theres no alternative available. I think a Spice-like approach is the best thing long term. In the short term, I think doing the GL marshalling over virtio-serial makes a ton of sense since the kernel driver is already present upstream. It exists exactly for things like this. The virtio driver enfoces the PID field and understands the packet format used. Its better than using serial. Its also just one driver - which doesnt have any special interdependencies and can be extended or got rid of in future if and when better things come along. In the very, very short term, I think an external backend to QEMU also makes a lot of sense because that's something that Just Works today. Whos written that? The 2007 patch I've been working on and updating simply fails to work altogether without huge alterations on current qemu. My current patch touches a tiny part of the qemu sources. It works today. I think we can consider integrating it into QEMU (or at least simplifying the execution of the backend) but integrating into QEMU is going to require an awful lot of the existing code to be rewritten. Keeping it separate has the advantage of allowing something to Just Work as an interim solution as we wait for proper support in Spice. I dont know why you think integrating it into qemu is hard? I've already done it. I added one virtio driver and a seperate offscreen renderer. it touches the qemu code in *one* place. There should be no need to rewrite anything.
[Qemu-devel] site down (qemu.org)
For a lack (to my knowledge) for a better place, just say that I cannot resolve qemu.org. This affects both the webpage and the git repository. I'm using git://git.qemu.org/qemu.git, which I thought is the main one. Thanks, Lluis -- And it's much the same thing with knowledge, for whenever you learn something new, the whole world becomes that much richer. -- The Princess of Pure Reason, as told by Norton Juster in The Phantom Tollbooth
Re: [Qemu-devel] Re: [PATCH] Implement a virtio GPU transport
On 11/03/2010 01:03 PM, Ian Molton wrote: The virtio driver enfoces the PID field and understands the packet format used. Its better than using serial. Its also just one driver - which doesnt have any special interdependencies and can be extended or got rid of in future if and when better things come along. Why is it better than using virtio-serial? In the very, very short term, I think an external backend to QEMU also makes a lot of sense because that's something that Just Works today. Whos written that? The 2007 patch I've been working on and updating simply fails to work altogether without huge alterations on current qemu. My current patch touches a tiny part of the qemu sources. It works today. But it's not at all mergable in the current form. If you want to do the work of getting it into a mergable state (cleaning up the coding style, moving it to hw/, etc.) than I'm willing to consider it. But I don't think a custom virtio transport is the right thing to do here. However, if you want something that Just Works with the least amount of code possible, just split it into a separate process and we can stick it in a contrib/ directory or something. I think we can consider integrating it into QEMU (or at least simplifying the execution of the backend) but integrating into QEMU is going to require an awful lot of the existing code to be rewritten. Keeping it separate has the advantage of allowing something to Just Work as an interim solution as we wait for proper support in Spice. I dont know why you think integrating it into qemu is hard? I've already done it. Adding a file that happens to compile as part of qemu even though it doesn't actually integrate with qemu in any meaningful way is not integrating. That's just build system manipulation. Regards, Anthony Liguori I added one virtio driver and a seperate offscreen renderer. it touches the qemu code in *one* place. There should be no need to rewrite anything.
Re: [Qemu-devel] site down (qemu.org)
On 11/03/2010 01:14 PM, Lluís wrote: For a lack (to my knowledge) for a better place, just say that I cannot resolve qemu.org. This affects both the webpage and the git repository. I'm using git://git.qemu.org/qemu.git, which I thought is the main one. The site is actually up but the DNS server seems to be fubar. I'll register a temporary domain name later tonight when I'm not on a public wifi network until we can get qemu.org resolved. Regards, Anthony Liguori Thanks, Lluis
[Qemu-devel] Re: [PATCH 1/4] Introduce strtosz() library function to convert a string to a byte count.
On 10/21/2010 10:15 AM, jes.soren...@redhat.com wrote: From: Jes Sorensenjes.soren...@redhat.com strtosz() returns -1 on error. It now supports human unit formats in eg. 1.0G, with better error handling. The following suffixes are supported: B/b = bytes K/k = KB M/m = MB G/g = GB T/t = TB This patch changes -numa and -m input to use strtosz(). Signed-off-by: Jes Sorensenjes.soren...@redhat.com Applied all. Thanks. Regards, Anthony Liguori --- cutils.c | 88 + qemu-common.h |1 + vl.c | 31 ++- 3 files changed, 99 insertions(+), 21 deletions(-) diff --git a/cutils.c b/cutils.c index 5883737..28089aa 100644 --- a/cutils.c +++ b/cutils.c @@ -23,6 +23,7 @@ */ #include qemu-common.h #include host-utils.h +#includemath.h void pstrcpy(char *buf, int buf_size, const char *str) { @@ -283,3 +284,90 @@ int fcntl_setfl(int fd, int flag) } #endif +/* + * Convert string to bytes, allowing either B/b for bytes, K/k for KB, + * M/m for MB, G/g for GB or T/t for TB. Default without any postfix + * is MB. End pointer will be returned in *end, if not NULL. A valid + * value must be terminated by whitespace, ',' or '\0'. Return -1 on + * error. + */ +ssize_t strtosz(const char *nptr, char **end) +{ +ssize_t retval = -1; +char *endptr, c; +int mul_required = 0; +double val, mul, integral, fraction; + +errno = 0; +val = strtod(nptr,endptr); +if (isnan(val) || endptr == nptr || errno != 0) { +goto fail; +} +integral = modf(val,fraction); +if (integral != 0) { +mul_required = 1; +} +/* + * Any whitespace character is fine for terminating the number, + * in addition we accept ',' to handle strings where the size is + * part of a multi token argument. + */ +c = *endptr; +if (isspace(c) || c == '\0' || c == ',') { +c = 0; +} +switch (c) { +case 'B': +case 'b': +mul = 1; +if (mul_required) { +goto fail; +} +break; +case 'K': +case 'k': +mul = 1 10; +break; +case 0: +if (mul_required) { +goto fail; +} +case 'M': +case 'm': +mul = 1ULL 20; +break; +case 'G': +case 'g': +mul = 1ULL 30; +break; +case 'T': +case 't': +mul = 1ULL 40; +break; +default: +goto fail; +} +/* + * If not terminated by whitespace, ',', or \0, increment endptr + * to point to next character, then check that we are terminated + * by an appropriate separating character, ie. whitespace, ',', or + * \0. If not, we are seeing trailing garbage, thus fail. + */ +if (c != 0) { +endptr++; +if (!isspace(*endptr) *endptr != ',' *endptr != 0) { +goto fail; +} +} +if ((val * mul= ~(size_t)0) || val 0) { +goto fail; +} +retval = val * mul; + +fail: +if (end) { +*end = endptr; +} + +return retval; +} diff --git a/qemu-common.h b/qemu-common.h index 81aafa0..0a062d4 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -153,6 +153,7 @@ time_t mktimegm(struct tm *tm); int qemu_fls(int i); int qemu_fdatasync(int fd); int fcntl_setfl(int fd, int flag); +ssize_t strtosz(const char *nptr, char **end); /* path.c */ void init_paths(const char *prefix); diff --git a/vl.c b/vl.c index df414ef..6043fa2 100644 --- a/vl.c +++ b/vl.c @@ -734,16 +734,13 @@ static void numa_add(const char *optarg) if (get_param_value(option, 128, mem, optarg) == 0) { node_mem[nodenr] = 0; } else { -value = strtoull(option,endptr, 0); -switch (*endptr) { -case 0: case 'M': case 'm': -value= 20; -break; -case 'G': case 'g': -value= 30; -break; +ssize_t sval; +sval = strtosz(option, NULL); +if (sval 0) { +fprintf(stderr, qemu: invalid numa mem size: %s\n, optarg); +exit(1); } -node_mem[nodenr] = value; +node_mem[nodenr] = sval; } if (get_param_value(option, 128, cpus, optarg) == 0) { node_cpumask[nodenr] = 0; @@ -2163,18 +2160,10 @@ int main(int argc, char **argv, char **envp) exit(0); break; case QEMU_OPTION_m: { -uint64_t value; -char *ptr; +ssize_t value; -value = strtoul(optarg,ptr, 10); -switch (*ptr) { -case 0: case 'M': case 'm': -value= 20; -break; -case 'G': case 'g': -value= 30; -break; -default: +value =
Re: [Qemu-devel] [PATCH 1/1] Fold send_all() wrapper unix_write() into one function
On 11/01/2010 02:02 PM, jes.soren...@redhat.com wrote: From: Jes Sorensenjes.soren...@redhat.com The current send_all() wrapper for POSIX calls does nothing but call unix_write(). Merge them to simplify the code. Signed-off-by: Jes Sorensenjes.soren...@redhat.com Applied. Thanks. Regards, Anthony Liguori --- qemu-char.c |8 ++-- 1 files changed, 2 insertions(+), 6 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 6d2dce7..88997f9 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -508,9 +508,10 @@ int send_all(int fd, const void *buf, int len1) #else -static int unix_write(int fd, const uint8_t *buf, int len1) +int send_all(int fd, const void *_buf, int len1) { int ret, len; +const uint8_t *buf = _buf; len = len1; while (len 0) { @@ -527,11 +528,6 @@ static int unix_write(int fd, const uint8_t *buf, int len1) } return len1 - len; } - -int send_all(int fd, const void *buf, int len1) -{ -return unix_write(fd, buf, len1); -} #endif /* !_WIN32 */ #ifndef _WIN32
[Qemu-devel] Re: [PATCH] Delete IOHandlers after potentially running them
Anthony Liguori anth...@codemonkey.ws wrote: On 11/03/2010 10:12 AM, Juan Quintela wrote: Anthony Liguorianth...@codemonkey.ws wrote: On 11/03/2010 09:29 AM, Stefan Hajnoczi wrote: Since commit 4bed9837309e58d208183f81d8344996744292cf an .fd_read() handler that deletes its IOHandler is exposed to .fd_write() being called on the deleted IOHandler. This patch fixes deletion so that .fd_read() and .fd_write() are never called on an IOHandler that is marked for deletion. Signed-off-by: Stefan Hajnoczistefa...@linux.vnet.ibm.com --- vl.c | 15 --- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/vl.c b/vl.c index 7038952..6f56123 100644 --- a/vl.c +++ b/vl.c @@ -1252,17 +1252,18 @@ void main_loop_wait(int nonblocking) IOHandlerRecord *pioh; QLIST_FOREACH_SAFE(ioh,io_handlers, next, pioh) { -if (ioh-deleted) { -QLIST_REMOVE(ioh, next); -qemu_free(ioh); -continue; -} -if (ioh-fd_read FD_ISSET(ioh-fd,rfds)) { +if (!ioh-deleted ioh-fd_read FD_ISSET(ioh-fd,rfds)) { ioh-fd_read(ioh-opaque); } -if (ioh-fd_write FD_ISSET(ioh-fd,wfds)) { +if (!ioh-deleted ioh-fd_write FD_ISSET(ioh-fd,wfds)) { ioh-fd_write(ioh-opaque); } + +/* Do this last in case read/write handlers marked it for deletion */ +if (ioh-deleted) { +QLIST_REMOVE(ioh, next); +qemu_free(ioh); +} } This isn't enough. If you end up with a handler deleting the next pointer and the current pointer, you'll end up running off the end of the list. What is the point of that? That a handler can remove itself is ok. But that a handler can remove also the next in a list that is used for other things looks pretty insane to me. If you have multiple file descriptors registered for something and you get an EOF on one of the file descriptors, your clean-up action that happens as a result of closing the session may involve deleting more than one file descriptor callback. But that is completely wrong. you just put an ioh-deleted=1 for the others, and you are right, no? Later, Juan.
[Qemu-devel] [RFC][PATCH v1 0/6] backdoor: instruction-based guest-to-QEMU backdoor communication channel
Provides the ability for the guest to communicate with user-provided code inside QEMU itself. This backdoor communication channel is based on using instructions, as opposed to methods based on MMIO/PIO or virtproxy/virtagent. Then, these instructions are redirected to a set of user-provided routines, which are expected to be in the static library libbackdoor.a, identified by the --with-backdoor configuration parameter. The advantages of this method are: * Minimal setup for the guest. Can be used with a simple library using LD_PRELOAD, or simply adding calls to the macros in backdoor/guest.h. * Low-overhead. Using instructions does not go through any OS abstraction, not even for the setup of the communication channel. * Non-intrusive wrt OS. It can be used on any OS without prior modifications. When possible, this will overload unused/meaningless instructions in order to let the modified guest application to run natively without errors (e.g., using the CPUID instruction in x86 systems). Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- Lluís Vilanova (6): [arm m68k] move helpers.h to helper.h backdoor: handle config-time activation backdoor: declare host-side backdoor helpers backdoor: declare guest-side interface macros backdoor: [i386] provide and implement intruction-based backdoor interface backdoor: add a simple example .gitignore |1 Makefile.target| 40 +++ backdoor/examples/print/README | 13 + backdoor/examples/print/guest/Makefile |7 backdoor/examples/print/guest/test.c | 33 ++ backdoor/examples/print/host/Makefile | 13 + backdoor/examples/print/host/printcb.c | 36 +++ backdoor/guest.h | 54 backdoor/helper.h | 21 + configure | 21 + target-arm/helper.c|2 target-arm/helper.h| 450 target-arm/helpers.h | 450 target-arm/iwmmxt_helper.c |2 target-arm/neon_helper.c |2 target-arm/op_helper.c |2 target-arm/translate.c |6 target-i386/cpuid.c| 27 ++ target-i386/helper.h |4 target-i386/translate.c|4 target-m68k/helper.c |2 target-m68k/helper.h | 54 target-m68k/helpers.h | 54 target-m68k/op_helper.c|2 target-m68k/translate.c|6 25 files changed, 786 insertions(+), 520 deletions(-) create mode 100644 backdoor/examples/print/README create mode 100644 backdoor/examples/print/guest/Makefile create mode 100644 backdoor/examples/print/guest/test.c create mode 100644 backdoor/examples/print/host/Makefile create mode 100644 backdoor/examples/print/host/printcb.c create mode 100644 backdoor/guest.h create mode 100644 backdoor/helper.h create mode 100644 target-arm/helper.h delete mode 100644 target-arm/helpers.h create mode 100644 target-m68k/helper.h delete mode 100644 target-m68k/helpers.h
[Qemu-devel] [PATCH v1 1/6] [arm m68k] move helpers.h to helper.h
This provides a consistent naming scheme across all targets. Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- target-arm/helper.c|2 target-arm/helper.h| 450 target-arm/helpers.h | 450 target-arm/iwmmxt_helper.c |2 target-arm/neon_helper.c |2 target-arm/op_helper.c |2 target-arm/translate.c |6 - target-m68k/helper.c |2 target-m68k/helper.h | 54 + target-m68k/helpers.h | 54 - target-m68k/op_helper.c|2 target-m68k/translate.c|6 - 12 files changed, 516 insertions(+), 516 deletions(-) create mode 100644 target-arm/helper.h delete mode 100644 target-arm/helpers.h create mode 100644 target-m68k/helper.h delete mode 100644 target-m68k/helpers.h diff --git a/target-arm/helper.c b/target-arm/helper.c index 2dd64d9..08afe24 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -5,7 +5,7 @@ #include cpu.h #include exec-all.h #include gdbstub.h -#include helpers.h +#include helper.h #include qemu-common.h #include host-utils.h #if !defined(CONFIG_USER_ONLY) diff --git a/target-arm/helper.h b/target-arm/helper.h new file mode 100644 index 000..0d1bc47 --- /dev/null +++ b/target-arm/helper.h @@ -0,0 +1,450 @@ +#include def-helper.h + +DEF_HELPER_1(clz, i32, i32) +DEF_HELPER_1(sxtb16, i32, i32) +DEF_HELPER_1(uxtb16, i32, i32) + +DEF_HELPER_2(add_setq, i32, i32, i32) +DEF_HELPER_2(add_saturate, i32, i32, i32) +DEF_HELPER_2(sub_saturate, i32, i32, i32) +DEF_HELPER_2(add_usaturate, i32, i32, i32) +DEF_HELPER_2(sub_usaturate, i32, i32, i32) +DEF_HELPER_1(double_saturate, i32, s32) +DEF_HELPER_2(sdiv, s32, s32, s32) +DEF_HELPER_2(udiv, i32, i32, i32) +DEF_HELPER_1(rbit, i32, i32) +DEF_HELPER_1(abs, i32, i32) + +#define PAS_OP(pfx) \ +DEF_HELPER_3(pfx ## add8, i32, i32, i32, ptr) \ +DEF_HELPER_3(pfx ## sub8, i32, i32, i32, ptr) \ +DEF_HELPER_3(pfx ## sub16, i32, i32, i32, ptr) \ +DEF_HELPER_3(pfx ## add16, i32, i32, i32, ptr) \ +DEF_HELPER_3(pfx ## addsubx, i32, i32, i32, ptr) \ +DEF_HELPER_3(pfx ## subaddx, i32, i32, i32, ptr) + +PAS_OP(s) +PAS_OP(u) +#undef PAS_OP + +#define PAS_OP(pfx) \ +DEF_HELPER_2(pfx ## add8, i32, i32, i32) \ +DEF_HELPER_2(pfx ## sub8, i32, i32, i32) \ +DEF_HELPER_2(pfx ## sub16, i32, i32, i32) \ +DEF_HELPER_2(pfx ## add16, i32, i32, i32) \ +DEF_HELPER_2(pfx ## addsubx, i32, i32, i32) \ +DEF_HELPER_2(pfx ## subaddx, i32, i32, i32) +PAS_OP(q) +PAS_OP(sh) +PAS_OP(uq) +PAS_OP(uh) +#undef PAS_OP + +DEF_HELPER_2(ssat, i32, i32, i32) +DEF_HELPER_2(usat, i32, i32, i32) +DEF_HELPER_2(ssat16, i32, i32, i32) +DEF_HELPER_2(usat16, i32, i32, i32) + +DEF_HELPER_2(usad8, i32, i32, i32) + +DEF_HELPER_1(logicq_cc, i32, i64) + +DEF_HELPER_3(sel_flags, i32, i32, i32, i32) +DEF_HELPER_1(exception, void, i32) +DEF_HELPER_0(wfi, void) + +DEF_HELPER_2(cpsr_write, void, i32, i32) +DEF_HELPER_0(cpsr_read, i32) + +DEF_HELPER_3(v7m_msr, void, env, i32, i32) +DEF_HELPER_2(v7m_mrs, i32, env, i32) + +DEF_HELPER_3(set_cp15, void, env, i32, i32) +DEF_HELPER_2(get_cp15, i32, env, i32) + +DEF_HELPER_3(set_cp, void, env, i32, i32) +DEF_HELPER_2(get_cp, i32, env, i32) + +DEF_HELPER_2(get_r13_banked, i32, env, i32) +DEF_HELPER_3(set_r13_banked, void, env, i32, i32) + +DEF_HELPER_1(get_user_reg, i32, i32) +DEF_HELPER_2(set_user_reg, void, i32, i32) + +DEF_HELPER_1(vfp_get_fpscr, i32, env) +DEF_HELPER_2(vfp_set_fpscr, void, env, i32) + +DEF_HELPER_3(vfp_adds, f32, f32, f32, env) +DEF_HELPER_3(vfp_addd, f64, f64, f64, env) +DEF_HELPER_3(vfp_subs, f32, f32, f32, env) +DEF_HELPER_3(vfp_subd, f64, f64, f64, env) +DEF_HELPER_3(vfp_muls, f32, f32, f32, env) +DEF_HELPER_3(vfp_muld, f64, f64, f64, env) +DEF_HELPER_3(vfp_divs, f32, f32, f32, env) +DEF_HELPER_3(vfp_divd, f64, f64, f64, env) +DEF_HELPER_1(vfp_negs, f32, f32) +DEF_HELPER_1(vfp_negd, f64, f64) +DEF_HELPER_1(vfp_abss, f32, f32) +DEF_HELPER_1(vfp_absd, f64, f64) +DEF_HELPER_2(vfp_sqrts, f32, f32, env) +DEF_HELPER_2(vfp_sqrtd, f64, f64, env) +DEF_HELPER_3(vfp_cmps, void, f32, f32, env) +DEF_HELPER_3(vfp_cmpd, void, f64, f64, env) +DEF_HELPER_3(vfp_cmpes, void, f32, f32, env) +DEF_HELPER_3(vfp_cmped, void, f64, f64, env) + +DEF_HELPER_2(vfp_fcvtds, f64, f32, env) +DEF_HELPER_2(vfp_fcvtsd, f32, f64, env) + +DEF_HELPER_2(vfp_uitos, f32, f32, env) +DEF_HELPER_2(vfp_uitod, f64, f32, env) +DEF_HELPER_2(vfp_sitos, f32, f32, env) +DEF_HELPER_2(vfp_sitod, f64, f32, env) + +DEF_HELPER_2(vfp_touis, f32, f32, env) +DEF_HELPER_2(vfp_touid, f32, f64, env) +DEF_HELPER_2(vfp_touizs, f32, f32, env) +DEF_HELPER_2(vfp_touizd, f32, f64, env) +DEF_HELPER_2(vfp_tosis, f32, f32, env) +DEF_HELPER_2(vfp_tosid, f32, f64, env) +DEF_HELPER_2(vfp_tosizs, f32, f32, env) +DEF_HELPER_2(vfp_tosizd, f32, f64, env) + +DEF_HELPER_3(vfp_toshs, f32, f32, i32, env) +DEF_HELPER_3(vfp_tosls, f32, f32, i32, env) +DEF_HELPER_3(vfp_touhs, f32,
[Qemu-devel] [PATCH v1 2/6] backdoor: handle config-time activation
Add a '--with-backdoor' configuration option pointing to user-provided backdoor callback implementation. Make is invoked on the user-provided directory, which must build a static library containing, at least, the implementation of the backdoor helpers. Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- Makefile.target | 40 configure | 21 + 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/Makefile.target b/Makefile.target index c48cbcc..9152723 100644 --- a/Makefile.target +++ b/Makefile.target @@ -29,7 +29,7 @@ QEMU_PROG=qemu-system-$(TARGET_ARCH2)$(EXESUF) endif endif -PROGS=$(QEMU_PROG) +PROGS=$(QEMU_PROG)-prepare $(QEMU_PROG) ifndef CONFIG_HAIKU LIBS+=-lm @@ -323,8 +323,40 @@ endif # CONFIG_SOFTMMU obj-y += $(addprefix ../, $(trace-obj-y)) obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o -$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y) - $(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)) + +.PHONY: force +force: + +# +# backdoor communication channel +ifdef CONFIG_BACKDOOR +VPATH := $(VPATH):$(BACKDOOR_PATH) + +LIBBACKDOOR_LIB = libbackdoor/libbackdoor.a +LIBBACKDOOR_CLEAN = libbackdoor-clean + +libbackdoor/Makefile: + $(call quiet-command, mkdir -p libbackdoor, CREAT $(TARGET_DIR)$@) + $(call quiet-command, rm -f libbackdoor/Makefile) + $(call quiet-command, ln -s $(BACKDOOR_PATH)/Makefile libbackdoor/Makefile) + +libbackdoor/libbackdoor.a: libbackdoor/Makefile force + $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libbackdoor \ + QEMU_CFLAGS=$(QEMU_CFLAGS) -I../target-$(TARGET_BASE_ARCH) \ + TARGET_DIR=$(TARGET_DIR)libbackdoor/ VPATH=$(VPATH) \ + SRC_PATH=$(SRC_PATH) V=$(V) libbackdoor.a) + +libbackdoor-clean: + $(MAKE) $(SUBDIR_MAKEFLAGS) -C $(LIBBACKDOOR_DIR) \ + VPATH=$(VPATH) SRC_PATH=$(SRC_PATH) V=$(V) clean || true +endif + + + +$(QEMU_PROG)-prepare: $(GENERATED_HEADERS) $(LIBBACKDOOR_LIB) $(QEMU_PROG) + +$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y) $(LIBBACKDOOR_LIB) + $(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)) $(LIBBACKDOOR_LIB) gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/feature_to_c.sh @@ -336,7 +368,7 @@ hmp-commands.h: $(SRC_PATH)/hmp-commands.hx qmp-commands.h: $(SRC_PATH)/qmp-commands.hx $(call quiet-command,sh $(SRC_PATH)/hxtool -h $ $@, GEN $(TARGET_DIR)$@) -clean: +clean: $(LIBBACKDOOR_CLEAN) rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o rm -f *.d */*.d tcg/*.o ide/*.o rm -f hmp-commands.h qmp-commands.h gdbstub-xml.c diff --git a/configure b/configure index a079a49..991f0b8 100755 --- a/configure +++ b/configure @@ -331,6 +331,7 @@ zero_malloc= trace_backend=nop trace_file=trace spice= +backdoor= # OS specific if check_define __linux__ ; then @@ -740,6 +741,17 @@ for opt do ;; --*dir) ;; + --with-backdoor=*) backdoor=$optarg + if test ! -f $backdoor/Makefile; then + echo + echo Error: cannot make into '$backdoor' + echo Please choose a directory where I can run 'make' + echo + exit 1 + else + backdoor=`readlink -f $backdoor` + fi + ;; *) echo ERROR: unknown option $opt; show_help=yes ;; esac @@ -2320,6 +2332,9 @@ echo vhost-net support $vhost_net echo Trace backend $trace_backend echo Trace output file $trace_file-pid echo spice support $spice +if test -n $backdoor; then +echo Backdoor comm.$backdoor +fi if test $sdl_too_old = yes; then echo - Your SDL version is too old - please upgrade to have SDL support @@ -2579,6 +2594,12 @@ if test $spice = yes ; then echo CONFIG_SPICE=y $config_host_mak fi +if test -n $backdoor; then + echo CONFIG_BACKDOOR=y $config_host_mak + echo BACKDOOR_PATH=$backdoor $config_host_mak + rm -rf *-{bsd-usr,darwin-user,linux-user,softmmu}/libbackdoor/ +fi + # XXX: suppress that if [ $bsd = yes ] ; then echo CONFIG_BSD=y $config_host_mak
[Qemu-devel] [PATCH v1 3/6] backdoor: declare host-side backdoor helpers
These helpers must be implemented by the user on libbackdoor.a. Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- backdoor/helper.h | 21 + 1 files changed, 21 insertions(+), 0 deletions(-) create mode 100644 backdoor/helper.h diff --git a/backdoor/helper.h b/backdoor/helper.h new file mode 100644 index 000..d3c19d9 --- /dev/null +++ b/backdoor/helper.h @@ -0,0 +1,21 @@ +/* + * Helpers for instruction-based backdoor communication. + * + * Copyright (c) 2010 Lluís Vilanova vilan...@ac.upc.edu + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see http://www.gnu.org/licenses/. + */ + +DEF_HELPER_1(backdoor_i8, void, i32); +DEF_HELPER_2(backdoor_i8_v32, void, i32, i32);
[Qemu-devel] [PATCH v1 5/6] backdoor: [i386] provide and implement intruction-based backdoor interface
Take the unused CPUID 0x40001xxx range as the backdoor instruction. Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- backdoor/guest.h| 21 + target-i386/cpuid.c | 27 +++ target-i386/helper.h|4 target-i386/translate.c |4 4 files changed, 56 insertions(+), 0 deletions(-) diff --git a/backdoor/guest.h b/backdoor/guest.h index 8373762..3edcbc6 100644 --- a/backdoor/guest.h +++ b/backdoor/guest.h @@ -26,8 +26,29 @@ * - v32: value of 32 bits */ +#include stdint.h + +#if __i386__ || __i486__ || __x86_64__ + +#define _BACKDOOR(t, i8, v32) \ +({ \ +uint32_t eax, ebx, ecx, edx;\ +uint32_t index = (uint32_t)0x40001000 + (t8) + (uint8_t)i8; \ +uint32_t count = (uint32_t)v32; \ +asm volatile (cpuid \ + : =a(eax), =b(ebx), =c(ecx), =d(edx) \ + : 0(index), 2(count) \ +); \ +eax;\ +}) + +#define BACKDOOR_i8(i)_BACKDOOR(0, i, 0) +#define BACKDOOR_i8_v32(i, v) _BACKDOOR(1, i, v) + +#else #error Undefined instruction-based backdoor interface for guest architecture +#endif #endif /* BACKDOOR__GUEST_H */ diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index 04ba8d5..5163e69 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -27,6 +27,9 @@ #include qemu-option.h #include qemu-config.h +#include helper.h + + /* feature flags taken from Intel Processor Identification and the CPUID * Instruction and AMD's CPUID Specification. In cases of disagreement * between feature naming conventions, aliases may be added. @@ -991,6 +994,30 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { +#if defined(CONFIG_BACKDOOR)/* synched with backdoor/guest.h */ +if ((index ~0xfff) == 0x40001000) { +int type = (index 8) 0xf; +uint8_t i8 = index 0x0ff; +uint32_t v32 = count; +switch (type) { +case 0: +helper_backdoor_i8(i8); +break; +case 1: +helper_backdoor_i8_v32(i8, v32); +break; +default: +printf(invalid backdoor request\n); +abort(); +} +*eax = 0; +*ebx = 0; +*ecx = 0; +*edx = 0; +return; +} +#endif + /* test if maximum index reached */ if (index 0x8000) { if (index env-cpuid_xlevel) diff --git a/target-i386/helper.h b/target-i386/helper.h index 6b518ad..979d94e 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -217,4 +217,8 @@ DEF_HELPER_2(rclq, tl, tl, tl) DEF_HELPER_2(rcrq, tl, tl, tl) #endif +#if defined(CONFIG_BACKDOOR) +#include backdoor/helper.h +#endif + #include def-helper.h diff --git a/target-i386/translate.c b/target-i386/translate.c index 7b6e3c2..dfdc2f0 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -6941,6 +6941,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_set_cc_op(s-cc_op); gen_jmp_im(pc_start - s-cs_base); gen_helper_cpuid(); +#if defined(CONFIG_BACKDOOR) +gen_jmp_im(s-pc); +gen_eob(s); +#endif break; case 0xf4: /* hlt */ if (s-cpl != 0) {
[Qemu-devel] [PATCH v1 4/6] backdoor: declare guest-side interface macros
Header for the user to include when compiling guest applications that want to communicate with QEMU through backdoor instructions. Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- backdoor/guest.h | 33 + 1 files changed, 33 insertions(+), 0 deletions(-) create mode 100644 backdoor/guest.h diff --git a/backdoor/guest.h b/backdoor/guest.h new file mode 100644 index 000..8373762 --- /dev/null +++ b/backdoor/guest.h @@ -0,0 +1,33 @@ +/* + * Guest-side interface for instruction-based backdoor communication. + * + * Copyright (c) 2010 Lluís Vilanova vilan...@ac.upc.edu + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see http://www.gnu.org/licenses/. + */ + +#ifndef BACKDOOR__GUEST_H +#define BACKDOOR__GUEST_H + +/* Backdoor macro names define the types of its arguments: + * + * - i8: immediate of 8 bits + * - v32: value of 32 bits + */ + + +#error Undefined instruction-based backdoor interface for guest architecture + + +#endif /* BACKDOOR__GUEST_H */
[Qemu-devel] [PATCH v1 3/3] trace-instrument: handle config-time activation
Add a '--with-instrument' configuration option pointing to user-provided instrumentation callbacks. Make is invoked on the user-provided directory, which must build a static library that might contain extra code needed by the user-provided instrumentation. Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- Makefile.target | 29 ++--- configure | 30 ++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/Makefile.target b/Makefile.target index 9152723..90867e7 100644 --- a/Makefile.target +++ b/Makefile.target @@ -351,12 +351,35 @@ libbackdoor-clean: VPATH=$(VPATH) SRC_PATH=$(SRC_PATH) V=$(V) clean || true endif +# +# static instrumentation +ifdef CONFIG_INSTRUMENT +VPATH := $(VPATH):$(INSTRUMENT_PATH) + +LIBINSTRUMENT_LIB = libinstrument/libinstrument.a +LIBINSTRUMENT_CLEAN = libinstrument-clean + +libinstrument/Makefile: + $(call quiet-command, mkdir -p libinstrument, CREAT $(TARGET_DIR)$@) + $(call quiet-command, rm -f libinstrument/Makefile) + $(call quiet-command, ln -s $(INSTRUMENT_PATH)/Makefile libinstrument/Makefile) + +libinstrument/libinstrument.a: libinstrument/Makefile force + $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libinstrument \ + QEMU_CFLAGS=$(QEMU_CFLAGS) -I../target-$(TARGET_BASE_ARCH) \ + TARGET_DIR=$(TARGET_DIR)libinstrument/ VPATH=$(VPATH) \ + SRC_PATH=$(SRC_PATH) V=$(V) libinstrument.a) + +libinstrument-clean: + $(MAKE) $(SUBDIR_MAKEFLAGS) -C $(LIBINSTRUMENT_DIR) \ + VPATH=$(VPATH) SRC_PATH=$(SRC_PATH) V=$(V) clean || true +endif -$(QEMU_PROG)-prepare: $(GENERATED_HEADERS) $(LIBBACKDOOR_LIB) $(QEMU_PROG) +$(QEMU_PROG)-prepare: $(GENERATED_HEADERS) $(LIBBACKDOOR_LIB) $(LIBINSTRUMENT_LIB) $(QEMU_PROG) -$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y) $(LIBBACKDOOR_LIB) - $(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)) $(LIBBACKDOOR_LIB) +$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y) $(LIBBACKDOOR_LIB) $(LIBINSTRUMENT_LIB) + $(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)) $(LIBBACKDOOR_LIB) $(LIBINSTRUMENT_LIB) gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/feature_to_c.sh diff --git a/configure b/configure index 991f0b8..2476512 100755 --- a/configure +++ b/configure @@ -332,6 +332,7 @@ trace_backend=nop trace_file=trace spice= backdoor= +instrument= # OS specific if check_define __linux__ ; then @@ -752,6 +753,22 @@ for opt do backdoor=`readlink -f $backdoor` fi ;; + --with-instrument=*) instrument=$optarg + if test ! -f $instrument/Makefile; then + echo + echo Error: cannot make into '$instrument' + echo Please choose a directory where I can run 'make' + echo + exit 1 + elif test ! -f $instrument/trace-instrument.h; then + echo + echo Error: directory '$instrument' does not contain a \trace-instrument.h\ file + echo + exit 1 + else + instrument=`readlink -f $instrument` + fi + ;; *) echo ERROR: unknown option $opt; show_help=yes ;; esac @@ -943,6 +960,8 @@ echo --trace-file=NAMEFull PATH,NAME of file to store traces echoDefault:trace-pid echo --disable-spice disable spice echo --enable-spice enable spice +echo --with-backdoor=PATH enable backdoor communication and compile implementation in PATH +echo --with-instrument=PATH enable static instrumentation and compile user code in PATH echo echo NOTE: The object files are built at the place where configure is launched exit 1 @@ -2335,6 +2354,9 @@ echo spice support $spice if test -n $backdoor; then echo Backdoor comm.$backdoor fi +if test -n $instrument; then +echo Instrumentation $instrument +fi if test $sdl_too_old = yes; then echo - Your SDL version is too old - please upgrade to have SDL support @@ -2600,6 +2622,14 @@ if test -n $backdoor; then rm -rf *-{bsd-usr,darwin-user,linux-user,softmmu}/libbackdoor/ fi +if test -n $instrument; then + echo CONFIG_INSTRUMENT=y $config_host_mak + echo INSTRUMENT_PATH=$instrument $config_host_mak + echo TRACETOOL_EXTRA=--instrument $config_host_mak + QEMU_CFLAGS=-I$instrument $QEMU_CFLAGS + rm -rf *-{bsd-usr,darwin-user,linux-user,softmmu}/libinstrument/ +fi + # XXX: suppress that if [ $bsd = yes ] ; then echo CONFIG_BSD=y $config_host_mak
[Qemu-devel] [RFC][PATCH v1 0/3] trace-instrument: let the user wrap/override code generated from trace-events
Adds a new optional keyword (instrument) to the syntax in trace-events. When specified, this event property lets the user provide her own implementation for that tracing event. Still, in case the user only wants to wrap around the tracing event, tracetool's original implementation is accessible through function 'trace_##name##_backend', instead of the original 'trace_##name' (which now the user has to provide). The user-provided tracing functions are expected to be in the static library libinstrument.a, identified by the --with-instrument configuration parameter. TODO: * Having the 'simple' backend generate code even when the disable property is present, complicates the flow in 'tracetool'. Is this behaviour really needed? Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- Lluís Vilanova (3): trace: rewrite 'tracetool' to facilitate future extensions trace-instrument: let the user override events generated by 'tracetool' trace-instrument: handle config-time activation Makefile|4 - Makefile.target | 29 - configure | 30 + simpletrace.py |2 trace-events| 23 +++- tracetool | 336 +++ 6 files changed, 289 insertions(+), 135 deletions(-)
[Qemu-devel] [PATCH v1 6/6] backdoor: add a simple example
Provides a guest application that exercices the instruction-based backdoor communication, as well as a backdoor callback implementation that prints the guest requests. Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- .gitignore |1 + backdoor/examples/print/README | 13 backdoor/examples/print/guest/Makefile |7 ++ backdoor/examples/print/guest/test.c | 33 + backdoor/examples/print/host/Makefile | 13 backdoor/examples/print/host/printcb.c | 36 6 files changed, 103 insertions(+), 0 deletions(-) create mode 100644 backdoor/examples/print/README create mode 100644 backdoor/examples/print/guest/Makefile create mode 100644 backdoor/examples/print/guest/test.c create mode 100644 backdoor/examples/print/host/Makefile create mode 100644 backdoor/examples/print/host/printcb.c diff --git a/.gitignore b/.gitignore index a43e4d1..e4a351d 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,4 @@ pc-bios/optionrom/multiboot.bin pc-bios/optionrom/multiboot.raw .stgit-* cscope.* +backdoor/examples/print/guest/test diff --git a/backdoor/examples/print/README b/backdoor/examples/print/README new file mode 100644 index 000..0675f16 --- /dev/null +++ b/backdoor/examples/print/README @@ -0,0 +1,13 @@ +This example simply defines instruction-based backdoors to print their +arguments, along with a guest example code that makes use of backdoor +instructions. + +To compile the host (quemu) run: + /path/to/qemu/configure --with-backdoor=/path/to/qemu/backdoor/examples/print/host/ + make + +To compile the guest program run: + make -C /path/to/qemu/backdoor/examples/print/guest/ + +Now you can run it with: + /path/to/qemu/i386-linux-user/qemu-i386 /path/to/qemu/backdoor/examples/print/guest/test diff --git a/backdoor/examples/print/guest/Makefile b/backdoor/examples/print/guest/Makefile new file mode 100644 index 000..ea266f2 --- /dev/null +++ b/backdoor/examples/print/guest/Makefile @@ -0,0 +1,7 @@ +CFLAGS += -I../../../../ +PROGS = test + +all: $(PROGS) + +clean: + rm -f $(PROGS) diff --git a/backdoor/examples/print/guest/test.c b/backdoor/examples/print/guest/test.c new file mode 100644 index 000..aeae948 --- /dev/null +++ b/backdoor/examples/print/guest/test.c @@ -0,0 +1,33 @@ +/* + * Sample guest program exercising instruction-based backdoor communication. + * + * Copyright (c) 2010 Lluís Vilanova vilan...@ac.upc.edu + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see http://www.gnu.org/licenses/. + */ + +#include stdio.h + +#include backdoor/guest.h + +int main () +{ +int i = 23; +printf(i8 1\n); +BACKDOOR_i8(0x01); +printf(i8_v32 1 32\n); +BACKDOOR_i8_v32(0x01, 32); +printf(i8_v32 2 i (%d)\n, i); +BACKDOOR_i8_v32(0x02, i); +} diff --git a/backdoor/examples/print/host/Makefile b/backdoor/examples/print/host/Makefile new file mode 100644 index 000..bfd6311 --- /dev/null +++ b/backdoor/examples/print/host/Makefile @@ -0,0 +1,13 @@ +# Makefile for user-provided backdoor code + +include $(SRC_PATH)/config-host.mak +include $(SRC_PATH)/rules.mak +include $(SRC_PATH)/Makefile.objs + +objs = printcb.o + +libbackdoor.a: $(objs) + $(call quiet-command,rm -f $@ $(AR) rcs $@ $^, AR $(TARGET_DIR)$@) + +clean: + rm -f libbackdoor.a $(objs) diff --git a/backdoor/examples/print/host/printcb.c b/backdoor/examples/print/host/printcb.c new file mode 100644 index 000..60499c9 --- /dev/null +++ b/backdoor/examples/print/host/printcb.c @@ -0,0 +1,36 @@ +/* + * Sample user-defined callbacks for backdoor communication. + * + * Copyright (c) 2010 Lluís Vilanova vilan...@ac.upc.edu + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not,
[Qemu-devel] [RFC][PATCH v1 0/4] trace-gen: support for trace points in code-generation routines
Adds a new optional keyword (gen) to the syntax in trace-events. When specified, this event property will generate an extra set of functions that provide the ability to inject trace points into TCG-generated code. Note that the regular backend-dependant functions will also be generated. The extra files generated, and their functions are: - trace-helper.h Declares a 'trace_proxy_##name' TCG helper for each affected trace event. - trace-helper.c Defines a 'trace_proxy_##name' TCG helper for each affected trace event, which simply calls 'trace_##name'. Note that this scheme neatly blends with the instrument property. - trace-gen.h Defines a 'trace_gen_##name##_backend' function for each affected trace event, which handles all the (de)allocation of TCG temporaries and calls 'gen_helper_trace_proxy_##name'. If the instrument property is not present, 'trace_gen_##name' is defined as an alias. This file is instended to be included instead of trace.h for generating TCG calls to trace points. In order to fully exploit the information available during TCG code generation, trace events with the gen property can also use TCG data types (e.g., TCG_ptr), which are gracefully handled by 'tracetool' when generating the trace.h and trace.c files. TODO: * Handle TCGv_tl and target_long/target_ulong Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- Lluís Vilanova (4): trace-gen: gracefully handle TCG types in trace-events trace-gen: auto-generate TCG helper routines for tracing trace-gen: [all] include trace-helper.h on all helper.h files trace-gen: auto-generate wrappers to call TCG trace helpers .gitignore |2 Makefile | 21 ++- Makefile.target|5 - target-alpha/helper.h |2 target-arm/helper.h|2 target-cris/helper.h |2 target-i386/helper.h |2 target-m68k/helper.h |2 target-microblaze/helper.h |2 target-mips/helper.h |2 target-ppc/helper.h|2 target-sh4/helper.h|2 target-sparc/helper.h |2 trace-events |8 + tracetool | 366 +++- 15 files changed, 409 insertions(+), 13 deletions(-)
[Qemu-devel] [PATCH v1 2/3] trace-instrument: let the user override events generated by 'tracetool'
Add a new event keyword (instrument) that lets the user provide her own implementation of tracing events. Still, tracetool's original implementation is accessible through function '_trace_##name' instead of 'trace_##name' (in case the user only wants to wrap around the event). Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- Makefile |4 ++-- simpletrace.py |2 +- trace-events | 23 +-- tracetool | 23 ++- 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index fec086b..1886317 100644 --- a/Makefile +++ b/Makefile @@ -108,12 +108,12 @@ bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS) trace.h: trace.h-timestamp trace.h-timestamp: $(SRC_PATH)/trace-events config-host.mak - $(call quiet-command,sh $(SRC_PATH)/tracetool --regular --$(TRACE_BACKEND) -h $ $@, GEN trace.h) + $(call quiet-command,sh $(SRC_PATH)/tracetool $(TRACETOOL_EXTRA) --regular --$(TRACE_BACKEND) -h $ $@, GEN trace.h) @cmp -s $@ trace.h || cp $@ trace.h trace.c: trace.c-timestamp trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak - $(call quiet-command,sh $(SRC_PATH)/tracetool --regular --$(TRACE_BACKEND) -c $ $@, GEN trace.c) + $(call quiet-command,sh $(SRC_PATH)/tracetool $(TRACETOOL_EXTRA) --regular --$(TRACE_BACKEND) -c $ $@, GEN trace.c) @cmp -s $@ trace.c || cp $@ trace.c trace.o: trace.c $(GENERATED_HEADERS) diff --git a/simpletrace.py b/simpletrace.py index c2cf168..0f3fab5 100755 --- a/simpletrace.py +++ b/simpletrace.py @@ -19,7 +19,7 @@ header_version = 0 trace_fmt = '=' trace_len = struct.calcsize(trace_fmt) -event_re = re.compile(r'(disable\s+)?([a-zA-Z0-9_]+)\(([^)]*)\)\s+([^]*)') +event_re = re.compile(r'\s*(disable\s+|instrument\s+)*([a-zA-Z0-9_]+)\(([^)]*)\)\s+([^]*)') def err(msg): sys.stderr.write(msg + '\n') diff --git a/trace-events b/trace-events index 4300178..3b91a1c 100644 --- a/trace-events +++ b/trace-events @@ -12,21 +12,32 @@ # # Format of a trace event: # -# [disable] name(type1 arg1[, type2 arg2] ...) format-string +# [property ...] name(type1 arg1[, type2 arg2] ...) format-string # # Example: qemu_malloc(size_t size) size %zu # -# The disable keyword will build without the trace event. -# In case of 'simple' trace backend, it will allow the trace event to be -# compiled, but this would be turned off by default. It can be toggled on via -# the monitor. -# # The name must be a valid as a C function name. # # Types should be standard C types. Use void * for pointers because the trace # system may not have the necessary headers included. # # The format-string should be a sprintf()-compatible format string. +# +# Properties: +# +# - disable +# Build QEMU without the trace event. +# In case of using the 'simple' trace backend, it will allow the trace event +# to be compiled, but this would be turned off by default. It can be toggled +# on via the monitor. +# +# - instrument +# Let the user provide code for the trace event. +# The instrument keyword will let the user provide her own 'trace_##name' +# implementation on trace-instrument.h and libinstrument.a (their location +# is identified by the '--with-instrument' configure option). +# The original backend-specific function is still available under the name +# 'trace_##name##_backend'. # qemu-malloc.c disable qemu_malloc(size_t size, void *ptr) size %zu ptr %p diff --git a/tracetool b/tracetool index 4bd264f..facb385 100755 --- a/tracetool +++ b/tracetool @@ -349,12 +349,21 @@ traceto_h_regular() #include qemu-common.h EOF convert h $1 $2 +if [ $had_instrument = 1 ]; then +echo '#include trace-instrument.h' +fi echo #endif /* TRACE_H */ } line_h_regular() { +# XXX: should still provide instrumentation if event is disabled? local instrument +instrument=$(get_property $1 instrument) +if [ $instrument = 1 ]; then +had_instrument=1 +return +fi local api func api=$(get_api_name $1) @@ -404,12 +413,18 @@ frontend=nil backend=nil output=nil +enable_instrument=0 +had_instrument=0 + usage() { cat 2 EOF -usage: $0 frontend backend output +usage: $0 [flag] frontend backend output Generate tracing code for a file on stdin. +Flags: + --instrument Enable instrumentation + Frontends: --regular Regular frontend @@ -427,6 +442,7 @@ EOF while [ $# -gt 0 ]; do case $1 in +--instrument) enable_instrument=1 ;; --regular) frontend=${1#--} ;; --nop|--simple|--ust) backend=${1#--} ;; -h|-c) output=${1#-} ;; @@ -443,4 +459,9 @@ fi traceto_${output}_$frontend $frontend $backend +if [ $had_instrument = 1 -a $enable_instrument = 0 ]; then +echo ERROR: You must configure QEMU using '--with-instrument' to use the 'instrument' property in \trace-events\ /dev/stderr +exit 1 +fi + exit 0
[Qemu-devel] [PATCH v1 1/4] trace-gen: gracefully handle TCG types in trace-events
Some trace events with the gen property will need to use TCG arguments. As such, modify 'tracetool' to gracefully handle these types and let the backend code transliterate these types into their native counterpart. Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- tracetool | 140 ++--- 1 files changed, 132 insertions(+), 8 deletions(-) diff --git a/tracetool b/tracetool index facb385..3172259 100755 --- a/tracetool +++ b/tracetool @@ -38,13 +38,71 @@ get_api_name() echo $event } +# Convenience function to pair elements of two lists (of comma-separated values) of equal size +# $1: list +# $2: list +# $3: format (defaults to , $1 $2) +zip_lists() +{ +local format +format=$3 +[ -n $format ] || format=, %s %s + +local i elem accum +i=1 +accum= +for elem in $1; do +if [ $elem = ${elem%,} ]; then +accum=$accum $elem +else +accum=$accum ${elem%,} +eval __elem_$i=\$accum\ +i=$(($i + 1)) +accum= +fi +done +eval __elem_$i=\$accum\ + +local tmp res +accum= +res= +i=1 +for elem in $2; do +if [ $elem = ${elem%,} ]; then +accum=$accum $elem +else +accum=$accum ${elem%,} +eval tmp=\$__elem_$i +tmp=$(printf $format $tmp $accum) +res=$res$tmp +i=$(($i + 1)) +accum= +fi +done +eval tmp=\$__elem_$i +tmp=$(printf $format $tmp $elem) +res=$res$tmp + +echo $res +} + # Get the argument list of a trace event, including types and names +# If given, the second argument is a function name to map on each element of the +# comma-separated list get_args() { -local args -args=${1#*\(} -args=${args%\)*} -echo $args +if [ -z $2 ]; then +local args +args=${1#*\(} +args=${args%\)*} +echo $args +else +local argtypes argnames res +argtypes=$(get_argtypes $1 $2) +argnames=$(get_argnames $1) +res=$(zip_lists $argtypes $argnames) +echo ${res#, } +fi } # Get the argument name list of a trace event @@ -72,6 +130,60 @@ get_argnames() fi } +# Get the argument type list of a trace event +# If given, the second argument is a function name to map on each element of the +# comma-separated list +get_argtypes() +{ +if [ -z $2 ]; then +local res elem accum +res= +accum= +for elem in $(get_args $1); do +if [ ${elem} = ${elem%,} ]; then +accum=$accum $elem +else +[ $elem = ${elem#\*} ] || accum=$accum * +res=$res, $accum +accum= +fi +done +accum=${accum% *} +[ $elem = ${elem#\*} ] || accum=$accum * +res=$res, $accum +echo ${res#, } +else +local res elem accum +res= +accum= +for elem in $(get_argtypes $1); do +if [ ${elem} = ${elem%,} ]; then +accum=$accum $elem +else +accum=$accum ${elem%,} + +# trim spaces +accum=${accum## } +accum=${accum%% } +# transliterate +[ -z $2 ] || accum=$($2 $accum) + +res=$res, $accum +accum= +fi +done + +# trim spaces +accum=${accum## } +accum=${accum%% } +# transliterate +[ -z $2 ] || accum=$($2 $accum) + +res=$res, $accum +echo ${res#, } +fi +} + # Get the number of arguments to a trace event get_argc() { @@ -107,6 +219,18 @@ get_fmt() echo $fmt } +# Transliterate an argument in trace-events (raw) into its native counterpart +# (e.g., TCGv_i32 - uint32_t) +native_type() +{ +case $1 in +TCGv_i32) echo uint32_t ;; +TCGv_i64) echo uint64_t ;; +TCGv_ptr) echo void * ;; +*) echo $1 ;; +esac +} + ### Backend code @@ -120,7 +244,7 @@ line_h_nop() { local func args func=$(get_func_name $1) -args=$(get_args $1) +args=$(get_args $1 native_type) # Define an empty function for the trace event cat EOF @@ -173,7 +297,7 @@ line_h_simple() # XXX: why 'simple' backend does not expand into 'nop' when disabled? local func args argc trace_args func=$(get_func_name $1) -args=$(get_args $1) +args=$(get_args $1 native_type) argc=$(get_argc $1) trace_args=$simple_event_num @@ -267,7 +391,7 @@ line_h_ust() local name func args argnames name=$(get_event_name $1) func=$(get_func_name $1) -args=$(get_args $1) +args=$(get_args $1 native_type) argnames=$(get_argnames $1) cat EOF @@ -302,7 +426,7 @@
[Qemu-devel] [PATCH v1 1/3] trace: rewrite 'tracetool' to facilitate future extensions
Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- Makefile |4 - tracetool | 315 + 2 files changed, 194 insertions(+), 125 deletions(-) diff --git a/Makefile b/Makefile index 252c817..fec086b 100644 --- a/Makefile +++ b/Makefile @@ -108,12 +108,12 @@ bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS) trace.h: trace.h-timestamp trace.h-timestamp: $(SRC_PATH)/trace-events config-host.mak - $(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -h $ $@, GEN trace.h) + $(call quiet-command,sh $(SRC_PATH)/tracetool --regular --$(TRACE_BACKEND) -h $ $@, GEN trace.h) @cmp -s $@ trace.h || cp $@ trace.h trace.c: trace.c-timestamp trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak - $(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -c $ $@, GEN trace.c) + $(call quiet-command,sh $(SRC_PATH)/tracetool --regular --$(TRACE_BACKEND) -c $ $@, GEN trace.c) @cmp -s $@ trace.c || cp $@ trace.c trace.o: trace.c $(GENERATED_HEADERS) diff --git a/tracetool b/tracetool index 7010858..4bd264f 100755 --- a/tracetool +++ b/tracetool @@ -10,28 +10,32 @@ # Disable pathname expansion, makes processing text with '*' characters simpler set -f -usage() -{ -cat 2 EOF -usage: $0 [--nop | --simple | --ust] [-h | -c] -Generate tracing code for a file on stdin. + +### Helper routines -Backends: - --nop Tracing disabled - --simple Simple built-in backend - --ust LTTng User Space Tracing backend +# Get the name of a trace event +get_event_name() +{ +local str i last +str=${1%%\(*} +str=${str##* } +echo $str +} -Output formats: - -hGenerate .h file - -cGenerate .c file -EOF -exit 1 +# Get the name of the backend-specific function recording the trace event +get_func_name() +{ +local name +name=$(get_event_name $1) +echo trace_${name}_backend } -# Get the name of a trace event -get_name() +# Get the name of the public function recording the trace event +get_api_name() { -echo ${1%%\(*} +local event +event=trace_$(get_event_name $1) +echo $event } # Get the argument list of a trace event, including types and names @@ -79,6 +83,21 @@ get_argc() echo $argc } +# See if an event property is set (returns 1 or 0) +get_property() +{ +local i str prop +str=${1%%\(*} +prop=$2 +for i in $str; do +if [ $i = $prop ] ; then +echo 1 +return +fi +done +echo 0 +} + # Get the format string for a trace event get_fmt() { @@ -88,70 +107,60 @@ get_fmt() echo $fmt } -# Get the state of a trace event -get_state() -{ -local str disable state -str=$(get_name $1) -disable=${str##disable } -if [ $disable = $str ] ; then -state=1 -else -state=0 -fi -echo $state -} + +### Backend code -linetoh_begin_nop() +### nop -- H +begin_h_nop() { return } -linetoh_nop() +line_h_nop() { -local name args -name=$(get_name $1) +local func args +func=$(get_func_name $1) args=$(get_args $1) # Define an empty function for the trace event cat EOF -static inline void trace_$name($args) +static inline void $func($args) { } EOF } -linetoh_end_nop() +end_h_nop() { return } -linetoc_begin_nop() +### nop -- H +begin_c_nop() { return } -linetoc_nop() +line_c_nop() { -# No need for function definitions in nop backend return } -linetoc_end_nop() +end_c_nop() { return } -linetoh_begin_simple() +### simple -- H +begin_h_simple() { cat EOF #include simpletrace.h EOF - simple_event_num=0 } -cast_args_to_uint64_t() +get_trace_args_simple() { local arg for arg in $(get_argnames $1); do @@ -159,25 +168,22 @@ cast_args_to_uint64_t() done } -linetoh_simple() +line_h_simple() { -local name args argc trace_args state -name=$(get_name $1) +# XXX: why 'simple' backend does not expand into 'nop' when disabled? +local func args argc trace_args +func=$(get_func_name $1) args=$(get_args $1) argc=$(get_argc $1) -state=$(get_state $1) -if [ $state = 0 ]; then -name=${name##disable } -fi - + trace_args=$simple_event_num if [ $argc -gt 0 ] then -trace_args=$trace_args, $(cast_args_to_uint64_t $1) +trace_args=$trace_args, $(get_trace_args_simple $1) fi cat EOF -static inline void trace_$name($args) +static inline void $func($args) { trace$argc($trace_args); } @@ -186,7 +192,7 @@ EOF simple_event_num=$((simple_event_num + 1)) } -linetoh_end_simple() +end_h_simple() { cat EOF #define NR_TRACE_EVENTS $simple_event_num @@ -194,7 +200,8 @@ extern
[Qemu-devel] [PATCH v1 4/4] trace-gen: auto-generate wrappers to call TCG trace helpers
Auto-generates file trace-gen.h with instrumentable wrappers to generate calls to TCG trace helpers. Such wrappers are named 'trace_gen_##name', also reachable as 'trace_gen_##name##_backend' when instrumented. Events with the gen property are also able to use TCG types on the trace event declaration, which are gracefully handled when generating trace functions. Only trace events with the 'gen' property are affected. Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- Makefile |8 +++- trace-events |3 + tracetool| 130 ++ 3 files changed, 139 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 5975926..2831dc3 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Makefile for QEMU. -GENERATED_HEADERS = config-host.h trace.h trace-helper.h trace-helper.c +GENERATED_HEADERS = config-host.h trace.h trace-helper.h trace-helper.c trace-gen.h ifneq ($(wildcard config-host.mak),) # Put the all: rule here so that config-host.mak can contain dependencies. @@ -130,6 +130,11 @@ trace-helper.c-timestamp: $(SRC_PATH)/trace-events config-host.mak trace-helper.o: trace-helper.c $(GENERATED_HEADERS) +trace-gen.h: trace-gen.h-timestamp +trace-gen.h-timestamp: $(SRC_PATH)/trace-events config-host.mak + $(call quiet-command,sh $(SRC_PATH)/tracetool $(TRACETOOL_EXTRA) --gen --$(TRACE_BACKEND) -h $ $@, GEN trace-gen.h) + @cmp -s $@ trace-gen.h || cp $@ trace-gen.h + simpletrace.o: simpletrace.c $(GENERATED_HEADERS) version.o: $(SRC_PATH)/version.rc config-host.mak @@ -167,6 +172,7 @@ clean: rm -f qemu-img-cmds.h rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp rm -f trace-helper.c trace-helper.h trace-helper.h-timestamp trace-helper.c-timestamp + rm -f trace-gen.h-timestamp trace-gen.c-timestamp $(MAKE) -C tests clean for d in $(ALL_SUBDIRS) libhw32 libhw64 libuser libdis libdis-user; do \ if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \ diff --git a/trace-events b/trace-events index 4a89d97..a54fa03 100644 --- a/trace-events +++ b/trace-events @@ -43,6 +43,9 @@ # Provide trace events suitable for using during TCG code generation. # Generates TCG function helpers reachable through 'helper_trace_gen_##name' # which proxy their calls onto 'trace_##name'. +# As an extra aid, functions named 'trace_gen_##name' are generated into +# trace-gen.h, which can be reched through 'trace_gen_##name##_backend' when +# the event is instrumented. # qemu-malloc.c disable qemu_malloc(size_t size, void *ptr) size %zu ptr %p diff --git a/tracetool b/tracetool index 588f442..e99da0c 100755 --- a/tracetool +++ b/tracetool @@ -602,6 +602,134 @@ void helper_trace_proxy_$name($args) EOF } +### Gen - H +traceto_h_gen() +{ + cat EOF +#ifndef TRACE_GEN_H +#define TRACE_GEN_H + +/* This file is autogenerated by tracetool, do not edit. */ +EOF + +convert h $1 nil + +if [ $had_instrument = 1 ]; then +echo '#include trace-instrument.h' +fi +echo #endif /* TRACE_GEN_H */ +} + +line_h_gen_parse_pre() +{ +case $3 in +uint32_t) echo TCGv_i32 __arg_$1 = tcg_const_i32($2); ;; +uint64_t) echo TCGv_i64 __arg_$1 = tcg_const_i64($2); ;; +void *) echo TCGv_ptr __arg_$1 = tcg_const_ptr((int64_t)$2); ;; +esac +} + +line_h_gen_parse_args() +{ +case $3 in +uint64_t) echo __arg_$1 ;; +uint32_t) echo __arg_$1 ;; +void *) echo __arg_$1 ;; +*) echo $2 ;; +esac +} + +line_h_gen_parse_post() +{ +case $3 in +uint32_t) echo tcg_temp_free_i32(__arg_$1); ;; +uint64_t) echo tcg_temp_free_i64(__arg_$1); ;; +void *) echo tcg_temp_free_i64(__arg_$1); ;; +esac +} + +line_h_gen() +{ +local gen +gen=$(get_property $1 gen) +[ $gen = 1 ] || return + +local name args +name=$(get_event_name $1) +args=$(get_args $1) + +local gen_pre gen_post gen_args i +gen_pre= +gen_post= +gen_args= + +local argname +i=1 +for argname in $(get_argnames $1); do +argname=${argname%,} +eval __argname_$i=$argname +i=$(($i + 1)) +done + +local argtypes argtype accum _pre _arg _post +argtypes=$(get_argtypes $1) +i=1 +accum= +for argtype in $argtypes; do +accum=$accum ${argtype%,} +if [ $argtype = ${argtype%,} ]; then +continue +fi +argtype=${accum# } +accum= + +eval argname=\$__argname_$i + +_pre=$(line_h_gen_parse_pre $i $argname $argtype) +gen_pre=$gen_pre +$_pre +_arg=$(line_h_gen_parse_arg $i $argname $argtype) +gen_args=$gen_args$_arg +_post=$(line_h_gen_parse_post $i $argname $argtype) +gen_post=$gen_post +$_post + +i=$(($i + 1)) +done +argtype=${accum# } +eval argname=\$__argname_$i + +
[Qemu-devel] [PATCH v1 2/4] trace-gen: auto-generate TCG helper routines for tracing
Auto-generates file trace-helper.h to provide TCG helpers and trace-helper.c to proxy these helpers onto trace event routines. Only trace events with the 'gen' property are affected. Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- .gitignore |2 + Makefile| 15 Makefile.target |5 +-- trace-events|5 +++ tracetool | 98 ++- 5 files changed, 120 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index e4a351d..758f457 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ config-host.* config-target.* trace.h trace.c +trace-helper.h +trace-helper.c *-timestamp *-softmmu *-darwin-user diff --git a/Makefile b/Makefile index 1886317..5975926 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Makefile for QEMU. -GENERATED_HEADERS = config-host.h trace.h +GENERATED_HEADERS = config-host.h trace.h trace-helper.h trace-helper.c ifneq ($(wildcard config-host.mak),) # Put the all: rule here so that config-host.mak can contain dependencies. @@ -118,6 +118,18 @@ trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak trace.o: trace.c $(GENERATED_HEADERS) +trace-helper.h: trace-helper.h-timestamp +trace-helper.h-timestamp: $(SRC_PATH)/trace-events config-host.mak + $(call quiet-command,sh $(SRC_PATH)/tracetool $(TRACETOOL_EXTRA) --helper --$(TRACE_BACKEND) -h $ $@, GEN trace-helper.h) + @cmp -s $@ trace-helper.h || cp $@ trace-helper.h + +trace-helper.c: trace-helper.c-timestamp +trace-helper.c-timestamp: $(SRC_PATH)/trace-events config-host.mak + $(call quiet-command,sh $(SRC_PATH)/tracetool $(TRACETOOL_EXTRA) --helper --$(TRACE_BACKEND) -c $ $@, GEN trace-helper.c) + @cmp -s $@ trace-helper.c || cp $@ trace-helper.c + +trace-helper.o: trace-helper.c $(GENERATED_HEADERS) + simpletrace.o: simpletrace.c $(GENERATED_HEADERS) version.o: $(SRC_PATH)/version.rc config-host.mak @@ -154,6 +166,7 @@ clean: rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d rm -f qemu-img-cmds.h rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp + rm -f trace-helper.c trace-helper.h trace-helper.h-timestamp trace-helper.c-timestamp $(MAKE) -C tests clean for d in $(ALL_SUBDIRS) libhw32 libhw64 libuser libdis libdis-user; do \ if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \ diff --git a/Makefile.target b/Makefile.target index 90867e7..c7e26e2 100644 --- a/Makefile.target +++ b/Makefile.target @@ -378,9 +378,8 @@ endif $(QEMU_PROG)-prepare: $(GENERATED_HEADERS) $(LIBBACKDOOR_LIB) $(LIBINSTRUMENT_LIB) $(QEMU_PROG) -$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y) $(LIBBACKDOOR_LIB) $(LIBINSTRUMENT_LIB) - $(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)) $(LIBBACKDOOR_LIB) $(LIBINSTRUMENT_LIB) - +$(QEMU_PROG): trace-helper.o $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y) $(LIBBACKDOOR_LIB) $(LIBINSTRUMENT_LIB) + $(call LINK,trace-helper.o $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)) $(LIBBACKDOOR_LIB) $(LIBINSTRUMENT_LIB) gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/feature_to_c.sh $(call quiet-command,rm -f $@ $(SHELL) $(SRC_PATH)/feature_to_c.sh $@ $(TARGET_XML_FILES), GEN $(TARGET_DIR)$@) diff --git a/trace-events b/trace-events index 3b91a1c..4a89d97 100644 --- a/trace-events +++ b/trace-events @@ -38,6 +38,11 @@ # is identified by the '--with-instrument' configure option). # The original backend-specific function is still available under the name # 'trace_##name##_backend'. +# +# - gen +# Provide trace events suitable for using during TCG code generation. +# Generates TCG function helpers reachable through 'helper_trace_gen_##name' +# which proxy their calls onto 'trace_##name'. # qemu-malloc.c disable qemu_malloc(size_t size, void *ptr) size %zu ptr %p diff --git a/tracetool b/tracetool index 3172259..588f442 100755 --- a/tracetool +++ b/tracetool @@ -234,6 +234,38 @@ native_type() ### Backend code +### nil -- H +begin_h_nil() +{ +return +} + +line_h_nil() +{ +return +} + +end_h_nil() +{ +return +} + +### nil -- C +begin_c_nil() +{ +return +} + +line_c_nil() +{ +return +} + +end_c_nil() +{ +return +} + ### nop -- H begin_h_nop() { @@ -507,6 +539,69 @@ line_c_regular() return } +### Helper -- H +traceto_h_helper() +{ +echo /* This file is autogenerated by tracetool, do not edit. */ +convert h $1 nil +} + +helper_h_type() +{ +case $1 in +void *|TCGv_ptr) echo ptr;; +uint32_t|TCGv_i64) echo i32;; +uint64_t|TCGv_i32) echo i64;; +*) echo i64;; +esac +} + +line_h_helper() +{ +local gen +gen=$(get_property $1 gen) +[ $gen = 1 ] || return + +local name argc argtypes +
[Qemu-devel] [PATCH v1 3/4] trace-gen: [all] include trace-helper.h on all helper.h files
Signed-off-by: Lluís Vilanova vilan...@ac.upc.edu --- target-alpha/helper.h |2 ++ target-arm/helper.h|2 ++ target-cris/helper.h |2 ++ target-i386/helper.h |2 ++ target-m68k/helper.h |2 ++ target-microblaze/helper.h |2 ++ target-mips/helper.h |2 ++ target-ppc/helper.h|2 ++ target-sh4/helper.h|2 ++ target-sparc/helper.h |2 ++ 10 files changed, 20 insertions(+), 0 deletions(-) diff --git a/target-alpha/helper.h b/target-alpha/helper.h index ccf6a2a..030def3 100644 --- a/target-alpha/helper.h +++ b/target-alpha/helper.h @@ -123,4 +123,6 @@ DEF_HELPER_2(stl_c_raw, i64, i64, i64) DEF_HELPER_2(stq_c_raw, i64, i64, i64) #endif +#include trace-helper.h + #include def-helper.h diff --git a/target-arm/helper.h b/target-arm/helper.h index 0d1bc47..d3ba5d9 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -447,4 +447,6 @@ DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32) DEF_HELPER_2(set_teecr, void, env, i32) +#include trace-helper.h + #include def-helper.h diff --git a/target-cris/helper.h b/target-cris/helper.h index 093063a..620a199 100644 --- a/target-cris/helper.h +++ b/target-cris/helper.h @@ -23,4 +23,6 @@ DEF_HELPER_FLAGS_2(evaluate_flags_move_2, TCG_CALL_PURE, i32, i32, i32) DEF_HELPER_0(evaluate_flags, void) DEF_HELPER_0(top_evaluate_flags, void) +#include trace-helper.h + #include def-helper.h diff --git a/target-i386/helper.h b/target-i386/helper.h index 979d94e..94d7bd1 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -217,6 +217,8 @@ DEF_HELPER_2(rclq, tl, tl, tl) DEF_HELPER_2(rcrq, tl, tl, tl) #endif +#include trace-helper.h + #if defined(CONFIG_BACKDOOR) #include backdoor/helper.h #endif diff --git a/target-m68k/helper.h b/target-m68k/helper.h index cb8a0c7..29e206b 100644 --- a/target-m68k/helper.h +++ b/target-m68k/helper.h @@ -51,4 +51,6 @@ DEF_HELPER_3(set_mac_extu, void, env, i32, i32) DEF_HELPER_2(flush_flags, void, env, i32) DEF_HELPER_1(raise_exception, void, i32) +#include trace-helper.h + #include def-helper.h diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h index 11ad1b6..3606614 100644 --- a/target-microblaze/helper.h +++ b/target-microblaze/helper.h @@ -34,4 +34,6 @@ DEF_HELPER_2(mmu_write, void, i32, i32) DEF_HELPER_4(memalign, void, i32, i32, i32, i32) +#include trace-helper.h + #include def-helper.h diff --git a/target-mips/helper.h b/target-mips/helper.h index cb13fb2..4855b67 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -287,4 +287,6 @@ DEF_HELPER_0(rdhwr_ccres, tl) DEF_HELPER_1(pmon, void, int) DEF_HELPER_0(wait, void) +#include trace-helper.h + #include def-helper.h diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 2bf9283..c76e733 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -401,4 +401,6 @@ DEF_HELPER_2(store_601_batl, void, i32, tl) DEF_HELPER_2(store_601_batu, void, i32, tl) #endif +#include trace-helper.h + #include def-helper.h diff --git a/target-sh4/helper.h b/target-sh4/helper.h index 4b2fcdd..daec7cd 100644 --- a/target-sh4/helper.h +++ b/target-sh4/helper.h @@ -50,4 +50,6 @@ DEF_HELPER_1(fsqrt_DT, i64, i64) DEF_HELPER_1(ftrc_FT, i32, i32) DEF_HELPER_1(ftrc_DT, i32, i64) +#include trace-helper.h + #include def-helper.h diff --git a/target-sparc/helper.h b/target-sparc/helper.h index 6f103e7..f2014b8 100644 --- a/target-sparc/helper.h +++ b/target-sparc/helper.h @@ -160,4 +160,6 @@ VIS_CMPHELPER(cmpne); DEF_HELPER_0(compute_psr, void); DEF_HELPER_0(compute_C_icc, i32); +#include trace-helper.h + #include def-helper.h
Re: [Qemu-devel] [PATCH 0/3] v4 Decouple block device removal from device removal
* Michael S. Tsirkin m...@redhat.com [2010-11-03 13:03]: On Wed, Nov 03, 2010 at 12:29:10PM -0500, Ryan Harper wrote: * Markus Armbruster arm...@redhat.com [2010-11-03 11:42]: Ryan Harper ry...@us.ibm.com writes: * Michael S. Tsirkin m...@redhat.com [2010-11-03 02:22]: On Tue, Nov 02, 2010 at 03:23:38PM -0500, Ryan Harper wrote: * Michael S. Tsirkin m...@redhat.com [2010-11-02 14:18]: On Tue, Nov 02, 2010 at 02:01:08PM -0500, Ryan Harper wrote: I like the idea of disconnect; if part of the device_del method was to invoke a disconnect method, we could implement that for block, net, etc; I'd think we'd want to send the notification, then disconnect. Struggling with whether it's worth having some reasonable timeout between notification and disconnect. The problem with this is that it has no analog in real world. In real world, you can send some notifications to the guest, and you can remove the card. Tying them together is what created the problem in the first place. Timeouts can be implemented by management, maybe with a nice dialog being shown to the user. Very true. I'm fine with forcing a disconnect during the removal path prior to notification. Do we want a new disconnect method at the device level (pci)? or just use the existing removal callback and call that during the initial hotremov event? Not sure what you mean by that, but I don't see a device doing anything differently wrt surprise or ordered removal. So probably the existing callback should do. I don't think we need to talk about disconnect: since we decided we are emulating device removal, let's call it just that. Because current the removal process depends on the guest actually responding. What I'm suggesting is that, in Marcus's term, and what drive_unplug() implements, is to disconnect the host block device from the guest device to prevent any further access to it in the case the guest doesn't respond to the removal request made via ACPI. Very specifically, what we're suggesting instead of the drive_unplug() command so to complete the device removal operation without waiting for the guest to respond; that's what's going to happen if we invoke the response callback; it will appear as if the guest responded whether it did or not. What I was suggesting above was to instead of calling the callback for handing the guest response was to add a device function called disconnect which would remove any association of host resources from guest resources before we notified the guest. Thinking about it again I'm not sure this is useful, but if we're going to remove the device without the guests knowledge, I'm not sure how useful sending the removal requests via ACPI is in the first place. My feeling is that I'd like to have explicit control over the disconnect from host resources separate from the device removal *if* we're going to retain the guest notification. If we don't care to notify the guest, then we can just do device removal without notifying the guest and be done with it. I imagine management would typically want to do this: 1. notify guest 2. wait a bit 3. remove device Yes; but this argues for (1) being a separate command from (3) Yes. Long term I think we will want a way to do that. unless we require (3) to include (1) and (2) in the qemu implementation. Currently we implement: 1. device_del (attempt to remove device) 2. notify guest 3. if guest responds, remove device 4. disconnect host resource from device on destruction With my drive_unplug patch we do: 1. disconnect host resource from device This is what drive_unplug does, right? Correct. 2. device_del (attempt to remove device) 3. notify guest 4. if guest responds, remove device I think we're suggesting to instead do (if we keep disconnect as part of device_del) 1. device_del (attemp to remove device) 2. notify guest 3. invoke device destruction callback resulting in disconnect host resource from device 4. if guest responds, invoke device destruction path a second time. By response you mean eject? No, this is not what I was suggesting.