Compare commits

..

79 Commits

Author SHA1 Message Date
Gabriel L. Somlo
c97294ec1b SMBIOS: Build aggregate smbios tables and entry point
Build an aggregate set of smbios tables and an entry point structure.

Insert tables and entry point into fw_cfg respectively under
"etc/smbios/smbios-tables" and "etc/smbios/smbios-anchor".

Machine types <= 2.0 will for now continue using field-by-field
overrides to SeaBIOS defaults, but for machine types 2.1 and up we
expect the BIOS to look for and use the aggregate tables generated
by this patch.

Signed-off-by: Gabriel Somlo <somlo@cmu.edu>

[ kraxel: fix 32bit build ]

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-05 13:14:48 +02:00
Gabriel L. Somlo
2e6e8d7a25 SMBIOS: Use bitmaps to prevent incompatible comand line options
Replace existing smbios_check_collision() functionality with
a pair of bitmaps: have_binfile_bitmap and have_fields_bitmap.
Bits corresponding to each smbios type are set by smbios_entry_add(),
which also uses the bitmaps to ensure that binary blobs and field
values are never accepted for the same type.

These bitmaps will also be used in the future to decide whether
or not to build a full table for a given smbios type.

Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-05 12:29:39 +02:00
Gabriel L. Somlo
cb36acb672 SMBIOS: Use macro to set smbios defaults
The function smbios_set_defaults() uses a repeating code pattern
for each field. This patch replaces that pattern with a macro.

This patch contains no functional changes.

Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-05 12:29:39 +02:00
Gabriel L. Somlo
e41fca3da7 SMBIOS: Update header file definitions
Add definitions for smbios entry point (anchor), and for type 2
(base board) structure which is required by some versions of OS X.

Remove definition for type 20 (memory device mapped address)
structure, which is no longer required as of smbios spec v2.5.

Update all other structure definitions to bring them into
compliance with smbios spec v2.8.

This patch contains no functional changes.

Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-05 12:29:39 +02:00
Gabriel L. Somlo
e6667f719c SMBIOS: Rename symbols to better reflect future use
Rename the following symbols:

  - smbios_set_type1_defaults() to the more general smbios_set_defaults();
  - bool smbios_type1_defaults to the more general smbios_defaults;
  - smbios_get_table() to smbios_get_table_legacy();

This patch contains no functional changes.

Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-05 12:29:39 +02:00
Gabriel L. Somlo
7bf8ef196e E820: Add interface for accessing e820 table
Add the following two functions:

  - e820_get_num_entries() - query the size of the e820 table
  - e820_get_entry() - grab an entry matching a given set of criteria

This interface is currently necessary for creating type 19
(memory array mapped address) structures in smbios.

Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-05 12:29:39 +02:00
Michael S. Tsirkin
3458b2b075 pc: add 2.1 machine type
At the moment, 2.1 and 2.0 machines are identical.
As several people are working on incompatible changes
to the PC machine, collaboration will be made easier
by merging this place-holder.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-05 12:29:39 +02:00
Peter Maydell
fdaad4715a Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20140501' into staging
target-arm queue:
 * implement XScale cache lockdown cp15 ops
 * fix v7M CPUID base register
 * implement WFE and YIELD as yields for A64
 * fix A64 "BLR LR"
 * support Cortex-A57 in virt machine model
 * a few other minor AArch64 bugfixes

# gpg: Signature made Thu 01 May 2014 15:42:17 BST using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"

* remotes/pmaydell/tags/pull-target-arm-20140501:
  hw/arm/virt: Add support for Cortex-A57
  hw/arm/virt: Put GIC register banks on 64K boundaries
  hw/arm/virt: Create the GIC ourselves rather than (ab)using a15mpcore_priv
  target-arm: Correct a comment refering to EL0
  target-arm: A64: Fix a typo when declaring TLBI ops
  target-arm: A64: Handle blr lr
  target-arm: Make vbar_write 64bit friendly on 32bit hosts
  target-arm: implement WFE/YIELD as a yield for AArch64
  armv7m_nvic: fix CPUID Base Register
  target-arm: Implement XScale cache lockdown operations as NOPs

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-05-02 11:32:00 +01:00
Peter Maydell
e50bf23438 Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block patches

# gpg: Signature made Wed 30 Apr 2014 19:19:32 BST using RSA key ID C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"

* remotes/kevin/tags/for-upstream: (31 commits)
  curl: Fix hang reading from slow connections
  curl: Ensure all informationals are checked for completion
  curl: Eliminate unnecessary use of curl_multi_socket_all
  curl: Remove unnecessary explicit calls to internal event handler
  curl: Remove erroneous sleep waiting for curl completion
  curl: Fix return from curl_read_cb with invalid state
  curl: Remove unnecessary use of goto
  curl: Fix long line
  block/vdi: Error out immediately in vdi_create()
  block/bochs: Fix error handling for seek_to_sector()
  qcow2: Check min_size in qcow2_grow_l1_table()
  qcow2: Catch bdrv_getlength() error
  block: Use correct width in format strings
  qcow2: Avoid overflow in alloc_clusters_noref()
  block: Use error_abort in bdrv_image_info_specific_dump()
  block: Fix open_flags in bdrv_reopen()
  Revert "block: another bdrv_append fix"
  block: Unlink temporary files in raw-posix/win32
  block: Remove BDRV_O_COPY_ON_READ for bs->file
  block: Create bdrv_backing_flags()
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-05-02 10:50:58 +01:00
Peter Maydell
c090c10dc4 Merge remote-tracking branch 'remotes/cohuck/tags/kvm_cap_helpers' into staging
Add helpers for enabling kvm capabilities and convert the existing
s390x and ppc users to use them.

# gpg: Signature made Wed 30 Apr 2014 14:48:45 BST using RSA key ID C6F02FAF
# gpg: Can't check signature: public key not found

* remotes/cohuck/tags/kvm_cap_helpers:
  ppc: use kvm_vcpu_enable_cap()
  s390x: use kvm_vcpu_enable_cap()
  kvm: add kvm_{vm,vcpu}_enable_cap

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-05-01 17:32:25 +01:00
Peter Maydell
87f6ede9bb Merge remote-tracking branch 'remotes/kraxel/tags/pull-vga-2' into staging
vga: add secondary stdvga variant

