Compare commits

...

89 Commits

Author SHA1 Message Date
Anthony Liguori
a68fc29ceb Update Changelog and VERSION for 0.12.0-rc2
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-12-12 08:29:25 -06:00
Glauber Costa
0014803d23 v2: properly save kvm system time msr registers
Currently, the msrs involved in setting up pvclock are not saved over
migration and/or save/restore. This patch puts their value in special
fields in our CPUState, and deal with them using vmstate.

kvm also has to account for it, by including them in the msr list
for the ioctls.

This is a backport from qemu-kvm.git

[v2: sucessfully build without kerneldir ]

Signed-off-by: Glauber Costa <glommer@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 1a03675db1)
2009-12-12 08:17:33 -06:00
Luiz Capitulino
5118f7b47c VNC: Convert do_info_vnc() to QObject
Return a QDict with server information. Connected clients are returned
as a QList of QDicts.

The new functions (vnc_qdict_remote_addr(), vnc_qdict_local_addr() and
put_addr_qdict()) are used to insert 'host' and 'service' information
in the returned QDict.

This patch is big, but I don't see how to split it.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit d96fd29cca)
2009-12-12 08:17:33 -06:00
Luiz Capitulino
1c1d7bda2c PCI: Convert pci_device_hot_add() to QObject
Return a QDict with information about the just added device.

This commit should not change user output.

Please, note that this patch does not do error handling
conversion. In error conditions the handler still calls
monitor_printf().

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7a344f7ac7)
2009-12-12 08:17:32 -06:00
Luiz Capitulino
bdae662c94 char: Convert qemu_chr_info() to QObject
Each device is represented by a QDict. The returned QObject is a QList
of all devices.

This commit should not change user output.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 588b383201)
2009-12-12 08:17:32 -06:00
Luiz Capitulino
0108d4e323 block: Convert bdrv_info_stats() to QObject
Each device statistic information is stored in a QDict and
the returned QObject is a QList of all devices.

This commit should not change user output.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 218a536a7a)
2009-12-12 08:17:32 -06:00
Luiz Capitulino
4305793bad block: Convert bdrv_info() to QObject
Each block device information is stored in a QDict and the
returned QObject is a QList of all devices.

This commit should not change user output.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit d15e546567)
2009-12-12 08:17:32 -06:00
Luiz Capitulino
d2d51eeff0 migration: Convert do_info_migrate() to QObject
Return a QDict, which may contain up to more two QDicts, depending
on the type of migration we're performing.

IMPORTANT: as a QInt stores a int64_t integer, RAM values are going
to be stored as int64_t and not as uint64_t as they are today. If
this is a problem QInt will have to be changed.

This commit should not change user output.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit c86a668390)
2009-12-12 08:17:32 -06:00
Luiz Capitulino
3be42b28c1 monitor: Convert do_info_mice() to QObject
Each mouse is represented by a QDict, the returned QObject is a QList of
all mice.

This commit should not change user output.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit e78c48ec4e)
2009-12-12 08:17:32 -06:00
Luiz Capitulino
ee70ef8771 monitor: Convert do_info_uuid() to QObject
snprintf() is used because the UUID_FMT is too complex for
qobject_from_jsonf().

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 9603ceba2e)
2009-12-12 08:17:31 -06:00
Luiz Capitulino
5f9fe0f8d0 monitor: Convert do_info_hpet() to QObject
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 14f0720df9)
2009-12-12 08:17:31 -06:00
Luiz Capitulino
7589acc9e8 monitor: Convert do_info_name() to QObject
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit e05486cba6)
2009-12-12 08:17:31 -06:00
Luiz Capitulino
94f539bdac monitor: Convert do_info_kvm() to QObject
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 2af5ba712b)
2009-12-12 08:17:31 -06:00
Luiz Capitulino
e637fd2386 monitor: Convert do_info_status() to QObject
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit c0e8520ed5)
2009-12-12 08:17:31 -06:00
Luiz Capitulino
6e785bee32 monitor: do_info_version(): Use QDict
All 'info' commands should use QDict, this commit also kills
monitor_print_qobject() as do_info_version() doesn't use it
anymore (and no handler will).

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 45e914cfe0)
2009-12-12 08:17:31 -06:00
Luiz Capitulino
f883e4f7b8 monitor: do_info_cpus(): Use QBool
While there update the documentation as well.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 55483ad657)
2009-12-12 08:17:31 -06:00
Luiz Capitulino
5daa7bb7a4 monitor: Fix do_info_commands() output
Should return a QDict and should not print the user protocol bits
(eg. "c|cont").

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 1a728677d4)
2009-12-12 08:17:31 -06:00
Luiz Capitulino
b0a84d0525 monitor: Fix do_info_balloon() output
Monitor commands should always return values in bytes and info
commands should always return a QDict.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7f1796713e)
2009-12-12 08:17:31 -06:00
Luiz Capitulino
f1f84ba223 QDict: Introduce qdict_get_qlist()
A helper function to get a QList from a QDict.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit f2e1750803)
2009-12-12 08:17:31 -06:00
Luiz Capitulino
db830f26cb QDict: Introduce qdict_get_qbool()
This is a helper function that does type checking before retrieving
a QBool from the dictionary.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit cd4dde36ae)
2009-12-12 08:17:31 -06:00
Luiz Capitulino
61a606dade Makefile: move QObject objs to their own entry
Other subsystems will need to link against them.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 2a01000f7d)
2009-12-12 08:17:31 -06:00
Luiz Capitulino
2d95575edb Introduce qemu-objects.h header file
An easy way to include all QEMU objects.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 2471dd00ef)
2009-12-12 08:17:31 -06:00
Gerd Hoffmann
d707483ce3 vnc: fix capslock tracking logic.
The capslock tracking logic added by commit
6b1325029d doesn't work correctly for vnc
clients without EXT_KEY_EVENT support.  The reason is that qemu converts
keysyms for letters to lowercase for the keysym2scancode lookup.  It
then also passes the lowercase value down to do_key_event(), but the
capslock tracking code needs it with the correct case to work properly.

This patch adds a new variable for the lowercase keysym so we'll keep
the unmodified value for do_key_event().

The keysym2scancode is not needed with EXT_KEY_EVENT capable clients
like any app based on the gtk-vnc widget, so I missed that case in
testing ...

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 4a93fe1708)
2009-12-12 08:17:30 -06:00
Gerd Hoffmann
e2deb622c2 QemuOpts: allow larger option values.
Use case: loooooooooooooooooong file names for -drive file=...

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit d318ff9900)
2009-12-12 08:17:30 -06:00
Gerd Hoffmann
6e792a557e scsi: fix drive hotplug.
This patch fills the DriveInfo->unit after hotplugging a scsi disk.
It makes a difference when auto-assigning a scsi id, where unit was
left filled with '-1' instead of the actual scsi id.

With this patch applied the the drive naming logic in drive_init() works
as good as it did in previous releases.  Which means it works fine with
a single scsi bus.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 11f4d7f483)
2009-12-12 08:17:30 -06:00
Gerd Hoffmann
ea2138cf90 pci: don't hw_error() when no slot is available.
Current PCI code will simply hw_error() and thus abort in case no free
PCI slot is available or the requested PCI slot is already in use by
another device.  For the hotplug case this behavior is not acceptable.
This patch makes qemu pass up the error properly, so the calling code
can decide whenever it wants to exit with an error (on startup) or
whenever it wants to continue (hotplug).

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 09e3acc6cf)
2009-12-12 08:17:30 -06:00
Gerd Hoffmann
992f3cb78e pci: don't abort() when trying to hotplug with acpi off.
The PCI bus on x86 requires ACPI for hotplug support, thus disbling ACPI
also disables hotplug for the PCI bus.  This patch makes qemu check
whenever the PCI bus in question can handle hotplug before trying to add
devices.  This is needed because qdev will abort() on any attempt to
hotplug devices into a non-hotpluggable bus.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 53e0d8affe)
2009-12-12 08:17:30 -06:00
Gerd Hoffmann
828b2ff676 Set default console to virtio on S390x
All "normal" system emulation targets in qemu I'm aware of display
output on either VGA or serial output.

Our S390x virtio machine doesn't have such kind of legacy hardware. So
instead we need to default to a virtio console.

Add flags to QEMUMachine to indicate which kind of default devices make
sense for the machine in question.  Use it for S390x: enable virtcon,
disable serial, parallel and vga.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 986c5f7854)
2009-12-12 08:17:30 -06:00
Gerd Hoffmann
a231a8272c default devices: virtio consoles.
This patch adds a variable default_virtcon which says whenever a default
virtio console should be added.  It is disabled by default, followup
patch will enable it for s390.  It is cleared when qemu finds
'-virtiocon', '-device virtio-console-s390' or '-device
virtio-console-pci' on the command line.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit aee1b935c5)
2009-12-12 08:17:30 -06:00
Gerd Hoffmann
f2604b35dc add -qmp convinience switch
Acts like -monitor but switched into qmp mode.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 6ca5582d4f)
2009-12-12 08:17:30 -06:00
Gerd Hoffmann
fc05630f1f add new -mon switch
Add -mon switch which maps pretty straight forward into the QemuOpts
internal representation:

  -mon chardev=<name>[,mode=[control|readline]][,[no]default]

Via config file:

[mon]
   chardev = "<name>"
   mode = "readline"
   default = "on"

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 22a0e04b9b)
2009-12-12 08:17:30 -06:00
Gerd Hoffmann
ad960ddbce rework -monitor handling, switch to QemuOpts
This patch reworks the -monitor handling:

 - It adds a new "mon" QemuOpts list for the monitor(s).
 - It adds a monitor_parse() function to parse the -monitor switch.
 - It adds a mon_init function to initialize the monitor(s) from the
   "mon" QemuOpts list.
 - It winds up everything and removes the old bits.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 8858934370)
2009-12-12 08:17:30 -06:00
Gerd Hoffmann
239a69680c un-static qemu_chr_parse_compat()
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 33521634bf)
2009-12-12 08:17:30 -06:00
Gerd Hoffmann
f4f1df70f2 default devices: drives
Add a default_drive variable which specified whenever the default drives
(cdrom, floppy, sd) should be created.  It is cleared when the new
-nodefaults switch is specified on the command line.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit aa40fc9c96)
2009-12-12 08:17:30 -06:00
Gerd Hoffmann
782e9e6554 default devices: network
Add a default_net variable which specified whenever a default network
should be created.  It is cleared in case any -net option is specified
and it is also added to the new -nodefaults switch.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit cb4522ccf6)
2009-12-12 08:17:30 -06:00
Gerd Hoffmann
64de0113f1 default devices: add global cmd line option.
Add global command line option to disable default devices.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit d8c208dd8a)
2009-12-12 08:17:30 -06:00
Gerd Hoffmann
84db615abc default devices: vga adapter.
Qemu creates a vga display for you in case you didn't specify one on the
command line.  Right now this is tied to the '-vga <type>' command line
switch, which in turn causes trouble if you are creating your gfx card
using '-device VGA,<props>'.

This patch adds a variable default_vga which says whenever a default
serial line should be added.  It is enabled by default.  It is cleared
when qemu finds '-vga' or '-device {VGA,Cirrus VGA,QEMUware SVGA}' on
the command line.

'-device VGA' still doesn't work though due to a initialization order
issue (vga must init before calling i440fx_init_memory_mappings).

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 64465297cd)
2009-12-12 08:17:29 -06:00
Gerd Hoffmann
7c6a56cc63 zap serial_monitor_mux
The logic in this code obviously predates the multiple monitor
capability of qemu and looks increasingly silly these days.

I think the intention of this piece of code is to get a reasonable
default for the -nographic case: have monitor and serial line muxed
on stdio.

With the new default_serial and default_monitor variables we have now
doing just that became much easier ;)

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit e1c09175bc)
2009-12-12 08:17:29 -06:00
Gerd Hoffmann
a20600b917 default devices: qemu monitor.
This patch makes the monitor default device configuration work like the
default serial and parallel port devices.  It adds a variable
default_monitor which says whenever a default monitor should be added.
It is enabled by default.  It is cleared when qemu finds '-monitor' on
the command line.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit abdeed06b4)
2009-12-12 08:17:29 -06:00
Gerd Hoffmann
4986fd4111 default devices: parallel port.
Qemu creates a default parallel port for you in case you didn't specify
one on the command line.  Right now this is tied to the '-parallel
<chardev>' command line switch, which in turn causes trouble if you are
creating your parallel port via '-device isa-parallel,<props>'.

This patch adds a variable default_parallel which says whenever a default
parallel port should be added.  It is enabled by default.  It is cleared
when qemu finds '-parallel' or '-device isa-parallel' on the command line.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 6a5e8b0e31)
2009-12-12 08:17:29 -06:00
Gerd Hoffmann
96639424e2 default devices: core code & serial lines.
Qemu creates a default serial line for you in case you didn't specify
one on the command line.  Right now this is tied to the '-serial
<chardev>' command line switch, which in turn causes trouble if you are
creating your serial line via '-device isa-serial,<props>'.

This patch adds a variable default_serial which says whenever a default
serial line should be added.  It is enabled by default.  It is cleared
when qemu finds '-serial' or '-device isa-serial' on the command line.

Part of the patch is some infrastructure for the '-device $driver'
checking (default_driver_check function) which will also be used by the
other patches of this series.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 998bbd74b9)
2009-12-12 08:17:29 -06:00
Gerd Hoffmann
6ac733bf09 vc: colorize chardev title line with blue background.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 735ba58849)
2009-12-12 08:17:29 -06:00
Gerd Hoffmann
25d82d3311 chardev: move greeting into vc backend.
Make the 'vc' chardev backend print a title line with the chardev name
after initialization, using CharDriverState->label.

This replaces the banner printing code in vl.c.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 51bfa4d316)
2009-12-12 08:17:29 -06:00
Gerd Hoffmann
f9800fe5a0 Revert "Set default console to virtio on S390x"
This reverts commit 93d434b4ae.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 014100bb73)
2009-12-12 08:17:29 -06:00
Gerd Hoffmann
542d991b4c Revert "monitor: Command-line flag to enable control mode"
This reverts commit adcb181afe.

Conflicts:

	monitor.h

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 4e307fc883)
2009-12-12 08:17:29 -06:00
Gerd Hoffmann
d1d6963eba chardev: make chardevs specified in config file work.
The patch decuples the -chardev switch and the actual chardev
initialization.  Without this patch qemu ignores chardev entries
coming via -readconfig.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 1a688d3bbc)
2009-12-12 08:17:29 -06:00
Gerd Hoffmann
7058b807cd qdev: also match bus name for global properties
i.e. -global PCI.<property>=<value> will set a default property for all
PCI devices.  Also works for the compat properties used by machine
types.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 07a8de3566)
2009-12-12 08:17:29 -06:00
Gerd Hoffmann
f49d2561cb qdev: add command line option to set global defaults for properties.
This patch adds infrastructure and command line option for setting
global defaults for device properties, i.e. you can for example use

  -global virtio-blk-pci.vectors=0

to turn off msi by default for all virtio block devices.  The config
file syntax is:

[global]
  driver = "virtio-blk-pci"
  property = "vectors"
  value = "0"

This can also be used to set properties for devices which are not
created via -device but implicitly via machine init, i.e.

  -global isa-fdc,driveA=<name>

This patch uses the mechanism which configures properties for the
compatibility machine types (pc-0.10 & friends).  The command line
takes precedence over the machine type values.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit d0fef6fbea)
2009-12-12 08:17:29 -06:00
Gerd Hoffmann
a63e5f1971 qdev: make compat stuff more generic
This patch renames the compat properties into global properties and
makes them more generic.  The compatibility stuff is only one of
multiple possible users now.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 458fb6792d)
2009-12-12 08:17:29 -06:00
Jan Kiszka
ebbc8a3d8e kvm: x86: Save/restore exception_index
As KVM now makes use of exception_index to keep pending exceptions, we
have to save&restore this field as well.

NOTE: We have to nail the arch-independent exception_index down to a
certain bit width for proper vmstate processing, namely to 32 bit.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 4d6e3ac5d4)
2009-12-12 08:17:28 -06:00
Markus Armbruster
08b2d3ba9a Fix recently added QERR_ definitions
Commits c7c338c4, 41471a23, 7a046f5f and a488be27 used
lower_case_with_underscores for class values.  Existing usage
CamelCase.  ChangeToThatForConsistency.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit bd9d30640c)
2009-12-12 08:17:28 -06:00
Markus Armbruster
72fbd9f97c qdev: Replace device names containing whitespace
Device names with whitespace require quoting in the shell and in the
monitor.  Some of the offenders are also overly long.  Some have a
more convenient alias, some don't.

The place for verbose device names is DeviceInfo member desc.  The
name should be short & sweet.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 556cd09885)
2009-12-12 08:17:28 -06:00
Markus Armbruster
5b6d0419d9 qdev: Separate USB product description from qdev name
Using the qdev name for the product description makes for inconvenient
qdev names.

Put the product description in new USBDeviceInfo member product_desc.
Make usb_qdev_init() use it.  No user or guest visible change, since
the value is still the same.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 063846984c)
2009-12-12 08:17:28 -06:00
Markus Armbruster
9df9eeeb18 qdev: Rename USBDevice member devname to product_desc
It's not a device name, it's the USB product description string.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 0fe6d12e0b)
2009-12-12 08:17:28 -06:00
Gleb Natapov
5b6321a237 fix rtc-td-hack on host without high-res timers
On hosts without high-res timers it is impossible to inject rtc interrupt
faster then 1kHz. Windows sometimes configures RTC to generate 1kHz
interrupts, so we can't inject missed interrupts when running on such
hosts. Always injecting an interrupt on REG_C read is also not an option
since Windows wait for REG_C to become zero with interrupt disabled
during boot. This patch uses mixed approach: accelerate timer + inject
up to 1000 interrupts on REG_C read.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit ba32edab7f)
2009-12-12 08:17:28 -06:00
Michael S. Tsirkin
5e0c455842 virtio: verify features on load
migrating between hosts which have different features
might break silently, if the migration destination
does not support some features supported by source.

Prevent this from happening by comparing acked feature
bits with the mask supported by the device.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 6d74ca5aa8)
2009-12-12 08:17:28 -06:00
Dave Airlie
4d687b13cf vmware_vga: add rom file so that it boots.
This just adds the rom file to the vmware SVGA chipset so it boots.

Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit b3c3f123f7)
2009-12-12 08:17:28 -06:00
Anthony Liguori
d7b8193716 Do not abort on qemu_malloc(0) in production builds
qemu_malloc() does not allow size=0 to be passed in and aborts on this behavior.

Unfortunately, there is good reason to believe that within qemu, there are a
number of, so far, undetected places that assume size=0 can be safely passed.
Since we do not want to abort unnecessarily in production builds, return
qemu_malloc(1) whenever the version file indicates that this is a production
build.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 20ff6c8066)
2009-12-12 08:17:26 -06:00
Paul Brook
2e51813417 Fix ARM userspace strex implementation.
Signed-off-by: Paul Brook <paul@codesourcery.com>
2009-12-11 15:49:14 +00:00
Michael S. Tsirkin
90f445e1c9 qemu: delete rule target on error
Instruct make to remove any rule target on error. This prevetns
situation where there was an error during build but generated file still
stays behind.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7dbbbb0c9e)
2009-12-07 16:36:50 -06:00
Markus Armbruster
143d288cba QMP: add human-readable description to error response
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 77e595e7c6)
2009-12-07 16:36:50 -06:00
Markus Armbruster
13a2ccc46f monitor: convert do_getfd() to QError
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7cdfcfe18f)
2009-12-07 16:36:50 -06:00
Markus Armbruster
ea2b7d7079 QError: New QERR_TOO_MANY_FILES
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit a488be27e5)
2009-12-07 16:36:50 -06:00
Markus Armbruster
0b52786ce1 New QERR_INVALID_PARAMETER
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7a046f5f14)
2009-12-07 16:36:50 -06:00
Markus Armbruster
e36469149a QError: New QERR_FD_NOT_SUPPLIED
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 41471a2338)
2009-12-07 16:36:50 -06:00
Markus Armbruster
e5fc266be5 monitor: convert do_closefd() to QError
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 063c1a0918)
2009-12-07 16:36:50 -06:00
Markus Armbruster
3e4cd634cc QError: New QERR_FD_NOT_FOUND
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit c7c338c497)
2009-12-07 16:36:50 -06:00
Markus Armbruster
06976f82e7 monitor: convert do_change() to QObject, QError
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit ec3b82afaa)
2009-12-07 16:36:50 -06:00
Markus Armbruster
fe7c6c90a8 QError: New QERR_VNC_SERVER_FAILED
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit a6906e31a8)
2009-12-07 16:36:50 -06:00
Markus Armbruster
960a4b537a QError: New QERR_SET_PASSWD_FAILED
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7a84cb23c0)
2009-12-07 16:36:49 -06:00
Markus Armbruster
c756b1e762 QError: New QERR_INVALID_BLOCK_FORMAT
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 17901e7532)
2009-12-07 16:36:49 -06:00
Markus Armbruster
06921ec84f monitor: convert do_eject() to QError
Also affects do_change(), because the two share eject_device().

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 2c2a6bb860)
2009-12-07 16:36:49 -06:00
Markus Armbruster
8cb1cec656 QError: New QERR_DEVICE_NOT_REMOVABLE
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 5cfe026475)
2009-12-07 16:36:49 -06:00
Markus Armbruster
a46657d185 QError: New QERR_DEVICE_LOCKED
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit b086838090)
2009-12-07 16:36:49 -06:00
Markus Armbruster
28acf422cb QError: Put error definitions in alphabetical order
Also fix the odd typoe and clean up whitespace.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit e16a181222)
2009-12-07 16:36:49 -06:00
Markus Armbruster
a7d5da8857 monitor: Fix double-prompt after "change vnc passwd BLA"
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 2895e075c6)
2009-12-07 16:36:49 -06:00
Luiz Capitulino
931a548be3 monitor: do_cont(): Don't ask for passwords
The do_cont() function will ask the user to enter a password if a
device is encrypted.