# gpg: Signature made Mon 28 Apr 2014 10:11:44 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-vga-2:
  add secondary-vga to display-vga test
  add display-vga test
  vga: add secondary stdvga variant
  vga: allow non-global vmstate

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-05-01 16:02:45 +01:00
Peter Maydell
f42c5c8ec8 hw/arm/virt: Add support for Cortex-A57
Support the Cortex-A57 in the virt machine model.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1398362083-17737-4-git-send-email-peter.maydell@linaro.org
2014-05-01 15:25:52 +01:00
Peter Maydell
3078e848fa hw/arm/virt: Put GIC register banks on 64K boundaries
For an AArch64 CPU which supports 64K pages, having the GIC
register banks at 4K offsets is potentially awkward. Move
them out to being at 64K offsets. (This is harmless for
AArch32 CPUs and for AArch64 CPUs with 4K pages, so it is simpler
to use the same offsets everywhere than to try to use 64K offsets
only for AArch64 host CPUs.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1398362083-17737-3-git-send-email-peter.maydell@linaro.org
2014-05-01 15:25:52 +01:00
Peter Maydell
6420474384 hw/arm/virt: Create the GIC ourselves rather than (ab)using a15mpcore_priv
Rather than having the virt machine model create an a15mpcore_priv
device regardless of the actual CPU type in order to instantiate the GIC,
move to having the machine model create the GIC directly. This
corresponds to a system which uses a standalone GIC (eg the GIC-400)
rather than the one built in to the CPU core.

The primary motivation for this is to support the Cortex-A57,
which for a KVM configuration will use a GICv2, which is not
built into the CPU.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1398362083-17737-2-git-send-email-peter.maydell@linaro.org
2014-05-01 15:24:46 +01:00
Edgar E. Iglesias
37f0806ed9 target-arm: Correct a comment refering to EL0
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1398926097-28097-5-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-05-01 15:24:46 +01:00
Edgar E. Iglesias
6ab9f49934 target-arm: A64: Fix a typo when declaring TLBI ops
Harmless typo as opc1 defaults to zero and opc2 gets
re-declared to its correct value.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1398926097-28097-4-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-05-01 15:24:46 +01:00
Edgar E. Iglesias
1b505f93bc target-arm: A64: Handle blr lr
For linked branches, updates to the link register happen
conceptually after the read of the branch target register.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Cc: qemu-stable@nongnu.org
Message-id: 1398926097-28097-3-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-05-01 15:24:45 +01:00
Edgar E. Iglesias
fed3ffb9f1 target-arm: Make vbar_write 64bit friendly on 32bit hosts
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1398926097-28097-2-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-05-01 15:24:45 +01:00
Rob Herring
252ec40576 target-arm: implement WFE/YIELD as a yield for AArch64
Like was done for AArch32 for WFE, implement both WFE and YIELD as a
yield operation. This speeds up multi-core system emulation.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
Message-id: 1397588401-20366-1-git-send-email-robherring2@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-05-01 15:24:45 +01:00
Rabin Vincent
e3da9921eb armv7m_nvic: fix CPUID Base Register
cp15.c0_cpuid is never initialized for ARMv7-M; take the value directly
from cpu->midr instead.

Signed-off-by: Rabin Vincent <rabin@rab.in>
Message-id: 1398036308-32166-1-git-send-email-rabin@rab.in
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-05-01 15:24:44 +01:00
Peter Maydell
3b77157964 target-arm: Implement XScale cache lockdown operations as NOPs
XScale defines some implementation-specific coprocessor registers
for doing cache lockdown operations. Since QEMU doesn't model a
cache no proper implementation is possible, but NOP out the
registers so that guest code like u-boot that tries to use them
doesn't crash.

Reported-by: <prqek@centrum.cz>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-05-01 15:24:44 +01:00
Peter Maydell
051b9980b9 Merge remote-tracking branch 'remotes/kraxel/tags/pull-gtk-6' into staging
gtk: collection of fixes and cleanups by Cole Robinson

# gpg: Signature made Tue 29 Apr 2014 10:44:44 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-gtk-6:
  gtk: Fix accelerators being triggered twice with gtk3
  gtk: Fix -serial vc
  gtk: Use ctrl+alt+q for quit accelerator
  gtk: Remove use of deprecated stock items
  gtk: Don't use deprecated vte_terminal_get_adjustment
  gtk: Don't use deprecated gtk_image_menu_item_new_with_mnemonic
  configure: Re-run make if gtkabi/sdlabi is changed
  configure: Document --with-gtkabi

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-05-01 14:17:33 +01:00
Peter Maydell
52b08670e2 Merge remote-tracking branch 'remotes/kraxel/tags/pull-sdl-2' into staging
sdl2: mouse wheel support, ui config notify

# gpg: Signature made Tue 29 Apr 2014 11:17:01 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-sdl-2:
  sdl2: Support mouse wheel
  sdl2: add ui info setting.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-05-01 13:51:23 +01:00
Peter Maydell
61e5b75c17 Merge remote-tracking branch 'remotes/kraxel/tags/pull-audio-4' into staging
hda-audio: fix non-mixer codecs

# gpg: Signature made Tue 29 Apr 2014 10:03:44 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-audio-4:
  hda-audio: fix non-mixer codecs

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-05-01 13:05:54 +01:00
Matthew Booth
b7079df410 curl: Fix hang reading from slow connections
When receiving a new aio read request, we first look for an existing
transaction whose range will cover the read request by the time it
completes. However, we weren't checking that the existing transaction
was still active. If it had timed out, we were adding the request to a
transaction which would never complete and had already been cancelled,
resulting in a hang.

Signed-off-by: Matthew Booth <mbooth@redhat.com>
Tested-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 16:34:21 +02:00
Matthew Booth
1f2cead324 curl: Ensure all informationals are checked for completion
According to the documentation, the correct way to ensure all
informationals have been returned by curl_multi_info_read is to loop
until it returns NULL.

Signed-off-by: Matthew Booth <mbooth@redhat.com>
Tested-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 16:34:18 +02:00
Matthew Booth
838ef60249 curl: Eliminate unnecessary use of curl_multi_socket_all
curl_multi_socket_all is a deprecated catch-all which checks for
activities on all open curl sockets. We have enough information from
the event loop to check only the sockets with activity. This change
removes use of curl_multi_socket_all in favour of
curl_multi_socket_action called with the relevant handle.

At the same time, it also ensures that the driver only checks for
completion of read operations after reading from a socket, rather than
both reading and writing.

Signed-off-by: Matthew Booth <mbooth@redhat.com>
Tested-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 16:34:16 +02:00
Matthew Booth
b69cdef876 curl: Remove unnecessary explicit calls to internal event handler
Remove calls to curl_multi_do where the relevant handles are already
registered to the event loop.

Ensure that we kick off socket handling with CURL_SOCKET_TIMEOUT after
adding a new handle.

Signed-off-by: Matthew Booth <mbooth@redhat.com>
Tested-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 16:34:14 +02:00
Matthew Booth
e466183718 curl: Remove erroneous sleep waiting for curl completion
The driver will not start more than a fixed number of curl sessions.
If it needs more, it must wait for the completion of an existing one.
The driver was sleeping, which will prevent the main loop from
running, and therefore the event it's waiting on. It was also directly
calling its internal handler rather than waiting on existing
registered handlers to be called from the main loop.

This change causes it simply to wait for a period of time whilst
allowing the main loop to execute.

Signed-off-by: Matthew Booth <mbooth@redhat.com>
Tested-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 16:34:11 +02:00
Matthew Booth
38bbc0a580 curl: Fix return from curl_read_cb with invalid state
A curl write callback is supposed to return the number of bytes it
handled.  curl_read_cb would have erroneously reported it had handled
all bytes in the event that the internal curl state was invalid.

Signed-off-by: Matthew Booth <mbooth@redhat.com>
Tested-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 16:34:08 +02:00
Matthew Booth
9e550b3260 curl: Remove unnecessary use of goto
This isn't any of the usually acceptable uses of goto.

Signed-off-by: Matthew Booth <mbooth@redhat.com>
Tested-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 16:34:06 +02:00
Matthew Booth
f6246509be curl: Fix long line
Signed-off-by: Matthew Booth <mbooth@redhat.com>
Tested-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 16:33:39 +02:00
Max Reitz
0549ea8b6d block/vdi: Error out immediately in vdi_create()
Currently, if an error occurs during the part of vdi_create() which
actually writes the image, the function stores -errno, but continues
anyway.

Instead of trying to write data which (if it can be written at all) does
not make any sense without the operations before succeeding (e.g.,
writing the image header), just error out immediately.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 14:46:17 +02:00
Max Reitz
e1b42f456f block/bochs: Fix error handling for seek_to_sector()
Currently, seek_to_sector() returns -1 both for errors and unallocated
sectors, resulting in silent errors. As 0 is an invalid offset of data
clusters (bitmap_offset is greater than 0 because s->data_offset is
greater than 0), just return 0 for unallocated sectors and -errno in
case of error. This should then be propagated by bochs_read(), the sole
user of seek_to_sector().

That function also has a case of "return -1 in case of error", which is
fixed by this patch as well.

bochs_read() is called by bochs_co_read() which passes the return value
through, therefore it is indeed correct for bochs_read() to return
-errno.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 14:46:17 +02:00
Max Reitz
b93f995081 qcow2: Check min_size in qcow2_grow_l1_table()
First, new_l1_size is an int64_t, whereas min_size is a uint64_t.
Therefore, during the loop which adjusts new_l1_size until it equals or
exceeds min_size, new_l1_size might overflow and become negative. The
comparison in the loop condition however will take it as an unsigned
value (because min_size is unsigned) and therefore recognize it as
exceeding min_size. Therefore, the loop is left with a negative
new_l1_size, which is not correct. This could be fixed by making
new_l1_size uint64_t.

On the other hand, however, by doing this, the while loop may take
forever. If min_size is e.g. UINT64_MAX, it will take new_l1_size
probably multiple overflows to reach the exact same value (if it reaches
it at all). Then, right after the loop, new_l1_size will be recognized
as being too big anyway.

Both problems require a ridiculously high min_size value, which is very
unlikely to occur; but both problems are also simply avoided by checking
whether min_size is sane before calculating new_l1_size (which should
still be checked separately, though).

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 14:46:17 +02:00
Max Reitz
a49139af77 qcow2: Catch bdrv_getlength() error
The call to bdrv_getlength() from qcow2_check_refcounts() may result in
an error. Check this and abort if necessary.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 14:46:17 +02:00
Max Reitz
521b2b5df0 block: Use correct width in format strings
Instead of blindly relying on a normal integer having a width of 32 bits
(which is a pretty good assumption, but we should not rely on it if
there is no need), use the correct format string macros.

This does not touch DEBUG output.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 14:46:17 +02:00
Max Reitz
91f827dcff qcow2: Avoid overflow in alloc_clusters_noref()
alloc_clusters_noref() stores the cluster index in a uint64_t. However,
offsets are often represented as int64_t (as for example the return
value of alloc_clusters_noref() itself demonstrates). Therefore, we
should make sure all offsets in the allocated range of clusters are
representable using int64_t without overflows.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 14:46:13 +02:00
Cornelia Huck
48add816cf ppc: use kvm_vcpu_enable_cap()
Convert existing users of KVM_ENABLE_CAP to new helper.

Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-04-30 14:39:58 +02:00
Cornelia Huck
e080f0fdff s390x: use kvm_vcpu_enable_cap()
Make kvm_s390_enable_css_support() use new interface.

Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-04-30 14:39:49 +02:00
Cornelia Huck
40f1ee27aa kvm: add kvm_{vm,vcpu}_enable_cap
Provide helper functions for enabling capabilities (on a vcpu and on a vm).

Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-04-30 14:39:39 +02:00
Max Reitz
35d0d40a03 block: Use error_abort in bdrv_image_info_specific_dump()
Currently, bdrv_image_info_specific_dump() uses an error variable for
visit_type_ImageInfoSpecific, but ignores the result. As this function
is used here with an output visitor to transform the ImageInfoSpecific
object to a generic QDict, an error should actually be impossible. It is
however better to assert that this is indeed the case. This is done by
this patch using error_abort instead of an unused local Error variable.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reported-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-30 12:43:30 +02:00
Kevin Wolf
f1f25a2e2e block: Fix open_flags in bdrv_reopen()
Use the same function as bdrv_open() for determining what the right
flags for bs->file are. Without doing this, a reopen means that
bs->file loses BDRV_O_CACHE_WB or BDRV_O_UNMAP if bs doesn't have it as
well.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2014-04-30 11:05:00 +02:00
Kevin Wolf
7e3d98dd31 Revert "block: another bdrv_append fix"
This reverts commit 3a389e7926. The commit
was wrong and what it tried to fix just works today without any change.

What the commit tried to fix:

    When creating live snapshots, the new image file is opened with
    BDRV_O_NO_BACKING because the whole backing chain is already opened.
    It is then appended to the chain using bdrv_append(). The result of
    this was that the image had a backing file, but BDRV_O_NO_BACKING
    was still set. This is obviously inconsistent.

    There used to be some places in qemu that closed and image and then
    opened it again, with its old flags (a bdrv_open()/close() sequence
    involves reopening the whole backing file chain, too). In this case
    the BDRV_O_NO_BACKING flag meant that the backing chain wasn't
    reopened and only the top layer was left.

    (Most, but not all of these places are replaced by bdrv_reopen()
    today, which doesn't touch the backing files at all.)

    Other places that looked at bs->open_flags weren't interested in
    BDRV_O_NO_BACKING, so no breakage there.

What it actually did:

    The commit moved the BDRV_O_NO_BACKING away to the backing file.
    Because the bdrv_open()/close() sequences only looked at the flags
    of the top level BlockDriverState and used it for the whole chain,
    the flag didn't hurt there any more. Obviously, it is still
    inconsistent because the backing file may have another backing file,
    but without practical impact.

    At the same time, it swapped all other flags. This is practically
    irrelevant as long as live snapshots only allow opening the new
    layer with the same flags as the old top layer. It still doesn't
    make any sense, and it is a time bomb that explodes as soon as the
    flags can differ.

    bdrv_append_temp_snapshot() is such a case: It adds the new flag
    BDRV_O_TEMPORARY for the temporary snapshot. The swapping of commit
    3a389e79 results in the following nonsensical configuration:

    bs->open_flags:                     BDRV_O_TEMPORARY cleared
    bs->file->open_flags:               BDRV_O_TEMPORARY set
    bs->backing_hd->open_flags:         BDRV_O_TEMPORARY set
    bs->backing_hd->file->open_flags:   BDRV_O_TEMPORARY cleared

    We're still lucky because the format layer ignores the flag and the
    protocol layer happens to get the right value, but sooner or later
    this is bound to go wrong...

What the right fix would have been:

    Simply clear the BDRV_O_NO_BACKING flag when the BlockDriverState is
    appended to an existing backing file chain, because now it does have
    a backing file.

    Commit 4ddc07ca already implemented this silently in bdrv_append(),
    so we don't have to come up with a new fix.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2014-04-30 11:05:00 +02:00
Kevin Wolf
8bfea15dda block: Unlink temporary files in raw-posix/win32
Instead of having unlink() calls in the generic block layer, where we
aren't even guarateed to have a file name, move them to those block
drivers that are actually used and that always have a filename. Gets us
rid of some #ifdefs as well.

The patch also converts bs->is_temporary to a new BDRV_O_TEMPORARY open
flag so that it is inherited in the protocol layer and the raw-posix and
raw-win32 drivers can unlink the file.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2014-04-30 11:05:00 +02:00
Kevin Wolf
5669b44de5 block: Remove BDRV_O_COPY_ON_READ for bs->file
Copy on Read makes sense on the format level where backing files are
implemented, but it's not required on the protocol level. While it
shouldn't actively break anything to have COR enabled on both layers,
needless serialisation and allocation checks may impact performance.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2014-04-30 11:05:00 +02:00
Kevin Wolf
317fc44ef2 block: Create bdrv_backing_flags()
Instead of manipulation flags inline, move the derivation of the flags
of a backing file into a new function next to the existing functions
that derive flags for bs->file and for the block driver open function.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2014-04-30 11:05:00 +02:00
Kevin Wolf
0b50cc8853 block: Create bdrv_inherited_flags()
Instead of having bdrv_open_flags() as a function that creates flags for
several unrelated places and then adding open-coded flags on top, create
a new function that derives the flags for bs->file from the flags for bs.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2014-04-30 11:05:00 +02:00
Max Reitz
cffb12051a iotests: Discarding compressed clusters on qcow2
Add a test which discards a compressed cluster on qcow2. This should
work without any problems.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-29 16:39:51 +02:00
Max Reitz
c883db0df9 qcow2: Fix discard
discard_single_l2() should not implement its own version of
qcow2_get_cluster_type(), but rather rely on this already existing
function. By doing so, it will work for compressed clusters as well
(which it did not so far).

Also, rename "old_offset" to "old_l2_entry", as both are quite different
(and the value is indeed of the latter kind).

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-29 16:39:51 +02:00
Jeff Cody
cc8a7e560c block: qemu-iotests: make test 019 and 086 work with spaced pathnames
Both tests 019 and 086 need proper quotations to work with pathnames
that contain spaces.

Reviewed-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-29 16:19:37 +02:00
Jeff Cody
c557527455 block: qemu-iotests - fix image cleanup when using spaced pathnames
The _rm_test_img() function in common.rc did not quote the image
file, which left droppings in the scratch directory (and performed
a potentially unsafe rm -f).

This adds the necessary quotes.

Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-29 16:19:33 +02:00
Peter Maydell
b006f8162e Merge remote-tracking branch 'remotes/rth/tags/tcg-sparc-pull-20140428' into staging
TCG sparc backend update for 20140428

# gpg: Signature made Mon 28 Apr 2014 19:36:55 BST using RSA key ID 4DD0279B
# gpg: Can't check signature: public key not found

* remotes/rth/tags/tcg-sparc-pull-20140428:
  tcg-sparc: Accept stores of zero
  tcg-sparc: Fix small 32-bit movi
  tcg-sparc: Fixup function argument types
  tcg-sparc: Hoist common argument loads in tcg_out_op
  tcg-sparc: Don't handle mov/movi in tcg_out_op
  tcg-sparc: Tidy check_fit_* tests
  tcg-sparc: Implement muls2_i32
  tcg-sparc: Use the RETURN instruction
  tcg-sparc: Use 64-bit registers with sparcv8plus
  tcg-sparc: Support trunc_shr_i32
  tcg-sparc: Remove most uses of TCG_TARGET_REG_BITS
  tcg: Add INDEX_op_trunc_shr_i32
  tcg: Fix missed pointer size != TCG_TARGET_REG_BITS changes

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-04-29 13:03:25 +01:00
Fam Zheng
c3cc95bd15 mirror: Check for bdrv_get_info result
bdrv_get_info could fail. Add check before using the returned value.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-29 13:43:08 +02:00
Fam Zheng
373df5b135 mirror: Fix resource leak when bdrv_getlength fails
The direct return will skip releasing of all the resouces at
immediate_exit, don't miss that.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-29 13:43:00 +02:00
Jeff Cody
e855e4fb7b block: Ignore duplicate or NULL format_name in bdrv_iterate_format
Some block drivers have multiple BlockDriver instances with identical
format_name fields (e.g. gluster, nbd).

Both qemu-img and qemu will use bdrv_iterate_format() to list the
supported formats when a help option is invoked.  As protocols and
formats may register multiple drivers, redundant listings of formats
occur (e.g., "Supported formats: ... gluster gluster gluster gluster ...
").

Since the list of driver formats will be small, this performs a simple
linear search on format_name, and ignores any duplicates.

The end result change is that the iterator will no longer receive
duplicate string names, nor will it receive NULL pointers.

Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-29 11:58:07 +02:00
Cole Robinson
3f2fde2a00 sdl2: Support mouse wheel
In SDL2, wheel movement is its own event, not a button event. Wire
it up similar to gtk.c

Signed-off-by: Cole Robinson <crobinso@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-29 10:46:33 +02:00
Dave Airlie
8b15d9f1d2 sdl2: add ui info setting.
Allows you to resize the sdl2 window and have the guest notice.

[ kraxel: zero-initialize QemuUIInfo ]

Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-29 10:46:33 +02:00
Gerd Hoffmann
4843877e5d hda-audio: fix non-mixer codecs
They don't advertise mixer support, but still allow the guest change
mixer settings.  Add a check to avoid it.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-29 10:46:29 +02:00
Jeff Cody
5f6979cba9 block: Add '--version' option to qemu-img
This allows qemu-img to print out version information, without
needing to print the long help wall of text.

While there, perform some minor whitespace cleanup, and remove the
unused option_index variable in the call to getopt_long().

Reported-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-29 10:36:35 +02:00
Richard Henderson
ebd0c614d7 tcg-sparc: Accept stores of zero
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-28 11:06:35 -07:00
Richard Henderson
035b239826 tcg-sparc: Fix small 32-bit movi
We tested imm13 before discarding garbage high bits.

Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-28 11:06:35 -07:00
Richard Henderson
35e2da1556 tcg-sparc: Fixup function argument types
Use TCGReg everywhere appropriate.  Use int32_t for all arguments
that may be registers or immediate constants.  Merge tcg_out_addi
into its only caller.

Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-28 11:06:35 -07:00
Richard Henderson
b357f902bf tcg-sparc: Hoist common argument loads in tcg_out_op
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-28 11:06:35 -07:00
Richard Henderson
98b90bab3f tcg-sparc: Don't handle mov/movi in tcg_out_op
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-28 11:06:35 -07:00
Richard Henderson
425532d71d tcg-sparc: Tidy check_fit_* tests
Use sextract instead of raw bit shifting for the tests.  Introduce
a new check_fit_ptr macro to make it clear we're looking at pointers.

Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-28 11:06:35 -07:00
Richard Henderson
f4c166619e tcg-sparc: Implement muls2_i32
Using the 32-bit SMUL is a tad more efficient than
resorting to extending and using the 64-bit MULX.

Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-28 11:06:35 -07:00
Richard Henderson
8b66eefe0d tcg-sparc: Use the RETURN instruction
Saves one insn per TB exit over JMPL+RESTORE.

Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-28 11:06:35 -07:00
Richard Henderson
34b1a49cb1 tcg-sparc: Use 64-bit registers with sparcv8plus
Quite a lot of effort was spent composing and decomposing 64-bit
quantities in registers, when we should just create them and leave
them as one 64-bit register.

Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-28 11:06:35 -07:00
Richard Henderson
a24fba935a tcg-sparc: Support trunc_shr_i32
Unlike a 64-bit shift op, allows the output to be in %l or %i registers
for sparcv8plus.

Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-28 11:06:35 -07:00
Richard Henderson
9f44adc573 tcg-sparc: Remove most uses of TCG_TARGET_REG_BITS
Replace with SPARC64 define.  Soon even sparcv8plus will use
64-bit register as far as TCG is concerned.

Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-28 11:06:35 -07:00
Richard Henderson
4bb7a41ed6 tcg: Add INDEX_op_trunc_shr_i32
Let the backend do something special for truncation.

Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-28 11:06:34 -07:00
Richard Henderson
71b926992e tcg: Fix missed pointer size != TCG_TARGET_REG_BITS changes
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-04-28 11:06:34 -07:00
Fam Zheng
f0e9736012 mirror: Use DIV_ROUND_UP
Although bdrv_getlength() was just called above this, and checked for
error, it is better to just use the value we already get, and use
DIV_ROUND_UP.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-28 17:36:30 +02:00
Jeff Cody
7db1689c35 block: fix qemu-img --help invocation
This fixes a bug introduced in commit ac1307ab, that caused the
'--help' option to not be recognized as a valid command, and not
print any help.

Signed-off-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-04-28 17:36:30 +02:00
Gerd Hoffmann
a889bc2bb2 add secondary-vga to display-vga test
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-28 11:03:39 +02:00
Gerd Hoffmann
0850fd583f add display-vga test
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-28 11:03:35 +02:00
Gerd Hoffmann
63e3e24db2 vga: add secondary stdvga variant
Add a standard vga variant which doesn't occupy any legacy
resources and thus can easily be used as secondary (or legacy-free)
graphics adapter.  Programming must be done using the MMIO bar.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-28 11:03:32 +02:00
Gerd Hoffmann
e2bbfc8ee2 vga: allow non-global vmstate
Need a way to opt-out from vga.vram being global vmstate, for
secondary vga cards.  Add a bool parameter to vga_common_init
to support this.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-28 10:21:55 +02:00
68 changed files with 2064 additions and 913 deletions

106
block.c
View File

@@ -774,6 +774,45 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs)
bs->copy_on_read--;
}
/*
* Returns the flags that bs->file should get, based on the given flags for
* the parent BDS
*/
static int bdrv_inherited_flags(int flags)
{
/* Enable protocol handling, disable format probing for bs->file */
flags |= BDRV_O_PROTOCOL;
/* Our block drivers take care to send flushes and respect unmap policy,
* so we can enable both unconditionally on lower layers. */
flags |= BDRV_O_CACHE_WB | BDRV_O_UNMAP;
/* The backing file of a temporary snapshot is read-only */
if (flags & BDRV_O_SNAPSHOT) {
flags &= ~BDRV_O_RDWR;
}
/* Clear flags that only apply to the top layer */
flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ);
return flags;
}
/*
* Returns the flags that bs->backing_hd should get, based on the given flags
* for the parent BDS
*/
static int bdrv_backing_flags(int flags)
{
/* backing files always opened read-only */
flags &= ~(BDRV_O_RDWR | BDRV_O_COPY_ON_READ);
/* snapshot=on is handled on the top layer */
flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_TEMPORARY);
return flags;
}
static int bdrv_open_flags(BlockDriverState *bs, int flags)
{
int open_flags = flags | BDRV_O_CACHE_WB;
@@ -792,7 +831,7 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
/*
* Snapshots should be writable.
*/
if (bs->is_temporary) {
if (flags & BDRV_O_TEMPORARY) {
open_flags |= BDRV_O_RDWR;
}
@@ -951,13 +990,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
bdrv_refresh_limits(bs);
assert(bdrv_opt_mem_align(bs) != 0);
assert((bs->request_alignment != 0) || bs->sg);
#ifndef _WIN32
if (bs->is_temporary) {
assert(bs->filename[0] != '\0');
unlink(bs->filename);
}
#endif
return 0;
free_and_fail:
@@ -1069,7 +1101,7 @@ fail:
int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
{
char *backing_filename = g_malloc0(PATH_MAX);
int back_flags, ret = 0;
int ret = 0;
BlockDriver *back_drv = NULL;
Error *local_err = NULL;
@@ -1097,14 +1129,10 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
back_drv = bdrv_find_format(bs->backing_format);
}
/* backing files always opened read-only */
back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT |
BDRV_O_COPY_ON_READ);
assert(bs->backing_hd == NULL);
ret = bdrv_open(&bs->backing_hd,
*backing_filename ? backing_filename : NULL, NULL, options,
back_flags, back_drv, &local_err);
bdrv_backing_flags(bs->open_flags), back_drv, &local_err);
if (ret < 0) {
bs->backing_hd = NULL;
bs->open_flags |= BDRV_O_NO_BACKING;
@@ -1232,10 +1260,10 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
qstring_from_str(tmp_filename));
bs_snapshot = bdrv_new("", &error_abort);
bs_snapshot->is_temporary = 1;
ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
bs->open_flags & ~BDRV_O_SNAPSHOT, bdrv_qcow2, &local_err);
(bs->open_flags & ~BDRV_O_SNAPSHOT) | BDRV_O_TEMPORARY,
bdrv_qcow2, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
goto out;
@@ -1333,10 +1361,10 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
assert(file == NULL);
ret = bdrv_open_image(&file, filename, options, "file",
bdrv_open_flags(bs, flags | BDRV_O_UNMAP) |
BDRV_O_PROTOCOL, true, &local_err);
bdrv_inherited_flags(flags),
true, &local_err);
if (ret < 0) {
goto unlink_and_fail;
goto fail;
}
/* Find the right image format driver */
@@ -1347,7 +1375,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
if (!drv) {
error_setg(errp, "Invalid driver: '%s'", drvname);
ret = -EINVAL;
goto unlink_and_fail;
goto fail;
}
}
@@ -1357,18 +1385,18 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
} else {
error_setg(errp, "Must specify either driver or file");
ret = -EINVAL;
goto unlink_and_fail;
goto fail;
}
}
if (!drv) {
goto unlink_and_fail;
goto fail;
}
/* Open the image */
ret = bdrv_open_common(bs, file, options, flags, drv, &local_err);
if (ret < 0) {
goto unlink_and_fail;
goto fail;
}
if (file && (bs->file != file)) {
@@ -1430,14 +1458,10 @@ done:
*pbs = bs;
return 0;
unlink_and_fail:
fail:
if (file != NULL) {
bdrv_unref(file);
}
if (bs->is_temporary) {
unlink(filename);
}
fail:
QDECREF(bs->options);
QDECREF(options);
bs->options = NULL;
@@ -1501,8 +1525,11 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
QSIMPLEQ_INIT(bs_queue);
}
/* bdrv_open() masks this flag out */
flags &= ~BDRV_O_PROTOCOL;
if (bs->file) {
bdrv_reopen_queue(bs_queue, bs->file, flags);
bdrv_reopen_queue(bs_queue, bs->file, bdrv_inherited_flags(flags));
}
bs_entry = g_new0(BlockReopenQueueEntry, 1);
@@ -1717,11 +1744,6 @@ void bdrv_close(BlockDriverState *bs)
}
bs->drv->bdrv_close(bs);
g_free(bs->opaque);
#ifdef _WIN32
if (bs->is_temporary) {
unlink(bs->filename);
}
#endif
bs->opaque = NULL;
bs->drv = NULL;
bs->copy_on_read = 0;
@@ -1845,7 +1867,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
BlockDriverState *bs_src)
{
/* move some fields that need to stay attached to the device */
bs_dest->open_flags = bs_src->open_flags;
/* dev info */
bs_dest->dev_ops = bs_src->dev_ops;
@@ -3601,11 +3622,26 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
void *opaque)
{
BlockDriver *drv;
int count = 0;
const char **formats = NULL;
QLIST_FOREACH(drv, &bdrv_drivers, list) {
if (drv->format_name) {
bool found = false;
int i = count;
while (formats && i && !found) {
found = !strcmp(formats[--i], drv->format_name);
}
if (!found) {
formats = g_realloc(formats, (count + 1) * sizeof(char *));
formats[count++] = drv->format_name;
it(opaque, drv->format_name);
}
}
}
g_free(formats);
}
/* This function is to find block backend bs */
BlockDriverState *bdrv_find(const char *name)

View File

@@ -187,13 +187,14 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
uint64_t offset = sector_num * 512;
uint64_t extent_index, extent_offset, bitmap_offset;
char bitmap_entry;
int ret;
// seek to sector
extent_index = offset / s->extent_size;
extent_offset = (offset % s->extent_size) / 512;
if (s->catalog_bitmap[extent_index] == 0xffffffff) {
return -1; /* not allocated */
return 0; /* not allocated */
}
bitmap_offset = s->data_offset +
@@ -201,13 +202,14 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
(s->extent_blocks + s->bitmap_blocks));
/* read in bitmap for current extent */
if (bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
&bitmap_entry, 1) != 1) {
return -1;
ret = bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
&bitmap_entry, 1);
if (ret < 0) {
return ret;
}
if (!((bitmap_entry >> (extent_offset % 8)) & 1)) {
return -1; /* not allocated */
return 0; /* not allocated */
}
return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
@@ -220,13 +222,16 @@ static int bochs_read(BlockDriverState *bs, int64_t sector_num,
while (nb_sectors > 0) {
int64_t block_offset = seek_to_sector(bs, sector_num);
if (block_offset >= 0) {
if (block_offset < 0) {
return block_offset;
} else if (block_offset > 0) {
ret = bdrv_pread(bs->file, block_offset, buf, 512);
if (ret != 512) {
return -1;
if (ret < 0) {
return ret;
}
} else
} else {
memset(buf, 0, 512);
}
nb_sectors--;
sector_num++;
buf += 512;

View File

@@ -82,7 +82,7 @@ static int cow_open(BlockDriverState *bs, QDict *options, int flags,
if (be32_to_cpu(cow_header.version) != COW_VERSION) {
char version[64];
snprintf(version, sizeof(version),
"COW version %d", cow_header.version);
"COW version %" PRIu32, cow_header.version);
error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
bs->device_name, "cow", version);
ret = -ENOTSUP;

View File

@@ -71,6 +71,7 @@ typedef struct CURLState
struct BDRVCURLState *s;
CURLAIOCB *acb[CURL_NUM_ACB];
CURL *curl;
curl_socket_t sock_fd;
char *orig_buf;
size_t buf_start;
size_t buf_off;
@@ -92,6 +93,7 @@ typedef struct BDRVCURLState {
static void curl_clean_state(CURLState *s);
static void curl_multi_do(void *arg);
static void curl_multi_read(void *arg);
#ifdef NEED_CURL_TIMER_CALLBACK
static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
@@ -113,16 +115,20 @@ static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
void *s, void *sp)
{
CURLState *state = NULL;
curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state);
state->sock_fd = fd;
DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd);
switch (action) {
case CURL_POLL_IN:
qemu_aio_set_fd_handler(fd, curl_multi_do, NULL, s);
qemu_aio_set_fd_handler(fd, curl_multi_read, NULL, state);
break;
case CURL_POLL_OUT:
qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, s);
qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, state);
break;
case CURL_POLL_INOUT:
qemu_aio_set_fd_handler(fd, curl_multi_do, curl_multi_do, s);
qemu_aio_set_fd_handler(fd, curl_multi_read, curl_multi_do, state);
break;
case CURL_POLL_REMOVE:
qemu_aio_set_fd_handler(fd, NULL, NULL, NULL);
@@ -155,7 +161,7 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
DPRINTF("CURL: Just reading %zd bytes\n", realsize);
if (!s || !s->orig_buf)
goto read_end;
return 0;
if (s->buf_off >= s->buf_len) {
/* buffer full, read nothing */
@@ -180,7 +186,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
}
}
read_end:
return realsize;
}
@@ -215,7 +220,8 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
}
// Wait for unfinished chunks
if ((start >= state->buf_start) &&
if (state->in_use &&
(start >= state->buf_start) &&
(start <= buf_fend) &&
(end >= state->buf_start) &&
(end <= buf_fend))
@@ -237,26 +243,24 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
return FIND_RET_NONE;
}
static void curl_multi_read(BDRVCURLState *s)
static void curl_multi_check_completion(BDRVCURLState *s)
{
int msgs_in_queue;
/* Try to find done transfers, so we can free the easy
* handle again. */
do {
for (;;) {
CURLMsg *msg;
msg = curl_multi_info_read(s->multi, &msgs_in_queue);
/* Quit when there are no more completions */
if (!msg)
break;
if (msg->msg == CURLMSG_NONE)
break;
switch (msg->msg) {
case CURLMSG_DONE:
{
if (msg->msg == CURLMSG_DONE) {
CURLState *state = NULL;
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char**)&state);
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE,
(char **)&state);
/* ACBs for successful messages get completed in curl_read_cb */
if (msg->data.result != CURLE_OK) {
@@ -277,28 +281,31 @@ static void curl_multi_read(BDRVCURLState *s)
curl_clean_state(state);
break;
}
default:
msgs_in_queue = 0;
break;
}
} while(msgs_in_queue);
}
static void curl_multi_do(void *arg)
{
BDRVCURLState *s = (BDRVCURLState *)arg;
CURLState *s = (CURLState *)arg;
int running;
int r;
if (!s->multi) {
if (!s->s->multi) {
return;
}
do {
r = curl_multi_socket_all(s->multi, &running);
r = curl_multi_socket_action(s->s->multi, s->sock_fd, 0, &running);
} while(r == CURLM_CALL_MULTI_PERFORM);
curl_multi_read(s);
}
static void curl_multi_read(void *arg)
{
CURLState *s = (CURLState *)arg;
curl_multi_do(arg);
curl_multi_check_completion(s->s);
}
static void curl_multi_timeout_do(void *arg)
@@ -313,7 +320,7 @@ static void curl_multi_timeout_do(void *arg)
curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
curl_multi_read(s);
curl_multi_check_completion(s);
#else
abort();
#endif
@@ -337,20 +344,19 @@ static CURLState *curl_init_state(BDRVCURLState *s)
break;
}
if (!state) {
g_usleep(100);
curl_multi_do(s);
qemu_aio_wait();
}
} while(!state);
if (state->curl)
goto has_curl;
if (!state->curl) {
state->curl = curl_easy_init();
if (!state->curl)
if (!state->curl) {
return NULL;
}
curl_easy_setopt(state->curl, CURLOPT_URL, s->url);
curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5);
curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, (void *)curl_read_cb);
curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION,
(void *)curl_read_cb);
curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state);
curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state);
curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1);
@@ -373,8 +379,7 @@ static CURLState *curl_init_state(BDRVCURLState *s)
#ifdef DEBUG_VERBOSE
curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1);
#endif
has_curl:
}
state->s = s;
@@ -531,13 +536,11 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
// initialize the multi interface!
s->multi = curl_multi_init();
curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, s);
curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
#ifdef NEED_CURL_TIMER_CALLBACK
curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
#endif
curl_multi_do(s);
qemu_opts_del(opts);
return 0;
@@ -566,6 +569,7 @@ static const AIOCBInfo curl_aiocb_info = {
static void curl_readv_bh_cb(void *p)
{
CURLState *state;
int running;
CURLAIOCB *acb = p;
BDRVCURLState *s = acb->common.bs->opaque;
@@ -614,8 +618,9 @@ static void curl_readv_bh_cb(void *p)
curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range);
curl_multi_add_handle(s->multi, state->curl);
curl_multi_do(s);
/* Tell curl it needs to kick things off */
curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
}
static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,

View File