This is invalid under QMP, so we raise a QERR_DEVICE_ENCRYPTED
error.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 94171e119c)
2009-12-07 16:36:49 -06:00
Luiz Capitulino
bcddbd0f6a QError: new class for device encrypted errors
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 0df37c411c)
2009-12-07 16:36:49 -06:00
Luiz Capitulino
b3dfdb5a3b monitor: Introduce 'block_passwd' command
When using encrypted disk images, QEMU will prompt the user
for passwords when started.

This makes sense for the user protocol, but doesn't for QMP.

The solution is to have Monitor command which allows the user
or a Client to set passwords in advance, so that we avoid
the prompt completely.

This is what block_passwd does, for example:

(QEMU) block_passwd ide0-hd0 foobar

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit a3a55a2edb)
2009-12-07 16:36:49 -06:00
Luiz Capitulino
6ccc51fd20 QError: Add class for invalid passwords
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit f6d855c50d)
2009-12-07 16:36:49 -06:00
Michael S. Tsirkin
0ea5709a32 pci: interrupt disable bit support
Interrupt disable bit is mandatory in PCI spec.
Implement it to make devices spec compliant.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Isaku Yamahata <yamahata@valinux.co.jp>
(cherry picked from commit b6981cb57b)
2009-12-07 16:36:49 -06:00
Michael S. Tsirkin
67a2698dac pci: interrupt status bit implementation
interrupt status is a mandatory feature in PCI spec,
so devices must implement it to be spec compliant.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Isaku Yamahata <yamahata@valinux.co.jp>
(cherry picked from commit f9bf77dd1f)
2009-12-07 16:36:48 -06:00
Michael S. Tsirkin
eea4acfa5c pci: prepare irq code for interrupt state
This rearranges code in preparation for interrupt state
implementation.
Changes:
	- split up bus walk away from interrupt handling
          into a subroutine
	- change irq_state from an array to bitmask
	- verify that irq_state values are 0 or 1 on load

There are no functional changes.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Isaku Yamahata <yamahata@valinux.co.jp>
(cherry picked from commit d036bb215e)
2009-12-07 16:36:48 -06:00
Michael S. Tsirkin
c99d32efe6 msix: function mask support
Function mask is a mandatory feature in MSIX
spec so not implementing it is a spec violation.
Implement.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 5b5cb08683)
2009-12-07 16:36:48 -06:00
Michael S. Tsirkin
9fa7591beb msix: macro rename for function mask support
rename ENABLE_OFFSET -> CONTROL_OFFSET, since
same byte includes function mask.
This is in preparation for function mask support.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 2760952ba9)
2009-12-07 16:36:48 -06:00
Andre Przywara
066263f377 cpuid: Fix multicore setup on Intel
The multicore CPUID code detects whether the guest is an Intel or an
AMD CPU, because the Linux kernel is picky about the CmpLegacy bit.
KVM by default passes through the host's vendor, which was not
catched by the code. So fork out the vendor determining bits into a
separate function to be used from both places and always get the real
vendor.
This fixes KVM's multicore setup on Intel CPUs.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
Reported-by: Dietmar Maurer <dietmar@proxmox.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 6d9fef1a02)
2009-12-07 16:36:48 -06:00
Jan Kiszka
20c1a35211 kvm: x86: Fix initial kvm_has_msr_star
KVM_GET_MSR_INDEX_LIST returns -E2BIG when the provided space is too
small for all MSRs. But this is precisely the error we trigger with the
initial request in order to obtain that size. Do not fail in that case.

This caused a subtle corruption of the guest state as MSR_STAR was not
properly saved/restored. The corruption became visible with latest kvm
optimizing the MSR updates.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 6fb6d24554)
2009-12-07 16:36:46 -06:00
Aurelien Jarno
ea6112b165 Update OpenBIOS images to r640
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
2009-12-06 13:00:22 +01:00
Anthony Liguori
e222100afe Update version to -rc1
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2009-12-05 11:22:19 -06:00
76 changed files with 2011 additions and 649 deletions

View File

@@ -1,3 +1,39 @@
version 0.12.0-rc2:
- v2: properly save kvm system time msr registers (Glauber Costa)
- convert more monitor commands to qmp (Luiz Capitulino)
- vnc: fix capslock tracking logic. (Gerd Hoffmann)
- QemuOpts: allow larger option values. (Gerd Hoffmann)
- scsi: fix drive hotplug. (Gerd Hoffmann)
- pci: don't hw_error() when no slot is available. (Gerd Hoffmann)
- pci: don't abort() when trying to hotplug with acpi off. (Gerd Hoffmann)
- allow default devices to be implemented in config file (Gerd Hoffman)
- vc: colorize chardev title line with blue background. (Gerd Hoffmann)
- chardev: make chardevs specified in config file work. (Gerd Hoffmann)
- qdev: also match bus name for global properties (Gerd Hoffmann)
- qdev: add command line option to set global defaults for properties. (Gerd Hoffmann)
- kvm: x86: Save/restore exception_index (Jan Kiszka)
- qdev: Replace device names containing whitespace (Markus Armbruster)
- fix rtc-td-hack on host without high-res timers (Gleb Natapov)
- virtio: verify features on load (Michael S. Tsirkin)
- vmware_vga: add rom file so that it boots. (Dave Airlie)
- Do not abort on qemu_malloc(0) in production builds (Anthony Liguori)
- Fix ARM userspace strex implementation. (Paul Brook)
- qemu: delete rule target on error (Michael S. Tsirkin)
- QMP: add human-readable description to error response (Markus Armbruster)
- convert more monitor commands to QError (Markus Armbruster)
- monitor: Fix double-prompt after "change vnc passwd BLA" (Markus Armbruster)
- monitor: do_cont(): Don't ask for passwords (Luiz Capitulino)
- monitor: Introduce 'block_passwd' command (Luiz Capitulino)
- pci: interrupt disable bit support (Michael S. Tsirkin)
- pci: interrupt status bit implementation (Michael S. Tsirkin)
- pci: prepare irq code for interrupt state (Michael S. Tsirkin)
- msix: function mask support (Michael S. Tsirkin)
- msix: macro rename for function mask support (Michael S. Tsirkin)
- cpuid: Fix multicore setup on Intel (Andre Przywara)
- kvm: x86: Fix initial kvm_has_msr_star (Jan Kiszka)
- Update OpenBIOS images to r640 (Aurelien Jarno)
version 0.10.2:
- fix savevm/loadvm (Anthony Liguori)

View File

@@ -81,6 +81,12 @@ ALL_SUBDIRS=$(TARGET_DIRS) $(patsubst %,pc-bios/%, $(ROMS))
recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
#######################################################################
# QObject
qobject-obj-y = qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o
qobject-obj-y += qjson.o json-lexer.o json-streamer.o json-parser.o
qobject-obj-y += qerror.o
#######################################################################
# block-obj-y is code used by both qemu system emulation and qemu-img
@@ -120,6 +126,7 @@ net-obj-y += $(addprefix net/, $(net-nested-y))
obj-y = $(block-obj-y)
obj-y += $(net-obj-y)
obj-y += $(qobject-obj-y)
obj-y += readline.o console.o
obj-y += tcg-runtime.o host-utils.o
@@ -152,8 +159,6 @@ obj-y += buffered_file.o migration.o migration-tcp.o qemu-sockets.o
obj-y += qemu-char.o aio.o savevm.o
obj-y += msmouse.o ps2.o
obj-y += qdev.o qdev-properties.o
obj-y += qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o json-lexer.o
obj-y += json-streamer.o json-parser.o qjson.o qerror.o
obj-y += qemu-config.o block-migration.o
obj-$(CONFIG_BRLAPI) += baum.o
@@ -230,18 +235,18 @@ libqemu_common.a: $(obj-y)
qemu-img.o: qemu-img-cmds.h
qemu-img$(EXESUF): qemu-img.o qemu-tool.o $(block-obj-y)
qemu-img$(EXESUF): qemu-img.o qemu-tool.o $(block-obj-y) $(qobject-obj-y)
qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o $(block-obj-y)
qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o $(block-obj-y) $(qobject-obj-y)
qemu-io$(EXESUF): qemu-io.o qemu-tool.o cmd.o $(block-obj-y)
qemu-io$(EXESUF): qemu-io.o qemu-tool.o cmd.o $(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 $@")
check-qint: check-qint.o qint.o qemu-malloc.o
check-qstring: check-qstring.o qstring.o qemu-malloc.o
check-qdict: check-qdict.o qdict.o qint.o qstring.o qemu-malloc.o
check-qdict: check-qdict.o qdict.o qint.o qstring.o qbool.o qemu-malloc.o qlist.o
check-qlist: check-qlist.o qlist.o qint.o qemu-malloc.o
check-qfloat: check-qfloat.o qfloat.o qemu-malloc.o
check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o qemu-malloc.o

View File

@@ -102,13 +102,16 @@ completed because of an error condition.
The format is:
{ "error": { "class": json-string, "data": json-value }, "id": json-value }
{ "error": { "class": json-string, "data": json-value, "desc": json-string },
"id": json-value }
Where,
- The "class" member contains the error class name (eg. "ServiceUnavailable")
- The "data" member contains specific error data and is defined in a
per-command basis, it will be an empty json-object if the error has no data
- The "desc" member is a human-readable error message. Clients should
not attempt to parse this message.
- The "id" member contains the transaction identification associated with
the command execution (if issued by the Client)

View File

@@ -1 +1 @@
0.11.50
0.11.92

233
block.c
View File

@@ -26,6 +26,7 @@
#include "monitor.h"
#include "block_int.h"
#include "module.h"
#include "qemu-objects.h"
#ifdef CONFIG_BSD
#include <sys/types.h>
@@ -1139,61 +1140,203 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
return bs->drv->bdrv_is_allocated(bs, sector_num, nb_sectors, pnum);
}
void bdrv_info(Monitor *mon)
static void bdrv_print_dict(QObject *obj, void *opaque)
{
BlockDriverState *bs;
QDict *bs_dict;
Monitor *mon = opaque;
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
monitor_printf(mon, "%s:", bs->device_name);
monitor_printf(mon, " type=");
switch(bs->type) {
case BDRV_TYPE_HD:
monitor_printf(mon, "hd");
break;
case BDRV_TYPE_CDROM:
monitor_printf(mon, "cdrom");
break;
case BDRV_TYPE_FLOPPY:
monitor_printf(mon, "floppy");
break;
}
monitor_printf(mon, " removable=%d", bs->removable);
if (bs->removable) {
monitor_printf(mon, " locked=%d", bs->locked);
}
if (bs->drv) {
monitor_printf(mon, " file=");
monitor_print_filename(mon, bs->filename);
if (bs->backing_file[0] != '\0') {
monitor_printf(mon, " backing_file=");
monitor_print_filename(mon, bs->backing_file);
}
monitor_printf(mon, " ro=%d", bs->read_only);
monitor_printf(mon, " drv=%s", bs->drv->format_name);
monitor_printf(mon, " encrypted=%d", bdrv_is_encrypted(bs));
} else {
monitor_printf(mon, " [not inserted]");
}
monitor_printf(mon, "\n");
bs_dict = qobject_to_qdict(obj);
monitor_printf(mon, "%s: type=%s removable=%d",
qdict_get_str(bs_dict, "device"),
qdict_get_str(bs_dict, "type"),
qdict_get_bool(bs_dict, "removable"));
if (qdict_get_bool(bs_dict, "removable")) {
monitor_printf(mon, " locked=%d", qdict_get_bool(bs_dict, "locked"));
}
if (qdict_haskey(bs_dict, "inserted")) {
QDict *qdict = qobject_to_qdict(qdict_get(bs_dict, "inserted"));
monitor_printf(mon, " file=");
monitor_print_filename(mon, qdict_get_str(qdict, "file"));
if (qdict_haskey(qdict, "backing_file")) {
monitor_printf(mon, " backing_file=");
monitor_print_filename(mon, qdict_get_str(qdict, "backing_file"));
}
monitor_printf(mon, " ro=%d drv=%s encrypted=%d",
qdict_get_bool(qdict, "ro"),
qdict_get_str(qdict, "drv"),
qdict_get_bool(qdict, "encrypted"));
} else {
monitor_printf(mon, " [not inserted]");
}
monitor_printf(mon, "\n");
}
/* The "info blockstats" command. */
void bdrv_info_stats(Monitor *mon)
void bdrv_info_print(Monitor *mon, const QObject *data)
{
qlist_iter(qobject_to_qlist(data), bdrv_print_dict, mon);
}
/**
* bdrv_info(): Block devices information
*
* Each block device information is stored in a QDict and the
* returned QObject is a QList of all devices.
*
* The QDict contains the following:
*
* - "device": device name
* - "type": device type
* - "removable": true if the device is removable, false otherwise
* - "locked": true if the device is locked, false otherwise
* - "inserted": only present if the device is inserted, it is a QDict
* containing the following:
* - "file": device file name
* - "ro": true if read-only, false otherwise
* - "drv": driver format name
* - "backing_file": backing file name if one is used
* - "encrypted": true if encrypted, false otherwise
*
* Example:
*
* [ { "device": "ide0-hd0", "type": "hd", "removable": false, "locked": false,
* "inserted": { "file": "/tmp/foobar", "ro": false, "drv": "qcow2" } },
* { "device": "floppy0", "type": "floppy", "removable": true,
* "locked": false } ]
*/
void bdrv_info(Monitor *mon, QObject **ret_data)
{
QList *bs_list;
BlockDriverState *bs;
bs_list = qlist_new();
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
monitor_printf(mon, "%s:"
" rd_bytes=%" PRIu64
" wr_bytes=%" PRIu64
" rd_operations=%" PRIu64
" wr_operations=%" PRIu64
"\n",
bs->device_name,
bs->rd_bytes, bs->wr_bytes,
bs->rd_ops, bs->wr_ops);
QObject *bs_obj;
const char *type = "unknown";
switch(bs->type) {
case BDRV_TYPE_HD:
type = "hd";
break;
case BDRV_TYPE_CDROM:
type = "cdrom";
break;
case BDRV_TYPE_FLOPPY:
type = "floppy";
break;
}
bs_obj = qobject_from_jsonf("{ 'device': %s, 'type': %s, "
"'removable': %i, 'locked': %i }",
bs->device_name, type, bs->removable,
bs->locked);
assert(bs_obj != NULL);
if (bs->drv) {
QObject *obj;
QDict *bs_dict = qobject_to_qdict(bs_obj);
obj = qobject_from_jsonf("{ 'file': %s, 'ro': %i, 'drv': %s, "
"'encrypted': %i }",
bs->filename, bs->read_only,
bs->drv->format_name,
bdrv_is_encrypted(bs));
assert(obj != NULL);
if (bs->backing_file[0] != '\0') {
QDict *qdict = qobject_to_qdict(obj);
qdict_put(qdict, "backing_file",
qstring_from_str(bs->backing_file));
}
qdict_put_obj(bs_dict, "inserted", obj);
}
qlist_append_obj(bs_list, bs_obj);
}
*ret_data = QOBJECT(bs_list);
}
static void bdrv_stats_iter(QObject *data, void *opaque)
{
QDict *qdict;
Monitor *mon = opaque;
qdict = qobject_to_qdict(data);
monitor_printf(mon, "%s:", qdict_get_str(qdict, "device"));
qdict = qobject_to_qdict(qdict_get(qdict, "stats"));
monitor_printf(mon, " rd_bytes=%" PRId64
" wr_bytes=%" PRId64
" rd_operations=%" PRId64
" wr_operations=%" PRId64
"\n",
qdict_get_int(qdict, "rd_bytes"),
qdict_get_int(qdict, "wr_bytes"),
qdict_get_int(qdict, "rd_operations"),
qdict_get_int(qdict, "wr_operations"));
}
void bdrv_stats_print(Monitor *mon, const QObject *data)
{
qlist_iter(qobject_to_qlist(data), bdrv_stats_iter, mon);
}
/**
* bdrv_info_stats(): show block device statistics
*
* Each device statistic information is stored in a QDict and
* the returned QObject is a QList of all devices.
*
* The QDict contains the following:
*
* - "device": device name
* - "stats": A QDict with the statistics information, it contains:
* - "rd_bytes": bytes read
* - "wr_bytes": bytes written
* - "rd_operations": read operations
* - "wr_operations": write operations
*
* Example:
*
* [ { "device": "ide0-hd0",
* "stats": { "rd_bytes": 512,
* "wr_bytes": 0,
* "rd_operations": 1,
* "wr_operations": 0 } },
* { "device": "ide1-cd0",
* "stats": { "rd_bytes": 0,
* "wr_bytes": 0,
* "rd_operations": 0,
* "wr_operations": 0 } } ]
*/
void bdrv_info_stats(Monitor *mon, QObject **ret_data)
{
QObject *obj;
QList *devices;
BlockDriverState *bs;
devices = qlist_new();
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
obj = qobject_from_jsonf("{ 'device': %s, 'stats': {"
"'rd_bytes': %" PRId64 ","
"'wr_bytes': %" PRId64 ","
"'rd_operations': %" PRId64 ","
"'wr_operations': %" PRId64
"} }",
bs->device_name,
bs->rd_bytes, bs->wr_bytes,
bs->rd_ops, bs->wr_ops);
assert(obj != NULL);
qlist_append_obj(devices, obj);
}
*ret_data = QOBJECT(devices);
}
const char *bdrv_get_encrypted_filename(BlockDriverState *bs)

View File

@@ -4,6 +4,7 @@
#include "qemu-aio.h"
#include "qemu-common.h"
#include "qemu-option.h"
#include "qobject.h"
/* block.c */
typedef struct BlockDriver BlockDriver;
@@ -45,8 +46,10 @@ typedef struct QEMUSnapshotInfo {
#define BDRV_SECTOR_SIZE (1 << BDRV_SECTOR_BITS)
#define BDRV_SECTOR_MASK ~(BDRV_SECTOR_SIZE - 1);
void bdrv_info(Monitor *mon);
void bdrv_info_stats(Monitor *mon);
void bdrv_info_print(Monitor *mon, const QObject *data);
void bdrv_info(Monitor *mon, QObject **ret_data);
void bdrv_stats_print(Monitor *mon, const QObject *data);
void bdrv_info_stats(Monitor *mon, QObject **ret_data);
void bdrv_init(void);
void bdrv_init_with_whitelist(void);

18
configure vendored
View File

@@ -256,6 +256,7 @@ blobs="yes"
pkgversion=""
check_utests="no"
user_pie="no"
zero_malloc=""
# OS specific
if check_define __linux__ ; then
@@ -1792,8 +1793,9 @@ fi
# Consult white-list to determine whether to enable werror
# by default. Only enable by default for git builds
z_version=`cut -f3 -d. $source_path/VERSION`
if test -z "$werror" ; then
z_version=`cut -f3 -d. $source_path/VERSION`
if test "$z_version" = "50" -a \
"$linux" = "yes" ; then
werror="yes"
@@ -1802,6 +1804,16 @@ if test -z "$werror" ; then
fi
fi
# Disable zero malloc errors for official releases unless explicitly told to
# enable/disable
if test -z "$zero_malloc" ; then
if test "$z_version" = "50" ; then
zero_malloc="no"
else
zero_malloc="yes"
fi
fi
if test "$werror" = "yes" ; then
QEMU_CFLAGS="-Werror $QEMU_CFLAGS"
fi
@@ -2109,6 +2121,10 @@ fi
echo "CONFIG_UNAME_RELEASE=\"$uname_release\"" >> $config_host_mak
if test "$zero_malloc" = "yes" ; then
echo "CONFIG_ZERO_MALLOC=y" >> $config_host_mak
fi
# USB host support
case "$usb" in
linux)

View File

@@ -1384,6 +1384,16 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpt
s->t_attrib = s->t_attrib_default;
text_console_resize(s);
if (chr->label) {
char msg[128];
int len;
s->t_attrib.bgcol = COLOR_BLUE;
len = snprintf(msg, sizeof(msg), "%s console\r\n", chr->label);
console_puts(chr, (uint8_t*)msg, len);
s->t_attrib = s->t_attrib_default;
}
qemu_chr_generic_open(chr);
if (chr->init)
chr->init(chr);

View File

@@ -44,7 +44,8 @@ struct MouseTransformInfo {
int a[7];
};
void do_info_mice(Monitor *mon);
void do_info_mice_print(Monitor *mon, const QObject *data);
void do_info_mice(Monitor *mon, QObject **ret_data);
void do_mouse_set(Monitor *mon, const QDict *qdict);
/* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
@@ -322,7 +323,8 @@ void vnc_display_init(DisplayState *ds);
void vnc_display_close(DisplayState *ds);
int vnc_display_open(DisplayState *ds, const char *display);
int vnc_display_password(DisplayState *ds, const char *password);
void do_info_vnc(Monitor *mon);
void do_info_vnc_print(Monitor *mon, const QObject *data);
void do_info_vnc(Monitor *mon, QObject **ret_data);
char *vnc_display_local_addr(DisplayState *ds);
/* curses.c */

View File