@@ -248,8 +248,8 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
offset += 8;
if (s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) {
error_report("sector count %" PRIu64 " for chunk %u is "
"larger than max (%u)",
error_report("sector count %" PRIu64 " for chunk %" PRIu32
" is larger than max (%u)",
s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX);
ret = -EINVAL;
goto fail;
@@ -269,8 +269,8 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
offset += 8;
if (s->lengths[i] > DMG_LENGTHS_MAX) {
error_report("length %" PRIu64 " for chunk %u is larger "
"than max (%u)",
error_report("length %" PRIu64 " for chunk %" PRIu32
" is larger than max (%u)",
s->lengths[i], i, DMG_LENGTHS_MAX);
ret = -EINVAL;
goto fail;

View File

@@ -325,11 +325,11 @@ static void coroutine_fn mirror_run(void *opaque)
s->common.len = bdrv_getlength(bs);
if (s->common.len <= 0) {
block_job_completed(&s->common, s->common.len);
return;
ret = s->common.len;
goto immediate_exit;
}
length = (bdrv_getlength(bs) + s->granularity - 1) / s->granularity;
length = DIV_ROUND_UP(s->common.len, s->granularity);
s->in_flight_bitmap = bitmap_new(length);
/* If we have no backing file yet in the destination, we cannot let
@@ -339,7 +339,10 @@ static void coroutine_fn mirror_run(void *opaque)
bdrv_get_backing_filename(s->target, backing_filename,
sizeof(backing_filename));
if (backing_filename[0] && !s->target->backing_hd) {
bdrv_get_info(s->target, &bdi);
ret = bdrv_get_info(s->target, &bdi);
if (ret < 0) {
goto immediate_exit;
}
if (s->granularity < bdi.cluster_size) {
s->buf_size = MAX(s->buf_size, bdi.cluster_size);
s->cow_bitmap = bitmap_new(length);

View File

@@ -532,12 +532,11 @@ static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,
ImageInfoSpecific *info_spec)
{
Error *local_err = NULL;
QmpOutputVisitor *ov = qmp_output_visitor_new();
QObject *obj, *data;
visit_type_ImageInfoSpecific(qmp_output_get_visitor(ov), &info_spec, NULL,
&local_err);
&error_abort);
obj = qmp_output_get_qobject(ov);
assert(qobject_type(obj) == QTYPE_QDICT);
data = qdict_get(qobject_to_qdict(obj), "data");

View File

@@ -119,7 +119,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
}
if (header.version != QCOW_VERSION) {
char version[64];
snprintf(version, sizeof(version), "QCOW version %d", header.version);
snprintf(version, sizeof(version), "QCOW version %" PRIu32,
header.version);
error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
bs->device_name, "qcow", version);
ret = -ENOTSUP;

View File

@@ -42,6 +42,13 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
if (min_size <= s->l1_size)
return 0;
/* Do a sanity check on min_size before trying to calculate new_l1_size
* (this prevents overflows during the while loop for the calculation of
* new_l1_size) */
if (min_size > INT_MAX / sizeof(uint64_t)) {
return -EFBIG;
}
if (exact_size) {
new_l1_size = min_size;
} else {
@@ -1360,9 +1367,9 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
for (i = 0; i < nb_clusters; i++) {
uint64_t old_offset;
uint64_t old_l2_entry;
old_offset = be64_to_cpu(l2_table[l2_index + i]);
old_l2_entry = be64_to_cpu(l2_table[l2_index + i]);
/*
* Make sure that a discarded area reads back as zeroes for v3 images
@@ -1373,12 +1380,22 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
* TODO We might want to use bdrv_get_block_status(bs) here, but we're
* holding s->lock, so that doesn't work today.
*/
if (old_offset & QCOW_OFLAG_ZERO) {
switch (qcow2_get_cluster_type(old_l2_entry)) {
case QCOW2_CLUSTER_UNALLOCATED:
if (!bs->backing_hd) {
continue;
}
break;
if ((old_offset & L2E_OFFSET_MASK) == 0 && !bs->backing_hd) {
case QCOW2_CLUSTER_ZERO:
continue;
case QCOW2_CLUSTER_NORMAL:
case QCOW2_CLUSTER_COMPRESSED:
break;
default:
abort();
}
/* First remove L2 entries */
@@ -1390,7 +1407,7 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
}
/* Then decrease the refcount */
qcow2_free_any_clusters(bs, old_offset, 1, type);
qcow2_free_any_clusters(bs, old_l2_entry, 1, type);
}
ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);

View File

@@ -653,6 +653,13 @@ retry:
goto retry;
}
}
/* Make sure that all offsets in the "allocated" range are representable
* in an int64_t */
if (s->free_cluster_index - 1 > (INT64_MAX >> s->cluster_bits)) {
return -EFBIG;
}
#ifdef DEBUG_ALLOC2
fprintf(stderr, "alloc_clusters: size=%" PRId64 " -> %" PRId64 "\n",
size,
@@ -1480,6 +1487,11 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
int ret;
size = bdrv_getlength(bs->file);
if (size < 0) {
res->check_errors++;
return size;
}
nb_clusters = size_to_clusters(s, size);
if (nb_clusters > INT_MAX) {
res->check_errors++;

View File

@@ -124,8 +124,9 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
case QCOW2_EXT_MAGIC_BACKING_FORMAT:
if (ext.len >= sizeof(bs->backing_format)) {
error_setg(errp, "ERROR: ext_backing_format: len=%u too large"
" (>=%zu)", ext.len, sizeof(bs->backing_format));
error_setg(errp, "ERROR: ext_backing_format: len=%" PRIu32
" too large (>=%zu)", ext.len,
sizeof(bs->backing_format));
return 2;
}
ret = bdrv_pread(bs->file, offset, bs->backing_format, ext.len);
@@ -483,7 +484,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
goto fail;
}
if (header.version < 2 || header.version > 3) {
report_unsupported(bs, errp, "QCOW version %d", header.version);
report_unsupported(bs, errp, "QCOW version %" PRIu32, header.version);
ret = -ENOTSUP;
goto fail;
}
@@ -493,7 +494,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
/* Initialise cluster size */
if (header.cluster_bits < MIN_CLUSTER_BITS ||
header.cluster_bits > MAX_CLUSTER_BITS) {
error_setg(errp, "Unsupported cluster size: 2^%i", header.cluster_bits);
error_setg(errp, "Unsupported cluster size: 2^%" PRIu32,
header.cluster_bits);
ret = -EINVAL;
goto fail;
}
@@ -591,7 +593,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
s->refcount_order = header.refcount_order;
if (header.crypt_method > QCOW_CRYPT_AES) {
error_setg(errp, "Unsupported encryption method: %i",
error_setg(errp, "Unsupported encryption method: %" PRIu32,
header.crypt_method);
ret = -EINVAL;
goto fail;

View File

@@ -366,7 +366,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
BDRVRawState *s = bs->opaque;
QemuOpts *opts;
Error *local_err = NULL;
const char *filename;
const char *filename = NULL;
int fd, ret;
struct stat st;
@@ -446,6 +446,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
ret = 0;
fail:
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
unlink(filename);
}
qemu_opts_del(opts);
return ret;
}

View File

@@ -390,6 +390,9 @@ static void raw_close(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
CloseHandle(s->hfile);
if (bs->open_flags & BDRV_O_TEMPORARY) {
unlink(bs->filename);
}
}
static int raw_truncate(BlockDriverState *bs, int64_t offset)

View File

@@ -1099,7 +1099,7 @@ static int find_vdi_name(BDRVSheepdogState *s, const char *filename,
}
if (rsp->result != SD_RES_SUCCESS) {
error_report("cannot get vdi info, %s, %s %d %s",
error_report("cannot get vdi info, %s, %s %" PRIu32 " %s",
sd_strerror(rsp->result), filename, snapid, tag);
if (rsp->result == SD_RES_NO_VDI) {
ret = -ENOENT;
@@ -2316,8 +2316,8 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
sn_tab[found].vm_state_size = inode.vm_state_size;
sn_tab[found].vm_clock_nsec = inode.vm_clock_nsec;
snprintf(sn_tab[found].id_str, sizeof(sn_tab[found].id_str), "%u",
inode.snap_id);
snprintf(sn_tab[found].id_str, sizeof(sn_tab[found].id_str),
"%" PRIu32, inode.snap_id);
pstrcpy(sn_tab[found].name,
MIN(sizeof(sn_tab[found].name), sizeof(inode.tag)),
inode.tag);

View File

@@ -408,34 +408,35 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
}
if (header.signature != VDI_SIGNATURE) {
error_setg(errp, "Image not in VDI format (bad signature %08x)", header.signature);
error_setg(errp, "Image not in VDI format (bad signature %08" PRIx32
")", header.signature);
ret = -EINVAL;
goto fail;
} else if (header.version != VDI_VERSION_1_1) {
error_setg(errp, "unsupported VDI image (version %u.%u)",
header.version >> 16, header.version & 0xffff);
error_setg(errp, "unsupported VDI image (version %" PRIu32 ".%" PRIu32
")", header.version >> 16, header.version & 0xffff);
ret = -ENOTSUP;
goto fail;
} else if (header.offset_bmap % SECTOR_SIZE != 0) {
/* We only support block maps which start on a sector boundary. */
error_setg(errp, "unsupported VDI image (unaligned block map offset "
"0x%x)", header.offset_bmap);
"0x%" PRIx32 ")", header.offset_bmap);
ret = -ENOTSUP;
goto fail;
} else if (header.offset_data % SECTOR_SIZE != 0) {
/* We only support data blocks which start on a sector boundary. */
error_setg(errp, "unsupported VDI image (unaligned data offset 0x%x)",
header.offset_data);
error_setg(errp, "unsupported VDI image (unaligned data offset 0x%"
PRIx32 ")", header.offset_data);
ret = -ENOTSUP;
goto fail;
} else if (header.sector_size != SECTOR_SIZE) {
error_setg(errp, "unsupported VDI image (sector size %u is not %u)",
header.sector_size, SECTOR_SIZE);
error_setg(errp, "unsupported VDI image (sector size %" PRIu32
" is not %u)", header.sector_size, SECTOR_SIZE);
ret = -ENOTSUP;
goto fail;
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
error_setg(errp, "unsupported VDI image (block size %u is not %u)",
header.block_size, DEFAULT_CLUSTER_SIZE);
error_setg(errp, "unsupported VDI image (block size %" PRIu32
" is not %u)", header.block_size, DEFAULT_CLUSTER_SIZE);
ret = -ENOTSUP;
goto fail;
} else if (header.disk_size >
@@ -755,6 +756,7 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
vdi_header_to_le(&header);
if (write(fd, &header, sizeof(header)) < 0) {
result = -errno;
goto close_and_exit;
}
if (bmap_size > 0) {
@@ -768,6 +770,8 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
}
if (write(fd, bmap, bmap_size) < 0) {
result = -errno;
g_free(bmap);
goto close_and_exit;
}
g_free(bmap);
}
@@ -775,10 +779,12 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
if (image_type == VDI_TYPE_STATIC) {
if (ftruncate(fd, sizeof(header) + bmap_size + blocks * block_size)) {
result = -errno;
goto close_and_exit;
}
}
if (close(fd) < 0) {
close_and_exit:
if ((close(fd) < 0) && !result) {
result = -errno;
}

View File

@@ -8,6 +8,7 @@ command line switches:
-vga std [ picks isa for -M isapc, otherwise pci ]
-device VGA [ pci variant ]
-device isa-vga [ isa variant ]
-device secondary-vga [ legacy-free pci variant ]
PCI spec
@@ -31,9 +32,15 @@ PCI ROM Region:
Holds the vgabios (qemu 0.14+).
The legacy-free variant has no ROM and has PCI_CLASS_DISPLAY_OTHER
instead of PCI_CLASS_DISPLAY_VGA.
IO ports used
-------------
Doesn't apply to the legacy-free pci variant, use the MMIO bar instead.
03c0 - 03df : standard vga ports
01ce : bochs vbe interface index port
01cf : bochs vbe interface data port (x86 only)

View File

@@ -75,8 +75,6 @@ typedef struct MemMapEntry {
typedef struct VirtBoardInfo {
struct arm_boot_info bootinfo;
const char *cpu_model;
const char *qdevname;
const char *gic_compatible;
const MemMapEntry *memmap;
const int *irqmap;
int smp_cpus;
@@ -98,10 +96,10 @@ typedef struct VirtBoardInfo {
static const MemMapEntry a15memmap[] = {
/* Space up to 0x8000000 is reserved for a boot ROM */
[VIRT_FLASH] = { 0, 0x8000000 },
[VIRT_CPUPERIPHS] = { 0x8000000, 0x8000 },
[VIRT_CPUPERIPHS] = { 0x8000000, 0x20000 },
/* GIC distributor and CPU interfaces sit inside the CPU peripheral space */
[VIRT_GIC_DIST] = { 0x8001000, 0x1000 },
[VIRT_GIC_CPU] = { 0x8002000, 0x1000 },
[VIRT_GIC_DIST] = { 0x8000000, 0x10000 },
[VIRT_GIC_CPU] = { 0x8010000, 0x10000 },
[VIRT_UART] = { 0x9000000, 0x1000 },
[VIRT_MMIO] = { 0xa000000, 0x200 },
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
@@ -117,16 +115,16 @@ static const int a15irqmap[] = {
static VirtBoardInfo machines[] = {
{
.cpu_model = "cortex-a15",
.qdevname = "a15mpcore_priv",
.gic_compatible = "arm,cortex-a15-gic",
.memmap = a15memmap,
.irqmap = a15irqmap,
},
{
.cpu_model = "cortex-a57",
.memmap = a15memmap,
.irqmap = a15irqmap,
},
{
.cpu_model = "host",
/* We use the A15 private peripheral model to get a V2 GIC */
.qdevname = "a15mpcore_priv",
.gic_compatible = "arm,cortex-a15-gic",
.memmap = a15memmap,
.irqmap = a15irqmap,
},
@@ -251,8 +249,9 @@ static void fdt_add_gic_node(const VirtBoardInfo *vbi)
qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", gic_phandle);
qemu_fdt_add_subnode(vbi->fdt, "/intc");
/* 'cortex-a15-gic' means 'GIC v2' */
qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
vbi->gic_compatible);
"arm,cortex-a15-gic");
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#interrupt-cells", 3);
qemu_fdt_setprop(vbi->fdt, "/intc", "interrupt-controller", NULL, 0);
qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
@@ -263,6 +262,56 @@ static void fdt_add_gic_node(const VirtBoardInfo *vbi)
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", gic_phandle);
}
static void create_gic(const VirtBoardInfo *vbi, qemu_irq *pic)
{
/* We create a standalone GIC v2 */
DeviceState *gicdev;
SysBusDevice *gicbusdev;
const char *gictype = "arm_gic";
int i;
if (kvm_irqchip_in_kernel()) {
gictype = "kvm-arm-gic";
}
gicdev = qdev_create(NULL, gictype);
qdev_prop_set_uint32(gicdev, "revision", 2);
qdev_prop_set_uint32(gicdev, "num-cpu", smp_cpus);
/* Note that the num-irq property counts both internal and external
* interrupts; there are always 32 of the former (mandated by GIC spec).
*/
qdev_prop_set_uint32(gicdev, "num-irq", NUM_IRQS + 32);
qdev_init_nofail(gicdev);
gicbusdev = SYS_BUS_DEVICE(gicdev);
sysbus_mmio_map(gicbusdev, 0, vbi->memmap[VIRT_GIC_DIST].base);
sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_CPU].base);
/* Wire the outputs from each CPU's generic timer to the
* appropriate GIC PPI inputs, and the GIC's IRQ output to
* the CPU's IRQ input.
*/
for (i = 0; i < smp_cpus; i++) {
DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
int ppibase = NUM_IRQS + i * 32;
/* physical timer; we wire it up to the non-secure timer's ID,
* since a real A15 always has TrustZone but QEMU doesn't.
*/
qdev_connect_gpio_out(cpudev, 0,
qdev_get_gpio_in(gicdev, ppibase + 30));
/* virtual timer */
qdev_connect_gpio_out(cpudev, 1,
qdev_get_gpio_in(gicdev, ppibase + 27));
sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
}
for (i = 0; i < NUM_IRQS; i++) {
pic[i] = qdev_get_gpio_in(gicdev, i);
}
fdt_add_gic_node(vbi);
}
static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
{
char *nodename;
@@ -340,8 +389,6 @@ static void machvirt_init(QEMUMachineInitArgs *args)
MemoryRegion *sysmem = get_system_memory();
int n;
MemoryRegion *ram = g_new(MemoryRegion, 1);
DeviceState *dev;
SysBusDevice *busdev;
const char *cpu_model = args->cpu_model;
VirtBoardInfo *vbi;
@@ -404,25 +451,7 @@ static void machvirt_init(QEMUMachineInitArgs *args)
vmstate_register_ram_global(ram);
memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, ram);
dev = qdev_create(NULL, vbi->qdevname);
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
/* Note that the num-irq property counts both internal and external
* interrupts; there are always 32 of the former (mandated by GIC spec).
*/
qdev_prop_set_uint32(dev, "num-irq", NUM_IRQS + 32);
qdev_init_nofail(dev);
busdev = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(busdev, 0, vbi->memmap[VIRT_CPUPERIPHS].base);
fdt_add_gic_node(vbi);
for (n = 0; n < smp_cpus; n++) {
DeviceState *cpudev = DEVICE(qemu_get_cpu(n));
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
}
for (n = 0; n < NUM_IRQS; n++) {
pic[n] = qdev_get_gpio_in(dev, n);
}
create_gic(vbi, pic);
create_uart(vbi, pic);

View File

@@ -261,6 +261,9 @@ static void hda_audio_set_amp(HDAAudioStream *st)
left = left * 255 / QEMU_HDA_AMP_STEPS;
right = right * 255 / QEMU_HDA_AMP_STEPS;
if (!st->state->mixer) {
return;
}
if (st->output) {
AUD_set_volume_out(st->voice.out, muted, left, right);
} else {

View File

@@ -2913,7 +2913,7 @@ static void isa_cirrus_vga_realizefn(DeviceState *dev, Error **errp)
ISACirrusVGAState *d = ISA_CIRRUS_VGA(dev);
VGACommonState *s = &d->cirrus_vga.vga;
vga_common_init(s, OBJECT(dev));
vga_common_init(s, OBJECT(dev), true);
cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0,
isa_address_space(isadev),
isa_address_space_io(isadev));
@@ -2960,7 +2960,7 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
int16_t device_id = pc->device_id;
/* setup VGA */
vga_common_init(&s->vga, OBJECT(dev));
vga_common_init(&s->vga, OBJECT(dev), true);
cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev),
pci_address_space_io(dev));
s->vga.con = graphic_console_init(DEVICE(dev), 0, s->vga.hw_ops, &s->vga);

View File

@@ -2061,7 +2061,7 @@ static int qxl_init_primary(PCIDevice *dev)
qxl->id = 0;
qxl_init_ramsize(qxl);
vga->vram_size_mb = qxl->vga.vram_size >> 20;
vga_common_init(vga, OBJECT(dev));
vga_common_init(vga, OBJECT(dev), true);
vga_init(vga, OBJECT(dev),
pci_address_space(dev), pci_address_space_io(dev), false);
portio_list_init(qxl_vga_port_list, OBJECT(dev), qxl_vga_portio_list,

View File

@@ -132,7 +132,7 @@ int isa_vga_mm_init(hwaddr vram_base,
s = g_malloc0(sizeof(*s));
s->vga.vram_size_mb = VGA_RAM_SIZE >> 20;
vga_common_init(&s->vga, NULL);
vga_common_init(&s->vga, NULL, true);
vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s);

View File

@@ -56,7 +56,7 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp)
MemoryRegion *vga_io_memory;
const MemoryRegionPortio *vga_ports, *vbe_ports;
vga_common_init(s, OBJECT(dev));
vga_common_init(s, OBJECT(dev), true);
s->legacy_address_space = isa_address_space(isadev);
vga_io_memory = vga_init_io(s, OBJECT(dev), &vga_ports, &vbe_ports);
isa_register_portio_list(isadev, 0x3b0, vga_ports, s, "vga");

View File

@@ -147,7 +147,7 @@ static int pci_std_vga_initfn(PCIDevice *dev)
VGACommonState *s = &d->vga;
/* vga + console init */
vga_common_init(s, OBJECT(dev));
vga_common_init(s, OBJECT(dev), true);
vga_init(s, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev),
true);
@@ -179,12 +179,51 @@ static int pci_std_vga_initfn(PCIDevice *dev)
return 0;
}
static int pci_secondary_vga_initfn(PCIDevice *dev)
{
PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
VGACommonState *s = &d->vga;
/* vga + console init */
vga_common_init(s, OBJECT(dev), false);
s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s);
/* mmio bar */
memory_region_init(&d->mmio, OBJECT(dev), "vga.mmio", 4096);
memory_region_init_io(&d->ioport, OBJECT(dev), &pci_vga_ioport_ops, d,
"vga ioports remapped", PCI_VGA_IOPORT_SIZE);
memory_region_init_io(&d->bochs, OBJECT(dev), &pci_vga_bochs_ops, d,
"bochs dispi interface", PCI_VGA_BOCHS_SIZE);
memory_region_add_subregion(&d->mmio, PCI_VGA_IOPORT_OFFSET,
&d->ioport);
memory_region_add_subregion(&d->mmio, PCI_VGA_BOCHS_OFFSET,
&d->bochs);
pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
return 0;
}
static void pci_secondary_vga_reset(DeviceState *dev)
{
PCIVGAState *d = DO_UPCAST(PCIVGAState, dev.qdev, dev);
vga_common_reset(&d->vga);
}
static Property vga_pci_properties[] = {
DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
DEFINE_PROP_BIT("mmio", PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_MMIO, true),
DEFINE_PROP_END_OF_LIST(),
};
static Property secondary_pci_properties[] = {
DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
DEFINE_PROP_END_OF_LIST(),
};
static void vga_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -201,6 +240,20 @@ static void vga_class_init(ObjectClass *klass, void *data)
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
}
static void secondary_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->init = pci_secondary_vga_initfn;
k->vendor_id = PCI_VENDOR_ID_QEMU;
k->device_id = PCI_DEVICE_ID_QEMU_VGA;
k->class_id = PCI_CLASS_DISPLAY_OTHER;
dc->vmsd = &vmstate_vga_pci;
dc->props = secondary_pci_properties;
dc->reset = pci_secondary_vga_reset;
}
static const TypeInfo vga_info = {
.name = "VGA",
.parent = TYPE_PCI_DEVICE,
@@ -208,9 +261,17 @@ static const TypeInfo vga_info = {
.class_init = vga_class_init,
};
static const TypeInfo secondary_info = {
.name = "secondary-vga",
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(PCIVGAState),
.class_init = secondary_class_init,
};
static void vga_register_types(void)
{
type_register_static(&vga_info);
type_register_static(&secondary_info);
}
type_init(vga_register_types)

View File

@@ -171,6 +171,10 @@ static void vga_update_memory_access(VGACommonState *s)
MemoryRegion *region, *old_region = s->chain4_alias;
hwaddr base, offset, size;
if (s->legacy_address_space == NULL) {
return;
}
s->chain4_alias = NULL;
if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) ==
@@ -2252,7 +2256,7 @@ static const GraphicHwOps vga_ops = {
.text_update = vga_update_text,
};
void vga_common_init(VGACommonState *s, Object *obj)
void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate)
{
int i, j, v, b;
@@ -2289,7 +2293,7 @@ void vga_common_init(VGACommonState *s, Object *obj)
s->is_vbe_vmstate = 1;
memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size);
vmstate_register_ram_global(&s->vram);
vmstate_register_ram(&s->vram, global_vmstate ? NULL : DEVICE(obj));
xen_register_framebuffer(&s->vram);
s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
s->get_bpp = vga_get_bpp;

View File

@@ -177,7 +177,7 @@ static inline int c6_to_8(int v)
return (v << 2) | (b << 1) | b;
}
void vga_common_init(VGACommonState *s, Object *obj);
void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate);
void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
MemoryRegion *address_space_io, bool init_vga_ports);
MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,

View File

@@ -1207,7 +1207,7 @@ static void vmsvga_init(DeviceState *dev, struct vmsvga_state_s *s,
vmstate_register_ram_global(&s->fifo_ram);
s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram);
vga_common_init(&s->vga, OBJECT(dev));
vga_common_init(&s->vga, OBJECT(dev), true);
vga_init(&s->vga, OBJECT(dev), address_space, io, true);
vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
s->new_depth = 32;

View File

@@ -612,6 +612,21 @@ int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
return e820_entries;
}
int e820_get_num_entries(void)
{
return e820_entries;
}
bool e820_get_entry(int idx, uint32_t type, uint64_t *address, uint64_t *length)
{
if (idx < e820_entries && e820_table[idx].type == cpu_to_le32(type)) {
*address = le64_to_cpu(e820_table[idx].address);
*length = le64_to_cpu(e820_table[idx].length);
return true;
}
return false;
}
/* Calculates the limit to CPU APIC ID values
*
* This function returns the limit for the APIC ID value, so that all
@@ -627,8 +642,8 @@ static unsigned int pc_apic_id_limit(unsigned int max_cpus)
static FWCfgState *bochs_bios_init(void)
{
FWCfgState *fw_cfg;
uint8_t *smbios_table;
size_t smbios_len;
uint8_t *smbios_tables, *smbios_anchor;
size_t smbios_tables_len, smbios_anchor_len;
uint64_t *numa_fw_cfg;
int i, j;
unsigned int apic_id_limit = pc_apic_id_limit(max_cpus);
@@ -655,10 +670,21 @@ static FWCfgState *bochs_bios_init(void)
acpi_tables, acpi_tables_len);
fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
smbios_table = smbios_get_table(&smbios_len);
if (smbios_table)
smbios_tables = smbios_get_table_legacy(&smbios_tables_len);
if (smbios_tables) {
fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES,
smbios_table, smbios_len);
smbios_tables, smbios_tables_len);
}
smbios_get_tables(&smbios_tables, &smbios_tables_len,
&smbios_anchor, &smbios_anchor_len);
if (smbios_anchor) {
fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-tables",
smbios_tables, smbios_tables_len);
fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-anchor",
smbios_anchor, smbios_anchor_len);
}
fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE,
&e820_reserve, sizeof(e820_reserve));
fw_cfg_add_file(fw_cfg, "etc/e820", e820_table,
@@ -1027,6 +1053,9 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(icc_bridge), 0,
APIC_DEFAULT_ADDRESS, 0x1000);
}
/* tell smbios about cpuid version and features */
smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]);
}
/* pci-info ROM file. Little endian format */

View File

@@ -60,7 +60,8 @@ static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
static bool has_pci_info;
static bool has_acpi_build = true;
static bool smbios_type1_defaults = true;
static bool smbios_defaults = true;
static bool smbios_legacy_mode;
/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
* pages in the host.
@@ -143,10 +144,10 @@ static void pc_init1(QEMUMachineInitArgs *args,
guest_info->has_pci_info = has_pci_info;
guest_info->isapc_ram_fw = !pci_enabled;
if (smbios_type1_defaults) {
if (smbios_defaults) {
/* These values are guest ABI, do not change */
smbios_set_type1_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
args->machine->name);
smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
args->machine->name, smbios_legacy_mode);
}
/* allocate ram and load rom/bios */
@@ -262,9 +263,15 @@ static void pc_init_pci(QEMUMachineInitArgs *args)
pc_init1(args, 1, 1);
}
static void pc_compat_2_0(QEMUMachineInitArgs *args)
{
smbios_legacy_mode = true;
}
static void pc_compat_1_7(QEMUMachineInitArgs *args)
{
smbios_type1_defaults = false;
pc_compat_2_0(args);
smbios_defaults = false;
gigabyte_align = false;
option_rom_has_mr = true;
x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC);
@@ -303,6 +310,12 @@ static void pc_compat_1_2(QEMUMachineInitArgs *args)
x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
}
static void pc_init_pci_2_0(QEMUMachineInitArgs *args)
{
pc_compat_2_0(args);
pc_init_pci(args);
}
static void pc_init_pci_1_7(QEMUMachineInitArgs *args)
{
pc_compat_1_7(args);
@@ -345,7 +358,7 @@ static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args)
{
has_pci_info = false;
has_acpi_build = false;
smbios_type1_defaults = false;
smbios_defaults = false;
x86_cpu_compat_disable_kvm_features(FEAT_KVM, KVM_FEATURE_PV_EOI);
enable_compat_apic_id_mode();
pc_init1(args, 1, 0);
@@ -355,7 +368,7 @@ static void pc_init_isa(QEMUMachineInitArgs *args)
{
has_pci_info = false;
has_acpi_build = false;
smbios_type1_defaults = false;
smbios_defaults = false;
if (!args->cpu_model) {
args->cpu_model = "486";
}
@@ -383,16 +396,24 @@ static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
.desc = "Standard PC (i440FX + PIIX, 1996)", \
.hot_add_cpu = pc_hot_add_cpu
#define PC_I440FX_2_0_MACHINE_OPTIONS \
#define PC_I440FX_2_1_MACHINE_OPTIONS \
PC_I440FX_MACHINE_OPTIONS, \
.default_machine_opts = "firmware=bios-256k.bin"
static QEMUMachine pc_i440fx_machine_v2_1 = {
PC_I440FX_2_1_MACHINE_OPTIONS,
.name = "pc-i440fx-2.1",
.alias = "pc",
.init = pc_init_pci,
.is_default = 1,
};
#define PC_I440FX_2_0_MACHINE_OPTIONS PC_I440FX_2_1_MACHINE_OPTIONS
static QEMUMachine pc_i440fx_machine_v2_0 = {
PC_I440FX_2_0_MACHINE_OPTIONS,
.name = "pc-i440fx-2.0",
.alias = "pc",
.init = pc_init_pci,
.is_default = 1,
.init = pc_init_pci_2_0,
};
#define PC_I440FX_1_7_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
@@ -817,6 +838,7 @@ static QEMUMachine xenfv_machine = {
static void pc_machine_init(void)
{
qemu_register_machine(&pc_i440fx_machine_v2_1);
qemu_register_machine(&pc_i440fx_machine_v2_0);
qemu_register_machine(&pc_i440fx_machine_v1_7);
qemu_register_machine(&pc_i440fx_machine_v1_6);

View File

@@ -50,7 +50,8 @@
static bool has_pci_info;
static bool has_acpi_build = true;
static bool smbios_type1_defaults = true;
static bool smbios_defaults = true;
static bool smbios_legacy_mode;
/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
* host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
* pages in the host.
@@ -130,10 +131,10 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
guest_info->isapc_ram_fw = false;
guest_info->has_acpi_build = has_acpi_build;
if (smbios_type1_defaults) {
if (smbios_defaults) {
/* These values are guest ABI, do not change */
smbios_set_type1_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
args->machine->name);
smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
args->machine->name, smbios_legacy_mode);
}
/* allocate ram and load rom/bios */
@@ -240,9 +241,15 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
}
}
static void pc_compat_2_0(QEMUMachineInitArgs *args)
{
smbios_legacy_mode = true;
}
static void pc_compat_1_7(QEMUMachineInitArgs *args)
{
smbios_type1_defaults = false;
pc_compat_2_0(args);
smbios_defaults = false;
gigabyte_align = false;
option_rom_has_mr = true;
x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC);
@@ -268,6 +275,12 @@ static void pc_compat_1_4(QEMUMachineInitArgs *args)
x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
}
static void pc_q35_init_2_0(QEMUMachineInitArgs *args)
{
pc_compat_2_0(args);
pc_q35_init(args);
}
static void pc_q35_init_1_7(QEMUMachineInitArgs *args)
{
pc_compat_1_7(args);
@@ -297,15 +310,23 @@ static void pc_q35_init_1_4(QEMUMachineInitArgs *args)
.desc = "Standard PC (Q35 + ICH9, 2009)", \
.hot_add_cpu = pc_hot_add_cpu
#define PC_Q35_2_0_MACHINE_OPTIONS \
#define PC_Q35_2_1_MACHINE_OPTIONS \
PC_Q35_MACHINE_OPTIONS, \
.default_machine_opts = "firmware=bios-256k.bin"
static QEMUMachine pc_q35_machine_v2_1 = {
PC_Q35_2_1_MACHINE_OPTIONS,
.name = "pc-q35-2.1",
.alias = "q35",
.init = pc_q35_init,
};
#define PC_Q35_2_0_MACHINE_OPTIONS PC_Q35_2_1_MACHINE_OPTIONS
static QEMUMachine pc_q35_machine_v2_0 = {
PC_Q35_2_0_MACHINE_OPTIONS,
.name = "pc-q35-2.0",
.alias = "q35",
.init = pc_q35_init,
.init = pc_q35_init_2_0,
};
#define PC_Q35_1_7_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
@@ -358,6 +379,7 @@ static QEMUMachine pc_q35_machine_v1_4 = {
static void pc_q35_machine_init(void)
{
qemu_register_machine(&pc_q35_machine_v2_1);
qemu_register_machine(&pc_q35_machine_v2_0);
qemu_register_machine(&pc_q35_machine_v1_7);
qemu_register_machine(&pc_q35_machine_v1_6);

View File

@@ -18,12 +18,13 @@
#include "qemu/config-file.h"
#include "qemu/error-report.h"
#include "sysemu/sysemu.h"
#include "sysemu/cpus.h"
#include "hw/i386/pc.h"
#include "hw/i386/smbios.h"
#include "hw/loader.h"
/*
* Structures shared with the BIOS
*/
/* legacy structures and constants for <= 2.0 machines */
struct smbios_header {
uint16_t length;
uint8_t type;
@@ -46,14 +47,23 @@ struct smbios_table {
static uint8_t *smbios_entries;
static size_t smbios_entries_len;
static bool smbios_legacy = true;
/* end: legacy structures & constants for <= 2.0 machines */
static uint8_t *smbios_tables;
static size_t smbios_tables_len;
static unsigned smbios_table_max;
static unsigned smbios_table_cnt;
static struct smbios_entry_point ep;
static int smbios_type4_count = 0;
static bool smbios_immutable;
static bool smbios_have_defaults;
static uint32_t smbios_cpuid_version, smbios_cpuid_features, smbios_smp_sockets;
static struct {
bool seen;
int headertype;
Location loc;
} first_opt[2];
static DECLARE_BITMAP(have_binfile_bitmap, SMBIOS_MAX_TYPE+1);
static DECLARE_BITMAP(have_fields_bitmap, SMBIOS_MAX_TYPE+1);
static struct {
const char *vendor, *version, *date;
@@ -66,6 +76,22 @@ static struct {
/* uuid is in qemu_uuid[] */
} type1;
static struct {
const char *manufacturer, *product, *version, *serial, *asset, *location;
} type2;
static struct {
const char *manufacturer, *version, *serial, *asset, *sku;
} type3;
static struct {
const char *sock_pfx, *manufacturer, *version, *serial, *asset, *part;
} type4;
static struct {
const char *loc_pfx, *bank, *manufacturer, *serial, *asset, *part;
} type17;
static QemuOptsList qemu_smbios_opts = {
.name = "smbios",
.head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head),
@@ -149,6 +175,134 @@ static const QemuOptDesc qemu_smbios_type1_opts[] = {
{ /* end of list */ }
};
static const QemuOptDesc qemu_smbios_type2_opts[] = {
{
.name = "type",
.type = QEMU_OPT_NUMBER,
.help = "SMBIOS element type",
},{
.name = "manufacturer",
.type = QEMU_OPT_STRING,
.help = "manufacturer name",
},{
.name = "product",
.type = QEMU_OPT_STRING,
.help = "product name",
},{
.name = "version",
.type = QEMU_OPT_STRING,
.help = "version number",
},{
.name = "serial",
.type = QEMU_OPT_STRING,
.help = "serial number",
},{
.name = "asset",
.type = QEMU_OPT_STRING,
.help = "asset tag number",
},{
.name = "location",
.type = QEMU_OPT_STRING,
.help = "location in chassis",
},
{ /* end of list */ }
};
static const QemuOptDesc qemu_smbios_type3_opts[] = {
{
.name = "type",
.type = QEMU_OPT_NUMBER,
.help = "SMBIOS element type",
},{
.name = "manufacturer",
.type = QEMU_OPT_STRING,
.help = "manufacturer name",
},{
.name = "version",
.type = QEMU_OPT_STRING,
.help = "version number",
},{
.name = "serial",
.type = QEMU_OPT_STRING,
.help = "serial number",
},{
.name = "asset",
.type = QEMU_OPT_STRING,
.help = "asset tag number",
},{
.name = "sku",
.type = QEMU_OPT_STRING,
.help = "SKU number",
},
{ /* end of list */ }
};
static const QemuOptDesc qemu_smbios_type4_opts[] = {
{
.name = "type",
.type = QEMU_OPT_NUMBER,
.help = "SMBIOS element type",
},{
.name = "sock_pfx",
.type = QEMU_OPT_STRING,
.help = "socket designation string prefix",
},{
.name = "manufacturer",
.type = QEMU_OPT_STRING,
.help = "manufacturer name",
},{
.name = "version",
.type = QEMU_OPT_STRING,
.help = "version number",
},{
.name = "serial",
.type = QEMU_OPT_STRING,
.help = "serial number",
},{
.name = "asset",
.type = QEMU_OPT_STRING,
.help = "asset tag number",
},{
.name = "part",
.type = QEMU_OPT_STRING,
.help = "part number",
},
{ /* end of list */ }
};
static const QemuOptDesc qemu_smbios_type17_opts[] = {
{
.name = "type",
.type = QEMU_OPT_NUMBER,
.help = "SMBIOS element type",
},{
.name = "loc_pfx",
.type = QEMU_OPT_STRING,
.help = "device locator string prefix",
},{
.name = "bank",
.type = QEMU_OPT_STRING,
.help = "bank locator string",
},{
.name = "manufacturer",
.type = QEMU_OPT_STRING,
.help = "manufacturer name",
},{
.name = "serial",
.type = QEMU_OPT_STRING,
.help = "serial number",
},{
.name = "asset",
.type = QEMU_OPT_STRING,
.help = "asset tag number",
},{
.name = "part",
.type = QEMU_OPT_STRING,
.help = "part number",
},
{ /* end of list */ }
};
static void smbios_register_config(void)
{
qemu_add_opts(&qemu_smbios_opts);
@@ -158,35 +312,17 @@ machine_init(smbios_register_config);
static void smbios_validate_table(void)
{
if (smbios_type4_count && smbios_type4_count != smp_cpus) {
error_report("Number of SMBIOS Type 4 tables must match cpu count");
uint32_t expect_t4_count = smbios_legacy ? smp_cpus : smbios_smp_sockets;
if (smbios_type4_count && smbios_type4_count != expect_t4_count) {
error_report("Expected %d SMBIOS Type 4 tables, got %d instead",
expect_t4_count, smbios_type4_count);
exit(1);
}
}
/*
* To avoid unresolvable overlaps in data, don't allow both
* tables and fields for the same smbios type.
*/
static void smbios_check_collision(int type, int entry)
{
if (type < ARRAY_SIZE(first_opt)) {
if (first_opt[type].seen) {
if (first_opt[type].headertype != entry) {
error_report("Can't mix file= and type= for same type");
loc_push_restore(&first_opt[type].loc);
error_report("This is the conflicting setting");
loc_pop(&first_opt[type].loc);
exit(1);
}
} else {
first_opt[type].seen = true;
first_opt[type].headertype = entry;
loc_save(&first_opt[type].loc);
}
}
}
/* legacy setup functions for <= 2.0 machines */
static void smbios_add_field(int type, int offset, const void *data, size_t len)
{
struct smbios_field *field;
@@ -256,22 +392,13 @@ static void smbios_build_type_1_fields(void)
}
}
void smbios_set_type1_defaults(const char *manufacturer,
const char *product, const char *version)
uint8_t *smbios_get_table_legacy(size_t *length)
{
if (!type1.manufacturer) {
type1.manufacturer = manufacturer;
}
if (!type1.product) {
type1.product = product;
}
if (!type1.version) {
type1.version = version;
}
if (!smbios_legacy) {
*length = 0;
return NULL;
}
uint8_t *smbios_get_table(size_t *length)
{
if (!smbios_immutable) {
smbios_build_type_0_fields();
smbios_build_type_1_fields();
@@ -281,6 +408,458 @@ uint8_t *smbios_get_table(size_t *length)
*length = smbios_entries_len;
return smbios_entries;
}
/* end: legacy setup functions for <= 2.0 machines */
static bool smbios_skip_table(uint8_t type, bool required_table)
{
if (test_bit(type, have_binfile_bitmap)) {
return true; /* user provided their own binary blob(s) */
}
if (test_bit(type, have_fields_bitmap)) {
return false; /* user provided fields via command line */
}
if (smbios_have_defaults && required_table) {
return false; /* we're building tables, and this one's required */
}
return true;
}
#define SMBIOS_BUILD_TABLE_PRE(tbl_type, tbl_handle, tbl_required) \
struct smbios_type_##tbl_type *t; \
size_t t_off; /* table offset into smbios_tables */ \
int str_index = 0; \
do { \
/* should we skip building this table ? */ \
if (smbios_skip_table(tbl_type, tbl_required)) { \
return; \
} \
\
/* use offset of table t within smbios_tables */ \
/* (pointer must be updated after each realloc) */ \
t_off = smbios_tables_len; \
smbios_tables_len += sizeof(*t); \
smbios_tables = g_realloc(smbios_tables, smbios_tables_len); \
t = (struct smbios_type_##tbl_type *)(smbios_tables + t_off); \
\
t->header.type = tbl_type; \
t->header.length = sizeof(*t); \
t->header.handle = tbl_handle; \
} while (0)
#define SMBIOS_TABLE_SET_STR(tbl_type, field, value) \
do { \
int len = (value != NULL) ? strlen(value) + 1 : 0; \
if (len > 1) { \
smbios_tables = g_realloc(smbios_tables, \
smbios_tables_len + len); \
memcpy(smbios_tables + smbios_tables_len, value, len); \
smbios_tables_len += len; \
/* update pointer post-realloc */ \
t = (struct smbios_type_##tbl_type *)(smbios_tables + t_off); \
t->field = ++str_index; \
} else { \
t->field = 0; \
} \
} while (0)
#define SMBIOS_BUILD_TABLE_POST \
do { \
size_t term_cnt, t_size; \
\
/* add '\0' terminator (add two if no strings defined) */ \
term_cnt = (str_index == 0) ? 2 : 1; \
smbios_tables = g_realloc(smbios_tables, \
smbios_tables_len + term_cnt); \
memset(smbios_tables + smbios_tables_len, 0, term_cnt); \
smbios_tables_len += term_cnt; \
\
/* update smbios max. element size */ \
t_size = smbios_tables_len - t_off; \
if (t_size > smbios_table_max) { \
smbios_table_max = t_size; \
} \
\
/* update smbios element count */ \
smbios_table_cnt++; \
} while (0)
static void smbios_build_type_0_table(void)
{
SMBIOS_BUILD_TABLE_PRE(0, 0x000, false); /* optional, leave up to BIOS */
SMBIOS_TABLE_SET_STR(0, vendor_str, type0.vendor);
SMBIOS_TABLE_SET_STR(0, bios_version_str, type0.version);
t->bios_starting_address_segment = 0xE800; /* hardcoded in SeaBIOS */
SMBIOS_TABLE_SET_STR(0, bios_release_date_str, type0.date);
t->bios_rom_size = 0; /* hardcoded in SeaBIOS with FIXME comment */
/* BIOS characteristics not supported */
memset(t->bios_characteristics, 0, 8);
t->bios_characteristics[0] = 0x08;
/* Enable targeted content distribution (needed for SVVP, per SeaBIOS) */
t->bios_characteristics_extension_bytes[0] = 0;
t->bios_characteristics_extension_bytes[1] = 4;
if (type0.have_major_minor) {
t->system_bios_major_release = type0.major;
t->system_bios_minor_release = type0.minor;
} else {
t->system_bios_major_release = 0;
t->system_bios_minor_release = 0;
}
/* hardcoded in SeaBIOS */
t->embedded_controller_major_release = 0xFF;
t->embedded_controller_minor_release = 0xFF;
SMBIOS_BUILD_TABLE_POST;
}
static void smbios_build_type_1_table(void)
{
SMBIOS_BUILD_TABLE_PRE(1, 0x100, true); /* required */
SMBIOS_TABLE_SET_STR(1, manufacturer_str, type1.manufacturer);
SMBIOS_TABLE_SET_STR(1, product_name_str, type1.product);
SMBIOS_TABLE_SET_STR(1, version_str, type1.version);
SMBIOS_TABLE_SET_STR(1, serial_number_str, type1.serial);
if (qemu_uuid_set) {
memcpy(t->uuid, qemu_uuid, 16);
} else {
memset(t->uuid, 0, 16);
}
t->wake_up_type = 0x06; /* power switch */
SMBIOS_TABLE_SET_STR(1, sku_number_str, type1.sku);
SMBIOS_TABLE_SET_STR(1, family_str, type1.family);
SMBIOS_BUILD_TABLE_POST;
}
static void smbios_build_type_2_table(void)
{
SMBIOS_BUILD_TABLE_PRE(2, 0x200, false); /* optional */
SMBIOS_TABLE_SET_STR(2, manufacturer_str, type2.manufacturer);
SMBIOS_TABLE_SET_STR(2, product_str, type2.product);
SMBIOS_TABLE_SET_STR(2, version_str, type2.version);
SMBIOS_TABLE_SET_STR(2, serial_number_str, type2.serial);
SMBIOS_TABLE_SET_STR(2, asset_tag_number_str, type2.asset);
t->feature_flags = 0x01; /* Motherboard */
SMBIOS_TABLE_SET_STR(2, location_str, type2.location);
t->chassis_handle = 0x300; /* Type 3 (System enclosure) */
t->board_type = 0x0A; /* Motherboard */
t->contained_element_count = 0;
SMBIOS_BUILD_TABLE_POST;
}
static void smbios_build_type_3_table(void)
{
SMBIOS_BUILD_TABLE_PRE(3, 0x300, true); /* required */
SMBIOS_TABLE_SET_STR(3, manufacturer_str, type3.manufacturer);
t->type = 0x01; /* Other */
SMBIOS_TABLE_SET_STR(3, version_str, type3.version);
SMBIOS_TABLE_SET_STR(3, serial_number_str, type3.serial);
SMBIOS_TABLE_SET_STR(3, asset_tag_number_str, type3.asset);
t->boot_up_state = 0x03; /* Safe */
t->power_supply_state = 0x03; /* Safe */
t->thermal_state = 0x03; /* Safe */
t->security_status = 0x02; /* Unknown */
t->oem_defined = 0;
t->height = 0;
t->number_of_power_cords = 0;
t->contained_element_count = 0;
SMBIOS_TABLE_SET_STR(3, sku_number_str, type3.sku);
SMBIOS_BUILD_TABLE_POST;
}
static void smbios_build_type_4_table(unsigned instance)
{
char sock_str[128];
SMBIOS_BUILD_TABLE_PRE(4, 0x400 + instance, true); /* required */
snprintf(sock_str, sizeof(sock_str), "%s%2x", type4.sock_pfx, instance);
SMBIOS_TABLE_SET_STR(4, socket_designation_str, sock_str);
t->processor_type = 0x03; /* CPU */
SMBIOS_TABLE_SET_STR(4, processor_manufacturer_str, type4.manufacturer);
t->processor_id[0] = smbios_cpuid_version;
t->processor_id[1] = smbios_cpuid_features;
SMBIOS_TABLE_SET_STR(4, processor_version_str, type4.version);
t->voltage = 0;
t->external_clock = 0; /* Unknown */
t->max_speed = 0; /* Unknown */
t->current_speed = 0; /* Unknown */
t->status = 0x41; /* Socket populated, CPU enabled */
t->processor_upgrade = 0x01; /* Other */
t->l1_cache_handle = 0xFFFF; /* N/A */
t->l2_cache_handle = 0xFFFF; /* N/A */
t->l3_cache_handle = 0xFFFF; /* N/A */
SMBIOS_TABLE_SET_STR(4, serial_number_str, type4.serial);
SMBIOS_TABLE_SET_STR(4, asset_tag_number_str, type4.asset);
SMBIOS_TABLE_SET_STR(4, part_number_str, type4.part);
t->core_count = t->core_enabled = smp_cores;
t->thread_count = smp_threads;
t->processor_characteristics = 0x02; /* Unknown */
t->processor_family = t->processor_family2 = 0x01; /* Other */
SMBIOS_BUILD_TABLE_POST;
smbios_type4_count++;
}
#define ONE_KB ((ram_addr_t)1 << 10)
#define ONE_MB ((ram_addr_t)1 << 20)
#define ONE_GB ((ram_addr_t)1 << 30)
#define MAX_T16_STD_SZ 0x80000000 /* 2T in Kilobytes */
static void smbios_build_type_16_table(unsigned dimm_cnt)
{
ram_addr_t size_kb;
SMBIOS_BUILD_TABLE_PRE(16, 0x1000, true); /* required */
t->location = 0x01; /* Other */
t->use = 0x03; /* System memory */
t->error_correction = 0x06; /* Multi-bit ECC (for Microsoft, per SeaBIOS) */
size_kb = QEMU_ALIGN_UP(ram_size, ONE_KB) / ONE_KB;
if (size_kb < MAX_T16_STD_SZ) {
t->maximum_capacity = size_kb;
t->extended_maximum_capacity = 0;
} else {
t->maximum_capacity = MAX_T16_STD_SZ;
t->extended_maximum_capacity = ram_size;
}
t->memory_error_information_handle = 0xFFFE; /* Not provided */
t->number_of_memory_devices = dimm_cnt;
SMBIOS_BUILD_TABLE_POST;
}
#define MAX_T17_STD_SZ 0x7FFF /* (32G - 1M), in Megabytes */
#define MAX_T17_EXT_SZ 0x80000000 /* 2P, in Megabytes */
static void smbios_build_type_17_table(unsigned instance, ram_addr_t size)
{
char loc_str[128];
ram_addr_t size_mb;
SMBIOS_BUILD_TABLE_PRE(17, 0x1100 + instance, true); /* required */
t->physical_memory_array_handle = 0x1000; /* Type 16 (Phys. Mem. Array) */
t->memory_error_information_handle = 0xFFFE; /* Not provided */
t->total_width = 0xFFFF; /* Unknown */
t->data_width = 0xFFFF; /* Unknown */
size_mb = QEMU_ALIGN_UP(size, ONE_MB) / ONE_MB;
if (size_mb < MAX_T17_STD_SZ) {
t->size = size_mb;
t->extended_size = 0;
} else {
assert(size_mb < MAX_T17_EXT_SZ);
t->size = MAX_T17_STD_SZ;
t->extended_size = size_mb;
}
t->form_factor = 0x09; /* DIMM */
t->device_set = 0; /* Not in a set */
snprintf(loc_str, sizeof(loc_str), "%s %d", type17.loc_pfx, instance);
SMBIOS_TABLE_SET_STR(17, device_locator_str, loc_str);
SMBIOS_TABLE_SET_STR(17, bank_locator_str, type17.bank);
t->memory_type = 0x07; /* RAM */
t->type_detail = 0x02; /* Other */
t->speed = 0; /* Unknown */
SMBIOS_TABLE_SET_STR(17, manufacturer_str, type17.manufacturer);
SMBIOS_TABLE_SET_STR(17, serial_number_str, type17.serial);
SMBIOS_TABLE_SET_STR(17, asset_tag_number_str, type17.asset);
SMBIOS_TABLE_SET_STR(17, part_number_str, type17.part);
t->attributes = 0; /* Unknown */
t->configured_clock_speed = 0; /* Unknown */
t->minimum_voltage = 0; /* Unknown */
t->maximum_voltage = 0; /* Unknown */
t->configured_voltage = 0; /* Unknown */
SMBIOS_BUILD_TABLE_POST;
}
static void smbios_build_type_19_table(unsigned instance,
ram_addr_t start, ram_addr_t size)
{
ram_addr_t end, start_kb, end_kb;
SMBIOS_BUILD_TABLE_PRE(19, 0x1300 + instance, true); /* required */
end = start + size - 1;
assert(end > start);
start_kb = start / ONE_KB;
end_kb = end / ONE_KB;
if (start_kb < UINT32_MAX && end_kb < UINT32_MAX) {
t->starting_address = start_kb;
t->ending_address = end_kb;
t->extended_starting_address = t->extended_ending_address = 0;
} else {
t->starting_address = t->ending_address = UINT32_MAX;
t->extended_starting_address = start;
t->extended_ending_address = end;
}
t->memory_array_handle = 0x1000; /* Type 16 (Phys. Mem. Array) */
t->partition_width = 1; /* One device per row */
SMBIOS_BUILD_TABLE_POST;
}
static void smbios_build_type_32_table(void)
{
SMBIOS_BUILD_TABLE_PRE(32, 0x2000, true); /* required */
memset(t->reserved, 0, 6);
t->boot_status = 0; /* No errors detected */
SMBIOS_BUILD_TABLE_POST;
}
static void smbios_build_type_127_table(void)
{
SMBIOS_BUILD_TABLE_PRE(127, 0x7F00, true); /* required */
SMBIOS_BUILD_TABLE_POST;
}
void smbios_set_cpuid(uint32_t version, uint32_t features)
{
smbios_cpuid_version = version;
smbios_cpuid_features = features;
}
#define SMBIOS_SET_DEFAULT(field, value) \
if (!field) { \
field = value; \
}
#define G_FREE_UNLESS_NULL(ptr) \
if (ptr != NULL) { \
g_free(ptr); \
}
void smbios_set_defaults(const char *manufacturer, const char *product,
const char *version, bool legacy_mode)
{
smbios_have_defaults = true;
smbios_legacy = legacy_mode;
/* drop unwanted version of command-line file blob(s) */
if (smbios_legacy) {
G_FREE_UNLESS_NULL(smbios_tables);
/* in legacy mode, also complain if fields were given for types > 1 */
if (find_next_bit(have_fields_bitmap,
SMBIOS_MAX_TYPE+1, 2) < SMBIOS_MAX_TYPE+1) {
error_report("can't process fields for smbios "
"types > 1 on machine versions < 2.1!");
exit(1);
}
} else {
G_FREE_UNLESS_NULL(smbios_entries);
}
SMBIOS_SET_DEFAULT(type1.manufacturer, manufacturer);
SMBIOS_SET_DEFAULT(type1.product, product);
SMBIOS_SET_DEFAULT(type1.version, version);
SMBIOS_SET_DEFAULT(type2.manufacturer, manufacturer);
SMBIOS_SET_DEFAULT(type2.product, product);
SMBIOS_SET_DEFAULT(type2.version, version);
SMBIOS_SET_DEFAULT(type3.manufacturer, manufacturer);
SMBIOS_SET_DEFAULT(type3.version, version);
SMBIOS_SET_DEFAULT(type4.sock_pfx, "CPU");
SMBIOS_SET_DEFAULT(type4.manufacturer, manufacturer);
SMBIOS_SET_DEFAULT(type4.version, version);
SMBIOS_SET_DEFAULT(type17.loc_pfx, "DIMM");
SMBIOS_SET_DEFAULT(type17.manufacturer, manufacturer);
}
static void smbios_entry_point_setup(void)
{
memcpy(ep.anchor_string, "_SM_", 4);
memcpy(ep.intermediate_anchor_string, "_DMI_", 5);
ep.length = sizeof(struct smbios_entry_point);
ep.entry_point_revision = 0; /* formatted_area reserved, per spec v2.1+ */
memset(ep.formatted_area, 0, 5);
/* compliant with smbios spec v2.8 */
ep.smbios_major_version = 2;
ep.smbios_minor_version = 8;
ep.smbios_bcd_revision = 0x28;
/* set during table construction, but BIOS may override: */
ep.structure_table_length = smbios_tables_len;
ep.max_structure_size = smbios_table_max;
ep.number_of_structures = smbios_table_cnt;
/* BIOS must recalculate: */
ep.checksum = 0;
ep.intermediate_checksum = 0;
ep.structure_table_address = 0; /* where BIOS has copied smbios_tables */
}
void smbios_get_tables(uint8_t **tables, size_t *tables_len,
uint8_t **anchor, size_t *anchor_len)
{
unsigned i, dimm_cnt, instance;
if (smbios_legacy) {
*tables = *anchor = NULL;
*tables_len = *anchor_len = 0;
return;
}
if (!smbios_immutable) {
smbios_build_type_0_table();
smbios_build_type_1_table();
smbios_build_type_2_table();
smbios_build_type_3_table();
smbios_smp_sockets = smp_cpus / (smp_cores * smp_threads);
assert(smbios_smp_sockets >= 1);
for (i = 0; i < smbios_smp_sockets; i++) {
smbios_build_type_4_table(i);
}
#define MAX_DIMM_SZ (16ll * ONE_GB)
#define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ : ram_size % MAX_DIMM_SZ)
dimm_cnt = QEMU_ALIGN_UP(ram_size, MAX_DIMM_SZ) / MAX_DIMM_SZ;
smbios_build_type_16_table(dimm_cnt);
for (i = 0; i < dimm_cnt; i++) {
smbios_build_type_17_table(i, GET_DIMM_SZ);
}
for (i = 0, instance = 0; i < e820_get_num_entries(); i++) {
uint64_t address, length;
if (e820_get_entry(i, E820_RAM, &address, &length)) {
smbios_build_type_19_table(instance++, address, length);
}
}
smbios_build_type_32_table();
smbios_build_type_127_table();
smbios_validate_table();
smbios_entry_point_setup();
smbios_immutable = true;
}
/* return tables blob and entry point (anchor), and their sizes */
*tables = smbios_tables;
*tables_len = smbios_tables_len;
*anchor = (uint8_t *)&ep;
*anchor_len = sizeof(struct smbios_entry_point);
}
static void save_opt(const char **dest, QemuOpts *opts, const char *name)
{
@@ -297,11 +876,12 @@ void smbios_entry_add(QemuOpts *opts)
const char *val;
assert(!smbios_immutable);
val = qemu_opt_get(opts, "file");
if (val) {
struct smbios_structure_header *header;
struct smbios_table *table;
int size;
struct smbios_table *table; /* legacy mode only */
qemu_opts_validate(opts, qemu_smbios_file_opts, &local_err);
if (local_err) {
@@ -315,31 +895,60 @@ void smbios_entry_add(QemuOpts *opts)
exit(1);
}
if (!smbios_entries) {
smbios_entries_len = sizeof(uint16_t);
smbios_entries = g_malloc0(smbios_entries_len);
}
/*
* NOTE: standard double '\0' terminator expected, per smbios spec.
* (except in legacy mode, where the second '\0' is implicit and
* will be inserted by the BIOS).
*/
smbios_tables = g_realloc(smbios_tables, smbios_tables_len + size);
header = (struct smbios_structure_header *)(smbios_tables +
smbios_tables_len);
smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
sizeof(*table) + size);
table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
table->header.type = SMBIOS_TABLE_ENTRY;
table->header.length = cpu_to_le16(sizeof(*table) + size);
if (load_image(val, table->data) != size) {
if (load_image(val, (uint8_t *)header) != size) {
error_report("Failed to load SMBIOS file %s", val);
exit(1);
}
header = (struct smbios_structure_header *)(table->data);
smbios_check_collision(header->type, SMBIOS_TABLE_ENTRY);
if (test_bit(header->type, have_fields_bitmap)) {
error_report("can't load type %d struct, fields already specified!",
header->type);
exit(1);
}
set_bit(header->type, have_binfile_bitmap);
if (header->type == 4) {
smbios_type4_count++;
}
smbios_tables_len += size;
if (size > smbios_table_max) {
smbios_table_max = size;
}
smbios_table_cnt++;
/* add a copy of the newly loaded blob to legacy smbios_entries */
/* NOTE: This code runs before smbios_set_defaults(), so we don't
* yet know which mode (legacy vs. aggregate-table) will be
* required. We therefore add the binary blob to both legacy
* (smbios_entries) and aggregate (smbios_tables) tables, and
* delete the one we don't need from smbios_set_defaults(),
* once we know which machine version has been requested.
*/
if (!smbios_entries) {
smbios_entries_len = sizeof(uint16_t);
smbios_entries = g_malloc0(smbios_entries_len);
}
smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
size + sizeof(*table));
table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
table->header.type = SMBIOS_TABLE_ENTRY;
table->header.length = cpu_to_le16(sizeof(*table) + size);
memcpy(table->data, header, size);
smbios_entries_len += sizeof(*table) + size;
(*(uint16_t *)smbios_entries) =
cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
/* end: add a copy of the newly loaded blob to legacy smbios_entries */
return;
}
@@ -347,7 +956,16 @@ void smbios_entry_add(QemuOpts *opts)
if (val) {
unsigned long type = strtoul(val, NULL, 0);
smbios_check_collision(type, SMBIOS_FIELD_ENTRY);
if (type > SMBIOS_MAX_TYPE) {
error_report("out of range!");
exit(1);
}
if (test_bit(type, have_binfile_bitmap)) {
error_report("can't add fields, binary file already loaded!");
exit(1);
}
set_bit(type, have_fields_bitmap);
switch (type) {
case 0:
@@ -391,6 +1009,57 @@ void smbios_entry_add(QemuOpts *opts)
qemu_uuid_set = true;
}
return;
case 2:
qemu_opts_validate(opts, qemu_smbios_type2_opts, &local_err);
if (local_err) {
error_report("%s", error_get_pretty(local_err));
exit(1);
}
save_opt(&type2.manufacturer, opts, "manufacturer");
save_opt(&type2.product, opts, "product");
save_opt(&type2.version, opts, "version");
save_opt(&type2.serial, opts, "serial");
save_opt(&type2.asset, opts, "asset");
save_opt(&type2.location, opts, "location");
return;
case 3:
qemu_opts_validate(opts, qemu_smbios_type3_opts, &local_err);
if (local_err) {
error_report("%s", error_get_pretty(local_err));
exit(1);
}
save_opt(&type3.manufacturer, opts, "manufacturer");
save_opt(&type3.version, opts, "version");
save_opt(&type3.serial, opts, "serial");
save_opt(&type3.asset, opts, "asset");
save_opt(&type3.sku, opts, "sku");
return;
case 4:
qemu_opts_validate(opts, qemu_smbios_type4_opts, &local_err);
if (local_err) {
error_report("%s", error_get_pretty(local_err));
exit(1);
}
save_opt(&type4.sock_pfx, opts, "sock_pfx");
save_opt(&type4.manufacturer, opts, "manufacturer");
save_opt(&type4.version, opts, "version");
save_opt(&type4.serial, opts, "serial");
save_opt(&type4.asset, opts, "asset");
save_opt(&type4.part, opts, "part");
return;
case 17:
qemu_opts_validate(opts, qemu_smbios_type17_opts, &local_err);
if (local_err) {
error_report("%s", error_get_pretty(local_err));
exit(1);
}
save_opt(&type17.loc_pfx, opts, "loc_pfx");
save_opt(&type17.bank, opts, "bank");
save_opt(&type17.manufacturer, opts, "manufacturer");
save_opt(&type17.serial, opts, "serial");
save_opt(&type17.asset, opts, "asset");
save_opt(&type17.part, opts, "part");
return;
default:
error_report("Don't know how to build fields for SMBIOS type %ld",
type);

View File

@@ -173,7 +173,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
return 10000;
case 0xd00: /* CPUID Base. */
cpu = ARM_CPU(current_cpu);
return cpu->env.cp15.c0_cpuid;
return cpu->midr;
case 0xd04: /* Interrupt Control State. */
/* VECTACTIVE */
val = s->gic.running_irq[0];

View File

@@ -234,13 +234,9 @@ static void kvm_openpic_realize(DeviceState *dev, Error **errp)
int kvm_openpic_connect_vcpu(DeviceState *d, CPUState *cs)
{
KVMOpenPICState *opp = KVM_OPENPIC(d);
struct kvm_enable_cap encap = {};
encap.cap = KVM_CAP_IRQ_MPIC;
encap.args[0] = opp->fd;
encap.args[1] = kvm_arch_vcpu_id(cs);
return kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap);
return kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_MPIC, 0, opp->fd,
kvm_arch_vcpu_id(cs));
}
static Property kvm_openpic_properties[] = {

View File

@@ -331,15 +331,11 @@ static void xics_kvm_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
if (icpkvm->kernel_xics_fd != -1) {
int ret;
struct kvm_enable_cap xics_enable_cap = {
.cap = KVM_CAP_IRQ_XICS,
.flags = 0,
.args = {icpkvm->kernel_xics_fd, kvm_arch_vcpu_id(cs), 0, 0},
};
ss->cs = cs;
ret = kvm_vcpu_ioctl(ss->cs, KVM_ENABLE_CAP, &xics_enable_cap);
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_XICS, 0,
icpkvm->kernel_xics_fd, kvm_arch_vcpu_id(cs));
if (ret < 0) {
error_report("Unable to connect CPU%ld to kernel XICS: %s",
kvm_arch_vcpu_id(cs), strerror(errno));

View File

@@ -92,6 +92,7 @@ typedef enum {
#define BDRV_O_RDWR 0x0002
#define BDRV_O_SNAPSHOT 0x0008 /* open the file read only and save writes in a snapshot */
#define BDRV_O_TEMPORARY 0x0010 /* delete the file after use */
#define BDRV_O_NOCACHE 0x0020 /* do not use the host page cache */
#define BDRV_O_CACHE_WB 0x0040 /* use write-back caching */
#define BDRV_O_NATIVE_AIO 0x0080 /* use native AIO instead of the thread pool */

View File

@@ -299,7 +299,6 @@ struct BlockDriverState {
char backing_file[1024]; /* if non zero, the image is a diff of
this file image */
char backing_format[16]; /* if non-zero and backing_file exists */
int is_temporary;
BlockDriverState *backing_hd;
BlockDriverState *file;

View File

@@ -84,7 +84,7 @@
#define dh_is_64bit_noreturn 0
#define dh_is_64bit_i32 0
#define dh_is_64bit_i64 1
#define dh_is_64bit_ptr (TCG_TARGET_REG_BITS == 64)
#define dh_is_64bit_ptr (sizeof(void *) == 8)
#define dh_is_64bit(t) glue(dh_is_64bit_, dh_alias(t))
#define dh_is_signed_void 0

View File

@@ -239,6 +239,8 @@ uint16_t pvpanic_port(void);
#define E820_UNUSABLE 5
int e820_add_entry(uint64_t, uint64_t, uint32_t);
int e820_get_num_entries(void);
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
#define PC_Q35_COMPAT_1_7 \
PC_COMPAT_1_7, \

View File

@@ -15,15 +15,40 @@
#include "qemu/option.h"
#define SMBIOS_MAX_TYPE 127
void smbios_entry_add(QemuOpts *opts);
void smbios_set_type1_defaults(const char *manufacturer,
const char *product, const char *version);
uint8_t *smbios_get_table(size_t *length);
void smbios_set_cpuid(uint32_t version, uint32_t features);
void smbios_set_defaults(const char *manufacturer, const char *product,
const char *version, bool legacy_mode);
uint8_t *smbios_get_table_legacy(size_t *length);
void smbios_get_tables(uint8_t **tables, size_t *tables_len,
uint8_t **anchor, size_t *anchor_len);
/*
* SMBIOS spec defined tables
*/
/* SMBIOS entry point (anchor).
* BIOS must place this at a 16-bit-aligned address between 0xf0000 and 0xfffff.
*/
struct smbios_entry_point {
uint8_t anchor_string[4];
uint8_t checksum;
uint8_t length;
uint8_t smbios_major_version;
uint8_t smbios_minor_version;
uint16_t max_structure_size;
uint8_t entry_point_revision;
uint8_t formatted_area[5];
uint8_t intermediate_anchor_string[5];
uint8_t intermediate_checksum;
uint16_t structure_table_length;
uint32_t structure_table_address;
uint16_t number_of_structures;
uint8_t smbios_bcd_revision;
} QEMU_PACKED;
/* This goes at the beginning of every SMBIOS structure. */
struct smbios_structure_header {
uint8_t type;
@@ -60,7 +85,23 @@ struct smbios_type_1 {
uint8_t family_str;
} QEMU_PACKED;
/* SMBIOS type 3 - System Enclosure (v2.3) */
/* SMBIOS type 2 - Base Board */
struct smbios_type_2 {
struct smbios_structure_header header;
uint8_t manufacturer_str;
uint8_t product_str;
uint8_t version_str;
uint8_t serial_number_str;
uint8_t asset_tag_number_str;
uint8_t feature_flags;
uint8_t location_str;
uint16_t chassis_handle;
uint8_t board_type;
uint8_t contained_element_count;
/* contained elements follow */
} QEMU_PACKED;
/* SMBIOS type 3 - System Enclosure (v2.7) */
struct smbios_type_3 {
struct smbios_structure_header header;
uint8_t manufacturer_str;
@@ -76,10 +117,11 @@ struct smbios_type_3 {
uint8_t height;
uint8_t number_of_power_cords;
uint8_t contained_element_count;
// contained elements follow
uint8_t sku_number_str;
/* contained elements follow */
} QEMU_PACKED;
/* SMBIOS type 4 - Processor Information (v2.0) */
/* SMBIOS type 4 - Processor Information (v2.6) */
struct smbios_type_4 {
struct smbios_structure_header header;
uint8_t socket_designation_str;
@@ -97,11 +139,17 @@ struct smbios_type_4 {
uint16_t l1_cache_handle;
uint16_t l2_cache_handle;
uint16_t l3_cache_handle;
uint8_t serial_number_str;
uint8_t asset_tag_number_str;
uint8_t part_number_str;
uint8_t core_count;
uint8_t core_enabled;
uint8_t thread_count;
uint16_t processor_characteristics;
uint16_t processor_family2;
} QEMU_PACKED;
/* SMBIOS type 16 - Physical Memory Array
* Associated with one type 17 (Memory Device).
*/
/* SMBIOS type 16 - Physical Memory Array (v2.7) */
struct smbios_type_16 {
struct smbios_structure_header header;
uint8_t location;
@@ -110,10 +158,10 @@ struct smbios_type_16 {
uint32_t maximum_capacity;
uint16_t memory_error_information_handle;
uint16_t number_of_memory_devices;
uint64_t extended_maximum_capacity;
} QEMU_PACKED;
/* SMBIOS type 17 - Memory Device
* Associated with one type 19
*/
/* SMBIOS type 17 - Memory Device (v2.8) */
struct smbios_type_17 {
struct smbios_structure_header header;
uint16_t physical_memory_array_handle;
@@ -127,27 +175,28 @@ struct smbios_type_17 {
uint8_t bank_locator_str;
uint8_t memory_type;
uint16_t type_detail;
uint16_t speed;
uint8_t manufacturer_str;
uint8_t serial_number_str;
uint8_t asset_tag_number_str;
uint8_t part_number_str;
uint8_t attributes;
uint32_t extended_size;
uint32_t configured_clock_speed;
uint32_t minimum_voltage;
uint32_t maximum_voltage;
uint32_t configured_voltage;
} QEMU_PACKED;
/* SMBIOS type 19 - Memory Array Mapped Address */
/* SMBIOS type 19 - Memory Array Mapped Address (v2.7) */
struct smbios_type_19 {
struct smbios_structure_header header;
uint32_t starting_address;
uint32_t ending_address;
uint16_t memory_array_handle;
uint8_t partition_width;
} QEMU_PACKED;
/* SMBIOS type 20 - Memory Device Mapped Address */
struct smbios_type_20 {
struct smbios_structure_header header;
uint32_t starting_address;
uint32_t ending_address;
uint16_t memory_device_handle;
uint16_t memory_array_mapped_address_handle;
uint8_t partition_row_position;
uint8_t interleave_position;
uint8_t interleaved_data_depth;
uint64_t extended_starting_address;
uint64_t extended_ending_address;
} QEMU_PACKED;
/* SMBIOS type 32 - System Boot Information */

View File

@@ -294,6 +294,36 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cpu);
int kvm_check_extension(KVMState *s, unsigned int extension);
#define kvm_vm_enable_cap(s, capability, cap_flags, ...) \
({ \
struct kvm_enable_cap cap = { \
.cap = capability, \
.flags = cap_flags, \
}; \
uint64_t args_tmp[] = { __VA_ARGS__ }; \
int i; \
for (i = 0; i < ARRAY_SIZE(args_tmp) && \
i < ARRAY_SIZE(cap.args); i++) { \
cap.args[i] = args_tmp[i]; \
} \
kvm_vm_ioctl(s, KVM_ENABLE_CAP, &cap); \
})
#define kvm_vcpu_enable_cap(cpu, capability, cap_flags, ...) \
({ \
struct kvm_enable_cap cap = { \
.cap = capability, \
.flags = cap_flags, \
}; \
uint64_t args_tmp[] = { __VA_ARGS__ }; \
int i; \
for (i = 0; i < ARRAY_SIZE(args_tmp) && \
i < ARRAY_SIZE(cap.args); i++) { \
cap.args[i] = args_tmp[i]; \
} \
kvm_vcpu_ioctl(cpu, KVM_ENABLE_CAP, &cap); \
})
uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
uint32_t index, int reg);

View File

@@ -33,6 +33,9 @@
#include "block/qapi.h"
#include <getopt.h>
#define QEMU_IMG_VERSION "qemu-img version " QEMU_VERSION \
", Copyright (c) 2004-2008 Fabrice Bellard\n"
typedef struct img_cmd_t {
const char *name;
int (*handler)(int argc, char **argv);
@@ -75,7 +78,7 @@ static void QEMU_NORETURN GCC_FMT_ATTR(1, 2) error_exit(const char *fmt, ...)
static void QEMU_NORETURN help(void)
{
const char *help_msg =
"qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
QEMU_IMG_VERSION
"usage: qemu-img command [command options]\n"
"QEMU disk image utility\n"
"\n"
@@ -2789,6 +2792,12 @@ int main(int argc, char **argv)
{
const img_cmd_t *cmd;
const char *cmdname;
int c;
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'v'},
{0, 0, 0, 0}
};
#ifdef CONFIG_POSIX
signal(SIGPIPE, SIG_IGN);
@@ -2803,15 +2812,24 @@ int main(int argc, char **argv)
error_exit("Not enough arguments");
}
cmdname = argv[1];
argc--; argv++;
/* find the command */
for (cmd = img_cmds; cmd->name != NULL; cmd++) {
if (!strcmp(cmdname, cmd->name)) {
return cmd->handler(argc, argv);
return cmd->handler(argc - 1, argv + 1);
}
}
c = getopt_long(argc, argv, "h", long_options, NULL);
if (c == 'h') {
help();
}
if (c == 'v') {
printf(QEMU_IMG_VERSION);
return 0;
}
/* not found */
error_exit("Command not found: %s", cmdname);
}

View File

@@ -657,7 +657,7 @@ static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
* contexts. (ARMv8 would permit us to do no masking at all, but ARMv7
* requires the bottom five bits to be RAZ/WI because they're UNK/SBZP.)
*/
env->cp15.c12_vbar = value & ~0x1Ful;
env->cp15.c12_vbar = value & ~0x1FULL;
}
static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
@@ -1578,6 +1578,21 @@ static const ARMCPRegInfo xscale_cp_reginfo[] = {
.cp = 15, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 1, .access = PL1_RW,
.fieldoffset = offsetof(CPUARMState, cp15.c1_xscaleauxcr),
.resetvalue = 0, },
/* XScale specific cache-lockdown: since we have no cache we NOP these
* and hope the guest does not really rely on cache behaviour.
*/
{ .name = "XSCALE_LOCK_ICACHE_LINE",
.cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
.access = PL1_W, .type = ARM_CP_NOP },
{ .name = "XSCALE_UNLOCK_ICACHE",
.cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 1,
.access = PL1_W, .type = ARM_CP_NOP },
{ .name = "XSCALE_DCACHE_LOCK",
.cp = 15, .opc1 = 0, .crn = 9, .crm = 2, .opc2 = 0,
.access = PL1_RW, .type = ARM_CP_NOP },
{ .name = "XSCALE_UNLOCK_DCACHE",
.cp = 15, .opc1 = 0, .crn = 9, .crm = 2, .opc2 = 1,
.access = PL1_W, .type = ARM_CP_NOP },
REGINFO_SENTINEL
};
@@ -1893,51 +1908,51 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
.access = PL1_W, .type = ARM_CP_NOP },
/* TLBI operations */
{ .name = "TLBI_VMALLE1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 0,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0,
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
.writefn = tlbiall_write },
{ .name = "TLBI_VAE1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 1,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1,
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
.writefn = tlbi_aa64_va_write },
{ .name = "TLBI_ASIDE1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 2,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2,
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
.writefn = tlbi_aa64_asid_write },
{ .name = "TLBI_VAAE1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 3,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
.writefn = tlbi_aa64_vaa_write },
{ .name = "TLBI_VALE1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 5,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5,
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
.writefn = tlbi_aa64_va_write },
{ .name = "TLBI_VAALE1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 7,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7,
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
.writefn = tlbi_aa64_vaa_write },
{ .name = "TLBI_VMALLE1", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 0,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0,
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
.writefn = tlbiall_write },
{ .name = "TLBI_VAE1", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 1,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1,
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
.writefn = tlbi_aa64_va_write },
{ .name = "TLBI_ASIDE1", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 2,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2,
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
.writefn = tlbi_aa64_asid_write },
{ .name = "TLBI_VAAE1", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 3,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
.writefn = tlbi_aa64_vaa_write },
{ .name = "TLBI_VALE1", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 5,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5,
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
.writefn = tlbi_aa64_va_write },
{ .name = "TLBI_VAALE1", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 7,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7,
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
.writefn = tlbi_aa64_vaa_write },
#ifndef CONFIG_USER_ONLY

View File

@@ -418,7 +418,7 @@ void HELPER(exception_return)(CPUARMState *env)
goto illegal_return;
}
if (new_el == 0 && (spsr & PSTATE_SP)) {
/* Return to EL1 with M[0] bit set */
/* Return to EL0 with M[0] bit set */
goto illegal_return;
}
env->aarch64 = 1;

View File

@@ -1151,6 +1151,8 @@ static void handle_hint(DisasContext *s, uint32_t insn,
return;
case 1: /* YIELD */
case 2: /* WFE */
s->is_jmp = DISAS_WFE;
return;
case 4: /* SEV */
case 5: /* SEVL */
/* we treat all as NOP at least for now */
@@ -1507,8 +1509,10 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
switch (opc) {
case 0: /* BR */
case 2: /* RET */
tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
break;
case 1: /* BLR */
tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
break;
case 4: /* ERET */
@@ -1527,7 +1531,6 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
return;
}
tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
s->is_jmp = DISAS_JUMP;
}
@@ -10765,6 +10768,10 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
case DISAS_EXC:
case DISAS_SWI:
break;
case DISAS_WFE:
gen_a64_set_pc_im(dc->pc);
gen_helper_wfe(cpu_env);
break;
case DISAS_WFI:
/* This is a special case because we don't want to just halt the CPU
* if trying to debug across a WFI.

View File

@@ -151,7 +151,6 @@ static int kvm_booke206_tlb_init(PowerPCCPU *cpu)
CPUState *cs = CPU(cpu);
struct kvm_book3e_206_tlb_params params = {};
struct kvm_config_tlb cfg = {};
struct kvm_enable_cap encap = {};
unsigned int entries = 0;
int ret, i;
@@ -178,10 +177,7 @@ static int kvm_booke206_tlb_init(PowerPCCPU *cpu)
cfg.params = (uintptr_t)&params;
cfg.mmu_type = KVM_MMU_FSL_BOOKE_NOHV;
encap.cap = KVM_CAP_SW_TLB;
encap.args[0] = (uintptr_t)&cfg;
ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap);
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_SW_TLB, 0, (uintptr_t)&cfg);
if (ret < 0) {
fprintf(stderr, "%s: couldn't enable KVM_CAP_SW_TLB: %s\n",
__func__, strerror(-ret));
@@ -1292,7 +1288,6 @@ int kvmppc_set_tcr(PowerPCCPU *cpu)
int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu)
{
CPUState *cs = CPU(cpu);
struct kvm_enable_cap encap = {};
int ret;
if (!kvm_enabled()) {
@@ -1304,8 +1299,7 @@ int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu)
return -1;
}
encap.cap = KVM_CAP_PPC_BOOKE_WATCHDOG;
ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap);
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_BOOKE_WATCHDOG, 0);
if (ret < 0) {
fprintf(stderr, "%s: couldn't enable KVM_CAP_PPC_BOOKE_WATCHDOG: %s\n",
__func__, strerror(-ret));
@@ -1505,12 +1499,9 @@ int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
void kvmppc_set_papr(PowerPCCPU *cpu)
{
CPUState *cs = CPU(cpu);
struct kvm_enable_cap cap = {};
int ret;
cap.cap = KVM_CAP_PPC_PAPR;
ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &cap);
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_PAPR, 0);
if (ret) {
cpu_abort(cs, "This KVM version does not support PAPR\n");
}
@@ -1523,13 +1514,9 @@ void kvmppc_set_papr(PowerPCCPU *cpu)
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
{
CPUState *cs = CPU(cpu);
struct kvm_enable_cap cap = {};
int ret;
cap.cap = KVM_CAP_PPC_EPR;
cap.args[0] = mpic_proxy;
ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &cap);
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_PPC_EPR, 0, mpic_proxy);
if (ret && mpic_proxy) {
cpu_abort(cs, "This KVM version does not support EPR\n");
}

View File

@@ -929,12 +929,10 @@ void kvm_s390_crw_mchk(S390CPU *cpu)
void kvm_s390_enable_css_support(S390CPU *cpu)
{
struct kvm_enable_cap cap = {};
int r;
/* Activate host kernel channel subsystem support. */
cap.cap = KVM_CAP_S390_CSS_SUPPORT;
r = kvm_vcpu_ioctl(CPU(cpu), KVM_ENABLE_CAP, &cap);
r = kvm_vcpu_enable_cap(CPU(cpu), KVM_CAP_S390_CSS_SUPPORT, 0);
assert(r == 0);
}

View File

@@ -314,6 +314,11 @@ This operation would be equivalent to
dest = (t1 & ~0x0f00) | ((t2 << 8) & 0x0f00)
* trunc_shr_i32 t0, t1, pos
For 64-bit hosts only, right shift the 64-bit input T1 by POS and
truncate to 32-bit output T0. Depending on the host, this may be
a simple mov/shift, or may require additional canonicalization.
********* Conditional moves

View File

@@ -68,6 +68,7 @@ typedef enum {
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0
#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 1

View File

@@ -99,6 +99,7 @@ extern bool have_bmi1;
#define TCG_TARGET_HAS_mulsh_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_div2_i64 1
#define TCG_TARGET_HAS_rot_i64 1
#define TCG_TARGET_HAS_ext8s_i64 1

View File

@@ -152,6 +152,7 @@ typedef enum {
#define TCG_TARGET_HAS_muluh_i64 0
#define TCG_TARGET_HAS_mulsh_i32 0
#define TCG_TARGET_HAS_mulsh_i64 0
#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_new_ldst 1

View File

@@ -228,6 +228,7 @@ static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
case INDEX_op_shr_i32:
return (uint32_t)x >> (y & 31);
case INDEX_op_trunc_shr_i32:
case INDEX_op_shr_i64:
return (uint64_t)x >> (y & 63);
@@ -830,6 +831,10 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
}
break;
case INDEX_op_trunc_shr_i32:
mask = (uint64_t)temps[args[1]].mask >> args[2];
break;
CASE_OP_32_64(shl):
if (temps[args[2]].state == TCG_TEMP_CONST) {
tmp = temps[args[2]].val & (TCG_TARGET_REG_BITS - 1);
@@ -1021,6 +1026,17 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
}
goto do_default;
case INDEX_op_trunc_shr_i32:
if (temps[args[1]].state == TCG_TEMP_CONST) {
s->gen_opc_buf[op_index] = op_to_movi(op);
tmp = do_constant_folding(op, temps[args[1]].val, args[2]);
tcg_opt_gen_movi(gen_args, args[0], tmp);
gen_args += 2;
args += 3;
break;
}
goto do_default;
CASE_OP_32_64(add):
CASE_OP_32_64(sub):
CASE_OP_32_64(mul):

View File

@@ -96,6 +96,7 @@ typedef enum {
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0
#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 0

View File

@@ -69,6 +69,7 @@ typedef enum TCGReg {
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0
#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_div2_i64 1
#define TCG_TARGET_HAS_rot_i64 1

File diff suppressed because it is too large Load Diff

View File

@@ -24,13 +24,7 @@
#ifndef TCG_TARGET_SPARC
#define TCG_TARGET_SPARC 1
#if UINTPTR_MAX == UINT32_MAX
# define TCG_TARGET_REG_BITS 32
#elif UINTPTR_MAX == UINT64_MAX
#define TCG_TARGET_REG_BITS 64
#else
# error Unknown pointer size for tcg target
#endif
#define TCG_TARGET_NB_REGS 32
@@ -76,7 +70,7 @@ typedef enum {
/* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_O6
#if TCG_TARGET_REG_BITS == 64
#ifdef __arch64__
#define TCG_TARGET_STACK_BIAS 2047
#define TCG_TARGET_STACK_ALIGN 16
#define TCG_TARGET_CALL_STACK_OFFSET (128 + 6*8 + TCG_TARGET_STACK_BIAS)
@@ -86,7 +80,7 @@ typedef enum {
#define TCG_TARGET_CALL_STACK_OFFSET (64 + 4 + 6*4)
#endif
#if TCG_TARGET_REG_BITS == 64
#ifdef __arch64__
#define TCG_TARGET_EXTEND_ARGS 1
#endif
@@ -112,11 +106,11 @@ typedef enum {
#define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1
#define TCG_TARGET_HAS_mulu2_i32 1
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_muls2_i32 1
#define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_trunc_shr_i32 1
#define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_rot_i64 0
@@ -144,7 +138,6 @@ typedef enum {
#define TCG_TARGET_HAS_muls2_i64 0
#define TCG_TARGET_HAS_muluh_i64 0
#define TCG_TARGET_HAS_mulsh_i64 0
#endif
#define TCG_TARGET_HAS_new_ldst 1

View File

@@ -1624,9 +1624,20 @@ static inline void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
}
static inline void tcg_gen_trunc_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
static inline void tcg_gen_trunc_shr_i64_i32(TCGv_i32 ret, TCGv_i64 arg,
unsigned int count)
{
tcg_debug_assert(count < 64);
if (count >= 32) {
tcg_gen_shri_i32(ret, TCGV_HIGH(arg), count - 32);
} else if (count == 0) {
tcg_gen_mov_i32(ret, TCGV_LOW(arg));
} else {
TCGv_i64 t = tcg_temp_new_i64();
tcg_gen_shri_i64(t, arg, count);
tcg_gen_mov_i32(ret, TCGV_LOW(t));
tcg_temp_free_i64(t);
}
}
static inline void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
@@ -1727,11 +1738,21 @@ static inline void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
}
}
/* Note: we assume the target supports move between 32 and 64 bit
registers. This will probably break MIPS64 targets. */
static inline void tcg_gen_trunc_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
static inline void tcg_gen_trunc_shr_i64_i32(TCGv_i32 ret, TCGv_i64 arg,
unsigned int count)
{
tcg_debug_assert(count < 64);
if (TCG_TARGET_HAS_trunc_shr_i32) {
tcg_gen_op3i_i32(INDEX_op_trunc_shr_i32, ret,
MAKE_TCGV_I32(GET_TCGV_I64(arg)), count);
} else if (count == 0) {
tcg_gen_mov_i32(ret, MAKE_TCGV_I32(GET_TCGV_I64(arg)));
} else {
TCGv_i64 t = tcg_temp_new_i64();
tcg_gen_shri_i64(t, arg, count);
tcg_gen_mov_i32(ret, MAKE_TCGV_I32(GET_TCGV_I64(t)));
tcg_temp_free_i64(t);
}
}
/* Note: we assume the target supports move between 32 and 64 bit
@@ -2275,18 +2296,15 @@ static inline void tcg_gen_concat32_i64(TCGv_i64 dest, TCGv_i64 low,
tcg_gen_deposit_i64(dest, low, high, 32, 32);
}
static inline void tcg_gen_trunc_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
{
tcg_gen_trunc_shr_i64_i32(ret, arg, 0);
}
static inline void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg)
{
#if TCG_TARGET_REG_BITS == 32
tcg_gen_mov_i32(lo, TCGV_LOW(arg));
tcg_gen_mov_i32(hi, TCGV_HIGH(arg));
#else
TCGv_i64 t0 = tcg_temp_new_i64();
tcg_gen_trunc_i64_i32(lo, arg);
tcg_gen_shri_i64(t0, arg, 32);
tcg_gen_trunc_i64_i32(hi, t0);
tcg_temp_free_i64(t0);
#endif
tcg_gen_trunc_shr_i64_i32(lo, arg, 0);
tcg_gen_trunc_shr_i64_i32(hi, arg, 32);
}
static inline void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg)
@@ -2861,7 +2879,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
#define tcg_gen_muls2_tl tcg_gen_muls2_i32
#endif
#if TCG_TARGET_REG_BITS == 32
#if UINTPTR_MAX == UINT32_MAX
# define tcg_gen_ld_ptr(R, A, O) \
tcg_gen_ld_i32(TCGV_PTR_TO_NAT(R), (A), (O))
# define tcg_gen_discard_ptr(A) \
@@ -2883,4 +2901,4 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
tcg_gen_addi_i64(TCGV_PTR_TO_NAT(R), TCGV_PTR_TO_NAT(A), (B))
# define tcg_gen_ext_i32_ptr(R, A) \
tcg_gen_ext_i32_i64(TCGV_PTR_TO_NAT(R), (A))
#endif /* TCG_TARGET_REG_BITS == 32 */
#endif /* UINTPTR_MAX == UINT32_MAX */

View File

@@ -147,6 +147,10 @@ DEF(rotl_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rot_i64))
DEF(rotr_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rot_i64))
DEF(deposit_i64, 1, 2, 2, IMPL64 | IMPL(TCG_TARGET_HAS_deposit_i64))
DEF(trunc_shr_i32, 1, 1, 1,
IMPL(TCG_TARGET_HAS_trunc_shr_i32)
| (TCG_TARGET_REG_BITS == 32 ? TCG_OPF_NOT_PRESENT : 0))
DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | IMPL64)
DEF(ext8s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext8s_i64))
DEF(ext16s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext16s_i64))

View File

@@ -664,7 +664,36 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
int nb_rets;
TCGArg *nparam;
#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
#if defined(__sparc__) && !defined(__arch64__) \
&& !defined(CONFIG_TCG_INTERPRETER)
/* We have 64-bit values in one register, but need to pass as two
separate parameters. Split them. */
int orig_sizemask = sizemask;
int orig_nargs = nargs;
TCGv_i64 retl, reth;
TCGV_UNUSED_I64(retl);
TCGV_UNUSED_I64(reth);
if (sizemask != 0) {
TCGArg *split_args = __builtin_alloca(sizeof(TCGArg) * nargs * 2);
for (i = real_args = 0; i < nargs; ++i) {
int is_64bit = sizemask & (1 << (i+1)*2);
if (is_64bit) {
TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
TCGv_i32 h = tcg_temp_new_i32();
TCGv_i32 l = tcg_temp_new_i32();
tcg_gen_extr_i64_i32(l, h, orig);
split_args[real_args++] = GET_TCGV_I32(h);
split_args[real_args++] = GET_TCGV_I32(l);
} else {
split_args[real_args++] = args[i];
}
}
nargs = real_args;
args = split_args;
sizemask = 0;
}
#elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
for (i = 0; i < nargs; ++i) {
int is_64bit = sizemask & (1 << (i+1)*2);
int is_signed = sizemask & (2 << (i+1)*2);
@@ -684,8 +713,23 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
*s->gen_opc_ptr++ = INDEX_op_call;
nparam = s->gen_opparam_ptr++;
if (ret != TCG_CALL_DUMMY_ARG) {
#if TCG_TARGET_REG_BITS < 64
if (sizemask & 1) {
#if defined(__sparc__) && !defined(__arch64__) \
&& !defined(CONFIG_TCG_INTERPRETER)
if (orig_sizemask & 1) {
/* The 32-bit ABI is going to return the 64-bit value in
the %o0/%o1 register pair. Prepare for this by using
two return temporaries, and reassemble below. */
retl = tcg_temp_new_i64();
reth = tcg_temp_new_i64();
*s->gen_opparam_ptr++ = GET_TCGV_I64(reth);
*s->gen_opparam_ptr++ = GET_TCGV_I64(retl);
nb_rets = 2;
} else {
*s->gen_opparam_ptr++ = ret;
nb_rets = 1;
}
#else
if (TCG_TARGET_REG_BITS < 64 && (sizemask & 1)) {
#ifdef HOST_WORDS_BIGENDIAN
*s->gen_opparam_ptr++ = ret + 1;
*s->gen_opparam_ptr++ = ret;
@@ -694,12 +738,11 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
*s->gen_opparam_ptr++ = ret + 1;
#endif
nb_rets = 2;
} else
#endif
{
} else {
*s->gen_opparam_ptr++ = ret;
nb_rets = 1;
}
#endif
} else {
nb_rets = 0;
}
@@ -749,7 +792,29 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
/* total parameters, needed to go backward in the instruction stream */
*s->gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
#if defined(__sparc__) && !defined(__arch64__) \
&& !defined(CONFIG_TCG_INTERPRETER)
/* Free all of the parts we allocated above. */
for (i = real_args = 0; i < orig_nargs; ++i) {
int is_64bit = orig_sizemask & (1 << (i+1)*2);
if (is_64bit) {
TCGv_i32 h = MAKE_TCGV_I32(args[real_args++]);
TCGv_i32 l = MAKE_TCGV_I32(args[real_args++]);
tcg_temp_free_i32(h);
tcg_temp_free_i32(l);
} else {
real_args++;
}
}
if (orig_sizemask & 1) {
/* The 32-bit ABI returned two 32-bit pieces. Re-assemble them.
Note that describing these as TCGv_i64 eliminates an unnecessary
zero-extension that tcg_gen_concat_i32_i64 would create. */
tcg_gen_concat32_i64(MAKE_TCGV_I64(ret), retl, reth);
tcg_temp_free_i64(retl);
tcg_temp_free_i64(reth);
}
#elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
for (i = 0; i < nargs; ++i) {
int is_64bit = sizemask & (1 << (i+1)*2);
if (!is_64bit) {
@@ -2411,6 +2476,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
ts = &s->temps[arg];
reg = tcg_target_call_oarg_regs[i];
assert(s->reg_to_temp[reg] == -1);
if (ts->fixed_reg) {
if (ts->reg != reg) {
tcg_out_mov(s, ts->type, ts->reg, reg);

View File

@@ -66,6 +66,7 @@ typedef uint64_t TCGRegSet;
#if TCG_TARGET_REG_BITS == 32
/* Turn some undef macros into false macros. */
#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_div_i64 0
#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_div2_i64 0

View File

@@ -82,6 +82,7 @@
#define TCG_TARGET_HAS_mulsh_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_bswap16_i64 1
#define TCG_TARGET_HAS_bswap32_i64 1
#define TCG_TARGET_HAS_bswap64_i64 1

View File

@@ -113,6 +113,10 @@ check-qtest-pci-y += tests/tpci200-test$(EXESUF)
gcov-files-pci-y += hw/ipack/tpci200.c
check-qtest-pci-y += $(check-qtest-ipack-y)
gcov-files-pci-y += $(gcov-files-ipack-y)
check-qtest-pci-y += tests/display-vga-test$(EXESUF)
gcov-files-pci-y += hw/display/vga.c
gcov-files-pci-y += hw/display/cirrus_vga.c
gcov-files-pci-y += hw/display/vga-pci.c
check-qtest-i386-y = tests/endianness-test$(EXESUF)
check-qtest-i386-y += tests/fdc-test$(EXESUF)
@@ -280,6 +284,7 @@ tests/virtio-9p-test$(EXESUF): tests/virtio-9p-test.o
tests/virtio-serial-test$(EXESUF): tests/virtio-serial-test.o
tests/virtio-console-test$(EXESUF): tests/virtio-console-test.o
tests/tpci200-test$(EXESUF): tests/tpci200-test.o
tests/display-vga-test$(EXESUF): tests/display-vga-test.o
tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o
tests/qom-test$(EXESUF): tests/qom-test.o
tests/blockdev-test$(EXESUF): tests/blockdev-test.o $(libqos-pc-obj-y)

52
tests/display-vga-test.c Normal file
View File

@@ -0,0 +1,52 @@
/*
* QTest testcase for vga cards
*
* Copyright (c) 2014 Red Hat, Inc
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include <glib.h>
#include <string.h>
#include "libqtest.h"
#include "qemu/osdep.h"
static void pci_cirrus(void)
{
qtest_start("-vga none -device cirrus-vga");
qtest_end();
}
static void pci_stdvga(void)
{
qtest_start("-vga none -device VGA");
qtest_end();
}
static void pci_secondary(void)
{
qtest_start("-vga none -device secondary-vga");
qtest_end();
}
static void pci_multihead(void)
{
qtest_start("-vga none -device VGA -device secondary-vga");
qtest_end();
}
int main(int argc, char **argv)
{
int ret;
g_test_init(&argc, &argv, NULL);
qtest_add_func("/display/pci/cirrus", pci_cirrus);
qtest_add_func("/display/pci/stdvga", pci_stdvga);
qtest_add_func("/display/pci/secondary", pci_secondary);
qtest_add_func("/display/pci/multihead", pci_multihead);
ret = g_test_run();
return ret;
}

View File

@@ -96,7 +96,7 @@ mv "$TEST_IMG" "$TEST_IMG.orig"
for backing_option in "-B " "-o backing_file="; do
echo
echo Testing conversion with $backing_option$TEST_IMG.base | _filter_testdir | _filter_imgfmt
echo Testing conversion with $backing_option"$TEST_IMG.base" | _filter_testdir | _filter_imgfmt
echo
$QEMU_IMG convert -O $IMGFMT $backing_option"$TEST_IMG.base" "$TEST_IMG.orig" "$TEST_IMG"

View File

@@ -51,10 +51,10 @@ function run_qemu_img()
size=128M
_make_test_img $size
$QEMU_IO -c 'write 0 1M' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'write 2M 1M' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'write 4M 1M' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'write 32M 1M' $TEST_IMG | _filter_qemu_io
$QEMU_IO -c 'write 0 1M' "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c 'write 2M 1M' "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c 'write 4M 1M' "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c 'write 32M 1M' "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG convert -p -O $IMGFMT -f $IMGFMT "$TEST_IMG" "$TEST_IMG".base 2>&1 |\
_filter_testdir | sed -e 's/\r/\n/g'

61
tests/qemu-iotests/090 Executable file
View File

@@ -0,0 +1,61 @@
#!/bin/bash
#
# Test for discarding compressed clusters on qcow2 images
#
# Copyright (C) 2014 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# creator
owner=mreitz@redhat.com
seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
{
_cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
# get standard environment, filters and checks
. ./common.rc
. ./common.filter
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
IMG_SIZE=128K
_make_test_img $IMG_SIZE
$QEMU_IO -c 'write -c -P 42 0 64k' \
-c 'write -c -P 23 64k 64k' \
-c 'discard 64k 64k' \
"$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c 'read -P 0 64k 64k' "$TEST_IMG" | _filter_qemu_io
_check_test_img
# success, all done
echo "*** done"
rm -f $seq.full
status=0

View File

@@ -0,0 +1,12 @@
QA output created by 090
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 65536/65536 bytes at offset 65536
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
discard 65536/65536 bytes at offset 65536
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 65536/65536 bytes at offset 65536
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
No errors were found on the image.
*** done

View File

@@ -178,10 +178,10 @@ _rm_test_img()
local img=$1
if [ "$IMGFMT" = "vmdk" ]; then
# Remove all the extents for vmdk
$QEMU_IMG info $img 2>/dev/null | grep 'filename:' | cut -f 2 -d: \
"$QEMU_IMG" info "$img" 2>/dev/null | grep 'filename:' | cut -f 2 -d: \
| xargs -I {} rm -f "{}"
fi
rm -f $img
rm -f "$img"
}
_cleanup_test_img()

View File

@@ -95,3 +95,4 @@
086 rw auto quick
087 rw auto
088 rw auto
090 rw auto quick

View File

@@ -359,16 +359,12 @@ static void sdl_mouse_mode_change(Notifier *notify, void *data)
}
static void sdl_send_mouse_event(struct sdl2_state *scon, int dx, int dy,
int dz, int x, int y, int state)
int x, int y, int state)
{
static uint32_t bmap[INPUT_BUTTON_MAX] = {
[INPUT_BUTTON_LEFT] = SDL_BUTTON(SDL_BUTTON_LEFT),
[INPUT_BUTTON_MIDDLE] = SDL_BUTTON(SDL_BUTTON_MIDDLE),
[INPUT_BUTTON_RIGHT] = SDL_BUTTON(SDL_BUTTON_RIGHT),
#if 0
[INPUT_BUTTON_WHEEL_UP] = SDL_BUTTON(SDL_BUTTON_WHEELUP),
[INPUT_BUTTON_WHEEL_DOWN] = SDL_BUTTON(SDL_BUTTON_WHEELDOWN),
#endif
};
static uint32_t prev_state;
@@ -566,7 +562,7 @@ static void handle_mousemotion(SDL_Event *ev)
}
}
if (gui_grab || qemu_input_is_absolute() || absolute_enabled) {
sdl_send_mouse_event(scon, ev->motion.xrel, ev->motion.yrel, 0,
sdl_send_mouse_event(scon, ev->motion.xrel, ev->motion.yrel,
ev->motion.x, ev->motion.y, ev->motion.state);
}
}
@@ -576,7 +572,6 @@ static void handle_mousebutton(SDL_Event *ev)
int buttonstate = SDL_GetMouseState(NULL, NULL);
SDL_MouseButtonEvent *bev;
struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
int dz;
bev = &ev->button;
if (!gui_grab && !qemu_input_is_absolute()) {
@@ -585,23 +580,33 @@ static void handle_mousebutton(SDL_Event *ev)
sdl_grab_start(scon);
}
} else {
dz = 0;
if (ev->type == SDL_MOUSEBUTTONDOWN) {
buttonstate |= SDL_BUTTON(bev->button);
} else {
buttonstate &= ~SDL_BUTTON(bev->button);
}
#ifdef SDL_BUTTON_WHEELUP
if (bev->button == SDL_BUTTON_WHEELUP &&
ev->type == SDL_MOUSEBUTTONDOWN) {
dz = -1;
} else if (bev->button == SDL_BUTTON_WHEELDOWN &&
ev->type == SDL_MOUSEBUTTONDOWN) {
dz = 1;
sdl_send_mouse_event(scon, 0, 0, bev->x, bev->y, buttonstate);
}
#endif
sdl_send_mouse_event(scon, 0, 0, dz, bev->x, bev->y, buttonstate);
}
static void handle_mousewheel(SDL_Event *ev)
{
struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
SDL_MouseWheelEvent *wev = &ev->wheel;
InputButton btn;
if (wev->y > 0) {
btn = INPUT_BUTTON_WHEEL_UP;
} else if (wev->y < 0) {
btn = INPUT_BUTTON_WHEEL_DOWN;
} else {
return;
}
qemu_input_queue_btn(scon->dcl.con, btn, true);
qemu_input_event_sync();
qemu_input_queue_btn(scon->dcl.con, btn, false);
qemu_input_event_sync();
}
static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev)
@@ -612,6 +617,13 @@ static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev)
switch (ev->window.event) {
case SDL_WINDOWEVENT_RESIZED:
sdl_scale(scon, ev->window.data1, ev->window.data2);
{
QemuUIInfo info;
memset(&info, 0, sizeof(info));
info.width = ev->window.data1;
info.height = ev->window.data2;
dpy_set_ui_info(scon->dcl.con, &info);
}
graphic_hw_invalidate(scon->dcl.con);
graphic_hw_update(scon->dcl.con);
break;
@@ -678,6 +690,9 @@ static void sdl_refresh(DisplayChangeListener *dcl)
case SDL_MOUSEBUTTONUP:
handle_mousebutton(ev);
break;
case SDL_MOUSEWHEEL:
handle_mousewheel(ev);
break;
case SDL_WINDOWEVENT:
handle_windowevent(dcl, ev);
break;