@@ -179,7 +179,7 @@ typedef struct CPUWatchpoint {
\
/* Core interrupt code */ \
jmp_buf jmp_env; \
int exception_index; \
int32_t exception_index; \
\
CPUState *next_cpu; /* next CPU sharing TB cache */ \
int cpu_index; /* CPU index (informative) */ \

View File

@@ -19,8 +19,12 @@ typedef struct QEMUMachine {
QEMUMachineInitFunc *init;
int use_scsi;
int max_cpus;
int no_serial:1,
no_parallel:1,
use_virtcon:1,
no_vga:1;
int is_default;
CompatProperty *compat_props;
GlobalProperty *compat_props;
struct QEMUMachine *next;
} QEMUMachine;

View File

@@ -552,7 +552,7 @@ static struct bt_device_s *bt_hid_init(struct bt_scatternet_s *net,
BT_HID_MTU, bt_hid_new_interrupt_ch);
s->usbdev = dev;
s->btdev.device.lmp_name = s->usbdev->devname;
s->btdev.device.lmp_name = s->usbdev->product_desc;
usb_hid_datain_cb(s->usbdev, s, bt_hid_datain);
s->btdev.device.handle_destroy = bt_hid_destroy;
@@ -566,6 +566,6 @@ static struct bt_device_s *bt_hid_init(struct bt_scatternet_s *net,
struct bt_device_s *bt_keyboard_init(struct bt_scatternet_s *net)
{
USBDevice *dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Keyboard");
USBDevice *dev = usb_create_simple(NULL /* FIXME */, "usb-kbd");
return bt_hid_init(net, dev, class_keyboard);
}

View File

@@ -3217,11 +3217,12 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
void pci_cirrus_vga_init(PCIBus *bus)
{
pci_create_simple(bus, -1, "Cirrus VGA");
pci_create_simple(bus, -1, "cirrus-vga");
}
static PCIDeviceInfo cirrus_vga_info = {
.qdev.name = "Cirrus VGA",
.qdev.name = "cirrus-vga",
.qdev.desc = "Cirrus CLGD 54xx VGA",
.qdev.size = sizeof(PCICirrusVGAState),
.qdev.vmsd = &vmstate_pci_cirrus_vga,
.init = pci_cirrus_vga_initfn,

View File

@@ -178,7 +178,7 @@ static PCIDeviceInfo grackle_pci_host_info = {
};
static PCIDeviceInfo dec_21154_pci_host_info = {
.qdev.name = "DEC 21154",
.qdev.name = "dec-21154",
.qdev.size = sizeof(PCIDevice),
.init = dec_21154_pci_host_init,
};
@@ -188,7 +188,7 @@ static void grackle_register_devices(void)
sysbus_register_dev("grackle", sizeof(GrackleState),
pci_grackle_init_device);
pci_qdev_register(&grackle_pci_host_info);
sysbus_register_dev("DEC 21154", sizeof(GrackleState),
sysbus_register_dev("dec-21154", sizeof(GrackleState),
pci_dec_21154_init_device);
pci_qdev_register(&dec_21154_pci_host_info);
}

View File

@@ -245,7 +245,7 @@ void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table,
{
PCIDevice *dev;
dev = pci_create(bus, -1, "CMD646 IDE");
dev = pci_create(bus, -1, "cmd646-ide");
qdev_prop_set_uint32(&dev->qdev, "secondary", secondary_ide_enabled);
qdev_init_nofail(&dev->qdev);
@@ -254,7 +254,7 @@ void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table,
static PCIDeviceInfo cmd646_ide_info[] = {
{
.qdev.name = "CMD646 IDE",
.qdev.name = "cmd646-ide",
.qdev.size = sizeof(PCIIDEState),
.init = pci_cmd646_ide_initfn,
.qdev.props = (Property[]) {

View File

@@ -161,7 +161,7 @@ void pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
{
PCIDevice *dev;
dev = pci_create_simple(bus, devfn, "PIIX3 IDE");
dev = pci_create_simple(bus, devfn, "piix3-ide");
pci_ide_create_devs(dev, hd_table);
}
@@ -171,18 +171,18 @@ void pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
{
PCIDevice *dev;
dev = pci_create_simple(bus, devfn, "PIIX4 IDE");
dev = pci_create_simple(bus, devfn, "piix4-ide");
pci_ide_create_devs(dev, hd_table);
}
static PCIDeviceInfo piix_ide_info[] = {
{
.qdev.name = "PIIX3 IDE",
.qdev.name = "piix3-ide",
.qdev.size = sizeof(PCIIDEState),
.qdev.no_user = 1,
.init = pci_piix3_ide_initfn,
},{
.qdev.name = "PIIX4 IDE",
.qdev.name = "piix4-ide",
.qdev.size = sizeof(PCIIDEState),
.qdev.no_user = 1,
.init = pci_piix4_ide_initfn,

View File

@@ -30,6 +30,8 @@
//#define DEBUG_CMOS
#define RTC_REINJECT_ON_ACK_COUNT 1000
#define RTC_SECONDS 0
#define RTC_SECONDS_ALARM 1
#define RTC_MINUTES 2
@@ -76,6 +78,7 @@ struct RTCState {
int64_t next_periodic_time;
/* second update */
int64_t next_second_time;
uint16_t irq_reinject_on_ack_count;
uint32_t irq_coalesced;
uint32_t period;
QEMUTimer *coalesced_timer;
@@ -180,6 +183,8 @@ static void rtc_periodic_timer(void *opaque)
s->cmos_data[RTC_REG_C] |= 0xc0;
#ifdef TARGET_I386
if(rtc_td_hack) {
if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
s->irq_reinject_on_ack_count = 0;
apic_reset_irq_delivered();
rtc_irq_raise(s->irq);
if (!apic_get_irq_delivered()) {
@@ -458,6 +463,18 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
case RTC_REG_C:
ret = s->cmos_data[s->cmos_index];
qemu_irq_lower(s->irq);
#ifdef TARGET_I386
if(s->irq_coalesced &&
s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
s->irq_reinject_on_ack_count++;
apic_reset_irq_delivered();
qemu_irq_raise(s->irq);
if (apic_get_irq_delivered())
s->irq_coalesced--;
break;
}
#endif
s->cmos_data[RTC_REG_C] = 0x00;
break;
default:

View File

@@ -20,6 +20,7 @@
#define PCI_MSIX_FLAGS 2 /* Table at lower 11 bits */
#define PCI_MSIX_FLAGS_QSIZE 0x7FF
#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
#define PCI_MSIX_FLAGS_MASKALL (1 << 14)
#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
/* MSI-X capability structure */
@@ -27,9 +28,10 @@
#define MSIX_PBA_OFFSET 8
#define MSIX_CAP_LENGTH 12
/* MSI enable bit is in byte 1 in FLAGS register */
#define MSIX_ENABLE_OFFSET (PCI_MSIX_FLAGS + 1)
/* MSI enable bit and maskall bit are in byte 1 in FLAGS register */
#define MSIX_CONTROL_OFFSET (PCI_MSIX_FLAGS + 1)
#define MSIX_ENABLE_MASK (PCI_MSIX_FLAGS_ENABLE >> 8)
#define MSIX_MASKALL_MASK (PCI_MSIX_FLAGS_MASKALL >> 8)
/* MSI-X table format */
#define MSIX_MSG_ADDR 0
@@ -101,22 +103,11 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries,
bar_nr);
pdev->msix_cap = config_offset;
/* Make flags bit writeable. */
pdev->wmask[config_offset + MSIX_ENABLE_OFFSET] |= MSIX_ENABLE_MASK;
pdev->wmask[config_offset + MSIX_CONTROL_OFFSET] |= MSIX_ENABLE_MASK |
MSIX_MASKALL_MASK;
return 0;
}
/* Handle MSI-X capability config write. */
void msix_write_config(PCIDevice *dev, uint32_t addr,
uint32_t val, int len)
{
unsigned enable_pos = dev->msix_cap + MSIX_ENABLE_OFFSET;
if (addr + len <= enable_pos || addr > enable_pos)
return;
if (msix_enabled(dev))
qemu_set_irq(dev->irq[0], 0);
}
static uint32_t msix_mmio_readl(void *opaque, target_phys_addr_t addr)
{
PCIDevice *dev = opaque;
@@ -157,10 +148,50 @@ static void msix_clr_pending(PCIDevice *dev, int vector)
*msix_pending_byte(dev, vector) &= ~msix_pending_mask(vector);
}
static int msix_function_masked(PCIDevice *dev)
{
return dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK;
}
static int msix_is_masked(PCIDevice *dev, int vector)
{
unsigned offset = vector * MSIX_ENTRY_SIZE + MSIX_VECTOR_CTRL;
return dev->msix_table_page[offset] & MSIX_VECTOR_MASK;
return msix_function_masked(dev) ||
dev->msix_table_page[offset] & MSIX_VECTOR_MASK;
}
static void msix_handle_mask_update(PCIDevice *dev, int vector)
{
if (!msix_is_masked(dev, vector) && msix_is_pending(dev, vector)) {
msix_clr_pending(dev, vector);
msix_notify(dev, vector);
}
}
/* Handle MSI-X capability config write. */
void msix_write_config(PCIDevice *dev, uint32_t addr,
uint32_t val, int len)
{
unsigned enable_pos = dev->msix_cap + MSIX_CONTROL_OFFSET;
int vector;
if (addr + len <= enable_pos || addr > enable_pos) {
return;
}
if (!msix_enabled(dev)) {
return;
}
qemu_set_irq(dev->irq[0], 0);
if (msix_function_masked(dev)) {
return;
}
for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
msix_handle_mask_update(dev, vector);
}
}
static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
@@ -170,10 +201,7 @@ static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3;
int vector = offset / MSIX_ENTRY_SIZE;
pci_set_long(dev->msix_table_page + offset, val);
if (!msix_is_masked(dev, vector) && msix_is_pending(dev, vector)) {
msix_clr_pending(dev, vector);
msix_notify(dev, vector);
}
msix_handle_mask_update(dev, vector);
}
static void msix_mmio_write_unallowed(void *opaque, target_phys_addr_t addr,
@@ -327,7 +355,7 @@ int msix_present(PCIDevice *dev)
int msix_enabled(PCIDevice *dev)
{
return (dev->cap_present & QEMU_PCI_CAP_MSIX) &&
(dev->config[dev->msix_cap + MSIX_ENABLE_OFFSET] &
(dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &
MSIX_ENABLE_MASK);
}
@@ -363,8 +391,8 @@ void msix_reset(PCIDevice *dev)
if (!(dev->cap_present & QEMU_PCI_CAP_MSIX))
return;
msix_free_irq_entries(dev);
dev->config[dev->msix_cap + MSIX_ENABLE_OFFSET] &=
~dev->wmask[dev->msix_cap + MSIX_ENABLE_OFFSET];
dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &=
~dev->wmask[dev->msix_cap + MSIX_CONTROL_OFFSET];
memset(dev->msix_table_page, 0, MSIX_PAGE_SIZE);
msix_mask_all(dev, dev->msix_entries_nr);
}

View File

@@ -1298,7 +1298,7 @@ static QEMUMachine pc_machine_v0_10 = {
.desc = "Standard PC, qemu 0.10",
.init = pc_init_pci,
.max_cpus = 255,
.compat_props = (CompatProperty[]) {
.compat_props = (GlobalProperty[]) {
{
.driver = "virtio-blk-pci",
.property = "class",

View File

@@ -33,6 +33,7 @@
#include "scsi.h"
#include "virtio-blk.h"
#include "qemu-config.h"
#include "qemu-objects.h"
#if defined(TARGET_I386)
static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
@@ -40,7 +41,18 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
const char *opts_str)
{
QemuOpts *opts;
int ret;
PCIBus *bus;
int ret, devfn;
bus = pci_get_bus_devfn(&devfn, devaddr);
if (!bus) {
monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
return NULL;
}
if (!((BusState*)bus)->allow_hotplug) {
monitor_printf(mon, "PCI bus doesn't support hotplug\n");
return NULL;
}
opts = qemu_opts_parse(&qemu_net_opts, opts_str ? opts_str : "", NULL);
if (!opts) {
@@ -82,6 +94,7 @@ static int scsi_hot_add(DeviceState *adapter, DriveInfo *dinfo, int printinfo)
*/
dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo, dinfo->unit);
dinfo->unit = scsidev->id;
if (printinfo)
qemu_error("OK bus %d, unit %d\n", scsibus->busnr, scsidev->id);
@@ -179,6 +192,10 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
return NULL;
}
if (!((BusState*)bus)->allow_hotplug) {
monitor_printf(mon, "PCI bus doesn't support hotplug\n");
return NULL;
}
switch (type) {
case IF_SCSI:
@@ -212,7 +229,36 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
return dev;
}
void pci_device_hot_add(Monitor *mon, const QDict *qdict)
void pci_device_hot_add_print(Monitor *mon, const QObject *data)
{
QDict *qdict;
assert(qobject_type(data) == QTYPE_QDICT);
qdict = qobject_to_qdict(data);
monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
(int) qdict_get_int(qdict, "domain"),
(int) qdict_get_int(qdict, "bus"),
(int) qdict_get_int(qdict, "slot"),
(int) qdict_get_int(qdict, "function"));
}
/**
* pci_device_hot_add(): Hot add a PCI device
*
* Return a QDict with the following device information:
*
* - "domain": domain number
* - "bus": bus number
* - "slot": slot number
* - "function": function number
*
* Example:
*
* { "domain": 0, "bus": 0, "slot": 5, "function": 0 }
*/
void pci_device_hot_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
PCIDevice *dev = NULL;
const char *pci_addr = qdict_get_str(qdict, "pci_addr");
@@ -239,9 +285,11 @@ void pci_device_hot_add(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "invalid type: %s\n", type);
if (dev) {
monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
0, pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn));
*ret_data =
qobject_from_jsonf("{ 'domain': 0, 'bus': %d, 'slot': %d, "
"'function': %d }", pci_bus_num(dev->bus),
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
assert(*ret_data != NULL);
} else
monitor_printf(mon, "failed to add %s\n", opts);
}

155
hw/pci.c
View File

@@ -103,11 +103,48 @@ static int pci_bar(PCIDevice *d, int reg)
return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
}
static inline int pci_irq_state(PCIDevice *d, int irq_num)
{
return (d->irq_state >> irq_num) & 0x1;
}
static inline void pci_set_irq_state(PCIDevice *d, int irq_num, int level)
{
d->irq_state &= ~(0x1 << irq_num);
d->irq_state |= level << irq_num;
}
static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
{
PCIBus *bus;
for (;;) {
bus = pci_dev->bus;
irq_num = bus->map_irq(pci_dev, irq_num);
if (bus->set_irq)
break;
pci_dev = bus->parent_dev;
}
bus->irq_count[irq_num] += change;
bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
}
/* Update interrupt status bit in config space on interrupt
* state change. */
static void pci_update_irq_status(PCIDevice *dev)
{
if (dev->irq_state) {
dev->config[PCI_STATUS] |= PCI_STATUS_INTERRUPT;
} else {
dev->config[PCI_STATUS] &= ~PCI_STATUS_INTERRUPT;
}
}
static void pci_device_reset(PCIDevice *dev)
{
int r;
memset(dev->irq_state, 0, sizeof dev->irq_state);
dev->irq_state = 0;
pci_update_irq_status(dev);
dev->config[PCI_COMMAND] &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER);
dev->config[PCI_CACHE_LINE_SIZE] = 0x0;
@@ -274,6 +311,43 @@ static VMStateInfo vmstate_info_pci_config = {
.put = put_pci_config_device,
};
static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
{
PCIDevice *s = container_of(pv, PCIDevice, config);
uint32_t irq_state[PCI_NUM_PINS];
int i;
for (i = 0; i < PCI_NUM_PINS; ++i) {
irq_state[i] = qemu_get_be32(f);
if (irq_state[i] != 0x1 && irq_state[i] != 0) {
fprintf(stderr, "irq state %d: must be 0 or 1.\n",
irq_state[i]);
return -EINVAL;
}
}
for (i = 0; i < PCI_NUM_PINS; ++i) {
pci_set_irq_state(s, i, irq_state[i]);
}
return 0;
}
static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size)
{
int i;
PCIDevice *s = container_of(pv, PCIDevice, config);
for (i = 0; i < PCI_NUM_PINS; ++i) {
qemu_put_be32(f, pci_irq_state(s, i));
}
}
static VMStateInfo vmstate_info_pci_irq_state = {
.name = "pci irq state",
.get = get_pci_irq_state,
.put = put_pci_irq_state,
};
const VMStateDescription vmstate_pci_device = {
.name = "PCIDevice",
.version_id = 2,
@@ -284,7 +358,9 @@ const VMStateDescription vmstate_pci_device = {
VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
vmstate_info_pci_config,
PCI_CONFIG_SPACE_SIZE),
VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2,
vmstate_info_pci_irq_state,
PCI_NUM_PINS * sizeof(int32_t)),
VMSTATE_END_OF_LIST()
}
};
@@ -299,7 +375,9 @@ const VMStateDescription vmstate_pcie_device = {
VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
vmstate_info_pci_config,
PCIE_CONFIG_SPACE_SIZE),
VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2,
vmstate_info_pci_irq_state,
PCI_NUM_PINS * sizeof(int32_t)),
VMSTATE_END_OF_LIST()
}
};
@@ -311,12 +389,23 @@ static inline const VMStateDescription *pci_get_vmstate(PCIDevice *s)
void pci_device_save(PCIDevice *s, QEMUFile *f)
{
/* Clear interrupt status bit: it is implicit
* in irq_state which we are saving.
* This makes us compatible with old devices
* which never set or clear this bit. */
s->config[PCI_STATUS] &= ~PCI_STATUS_INTERRUPT;
vmstate_save_state(f, pci_get_vmstate(s), s);
/* Restore the interrupt status bit. */
pci_update_irq_status(s);
}
int pci_device_load(PCIDevice *s, QEMUFile *f)
{
return vmstate_load_state(f, pci_get_vmstate(s), s, s->version_id);
int ret;
ret = vmstate_load_state(f, pci_get_vmstate(s), s, s->version_id);
/* Restore the interrupt status bit. */
pci_update_irq_status(s);
return ret;
}
static int pci_set_default_subsystem_id(PCIDevice *pci_dev)
@@ -429,7 +518,8 @@ static void pci_init_wmask(PCIDevice *dev)
dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
pci_set_word(dev->wmask + PCI_COMMAND,
PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
PCI_COMMAND_INTX_DISABLE);
memset(dev->wmask + PCI_CONFIG_HEADER_SIZE, 0xff,
config_size - PCI_CONFIG_HEADER_SIZE);
@@ -490,16 +580,18 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
if (!bus->devices[devfn])
goto found;
}
hw_error("PCI: no devfn available for %s, all in use\n", name);
qemu_error("PCI: no devfn available for %s, all in use\n", name);
return NULL;
found: ;
} else if (bus->devices[devfn]) {
hw_error("PCI: devfn %d not available for %s, in use by %s\n", devfn,
qemu_error("PCI: devfn %d not available for %s, in use by %s\n", devfn,
name, bus->devices[devfn]->name);
return NULL;
}
pci_dev->bus = bus;
pci_dev->devfn = devfn;
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
pci_dev->irq_state = 0;
pci_config_alloc(pci_dev);
header_type &= ~PCI_HEADER_TYPE_MULTI_FUNCTION;
@@ -535,6 +627,9 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
pci_dev = do_pci_register_device(pci_dev, bus, name, devfn,
config_read, config_write,
PCI_HEADER_TYPE_NORMAL);
if (pci_dev == NULL) {
hw_error("PCI: can't register device\n");
}
return pci_dev;
}
static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
@@ -849,6 +944,25 @@ static void pci_update_mappings(PCIDevice *d)
}
}
static inline int pci_irq_disabled(PCIDevice *d)
{
return pci_get_word(d->config + PCI_COMMAND) & PCI_COMMAND_INTX_DISABLE;
}
/* Called after interrupt disabled field update in config space,
* assert/deassert interrupts if necessary.
* Gets original interrupt disable bit value (before update). */
static void pci_update_irq_disabled(PCIDevice *d, int was_irq_disabled)
{
int i, disabled = pci_irq_disabled(d);
if (disabled == was_irq_disabled)
return;
for (i = 0; i < PCI_NUM_PINS; ++i) {
int state = pci_irq_state(d, i);
pci_change_irq_level(d, i, disabled ? -state : state);
}
}
uint32_t pci_default_read_config(PCIDevice *d,
uint32_t address, int len)
{
@@ -861,7 +975,7 @@ uint32_t pci_default_read_config(PCIDevice *d,
void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
{
int i;
int i, was_irq_disabled = pci_irq_disabled(d);
uint32_t config_size = pci_config_size(d);
for (i = 0; i < l && addr + i < config_size; val >>= 8, ++i) {
@@ -873,6 +987,9 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
ranges_overlap(addr, l, PCI_ROM_ADDRESS1, 4) ||
range_covers_byte(addr, l, PCI_COMMAND))
pci_update_mappings(d);
if (range_covers_byte(addr, l, PCI_COMMAND))
pci_update_irq_disabled(d, was_irq_disabled);
}
/***********************************************************/
@@ -882,23 +999,17 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
static void pci_set_irq(void *opaque, int irq_num, int level)
{
PCIDevice *pci_dev = opaque;
PCIBus *bus;
int change;
change = level - pci_dev->irq_state[irq_num];
change = level - pci_irq_state(pci_dev, irq_num);
if (!change)
return;
pci_dev->irq_state[irq_num] = level;
for (;;) {
bus = pci_dev->bus;
irq_num = bus->map_irq(pci_dev, irq_num);
if (bus->set_irq)
break;
pci_dev = bus->parent_dev;
}
bus->irq_count[irq_num] += change;
bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
pci_set_irq_state(pci_dev, irq_num, level);
pci_update_irq_status(pci_dev);
if (pci_irq_disabled(pci_dev))
return;
pci_change_irq_level(pci_dev, irq_num, change);
}
/***********************************************************/
@@ -1270,6 +1381,8 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
info->config_read, info->config_write,
info->header_type);
if (pci_dev == NULL)
return -1;
rc = info->init(pci_dev);
if (rc != 0)
return rc;

View File

@@ -101,7 +101,9 @@ typedef struct PCIIORegion {
#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
#define PCI_COMMAND_MASTER 0x4 /* Enable bus master */
#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
#define PCI_STATUS 0x06 /* 16 bits */
#define PCI_STATUS_INTERRUPT 0x08
#define PCI_REVISION_ID 0x08 /* 8 bits */
#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */
#define PCI_CLASS_DEVICE 0x0a /* Device class */
@@ -220,7 +222,7 @@ struct PCIDevice {
qemu_irq *irq;
/* Current IRQ levels. Used internally by the generic PCI code. */
int irq_state[PCI_NUM_PINS];
uint8_t irq_state;
/* Capability bits */
uint32_t cap_present;

View File

@@ -593,22 +593,29 @@ void qdev_prop_set_defaults(DeviceState *dev, Property *props)
}
}
static CompatProperty *compat_props;
static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
void qdev_prop_register_compat(CompatProperty *props)
void qdev_prop_register_global(GlobalProperty *prop)
{
compat_props = props;
QTAILQ_INSERT_TAIL(&global_props, prop, next);
}
void qdev_prop_set_compat(DeviceState *dev)
void qdev_prop_register_global_list(GlobalProperty *props)
{
CompatProperty *prop;
int i;
if (!compat_props) {
return;
for (i = 0; props[i].driver != NULL; i++) {
qdev_prop_register_global(props+i);
}
for (prop = compat_props; prop->driver != NULL; prop++) {
if (strcmp(dev->info->name, prop->driver) != 0) {
}
void qdev_prop_set_globals(DeviceState *dev)
{
GlobalProperty *prop;
QTAILQ_FOREACH(prop, &global_props, next) {
if (strcmp(dev->info->name, prop->driver) != 0 &&
strcmp(dev->info->bus_info->name, prop->driver) != 0) {
continue;
}
if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {

View File

@@ -103,7 +103,7 @@ DeviceState *qdev_create(BusState *bus, const char *name)
dev->parent_bus = bus;
qdev_prop_set_defaults(dev, dev->info->props);
qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
qdev_prop_set_compat(dev);
qdev_prop_set_globals(dev);
QLIST_INSERT_HEAD(&bus->children, dev, sibling);
if (qdev_hotplug) {
assert(bus->allow_hotplug);

View File

@@ -92,11 +92,12 @@ struct PropertyInfo {
int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
};
struct CompatProperty {
typedef struct GlobalProperty {
const char *driver;
const char *property;
const char *value;
};
QTAILQ_ENTRY(GlobalProperty) next;
} GlobalProperty;
/*** Board API. This should go away once we have a machine config file. ***/
@@ -256,8 +257,9 @@ void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
void qdev_prop_set_defaults(DeviceState *dev, Property *props);
void qdev_prop_register_compat(CompatProperty *props);
void qdev_prop_set_compat(DeviceState *dev);
void qdev_prop_register_global(GlobalProperty *prop);
void qdev_prop_register_global_list(GlobalProperty *props);
void qdev_prop_set_globals(DeviceState *dev);
/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
extern struct BusInfo system_bus_info;

View File

@@ -243,6 +243,10 @@ static QEMUMachine s390_machine = {
.alias = "s390",
.desc = "VirtIO based S390 machine",
.init = s390_init,
.no_serial = 1,
.no_parallel = 1,
.use_virtcon = 1.
.no_vga = 1,
.max_cpus = 255,
.is_default = 1,
};

View File

@@ -87,7 +87,7 @@ static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
break;
case SYBORG_VIRTIO_HOST_FEATURES:
ret = vdev->get_features(vdev);
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
ret |= vdev->binding->get_features(s);
break;
case SYBORG_VIRTIO_GUEST_FEATURES:
ret = vdev->features;
@@ -242,8 +242,16 @@ static void syborg_virtio_update_irq(void *opaque, uint16_t vector)
qemu_set_irq(proxy->irq, level != 0);
}
static unsigned syborg_virtio_get_features(void *opaque)
{
unsigned ret = 0;
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
return ret;
}
static VirtIOBindings syborg_virtio_bindings = {
.notify = syborg_virtio_update_irq
.notify = syborg_virtio_update_irq,
.get_features = syborg_virtio_get_features,
};
static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)

View File

@@ -148,7 +148,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
/* Use values found on a real PowerMac */
/* Uninorth main bus */
dev = qdev_create(NULL, "Uni-north main");
dev = qdev_create(NULL, "uni-north-main");
qdev_init_nofail(dev);
s = sysbus_from_qdev(dev);
d = FROM_SYSBUS(UNINState, s);
@@ -157,7 +157,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
pic, 11 << 3, 4);
#if 0
pci_create_simple(d->host_state.bus, 11 << 3, "Uni-north main");
pci_create_simple(d->host_state.bus, 11 << 3, "uni-north-main");
#endif
sysbus_mmio_map(s, 0, 0xf2800000);
@@ -166,12 +166,12 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
/* DEC 21154 bridge */
#if 0
/* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
pci_create_simple(d->host_state.bus, 12 << 3, "DEC 21154");
pci_create_simple(d->host_state.bus, 12 << 3, "dec-21154");
#endif
/* Uninorth AGP bus */
pci_create_simple(d->host_state.bus, 11 << 3, "Uni-north AGP");
dev = qdev_create(NULL, "Uni-north AGP");
pci_create_simple(d->host_state.bus, 11 << 3, "uni-north-AGP");
dev = qdev_create(NULL, "uni-north-AGP");
qdev_init_nofail(dev);
s = sysbus_from_qdev(dev);
sysbus_mmio_map(s, 0, 0xf0800000);
@@ -180,8 +180,8 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
/* Uninorth internal bus */
#if 0
/* XXX: not needed for now */
pci_create_simple(d->host_state.bus, 14 << 3, "Uni-north internal");
dev = qdev_create(NULL, "Uni-north internal");
pci_create_simple(d->host_state.bus, 14 << 3, "uni-north-internal");
dev = qdev_create(NULL, "uni-north-internal");
qdev_init_nofail(dev);
s = sysbus_from_qdev(dev);
sysbus_mmio_map(s, 0, 0xf4800000);
@@ -260,41 +260,41 @@ static int unin_internal_pci_host_init(PCIDevice *d)
}
static PCIDeviceInfo unin_main_pci_host_info = {
.qdev.name = "Uni-north main",
.qdev.name = "uni-north-main",
.qdev.size = sizeof(PCIDevice),
.init = unin_main_pci_host_init,
};
static PCIDeviceInfo dec_21154_pci_host_info = {
.qdev.name = "DEC 21154",
.qdev.name = "dec-21154",
.qdev.size = sizeof(PCIDevice),
.init = dec_21154_pci_host_init,
};
static PCIDeviceInfo unin_agp_pci_host_info = {
.qdev.name = "Uni-north AGP",
.qdev.name = "uni-north-AGP",
.qdev.size = sizeof(PCIDevice),
.init = unin_agp_pci_host_init,
};
static PCIDeviceInfo unin_internal_pci_host_info = {
.qdev.name = "Uni-north internal",
.qdev.name = "uni-north-internal",
.qdev.size = sizeof(PCIDevice),
.init = unin_internal_pci_host_init,
};
static void unin_register_devices(void)
{
sysbus_register_dev("Uni-north main", sizeof(UNINState),
sysbus_register_dev("uni-north-main", sizeof(UNINState),
pci_unin_main_init_device);
pci_qdev_register(&unin_main_pci_host_info);
sysbus_register_dev("DEC 21154", sizeof(UNINState),
sysbus_register_dev("dec-21154", sizeof(UNINState),
pci_dec_21154_init_device);
pci_qdev_register(&dec_21154_pci_host_info);
sysbus_register_dev("Uni-north AGP", sizeof(UNINState),
sysbus_register_dev("uni-north-AGP", sizeof(UNINState),
pci_unin_agp_init_device);
pci_qdev_register(&unin_agp_pci_host_info);
sysbus_register_dev("Uni-north internal", sizeof(UNINState),
sysbus_register_dev("uni-north-internal", sizeof(UNINState),
pci_unin_internal_init_device);
pci_qdev_register(&unin_internal_pci_host_info);
}

View File

@@ -630,7 +630,7 @@ USBDevice *usb_bt_init(HCIInfo *hci)
if (!hci)
return NULL;
dev = usb_create_simple(NULL /* FIXME */, "QEMU BT dongle");
dev = usb_create_simple(NULL /* FIXME */, "usb-bt-dongle");
s = DO_UPCAST(struct USBBtState, dev, dev);
s->dev.opaque = s;
@@ -645,7 +645,8 @@ USBDevice *usb_bt_init(HCIInfo *hci)
}
static struct USBDeviceInfo bt_info = {
.qdev.name = "QEMU BT dongle",
.product_desc = "QEMU BT dongle",
.qdev.name = "usb-bt-dongle",
.qdev.size = sizeof(struct USBBtState),
.init = usb_bt_initfn,
.handle_packet = usb_generic_handle_packet,

View File

@@ -43,7 +43,7 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
USBDeviceInfo *info = DO_UPCAST(USBDeviceInfo, qdev, base);
int rc;
pstrcpy(dev->devname, sizeof(dev->devname), qdev->info->name);
pstrcpy(dev->product_desc, sizeof(dev->product_desc), info->product_desc);
dev->info = info;
dev->auto_attach = 1;
rc = dev->info->init(dev);
@@ -131,7 +131,7 @@ static void do_attach(USBDevice *dev)
if (dev->attached) {
fprintf(stderr, "Warning: tried to attach usb device %s twice\n",
dev->devname);
dev->product_desc);
return;
}
dev->attached++;
@@ -153,7 +153,7 @@ int usb_device_attach(USBDevice *dev)
if (bus->nfree == 1) {
/* Create a new hub and chain it on. */
hub = usb_create_simple(bus, "QEMU USB Hub");
hub = usb_create_simple(bus, "usb-hub");
}
do_attach(dev);
return 0;
@@ -166,7 +166,7 @@ int usb_device_detach(USBDevice *dev)
if (!dev->attached) {
fprintf(stderr, "Warning: tried to detach unattached usb device %s\n",
dev->devname);
dev->product_desc);
return -1;
}
dev->attached--;
@@ -228,7 +228,7 @@ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
monitor_printf(mon, "%*saddr %d.%d, speed %s, name %s%s\n",
indent, "", bus->busnr, dev->addr,
usb_speed(dev->speed), dev->devname,
usb_speed(dev->speed), dev->product_desc,
dev->attached ? ", attached" : "");
}
@@ -249,7 +249,8 @@ void usb_info(Monitor *mon)
if (!dev)
continue;
monitor_printf(mon, " Device %d.%d, Speed %s Mb/s, Product %s\n",
bus->busnr, dev->addr, usb_speed(dev->speed), dev->devname);
bus->busnr, dev->addr, usb_speed(dev->speed),
dev->product_desc);
}
}
}

View File

@@ -701,7 +701,7 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
break;
case 2:
/* product description */
ret = set_usb_string(data, s->dev.devname);
ret = set_usb_string(data, s->dev.product_desc);
break;
case 3:
/* vendor description */
@@ -880,8 +880,8 @@ void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
static struct USBDeviceInfo hid_info[] = {
{
.qdev.name = "QEMU USB Tablet",
.qdev.alias = "usb-tablet",
.product_desc = "QEMU USB Tablet",
.qdev.name = "usb-tablet",
.usbdevice_name = "tablet",
.qdev.size = sizeof(USBHIDState),
.init = usb_tablet_initfn,
@@ -891,8 +891,8 @@ static struct USBDeviceInfo hid_info[] = {
.handle_data = usb_hid_handle_data,
.handle_destroy = usb_hid_handle_destroy,
},{
.qdev.name = "QEMU USB Mouse",
.qdev.alias = "usb-mouse",
.product_desc = "QEMU USB Mouse",
.qdev.name = "usb-mouse",
.usbdevice_name = "mouse",
.qdev.size = sizeof(USBHIDState),
.init = usb_mouse_initfn,
@@ -902,8 +902,8 @@ static struct USBDeviceInfo hid_info[] = {
.handle_data = usb_hid_handle_data,
.handle_destroy = usb_hid_handle_destroy,
},{
.qdev.name = "QEMU USB Keyboard",
.qdev.alias = "usb-kbd",
.product_desc = "QEMU USB Keyboard",
.qdev.name = "usb-kbd",
.usbdevice_name = "keyboard",
.qdev.size = sizeof(USBHIDState),
.init = usb_keyboard_initfn,

View File

@@ -544,7 +544,8 @@ static int usb_hub_initfn(USBDevice *dev)
}
static struct USBDeviceInfo hub_info = {
.qdev.name = "QEMU USB Hub",
.product_desc = "QEMU USB Hub",
.qdev.name = "usb-hub",
.qdev.size = sizeof(USBHubState),
.init = usb_hub_initfn,
.handle_packet = usb_hub_handle_packet,

View File

@@ -591,7 +591,7 @@ static USBDevice *usb_msd_init(const char *filename)
}
/* create guest device */
dev = usb_create(NULL /* FIXME */, "QEMU USB MSD");
dev = usb_create(NULL /* FIXME */, "usb-storage");
qdev_prop_set_drive(&dev->qdev, "drive", dinfo);
if (qdev_init(&dev->qdev) < 0)
return NULL;
@@ -600,8 +600,8 @@ static USBDevice *usb_msd_init(const char *filename)
}
static struct USBDeviceInfo msd_info = {
.qdev.name = "QEMU USB MSD",
.qdev.alias = "usb-storage",
.product_desc = "QEMU USB MSD",
.qdev.name = "usb-storage",
.qdev.size = sizeof(MSDState),
.init = usb_msd_initfn,
.handle_packet = usb_generic_handle_packet,

View File

@@ -1463,7 +1463,7 @@ USBDevice *usb_net_init(NICInfo *nd)
USBDevice *dev;
USBNetState *s;
dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Network Interface");
dev = usb_create_simple(NULL /* FIXME */, "usb-net");
s = DO_UPCAST(USBNetState, dev, dev);
memcpy(s->conf.macaddr.a, nd->macaddr, sizeof(nd->macaddr));
@@ -1487,7 +1487,8 @@ USBDevice *usb_net_init(NICInfo *nd)
}
static struct USBDeviceInfo net_info = {
.qdev.name = "QEMU USB Network Interface",
.product_desc = "QEMU USB Network Interface",
.qdev.name = "usb-net",
.qdev.size = sizeof(USBNetState),
.init = usb_net_initfn,
.handle_packet = usb_generic_handle_packet,

View File

@@ -1736,7 +1736,7 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev)
void usb_ohci_init_pci(struct PCIBus *bus, int devfn)
{
pci_create_simple(bus, devfn, "OHCI USB PCI");
pci_create_simple(bus, devfn, "pci-ohci");
}
void usb_ohci_init_pxa(target_phys_addr_t base, int num_ports, int devfn,
@@ -1762,8 +1762,7 @@ void usb_ohci_init_sm501(uint32_t mmio_base, uint32_t localmem_base,
}
static PCIDeviceInfo ohci_info = {
.qdev.name = "OHCI USB PCI",
.qdev.alias = "pci-ohci",
.qdev.name = "pci-ohci",
.qdev.desc = "Apple USB Controller",
.qdev.size = sizeof(OHCIPCIState),
.init = usb_ohci_initfn_pci,

View File

@@ -577,7 +577,7 @@ static USBDevice *usb_serial_init(const char *filename)
if (!cdrv)
return NULL;
dev = usb_create(NULL /* FIXME */, "QEMU USB Serial");
dev = usb_create(NULL /* FIXME */, "usb-serial");
qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
if (vendorid)
qdev_prop_set_uint16(&dev->qdev, "vendorid", vendorid);
@@ -597,7 +597,7 @@ static USBDevice *usb_braille_init(const char *unused)
if (!cdrv)
return NULL;
dev = usb_create(NULL /* FIXME */, "QEMU USB Braille");
dev = usb_create(NULL /* FIXME */, "usb-braille");
qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
qdev_init(&dev->qdev);
@@ -605,8 +605,8 @@ static USBDevice *usb_braille_init(const char *unused)
}
static struct USBDeviceInfo serial_info = {
.qdev.name = "QEMU USB Serial",
.qdev.alias = "usb-serial",
.product_desc = "QEMU USB Serial",
.qdev.name = "usb-serial",
.qdev.size = sizeof(USBSerialState),
.init = usb_serial_initfn,
.handle_packet = usb_generic_handle_packet,
@@ -625,8 +625,8 @@ static struct USBDeviceInfo serial_info = {
};
static struct USBDeviceInfo braille_info = {
.qdev.name = "QEMU USB Braille",
.qdev.alias = "usb-braille",
.product_desc = "QEMU USB Braille",
.qdev.name = "usb-braille",
.qdev.size = sizeof(USBSerialState),
.init = usb_serial_initfn,
.handle_packet = usb_generic_handle_packet,

View File

@@ -1111,12 +1111,12 @@ static int usb_uhci_piix4_initfn(PCIDevice *dev)
static PCIDeviceInfo uhci_info[] = {
{
.qdev.name = "PIIX3 USB-UHCI",
.qdev.name = "piix3-usb-uhci",
.qdev.size = sizeof(UHCIState),
.qdev.vmsd = &vmstate_uhci,
.init = usb_uhci_piix3_initfn,
},{
.qdev.name = "PIIX4 USB-UHCI",
.qdev.name = "piix4-usb-uhci",
.qdev.size = sizeof(UHCIState),
.qdev.vmsd = &vmstate_uhci,
.init = usb_uhci_piix4_initfn,
@@ -1133,10 +1133,10 @@ device_init(uhci_register);
void usb_uhci_piix3_init(PCIBus *bus, int devfn)
{
pci_create_simple(bus, devfn, "PIIX3 USB-UHCI");
pci_create_simple(bus, devfn, "piix3-usb-uhci");
}
void usb_uhci_piix4_init(PCIBus *bus, int devfn)
{
pci_create_simple(bus, devfn, "PIIX4 USB-UHCI");
pci_create_simple(bus, devfn, "piix4-usb-uhci");
}

View File

@@ -409,8 +409,9 @@ static int usb_wacom_initfn(USBDevice *dev)
}
static struct USBDeviceInfo wacom_info = {
.qdev.name = "QEMU PenPartner Tablet",
.qdev.alias = "wacom-tablet",
.product_desc = "QEMU PenPartner Tablet",
.qdev.name = "usb-wacom-tablet",
.qdev.desc = "QEMU PenPartner Tablet",
.usbdevice_name = "wacom-tablet",
.qdev.size = sizeof(USBWacomState),
.init = usb_wacom_initfn,

View File

@@ -132,7 +132,7 @@ struct USBDevice {
int speed;
uint8_t addr;
char devname[32];
char product_desc[32];
int auto_attach;
int attached;
@@ -185,6 +185,8 @@ struct USBDeviceInfo {
*/
int (*handle_data)(USBDevice *dev, USBPacket *p);
const char *product_desc;
/* handle legacy -usbdevice command line options */
const char *usbdevice_name;
USBDevice *(*usbdevice_init)(const char *params);

View File

@@ -236,9 +236,7 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
switch (addr) {
case VIRTIO_PCI_HOST_FEATURES:
ret = vdev->get_features(vdev);
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
ret |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
ret |= (1 << VIRTIO_F_BAD_FEATURE);
ret |= vdev->binding->get_features(proxy);
break;
case VIRTIO_PCI_GUEST_FEATURES:
ret = vdev->features;
@@ -382,12 +380,22 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
msix_write_config(pci_dev, address, val, len);
}
static unsigned virtio_pci_get_features(void *opaque)
{
unsigned ret = 0;
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
ret |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
ret |= (1 << VIRTIO_F_BAD_FEATURE);
return ret;
}
static const VirtIOBindings virtio_pci_bindings = {
.notify = virtio_pci_notify,
.save_config = virtio_pci_save_config,
.load_config = virtio_pci_load_config,
.save_queue = virtio_pci_save_queue,
.load_queue = virtio_pci_load_queue,
.get_features = virtio_pci_get_features,
};
static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,

View File

@@ -651,6 +651,9 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
int virtio_load(VirtIODevice *vdev, QEMUFile *f)
{
int num, i, ret;
uint32_t features;
uint32_t supported_features = vdev->get_features(vdev) |
vdev->binding->get_features(vdev->binding_opaque);
if (vdev->binding->load_config) {
ret = vdev->binding->load_config(vdev->binding_opaque, f);
@@ -661,7 +664,13 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
qemu_get_8s(f, &vdev->status);
qemu_get_8s(f, &vdev->isr);
qemu_get_be16s(f, &vdev->queue_sel);
qemu_get_be32s(f, &vdev->features);
qemu_get_be32s(f, &features);
if (features & ~supported_features) {
fprintf(stderr, "Features 0x%x unsupported. Allowed features: 0x%x\n",
features, supported_features);
return -1;
}
vdev->features = features;
vdev->config_len = qemu_get_be32(f);
qemu_get_buffer(f, vdev->config, vdev->config_len);

View File

@@ -31,6 +31,11 @@
/* We've given up on this device. */
#define VIRTIO_CONFIG_S_FAILED 0x80
/* Some virtio feature bits (currently bits 28 through 31) are reserved for the
* transport being used (eg. virtio_ring), the rest are per-device feature bits. */
#define VIRTIO_TRANSPORT_F_START 28
#define VIRTIO_TRANSPORT_F_END 32
/* We notify when the ring is completely used, even if the guest is suppressing
* callbacks */
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
@@ -82,6 +87,7 @@ typedef struct {
void (*save_queue)(void * opaque, int n, QEMUFile *f);
int (*load_config)(void * opaque, QEMUFile *f);
int (*load_queue)(void * opaque, int n, QEMUFile *f);
unsigned (*get_features)(void * opaque);
} VirtIOBindings;
#define VIRTIO_PCI_QUEUE_MAX 16

View File

@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
#include "hw.h"
#include "loader.h"
#include "console.h"
#include "pci.h"
#include "vmware_vga.h"
@@ -1124,6 +1125,7 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
vga_ram_size, s->vga.vram_offset);
#endif
rom_add_vga(VGABIOS_FILENAME);
}
static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
@@ -1194,11 +1196,11 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
void pci_vmsvga_init(PCIBus *bus)
{
pci_create_simple(bus, -1, "QEMUware SVGA");
pci_create_simple(bus, -1, "vmware-svga");
}
static PCIDeviceInfo vmsvga_info = {
.qdev.name = "QEMUware SVGA",
.qdev.name = "vmware-svga",
.qdev.size = sizeof(struct pci_vmsvga_state_s),
.qdev.vmsd = &vmstate_vmware_vga,
.init = pci_vmsvga_initfn,

View File

@@ -593,6 +593,7 @@ static int do_strex(CPUARMState *env)
}
rc = 0;
fail:
env->regs[15] += 4;
env->regs[(env->exclusive_info >> 4) & 0xf] = rc;
done:
end_exclusive();

View File

@@ -19,6 +19,7 @@
#include "block.h"
#include "qemu_socket.h"
#include "block-migration.h"
#include "qemu-objects.h"
//#define DEBUG_MIGRATION
@@ -163,37 +164,123 @@ void do_migrate_set_downtime(Monitor *mon, const QDict *qdict)
max_downtime = (uint64_t)d;
}
void do_info_migrate(Monitor *mon)
static void migrate_print_status(Monitor *mon, const char *name,
const QDict *status_dict)
{
QDict *qdict;
qdict = qobject_to_qdict(qdict_get(status_dict, name));
monitor_printf(mon, "transferred %s: %" PRIu64 " kbytes\n", name,
qdict_get_int(qdict, "transferred") >> 10);
monitor_printf(mon, "remaining %s: %" PRIu64 " kbytes\n", name,
qdict_get_int(qdict, "remaining") >> 10);
monitor_printf(mon, "total %s: %" PRIu64 " kbytes\n", name,
qdict_get_int(qdict, "total") >> 10);
}
void do_info_migrate_print(Monitor *mon, const QObject *data)
{
QDict *qdict;
qdict = qobject_to_qdict(data);
monitor_printf(mon, "Migration status: %s\n",
qdict_get_str(qdict, "status"));
if (qdict_haskey(qdict, "ram")) {
migrate_print_status(mon, "ram", qdict);
}
if (qdict_haskey(qdict, "disk")) {
migrate_print_status(mon, "disk", qdict);
}
}
static void migrate_put_status(QDict *qdict, const char *name,
uint64_t trans, uint64_t rem, uint64_t total)
{
QObject *obj;
obj = qobject_from_jsonf("{ 'transferred': %" PRId64 ", "
"'remaining': %" PRId64 ", "
"'total': %" PRId64 " }", trans, rem, total);
assert(obj != NULL);
qdict_put_obj(qdict, name, obj);
}
/**
* do_info_migrate(): Migration status
*
* Return a QDict. If migration is active there will be another
* QDict with RAM migration status and if block migration is active
* another one with block migration status.
*
* The main QDict contains the following:
*
* - "status": migration status
* - "ram": only present if "status" is "active", it is a QDict with the
* following RAM information (in bytes):
* - "transferred": amount transferred
* - "remaining": amount remaining
* - "total": total
* - "disk": only present if "status" is "active" and it is a block migration,
* it is a QDict with the following disk information (in bytes):
* - "transferred": amount transferred
* - "remaining": amount remaining
* - "total": total
*
* Examples:
*
* 1. Migration is "completed":
*
* { "status": "completed" }
*
* 2. Migration is "active" and it is not a block migration:
*
* { "status": "active",
* "ram": { "transferred": 123, "remaining": 123, "total": 246 } }
*
* 3. Migration is "active" and it is a block migration:
*
* { "status": "active",
* "ram": { "total": 1057024, "remaining": 1053304, "transferred": 3720 },
* "disk": { "total": 20971520, "remaining": 20880384, "transferred": 91136 }}
*/
void do_info_migrate(Monitor *mon, QObject **ret_data)
{
QDict *qdict;
MigrationState *s = current_migration;
if (s) {
monitor_printf(mon, "Migration status: ");
switch (s->get_status(s)) {
case MIG_STATE_ACTIVE:
monitor_printf(mon, "active\n");
monitor_printf(mon, "transferred ram: %" PRIu64 " kbytes\n", ram_bytes_transferred() >> 10);
monitor_printf(mon, "remaining ram: %" PRIu64 " kbytes\n", ram_bytes_remaining() >> 10);
monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n", ram_bytes_total() >> 10);
qdict = qdict_new();
qdict_put(qdict, "status", qstring_from_str("active"));
migrate_put_status(qdict, "ram", ram_bytes_transferred(),
ram_bytes_remaining(), ram_bytes_total());
if (blk_mig_active()) {
monitor_printf(mon, "transferred disk: %" PRIu64 " kbytes\n",
blk_mig_bytes_transferred() >> 10);
monitor_printf(mon, "remaining disk: %" PRIu64 " kbytes\n",
blk_mig_bytes_remaining() >> 10);
monitor_printf(mon, "total disk: %" PRIu64 " kbytes\n",
blk_mig_bytes_total() >> 10);
migrate_put_status(qdict, "disk", blk_mig_bytes_transferred(),
blk_mig_bytes_remaining(),
blk_mig_bytes_total());
}
*ret_data = QOBJECT(qdict);
break;
case MIG_STATE_COMPLETED:
monitor_printf(mon, "completed\n");
*ret_data = qobject_from_jsonf("{ 'status': 'completed' }");
break;
case MIG_STATE_ERROR:
monitor_printf(mon, "failed\n");
*ret_data = qobject_from_jsonf("{ 'status': 'failed' }");
break;
case MIG_STATE_CANCELLED:
monitor_printf(mon, "cancelled\n");
*ret_data = qobject_from_jsonf("{ 'status': 'cancelled' }");
break;
}
assert(*ret_data != NULL);
}
}

View File

@@ -62,7 +62,9 @@ uint64_t migrate_max_downtime(void);
void do_migrate_set_downtime(Monitor *mon, const QDict *qdict);
void do_info_migrate(Monitor *mon);
void do_info_migrate_print(Monitor *mon, const QObject *data);
void do_info_migrate(Monitor *mon, QObject **ret_data);
int exec_start_incoming_migration(const char *host_port);

403
monitor.c
View File

@@ -148,7 +148,10 @@ static void monitor_read_command(Monitor *mon, int show_prompt)
static int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
void *opaque)
{
if (mon->rs) {
if (monitor_ctrl_mode(mon)) {
qemu_error_new(QERR_MISSING_PARAMETER, "password");
return -EINVAL;
} else if (mon->rs) {
readline_start(mon->rs, "Password: ", 1, readline_func, opaque);
/* prompt is printed on return from the command handler */
return 0;
@@ -254,24 +257,6 @@ static inline int monitor_has_error(const Monitor *mon)
return mon->error != NULL;
}
static void monitor_print_qobject(Monitor *mon, const QObject *data)
{
switch (qobject_type(data)) {
case QTYPE_QSTRING:
monitor_printf(mon, "%s",qstring_get_str(qobject_to_qstring(data)));
break;
case QTYPE_QINT:
monitor_printf(mon, "%" PRId64,qint_get_int(qobject_to_qint(data)));
break;
default:
monitor_printf(mon, "ERROR: unsupported type: %d",
qobject_type(data));
break;
}
monitor_puts(mon, "\n");
}
static void monitor_json_emitter(Monitor *mon, const QObject *data)
{
QString *json;
@@ -302,6 +287,7 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data)
}
} else {
/* error response */
qdict_put(mon->error->error, "desc", qerror_human(mon->error));
qdict_put(qmp, "error", mon->error->error);
QINCREF(mon->error->error);
QDECREF(mon->error);
@@ -500,24 +486,91 @@ help:
help_cmd(mon, "info");
}
static void do_info_version_print(Monitor *mon, const QObject *data)
{
QDict *qdict;
qdict = qobject_to_qdict(data);
monitor_printf(mon, "%s%s\n", qdict_get_str(qdict, "qemu"),
qdict_get_str(qdict, "package"));
}
/**
* do_info_version(): Show QEMU version
*
* Return a QDict with the following information:
*
* - "qemu": QEMU's version
* - "package": package's version
*
* Example:
*
* { "qemu": "0.11.50", "package": "" }
*/
static void do_info_version(Monitor *mon, QObject **ret_data)
{
*ret_data = QOBJECT(qstring_from_str(QEMU_VERSION QEMU_PKGVERSION));
*ret_data = qobject_from_jsonf("{ 'qemu': %s, 'package': %s }",
QEMU_VERSION, QEMU_PKGVERSION);
}
static void do_info_name(Monitor *mon)
static void do_info_name_print(Monitor *mon, const QObject *data)
{
if (qemu_name)
monitor_printf(mon, "%s\n", qemu_name);
QDict *qdict;
qdict = qobject_to_qdict(data);
if (qdict_size(qdict) == 0) {
return;
}
monitor_printf(mon, "%s\n", qdict_get_str(qdict, "name"));
}
/**
* do_info_name(): Show VM name
*
* Return a QDict with the following information:
*
* - "name": VM's name (optional)
*
* Example:
*
* { "name": "qemu-name" }
*/
static void do_info_name(Monitor *mon, QObject **ret_data)
{
*ret_data = qemu_name ? qobject_from_jsonf("{'name': %s }", qemu_name) :
qobject_from_jsonf("{}");
}
static QObject *get_cmd_dict(const char *name)
{
const char *p;
/* Remove '|' from some commands */
p = strchr(name, '|');
if (p) {
p++;
} else {
p = name;
}
return qobject_from_jsonf("{ 'name': %s }", p);
}
/**
* do_info_commands(): List QMP available commands
*
* Return a QList of QStrings.
* Each command is represented by a QDict, the returned QObject is a QList
* of all commands.
*
* The QDict contains:
*
* - "name": command's name
*
* Example:
*
* { [ { "name": "query-balloon" }, { "name": "system_powerdown" } ] }
*/
static void do_info_commands(Monitor *mon, QObject **ret_data)
{
@@ -528,7 +581,7 @@ static void do_info_commands(Monitor *mon, QObject **ret_data)
for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
if (monitor_handler_ported(cmd) && !compare_cmd(cmd->name, "info")) {
qlist_append(cmd_list, qstring_from_str(cmd->name));
qlist_append_obj(cmd_list, get_cmd_dict(cmd->name));
}
}
@@ -536,7 +589,7 @@ static void do_info_commands(Monitor *mon, QObject **ret_data)
if (monitor_handler_ported(cmd)) {
char buf[128];
snprintf(buf, sizeof(buf), "query-%s", cmd->name);
qlist_append(cmd_list, qstring_from_str(buf));
qlist_append_obj(cmd_list, get_cmd_dict(buf));
}
}
@@ -544,20 +597,56 @@ static void do_info_commands(Monitor *mon, QObject **ret_data)
}
#if defined(TARGET_I386)
static void do_info_hpet(Monitor *mon)
static void do_info_hpet_print(Monitor *mon, const QObject *data)
{
monitor_printf(mon, "HPET is %s by QEMU\n",
(no_hpet) ? "disabled" : "enabled");
qdict_get_bool(qobject_to_qdict(data), "enabled") ?
"enabled" : "disabled");
}
/**
* do_info_hpet(): Show HPET state
*
* Return a QDict with the following information:
*
* - "enabled": true if hpet if enabled, false otherwise
*
* Example:
*
* { "enabled": true }
*/
static void do_info_hpet(Monitor *mon, QObject **ret_data)
{
*ret_data = qobject_from_jsonf("{ 'enabled': %i }", !no_hpet);
}
#endif
static void do_info_uuid(Monitor *mon)
static void do_info_uuid_print(Monitor *mon, const QObject *data)
{
monitor_printf(mon, UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1],
monitor_printf(mon, "%s\n", qdict_get_str(qobject_to_qdict(data), "UUID"));
}
/**
* do_info_uuid(): Show VM UUID
*
* Return a QDict with the following information:
*
* - "UUID": Universally Unique Identifier
*
* Example:
*
* { "UUID": "550e8400-e29b-41d4-a716-446655440000" }
*/
static void do_info_uuid(Monitor *mon, QObject **ret_data)
{
char uuid[64];
snprintf(uuid, sizeof(uuid), UUID_FMT, qemu_uuid[0], qemu_uuid[1],
qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], qemu_uuid[5],
qemu_uuid[6], qemu_uuid[7], qemu_uuid[8], qemu_uuid[9],
qemu_uuid[10], qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
qemu_uuid[14], qemu_uuid[15]);
*ret_data = qobject_from_jsonf("{ 'UUID': %s }", uuid);
}
/* get the current CPU defined by the user */
@@ -607,8 +696,9 @@ static void print_cpu_iter(QObject *obj, void *opaque)
assert(qobject_type(obj) == QTYPE_QDICT);
cpu = qobject_to_qdict(obj);
if (strcmp(qdict_get_str(cpu, "current"), "yes") == 0)
if (qdict_get_bool(cpu, "current")) {
active = '*';
}
monitor_printf(mon, "%c CPU #%d: ", active, (int)qdict_get_int(cpu, "CPU"));
@@ -628,8 +718,9 @@ static void print_cpu_iter(QObject *obj, void *opaque)
(target_long) qdict_get_int(cpu, "PC"));
#endif
if (strcmp(qdict_get_str(cpu, "halted"), "yes") == 0)
if (qdict_get_bool(cpu, "halted")) {
monitor_printf(mon, " (halted)");
}
monitor_printf(mon, "\n");
}
@@ -646,12 +737,21 @@ static void monitor_print_cpus(Monitor *mon, const QObject *data)
/**
* do_info_cpus(): Show CPU information
*
* Return a QList with a QDict for each CPU.
* Return a QList. Each CPU is represented by a QDict, which contains:
*
* For example:
* - "cpu": CPU index
* - "current": true if this is the current CPU, false otherwise
* - "halted": true if the cpu is halted, false otherwise
* - Current program counter. The key's name depends on the architecture:
* "pc": i386/x86)64
* "nip": PPC
* "pc" and "npc": sparc
* "PC": mips
*
* [ { "CPU": 0, "current": "yes", "pc": 0x..., "halted": "no" },
* { "CPU": 1, "current": "no", "pc": 0x..., "halted": "yes" } ]
* Example:
*
* [ { "CPU": 0, "current": true, "halted": false, "pc": 3227107138 },
* { "CPU": 1, "current": false, "halted": true, "pc": 7108165 } ]
*/
static void do_info_cpus(Monitor *mon, QObject **ret_data)
{
@@ -664,14 +764,17 @@ static void do_info_cpus(Monitor *mon, QObject **ret_data)
mon_get_cpu();
for(env = first_cpu; env != NULL; env = env->next_cpu) {
const char *answer;
QDict *cpu = qdict_new();
QDict *cpu;
QObject *obj;
cpu_synchronize_state(env);
qdict_put(cpu, "CPU", qint_from_int(env->cpu_index));
answer = (env == mon->mon_cpu) ? "yes" : "no";
qdict_put(cpu, "current", qstring_from_str(answer));
obj = qobject_from_jsonf("{ 'CPU': %d, 'current': %i, 'halted': %i }",
env->cpu_index, env == mon->mon_cpu,
env->halted);
assert(obj != NULL);
cpu = qobject_to_qdict(obj);
#if defined(TARGET_I386)
qdict_put(cpu, "pc", qint_from_int(env->eip + env->segs[R_CS].base));
@@ -683,8 +786,6 @@ static void do_info_cpus(Monitor *mon, QObject **ret_data)
#elif defined(TARGET_MIPS)
qdict_put(cpu, "PC", qint_from_int(env->active_tc.PC));
#endif
answer = env->halted ? "yes" : "no";
qdict_put(cpu, "halted", qstring_from_str(answer));
qlist_append(cpu_list, cpu);
}
@@ -745,11 +846,12 @@ static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
if (bdrv_is_inserted(bs)) {
if (!force) {
if (!bdrv_is_removable(bs)) {
monitor_printf(mon, "device is not removable\n");
qemu_error_new(QERR_DEVICE_NOT_REMOVABLE,
bdrv_get_device_name(bs));
return -1;
}
if (bdrv_is_locked(bs)) {
monitor_printf(mon, "device is locked\n");
qemu_error_new(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
return -1;
}
}
@@ -766,12 +868,28 @@ static void do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
bs = bdrv_find(filename);
if (!bs) {
monitor_printf(mon, "device not found\n");
qemu_error_new(QERR_DEVICE_NOT_FOUND, filename);
return;
}
eject_device(mon, bs, force);
}
static void do_block_set_passwd(Monitor *mon, const QDict *qdict,
QObject **ret_data)
{
BlockDriverState *bs;
bs = bdrv_find(qdict_get_str(qdict, "device"));
if (!bs) {
qemu_error_new(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
return;
}
if (bdrv_set_key(bs, qdict_get_str(qdict, "password")) < 0) {
qemu_error_new(QERR_INVALID_PASSWORD);
}
}
static void do_change_block(Monitor *mon, const char *device,
const char *filename, const char *fmt)
{
@@ -780,13 +898,13 @@ static void do_change_block(Monitor *mon, const char *device,
bs = bdrv_find(device);
if (!bs) {
monitor_printf(mon, "device not found\n");
qemu_error_new(QERR_DEVICE_NOT_FOUND, device);
return;
}
if (fmt) {
drv = bdrv_find_whitelisted_format(fmt);
if (!drv) {
monitor_printf(mon, "invalid format %s\n", fmt);
qemu_error_new(QERR_INVALID_BLOCK_FORMAT, fmt);
return;
}
}
@@ -796,12 +914,17 @@ static void do_change_block(Monitor *mon, const char *device,
monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
}
static void change_vnc_password(const char *password)
{
if (vnc_display_password(NULL, password) < 0)
qemu_error_new(QERR_SET_PASSWD_FAILED);
}
static void change_vnc_password_cb(Monitor *mon, const char *password,
void *opaque)
{
if (vnc_display_password(NULL, password) < 0)
monitor_printf(mon, "could not set VNC server password\n");
change_vnc_password(password);
monitor_read_command(mon, 1);
}
@@ -813,17 +936,20 @@ static void do_change_vnc(Monitor *mon, const char *target, const char *arg)
char password[9];
strncpy(password, arg, sizeof(password));
password[sizeof(password) - 1] = '\0';
change_vnc_password_cb(mon, password, NULL);
change_vnc_password(password);
} else {
monitor_read_password(mon, change_vnc_password_cb, NULL);
}
} else {
if (vnc_display_open(NULL, target) < 0)
monitor_printf(mon, "could not start VNC server on %s\n", target);
qemu_error_new(QERR_VNC_SERVER_FAILED, target);
}
}
static void do_change(Monitor *mon, const QDict *qdict)
/**
* do_change(): Change a removable medium, or VNC configuration
*/
static void do_change(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
const char *device = qdict_get_str(qdict, "device");
const char *target = qdict_get_str(qdict, "target");
@@ -1739,16 +1865,40 @@ static void tlb_info(Monitor *mon)
#endif
static void do_info_kvm(Monitor *mon)
static void do_info_kvm_print(Monitor *mon, const QObject *data)
{
QDict *qdict;
qdict = qobject_to_qdict(data);
monitor_printf(mon, "kvm support: ");
if (qdict_get_bool(qdict, "present")) {
monitor_printf(mon, "%s\n", qdict_get_bool(qdict, "enabled") ?
"enabled" : "disabled");
} else {
monitor_printf(mon, "not compiled\n");
}
}
/**
* do_info_kvm(): Show KVM information
*
* Return a QDict with the following information:
*
* - "enabled": true if KVM support is enabled, false otherwise
* - "present": true if QEMU has KVM support, false otherwise
*
* Example:
*
* { "enabled": true, "present": true }
*/
static void do_info_kvm(Monitor *mon, QObject **ret_data)
{
#ifdef CONFIG_KVM
monitor_printf(mon, "kvm support: ");
if (kvm_enabled())
monitor_printf(mon, "enabled\n");
else
monitor_printf(mon, "disabled\n");
*ret_data = qobject_from_jsonf("{ 'enabled': %i, 'present': true }",
kvm_enabled());
#else
monitor_printf(mon, "kvm support: not compiled\n");
*ret_data = qobject_from_jsonf("{ 'enabled': false, 'present': false }");
#endif
}
@@ -1866,16 +2016,41 @@ static void do_inject_nmi(Monitor *mon, const QDict *qdict)
}
#endif
static void do_info_status(Monitor *mon)
static void do_info_status_print(Monitor *mon, const QObject *data)
{
if (vm_running) {
if (singlestep) {
monitor_printf(mon, "VM status: running (single step mode)\n");
} else {
monitor_printf(mon, "VM status: running\n");
QDict *qdict;
qdict = qobject_to_qdict(data);
monitor_printf(mon, "VM status: ");
if (qdict_get_bool(qdict, "running")) {
monitor_printf(mon, "running");
if (qdict_get_bool(qdict, "singlestep")) {
monitor_printf(mon, " (single step mode)");
}
} else
monitor_printf(mon, "VM status: paused\n");
} else {
monitor_printf(mon, "paused");
}
monitor_printf(mon, "\n");
}
/**
* do_info_status(): VM status
*
* Return a QDict with the following information:
*
* - "running": true if the VM is running, or false if it is paused
* - "singlestep": true if the VM is in single step mode, false otherwise
*
* Example:
*
* { "running": true, "singlestep": false }
*/
static void do_info_status(Monitor *mon, QObject **ret_data)
{
*ret_data = qobject_from_jsonf("{ 'running': %i, 'singlestep': %i }",
vm_running, singlestep);
}
/**
@@ -1890,12 +2065,24 @@ static void do_balloon(Monitor *mon, const QDict *qdict, QObject **ret_data)
static void monitor_print_balloon(Monitor *mon, const QObject *data)
{
monitor_printf(mon, "balloon: actual=%d\n",
(int)qint_get_int(qobject_to_qint(data)));
QDict *qdict;
qdict = qobject_to_qdict(data);
monitor_printf(mon, "balloon: actual=%" PRId64 "\n",
qdict_get_int(qdict, "balloon") >> 20);
}
/**
* do_info_balloon(): Balloon information
*
* Return a QDict with the following information:
*
* - "balloon": current balloon value in bytes
*
* Example:
*
* { "balloon": 1073741824 }
*/
static void do_info_balloon(Monitor *mon, QObject **ret_data)
{
@@ -1907,7 +2094,8 @@ static void do_info_balloon(Monitor *mon, QObject **ret_data)
else if (actual == 0)
qemu_error_new(QERR_DEVICE_NOT_ACTIVE, "balloon");
else
*ret_data = QOBJECT(qint_from_int((int)(actual >> 20)));
*ret_data = qobject_from_jsonf("{ 'balloon': %" PRId64 "}",
(int64_t) actual);
}
static qemu_acl *find_acl(Monitor *mon, const char *name)
@@ -2043,19 +2231,21 @@ static void do_getfd(Monitor *mon, const QDict *qdict, QObject **ret_data)
fd = qemu_chr_get_msgfd(mon->chr);
if (fd == -1) {
monitor_printf(mon, "getfd: no file descriptor supplied via SCM_RIGHTS\n");
qemu_error_new(QERR_FD_NOT_SUPPLIED);
return;
}
if (qemu_isdigit(fdname[0])) {
monitor_printf(mon, "getfd: monitor names may not begin with a number\n");
qemu_error_new(QERR_INVALID_PARAMETER, "fdname");
return;
}
fd = dup(fd);
if (fd == -1) {
monitor_printf(mon, "Failed to dup() file descriptor: %s\n",
strerror(errno));
if (errno == EMFILE)
qemu_error_new(QERR_TOO_MANY_FILES);
else
qemu_error_new(QERR_UNDEFINED_ERROR);
return;
}
@@ -2093,8 +2283,7 @@ static void do_closefd(Monitor *mon, const QDict *qdict, QObject **ret_data)
return;
}
monitor_printf(mon, "Failed to find file descriptor named %s\n",
fdname);
qemu_error_new(QERR_FD_NOT_FOUND, fdname);
}
static void do_loadvm(Monitor *mon, const QDict *qdict)
@@ -2144,7 +2333,7 @@ static const mon_cmd_t info_cmds[] = {
.args_type = "",
.params = "",
.help = "show the version of QEMU",
.user_print = monitor_print_qobject,
.user_print = do_info_version_print,
.mhandler.info_new = do_info_version,
},
{
@@ -2167,21 +2356,24 @@ static const mon_cmd_t info_cmds[] = {
.args_type = "",
.params = "",
.help = "show the character devices",
.mhandler.info = qemu_chr_info,
.user_print = qemu_chr_info_print,
.mhandler.info_new = qemu_chr_info,
},
{
.name = "block",
.args_type = "",
.params = "",
.help = "show the block devices",
.mhandler.info = bdrv_info,
.user_print = bdrv_info_print,
.mhandler.info_new = bdrv_info,
},
{
.name = "blockstats",
.args_type = "",
.params = "",
.help = "show block device statistics",
.mhandler.info = bdrv_info_stats,
.user_print = bdrv_stats_print,
.mhandler.info_new = bdrv_info_stats,
},
{
.name = "registers",
@@ -2248,7 +2440,8 @@ static const mon_cmd_t info_cmds[] = {
.args_type = "",
.params = "",
.help = "show state of HPET",
.mhandler.info = do_info_hpet,
.user_print = do_info_hpet_print,
.mhandler.info_new = do_info_hpet,
},
#endif
{
@@ -2263,7 +2456,8 @@ static const mon_cmd_t info_cmds[] = {
.args_type = "",
.params = "",
.help = "show KVM information",
.mhandler.info = do_info_kvm,
.user_print = do_info_kvm_print,
.mhandler.info_new = do_info_kvm,
},
{
.name = "numa",
@@ -2312,7 +2506,8 @@ static const mon_cmd_t info_cmds[] = {
.args_type = "",
.params = "",
.help = "show the current VM status (running|paused)",
.mhandler.info = do_info_status,
.user_print = do_info_status_print,
.mhandler.info_new = do_info_status,
},
{
.name = "pcmcia",
@@ -2326,28 +2521,32 @@ static const mon_cmd_t info_cmds[] = {
.args_type = "",
.params = "",
.help = "show which guest mouse is receiving events",
.mhandler.info = do_info_mice,
.user_print = do_info_mice_print,
.mhandler.info_new = do_info_mice,
},
{
.name = "vnc",
.args_type = "",
.params = "",
.help = "show the vnc server status",
.mhandler.info = do_info_vnc,
.user_print = do_info_vnc_print,
.mhandler.info_new = do_info_vnc,
},
{
.name = "name",
.args_type = "",
.params = "",
.help = "show the current VM name",
.mhandler.info = do_info_name,
.user_print = do_info_name_print,
.mhandler.info_new = do_info_name,
},
{
.name = "uuid",
.args_type = "",
.params = "",
.help = "show the current VM UUID",
.mhandler.info = do_info_uuid,
.user_print = do_info_uuid_print,
.mhandler.info_new = do_info_uuid,
},
#if defined(TARGET_PPC)
{
@@ -2372,7 +2571,8 @@ static const mon_cmd_t info_cmds[] = {
.args_type = "",
.params = "",
.help = "show migration status",
.mhandler.info = do_info_migrate,
.user_print = do_info_migrate_print,
.mhandler.info_new = do_info_migrate,
},
{
.name = "balloon",
@@ -4008,24 +4208,6 @@ static void monitor_event(void *opaque, int event)
* End:
*/
const char *monitor_cmdline_parse(const char *cmdline, int *flags)
{
const char *dev;
if (strstart(cmdline, "control,", &dev)) {
if (strstart(dev, "vc", NULL)) {
fprintf(stderr, "qemu: control mode is for low-level interaction ");
fprintf(stderr, "cannot be used with device 'vc'\n");
exit(1);
}
*flags &= ~MONITOR_USE_READLINE;
*flags |= MONITOR_USE_CONTROL;
return dev;
}
return cmdline;
}
void monitor_init(CharDriverState *chr, int flags)
{
static int is_first_init = 1;
@@ -4087,6 +4269,11 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
return;
}
if (monitor_ctrl_mode(mon)) {
qemu_error_new(QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs));
return;
}
monitor_printf(mon, "%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
bdrv_get_encrypted_filename(bs));

View File

@@ -24,7 +24,6 @@ typedef enum MonitorEvent {
} MonitorEvent;
void monitor_protocol_event(MonitorEvent event, QObject *data);
const char *monitor_cmdline_parse(const char *cmdline, int *flags);
void monitor_init(CharDriverState *chr, int flags);
int monitor_suspend(Monitor *mon);

5
net.c
View File

@@ -39,6 +39,8 @@
static QTAILQ_HEAD(, VLANState) vlans;
static QTAILQ_HEAD(, VLANClientState) non_vlan_clients;
int default_net = 1;
/***********************************************************/
/* network device redirectors */
@@ -1317,7 +1319,7 @@ static int net_init_netdev(QemuOpts *opts, void *dummy)
int net_init_clients(void)
{
if (QTAILQ_EMPTY(&qemu_net_opts.head)) {
if (default_net) {
/* if no clients, we use a default config */
qemu_opts_set(&qemu_net_opts, NULL, "type", "nic");
#ifdef CONFIG_SLIRP
@@ -1353,5 +1355,6 @@ int net_client_parse(QemuOptsList *opts_list, const char *optarg)
return -1;
}
default_net = 0;
return 0;
}

1
net.h
View File

@@ -139,6 +139,7 @@ struct NICInfo {
extern int nb_nics;
extern NICInfo nd_table[MAX_NICS];
extern int default_net;
/* BT HCI info */

BIN
pc-bios/openbios-ppc Executable file → Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

28
qdict.c
View File

@@ -12,6 +12,7 @@
#include "qint.h"
#include "qdict.h"
#include "qbool.h"
#include "qstring.h"
#include "qobject.h"
#include "qemu-queue.h"
@@ -188,6 +189,33 @@ int64_t qdict_get_int(const QDict *qdict, const char *key)
return qint_get_int(qobject_to_qint(obj));
}
/**
* qdict_get_bool(): Get a bool mapped by 'key'
*
* This function assumes that 'key' exists and it stores a
* QBool object.
*
* Return bool mapped by 'key'.
*/
int qdict_get_bool(const QDict *qdict, const char *key)
{
QObject *obj = qdict_get_obj(qdict, key, QTYPE_QBOOL);
return qbool_get_int(qobject_to_qbool(obj));
}
/**
* qdict_get_qlist(): Get the QList mapped by 'key'
*
* This function assumes that 'key' exists and it stores a
* QList object.
*
* Return QList mapped by 'key'.
*/
QList *qdict_get_qlist(const QDict *qdict, const char *key)
{
return qobject_to_qlist(qdict_get_obj(qdict, key, QTYPE_QLIST));
}
/**
* qdict_get_str(): Get a pointer to the stored string mapped
* by 'key'

View File

@@ -2,6 +2,7 @@
#define QDICT_H
#include "qobject.h"
#include "qlist.h"
#include "qemu-queue.h"
#include <stdint.h>
@@ -37,6 +38,8 @@ void qdict_iter(const QDict *qdict,
/* High level helpers */
int64_t qdict_get_int(const QDict *qdict, const char *key);
int qdict_get_bool(const QDict *qdict, const char *key);
QList *qdict_get_qlist(const QDict *qdict, const char *key);
const char *qdict_get_str(const QDict *qdict, const char *key);
int64_t qdict_get_try_int(const QDict *qdict, const char *key,
int64_t err_value);

View File

@@ -32,6 +32,7 @@
#include "hw/usb.h"
#include "hw/baum.h"
#include "hw/msmouse.h"
#include "qemu-objects.h"
#include <unistd.h>
#include <fcntl.h>
@@ -2231,7 +2232,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
return NULL;
}
static QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
{
char host[65], port[33], width[8], height[8];
int pos;
@@ -2469,13 +2470,51 @@ void qemu_chr_close(CharDriverState *chr)
qemu_free(chr);
}
void qemu_chr_info(Monitor *mon)
static void qemu_chr_qlist_iter(QObject *obj, void *opaque)
{
QDict *chr_dict;
Monitor *mon = opaque;
chr_dict = qobject_to_qdict(obj);
monitor_printf(mon, "%s: filename=%s\n", qdict_get_str(chr_dict, "label"),
qdict_get_str(chr_dict, "filename"));
}
void qemu_chr_info_print(Monitor *mon, const QObject *ret_data)
{
qlist_iter(qobject_to_qlist(ret_data), qemu_chr_qlist_iter, mon);
}
/**
* qemu_chr_info(): Character devices information
*
* Each device is represented by a QDict. The returned QObject is a QList
* of all devices.
*
* The QDict contains the following:
*
* - "label": device's label
* - "filename": device's file
*
* Example:
*
* [ { "label": "monitor", "filename", "stdio" },
* { "label": "serial0", "filename": "vc" } ]
*/
void qemu_chr_info(Monitor *mon, QObject **ret_data)
{
QList *chr_list;
CharDriverState *chr;
chr_list = qlist_new();
QTAILQ_FOREACH(chr, &chardevs, next) {
monitor_printf(mon, "%s: filename=%s\n", chr->label, chr->filename);
QObject *obj = qobject_from_jsonf("{ 'label': %s, 'filename': %s }",
chr->label, chr->filename);
qlist_append_obj(chr_list, obj);
}
*ret_data = QOBJECT(chr_list);
}
CharDriverState *qemu_chr_find(const char *name)

View File

@@ -5,6 +5,7 @@
#include "qemu-queue.h"
#include "qemu-option.h"
#include "qemu-config.h"
#include "qobject.h"
/* character device */
@@ -69,6 +70,7 @@ struct CharDriverState {
QTAILQ_ENTRY(CharDriverState) next;
};
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
void (*init)(struct CharDriverState *s));
CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s));
@@ -87,7 +89,8 @@ int qemu_chr_can_read(CharDriverState *s);
void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len);
int qemu_chr_get_msgfd(CharDriverState *s);
void qemu_chr_accept_input(CharDriverState *s);
void qemu_chr_info(Monitor *mon);
void qemu_chr_info_print(Monitor *mon, const QObject *ret_data);
void qemu_chr_info(Monitor *mon, QObject **ret_data);
CharDriverState *qemu_chr_find(const char *name);
extern int term_escape_char;

View File

@@ -2,6 +2,7 @@
#include "qemu-option.h"
#include "qemu-config.h"
#include "sysemu.h"
#include "hw/qdev.h"
QemuOptsList qemu_drive_opts = {
.name = "drive",
@@ -205,6 +206,42 @@ QemuOptsList qemu_rtc_opts = {
},
};
QemuOptsList qemu_global_opts = {
.name = "global",
.head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
.desc = {
{
.name = "driver",
.type = QEMU_OPT_STRING,
},{
.name = "property",
.type = QEMU_OPT_STRING,
},{
.name = "value",
.type = QEMU_OPT_STRING,
},
{ /* end if list */ }
},
};
QemuOptsList qemu_mon_opts = {
.name = "mon",
.head = QTAILQ_HEAD_INITIALIZER(qemu_mon_opts.head),
.desc = {
{
.name = "mode",
.type = QEMU_OPT_STRING,
},{
.name = "chardev",
.type = QEMU_OPT_STRING,
},{
.name = "default",
.type = QEMU_OPT_BOOL,
},
{ /* end if list */ }
},
};
static QemuOptsList *lists[] = {
&qemu_drive_opts,
&qemu_chardev_opts,
@@ -212,6 +249,8 @@ static QemuOptsList *lists[] = {
&qemu_netdev_opts,
&qemu_net_opts,
&qemu_rtc_opts,
&qemu_global_opts,
&qemu_mon_opts,
NULL,
};
@@ -260,6 +299,42 @@ int qemu_set_option(const char *str)
return 0;
}
int qemu_global_option(const char *str)
{
char driver[64], property[64];
QemuOpts *opts;
int rc, offset;
rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
if (rc < 2 || str[offset] != '=') {
qemu_error("can't parse: \"%s\"\n", str);
return -1;
}
opts = qemu_opts_create(&qemu_global_opts, NULL, 0);
qemu_opt_set(opts, "driver", driver);
qemu_opt_set(opts, "property", property);
qemu_opt_set(opts, "value", str+offset+1);
return 0;
}
static int qemu_add_one_global(QemuOpts *opts, void *opaque)
{
GlobalProperty *g;
g = qemu_mallocz(sizeof(*g));
g->driver = qemu_opt_get(opts, "driver");
g->property = qemu_opt_get(opts, "property");
g->value = qemu_opt_get(opts, "value");
qdev_prop_register_global(g);
return 0;
}
void qemu_add_globals(void)
{
qemu_opts_foreach(&qemu_global_opts, qemu_add_one_global, NULL, 0);
}
struct ConfigWriteData {
QemuOptsList *list;
FILE *fp;

View File

@@ -7,8 +7,11 @@ extern QemuOptsList qemu_device_opts;
extern QemuOptsList qemu_netdev_opts;
extern QemuOptsList qemu_net_opts;
extern QemuOptsList qemu_rtc_opts;
extern QemuOptsList qemu_mon_opts;
int qemu_set_option(const char *str);
int qemu_global_option(const char *str);
void qemu_add_globals(void);
void qemu_config_write(FILE *fp);
int qemu_config_parse(FILE *fp);

View File

@@ -42,22 +42,29 @@ void qemu_free(void *ptr)
free(ptr);
}
static int allow_zero_malloc(void)
{
#if defined(CONFIG_ZERO_MALLOC)
return 1;
#else
return 0;
#endif
}
void *qemu_malloc(size_t size)
{
if (!size) {
if (!size && !allow_zero_malloc()) {
abort();
}
return oom_check(malloc(size));
return oom_check(malloc(size ? size : 1));
}
void *qemu_realloc(void *ptr, size_t size)
{
if (size) {
return oom_check(realloc(ptr, size));
} else {
if (ptr) {
return realloc(ptr, size);
}
} else if (allow_zero_malloc()) {
return oom_check(realloc(ptr, size ? size : 1));
}
abort();
}

View File

@@ -147,7 +147,8 @@ ETEXI
.args_type = "device:B,target:F,arg:s?",
.params = "device filename [format]",
.help = "change a removable medium, optional format",
.mhandler.cmd = do_change,
.user_print = monitor_user_noop,
.mhandler.cmd_new = do_change,
},
STEXI
@@ -809,7 +810,8 @@ ETEXI
.args_type = "pci_addr:s,type:s,opts:s?",
.params = "auto|[[<domain>:]<bus>:]<slot> nic|storage [[vlan=n][,macaddr=addr][,model=type]] [file=file][,if=type][,bus=nr]...",
.help = "hot-add PCI device",
.mhandler.cmd = pci_device_hot_add,
.user_print = pci_device_hot_add_print,
.mhandler.cmd_new = pci_device_hot_add,
},
#endif
@@ -1045,6 +1047,20 @@ STEXI
Close the file descriptor previously assigned to @var{fdname} using the
@code{getfd} command. This is only needed if the file descriptor was never
used by another monitor command.
ETEXI
{
.name = "block_passwd",
.args_type = "device:B,password:s",
.params = "block_passwd device password",
.help = "set the password of encrypted block devices",
.user_print = monitor_user_noop,
.mhandler.cmd_new = do_block_set_passwd,
},
STEXI
@item block_passwd @var{device} @var{password}
Set the encrypted device @var{device} password to @var{password}
ETEXI
STEXI

24
qemu-objects.h Normal file
View File

@@ -0,0 +1,24 @@
/*
* Include all QEMU objects.
*
* Copyright (C) 2009 Red Hat Inc.
*
* Authors:
* Luiz Capitulino <lcapitulino@redhat.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*/
#ifndef QEMU_OBJECTS_H
#define QEMU_OBJECTS_H
#include "qobject.h"
#include "qint.h"
#include "qfloat.h"
#include "qbool.h"
#include "qstring.h"
#include "qdict.h"
#include "qlist.h"
#include "qjson.h"
#endif /* QEMU_OBJECTS_H */

View File

@@ -705,7 +705,7 @@ int qemu_opts_print(QemuOpts *opts, void *dummy)
int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
{
char option[128], value[128];
char option[128], value[1024];
const char *p,*pe,*pc;
for (p = params; *p != '\0'; p++) {
@@ -751,7 +751,7 @@ int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname
QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, const char *firstname)
{
char value[128], *id = NULL;
char value[1024], *id = NULL;
const char *p;
QemuOpts *opts;

View File

@@ -109,6 +109,9 @@ DEF("set", HAS_ARG, QEMU_OPTION_set,
"-set group.id.arg=value\n"
" set <arg> parameter for item <id> of type <group>\n"
" i.e. -set drive.$id.file=/path/to/image\n")
DEF("global", HAS_ARG, QEMU_OPTION_global,
"-global driver.property=value\n"
" set a global default for a driver property\n")
STEXI
@item -drive @var{option}[,@var{option}[,@var{option}[,...]]]
@@ -1577,14 +1580,22 @@ Use @code{-parallel none} to disable all parallel ports.
ETEXI
DEF("monitor", HAS_ARG, QEMU_OPTION_monitor, \
"-monitor [control,]dev redirect the monitor to char device 'dev'\n")
"-monitor dev redirect the monitor to char device 'dev'\n")
STEXI
@item -monitor [@var{control},]@var{dev}
@item -monitor @var{dev}
Redirect the monitor to host device @var{dev} (same devices as the
serial port).
The default device is @code{vc} in graphical mode and @code{stdio} in
non graphical mode.
The option @var{control} enables the QEMU Monitor Protocol.
ETEXI
DEF("qmp", HAS_ARG, QEMU_OPTION_qmp, \
"-qmp dev like -monitor but opens in 'control' mode.\n")
DEF("mon", HAS_ARG, QEMU_OPTION_mon, \
"-mon chardev=[name][,mode=readline|control][,default]\n")
STEXI
@item -mon chardev=[name][,mode=readline|control][,default]
Setup monitor on chardev @var{name}.
ETEXI
DEF("pidfile", HAS_ARG, QEMU_OPTION_pidfile, \
@@ -1879,6 +1890,11 @@ DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \
STEXI
ETEXI
DEF("nodefaults", 0, QEMU_OPTION_nodefaults, \
"-nodefaults don't create default devices.\n")
STEXI
ETEXI
#ifndef _WIN32
DEF("chroot", HAS_ARG, QEMU_OPTION_chroot, \
"-chroot dir Chroot to dir just before starting the VM.\n")

View File

@@ -41,20 +41,56 @@ static const QType qerror_type = {
*/
static const QErrorStringTable qerror_table[] = {
{
.error_fmt = QERR_COMMAND_NOT_FOUND,
.desc = "The command %(name) has not been found",
.error_fmt = QERR_COMMAND_NOT_FOUND,
.desc = "The command %(name) has not been found",
},
{
.error_fmt = QERR_DEVICE_NOT_FOUND,
.desc = "The %(device) device has not been found",
.error_fmt = QERR_DEVICE_ENCRYPTED,
.desc = "The %(device) is encrypted",
},
{
.error_fmt = QERR_DEVICE_LOCKED,
.desc = "Device %(device) is locked",
},
{
.error_fmt = QERR_DEVICE_NOT_ACTIVE,
.desc = "The %(device) device has not been activated by the guest",
},
{
.error_fmt = QERR_INVALID_PARAMETER_TYPE,
.desc = "Invalid parameter type, expected: %(expected)",
.error_fmt = QERR_DEVICE_NOT_FOUND,
.desc = "The %(device) device has not been found",
},
{
.error_fmt = QERR_DEVICE_NOT_REMOVABLE,
.desc = "Device %(device) is not removable",
},
{
.error_fmt = QERR_FD_NOT_FOUND,
.desc = "Failed to find file descriptor named %(name)",
},
{
.error_fmt = QERR_FD_NOT_SUPPLIED,
.desc = "No file descriptor supplied via SCM_RIGHTS",
},
{
.error_fmt = QERR_INVALID_BLOCK_FORMAT,
.desc = "Invalid block format %(name)",
},
{
.error_fmt = QERR_INVALID_PARAMETER,
.desc = "Invalid parameter %(name)",
},
{
.error_fmt = QERR_INVALID_PARAMETER_TYPE,
.desc = "Invalid parameter type, expected: %(expected)",
},
{
.error_fmt = QERR_INVALID_PASSWORD,
.desc = "The entered password is invalid",
},
{
.error_fmt = QERR_JSON_PARSING,
.desc = "Invalid JSON syntax",
},
{
.error_fmt = QERR_KVM_MISSING_CAP,
@@ -69,12 +105,20 @@ static const QErrorStringTable qerror_table[] = {
.desc = "Bad QMP input object",
},
{
.error_fmt = QERR_JSON_PARSING,
.desc = "Invalid JSON synaxt",
.error_fmt = QERR_SET_PASSWD_FAILED,
.desc = "Could not set password",
},
{
.error_fmt = QERR_UNDEFINED_ERROR,
.desc = "An undefined error has ocurred",
.error_fmt = QERR_TOO_MANY_FILES,
.desc = "Too many open files",
},
{
.error_fmt = QERR_UNDEFINED_ERROR,
.desc = "An undefined error has ocurred",
},
{
.error_fmt = QERR_VNC_SERVER_FAILED,
.desc = "Could not start VNC server on %(target)",
},
{}
};
@@ -239,13 +283,11 @@ static const char *append_field(QString *outstr, const QError *qerror,
}
/**
* qerror_print(): Print QError data
* qerror_human(): Format QError data into human-readable string.
*
* This function will print the member 'desc' of the specified QError object,
* it uses qemu_error() for this, so that the output is routed to the right
* place (ie. stderr or Monitor's device).
* Formats according to member 'desc' of the specified QError object.
*/
void qerror_print(const QError *qerror)
QString *qerror_human(const QError *qerror)
{
const char *p;
QString *qstring;
@@ -265,6 +307,19 @@ void qerror_print(const QError *qerror)
}
}
return qstring;
}
/**
* qerror_print(): Print QError data
*
* This function will print the member 'desc' of the specified QError object,
* it uses qemu_error() for this, so that the output is routed to the right
* place (ie. stderr or Monitor's device).
*/
void qerror_print(const QError *qerror)
{
QString *qstring = qerror_human(qerror);
qemu_error("%s\n", qstring_get_str(qstring));
QDECREF(qstring);
}

View File

@@ -13,6 +13,7 @@
#define QERROR_H
#include "qdict.h"
#include "qstring.h"
#include <stdarg.h>
typedef struct QErrorStringTable {
@@ -32,6 +33,7 @@ typedef struct QError {
QError *qerror_new(void);
QError *qerror_from_info(const char *file, int linenr, const char *func,
const char *fmt, va_list *va);
QString *qerror_human(const QError *qerror);
void qerror_print(const QError *qerror);
QError *qobject_to_qerror(const QObject *obj);
@@ -39,30 +41,63 @@ QError *qobject_to_qerror(const QObject *obj);
* QError class list
*/
#define QERR_COMMAND_NOT_FOUND \
"{ 'class': 'CommandNotFound', 'data': { 'name': %s } }"
"{ 'class': 'CommandNotFound', 'data': { 'name': %s } }"
#define QERR_DEVICE_NOT_FOUND \
"{ 'class': 'DeviceNotFound', 'data': { 'device': %s } }"
#define QERR_DEVICE_ENCRYPTED \
"{ 'class': 'DeviceEncrypted', 'data': { 'device': %s } }"
#define QERR_DEVICE_LOCKED \
"{ 'class': 'DeviceLocked', 'data': { 'device': %s } }"
#define QERR_DEVICE_NOT_ACTIVE \
"{ 'class': 'DeviceNotActive', 'data': { 'device': %s } }"
"{ 'class': 'DeviceNotActive', 'data': { 'device': %s } }"
#define QERR_DEVICE_NOT_FOUND \
"{ 'class': 'DeviceNotFound', 'data': { 'device': %s } }"
#define QERR_DEVICE_NOT_REMOVABLE \
"{ 'class': 'DeviceNotRemovable', 'data': { 'device': %s } }"
#define QERR_FD_NOT_FOUND \
"{ 'class': 'FdNotFound', 'data': { 'name': %s } }"
#define QERR_FD_NOT_SUPPLIED \
"{ 'class': 'FdNotSupplied', 'data': {} }"
#define QERR_INVALID_BLOCK_FORMAT \
"{ 'class': 'InvalidBlockFormat', 'data': { 'name': %s } }"
#define QERR_INVALID_PARAMETER \
"{ 'class': 'InvalidParameter', 'data': { 'name': %s } }"
#define QERR_INVALID_PARAMETER_TYPE \
"{ 'class': 'InvalidParameterType', 'data': { 'name': %s,'expected': %s } }"
"{ 'class': 'InvalidParameterType', 'data': { 'name': %s,'expected': %s } }"
#define QERR_KVM_MISSING_CAP \
"{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }"
#define QERR_MISSING_PARAMETER \
"{ 'class': 'MissingParameter', 'data': { 'name': %s } }"
#define QERR_QMP_BAD_INPUT_OBJECT \
"{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }"
#define QERR_INVALID_PASSWORD \
"{ 'class': 'InvalidPassword', 'data': {} }"
#define QERR_JSON_PARSING \
"{ 'class': 'JSONParsing', 'data': {} }"
"{ 'class': 'JSONParsing', 'data': {} }"
#define QERR_KVM_MISSING_CAP \
"{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }"
#define QERR_MISSING_PARAMETER \
"{ 'class': 'MissingParameter', 'data': { 'name': %s } }"
#define QERR_QMP_BAD_INPUT_OBJECT \
"{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }"
#define QERR_SET_PASSWD_FAILED \
"{ 'class': 'SetPasswdFailed', 'data': {} }"
#define QERR_UNDEFINED_ERROR \
"{ 'class': 'UndefinedError', 'data': {} }"
"{ 'class': 'UndefinedError', 'data': {} }"
#define QERR_TOO_MANY_FILES \
"{ 'class': 'TooManyFiles', 'data': {} }"
#define QERR_VNC_SERVER_FAILED \
"{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }"
#endif /* QERROR_H */

View File

@@ -47,3 +47,6 @@ cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \
%.h-timestamp: %.mak
$(call quiet-command, sh $(SRC_PATH)/create_config < $< > $@, " GEN $*.h")
@cmp $@ $*.h >/dev/null 2>&1 || cp $@ $*.h
# will delete the target of a rule if commands exit with a nonzero exit status
.DELETE_ON_ERROR:

View File

@@ -212,7 +212,8 @@ extern DriveInfo *drive_init(QemuOpts *arg, void *machine, int *fatal_error);
DriveInfo *add_init_drive(const char *opts);
/* pci-hotplug */
void pci_device_hot_add(Monitor *mon, const QDict *qdict);
void pci_device_hot_add_print(Monitor *mon, const QObject *data);
void pci_device_hot_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
void drive_hot_add(Monitor *mon, const QDict *qdict);
void pci_device_hot_remove(Monitor *mon, const char *pci_addr);
void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict,

View File

@@ -651,6 +651,8 @@ typedef struct CPUX86State {
target_ulong fmask;
target_ulong kernelgsbase;
#endif
uint64_t system_time_msr;
uint64_t wall_clock_msr;
uint64_t tsc;

View File

@@ -1638,6 +1638,24 @@ static void host_cpuid(uint32_t function, uint32_t count,
#endif
}
static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx)
{
*ebx = env->cpuid_vendor1;
*edx = env->cpuid_vendor2;
*ecx = env->cpuid_vendor3;
/* sysenter isn't supported on compatibility mode on AMD, syscall
* isn't supported in compatibility mode on Intel.
* Normally we advertise the actual cpu vendor, but you can override
* this if you want to use KVM's sysenter/syscall emulation
* in compatibility mode and when doing cross vendor migration
*/
if (kvm_enabled() && env->cpuid_vendor_override) {
host_cpuid(0, 0, NULL, ebx, ecx, edx);
}
}
void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx)
@@ -1654,16 +1672,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
switch(index) {
case 0:
*eax = env->cpuid_level;
*ebx = env->cpuid_vendor1;
*edx = env->cpuid_vendor2;
*ecx = env->cpuid_vendor3;
/* sysenter isn't supported on compatibility mode on AMD. and syscall
* isn't supported in compatibility mode on Intel. so advertise the
* actuall cpu, and say goodbye to migration between different vendors
* is you use compatibility mode. */
if (kvm_enabled() && !env->cpuid_vendor_override)
host_cpuid(0, 0, NULL, ebx, ecx, edx);
get_cpuid_vendor(env, ebx, ecx, edx);
break;
case 1:
*eax = env->cpuid_version;
@@ -1759,11 +1768,18 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*ecx = env->cpuid_ext3_features;
*edx = env->cpuid_ext2_features;
if (env->nr_cores * env->nr_threads > 1 &&
env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 &&
env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 &&
env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) {
*ecx |= 1 << 1; /* CmpLegacy bit */
/* The Linux kernel checks for the CMPLegacy bit and
* discards multiple thread information if it is set.
* So dont set it here for Intel to make Linux guests happy.
*/
if (env->nr_cores * env->nr_threads > 1) {
uint32_t tebx, tecx, tedx;
get_cpuid_vendor(env, &tebx, &tecx, &tedx);
if (tebx != CPUID_VENDOR_INTEL_1 ||
tedx != CPUID_VENDOR_INTEL_2 ||
tecx != CPUID_VENDOR_INTEL_3) {
*ecx |= 1 << 1; /* CmpLegacy bit */
}
}
if (kvm_enabled()) {

View File

@@ -35,6 +35,9 @@
do { } while (0)
#endif
#define MSR_KVM_WALL_CLOCK 0x11
#define MSR_KVM_SYSTEM_TIME 0x12
#ifdef KVM_CAP_EXT_CPUID
static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
@@ -244,9 +247,9 @@ static int kvm_has_msr_star(CPUState *env)
* save/restore */
msr_list.nmsrs = 0;
ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, &msr_list);
if (ret < 0)
if (ret < 0 && ret != -E2BIG) {
return 0;
}
/* Old kernel modules had a bug and could write beyond the provided
memory. Allocate at least a safe amount of 1K. */
kvm_msr_list = qemu_mallocz(MAX(1024, sizeof(msr_list) +
@@ -494,6 +497,9 @@ static int kvm_put_msrs(CPUState *env)
kvm_msr_entry_set(&msrs[n++], MSR_FMASK, env->fmask);
kvm_msr_entry_set(&msrs[n++], MSR_LSTAR, env->lstar);
#endif
kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME, env->system_time_msr);
kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
msr_data.info.nmsrs = n;
return kvm_vcpu_ioctl(env, KVM_SET_MSRS, &msr_data);
@@ -634,6 +640,9 @@ static int kvm_get_msrs(CPUState *env)
msrs[n++].index = MSR_FMASK;
msrs[n++].index = MSR_LSTAR;
#endif
msrs[n++].index = MSR_KVM_SYSTEM_TIME;
msrs[n++].index = MSR_KVM_WALL_CLOCK;
msr_data.info.nmsrs = n;
ret = kvm_vcpu_ioctl(env, KVM_GET_MSRS, &msr_data);
if (ret < 0)
@@ -670,6 +679,12 @@ static int kvm_get_msrs(CPUState *env)
case MSR_IA32_TSC:
env->tsc = msrs[i].data;
break;
case MSR_KVM_SYSTEM_TIME:
env->system_time_msr = msrs[i].data;
break;
case MSR_KVM_WALL_CLOCK:
env->wall_clock_msr = msrs[i].data;
break;
}
}

View File

@@ -453,6 +453,7 @@ static const VMStateDescription vmstate_cpu = {
VMSTATE_UINT8_V(nmi_pending, CPUState, 11),
VMSTATE_UINT8_V(has_error_code, CPUState, 11),
VMSTATE_UINT32_V(sipi_vector, CPUState, 11),
VMSTATE_INT32_V(exception_index, CPUState, 11),
/* MCE */
VMSTATE_UINT64_V(mcg_cap, CPUState, 10),
VMSTATE_UINT64_V(mcg_status, CPUState, 10),
@@ -460,6 +461,9 @@ static const VMStateDescription vmstate_cpu = {
VMSTATE_UINT64_ARRAY_V(mce_banks, CPUState, MCE_BANKS_DEF *4, 10),
/* rdtscp */
VMSTATE_UINT64_V(tsc_aux, CPUState, 11),
/* KVM pvclock msr */
VMSTATE_UINT64_V(system_time_msr, CPUState, 11),
VMSTATE_UINT64_V(wall_clock_msr, CPUState, 11),
VMSTATE_END_OF_LIST()
/* The above list is not sorted /wrt version numbers, watch out! */
}

View File

@@ -361,7 +361,7 @@ USBDevice *usb_host_device_open(const char *devname)
goto fail;
}
d = usb_create(NULL /* FIXME */, "USB Host Device");
d = usb_create(NULL /* FIXME */, "usb-host");
dev = DO_UPCAST(USBHostDevice, dev, d);
if (dev_info.udi_speed == 1)
@@ -370,10 +370,10 @@ USBDevice *usb_host_device_open(const char *devname)
dev->dev.speed = USB_SPEED_FULL - 1;
if (strncmp(dev_info.udi_product, "product", 7) != 0)
pstrcpy(dev->dev.devname, sizeof(dev->dev.devname),
pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
dev_info.udi_product);
else
snprintf(dev->dev.devname, sizeof(dev->dev.devname),
snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
"host:%s", devname);
pstrcpy(dev->devpath, sizeof(dev->devpath), "/dev/");
@@ -393,7 +393,8 @@ fail:
}
static struct USBDeviceInfo usb_host_dev_info = {
.qdev.name = "USB Host Device",
.product_desc = "USB Host Device",
.qdev.name = "usb-host",
.qdev.size = sizeof(USBHostDevice),
.init = usb_host_initfn,
.handle_packet = usb_generic_handle_packet,

View File

@@ -933,10 +933,10 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
dev->dev.speed = USB_SPEED_HIGH;
if (!prod_name || prod_name[0] == '\0')
snprintf(dev->dev.devname, sizeof(dev->dev.devname),
snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
"host:%d.%d", bus_num, addr);
else
pstrcpy(dev->dev.devname, sizeof(dev->dev.devname),
pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
prod_name);
/* USB devio uses 'write' flag to check for async completions */
@@ -979,8 +979,8 @@ static int usb_host_initfn(USBDevice *dev)
}
static struct USBDeviceInfo usb_host_dev_info = {
.qdev.name = "USB Host Device",
.qdev.alias = "usb-host",
.product_desc = "USB Host Device",
.qdev.name = "usb-host",
.qdev.size = sizeof(USBHostDevice),
.init = usb_host_initfn,
.handle_packet = usb_host_handle_packet,
@@ -1010,7 +1010,7 @@ USBDevice *usb_host_device_open(const char *devname)
USBHostDevice *s;
char *p;
dev = usb_create(NULL /* FIXME */, "USB Host Device");
dev = usb_create(NULL /* FIXME */, "usb-host");
s = DO_UPCAST(USBHostDevice, dev, dev);
if (strstr(devname, "auto:")) {

554
vl.c
View File

@@ -156,6 +156,7 @@ int main(int argc, char **argv)
#include "balloon.h"
#include "qemu-option.h"
#include "qemu-config.h"
#include "qemu-objects.h"
#include "disas.h"
@@ -172,9 +173,6 @@ int main(int argc, char **argv)
#define DEFAULT_RAM_SIZE 128
/* Maximum number of monitor devices */
#define MAX_MONITOR_DEVICES 10
static const char *data_dir;
const char *bios_name = NULL;
/* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
@@ -193,7 +191,7 @@ int autostart;
static int rtc_utc = 1;
static int rtc_date_offset = -1; /* -1 means no change */
QEMUClock *rtc_clock;
int vga_interface_type = VGA_CIRRUS;
int vga_interface_type = VGA_NONE;
#ifdef TARGET_SPARC
int graphic_width = 1024;
int graphic_height = 768;
@@ -271,6 +269,41 @@ uint8_t qemu_uuid[16];
static QEMUBootSetHandler *boot_set_handler;
static void *boot_set_opaque;
static int default_serial = 1;
static int default_parallel = 1;
static int default_virtcon = 1;
static int default_monitor = 1;
static int default_vga = 1;
static int default_drive = 1;
static struct {
const char *driver;
int *flag;
} default_list[] = {
{ .driver = "isa-serial", .flag = &default_serial },
{ .driver = "isa-parallel", .flag = &default_parallel },
{ .driver = "virtio-console-pci", .flag = &default_virtcon },
{ .driver = "virtio-console-s390", .flag = &default_virtcon },
{ .driver = "VGA", .flag = &default_vga },
{ .driver = "Cirrus VGA", .flag = &default_vga },
{ .driver = "QEMUware SVGA", .flag = &default_vga },
};
static int default_driver_check(QemuOpts *opts, void *opaque)
{
const char *driver = qemu_opt_get(opts, "driver");
int i;
if (!driver)
return 0;
for (i = 0; i < ARRAY_SIZE(default_list); i++) {
if (strcmp(default_list[i].driver, driver) != 0)
continue;
*(default_list[i].flag) = 0;
}
return 0;
}
/***********************************************************/
/* x86 ISA bus support */
@@ -458,25 +491,72 @@ int kbd_mouse_is_absolute(void)
return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute;
}
void do_info_mice(Monitor *mon)
static void info_mice_iter(QObject *data, void *opaque)
{
QEMUPutMouseEntry *cursor;
int index = 0;
QDict *mouse;
Monitor *mon = opaque;
if (!qemu_put_mouse_event_head) {
mouse = qobject_to_qdict(data);
monitor_printf(mon, "%c Mouse #%" PRId64 ": %s\n",
(qdict_get_bool(mouse, "current") ? '*' : ' '),
qdict_get_int(mouse, "index"), qdict_get_str(mouse, "name"));
}
void do_info_mice_print(Monitor *mon, const QObject *data)
{
QList *mice_list;
mice_list = qobject_to_qlist(data);
if (qlist_empty(mice_list)) {
monitor_printf(mon, "No mouse devices connected\n");
return;
}
monitor_printf(mon, "Mouse devices available:\n");
qlist_iter(mice_list, info_mice_iter, mon);
}
/**
* do_info_mice(): Show VM mice information
*
* Each mouse is represented by a QDict, the returned QObject is a QList of
* all mice.
*
* The mouse QDict contains the following:
*
* - "name": mouse's name
* - "index": mouse's index
* - "current": true if this mouse is receiving events, false otherwise
*
* Example:
*
* [ { "name": "QEMU Microsoft Mouse", "index": 0, "current": false },
* { "name": "QEMU PS/2 Mouse", "index": 1, "current": true } ]
*/
void do_info_mice(Monitor *mon, QObject **ret_data)
{
QEMUPutMouseEntry *cursor;
QList *mice_list;
int index = 0;
mice_list = qlist_new();
if (!qemu_put_mouse_event_head) {
goto out;
}
cursor = qemu_put_mouse_event_head;
while (cursor != NULL) {
monitor_printf(mon, "%c Mouse #%d: %s\n",
(cursor == qemu_put_mouse_event_current ? '*' : ' '),
index, cursor->qemu_put_mouse_event_name);
QObject *obj;
obj = qobject_from_jsonf("{ 'name': %s, 'index': %d, 'current': %i }",
cursor->qemu_put_mouse_event_name,
index, cursor == qemu_put_mouse_event_current);
qlist_append_obj(mice_list, obj);
index++;
cursor = cursor->next;
}
out:
*ret_data = QOBJECT(mice_list);
}
void do_mouse_set(Monitor *mon, const QDict *qdict)
@@ -4345,6 +4425,7 @@ static void select_vgahw (const char *p)
{
const char *opts;
default_vga = 0;
vga_interface_type = VGA_NONE;
if (strstart(p, "std", &opts)) {
vga_interface_type = VGA_STD;
@@ -4586,10 +4667,94 @@ static int device_init_func(QemuOpts *opts, void *opaque)
return 0;
}
static int chardev_init_func(QemuOpts *opts, void *opaque)
{
CharDriverState *chr;
chr = qemu_chr_open_opts(opts, NULL);
if (!chr)
return -1;
return 0;
}
static int mon_init_func(QemuOpts *opts, void *opaque)
{
CharDriverState *chr;
const char *chardev;
const char *mode;
int flags;
mode = qemu_opt_get(opts, "mode");
if (mode == NULL) {
mode = "readline";
}
if (strcmp(mode, "readline") == 0) {
flags = MONITOR_USE_READLINE;
} else if (strcmp(mode, "control") == 0) {
flags = MONITOR_USE_CONTROL;
} else {
fprintf(stderr, "unknown monitor mode \"%s\"\n", mode);
exit(1);
}
if (qemu_opt_get_bool(opts, "default", 0))
flags |= MONITOR_IS_DEFAULT;
chardev = qemu_opt_get(opts, "chardev");
chr = qemu_chr_find(chardev);
if (chr == NULL) {
fprintf(stderr, "chardev \"%s\" not found\n", chardev);
exit(1);
}
monitor_init(chr, flags);
return 0;
}
static void monitor_parse(const char *optarg, const char *mode)
{
static int monitor_device_index = 0;
QemuOpts *opts;
const char *p;
char label[32];
int def = 0;
if (strstart(optarg, "chardev:", &p)) {
snprintf(label, sizeof(label), "%s", p);
} else {
if (monitor_device_index) {
snprintf(label, sizeof(label), "monitor%d",
monitor_device_index);
} else {
snprintf(label, sizeof(label), "monitor");
def = 1;
}
opts = qemu_chr_parse_compat(label, optarg);
if (!opts) {
fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
}
opts = qemu_opts_create(&qemu_mon_opts, label, 1);
if (!opts) {
fprintf(stderr, "duplicate chardev: %s\n", label);
exit(1);
}
qemu_opt_set(opts, "mode", mode);
qemu_opt_set(opts, "chardev", label);
if (def)
qemu_opt_set(opts, "default", "on");
monitor_device_index++;
}
struct device_config {
enum {
DEV_USB, /* -usbdevice */
DEV_BT, /* -bt */
DEV_USB, /* -usbdevice */
DEV_BT, /* -bt */
DEV_SERIAL, /* -serial */
DEV_PARALLEL, /* -parallel */
DEV_VIRTCON, /* -virtioconsole */
} type;
const char *cmdline;
QTAILQ_ENTRY(device_config) next;
@@ -4621,6 +4786,72 @@ static int foreach_device_config(int type, int (*func)(const char *cmdline))
return 0;
}
static int serial_parse(const char *devname)
{
static int index = 0;
char label[32];
if (strcmp(devname, "none") == 0)
return 0;
if (index == MAX_SERIAL_PORTS) {
fprintf(stderr, "qemu: too many serial ports\n");
exit(1);
}
snprintf(label, sizeof(label), "serial%d", index);
serial_hds[index] = qemu_chr_open(label, devname, NULL);
if (!serial_hds[index]) {
fprintf(stderr, "qemu: could not open serial device '%s': %s\n",
devname, strerror(errno));
return -1;
}
index++;
return 0;
}
static int parallel_parse(const char *devname)
{
static int index = 0;
char label[32];
if (strcmp(devname, "none") == 0)
return 0;
if (index == MAX_PARALLEL_PORTS) {
fprintf(stderr, "qemu: too many parallel ports\n");
exit(1);
}
snprintf(label, sizeof(label), "parallel%d", index);
parallel_hds[index] = qemu_chr_open(label, devname, NULL);
if (!parallel_hds[index]) {
fprintf(stderr, "qemu: could not open parallel device '%s': %s\n",
devname, strerror(errno));
return -1;
}
index++;
return 0;
}
static int virtcon_parse(const char *devname)
{
static int index = 0;
char label[32];
if (strcmp(devname, "none") == 0)
return 0;
if (index == MAX_VIRTIO_CONSOLES) {
fprintf(stderr, "qemu: too many virtio consoles\n");
exit(1);
}
snprintf(label, sizeof(label), "virtcon%d", index);
virtcon_hds[index] = qemu_chr_open(label, devname, NULL);
if (!virtcon_hds[index]) {
fprintf(stderr, "qemu: could not open virtio console '%s': %s\n",
devname, strerror(errno));
return -1;
}
index++;
return 0;
}
int main(int argc, char **argv, char **envp)
{
const char *gdbstub_dev = NULL;
@@ -4636,16 +4867,6 @@ int main(int argc, char **argv, char **envp)
QemuOpts *hda_opts = NULL, *opts;
int optind;
const char *r, *optarg;
CharDriverState *monitor_hds[MAX_MONITOR_DEVICES];
const char *monitor_devices[MAX_MONITOR_DEVICES];
int monitor_flags[MAX_MONITOR_DEVICES];
int monitor_device_index;
const char *serial_devices[MAX_SERIAL_PORTS];
int serial_device_index;
const char *parallel_devices[MAX_PARALLEL_PORTS];
int parallel_device_index;
const char *virtio_consoles[MAX_VIRTIO_CONSOLES];
int virtio_console_index;
const char *loadvm = NULL;
QEMUMachine *machine;
const char *cpu_model;
@@ -4711,43 +4932,6 @@ int main(int argc, char **argv, char **envp)
cyls = heads = secs = 0;
translation = BIOS_ATA_TRANSLATION_AUTO;
#ifdef TARGET_S390X
for(i = 0; i < MAX_SERIAL_PORTS; i++)
serial_devices[i] = NULL;
serial_device_index = 0;
for(i = 0; i < MAX_PARALLEL_PORTS; i++)
parallel_devices[i] = NULL;
parallel_device_index = 0;
virtio_consoles[0] = "mon:stdio";
for(i = 1; i < MAX_VIRTIO_CONSOLES; i++)
virtio_consoles[i] = NULL;
virtio_console_index = 0;
#else
serial_devices[0] = "vc:80Cx24C";
for(i = 1; i < MAX_SERIAL_PORTS; i++)
serial_devices[i] = NULL;
serial_device_index = 0;
parallel_devices[0] = "vc:80Cx24C";
for(i = 1; i < MAX_PARALLEL_PORTS; i++)
parallel_devices[i] = NULL;
parallel_device_index = 0;
for(i = 0; i < MAX_VIRTIO_CONSOLES; i++)
virtio_consoles[i] = NULL;
virtio_console_index = 0;
#endif
monitor_devices[0] = "vc:80Cx24C";
monitor_flags[0] = MONITOR_IS_DEFAULT | MONITOR_USE_READLINE;
for (i = 1; i < MAX_MONITOR_DEVICES; i++) {
monitor_devices[i] = NULL;
monitor_flags[i] = MONITOR_USE_READLINE;
}
monitor_device_index = 0;
for (i = 0; i < MAX_NODES; i++) {
node_mem[i] = 0;
node_cpumask[i] = 0;
@@ -4851,6 +5035,10 @@ int main(int argc, char **argv, char **envp)
if (qemu_set_option(optarg) != 0)
exit(1);
break;
case QEMU_OPTION_global:
if (qemu_global_option(optarg) != 0)
exit(1);
break;
case QEMU_OPTION_mtdblock:
drive_add(optarg, MTD_ALIAS);
break;
@@ -5161,14 +5349,20 @@ int main(int argc, char **argv, char **envp)
break;
}
case QEMU_OPTION_monitor:
if (monitor_device_index >= MAX_MONITOR_DEVICES) {
fprintf(stderr, "qemu: too many monitor devices\n");
monitor_parse(optarg, "readline");
default_monitor = 0;
break;
case QEMU_OPTION_qmp:
monitor_parse(optarg, "control");
default_monitor = 0;
break;
case QEMU_OPTION_mon:
opts = qemu_opts_parse(&qemu_mon_opts, optarg, "chardev");
if (!opts) {
fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
monitor_devices[monitor_device_index] =
monitor_cmdline_parse(optarg,
&monitor_flags[monitor_device_index]);
monitor_device_index++;
default_monitor = 0;
break;
case QEMU_OPTION_chardev:
opts = qemu_opts_parse(&qemu_chardev_opts, optarg, "backend");
@@ -5176,17 +5370,10 @@ int main(int argc, char **argv, char **envp)
fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
if (qemu_chr_open_opts(opts, NULL) == NULL) {
exit(1);
}
break;
case QEMU_OPTION_serial:
if (serial_device_index >= MAX_SERIAL_PORTS) {
fprintf(stderr, "qemu: too many serial ports\n");
exit(1);
}
serial_devices[serial_device_index] = optarg;
serial_device_index++;
add_device_config(DEV_SERIAL, optarg);
default_serial = 0;
break;
case QEMU_OPTION_watchdog:
if (watchdog) {
@@ -5203,20 +5390,12 @@ int main(int argc, char **argv, char **envp)
}
break;
case QEMU_OPTION_virtiocon:
if (virtio_console_index >= MAX_VIRTIO_CONSOLES) {
fprintf(stderr, "qemu: too many virtio consoles\n");
exit(1);
}
virtio_consoles[virtio_console_index] = optarg;
virtio_console_index++;
add_device_config(DEV_VIRTCON, optarg);
default_virtcon = 0;
break;
case QEMU_OPTION_parallel:
if (parallel_device_index >= MAX_PARALLEL_PORTS) {
fprintf(stderr, "qemu: too many parallel ports\n");
exit(1);
}
parallel_devices[parallel_device_index] = optarg;
parallel_device_index++;
add_device_config(DEV_PARALLEL, optarg);
default_parallel = 0;
break;
case QEMU_OPTION_loadvm:
loadvm = optarg;
@@ -5409,6 +5588,15 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_incoming:
incoming = optarg;
break;
case QEMU_OPTION_nodefaults:
default_serial = 0;
default_parallel = 0;
default_virtcon = 0;
default_monitor = 0;
default_vga = 0;
default_net = 0;
default_drive = 0;
break;
#ifndef _WIN32
case QEMU_OPTION_chroot:
chroot_dir = optarg;
@@ -5487,15 +5675,49 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
if (display_type == DT_NOGRAPHIC) {
if (serial_device_index == 0)
serial_devices[0] = "stdio";
if (parallel_device_index == 0)
parallel_devices[0] = "null";
if (strncmp(monitor_devices[0], "vc", 2) == 0) {
monitor_devices[0] = "stdio";
}
qemu_opts_foreach(&qemu_device_opts, default_driver_check, NULL, 0);
if (machine->no_serial) {
default_serial = 0;
}
if (machine->no_parallel) {
default_parallel = 0;
}
if (!machine->use_virtcon) {
default_virtcon = 0;
}
if (machine->no_vga) {
default_vga = 0;
}
if (display_type == DT_NOGRAPHIC) {
if (default_parallel)
add_device_config(DEV_PARALLEL, "null");
if (default_serial && default_monitor) {
add_device_config(DEV_SERIAL, "mon:stdio");
} else if (default_virtcon && default_monitor) {
add_device_config(DEV_VIRTCON, "mon:stdio");
} else {
if (default_serial)
add_device_config(DEV_SERIAL, "stdio");
if (default_virtcon)
add_device_config(DEV_VIRTCON, "stdio");
if (default_monitor)
monitor_parse("stdio", "readline");
}
} else {
if (default_serial)
add_device_config(DEV_SERIAL, "vc:80Cx24C");
if (default_parallel)
add_device_config(DEV_PARALLEL, "vc:80Cx24C");
if (default_monitor)
monitor_parse("vc:80Cx24C", "readline");
}
if (default_vga)
vga_interface_type = VGA_CIRRUS;
if (qemu_opts_foreach(&qemu_chardev_opts, chardev_init_func, NULL, 1) != 0)
exit(1);
#ifndef _WIN32
if (daemonize) {
@@ -5623,14 +5845,16 @@ int main(int argc, char **argv, char **envp)
blk_mig_init();
/* we always create the cdrom drive, even if no disk is there */
drive_add(NULL, CDROM_ALIAS);
if (default_drive) {
/* we always create the cdrom drive, even if no disk is there */
drive_add(NULL, CDROM_ALIAS);
/* we always create at least one floppy */
drive_add(NULL, FD_ALIAS, 0);
/* we always create at least one floppy */
drive_add(NULL, FD_ALIAS, 0);
/* we always create one sd slot, even if no card is in it */
drive_add(NULL, SD_ALIAS);
/* we always create one sd slot, even if no card is in it */
drive_add(NULL, SD_ALIAS);
}
/* open the virtual block devices */
if (snapshot)
@@ -5642,32 +5866,6 @@ int main(int argc, char **argv, char **envp)
register_savevm_live("ram", 0, 3, NULL, ram_save_live, NULL,
ram_load, NULL);
/* Maintain compatibility with multiple stdio monitors */
if (!strcmp(monitor_devices[0],"stdio")) {
for (i = 0; i < MAX_SERIAL_PORTS; i++) {
const char *devname = serial_devices[i];
if (devname && !strcmp(devname,"mon:stdio")) {
monitor_devices[0] = NULL;
break;
} else if (devname && !strcmp(devname,"stdio")) {
monitor_devices[0] = NULL;
serial_devices[i] = "mon:stdio";
break;
}
}
for (i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
const char *devname = virtio_consoles[i];
if (devname && !strcmp(devname,"mon:stdio")) {
monitor_devices[0] = NULL;
break;
} else if (devname && !strcmp(devname,"stdio")) {
monitor_devices[0] = NULL;
virtio_consoles[i] = "mon:stdio";
break;
}
}
}
if (nb_numa_nodes > 0) {
int i;
@@ -5710,65 +5908,12 @@ int main(int argc, char **argv, char **envp)
}
}
for (i = 0; i < MAX_MONITOR_DEVICES; i++) {
const char *devname = monitor_devices[i];
if (devname && strcmp(devname, "none")) {
char label[32];
if (i == 0) {
snprintf(label, sizeof(label), "monitor");
} else {
snprintf(label, sizeof(label), "monitor%d", i);
}
monitor_hds[i] = qemu_chr_open(label, devname, NULL);
if (!monitor_hds[i]) {
fprintf(stderr, "qemu: could not open monitor device '%s'\n",
devname);
exit(1);
}
}
}
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
const char *devname = serial_devices[i];
if (devname && strcmp(devname, "none")) {
char label[32];
snprintf(label, sizeof(label), "serial%d", i);
serial_hds[i] = qemu_chr_open(label, devname, NULL);
if (!serial_hds[i]) {
fprintf(stderr, "qemu: could not open serial device '%s': %s\n",
devname, strerror(errno));
exit(1);
}
}
}
for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
const char *devname = parallel_devices[i];
if (devname && strcmp(devname, "none")) {
char label[32];
snprintf(label, sizeof(label), "parallel%d", i);
parallel_hds[i] = qemu_chr_open(label, devname, NULL);
if (!parallel_hds[i]) {
fprintf(stderr, "qemu: could not open parallel device '%s': %s\n",
devname, strerror(errno));
exit(1);
}
}
}
for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
const char *devname = virtio_consoles[i];
if (devname && strcmp(devname, "none")) {
char label[32];
snprintf(label, sizeof(label), "virtcon%d", i);
virtcon_hds[i] = qemu_chr_open(label, devname, NULL);
if (!virtcon_hds[i]) {
fprintf(stderr, "qemu: could not open virtio console '%s': %s\n",
devname, strerror(errno));
exit(1);
}
}
}
if (foreach_device_config(DEV_SERIAL, serial_parse) < 0)
exit(1);
if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0)
exit(1);
if (foreach_device_config(DEV_VIRTCON, virtcon_parse) < 0)
exit(1);
module_call_init(MODULE_INIT_DEVICE);
@@ -5779,8 +5924,10 @@ int main(int argc, char **argv, char **envp)
}
if (machine->compat_props) {
qdev_prop_register_compat(machine->compat_props);
qdev_prop_register_global_list(machine->compat_props);
}
qemu_add_globals();
machine->init(ram_size, boot_devices,
kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
@@ -5873,35 +6020,8 @@ int main(int argc, char **argv, char **envp)
text_consoles_set_display(display_state);
for (i = 0; i < MAX_MONITOR_DEVICES; i++) {
if (monitor_devices[i] && monitor_hds[i]) {
monitor_init(monitor_hds[i], monitor_flags[i]);
}
}
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
const char *devname = serial_devices[i];
if (devname && strcmp(devname, "none")) {
if (strstart(devname, "vc", 0))
qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i);
}
}
for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
const char *devname = parallel_devices[i];
if (devname && strcmp(devname, "none")) {
if (strstart(devname, "vc", 0))
qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
}
}
for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
const char *devname = virtio_consoles[i];
if (virtcon_hds[i] && devname) {
if (strstart(devname, "vc", 0))
qemu_chr_printf(virtcon_hds[i], "virtio console%d\r\n", i);
}
}
if (qemu_opts_foreach(&qemu_mon_opts, mon_init_func, NULL, 1) != 0)
exit(1);
if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) {
fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n",

203
vnc.c
View File

@@ -29,6 +29,7 @@
#include "qemu_socket.h"
#include "qemu-timer.h"
#include "acl.h"
#include "qemu-objects.h"
#define VNC_REFRESH_INTERVAL_BASE 30
#define VNC_REFRESH_INTERVAL_INC 50
@@ -99,6 +100,54 @@ char *vnc_socket_remote_addr(const char *format, int fd) {
return addr_to_string(format, &sa, salen);
}
static int put_addr_qdict(QDict *qdict, struct sockaddr_storage *sa,
socklen_t salen)
{
char host[NI_MAXHOST];
char serv[NI_MAXSERV];
int err;
if ((err = getnameinfo((struct sockaddr *)sa, salen,
host, sizeof(host),
serv, sizeof(serv),
NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
VNC_DEBUG("Cannot resolve address %d: %s\n",
err, gai_strerror(err));
return -1;
}
qdict_put(qdict, "host", qstring_from_str(host));
qdict_put(qdict, "service", qstring_from_str(serv));
return 0;
}
static int vnc_qdict_local_addr(QDict *qdict, int fd)
{
struct sockaddr_storage sa;
socklen_t salen;
salen = sizeof(sa);
if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0) {
return -1;
}
return put_addr_qdict(qdict, &sa, salen);
}
static int vnc_qdict_remote_addr(QDict *qdict, int fd)
{
struct sockaddr_storage sa;
socklen_t salen;
salen = sizeof(sa);
if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0) {
return -1;
}
return put_addr_qdict(qdict, &sa, salen);
}
static const char *vnc_auth_name(VncDisplay *vd) {
switch (vd->auth) {
case VNC_AUTH_INVALID:
@@ -150,58 +199,140 @@ static const char *vnc_auth_name(VncDisplay *vd) {
return "unknown";
}
static void do_info_vnc_client(Monitor *mon, VncState *client)
static QDict *do_info_vnc_client(Monitor *mon, VncState *client)
{
char *clientAddr =
vnc_socket_remote_addr(" address: %s:%s\n",
client->csock);
if (!clientAddr)
return;
QDict *qdict;
monitor_printf(mon, "Client:\n");
monitor_printf(mon, "%s", clientAddr);
free(clientAddr);
qdict = qdict_new();
if (vnc_qdict_remote_addr(qdict, client->csock) < 0) {
QDECREF(qdict);
return NULL;
}
#ifdef CONFIG_VNC_TLS
if (client->tls.session &&
client->tls.dname)
monitor_printf(mon, " x509 dname: %s\n", client->tls.dname);
else
monitor_printf(mon, " x509 dname: none\n");
client->tls.dname) {
qdict_put(qdict, "x509_dname", qstring_from_str(client->tls.dname));
}
#endif
#ifdef CONFIG_VNC_SASL
if (client->sasl.conn &&
client->sasl.username)
monitor_printf(mon, " username: %s\n", client->sasl.username);
else
monitor_printf(mon, " username: none\n");
client->sasl.username) {
qdict_put(qdict, "username", qstring_from_str(client->sasl.username));
}
#endif
return qdict;
}
static void info_vnc_iter(QObject *obj, void *opaque)
{
QDict *client;
Monitor *mon = opaque;
client = qobject_to_qdict(obj);
monitor_printf(mon, "Client:\n");
monitor_printf(mon, " address: %s:%s\n",
qdict_get_str(client, "host"),
qdict_get_str(client, "service"));
#ifdef CONFIG_VNC_TLS
monitor_printf(mon, " x509_dname: %s\n",
qdict_haskey(client, "x509_dname") ?
qdict_get_str(client, "x509_dname") : "none");
#endif
#ifdef CONFIG_VNC_SASL
monitor_printf(mon, " username: %s\n",
qdict_haskey(client, "username") ?
qdict_get_str(client, "username") : "none");
#endif
}
void do_info_vnc(Monitor *mon)
void do_info_vnc_print(Monitor *mon, const QObject *data)
{
QDict *server;
QList *clients;
server = qobject_to_qdict(data);
if (strcmp(qdict_get_str(server, "status"), "disabled") == 0) {
monitor_printf(mon, "Server: disabled\n");
return;
}
monitor_printf(mon, "Server:\n");
monitor_printf(mon, " address: %s:%s\n",
qdict_get_str(server, "host"),
qdict_get_str(server, "service"));
monitor_printf(mon, " auth: %s\n",
qdict_haskey(server, "auth") ? qdict_get_str(server, "auth") : "none");
clients = qdict_get_qlist(server, "clients");
if (qlist_empty(clients)) {
monitor_printf(mon, "Client: none\n");
} else {
qlist_iter(clients, info_vnc_iter, mon);
}
}
/**
* do_info_vnc(): Show VNC server information
*
* Return a QDict with server information. Connected clients are returned
* as a QList of QDicts.
*
* The main QDict contains the following:
*
* - "status": "disabled" or "enabled"
* - "host": server's IP address
* - "service": server's port number
* - "auth": authentication method (optional)
* - "clients": a QList of all connected clients
*
* Clients are described by a QDict, with the following information:
*
* - "host": client's IP address
* - "service": client's port number
* - "x509_dname": TLS dname (optional)
* - "username": SASL username (optional)
*
* Example:
*
* { "status": "enabled", "host": "0.0.0.0", "service": "50402", "auth": "vnc",
* "clients": [ { "host": "127.0.0.1", "service": "50401" } ] }
*/
void do_info_vnc(Monitor *mon, QObject **ret_data)
{
if (vnc_display == NULL || vnc_display->display == NULL) {
monitor_printf(mon, "Server: disabled\n");
*ret_data = qobject_from_jsonf("{ 'status': 'disabled' }");
} else {
char *serverAddr = vnc_socket_local_addr(" address: %s:%s\n",
vnc_display->lsock);
if (!serverAddr)
return;
monitor_printf(mon, "Server:\n");
monitor_printf(mon, "%s", serverAddr);
free(serverAddr);
monitor_printf(mon, " auth: %s\n", vnc_auth_name(vnc_display));
QDict *qdict;
QList *clist;
clist = qlist_new();
if (vnc_display->clients) {
VncState *client = vnc_display->clients;
while (client) {
do_info_vnc_client(mon, client);
qdict = do_info_vnc_client(mon, client);
if (qdict)
qlist_append(clist, qdict);
client = client->next;
}
} else {
monitor_printf(mon, "Client: none\n");
}
*ret_data = qobject_from_jsonf("{ 'status': 'enabled', 'clients': %p }",
QOBJECT(clist));
assert(*ret_data != NULL);
qdict = qobject_to_qdict(*ret_data);
if (vnc_display->auth != VNC_AUTH_NONE) {
qdict_put(qdict, "auth",
qstring_from_str(vnc_auth_name(vnc_display)));
}
if (vnc_qdict_local_addr(qdict, vnc_display->lsock) < 0) {
qobject_decref(*ret_data);
*ret_data = NULL;
}
}
}
@@ -1506,11 +1637,13 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
static void key_event(VncState *vs, int down, uint32_t sym)
{
int keycode;
int lsym = sym;
if (sym >= 'A' && sym <= 'Z' && is_graphic_console())
sym = sym - 'A' + 'a';
if (lsym >= 'A' && lsym <= 'Z' && is_graphic_console()) {
lsym = lsym - 'A' + 'a';
}
keycode = keysym2scancode(vs->vd->kbd_layout, sym & 0xFFFF);
keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF);
do_key_event(vs, down, keycode, sym);
}