Compare commits

..

76 Commits

Author SHA1 Message Date
Hervé Poussineau
f205da688b raven: Use raven_ for all function prefixes
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
Signed-off-by: Andreas Färber <andreas.faerber@web.de>
2014-03-20 00:34:21 +01:00
Hervé Poussineau
2403837e67 raven: Fix PCI bus accesses with size > 1
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
Reviewed-by: Artyom Tarasenko <atar4qemu@gmail.com>
Signed-off-by: Andreas Färber <andreas.faerber@web.de>
2014-03-20 00:34:16 +01:00
Hervé Poussineau
d16644ec4c raven: Add PCI bus mastering address space
This has been tested on Linux 2.4/PPC with the lsi53c895a SCSI adapter.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
Signed-off-by: Andreas Färber <andreas.faerber@web.de>
2014-03-20 00:33:17 +01:00
Hervé Poussineau
1fe9e2626f raven: Set a correct PCI memory region
PCI memory region is 0x3f000000 bytes starting at 0xc0000000.

However, keep compatibility with Open Hack'Ware expectations
by adding a hack for Open Hack'Ware display.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
Signed-off-by: Andreas Färber <andreas.faerber@web.de>
2014-03-20 00:33:17 +01:00
Hervé Poussineau
1ae1dc5ba2 raven: Set a correct PCI I/O memory region
PCI I/O region is 0x3f800000 bytes starting at 0x80000000.
Do not use global QEMU I/O region, which is only 64KB.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
Signed-off-by: Andreas Färber <andreas.faerber@web.de>
2014-03-20 00:33:17 +01:00
Hervé Poussineau
9a1839164c raven: Implement non-contiguous I/O region
Remove now duplicated code from prep board.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
Signed-off-by: Andreas Färber <andreas.faerber@web.de>
2014-03-20 00:33:16 +01:00
Hervé Poussineau
49a4e21251 raven: Rename intack region to pci_intack
Regions added subsequently will also have the pci_ prefix.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
Signed-off-by: Andreas Färber <andreas.faerber@web.de>
2014-03-20 00:33:16 +01:00
Peter Maydell
d1a1451cd3 Merge remote-tracking branch 'remotes/afaerber/tags/qom-cpu-for-2.0' into staging
QOM CPUState refactorings / X86CPU

* CPUState layout optimization for TCG

# gpg: Signature made Wed 19 Mar 2014 21:51:46 GMT using RSA key ID 3E7E013F
# gpg: Good signature from "Andreas Färber <afaerber@suse.de>"
# gpg:                 aka "Andreas Färber <afaerber@suse.com>"

* remotes/afaerber/tags/qom-cpu-for-2.0:
  cpu: Move tcg_exit_req to the end of CPUState

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-19 22:36:44 +00:00
Peter Maydell
037b7addb7 Merge remote-tracking branch 'remotes/afaerber/tags/qom-devices-for-2.0' into staging
QOM/QTest infrastructure fixes

* QOM machine memory and build fixes
* QOM link<> and child<> property reference counting fixes

# gpg: Signature made Wed 19 Mar 2014 21:44:04 GMT using RSA key ID 3E7E013F
# gpg: Good signature from "Andreas Färber <afaerber@suse.de>"
# gpg:                 aka "Andreas Färber <afaerber@suse.com>"

* remotes/afaerber/tags/qom-devices-for-2.0:
  virtio-rng: Avoid default_backend refcount leak
  qom: Add check() argument to object_property_add_link()
  qom: Make QOM link property unref optional
  qom: Don't make link NULL on object_property_set_link() failure
  qom: Split object_property_set_link()
  vl.c: Fix OpenBSD compilation issue due to namespace collisions
  vl.c: Fix memory leak in qemu_register_machine()

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-19 21:45:42 +00:00
Stefan Hajnoczi
abdffd1fb7 virtio-rng: Avoid default_backend refcount leak
QOM child properties take a reference to the object and release it when
the property is deleted.  Therefore we should unref the default_backend
after we have added it as a child property.

Cc: KONRAD Frederic <fred.konrad@greensocs.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 22:23:47 +01:00
Stefan Hajnoczi
39f72ef94b qom: Add check() argument to object_property_add_link()
There are currently three types of object_property_add_link() callers:

1. The link property may be set at any time.
2. The link property of a DeviceState instance may only be set before
   realize.
3. The link property may never be set, it is read-only.

Something similar can already be achieved with
object_property_add_str()'s set() argument.  Follow its example and add
a check() argument to object_property_add_link().

Also provide default check() functions for case #1 and #2.  Case #3 is
covered by passing a NULL function pointer.

Cc: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Anthony Liguori <aliguori@amazon.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
[AF: Tweaked documentation comment]
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 22:23:13 +01:00
Richard Henderson
7e4fb26d75 cpu: Move tcg_exit_req to the end of CPUState
Reverse an increase in the size of generated code.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 22:11:19 +01:00
Stefan Hajnoczi
9561fda8d9 qom: Make QOM link property unref optional
Some object_property_add_link() callers expect property deletion to
unref the link property object.  Other callers expect to manage the
refcount themselves.  The former are currently broken and therefore leak
the link property object.

This patch adds a flags argument to object_property_add_link() so the
caller can specify which refcount behavior they require.  The new
OBJ_PROP_LINK_UNREF_ON_RELEASE flag causes the link pointer to be
unreferenced when the property is deleted.

This fixes refcount leaks in qdev.c, xilinx_axidma.c, xilinx_axienet.c,
s390-virtio-bus.c, virtio-pci.c, virtio-rng.c, and ui/console.c.

Rationale for refcount behavior:

 * hw/core/qdev.c
   - bus children are explicitly unreferenced, don't interfere
   - parent_bus is essentially a read-only property that doesn't hold a
     refcount, don't unref
   - hotplug_handler is leaked, do unref

 * hw/dma/xilinx_axidma.c
   - rx stream "dma" links are set using set_link, therefore they
     need unref
   - tx streams are set using set_link, therefore they need unref

 * hw/net/xilinx_axienet.c
   - same reasoning as hw/dma/xilinx_axidma.c

 * hw/pcmcia/pxa2xx.c
   - pxa2xx bypasses set_link and therefore does not use refcounts

 * hw/s390x/s390-virtio-bus.c
 * hw/virtio/virtio-pci.c
 * hw/virtio/virtio-rng.c
 * ui/console.c
   - set_link is used and there is no explicit unref, do unref

Cc: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Anthony Liguori <aliguori@amazon.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 22:05:20 +01:00
Stefan Hajnoczi
c6aed98334 qom: Don't make link NULL on object_property_set_link() failure
The error behavior of object_property_set_link() is dangerous.  It sets
the link property object to NULL if an error occurs.  A setter function
should either succeed or fail, it shouldn't leave the value NULL on
failure.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 22:01:34 +01:00
Stefan Hajnoczi
f5ec6704c7 qom: Split object_property_set_link()
The path resolution logic in object_property_set_link() should be a
separate function.  This makes the code easier to read and maintain.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 22:01:13 +01:00
Marcel Apfelbaum
c8897e8eb9 vl.c: Fix OpenBSD compilation issue due to namespace collisions
Machine rewriting added MACHINE() macro which is
already in use by other OpenBSD library.
Since qemu/sockets.h exposes the OpenBSD namespace,
the minimalistic approach is to add it as the first QEMU include.

Reported-by: Brad Smith <brad@comstyle.com>
Signed-off-by: Marcel Apfelbaum <marcel.a@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 21:00:34 +01:00
Christian Borntraeger
f5946dbab3 vl.c: Fix memory leak in qemu_register_machine()
Since commit 261747f176 (vl: Use MachineClass instead of global
QEMUMachine list) valgrind complains about the following:

==54082== 57 bytes in 3 blocks are definitely lost in loss record 365 of
729
==54082==    at 0x4031AFE: malloc (vg_replace_malloc.c:292)
==54082==    by 0x4145569: g_malloc (in
/usr/lib64/libglib-2.0.so.0.3400.2)
==54082==    by 0x415F9E9: g_strconcat (in
/usr/lib64/libglib-2.0.so.0.3400.2)
==54082==    by 0x80157FE7: qemu_register_machine (vl.c:1597)
==54082==    by 0x80208E6B: module_call_init (module.c:105)
==54082==    by 0x80013B91: main (vl.c:3000)

Turns out that valgrind is right. We simply forget the memory that
g_strconcat() has allocated. Lets free it after the type_register().
We need a 2nd variable due to constness of the name part of the
type structure.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 21:00:01 +01:00
Peter Maydell
f71e769d07 Merge remote-tracking branch 'remotes/afaerber/tags/qom-cpu-for-2.0' into staging
QOM CPUState refactorings / X86CPU

* Fix pointer type mismatch

# gpg: Signature made Wed 19 Mar 2014 18:51:47 GMT using RSA key ID 3E7E013F
# gpg: Good signature from "Andreas Färber <afaerber@suse.de>"
# gpg:                 aka "Andreas Färber <afaerber@suse.com>"

* remotes/afaerber/tags/qom-cpu-for-2.0:
  exec: Fix CPU rework fallout

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-19 19:05:13 +00:00
Christian Borntraeger
c01a71c1a5 exec: Fix CPU rework fallout
Commit 259186a7d2 (cpu: Move halted and
interrupt_request fields to CPUState) passed CPUState::env_ptr to
tlb_flush() directory rather than through a typed variable.

Commit 00c8cb0a36 (cputlb: Change
tlb_flush() argument to CPUState) now changed the argument type.
This was unnoticed by gcc because env_ptr is a void pointer.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 19:47:15 +01:00
Peter Maydell
ec864874bd linux-user: Fix build if headers don't define _LINUX_CAPABILITY_VERSION_1
Older kernel headers don't define _LINUX_CAPABILITY_VERSION_1.
Switch to using the older _LINUX_CAPABILITY_VERSION; newer headers
still define this for source compatibility.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Acked-by: Riku Voipio <riku.voipio@iki.fi>
2014-03-19 18:19:57 +00:00
Peter Maydell
4c8821d134 Merge remote-tracking branch 'remotes/riku/linux-user-for-upstream' into staging
* remotes/riku/linux-user-for-upstream:
  linux-user: Implement capget, capset
  linux-user: Don't allow guest to block SIGSEGV
  signal: added a wrapper for sigprocmask function
  linux-user: Don't reserve space for commpage for AArch64
  linux-user: implement F_[GS]ETOWN_EX
  linux-user: Don't return uninitialized value for atomic_barrier syscall
  linux-user/signal.c: Correct error path for AArch64 do_rt_sigreturn

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-19 14:14:15 +00:00
Peter Maydell
c1b94a0ed2 Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block patches for 2.0.0-rc1

# gpg: Signature made Wed 19 Mar 2014 13:03:27 GMT using RSA key ID C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"

* remotes/kevin/tags/for-upstream:
  dataplane: fix implicit IOThread refcount
  block/nfs: report errors from libnfs
  block/nfs: bump libnfs requirement to 1.9.3
  qcow2: Fix fail path in realloc_refcount_block()
  qcow2: Correct comment for realloc_refcount_block()
  qemu-io: Extended "--cmd" description in usage text
  qemu-io-cmds: Fixed typo in example for writev.
  block: Add error handling to bdrv_invalidate_cache()

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-19 13:47:22 +00:00
Peter Maydell
319c66d5ab Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20140319' into staging
target-arm queue:
 * last few A64 Neon instructions
 * fix some PL011 UART bugs causing occasional serial lockups
 * fix the non-PCI AHCI device

# gpg: Signature made Wed 19 Mar 2014 12:00:59 GMT using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"

* remotes/pmaydell/tags/pull-target-arm-20140319:
  target-arm: A64: Add saturating accumulate ops (USQADD/SUQADD)
  target-arm: A64: Add saturating int ops (SQNEG/SQABS)
  pl011: fix incorrect logic to set the RXFF flag
  pl011: fix UARTRSR accesses corrupting the UARTCR value
  pl011: reset the fifo when enabled or disabled
  ahci: fix sysbus support

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-19 13:00:41 +00:00
Stefan Hajnoczi
198fd05c35 dataplane: fix implicit IOThread refcount
When creating an IOThread implicitly (the user did not specify
x-iothread=<id>) remember that iothread_find() does not return the
object with an incremented refcount.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-19 09:45:25 +01:00
Peter Lieven
20fccb187c block/nfs: report errors from libnfs
if an NFS operation fails we should report what libnfs knows
about the failure. It is likely more than just an error code.

Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-19 09:39:41 +01:00
Peter Lieven
b7d769c932 block/nfs: bump libnfs requirement to 1.9.3
libnfs prior to 1.9.3 contains a bug that will report
wrong transfer sizes if the file offset grows beyond 4GB
and RPC responses are received out of order. this
error is not detectable and fixable in qemu.

additionally 1.9.3 introduces support for handling short
read/writes in general and takes care of the necessary
retransmissions internally.

Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-19 09:39:41 +01:00
Max Reitz
a134d90f50 qcow2: Fix fail path in realloc_refcount_block()
If qcow2_alloc_clusters() fails, new_offset and ret will both be
negative after the fail label, thus passing the first if condition and
subsequently resulting in a call of qcow2_free_clusters() with an
invalid (negative) offset parameter. Fix this by introducing a new label
"fail_free_cluster" which is only invoked if new_offset is indeed
pointing to a newly allocated cluster that should be cleaned up by
freeing it.

While we're at it, clean up the whole fail path. qcow2_cache_put()
should (and actually can) never fail, hence the return value can safely
be ignored (aside from asserting that it indeed did not fail).

Furthermore, there is no reason to give QCOW2_DISCARD_ALWAYS to
qcow2_free_clusters(), a mere QCOW2_DISCARD_OTHER will suffice.

Ultimately, rename the "fail" label to "done", as it is invoked both on
failure and success.

Suggested-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-19 09:39:41 +01:00
Max Reitz
8a15b813e6 qcow2: Correct comment for realloc_refcount_block()
Contrary to the comment describing this function's behavior, it does not
return 0 on success, but rather the offset of the newly allocated
cluster. This patch adjusts the comment accordingly to reflect the
actual behavior.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-19 09:39:41 +01:00
Maria Kustova
d208cc353a qemu-io: Extended "--cmd" description in usage text
It's not clear from the usage description that "--cmd" option accepts
its argument as a string, so any special symbols have to be quoted from
the shell.

Updates in usage text:
 - Specified parameter format for "--cmd" option.
 - Added an instruction how to get help for "--cmd" option.

Signed-off-by: Maria Kustova <maria.k@catit.be>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-19 09:39:41 +01:00
Maria Kustova
6e6507c06b qemu-io-cmds: Fixed typo in example for writev.
Signed-off-by: Maria Kustova <maria.k@catit.be>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-03-19 09:39:41 +01:00
Kevin Wolf
5a8a30db47 block: Add error handling to bdrv_invalidate_cache()
If it returns an error, the migrated VM will not be started, but qemu
exits with an error message.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
2014-03-19 09:39:41 +01:00
Alex Bennée
09e037354b target-arm: A64: Add saturating accumulate ops (USQADD/SUQADD)
Add the saturating accumulate operations USQADD and SUQADD
to the A64 instruction set. This completes coverage of A64 Neon.
These operations (which are unsigned + signed -> signed and
signed + unsigned -> unsigned) don't exist in the A32/T32
instruction set, so require a complete new set of helper functions.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
2014-03-18 23:10:06 +00:00
Alex Bennée
0a79bc87c3 target-arm: A64: Add saturating int ops (SQNEG/SQABS)
This mostly re-uses the existing NEON helpers with an additional two for
the 64 bit case. I also took the opportunity to add TCG_CALL_NO_RWG
options to the helpers as they don't modify globals (saturation flags
are in the CPU Environment).

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
2014-03-18 23:10:06 +00:00
Rob Herring
f72dbf3d26 pl011: fix incorrect logic to set the RXFF flag
The receive fifo full bit should be set when 1 character is received and
the fifo is disabled or when 16 characters are in the fifo.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1395166721-15716-4-git-send-email-robherring2@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-18 19:38:56 +00:00
Rob Herring
ce8f0905a5 pl011: fix UARTRSR accesses corrupting the UARTCR value
Offset 4 is UARTRSR/UARTECR, not the UARTCR. The UARTCR would be
corrupted if the UARTRSR is ever written. Fix by implementing a correct
model of the UARTRSR/UARTECR register. Reads of this register simply
reflect the error bits in data register. Only breaks can be triggered in
QEMU. With the pl011_can_receive function, we effectively have flow
control between the host and the model. Framing and parity errors simply
don't make sense in the model and will never occur.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1395166721-15716-3-git-send-email-robherring2@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-18 19:38:55 +00:00
Rob Herring
22709e90a2 pl011: reset the fifo when enabled or disabled
Intermittent issues have been seen where no serial input occurs. It
appears the pl011 gets in a state where the rx interrupt never fires
because the rx interrupt only asserts when crossing the fifo trigger
level. The fifo state appears to get out of sync when the pl011 is
re-configured. This combined with the rx timeout interrupt not being
modeled results in no more rx interrupts.

Disabling the fifo is the recommended way to clear the tx fifo in the
TRM (section 3.3.8). The behavior in this case for the rx fifo is
undefined in the TRM, but having fifo contents to be maintained during
configuration changes is not likely expected behavior. Reseting the
fifo state when the fifo size is changed is the simplest solution.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1395166721-15716-2-git-send-email-robherring2@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-18 19:36:49 +00:00
Rob Herring
bd16430777 ahci: fix sysbus support
Non-PCI AHCI support is broken due to assertion failures when trying
to convert AHCIState to a PCIDevice pointer as AHCIState can have
different container structs. Fix this by using the non-asserting object
cast and checking the returned pointer is not NULL.

The AddressSpace pointer is also being initialized to NULL and causing
dma_memory_map call to fail. Fix this by initializing to
address_space_memory for sysbus instances.

Also correct AHCI_VMSTATE to use the correct container SysbusAHCIState
for sysbus instances.

Signed-off-by: Rob Herring <rob.herring@linaro.org>
Message-id: 1392073373-3295-1-git-send-email-robherring2@gmail.com
[PMM: added linebreaks to fix overlong lines]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-18 19:36:13 +00:00
Peter Maydell
059b3527f0 Merge remote-tracking branch 'remotes/kraxel/tags/pull-vnc-2' into staging
vnc: fix vmware VGA incompatiblities

# gpg: Signature made Tue 18 Mar 2014 07:23:10 GMT 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-vnc-2:
  ui/vnc: fix vmware VGA incompatiblities

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-18 16:39:29 +00:00
Peter Maydell
2dda43bacc Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20140317' into staging
target-arm queue:
 * more A64 Neon instructions
 * fixes to reset CBAR values for A9 and A15 boards
 * fix accesses to PMCR register in -icount mode

# gpg: Signature made Mon 17 Mar 2014 22:04:52 GMT using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"

* remotes/pmaydell/tags/pull-target-arm-20140317: (30 commits)
  scripts/qemu-binfmt-conf.sh: Add AArch64 registration
  target-arm: A64: Add [UF]RSQRTE (reciprocal root estimate)
  target-arm: A64: Implement FCVTXN
  target-arm: A64: Implement scalar saturating narrow ops
  target-arm: A64: Move handle_2misc_narrow function
  target-arm: A64: Implement AdvSIMD reciprocal estimate insns URECPE, FRECPE
  softfloat: export squash_input_denormal functions
  target-arm: A64: Implement FCVTZS, FCVTZU in the shift-imm categories
  target-arm: A64: Handle saturating left shifts SQSHL, SQSHLU, UQSHL
  exec-all.h: Increase MAX_OP_PER_INSTR for ARM A64 decoder
  target-arm: A64: Implement FRINT*
  target-arm: A64: Implement SRI
  target-arm: A64: Add FRECPX (reciprocal exponent)
  target-arm: A64: List unsupported shift-imm opcodes
  target-arm: A64: Implement FCVTL
  target-arm: A64: Implement FCVTN
  target-arm: A64: Implement FCVT[NMAPZ][SU] SIMD instructions
  target-arm: A64: Implement SHLL, SHLL2
  target-arm: A64: Implement SADDLP, UADDLP, SADALP, UADALP
  target-arm: A64: Saturating and narrowing shift ops
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-18 14:31:42 +00:00
Peter Maydell
1ed27a17cd scripts/qemu-binfmt-conf.sh: Add AArch64 registration
Add the binfmt-misc magic needed to register QEMU for handling AArch64
ELF binaries.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-26-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:53 +00:00
Alex Bennée
c2fb418e35 target-arm: A64: Add [UF]RSQRTE (reciprocal root estimate)
This adds support for [UF]RSQRTE instructions. It utilises the existing
NEON helpers with some changes. The changes include an explicit passing
of fpstatus (so the correct one is used between arm32 and aarch64),
denormilzation, more correct error handling and also proper scaling of
the fraction going into the estimate.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-25-git-send-email-peter.maydell@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-17 16:31:53 +00:00
Peter Maydell
5553955eb6 target-arm: A64: Implement FCVTXN
Implement the FCVTXN operation, which does a narrowing fp precision
conversion using the "round to odd" (von Neumann) mode. This can
conveniently be implemented as "do operation using round to zero;
then set the LSB of the mantissa to 1 if the Inexact flag was set".

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-24-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:53 +00:00
Alex Bennée
5201c13654 target-arm: A64: Implement scalar saturating narrow ops
This completes the set of integer narrowing saturating ops including:
     SQXTN, SQXTN2
     SQXTUN, SQXTUN2
     UQXTN, UQXTN2

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-23-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:52 +00:00
Alex Bennée
8b092ca9ef target-arm: A64: Move handle_2misc_narrow function
Move the handle_2misc_narrow() function up the file so that it can
be called from disas_simd_scalar_two_reg_misc().

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-22-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:52 +00:00
Alex Bennée
b6d4443a7b target-arm: A64: Implement AdvSIMD reciprocal estimate insns URECPE, FRECPE
Implement URECPE and FRECPE instructions in both scalar and vector forms.
The actual reciprocal estimate function is shared with the A32/T32 Neon
code. However in A64 we aren't using the Neon "standard FPSCR value"
so extra checks are necessary to handle non-squashed denormal inputs
which can never happen for A32/T32. Calling conventions for the helpers
are thus modified to pass the fpst directly; we mark the helpers as
TCG_CALL_NO_RWG since we're changing the declarations anyway.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-21-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:52 +00:00
Alex Bennée
7baeabce1d softfloat: export squash_input_denormal functions
I need these available outside of softfloat for some of the reciprocal
processing in aarch64 helper functions.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-20-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:51 +00:00
Peter Maydell
2ed3ea110f target-arm: A64: Implement FCVTZS, FCVTZU in the shift-imm categories
Implement FCVTZS and FCVTZU in the shift-imm and scalar-shift-imm
categories; this completes the implementation of those two groups.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-19-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:51 +00:00
Peter Maydell
a847f32c04 target-arm: A64: Handle saturating left shifts SQSHL, SQSHLU, UQSHL
Implement the saturating left shift instructions SQSHL, SQSHLU
and UQSHL for the scalar-shift-imm and shift-imm categories.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-18-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:51 +00:00
Peter Maydell
14dcdac82f exec-all.h: Increase MAX_OP_PER_INSTR for ARM A64 decoder
The ARM A64 decoder's worst case number of TCG ops per instruction
is 266 (for insn 0x4c800000, a post-indexed ST4 multiple-structures
store). Raise the MAX_OP_PER_INSTR define accordingly.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-17-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:51 +00:00
Peter Maydell
03df01ed9a target-arm: A64: Implement FRINT*
Implement the FRINT* round-to-integral operations from
the 2-reg-misc category.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-16-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:50 +00:00
Peter Maydell
37a706adbf target-arm: A64: Implement SRI
Implement SRI (shift right and insert).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-15-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:50 +00:00
Alex Bennée
8f0c6758b0 target-arm: A64: Add FRECPX (reciprocal exponent)
These are fairly simple exponent only estimation functions using helpers.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-14-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:50 +00:00
Peter Maydell
a566da1b02 target-arm: A64: List unsupported shift-imm opcodes
Add the remaining unsupported opcodes to the decode switches
for the shift-imm and scalar shift-imm categories so we can
see what is still to be implemented.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-13-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:50 +00:00
Peter Maydell
931c8cc270 target-arm: A64: Implement FCVTL
Implement FCVTL, the only instruction in the 2-reg-misc group
which widens from size to 2*size elements.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-12-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:49 +00:00
Peter Maydell
261a5b4dd1 target-arm: A64: Implement FCVTN
Implement FCVTN (narrowing fp-to-fp conversions) from the SIMD
2-reg-misc category.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-11-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:49 +00:00
Peter Maydell
04c7c6c261 target-arm: A64: Implement FCVT[NMAPZ][SU] SIMD instructions
Implement the floating-point-to-integer conversion instructions
FCVT[NMAPZ][SU] in the 2-reg-misc and scalar-2-reg-misc
categories.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-10-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:49 +00:00
Peter Maydell
73a81d10fd target-arm: A64: Implement SHLL, SHLL2
Implement the SHLL and SHLL2 instructions from the 2-reg-misc
category.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-9-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:49 +00:00
Peter Maydell
6781fa119f target-arm: A64: Implement SADDLP, UADDLP, SADALP, UADALP
Implement the SADDLP, UADDLP, SADALP and UADALP instructions
in the SIMD 2-reg misc category.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-8-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:48 +00:00
Alex Bennée
c1b876b2e9 target-arm: A64: Saturating and narrowing shift ops
This implements the remaining [US][Q][R]SHR[U][N][2] opcodes, which are
saturating and narrowing shift right operations. These are used in
things like libav. Note signed shifts can have an "unsigned" saturating
narrow operation which will floor negative values.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1394822294-14837-7-git-send-email-peter.maydell@linaro.org
[PMM: Added the scalar encodings, style tweaks]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-17 16:31:48 +00:00
Alex Bennée
b05c306857 target-arm: A64: Add remaining CLS/Z vector ops
Implement the CLS, CLZ operations in the 2-reg-misc category.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-6-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:48 +00:00
Alex Bennée
f612537e07 target-arm: A64: Add FSQRT to C3.6.17 (two misc)
Implement FSQRT in the two-reg-misc category.
GCC uses this instruction form.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-5-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:47 +00:00
Alex Bennée
10113b6903 target-arm: A64: Add last AdvSIMD Integer to FP ops
This adds the remaining [US]CVTF operations to the SIMD
shift-immediate, scalar-shift-immediate, two-reg-misc and
scalar-two-reg-misc groups of opcodes.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1394822294-14837-4-git-send-email-peter.maydell@linaro.org
[PMM: added scalar 2-misc and scalar-shift-imm encodings]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-03-17 16:31:47 +00:00
Alex Bennée
cf4ab1af29 target-arm: A64: Fix bug in add_sub_ext handling of rn
rn == 31 always means SP (not XZR) whether an add_sub_ext
instruction is setting the flags or not; only rd has behaviour
dependent on whether we are setting flags.

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-3-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:47 +00:00
Peter Maydell
a984e42c91 target-arm: A64: Implement PMULL instruction
Implement the PMULL instruction; this is the last unimplemented insn
in the three-reg-diff group.

Note that PMULL with size 3 is considered part of the AES part
of the crypto extensions (see the ID_AA64ISAR0_EL1 register definition
in the v8 ARM ARM), so it isn't necessary to burn an extra feature
bit on it, even though we're using more feature bits than a single
"crypto extension present/not present" toggle.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-id: 1394822294-14837-2-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:47 +00:00
Peter Maydell
d6d60581f3 target-arm: Add ARM_CP_IO notation to PMCR reginfo
Now that the PMCR writefn makes timer accesses, its reginfo needs
the ARM_CP_IO flag, so that icount mode works correctly. (Fixes
the bug accidentally introduced in commit 7c2cb42b).

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1394908291-16546-1-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:46 +00:00
Peter Maydell
ba7500852d virt: Set reset-cbar on CPUs
Set the reset-cbar property on CPUs used by the virt board,
if they have it. This isn't necessary for correct functioning
under Linux (since the A9 isn't a valid CPU for the virt board),
but it is the correct behaviour.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 1394462692-8871-5-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:46 +00:00
Peter Maydell
4719ab918a exynos4210: Set reset-cbar property of Cortex-A9 CPUs
Set the reset-cbar property of the Exynos4210 SoC's Cortex-A9
CPUs, so that Linux doesn't misrecognize them as a broken
uniprocessor SoC.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 1394462692-8871-4-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:46 +00:00
Peter Maydell
b5a3ca3e30 realview-pbx-a9: Set reset-cbar property for CPUs
If the CPU is a Cortex-A9 then we should set its reset-cbar property
so that the guest can read the correct PERIPHBASE/CBAR register value;
newer versions of the Linux kernel (as of commit bc41b8724 in 3.12)
will otherwise assume the CPU is a buggy single core A9 SoC. The
realview-pbx-a9 is the only one of the cluster of boards in realview.c
which works with the Cortex-A9 (ie which gets an a9mpcore_priv device);
make sure it also has reset-cbar set correctly.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 1394462692-8871-3-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:45 +00:00
Peter Maydell
9948c38bd9 vexpress: Set reset-cbar property for CPUs
Newer versions of the Linux kernel (as of commit bc41b8724 in 3.12)
now assume that if the CPU is a Cortex-A9 and the reset value of the
PERIPHBASE/CBAR register is zero then the CPU is a specific buggy
single core A9 SoC, and will not try to start other cores. Since we
now have a CPU property for the reset value of the CBAR, we can
just fix the vexpress board model to correctly set CBAR so SMP
works again. To avoid duplicate boilerplate code in both the A9
and A15 daughterboard init functions, we split out the CPU and
private memory region init to its own function.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reported-by: Rob Herring <rob.herring@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 1394462692-8871-2-git-send-email-peter.maydell@linaro.org
2014-03-17 16:31:45 +00:00
Peter Maydell
e0eb210ec0 linux-user: Implement capget, capset
Implement the capget and capset syscalls. This is useful because
simple programs like 'ls' try to use it in AArch64, and otherwise
we emit a lot of noise about it being unimplemented.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
2014-03-17 15:26:58 +02:00
Peter Maydell
a7ec0f98e3 linux-user: Don't allow guest to block SIGSEGV
Don't allow the linux-user guest to block SIGSEGV -- QEMU needs this
signal to detect accesses to pages which it has marked read-only
because it has cached translated code from them.

We implement this by making the do_sigprocmask() wrapper suppress
SIGSEGV when doing the host process signal mask manipulation; instead
we store the current state of SIGSEGV in the TaskState struct.

If we get a SIGSEGV for the guest when the guest has blocked the
signal, we treat it as if the default SEGV handler was in place,
as the kernel does for forced SIGSEGV delivery.

This patch is based on an idea by Alex Barcelo, but rather than
simply lying to the guest about the SIGSEGV state we track it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reported-by: Alex Barcelo <abarcelo@ac.upc.edu>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
2014-03-17 11:44:32 +02:00
Alex Barcelo
1c275925bf signal: added a wrapper for sigprocmask function
Create a wrapper for signal mask changes initiated by the guest;
(this includes syscalls and also the sigreturns from signal.c)
this will give us a place to put code which prevents the guest
from changing the handling of signals used by QEMU itself
internally.

The wrapper is called from all the guest-initiated sigprocmask, but
is not called from internal qemu sigprocmask calls.

Signed-off-by: Alex Barcelo <abarcelo@ac.upc.edu>
[PMM: Added calls to wrapper for sigprocmask uses in signal.c
when setting the signal mask on entry and exit from signal
handlers, since these also are guest-provided signal masks.]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
2014-03-17 11:44:32 +02:00
Peter Maydell
6b1275ff15 linux-user: Don't reserve space for commpage for AArch64
AArch64 Linux, unlike AArch32, doesn't use a commpage. This means we
should not be reserving room in the guest address space for one.
Fixes LP:1287195.

Reported-by: Amanieu d'Antras <amanieu@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
2014-03-17 11:44:31 +02:00
8d5d30046b linux-user: implement F_[GS]ETOWN_EX
F_GETOWN is replaced by F_GETOWN_EX inside the glibc fcntl wrapper

Signed-off-by: Andreas Schwab <schwab@suse.de>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
2014-03-17 11:44:31 +02:00
Peter Maydell
3b899ea7d4 linux-user: Don't return uninitialized value for atomic_barrier syscall
QEMU's implementation of the m68k atomic_barrier syscall, like the kernel's,
is just a no-op. However we still need to return a result code from it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
2014-03-17 11:44:31 +02:00
Peter Maydell
7f72cd235f linux-user/signal.c: Correct error path for AArch64 do_rt_sigreturn
The error path in AArch64 do_rt_sigreturn() which fails before
attempting lock_user_struct() was doing an unlock_user_struct()
on an uninitialized variable. Initialize frame to NULL so we
can use the same error-exit path in all cases (unlock of NULL
is permitted and does nothing).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
2014-03-17 11:44:31 +02:00
55 changed files with 2973 additions and 558 deletions

28
block.c
View File

@@ -4781,27 +4781,43 @@ flush_parent:
return bdrv_co_flush(bs->file);
}
void bdrv_invalidate_cache(BlockDriverState *bs)
void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
{
Error *local_err = NULL;
int ret;
if (!bs->drv) {
return;
}
if (bs->drv->bdrv_invalidate_cache) {
bs->drv->bdrv_invalidate_cache(bs);
bs->drv->bdrv_invalidate_cache(bs, &local_err);
} else if (bs->file) {
bdrv_invalidate_cache(bs->file);
bdrv_invalidate_cache(bs->file, &local_err);
}
if (local_err) {
error_propagate(errp, local_err);
return;
}
refresh_total_sectors(bs, bs->total_sectors);
ret = refresh_total_sectors(bs, bs->total_sectors);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not refresh total sector count");
return;
}
}
void bdrv_invalidate_cache_all(void)
void bdrv_invalidate_cache_all(Error **errp)
{
BlockDriverState *bs;
Error *local_err = NULL;
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
bdrv_invalidate_cache(bs);
bdrv_invalidate_cache(bs, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
}
}

View File

@@ -112,6 +112,9 @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data,
if (task->ret == 0 && task->st) {
memcpy(task->st, data, sizeof(struct stat));
}
if (task->ret < 0) {
error_report("NFS Error: %s", nfs_get_error(nfs));
}
if (task->co) {
task->bh = qemu_bh_new(nfs_co_generic_bh_cb, task);
qemu_bh_schedule(task->bh);

View File

@@ -1383,7 +1383,7 @@ static int write_reftable_entry(BlockDriverState *bs, int rt_index)
* does _not_ decrement the reference count for the currently occupied cluster.
*
* This function prints an informative message to stderr on error (and returns
* -errno); on success, 0 is returned.
* -errno); on success, the offset of the newly allocated cluster is returned.
*/
static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index,
uint64_t offset)
@@ -1399,14 +1399,14 @@ static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index,
fprintf(stderr, "Could not allocate new cluster: %s\n",
strerror(-new_offset));
ret = new_offset;
goto fail;
goto done;
}
/* fetch current refcount block content */
ret = qcow2_cache_get(bs, s->refcount_block_cache, offset, &refcount_block);
if (ret < 0) {
fprintf(stderr, "Could not fetch refcount block: %s\n", strerror(-ret));
goto fail;
goto fail_free_cluster;
}
/* new block has not yet been entered into refcount table, therefore it is
@@ -1417,8 +1417,7 @@ static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index,
"check failed: %s\n", strerror(-ret));
/* the image will be marked corrupt, so don't even attempt on freeing
* the cluster */
new_offset = 0;
goto fail;
goto done;
}
/* write to new block */
@@ -1426,7 +1425,7 @@ static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index,
s->cluster_sectors);
if (ret < 0) {
fprintf(stderr, "Could not write refcount block: %s\n", strerror(-ret));
goto fail;
goto fail_free_cluster;
}
/* update refcount table */
@@ -1436,24 +1435,27 @@ static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index,
if (ret < 0) {
fprintf(stderr, "Could not update refcount table: %s\n",
strerror(-ret));
goto fail;
goto fail_free_cluster;
}
fail:
if (new_offset && (ret < 0)) {
qcow2_free_clusters(bs, new_offset, s->cluster_size,
QCOW2_DISCARD_ALWAYS);
}
goto done;
fail_free_cluster:
qcow2_free_clusters(bs, new_offset, s->cluster_size, QCOW2_DISCARD_OTHER);
done:
if (refcount_block) {
if (ret < 0) {
qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block);
} else {
ret = qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block);
}
/* This should never fail, as it would only do so if the given refcount
* block cannot be found in the cache. As this is impossible as long as
* there are no bugs, assert the success. */
int tmp = qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block);
assert(tmp == 0);
}
if (ret < 0) {
return ret;
}
return new_offset;
}

View File

@@ -1156,7 +1156,7 @@ static void qcow2_close(BlockDriverState *bs)
qcow2_free_snapshots(bs);
}
static void qcow2_invalidate_cache(BlockDriverState *bs)
static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
{
BDRVQcowState *s = bs->opaque;
int flags = s->flags;
@@ -1164,6 +1164,8 @@ static void qcow2_invalidate_cache(BlockDriverState *bs)
AES_KEY aes_decrypt_key;
uint32_t crypt_method = 0;
QDict *options;
Error *local_err = NULL;
int ret;
/*
* Backing files are read-only which makes all of their metadata immutable,
@@ -1178,11 +1180,25 @@ static void qcow2_invalidate_cache(BlockDriverState *bs)
qcow2_close(bs);
bdrv_invalidate_cache(bs->file);
bdrv_invalidate_cache(bs->file, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
memset(s, 0, sizeof(BDRVQcowState));
options = qdict_clone_shallow(bs->options);
qcow2_open(bs, options, flags, NULL);
ret = qcow2_open(bs, options, flags, &local_err);
if (local_err) {
error_setg(errp, "Could not reopen qcow2 layer: %s",
error_get_pretty(local_err));
error_free(local_err);
return;
} else if (ret < 0) {
error_setg_errno(errp, -ret, "Could not reopen qcow2 layer");
return;
}
QDECREF(options);

View File

@@ -1558,16 +1558,31 @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs,
return ret;
}
static void bdrv_qed_invalidate_cache(BlockDriverState *bs)
static void bdrv_qed_invalidate_cache(BlockDriverState *bs, Error **errp)
{
BDRVQEDState *s = bs->opaque;
Error *local_err = NULL;
int ret;
bdrv_qed_close(bs);
bdrv_invalidate_cache(bs->file);
bdrv_invalidate_cache(bs->file, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
memset(s, 0, sizeof(BDRVQEDState));
bdrv_qed_open(bs, NULL, bs->open_flags, NULL);
ret = bdrv_qed_open(bs, NULL, bs->open_flags, &local_err);
if (local_err) {
error_setg(errp, "Could not reopen qed layer: %s",
error_get_pretty(local_err));
error_free(local_err);
return;
} else if (ret < 0) {
error_setg_errno(errp, -ret, "Could not reopen qed layer");
return;
}
}
static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result,

View File

@@ -625,13 +625,18 @@ static int64_t quorum_getlength(BlockDriverState *bs)
return result;
}
static void quorum_invalidate_cache(BlockDriverState *bs)
static void quorum_invalidate_cache(BlockDriverState *bs, Error **errp)
{
BDRVQuorumState *s = bs->opaque;
Error *local_err = NULL;
int i;
for (i = 0; i < s->num_children; i++) {
bdrv_invalidate_cache(s->bs[i]);
bdrv_invalidate_cache(s->bs[i], &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
}
}

2
configure vendored
View File

@@ -3868,7 +3868,7 @@ fi
##########################################
# Do we have libnfs
if test "$libnfs" != "no" ; then
if $pkg_config --atleast-version=1.9.2 libnfs; then
if $pkg_config --atleast-version=1.9.3 libnfs; then
libnfs="yes"
libnfs_libs=$($pkg_config --libs libnfs)
LIBS="$LIBS $libnfs_libs"

2
exec.c
View File

@@ -420,7 +420,7 @@ static int cpu_common_post_load(void *opaque, int version_id)
/* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
version_id is increased. */
cpu->interrupt_request &= ~0x01;
tlb_flush(cpu->env_ptr, 1);
tlb_flush(cpu, 1);
return 0;
}

View File

@@ -288,7 +288,7 @@ INLINE flag extractFloat32Sign( float32 a )
| If `a' is denormal and we are in flush-to-zero mode then set the
| input-denormal exception and return zero. Otherwise just return the value.
*----------------------------------------------------------------------------*/
static float32 float32_squash_input_denormal(float32 a STATUS_PARAM)
float32 float32_squash_input_denormal(float32 a STATUS_PARAM)
{
if (STATUS(flush_inputs_to_zero)) {
if (extractFloat32Exp(a) == 0 && extractFloat32Frac(a) != 0) {
@@ -473,7 +473,7 @@ INLINE flag extractFloat64Sign( float64 a )
| If `a' is denormal and we are in flush-to-zero mode then set the
| input-denormal exception and return zero. Otherwise just return the value.
*----------------------------------------------------------------------------*/
static float64 float64_squash_input_denormal(float64 a STATUS_PARAM)
float64 float64_squash_input_denormal(float64 a STATUS_PARAM)
{
if (STATUS(flush_inputs_to_zero)) {
if (extractFloat64Exp(a) == 0 && extractFloat64Frac(a) != 0) {

View File

@@ -143,11 +143,21 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
unsigned long mem_size;
DeviceState *dev;
SysBusDevice *busdev;
ObjectClass *cpu_oc;
cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, "cortex-a9");
assert(cpu_oc);
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
s->cpu[n] = cpu_arm_init("cortex-a9");
if (!s->cpu[n]) {
fprintf(stderr, "Unable to find CPU %d definition\n", n);
Object *cpuobj = object_new(object_class_get_name(cpu_oc));
Error *err = NULL;
s->cpu[n] = ARM_CPU(cpuobj);
object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR,
"reset-cbar", &error_abort);
object_property_set_bool(cpuobj, true, "realized", &err);
if (err) {
error_report("%s", error_get_pretty(err));
exit(1);
}
}

View File

@@ -18,6 +18,7 @@
#include "hw/i2c/i2c.h"
#include "sysemu/blockdev.h"
#include "exec/address-spaces.h"
#include "qemu/error-report.h"
#define SMP_BOOT_ADDR 0xe0000000
#define SMP_BOOTREG_ADDR 0x10000030
@@ -49,6 +50,7 @@ static void realview_init(QEMUMachineInitArgs *args,
{
ARMCPU *cpu = NULL;
CPUARMState *env;
ObjectClass *cpu_oc;
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
@@ -70,12 +72,14 @@ static void realview_init(QEMUMachineInitArgs *args,
uint32_t sys_id;
ram_addr_t low_ram_size;
ram_addr_t ram_size = args->ram_size;
hwaddr periphbase = 0;
switch (board_type) {
case BOARD_EB:
break;
case BOARD_EB_MPCORE:
is_mpcore = 1;
periphbase = 0x10100000;
break;
case BOARD_PB_A8:
is_pb = 1;
@@ -83,16 +87,37 @@ static void realview_init(QEMUMachineInitArgs *args,
case BOARD_PBX_A9:
is_mpcore = 1;
is_pb = 1;
periphbase = 0x1f000000;
break;
}
cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, args->cpu_model);
if (!cpu_oc) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
for (n = 0; n < smp_cpus; n++) {
cpu = cpu_arm_init(args->cpu_model);
if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
Object *cpuobj = object_new(object_class_get_name(cpu_oc));
Error *err = NULL;
if (is_pb && is_mpcore) {
object_property_set_int(cpuobj, periphbase, "reset-cbar", &err);
if (err) {
error_report("%s", error_get_pretty(err));
exit(1);
}
}
object_property_set_bool(cpuobj, true, "realized", &err);
if (err) {
error_report("%s", error_get_pretty(err));
exit(1);
}
cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpuobj), ARM_CPU_IRQ);
}
cpu = ARM_CPU(first_cpu);
env = &cpu->env;
if (arm_feature(env, ARM_FEATURE_V7)) {
if (is_mpcore) {
@@ -141,16 +166,10 @@ static void realview_init(QEMUMachineInitArgs *args,
sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
if (is_mpcore) {
hwaddr periphbase;
dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore");
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
qdev_init_nofail(dev);
busdev = SYS_BUS_DEVICE(dev);
if (is_pb) {
periphbase = 0x1f000000;
} else {
periphbase = 0x10100000;
}
sysbus_mmio_map(busdev, 0, periphbase);
for (n = 0; n < smp_cpus; n++) {
sysbus_connect_irq(busdev, n, cpu_irq[n]);

View File

@@ -32,6 +32,7 @@
#include "sysemu/blockdev.h"
#include "hw/block/flash.h"
#include "sysemu/device_tree.h"
#include "qemu/error-report.h"
#include <libfdt.h>
#define VEXPRESS_BOARD_ID 0x8e0
@@ -173,6 +174,64 @@ struct VEDBoardInfo {
DBoardInitFn *init;
};
static void init_cpus(const char *cpu_model, const char *privdev,
hwaddr periphbase, qemu_irq *pic)
{
ObjectClass *cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
DeviceState *dev;
SysBusDevice *busdev;
int n;
if (!cpu_oc) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
/* Create the actual CPUs */
for (n = 0; n < smp_cpus; n++) {
Object *cpuobj = object_new(object_class_get_name(cpu_oc));
Error *err = NULL;
object_property_set_int(cpuobj, periphbase, "reset-cbar", &err);
if (err) {
error_report("%s", error_get_pretty(err));
exit(1);
}
object_property_set_bool(cpuobj, true, "realized", &err);
if (err) {
error_report("%s", error_get_pretty(err));
exit(1);
}
}
/* Create the private peripheral devices (including the GIC);
* this must happen after the CPUs are created because a15mpcore_priv
* wires itself up to the CPU's generic_timer gpio out lines.
*/
dev = qdev_create(NULL, privdev);
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
qdev_init_nofail(dev);
busdev = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(busdev, 0, periphbase);
/* Interrupts [42:0] are from the motherboard;
* [47:43] are reserved; [63:48] are daughterboard
* peripherals. Note that some documentation numbers
* external interrupts starting from 32 (because there
* are internal interrupts 0..31).
*/
for (n = 0; n < 64; n++) {
pic[n] = qdev_get_gpio_in(dev, n);
}
/* Connect the CPUs to the GIC */
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));
}
}
static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
ram_addr_t ram_size,
const char *cpu_model,
@@ -181,25 +240,12 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *lowram = g_new(MemoryRegion, 1);
DeviceState *dev;
SysBusDevice *busdev;
int n;
qemu_irq cpu_irq[4];
ram_addr_t low_ram_size;
if (!cpu_model) {
cpu_model = "cortex-a9";
}
for (n = 0; n < smp_cpus; n++) {
ARMCPU *cpu = cpu_arm_init(cpu_model);
if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
}
if (ram_size > 0x40000000) {
/* 1GB is the maximum the address space permits */
fprintf(stderr, "vexpress-a9: cannot model more than 1GB RAM\n");
@@ -221,23 +267,7 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
memory_region_add_subregion(sysmem, 0x60000000, ram);
/* 0x1e000000 A9MPCore (SCU) private memory region */
dev = qdev_create(NULL, "a9mpcore_priv");
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
qdev_init_nofail(dev);
busdev = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(busdev, 0, 0x1e000000);
for (n = 0; n < smp_cpus; n++) {
sysbus_connect_irq(busdev, n, cpu_irq[n]);
}
/* Interrupts [42:0] are from the motherboard;
* [47:43] are reserved; [63:48] are daughterboard
* peripherals. Note that some documentation numbers
* external interrupts starting from 32 (because the
* A9MP has internal interrupts 0..31).
*/
for (n = 0; n < 64; n++) {
pic[n] = qdev_get_gpio_in(dev, n);
}
init_cpus(cpu_model, "a9mpcore_priv", 0x1e000000, pic);
/* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
@@ -296,29 +326,14 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
const char *cpu_model,
qemu_irq *pic)
{
int n;
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *sram = g_new(MemoryRegion, 1);
qemu_irq cpu_irq[4];
DeviceState *dev;
SysBusDevice *busdev;
if (!cpu_model) {
cpu_model = "cortex-a15";
}
for (n = 0; n < smp_cpus; n++) {
ARMCPU *cpu;
cpu = cpu_arm_init(cpu_model);
if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
}
{
/* We have to use a separate 64 bit variable here to avoid the gcc
* "comparison is always false due to limited range of data type"
@@ -337,23 +352,7 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
memory_region_add_subregion(sysmem, 0x80000000, ram);
/* 0x2c000000 A15MPCore private memory region (GIC) */
dev = qdev_create(NULL, "a15mpcore_priv");
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
qdev_init_nofail(dev);
busdev = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(busdev, 0, 0x2c000000);
for (n = 0; n < smp_cpus; n++) {
sysbus_connect_irq(busdev, n, cpu_irq[n]);
}
/* Interrupts [42:0] are from the motherboard;
* [47:43] are reserved; [63:48] are daughterboard
* peripherals. Note that some documentation numbers
* external interrupts starting from 32 (because there
* are internal interrupts 0..31).
*/
for (n = 0; n < 64; n++) {
pic[n] = qdev_get_gpio_in(dev, n);
}
init_cpus(cpu_model, "a15mpcore_priv", 0x2c000000, pic);
/* A15 daughterboard peripherals: */

View File

@@ -390,6 +390,12 @@ static void machvirt_init(QEMUMachineInitArgs *args)
if (n > 0) {
object_property_set_bool(cpuobj, true, "start-powered-off", NULL);
}
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
object_property_set_int(cpuobj, vbi->memmap[VIRT_CPUPERIPHS].base,
"reset-cbar", &error_abort);
}
object_property_set_bool(cpuobj, true, "realized", NULL);
}
fdt_add_cpu_nodes(vbi);

View File

@@ -393,7 +393,6 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
if (blk->iothread) {
s->internal_iothread = false;
s->iothread = blk->iothread;
object_ref(OBJECT(s->iothread));
} else {
/* Create per-device IOThread if none specified */
Error *local_err = NULL;
@@ -408,6 +407,7 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
s->iothread = iothread_find(vdev->name);
assert(s->iothread);
}
object_ref(OBJECT(s->iothread));
s->ctx = iothread_get_aio_context(s->iothread);
/* Prevent block operations that conflict with data plane thread */

View File

@@ -20,6 +20,7 @@ typedef struct PL011State {
uint32_t readbuff;
uint32_t flags;
uint32_t lcr;
uint32_t rsr;
uint32_t cr;
uint32_t dmacr;
uint32_t int_enabled;
@@ -81,13 +82,14 @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
}
if (s->read_count == s->read_trigger - 1)
s->int_level &= ~ PL011_INT_RX;
s->rsr = c >> 8;
pl011_update(s);
if (s->chr) {
qemu_chr_accept_input(s->chr);
}
return c;
case 1: /* UARTCR */
return 0;
case 1: /* UARTRSR */
return s->rsr;
case 6: /* UARTFR */
return s->flags;
case 8: /* UARTILPR */
@@ -146,8 +148,8 @@ static void pl011_write(void *opaque, hwaddr offset,
s->int_level |= PL011_INT_TX;
pl011_update(s);
break;
case 1: /* UARTCR */
s->cr = value;
case 1: /* UARTRSR/UARTECR */
s->rsr = 0;
break;
case 6: /* UARTFR */
/* Writes to Flag register are ignored. */
@@ -162,6 +164,11 @@ static void pl011_write(void *opaque, hwaddr offset,
s->fbrd = value;
break;
case 11: /* UARTLCR_H */
/* Reset the FIFO state on FIFO enable or disable */
if ((s->lcr ^ value) & 0x10) {
s->read_count = 0;
s->read_pos = 0;
}
s->lcr = value;
pl011_set_read_trigger(s);
break;
@@ -214,7 +221,7 @@ static void pl011_put_fifo(void *opaque, uint32_t value)
s->read_fifo[slot] = value;
s->read_count++;
s->flags &= ~PL011_FLAG_RXFE;
if (s->cr & 0x10 || s->read_count == 16) {
if (!(s->lcr & 0x10) || s->read_count == 16) {
s->flags |= PL011_FLAG_RXFF;
}
if (s->read_count == s->read_trigger) {
@@ -242,13 +249,14 @@ static const MemoryRegionOps pl011_ops = {
static const VMStateDescription vmstate_pl011 = {
.name = "pl011",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.version_id = 2,
.minimum_version_id = 2,
.minimum_version_id_old = 2,
.fields = (VMStateField[]) {
VMSTATE_UINT32(readbuff, PL011State),
VMSTATE_UINT32(flags, PL011State),
VMSTATE_UINT32(lcr, PL011State),
VMSTATE_UINT32(rsr, PL011State),
VMSTATE_UINT32(cr, PL011State),
VMSTATE_UINT32(dmacr, PL011State),
VMSTATE_UINT32(int_enabled, PL011State),

View File

@@ -21,6 +21,18 @@ void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
}
}
void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name,
Object *val, Error **errp)
{
DeviceState *dev = DEVICE(obj);
if (dev->realized) {
error_setg(errp, "Attempt to set link property '%s' on device '%s' "
"(type '%s') after it was realized",
name, dev->id, object_get_typename(obj));
}
}
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
{
void *ptr = dev;

View File

@@ -98,6 +98,8 @@ static void bus_add_child(BusState *bus, DeviceState *child)
object_property_add_link(OBJECT(bus), name,
object_get_typename(OBJECT(child)),
(Object **)&kid->child,
NULL, /* read-only property */
0, /* return ownership on prop deletion */
NULL);
}
@@ -824,7 +826,8 @@ static void device_initfn(Object *obj)
} while (class != object_class_by_name(TYPE_DEVICE));
object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
(Object **)&dev->parent_bus, &error_abort);
(Object **)&dev->parent_bus, NULL, 0,
&error_abort);
}
static void device_post_init(Object *obj)
@@ -944,7 +947,10 @@ static void qbus_initfn(Object *obj)
QTAILQ_INIT(&bus->children);
object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY,
TYPE_HOTPLUG_HANDLER,
(Object **)&bus->hotplug_handler, NULL);
(Object **)&bus->hotplug_handler,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
NULL);
object_property_add_bool(obj, "realized",
bus_get_realized, bus_set_realized, NULL);
}

View File

@@ -537,9 +537,15 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
Error *local_errp = NULL;
object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
(Object **)&ds->dma, &local_errp);
(Object **)&ds->dma,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&local_errp);
object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA,
(Object **)&cs->dma, &local_errp);
(Object **)&cs->dma,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&local_errp);
if (local_errp) {
goto xilinx_axidma_realize_fail;
}
@@ -571,10 +577,16 @@ static void xilinx_axidma_init(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
(Object **)&s->tx_data_dev, &error_abort);
(Object **)&s->tx_data_dev,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
object_property_add_link(obj, "axistream-control-connected",
TYPE_STREAM_SLAVE,
(Object **)&s->tx_control_dev, &error_abort);
(Object **)&s->tx_control_dev,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
TYPE_XILINX_AXI_DMA_DATA_STREAM);

View File

@@ -118,11 +118,12 @@ static uint32_t ahci_port_read(AHCIState *s, int port, int offset)
static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
{
AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
PCIDevice *pci_dev = PCI_DEVICE(d);
PCIDevice *pci_dev =
(PCIDevice *)object_dynamic_cast(OBJECT(d), TYPE_PCI_DEVICE);
DPRINTF(0, "raise irq\n");
if (msi_enabled(pci_dev)) {
if (pci_dev && msi_enabled(pci_dev)) {
msi_notify(pci_dev, 0);
} else {
qemu_irq_raise(s->irq);
@@ -132,10 +133,12 @@ static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
static void ahci_irq_lower(AHCIState *s, AHCIDevice *dev)
{
AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
PCIDevice *pci_dev =
(PCIDevice *)object_dynamic_cast(OBJECT(d), TYPE_PCI_DEVICE);
DPRINTF(0, "lower irq\n");
if (!msi_enabled(PCI_DEVICE(d))) {
if (!pci_dev || !msi_enabled(pci_dev)) {
qemu_irq_lower(s->irq);
}
}
@@ -1311,7 +1314,7 @@ static const VMStateDescription vmstate_sysbus_ahci = {
.name = "sysbus-ahci",
.unmigratable = 1, /* Still buggy under I/O load */
.fields = (VMStateField []) {
VMSTATE_AHCI(ahci, AHCIPCIState),
VMSTATE_AHCI(ahci, SysbusAHCIState),
VMSTATE_END_OF_LIST()
},
};
@@ -1328,7 +1331,7 @@ static void sysbus_ahci_realize(DeviceState *dev, Error **errp)
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
SysbusAHCIState *s = SYSBUS_AHCI(dev);
ahci_init(&s->ahci, dev, NULL, s->num_ports);
ahci_init(&s->ahci, dev, &address_space_memory, s->num_ports);
sysbus_init_mmio(sbd, &s->ahci.mem);
sysbus_init_irq(sbd, &s->ahci.irq);

View File

@@ -945,9 +945,15 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp)
Error *local_errp = NULL;
object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet",
(Object **) &ds->enet, &local_errp);
(Object **) &ds->enet,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&local_errp);
object_property_add_link(OBJECT(cs), "enet", "xlnx.axi-ethernet",
(Object **) &cs->enet, &local_errp);
(Object **) &cs->enet,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&local_errp);
if (local_errp) {
goto xilinx_enet_realize_fail;
}
@@ -982,10 +988,16 @@ static void xilinx_enet_init(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
(Object **) &s->tx_data_dev, &error_abort);
(Object **) &s->tx_data_dev,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
object_property_add_link(obj, "axistream-control-connected",
TYPE_STREAM_SLAVE,
(Object **) &s->tx_control_dev, &error_abort);
(Object **) &s->tx_control_dev,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
TYPE_XILINX_AXI_ENET_DATA_STREAM);

View File

@@ -52,15 +52,25 @@ typedef struct RavenPCIState {
typedef struct PRePPCIState {
PCIHostState parent_obj;
MemoryRegion intack;
qemu_irq irq[PCI_NUM_PINS];
PCIBus pci_bus;
AddressSpace pci_io_as;
MemoryRegion pci_io;
MemoryRegion pci_io_non_contiguous;
MemoryRegion pci_memory;
MemoryRegion pci_intack;
MemoryRegion bm;
MemoryRegion bm_ram_alias;
MemoryRegion bm_pci_memory_alias;
AddressSpace bm_as;
RavenPCIState pci_dev;
int contiguous_map;
} PREPPCIState;
#define BIOS_SIZE (1024 * 1024)
static inline uint32_t PPC_PCIIO_config(hwaddr addr)
static inline uint32_t raven_pci_io_config(hwaddr addr)
{
int i;
@@ -72,53 +82,133 @@ static inline uint32_t PPC_PCIIO_config(hwaddr addr)
return (addr & 0x7ff) | (i << 11);
}
static void ppc_pci_io_write(void *opaque, hwaddr addr,
uint64_t val, unsigned int size)
static void raven_pci_io_write(void *opaque, hwaddr addr,
uint64_t val, unsigned int size)
{
PREPPCIState *s = opaque;
PCIHostState *phb = PCI_HOST_BRIDGE(s);
pci_data_write(phb->bus, PPC_PCIIO_config(addr), val, size);
pci_data_write(phb->bus, raven_pci_io_config(addr), val, size);
}
static uint64_t ppc_pci_io_read(void *opaque, hwaddr addr,
unsigned int size)
static uint64_t raven_pci_io_read(void *opaque, hwaddr addr,
unsigned int size)
{
PREPPCIState *s = opaque;
PCIHostState *phb = PCI_HOST_BRIDGE(s);
return pci_data_read(phb->bus, PPC_PCIIO_config(addr), size);
return pci_data_read(phb->bus, raven_pci_io_config(addr), size);
}
static const MemoryRegionOps PPC_PCIIO_ops = {
.read = ppc_pci_io_read,
.write = ppc_pci_io_write,
static const MemoryRegionOps raven_pci_io_ops = {
.read = raven_pci_io_read,
.write = raven_pci_io_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static uint64_t ppc_intack_read(void *opaque, hwaddr addr,
unsigned int size)
static uint64_t raven_intack_read(void *opaque, hwaddr addr,
unsigned int size)
{
return pic_read_irq(isa_pic);
}
static const MemoryRegionOps PPC_intack_ops = {
.read = ppc_intack_read,
static const MemoryRegionOps raven_intack_ops = {
.read = raven_intack_read,
.valid = {
.max_access_size = 1,
},
};
static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
static inline hwaddr raven_io_address(PREPPCIState *s,
hwaddr addr)
{
if (s->contiguous_map == 0) {
/* 64 KB contiguous space for IOs */
addr &= 0xFFFF;
} else {
/* 8 MB non-contiguous space for IOs */
addr = (addr & 0x1F) | ((addr & 0x007FFF000) >> 7);
}
/* FIXME: handle endianness switch */
return addr;
}
static uint64_t raven_io_read(void *opaque, hwaddr addr,
unsigned int size)
{
PREPPCIState *s = opaque;
uint8_t buf[4];
addr = raven_io_address(s, addr);
address_space_read(&s->pci_io_as, addr + 0x80000000, buf, size);
if (size == 1) {
return buf[0];
} else if (size == 2) {
return lduw_p(buf);
} else if (size == 4) {
return ldl_p(buf);
} else {
g_assert_not_reached();
}
}
static void raven_io_write(void *opaque, hwaddr addr,
uint64_t val, unsigned int size)
{
PREPPCIState *s = opaque;
uint8_t buf[4];
addr = raven_io_address(s, addr);
if (size == 1) {
buf[0] = val;
} else if (size == 2) {
stw_p(buf, val);
} else if (size == 4) {
stl_p(buf, val);
} else {
g_assert_not_reached();
}
address_space_write(&s->pci_io_as, addr + 0x80000000, buf, size);
}
static const MemoryRegionOps raven_io_ops = {
.read = raven_io_read,
.write = raven_io_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.impl.max_access_size = 4,
.valid.unaligned = true,
};
static int raven_map_irq(PCIDevice *pci_dev, int irq_num)
{
return (irq_num + (pci_dev->devfn >> 3)) & 1;
}
static void prep_set_irq(void *opaque, int irq_num, int level)
static void raven_set_irq(void *opaque, int irq_num, int level)
{
qemu_irq *pic = opaque;
qemu_set_irq(pic[irq_num] , level);
}
static AddressSpace *raven_pcihost_set_iommu(PCIBus *bus, void *opaque,
int devfn)
{
PREPPCIState *s = opaque;
return &s->bm_as;
}
static void raven_change_gpio(void *opaque, int n, int level)
{
PREPPCIState *s = opaque;
s->contiguous_map = level;
}
static void raven_pcihost_realizefn(DeviceState *d, Error **errp)
{
SysBusDevice *dev = SYS_BUS_DEVICE(d);
@@ -127,29 +217,30 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp)
MemoryRegion *address_space_mem = get_system_memory();
int i;
isa_mem_base = 0xc0000000;
for (i = 0; i < PCI_NUM_PINS; i++) {
sysbus_init_irq(dev, &s->irq[i]);
}
pci_bus_irqs(&s->pci_bus, prep_set_irq, prep_map_irq, s->irq, PCI_NUM_PINS);
qdev_init_gpio_in(d, raven_change_gpio, 1);
memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_be_ops, s,
"pci-conf-idx", 1);
sysbus_add_io(dev, 0xcf8, &h->conf_mem);
sysbus_init_ioports(&h->busdev, 0xcf8, 1);
pci_bus_irqs(&s->pci_bus, raven_set_irq, raven_map_irq, s->irq,
PCI_NUM_PINS);
memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_be_ops, s,
"pci-conf-data", 1);
sysbus_add_io(dev, 0xcfc, &h->data_mem);
sysbus_init_ioports(&h->busdev, 0xcfc, 1);
memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, s,
"pci-conf-idx", 4);
memory_region_add_subregion(&s->pci_io, 0xcf8, &h->conf_mem);
memory_region_init_io(&h->mmcfg, OBJECT(s), &PPC_PCIIO_ops, s, "pciio", 0x00400000);
memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, s,
"pci-conf-data", 4);
memory_region_add_subregion(&s->pci_io, 0xcfc, &h->data_mem);
memory_region_init_io(&h->mmcfg, OBJECT(s), &raven_pci_io_ops, s,
"pciio", 0x00400000);
memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg);
memory_region_init_io(&s->intack, OBJECT(s), &PPC_intack_ops, s, "pci-intack", 1);
memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->intack);
memory_region_init_io(&s->pci_intack, OBJECT(s), &raven_intack_ops, s,
"pci-intack", 1);
memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->pci_intack);
/* TODO Remove once realize propagates to child devices. */
object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp);
@@ -160,11 +251,36 @@ static void raven_pcihost_initfn(Object *obj)
PCIHostState *h = PCI_HOST_BRIDGE(obj);
PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(obj);
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *address_space_io = get_system_io();
DeviceState *pci_dev;
memory_region_init(&s->pci_io, obj, "pci-io", 0x3f800000);
memory_region_init_io(&s->pci_io_non_contiguous, obj, &raven_io_ops, s,
"pci-io-non-contiguous", 0x00800000);
/* Open Hack'Ware hack: real size should be only 0x3f000000 bytes */
memory_region_init(&s->pci_memory, obj, "pci-memory",
0x3f000000 + 0xc0000000ULL);
address_space_init(&s->pci_io_as, &s->pci_io, "raven-io");
/* CPU address space */
memory_region_add_subregion(address_space_mem, 0x80000000, &s->pci_io);
memory_region_add_subregion_overlap(address_space_mem, 0x80000000,
&s->pci_io_non_contiguous, 1);
memory_region_add_subregion(address_space_mem, 0xc0000000, &s->pci_memory);
pci_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), DEVICE(obj), NULL,
address_space_mem, address_space_io, 0, TYPE_PCI_BUS);
&s->pci_memory, &s->pci_io, 0, TYPE_PCI_BUS);
/* Bus master address space */
memory_region_init(&s->bm, obj, "bm-raven", UINT32_MAX);
memory_region_init_alias(&s->bm_pci_memory_alias, obj, "bm-pci-memory",
&s->pci_memory, 0,
memory_region_size(&s->pci_memory));
memory_region_init_alias(&s->bm_ram_alias, obj, "bm-system",
get_system_memory(), 0, 0x80000000);
memory_region_add_subregion(&s->bm, 0 , &s->bm_pci_memory_alias);
memory_region_add_subregion(&s->bm, 0x80000000, &s->bm_ram_alias);
address_space_init(&s->bm_as, &s->bm, "raven-bm");
pci_setup_iommu(&s->pci_bus, raven_pcihost_set_iommu, s);
h->bus = &s->pci_bus;
object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_RAVEN_PCI_DEVICE);

View File

@@ -198,7 +198,9 @@ static void pxa2xx_pcmcia_initfn(Object *obj)
s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
object_property_add_link(obj, "card", TYPE_PCMCIA_CARD,
(Object **)&s->card, NULL);
(Object **)&s->card,
NULL, /* read-only property */
0, NULL);
}
/* Insert a new card into a slot */

View File

@@ -185,6 +185,7 @@ typedef struct sysctrl_t {
uint8_t state;
uint8_t syscontrol;
int contiguous_map;
qemu_irq contiguous_map_irq;
int endian;
} sysctrl_t;
@@ -253,6 +254,7 @@ static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
case 0x0850:
/* I/O map type register */
sysctrl->contiguous_map = val & 0x01;
qemu_set_irq(sysctrl->contiguous_map_irq, sysctrl->contiguous_map);
break;
default:
printf("ERROR: unaffected IO port write: %04" PRIx32
@@ -327,91 +329,6 @@ static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
return retval;
}
static inline hwaddr prep_IO_address(sysctrl_t *sysctrl,
hwaddr addr)
{
if (sysctrl->contiguous_map == 0) {
/* 64 KB contiguous space for IOs */
addr &= 0xFFFF;
} else {
/* 8 MB non-contiguous space for IOs */
addr = (addr & 0x1F) | ((addr & 0x007FFF000) >> 7);
}
return addr;
}
static void PPC_prep_io_writeb (void *opaque, hwaddr addr,
uint32_t value)
{
sysctrl_t *sysctrl = opaque;
addr = prep_IO_address(sysctrl, addr);
cpu_outb(addr, value);
}
static uint32_t PPC_prep_io_readb (void *opaque, hwaddr addr)
{
sysctrl_t *sysctrl = opaque;
uint32_t ret;
addr = prep_IO_address(sysctrl, addr);
ret = cpu_inb(addr);
return ret;
}
static void PPC_prep_io_writew (void *opaque, hwaddr addr,
uint32_t value)
{
sysctrl_t *sysctrl = opaque;
addr = prep_IO_address(sysctrl, addr);
PPC_IO_DPRINTF("0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", addr, value);
cpu_outw(addr, value);
}
static uint32_t PPC_prep_io_readw (void *opaque, hwaddr addr)
{
sysctrl_t *sysctrl = opaque;
uint32_t ret;
addr = prep_IO_address(sysctrl, addr);
ret = cpu_inw(addr);
PPC_IO_DPRINTF("0x" TARGET_FMT_plx " <= 0x%08" PRIx32 "\n", addr, ret);
return ret;
}
static void PPC_prep_io_writel (void *opaque, hwaddr addr,
uint32_t value)
{
sysctrl_t *sysctrl = opaque;
addr = prep_IO_address(sysctrl, addr);
PPC_IO_DPRINTF("0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", addr, value);
cpu_outl(addr, value);
}
static uint32_t PPC_prep_io_readl (void *opaque, hwaddr addr)
{
sysctrl_t *sysctrl = opaque;
uint32_t ret;
addr = prep_IO_address(sysctrl, addr);
ret = cpu_inl(addr);
PPC_IO_DPRINTF("0x" TARGET_FMT_plx " <= 0x%08" PRIx32 "\n", addr, ret);
return ret;
}
static const MemoryRegionOps PPC_prep_io_ops = {
.old_mmio = {
.read = { PPC_prep_io_readb, PPC_prep_io_readw, PPC_prep_io_readl },
.write = { PPC_prep_io_writeb, PPC_prep_io_writew, PPC_prep_io_writel },
},
.endianness = DEVICE_NATIVE_ENDIAN,
};
#define NVRAM_SIZE 0x2000
@@ -458,13 +375,13 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
CPUPPCState *env = NULL;
nvram_t nvram;
M48t59State *m48t59;
MemoryRegion *PPC_io_memory = g_new(MemoryRegion, 1);
PortioList *port_list = g_new(PortioList, 1);
#if 0
MemoryRegion *xcsr = g_new(MemoryRegion, 1);
#endif
int linux_boot, i, nb_nics1;
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *vga = g_new(MemoryRegion, 1);
uint32_t kernel_base, initrd_base;
long kernel_size, initrd_size;
DeviceState *dev;
@@ -567,6 +484,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
fprintf(stderr, "Couldn't create PCI host controller.\n");
exit(1);
}
sysctrl->contiguous_map_irq = qdev_get_gpio_in(dev, 0);
/* PCI -> ISA bridge */
pci = pci_create_simple(pci_bus, PCI_DEVFN(1, 0), "i82378");
@@ -587,13 +505,16 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
qdev_prop_set_uint8(dev, "config", 13); /* fdc, ser0, ser1, par0 */
qdev_init_nofail(dev);
/* Register 8 MB of ISA IO space (needed for non-contiguous map) */
memory_region_init_io(PPC_io_memory, NULL, &PPC_prep_io_ops, sysctrl,
"ppc-io", 0x00800000);
memory_region_add_subregion(sysmem, 0x80000000, PPC_io_memory);
/* init basic PC hardware */
pci_vga_init(pci_bus);
/* Open Hack'Ware hack: PCI BAR#0 is programmed to 0xf0000000.
* While bios will access framebuffer at 0xf0000000, real physical
* address is 0xf0000000 + 0xc0000000 (PCI memory base).
* Alias the wrong memory accesses to the right place.
*/
memory_region_init_alias(vga, NULL, "vga-alias", pci_address_space(pci),
0xf0000000, 0x1000000);
memory_region_add_subregion_overlap(sysmem, 0xf0000000, vga, 10);
nb_nics1 = nb_nics;
if (nb_nics1 > NE2000_NB_MAX)

View File

@@ -313,7 +313,9 @@ static void s390_virtio_rng_instance_init(Object *obj)
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
(Object **)&dev->vdev.conf.rng, NULL);
(Object **)&dev->vdev.conf.rng,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
}
static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)

View File

@@ -1272,7 +1272,9 @@ static void virtio_ccw_rng_instance_init(Object *obj)
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
(Object **)&dev->vdev.conf.rng, NULL);
(Object **)&dev->vdev.conf.rng,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
}
static Property virtio_ccw_rng_properties[] = {

View File

@@ -1517,7 +1517,9 @@ static void virtio_rng_initfn(Object *obj)
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
(Object **)&dev->vdev.conf.rng, NULL);
(Object **)&dev->vdev.conf.rng,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
}

View File

@@ -162,6 +162,9 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
OBJECT(vrng->conf.default_backend),
NULL);
/* The child property took a reference, we can safely drop ours now */
object_unref(OBJECT(vrng->conf.default_backend));
object_property_set_link(OBJECT(dev),
OBJECT(vrng->conf.default_backend),
"rng", NULL);
@@ -223,7 +226,9 @@ static void virtio_rng_initfn(Object *obj)
VirtIORNG *vrng = VIRTIO_RNG(obj);
object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
(Object **)&vrng->conf.rng, NULL);
(Object **)&vrng->conf.rng,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
}
static const TypeInfo virtio_rng_info = {

View File

@@ -329,8 +329,8 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
BlockDriverCompletionFunc *cb, void *opaque);
/* Invalidate any cached metadata used by image formats */
void bdrv_invalidate_cache(BlockDriverState *bs);
void bdrv_invalidate_cache_all(void);
void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp);
void bdrv_invalidate_cache_all(Error **errp);
void bdrv_clear_incoming_migration_all(void);

View File

@@ -153,7 +153,7 @@ struct BlockDriver {
/*
* Invalidate any cached meta-data.
*/
void (*bdrv_invalidate_cache)(BlockDriverState *bs);
void (*bdrv_invalidate_cache)(BlockDriverState *bs, Error **errp);
/*
* Flushes all data that was already written to the OS all the way down to

View File

@@ -44,7 +44,7 @@ struct TranslationBlock;
typedef struct TranslationBlock TranslationBlock;
/* XXX: make safe guess about sizes */
#define MAX_OP_PER_INSTR 208
#define MAX_OP_PER_INSTR 266
#if HOST_LONG_BITS == 32
#define MAX_OPC_PARAM_PER_ARG 2

View File

@@ -244,6 +244,13 @@ INLINE flag get_default_nan_mode(float_status *status)
*----------------------------------------------------------------------------*/
void float_raise( int8 flags STATUS_PARAM);
/*----------------------------------------------------------------------------
| If `a' is denormal and we are in flush-to-zero mode then set the
| input-denormal exception and return zero. Otherwise just return the value.
*----------------------------------------------------------------------------*/
float32 float32_squash_input_denormal(float32 a STATUS_PARAM);
float64 float64_squash_input_denormal(float64 a STATUS_PARAM);
/*----------------------------------------------------------------------------
| Options to indicate which negations to perform in float*_muladd()
| Using these differs from negating an input or output before calling

View File

@@ -54,6 +54,7 @@ struct QEMUMachine {
int qemu_register_machine(QEMUMachine *m);
#define TYPE_MACHINE "machine"
#undef MACHINE /* BSD defines it and QEMU does not use it */
#define MACHINE(obj) \
OBJECT_CHECK(MachineState, (obj), TYPE_MACHINE)
#define MACHINE_GET_CLASS(obj) \

View File

@@ -204,4 +204,15 @@ void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp);
*/
void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
Error **errp);
/**
* qdev_prop_allow_set_link_before_realize:
*
* Set the #Error object if an attempt is made to set the link after realize.
* This function should be used as the check() argument to
* object_property_add_link().
*/
void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name,
Object *val, Error **errp);
#endif

View File

@@ -227,7 +227,6 @@ struct CPUState {
bool stop;
bool stopped;
volatile sig_atomic_t exit_request;
volatile sig_atomic_t tcg_exit_req;
uint32_t interrupt_request;
int singlestep_enabled;
int64_t icount_extra;
@@ -272,6 +271,12 @@ struct CPUState {
} icount_decr;
uint32_t can_do_io;
int32_t exception_index; /* used by m68k TCG */
/* Note that this is accessed at the start of every TB via a negative
offset from AREG0. Leave this field at the end so as to make the
(absolute value) offset as small as possible. This reduces code
size, especially for hosts without large memory offsets. */
volatile sig_atomic_t tcg_exit_req;
};
QTAILQ_HEAD(CPUTailQ, CPUState);

View File

@@ -1067,12 +1067,29 @@ Object *object_resolve_path_component(Object *parent, const gchar *part);
void object_property_add_child(Object *obj, const char *name,
Object *child, Error **errp);
typedef enum {
/* Unref the link pointer when the property is deleted */
OBJ_PROP_LINK_UNREF_ON_RELEASE = 0x1,
} ObjectPropertyLinkFlags;
/**
* object_property_allow_set_link:
*
* The default implementation of the object_property_add_link() check()
* callback function. It allows the link property to be set and never returns
* an error.
*/
void object_property_allow_set_link(Object *, const char *,
Object *, Error **);
/**
* object_property_add_link:
* @obj: the object to add a property to
* @name: the name of the property
* @type: the qobj type of the link
* @child: a pointer to where the link object reference is stored
* @check: callback to veto setting or NULL if the property is read-only
* @flags: additional options for the link
* @errp: if an error occurs, a pointer to an area to store the area
*
* Links establish relationships between objects. Links are unidirectional
@@ -1081,13 +1098,23 @@ void object_property_add_child(Object *obj, const char *name,
*
* Links form the graph in the object model.
*
* The <code>@check()</code> callback is invoked when
* object_property_set_link() is called and can raise an error to prevent the
* link being set. If <code>@check</code> is NULL, the property is read-only
* and cannot be set.
*
* Ownership of the pointer that @child points to is transferred to the
* link property. The reference count for <code>*@child</code> is
* managed by the property from after the function returns till the
* property is deleted with object_property_del().
* property is deleted with object_property_del(). If the
* <code>@flags</code> <code>OBJ_PROP_LINK_UNREF_ON_RELEASE</code> bit is set,
* the reference count is decremented when the property is deleted.
*/
void object_property_add_link(Object *obj, const char *name,
const char *type, Object **child,
void (*check)(Object *obj, const char *name,
Object *val, Error **errp),
ObjectPropertyLinkFlags flags,
Error **errp);
/**

View File

@@ -352,6 +352,9 @@ enum
ARM_HWCAP_ARM_VFPv3D16 = 1 << 13,
};
#ifndef TARGET_AARCH64
/* The commpage only exists for 32 bit kernels */
#define TARGET_HAS_VALIDATE_GUEST_SPACE
/* Return 1 if the proposed guest space is suitable for the guest.
* Return 0 if the proposed guest space isn't suitable, but another
@@ -411,7 +414,7 @@ static int validate_guest_space(unsigned long guest_base,
return 1; /* All good */
}
#endif
#define ELF_HWCAP get_elf_hwcap()

View File

@@ -126,6 +126,7 @@ typedef struct TaskState {
#endif
uint32_t stack_base;
int used; /* non zero if used */
bool sigsegv_blocked; /* SIGSEGV blocked by guest */
struct image_info *info;
struct linux_binprm *bprm;
@@ -235,6 +236,7 @@ int host_to_target_signal(int sig);
long do_sigreturn(CPUArchState *env);
long do_rt_sigreturn(CPUArchState *env);
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
#ifdef TARGET_I386
/* vm86.c */

View File

@@ -197,6 +197,55 @@ void target_to_host_old_sigset(sigset_t *sigset,
target_to_host_sigset(sigset, &d);
}
/* Wrapper for sigprocmask function
* Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
* are host signal set, not guest ones. This wraps the sigprocmask host calls
* that should be protected (calls originated from guest)
*/
int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
{
int ret;
sigset_t val;
sigset_t *temp = NULL;
CPUState *cpu = thread_cpu;
TaskState *ts = (TaskState *)cpu->opaque;
bool segv_was_blocked = ts->sigsegv_blocked;
if (set) {
bool has_sigsegv = sigismember(set, SIGSEGV);
val = *set;
temp = &val;
sigdelset(temp, SIGSEGV);
switch (how) {
case SIG_BLOCK:
if (has_sigsegv) {
ts->sigsegv_blocked = true;
}
break;
case SIG_UNBLOCK:
if (has_sigsegv) {
ts->sigsegv_blocked = false;
}
break;
case SIG_SETMASK:
ts->sigsegv_blocked = has_sigsegv;
break;
default:
g_assert_not_reached();
}
}
ret = sigprocmask(how, temp, oldset);
if (oldset && segv_was_blocked) {
sigaddset(oldset, SIGSEGV);
}
return ret;
}
/* siginfo conversion */
static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
@@ -458,6 +507,19 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
k = &ts->sigtab[sig - 1];
queue = gdb_queuesig ();
handler = sigact_table[sig - 1]._sa_handler;
if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
/* Guest has blocked SIGSEGV but we got one anyway. Assume this
* is a forced SIGSEGV (ie one the kernel handles via force_sig_info
* because it got a real MMU fault). A blocked SIGSEGV in that
* situation is treated as if using the default handler. This is
* not correct if some other process has randomly sent us a SIGSEGV
* via kill(), but that is not easy to distinguish at this point,
* so we assume it doesn't happen.
*/
handler = TARGET_SIG_DFL;
}
if (!queue && handler == TARGET_SIG_DFL) {
if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
kill(getpid(),SIGSTOP);
@@ -1056,7 +1118,7 @@ long do_sigreturn(CPUX86State *env)
}
target_to_host_sigset_internal(&set, &target_set);
sigprocmask(SIG_SETMASK, &set, NULL);
do_sigprocmask(SIG_SETMASK, &set, NULL);
/* restore registers */
if (restore_sigcontext(env, &frame->sc, &eax))
@@ -1081,7 +1143,7 @@ long do_rt_sigreturn(CPUX86State *env)
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
goto badframe;
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
sigprocmask(SIG_SETMASK, &set, NULL);
do_sigprocmask(SIG_SETMASK, &set, NULL);
if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))
goto badframe;
@@ -1220,7 +1282,7 @@ static int target_restore_sigframe(CPUARMState *env,
uint64_t pstate;
target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
sigprocmask(SIG_SETMASK, &set, NULL);
do_sigprocmask(SIG_SETMASK, &set, NULL);
for (i = 0; i < 31; i++) {
__get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
@@ -1340,7 +1402,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
long do_rt_sigreturn(CPUARMState *env)
{
struct target_rt_sigframe *frame;
struct target_rt_sigframe *frame = NULL;
abi_ulong frame_addr = env->xregs[31];
if (frame_addr & 15) {
@@ -1861,7 +1923,7 @@ static long do_sigreturn_v1(CPUARMState *env)
}
target_to_host_sigset_internal(&host_set, &set);
sigprocmask(SIG_SETMASK, &host_set, NULL);
do_sigprocmask(SIG_SETMASK, &host_set, NULL);
if (restore_sigcontext(env, &frame->sc))
goto badframe;
@@ -1942,7 +2004,7 @@ static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
abi_ulong *regspace;
target_to_host_sigset(&host_set, &uc->tuc_sigmask);
sigprocmask(SIG_SETMASK, &host_set, NULL);
do_sigprocmask(SIG_SETMASK, &host_set, NULL);
if (restore_sigcontext(env, &uc->tuc_mcontext))
return 1;
@@ -2033,7 +2095,7 @@ static long do_rt_sigreturn_v1(CPUARMState *env)
goto badframe;
target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
sigprocmask(SIG_SETMASK, &host_set, NULL);
do_sigprocmask(SIG_SETMASK, &host_set, NULL);
if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
goto badframe;
@@ -2444,7 +2506,7 @@ long do_sigreturn(CPUSPARCState *env)
}
target_to_host_sigset_internal(&host_set, &set);
sigprocmask(SIG_SETMASK, &host_set, NULL);
do_sigprocmask(SIG_SETMASK, &host_set, NULL);
if (err)
goto segv_and_exit;
@@ -2567,7 +2629,7 @@ void sparc64_set_context(CPUSPARCState *env)
goto do_sigsegv;
}
target_to_host_sigset_internal(&set, &target_set);
sigprocmask(SIG_SETMASK, &set, NULL);
do_sigprocmask(SIG_SETMASK, &set, NULL);
}
env->pc = pc;
env->npc = npc;
@@ -2656,7 +2718,7 @@ void sparc64_get_context(CPUSPARCState *env)
err = 0;
sigprocmask(0, NULL, &set);
do_sigprocmask(0, NULL, &set);
host_to_target_sigset_internal(&target_set, &set);
if (TARGET_NSIG_WORDS == 1) {
err |= __put_user(target_set.sig[0],
@@ -2991,7 +3053,7 @@ long do_sigreturn(CPUMIPSState *regs)
}
target_to_host_sigset_internal(&blocked, &target_set);
sigprocmask(SIG_SETMASK, &blocked, NULL);
do_sigprocmask(SIG_SETMASK, &blocked, NULL);
if (restore_sigcontext(regs, &frame->sf_sc))
goto badframe;
@@ -3095,7 +3157,7 @@ long do_rt_sigreturn(CPUMIPSState *env)
goto badframe;
target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
sigprocmask(SIG_SETMASK, &blocked, NULL);
do_sigprocmask(SIG_SETMASK, &blocked, NULL);
if (restore_sigcontext(env, &frame->rs_uc.tuc_mcontext))
goto badframe;
@@ -3385,7 +3447,7 @@ long do_sigreturn(CPUSH4State *regs)
goto badframe;
target_to_host_sigset_internal(&blocked, &target_set);
sigprocmask(SIG_SETMASK, &blocked, NULL);
do_sigprocmask(SIG_SETMASK, &blocked, NULL);
if (restore_sigcontext(regs, &frame->sc, &r0))
goto badframe;
@@ -3414,7 +3476,7 @@ long do_rt_sigreturn(CPUSH4State *regs)
goto badframe;
target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
sigprocmask(SIG_SETMASK, &blocked, NULL);
do_sigprocmask(SIG_SETMASK, &blocked, NULL);
if (restore_sigcontext(regs, &frame->uc.tuc_mcontext, &r0))
goto badframe;
@@ -3644,7 +3706,7 @@ long do_sigreturn(CPUMBState *env)
goto badframe;
}
target_to_host_sigset_internal(&set, &target_set);
sigprocmask(SIG_SETMASK, &set, NULL);
do_sigprocmask(SIG_SETMASK, &set, NULL);
restore_sigcontext(&frame->uc.tuc_mcontext, env);
/* We got here through a sigreturn syscall, our path back is via an
@@ -3819,7 +3881,7 @@ long do_sigreturn(CPUCRISState *env)
goto badframe;
}
target_to_host_sigset_internal(&set, &target_set);
sigprocmask(SIG_SETMASK, &set, NULL);
do_sigprocmask(SIG_SETMASK, &set, NULL);
restore_sigcontext(&frame->sc, env);
unlock_user_struct(frame, frame_addr, 0);
@@ -4350,7 +4412,7 @@ long do_sigreturn(CPUS390XState *env)
}
target_to_host_sigset_internal(&set, &target_set);
sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
if (restore_sigregs(env, &frame->sregs)) {
goto badframe;
@@ -4378,7 +4440,7 @@ long do_rt_sigreturn(CPUS390XState *env)
}
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */
if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
goto badframe;
@@ -4906,7 +4968,7 @@ long do_sigreturn(CPUPPCState *env)
goto sigsegv;
#endif
target_to_host_sigset_internal(&blocked, &set);
sigprocmask(SIG_SETMASK, &blocked, NULL);
do_sigprocmask(SIG_SETMASK, &blocked, NULL);
if (__get_user(sr_addr, &sc->regs))
goto sigsegv;
@@ -4950,7 +5012,7 @@ static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
return 1;
target_to_host_sigset_internal(&blocked, &set);
sigprocmask(SIG_SETMASK, &blocked, NULL);
do_sigprocmask(SIG_SETMASK, &blocked, NULL);
if (restore_user_regs(env, mcp, sig))
goto sigsegv;
@@ -5324,7 +5386,7 @@ long do_sigreturn(CPUM68KState *env)
}
target_to_host_sigset_internal(&set, &target_set);
sigprocmask(SIG_SETMASK, &set, NULL);
do_sigprocmask(SIG_SETMASK, &set, NULL);
/* restore registers */
@@ -5352,7 +5414,7 @@ long do_rt_sigreturn(CPUM68KState *env)
goto badframe;
target_to_host_sigset_internal(&set, &target_set);
sigprocmask(SIG_SETMASK, &set, NULL);
do_sigprocmask(SIG_SETMASK, &set, NULL);
/* restore registers */
@@ -5599,7 +5661,7 @@ long do_sigreturn(CPUAlphaState *env)
}
target_to_host_sigset_internal(&set, &target_set);
sigprocmask(SIG_SETMASK, &set, NULL);
do_sigprocmask(SIG_SETMASK, &set, NULL);
if (restore_sigcontext(env, sc)) {
goto badframe;
@@ -5622,7 +5684,7 @@ long do_rt_sigreturn(CPUAlphaState *env)
goto badframe;
}
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
sigprocmask(SIG_SETMASK, &set, NULL);
do_sigprocmask(SIG_SETMASK, &set, NULL);
if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
goto badframe;
@@ -5716,6 +5778,14 @@ void process_pending_signals(CPUArchState *cpu_env)
handler = sa->_sa_handler;
}
if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
/* Guest has blocked SIGSEGV but we got one anyway. Assume this
* is a forced SIGSEGV (ie one the kernel handles via force_sig_info
* because it got a real MMU fault), and treat as if default handler.
*/
handler = TARGET_SIG_DFL;
}
if (handler == TARGET_SIG_DFL) {
/* default handler : ignore some signal. The other are job control or fatal */
if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
@@ -5739,7 +5809,7 @@ void process_pending_signals(CPUArchState *cpu_env)
sigaddset(&set, target_to_host_signal(sig));
/* block signals in the handler using Linux */
sigprocmask(SIG_BLOCK, &set, &old_set);
do_sigprocmask(SIG_BLOCK, &set, &old_set);
/* save the previous blocked signal state to restore it at the
end of the signal execution (see do_sigreturn) */
host_to_target_sigset_internal(&target_old_set, &old_set);

View File

@@ -43,6 +43,7 @@
#include <sys/resource.h>
#include <sys/mman.h>
#include <sys/swap.h>
#include <linux/capability.h>
#include <signal.h>
#include <sched.h>
#ifdef __ia64__
@@ -243,6 +244,10 @@ _syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
unsigned long *, user_mask_ptr);
_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
void *, arg);
_syscall2(int, capget, struct __user_cap_header_struct *, header,
struct __user_cap_data_struct *, data);
_syscall2(int, capset, struct __user_cap_header_struct *, header,
struct __user_cap_data_struct *, data);
static bitmask_transtbl fcntl_flags_tbl[] = {
{ TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
@@ -4421,6 +4426,14 @@ static int target_to_host_fcntl_cmd(int cmd)
#endif
case TARGET_F_NOTIFY:
return F_NOTIFY;
#ifdef F_GETOWN_EX
case TARGET_F_GETOWN_EX:
return F_GETOWN_EX;
#endif
#ifdef F_SETOWN_EX
case TARGET_F_SETOWN_EX:
return F_SETOWN_EX;
#endif
default:
return -TARGET_EINVAL;
}
@@ -4443,6 +4456,10 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
struct target_flock *target_fl;
struct flock64 fl64;
struct target_flock64 *target_fl64;
#ifdef F_GETOWN_EX
struct f_owner_ex fox;
struct target_f_owner_ex *target_fox;
#endif
abi_long ret;
int host_cmd = target_to_host_fcntl_cmd(cmd);
@@ -4536,6 +4553,30 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
ret = get_errno(fcntl(fd, host_cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
break;
#ifdef F_GETOWN_EX
case TARGET_F_GETOWN_EX:
ret = get_errno(fcntl(fd, host_cmd, &fox));
if (ret >= 0) {
if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
return -TARGET_EFAULT;
target_fox->type = tswap32(fox.type);
target_fox->pid = tswap32(fox.pid);
unlock_user_struct(target_fox, arg, 1);
}
break;
#endif
#ifdef F_SETOWN_EX
case TARGET_F_SETOWN_EX:
if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
return -TARGET_EFAULT;
fox.type = tswap32(target_fox->type);
fox.pid = tswap32(target_fox->pid);
unlock_user_struct(target_fox, arg, 0);
ret = get_errno(fcntl(fd, host_cmd, &fox));
break;
#endif
case TARGET_F_SETOWN:
case TARGET_F_GETOWN:
case TARGET_F_SETSIG:
@@ -5993,7 +6034,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
{
sigset_t cur_set;
abi_ulong target_set;
sigprocmask(0, NULL, &cur_set);
do_sigprocmask(0, NULL, &cur_set);
host_to_target_old_sigset(&target_set, &cur_set);
ret = target_set;
}
@@ -6004,10 +6045,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
{
sigset_t set, oset, cur_set;
abi_ulong target_set = arg1;
sigprocmask(0, NULL, &cur_set);
do_sigprocmask(0, NULL, &cur_set);
target_to_host_old_sigset(&set, &target_set);
sigorset(&set, &set, &cur_set);
sigprocmask(SIG_SETMASK, &set, &oset);
do_sigprocmask(SIG_SETMASK, &set, &oset);
host_to_target_old_sigset(&target_set, &oset);
ret = target_set;
}
@@ -6038,7 +6079,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
mask = arg2;
target_to_host_old_sigset(&set, &mask);
ret = get_errno(sigprocmask(how, &set, &oldset));
ret = get_errno(do_sigprocmask(how, &set, &oldset));
if (!is_error(ret)) {
host_to_target_old_sigset(&mask, &oldset);
ret = mask;
@@ -6072,7 +6113,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
how = 0;
set_ptr = NULL;
}
ret = get_errno(sigprocmask(how, set_ptr, &oldset));
ret = get_errno(do_sigprocmask(how, set_ptr, &oldset));
if (!is_error(ret) && arg3) {
if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
goto efault;
@@ -6112,7 +6153,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
how = 0;
set_ptr = NULL;
}
ret = get_errno(sigprocmask(how, set_ptr, &oldset));
ret = get_errno(do_sigprocmask(how, set_ptr, &oldset));
if (!is_error(ret) && arg3) {
if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
goto efault;
@@ -7641,9 +7682,75 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg1, ret);
break;
case TARGET_NR_capget:
goto unimplemented;
case TARGET_NR_capset:
goto unimplemented;
{
struct target_user_cap_header *target_header;
struct target_user_cap_data *target_data = NULL;
struct __user_cap_header_struct header;
struct __user_cap_data_struct data[2];
struct __user_cap_data_struct *dataptr = NULL;
int i, target_datalen;
int data_items = 1;
if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
goto efault;
}
header.version = tswap32(target_header->version);
header.pid = tswap32(target_header->pid);
if (header.version != _LINUX_CAPABILITY_VERSION) {
/* Version 2 and up takes pointer to two user_data structs */
data_items = 2;
}
target_datalen = sizeof(*target_data) * data_items;
if (arg2) {
if (num == TARGET_NR_capget) {
target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0);
} else {
target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1);
}
if (!target_data) {
unlock_user_struct(target_header, arg1, 0);
goto efault;
}
if (num == TARGET_NR_capset) {
for (i = 0; i < data_items; i++) {
data[i].effective = tswap32(target_data[i].effective);
data[i].permitted = tswap32(target_data[i].permitted);
data[i].inheritable = tswap32(target_data[i].inheritable);
}
}
dataptr = data;
}
if (num == TARGET_NR_capget) {
ret = get_errno(capget(&header, dataptr));
} else {
ret = get_errno(capset(&header, dataptr));
}
/* The kernel always updates version for both capget and capset */
target_header->version = tswap32(header.version);
unlock_user_struct(target_header, arg1, 1);
if (arg2) {
if (num == TARGET_NR_capget) {
for (i = 0; i < data_items; i++) {
target_data[i].effective = tswap32(data[i].effective);
target_data[i].permitted = tswap32(data[i].permitted);
target_data[i].inheritable = tswap32(data[i].inheritable);
}
unlock_user(target_data, arg2, target_datalen);
} else {
unlock_user(target_data, arg2, 0);
}
}
break;
}
case TARGET_NR_sigaltstack:
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) || \
@@ -8125,7 +8232,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
mask = arg2;
target_to_host_old_sigset(&set, &mask);
sigprocmask(how, &set, &oldset);
do_sigprocmask(how, &set, &oldset);
host_to_target_old_sigset(&mask, &oldset);
ret = mask;
}
@@ -9148,6 +9255,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_atomic_barrier:
{
/* Like the kernel implementation and the qemu arm barrier, no-op this? */
ret = 0;
break;
}
#endif

View File

@@ -2123,6 +2123,8 @@ struct target_statfs64 {
#define TARGET_F_SETOWN 8 /* for sockets. */
#define TARGET_F_GETOWN 9 /* for sockets. */
#endif
#define TARGET_F_SETOWN_EX 15
#define TARGET_F_GETOWN_EX 16
#ifndef TARGET_F_RDLCK
#define TARGET_F_RDLCK 0
@@ -2305,6 +2307,11 @@ struct target_eabi_flock64 {
} QEMU_PACKED;
#endif
struct target_f_owner_ex {
int type; /* Owner type of ID. */
int pid; /* ID of owner. */
};
/* soundcard defines */
/* XXX: convert them all to arch indepedent entries */
#define TARGET_SNDCTL_COPR_HALT TARGET_IOWR('C', 7, int);
@@ -2559,3 +2566,14 @@ struct target_sigevent {
} _sigev_thread;
} _sigev_un;
};
struct target_user_cap_header {
uint32_t version;
int pid;
};
struct target_user_cap_data {
uint32_t effective;
uint32_t permitted;
uint32_t inheritable;
};

View File

@@ -101,6 +101,7 @@ void qemu_start_incoming_migration(const char *uri, Error **errp)
static void process_incoming_migration_co(void *opaque)
{
QEMUFile *f = opaque;
Error *local_err = NULL;
int ret;
ret = qemu_loadvm_state(f);
@@ -115,7 +116,12 @@ static void process_incoming_migration_co(void *opaque)
bdrv_clear_incoming_migration_all();
/* Make sure all file formats flush their mutable metadata */
bdrv_invalidate_cache_all();
bdrv_invalidate_cache_all(&local_err);
if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
exit(EXIT_FAILURE);
}
if (autostart) {
vm_start();

View File

@@ -1087,7 +1087,7 @@ writev_help(void)
" writes a range of bytes from the given offset source from multiple buffers\n"
"\n"
" Example:\n"
" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
" 'writev 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
"\n"
" Writes into a segment of the currently open file, using a buffer\n"
" filled with a set pattern (0xcdcdcdcd).\n"

View File

@@ -193,10 +193,11 @@ static const cmdinfo_t quit_cmd = {
static void usage(const char *name)
{
printf(
"Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n"
"Usage: %s [-h] [-V] [-rsnm] [-c STRING] ... [file]\n"
"QEMU Disk exerciser\n"
"\n"
" -c, --cmd command to execute\n"
" -c, --cmd STRING execute command with its arguments\n"
" from the given string\n"
" -r, --read-only export read-only\n"
" -s, --snapshot use snapshot file\n"
" -n, --nocache disable host cache\n"
@@ -207,8 +208,10 @@ static void usage(const char *name)
" -T, --trace FILE enable trace events listed in the given file\n"
" -h, --help display this help and exit\n"
" -V, --version output version information and exit\n"
"\n"
"See '%s -c help' for information on available commands."
"\n",
name);
name, name);
}
static char *get_prompt(void)

View File

@@ -1023,10 +1023,23 @@ out:
g_free(type);
}
void object_property_allow_set_link(Object *obj, const char *name,
Object *val, Error **errp)
{
/* Allow the link to be set, always */
}
typedef struct {
Object **child;
void (*check)(Object *, const char *, Object *, Error **);
ObjectPropertyLinkFlags flags;
} LinkProperty;
static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
Object **child = opaque;
LinkProperty *lprop = opaque;
Object **child = lprop->child;
gchar *path;
if (*child) {
@@ -1039,65 +1052,119 @@ static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
}
}
/*
* object_resolve_link:
*
* Lookup an object and ensure its type matches the link property type. This
* is similar to object_resolve_path() except type verification against the
* link property is performed.
*
* Returns: The matched object or NULL on path lookup failures.
*/
static Object *object_resolve_link(Object *obj, const char *name,
const char *path, Error **errp)
{
const char *type;
gchar *target_type;
bool ambiguous = false;
Object *target;
/* Go from link<FOO> to FOO. */
type = object_property_get_type(obj, name, NULL);
target_type = g_strndup(&type[5], strlen(type) - 6);
target = object_resolve_path_type(path, target_type, &ambiguous);
if (ambiguous) {
error_set(errp, QERR_AMBIGUOUS_PATH, path);
} else if (!target) {
target = object_resolve_path(path, &ambiguous);
if (target || ambiguous) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
} else {
error_set(errp, QERR_DEVICE_NOT_FOUND, path);
}
target = NULL;
}
g_free(target_type);
return target;
}
static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
Object **child = opaque;
Object *old_target;
bool ambiguous = false;
const char *type;
char *path;
gchar *target_type;
Error *local_err = NULL;
LinkProperty *prop = opaque;
Object **child = prop->child;
Object *old_target = *child;
Object *new_target = NULL;
char *path = NULL;
type = object_property_get_type(obj, name, NULL);
visit_type_str(v, &path, name, &local_err);
visit_type_str(v, &path, name, errp);
old_target = *child;
*child = NULL;
if (strcmp(path, "") != 0) {
Object *target;
/* Go from link<FOO> to FOO. */
target_type = g_strndup(&type[5], strlen(type) - 6);
target = object_resolve_path_type(path, target_type, &ambiguous);
if (ambiguous) {
error_set(errp, QERR_AMBIGUOUS_PATH, path);
} else if (target) {
object_ref(target);
*child = target;
} else {
target = object_resolve_path(path, &ambiguous);
if (target || ambiguous) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
} else {
error_set(errp, QERR_DEVICE_NOT_FOUND, path);
}
}
g_free(target_type);
if (!local_err && strcmp(path, "") != 0) {
new_target = object_resolve_link(obj, name, path, &local_err);
}
g_free(path);
if (local_err) {
error_propagate(errp, local_err);
return;
}
prop->check(obj, name, new_target, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
if (new_target) {
object_ref(new_target);
}
*child = new_target;
if (old_target != NULL) {
object_unref(old_target);
}
}
static void object_release_link_property(Object *obj, const char *name,
void *opaque)
{
LinkProperty *prop = opaque;
if ((prop->flags & OBJ_PROP_LINK_UNREF_ON_RELEASE) && *prop->child) {
object_unref(*prop->child);
}
g_free(prop);
}
void object_property_add_link(Object *obj, const char *name,
const char *type, Object **child,
void (*check)(Object *, const char *,
Object *, Error **),
ObjectPropertyLinkFlags flags,
Error **errp)
{
Error *local_err = NULL;
LinkProperty *prop = g_malloc(sizeof(*prop));
gchar *full_type;
prop->child = child;
prop->check = check;
prop->flags = flags;
full_type = g_strdup_printf("link<%s>", type);
object_property_add(obj, name, full_type,
object_get_link_property,
object_set_link_property,
NULL, child, errp);
check ? object_set_link_property : NULL,
object_release_link_property,
prop,
&local_err);
if (local_err) {
error_propagate(errp, local_err);
g_free(prop);
}
g_free(full_type);
}

View File

@@ -41,6 +41,9 @@ if [ $cpu != "arm" ] ; then
echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-arm:' > /proc/sys/fs/binfmt_misc/register
echo ':armeb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-armeb:' > /proc/sys/fs/binfmt_misc/register
fi
if [ $cpu != "aarch64" ] ; then
echo ':aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-aarch64:' > /proc/sys/fs/binfmt_misc/register
fi
if [ $cpu != "sparc" ] ; then
echo ':sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-sparc:' > /proc/sys/fs/binfmt_misc/register
fi

View File

@@ -60,6 +60,11 @@ uint32_t HELPER(cls32)(uint32_t x)
return clrsb32(x);
}
uint32_t HELPER(clz32)(uint32_t x)
{
return clz32(x);
}
uint64_t HELPER(rbit64)(uint64_t x)
{
/* assign the correct byte position */
@@ -180,6 +185,36 @@ uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices,
return result;
}
/* Helper function for 64 bit polynomial multiply case:
* perform PolynomialMult(op1, op2) and return either the top or
* bottom half of the 128 bit result.
*/
uint64_t HELPER(neon_pmull_64_lo)(uint64_t op1, uint64_t op2)
{
int bitnum;
uint64_t res = 0;
for (bitnum = 0; bitnum < 64; bitnum++) {
if (op1 & (1ULL << bitnum)) {
res ^= op2 << bitnum;
}
}
return res;
}
uint64_t HELPER(neon_pmull_64_hi)(uint64_t op1, uint64_t op2)
{
int bitnum;
uint64_t res = 0;
/* bit 0 of op1 can't influence the high 64 bits at all */
for (bitnum = 1; bitnum < 64; bitnum++) {
if (op1 & (1ULL << bitnum)) {
res ^= op2 >> (64 - bitnum);
}
}
return res;
}
/* 64bit/double versions of the neon float compare functions */
uint64_t HELPER(neon_ceq_f64)(float64 a, float64 b, void *fpstp)
{
@@ -258,3 +293,146 @@ float64 HELPER(rsqrtsf_f64)(float64 a, float64 b, void *fpstp)
}
return float64_muladd(a, b, float64_three, float_muladd_halve_result, fpst);
}
/* Pairwise long add: add pairs of adjacent elements into
* double-width elements in the result (eg _s8 is an 8x8->16 op)
*/
uint64_t HELPER(neon_addlp_s8)(uint64_t a)
{
uint64_t nsignmask = 0x0080008000800080ULL;
uint64_t wsignmask = 0x8000800080008000ULL;
uint64_t elementmask = 0x00ff00ff00ff00ffULL;
uint64_t tmp1, tmp2;
uint64_t res, signres;
/* Extract odd elements, sign extend each to a 16 bit field */
tmp1 = a & elementmask;
tmp1 ^= nsignmask;
tmp1 |= wsignmask;
tmp1 = (tmp1 - nsignmask) ^ wsignmask;
/* Ditto for the even elements */
tmp2 = (a >> 8) & elementmask;
tmp2 ^= nsignmask;
tmp2 |= wsignmask;
tmp2 = (tmp2 - nsignmask) ^ wsignmask;
/* calculate the result by summing bits 0..14, 16..22, etc,
* and then adjusting the sign bits 15, 23, etc manually.
* This ensures the addition can't overflow the 16 bit field.
*/
signres = (tmp1 ^ tmp2) & wsignmask;
res = (tmp1 & ~wsignmask) + (tmp2 & ~wsignmask);
res ^= signres;
return res;
}
uint64_t HELPER(neon_addlp_u8)(uint64_t a)
{
uint64_t tmp;
tmp = a & 0x00ff00ff00ff00ffULL;
tmp += (a >> 8) & 0x00ff00ff00ff00ffULL;
return tmp;
}
uint64_t HELPER(neon_addlp_s16)(uint64_t a)
{
int32_t reslo, reshi;
reslo = (int32_t)(int16_t)a + (int32_t)(int16_t)(a >> 16);
reshi = (int32_t)(int16_t)(a >> 32) + (int32_t)(int16_t)(a >> 48);
return (uint32_t)reslo | (((uint64_t)reshi) << 32);
}
uint64_t HELPER(neon_addlp_u16)(uint64_t a)
{
uint64_t tmp;
tmp = a & 0x0000ffff0000ffffULL;
tmp += (a >> 16) & 0x0000ffff0000ffffULL;
return tmp;
}
/* Floating-point reciprocal exponent - see FPRecpX in ARM ARM */
float32 HELPER(frecpx_f32)(float32 a, void *fpstp)
{
float_status *fpst = fpstp;
uint32_t val32, sbit;
int32_t exp;
if (float32_is_any_nan(a)) {
float32 nan = a;
if (float32_is_signaling_nan(a)) {
float_raise(float_flag_invalid, fpst);
nan = float32_maybe_silence_nan(a);
}
if (fpst->default_nan_mode) {
nan = float32_default_nan;
}
return nan;
}
val32 = float32_val(a);
sbit = 0x80000000ULL & val32;
exp = extract32(val32, 23, 8);
if (exp == 0) {
return make_float32(sbit | (0xfe << 23));
} else {
return make_float32(sbit | (~exp & 0xff) << 23);
}
}
float64 HELPER(frecpx_f64)(float64 a, void *fpstp)
{
float_status *fpst = fpstp;
uint64_t val64, sbit;
int64_t exp;
if (float64_is_any_nan(a)) {
float64 nan = a;
if (float64_is_signaling_nan(a)) {
float_raise(float_flag_invalid, fpst);
nan = float64_maybe_silence_nan(a);
}
if (fpst->default_nan_mode) {
nan = float64_default_nan;
}
return nan;
}
val64 = float64_val(a);
sbit = 0x8000000000000000ULL & val64;
exp = extract64(float64_val(a), 52, 11);
if (exp == 0) {
return make_float64(sbit | (0x7feULL << 52));
} else {
return make_float64(sbit | (~exp & 0x7ffULL) << 52);
}
}
float32 HELPER(fcvtx_f64_to_f32)(float64 a, CPUARMState *env)
{
/* Von Neumann rounding is implemented by using round-to-zero
* and then setting the LSB of the result if Inexact was raised.
*/
float32 r;
float_status *fpst = &env->vfp.fp_status;
float_status tstat = *fpst;
int exflags;
set_float_rounding_mode(float_round_to_zero, &tstat);
set_float_exception_flags(0, &tstat);
r = float64_to_float32(a, &tstat);
r = float32_maybe_silence_nan(r);
exflags = get_float_exception_flags(&tstat);
if (exflags & float_flag_inexact) {
r = make_float32(float32_val(r) | 1);
}
exflags |= get_float_exception_flags(fpst);
set_float_exception_flags(exflags, fpst);
return r;
}

View File

@@ -21,12 +21,15 @@ DEF_HELPER_FLAGS_2(sdiv64, TCG_CALL_NO_RWG_SE, s64, s64, s64)
DEF_HELPER_FLAGS_1(clz64, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_1(cls64, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_1(cls32, TCG_CALL_NO_RWG_SE, i32, i32)
DEF_HELPER_FLAGS_1(clz32, TCG_CALL_NO_RWG_SE, i32, i32)
DEF_HELPER_FLAGS_1(rbit64, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
DEF_HELPER_3(vfp_cmpes_a64, i64, f32, f32, ptr)
DEF_HELPER_3(vfp_cmpd_a64, i64, f64, f64, ptr)
DEF_HELPER_3(vfp_cmped_a64, i64, f64, f64, ptr)
DEF_HELPER_FLAGS_5(simd_tbl, TCG_CALL_NO_RWG_SE, i64, env, i64, i64, i32, i32)
DEF_HELPER_FLAGS_2(neon_pmull_64_lo, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(neon_pmull_64_hi, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_3(vfp_mulxs, TCG_CALL_NO_RWG, f32, f32, f32, ptr)
DEF_HELPER_FLAGS_3(vfp_mulxd, TCG_CALL_NO_RWG, f64, f64, f64, ptr)
DEF_HELPER_FLAGS_3(neon_ceq_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr)
@@ -36,3 +39,10 @@ DEF_HELPER_FLAGS_3(recpsf_f32, TCG_CALL_NO_RWG, f32, f32, f32, ptr)
DEF_HELPER_FLAGS_3(recpsf_f64, TCG_CALL_NO_RWG, f64, f64, f64, ptr)
DEF_HELPER_FLAGS_3(rsqrtsf_f32, TCG_CALL_NO_RWG, f32, f32, f32, ptr)
DEF_HELPER_FLAGS_3(rsqrtsf_f64, TCG_CALL_NO_RWG, f64, f64, f64, ptr)
DEF_HELPER_FLAGS_1(neon_addlp_s8, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_1(neon_addlp_u8, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_1(neon_addlp_s16, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_1(neon_addlp_u16, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_2(frecpx_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
DEF_HELPER_FLAGS_2(frecpx_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
DEF_HELPER_FLAGS_2(fcvtx_f64_to_f32, TCG_CALL_NO_RWG, f32, f64, env)

View File

@@ -1983,6 +1983,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
ARMCPRegInfo pmcr = {
.name = "PMCR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 0,
.access = PL0_RW, .resetvalue = cpu->midr & 0xff000000,
.type = ARM_CP_IO,
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
.accessfn = pmreg_access, .writefn = pmcr_write,
.raw_writefn = raw_write,
@@ -4519,16 +4520,21 @@ float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
* int->float conversions at run-time. */
#define float64_256 make_float64(0x4070000000000000LL)
#define float64_512 make_float64(0x4080000000000000LL)
#define float32_maxnorm make_float32(0x7f7fffff)
#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
/* The algorithm that must be used to calculate the estimate
* is specified by the ARM ARM.
/* Reciprocal functions
*
* The algorithm that must be used to calculate the estimate
* is specified by the ARM ARM, see FPRecipEstimate()
*/
static float64 recip_estimate(float64 a, CPUARMState *env)
static float64 recip_estimate(float64 a, float_status *real_fp_status)
{
/* These calculations mustn't set any fp exception flags,
* so we use a local copy of the fp_status.
*/
float_status dummy_status = env->vfp.standard_fp_status;
float_status dummy_status = *real_fp_status;
float_status *s = &dummy_status;
/* q = (int)(a * 512.0) */
float64 q = float64_mul(float64_512, a, s);
@@ -4549,56 +4555,178 @@ static float64 recip_estimate(float64 a, CPUARMState *env)
return float64_div(int64_to_float64(q_int, s), float64_256, s);
}
float32 HELPER(recpe_f32)(float32 a, CPUARMState *env)
/* Common wrapper to call recip_estimate */
static float64 call_recip_estimate(float64 num, int off, float_status *fpst)
{
float_status *s = &env->vfp.standard_fp_status;
float64 f64;
uint32_t val32 = float32_val(a);
uint64_t val64 = float64_val(num);
uint64_t frac = extract64(val64, 0, 52);
int64_t exp = extract64(val64, 52, 11);
uint64_t sbit;
float64 scaled, estimate;
int result_exp;
int a_exp = (val32 & 0x7f800000) >> 23;
int sign = val32 & 0x80000000;
if (float32_is_any_nan(a)) {
if (float32_is_signaling_nan(a)) {
float_raise(float_flag_invalid, s);
/* Generate the scaled number for the estimate function */
if (exp == 0) {
if (extract64(frac, 51, 1) == 0) {
exp = -1;
frac = extract64(frac, 0, 50) << 2;
} else {
frac = extract64(frac, 0, 51) << 1;
}
return float32_default_nan;
} else if (float32_is_infinity(a)) {
return float32_set_sign(float32_zero, float32_is_neg(a));
} else if (float32_is_zero_or_denormal(a)) {
if (!float32_is_zero(a)) {
float_raise(float_flag_input_denormal, s);
}
float_raise(float_flag_divbyzero, s);
return float32_set_sign(float32_infinity, float32_is_neg(a));
} else if (a_exp >= 253) {
float_raise(float_flag_underflow, s);
return float32_set_sign(float32_zero, float32_is_neg(a));
}
f64 = make_float64((0x3feULL << 52)
| ((int64_t)(val32 & 0x7fffff) << 29));
/* scaled = '0' : '01111111110' : fraction<51:44> : Zeros(44); */
scaled = make_float64((0x3feULL << 52)
| extract64(frac, 44, 8) << 44);
result_exp = 253 - a_exp;
estimate = recip_estimate(scaled, fpst);
f64 = recip_estimate(f64, env);
/* Build new result */
val64 = float64_val(estimate);
sbit = 0x8000000000000000ULL & val64;
exp = off - exp;
frac = extract64(val64, 0, 52);
val32 = sign
| ((result_exp & 0xff) << 23)
| ((float64_val(f64) >> 29) & 0x7fffff);
return make_float32(val32);
if (exp == 0) {
frac = 1ULL << 51 | extract64(frac, 1, 51);
} else if (exp == -1) {
frac = 1ULL << 50 | extract64(frac, 2, 50);
exp = 0;
}
return make_float64(sbit | (exp << 52) | frac);
}
static bool round_to_inf(float_status *fpst, bool sign_bit)
{
switch (fpst->float_rounding_mode) {
case float_round_nearest_even: /* Round to Nearest */
return true;
case float_round_up: /* Round to +Inf */
return !sign_bit;
case float_round_down: /* Round to -Inf */
return sign_bit;
case float_round_to_zero: /* Round to Zero */
return false;
}
g_assert_not_reached();
}
float32 HELPER(recpe_f32)(float32 input, void *fpstp)
{
float_status *fpst = fpstp;
float32 f32 = float32_squash_input_denormal(input, fpst);
uint32_t f32_val = float32_val(f32);
uint32_t f32_sbit = 0x80000000ULL & f32_val;
int32_t f32_exp = extract32(f32_val, 23, 8);
uint32_t f32_frac = extract32(f32_val, 0, 23);
float64 f64, r64;
uint64_t r64_val;
int64_t r64_exp;
uint64_t r64_frac;
if (float32_is_any_nan(f32)) {
float32 nan = f32;
if (float32_is_signaling_nan(f32)) {
float_raise(float_flag_invalid, fpst);
nan = float32_maybe_silence_nan(f32);
}
if (fpst->default_nan_mode) {
nan = float32_default_nan;
}
return nan;
} else if (float32_is_infinity(f32)) {
return float32_set_sign(float32_zero, float32_is_neg(f32));
} else if (float32_is_zero(f32)) {
float_raise(float_flag_divbyzero, fpst);
return float32_set_sign(float32_infinity, float32_is_neg(f32));
} else if ((f32_val & ~(1ULL << 31)) < (1ULL << 21)) {
/* Abs(value) < 2.0^-128 */
float_raise(float_flag_overflow | float_flag_inexact, fpst);
if (round_to_inf(fpst, f32_sbit)) {
return float32_set_sign(float32_infinity, float32_is_neg(f32));
} else {
return float32_set_sign(float32_maxnorm, float32_is_neg(f32));
}
} else if (f32_exp >= 253 && fpst->flush_to_zero) {
float_raise(float_flag_underflow, fpst);
return float32_set_sign(float32_zero, float32_is_neg(f32));
}
f64 = make_float64(((int64_t)(f32_exp) << 52) | (int64_t)(f32_frac) << 29);
r64 = call_recip_estimate(f64, 253, fpst);
r64_val = float64_val(r64);
r64_exp = extract64(r64_val, 52, 11);
r64_frac = extract64(r64_val, 0, 52);
/* result = sign : result_exp<7:0> : fraction<51:29>; */
return make_float32(f32_sbit |
(r64_exp & 0xff) << 23 |
extract64(r64_frac, 29, 24));
}
float64 HELPER(recpe_f64)(float64 input, void *fpstp)
{
float_status *fpst = fpstp;
float64 f64 = float64_squash_input_denormal(input, fpst);
uint64_t f64_val = float64_val(f64);
uint64_t f64_sbit = 0x8000000000000000ULL & f64_val;
int64_t f64_exp = extract64(f64_val, 52, 11);
float64 r64;
uint64_t r64_val;
int64_t r64_exp;
uint64_t r64_frac;
/* Deal with any special cases */
if (float64_is_any_nan(f64)) {
float64 nan = f64;
if (float64_is_signaling_nan(f64)) {
float_raise(float_flag_invalid, fpst);
nan = float64_maybe_silence_nan(f64);
}
if (fpst->default_nan_mode) {
nan = float64_default_nan;
}
return nan;
} else if (float64_is_infinity(f64)) {
return float64_set_sign(float64_zero, float64_is_neg(f64));
} else if (float64_is_zero(f64)) {
float_raise(float_flag_divbyzero, fpst);
return float64_set_sign(float64_infinity, float64_is_neg(f64));
} else if ((f64_val & ~(1ULL << 63)) < (1ULL << 50)) {
/* Abs(value) < 2.0^-1024 */
float_raise(float_flag_overflow | float_flag_inexact, fpst);
if (round_to_inf(fpst, f64_sbit)) {
return float64_set_sign(float64_infinity, float64_is_neg(f64));
} else {
return float64_set_sign(float64_maxnorm, float64_is_neg(f64));
}
} else if (f64_exp >= 1023 && fpst->flush_to_zero) {
float_raise(float_flag_underflow, fpst);
return float64_set_sign(float64_zero, float64_is_neg(f64));
}
r64 = call_recip_estimate(f64, 2045, fpst);
r64_val = float64_val(r64);
r64_exp = extract64(r64_val, 52, 11);
r64_frac = extract64(r64_val, 0, 52);
/* result = sign : result_exp<10:0> : fraction<51:0> */
return make_float64(f64_sbit |
((r64_exp & 0x7ff) << 52) |
r64_frac);
}
/* The algorithm that must be used to calculate the estimate
* is specified by the ARM ARM.
*/
static float64 recip_sqrt_estimate(float64 a, CPUARMState *env)
static float64 recip_sqrt_estimate(float64 a, float_status *real_fp_status)
{
/* These calculations mustn't set any fp exception flags,
* so we use a local copy of the fp_status.
*/
float_status dummy_status = env->vfp.standard_fp_status;
float_status dummy_status = *real_fp_status;
float_status *s = &dummy_status;
float64 q;
int64_t q_int;
@@ -4645,49 +4773,64 @@ static float64 recip_sqrt_estimate(float64 a, CPUARMState *env)
return float64_div(int64_to_float64(q_int, s), float64_256, s);
}
float32 HELPER(rsqrte_f32)(float32 a, CPUARMState *env)
float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
{
float_status *s = &env->vfp.standard_fp_status;
float_status *s = fpstp;
float32 f32 = float32_squash_input_denormal(input, s);
uint32_t val = float32_val(f32);
uint32_t f32_sbit = 0x80000000 & val;
int32_t f32_exp = extract32(val, 23, 8);
uint32_t f32_frac = extract32(val, 0, 23);
uint64_t f64_frac;
uint64_t val64;
int result_exp;
float64 f64;
uint32_t val;
uint64_t val64;
val = float32_val(a);
if (float32_is_any_nan(a)) {
if (float32_is_signaling_nan(a)) {
if (float32_is_any_nan(f32)) {
float32 nan = f32;
if (float32_is_signaling_nan(f32)) {
float_raise(float_flag_invalid, s);
nan = float32_maybe_silence_nan(f32);
}
return float32_default_nan;
} else if (float32_is_zero_or_denormal(a)) {
if (!float32_is_zero(a)) {
float_raise(float_flag_input_denormal, s);
if (s->default_nan_mode) {
nan = float32_default_nan;
}
return nan;
} else if (float32_is_zero(f32)) {
float_raise(float_flag_divbyzero, s);
return float32_set_sign(float32_infinity, float32_is_neg(a));
} else if (float32_is_neg(a)) {
return float32_set_sign(float32_infinity, float32_is_neg(f32));
} else if (float32_is_neg(f32)) {
float_raise(float_flag_invalid, s);
return float32_default_nan;
} else if (float32_is_infinity(a)) {
} else if (float32_is_infinity(f32)) {
return float32_zero;
}
/* Normalize to a double-precision value between 0.25 and 1.0,
/* Scale and normalize to a double-precision value between 0.25 and 1.0,
* preserving the parity of the exponent. */
if ((val & 0x800000) == 0) {
f64 = make_float64(((uint64_t)(val & 0x80000000) << 32)
| (0x3feULL << 52)
| ((uint64_t)(val & 0x7fffff) << 29));
} else {
f64 = make_float64(((uint64_t)(val & 0x80000000) << 32)
| (0x3fdULL << 52)
| ((uint64_t)(val & 0x7fffff) << 29));
f64_frac = ((uint64_t) f32_frac) << 29;
if (f32_exp == 0) {
while (extract64(f64_frac, 51, 1) == 0) {
f64_frac = f64_frac << 1;
f32_exp = f32_exp-1;
}
f64_frac = extract64(f64_frac, 0, 51) << 1;
}
result_exp = (380 - ((val & 0x7f800000) >> 23)) / 2;
if (extract64(f32_exp, 0, 1) == 0) {
f64 = make_float64(((uint64_t) f32_sbit) << 32
| (0x3feULL << 52)
| f64_frac);
} else {
f64 = make_float64(((uint64_t) f32_sbit) << 32
| (0x3fdULL << 52)
| f64_frac);
}
f64 = recip_sqrt_estimate(f64, env);
result_exp = (380 - f32_exp) / 2;
f64 = recip_sqrt_estimate(f64, s);
val64 = float64_val(f64);
@@ -4696,8 +4839,72 @@ float32 HELPER(rsqrte_f32)(float32 a, CPUARMState *env)
return make_float32(val);
}
uint32_t HELPER(recpe_u32)(uint32_t a, CPUARMState *env)
float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
{
float_status *s = fpstp;
float64 f64 = float64_squash_input_denormal(input, s);
uint64_t val = float64_val(f64);
uint64_t f64_sbit = 0x8000000000000000ULL & val;
int64_t f64_exp = extract64(val, 52, 11);
uint64_t f64_frac = extract64(val, 0, 52);
int64_t result_exp;
uint64_t result_frac;
if (float64_is_any_nan(f64)) {
float64 nan = f64;
if (float64_is_signaling_nan(f64)) {
float_raise(float_flag_invalid, s);
nan = float64_maybe_silence_nan(f64);
}
if (s->default_nan_mode) {
nan = float64_default_nan;
}
return nan;
} else if (float64_is_zero(f64)) {
float_raise(float_flag_divbyzero, s);
return float64_set_sign(float64_infinity, float64_is_neg(f64));
} else if (float64_is_neg(f64)) {
float_raise(float_flag_invalid, s);
return float64_default_nan;
} else if (float64_is_infinity(f64)) {
return float64_zero;
}
/* Scale and normalize to a double-precision value between 0.25 and 1.0,
* preserving the parity of the exponent. */
if (f64_exp == 0) {
while (extract64(f64_frac, 51, 1) == 0) {
f64_frac = f64_frac << 1;
f64_exp = f64_exp - 1;
}
f64_frac = extract64(f64_frac, 0, 51) << 1;
}
if (extract64(f64_exp, 0, 1) == 0) {
f64 = make_float64(f64_sbit
| (0x3feULL << 52)
| f64_frac);
} else {
f64 = make_float64(f64_sbit
| (0x3fdULL << 52)
| f64_frac);
}
result_exp = (3068 - f64_exp) / 2;
f64 = recip_sqrt_estimate(f64, s);
result_frac = extract64(float64_val(f64), 0, 52);
return make_float64(f64_sbit |
((result_exp & 0x7ff) << 52) |
result_frac);
}
uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
{
float_status *s = fpstp;
float64 f64;
if ((a & 0x80000000) == 0) {
@@ -4707,13 +4914,14 @@ uint32_t HELPER(recpe_u32)(uint32_t a, CPUARMState *env)
f64 = make_float64((0x3feULL << 52)
| ((int64_t)(a & 0x7fffffff) << 21));
f64 = recip_estimate (f64, env);
f64 = recip_estimate(f64, s);
return 0x80000000 | ((float64_val(f64) >> 21) & 0x7fffffff);
}
uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUARMState *env)
uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
{
float_status *fpst = fpstp;
float64 f64;
if ((a & 0xc0000000) == 0) {
@@ -4728,7 +4936,7 @@ uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUARMState *env)
| ((uint64_t)(a & 0x3fffffff) << 22));
}
f64 = recip_sqrt_estimate(f64, env);
f64 = recip_sqrt_estimate(f64, fpst);
return 0x80000000 | ((float64_val(f64) >> 21) & 0x7fffffff);
}

View File

@@ -167,10 +167,12 @@ DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
DEF_HELPER_3(recps_f32, f32, f32, f32, env)
DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
DEF_HELPER_2(recpe_f32, f32, f32, env)
DEF_HELPER_2(rsqrte_f32, f32, f32, env)
DEF_HELPER_2(recpe_u32, i32, i32, env)
DEF_HELPER_2(rsqrte_u32, i32, i32, env)
DEF_HELPER_FLAGS_2(recpe_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
DEF_HELPER_FLAGS_2(rsqrte_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
DEF_HELPER_FLAGS_2(rsqrte_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
DEF_HELPER_2(recpe_u32, i32, i32, ptr)
DEF_HELPER_FLAGS_2(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32, ptr)
DEF_HELPER_5(neon_tbl, i32, env, i32, i32, i32, i32)
DEF_HELPER_3(shl_cc, i32, env, i32, i32)
@@ -184,12 +186,20 @@ DEF_HELPER_FLAGS_2(rints, TCG_CALL_NO_RWG, f32, f32, ptr)
DEF_HELPER_FLAGS_2(rintd, TCG_CALL_NO_RWG, f64, f64, ptr)
/* neon_helper.c */
DEF_HELPER_3(neon_qadd_u8, i32, env, i32, i32)
DEF_HELPER_3(neon_qadd_s8, i32, env, i32, i32)
DEF_HELPER_3(neon_qadd_u16, i32, env, i32, i32)
DEF_HELPER_3(neon_qadd_s16, i32, env, i32, i32)
DEF_HELPER_3(neon_qadd_u32, i32, env, i32, i32)
DEF_HELPER_3(neon_qadd_s32, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(neon_qadd_u8, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(neon_qadd_s8, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(neon_qadd_u16, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(neon_qadd_s16, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(neon_qadd_u32, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(neon_qadd_s32, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(neon_uqadd_s8, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(neon_uqadd_s16, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(neon_uqadd_s32, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(neon_uqadd_s64, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_FLAGS_3(neon_sqadd_u8, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(neon_sqadd_u16, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(neon_sqadd_u32, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(neon_sqadd_u64, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_3(neon_qsub_u8, i32, env, i32, i32)
DEF_HELPER_3(neon_qsub_s8, i32, env, i32, i32)
DEF_HELPER_3(neon_qsub_u16, i32, env, i32, i32)
@@ -373,12 +383,14 @@ DEF_HELPER_2(neon_mull_s16, i64, i32, i32)
DEF_HELPER_1(neon_negl_u16, i64, i64)
DEF_HELPER_1(neon_negl_u32, i64, i64)
DEF_HELPER_2(neon_qabs_s8, i32, env, i32)
DEF_HELPER_2(neon_qabs_s16, i32, env, i32)
DEF_HELPER_2(neon_qabs_s32, i32, env, i32)
DEF_HELPER_2(neon_qneg_s8, i32, env, i32)
DEF_HELPER_2(neon_qneg_s16, i32, env, i32)
DEF_HELPER_2(neon_qneg_s32, i32, env, i32)
DEF_HELPER_FLAGS_2(neon_qabs_s8, TCG_CALL_NO_RWG, i32, env, i32)
DEF_HELPER_FLAGS_2(neon_qabs_s16, TCG_CALL_NO_RWG, i32, env, i32)
DEF_HELPER_FLAGS_2(neon_qabs_s32, TCG_CALL_NO_RWG, i32, env, i32)
DEF_HELPER_FLAGS_2(neon_qabs_s64, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_2(neon_qneg_s8, TCG_CALL_NO_RWG, i32, env, i32)
DEF_HELPER_FLAGS_2(neon_qneg_s16, TCG_CALL_NO_RWG, i32, env, i32)
DEF_HELPER_FLAGS_2(neon_qneg_s32, TCG_CALL_NO_RWG, i32, env, i32)
DEF_HELPER_FLAGS_2(neon_qneg_s64, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_3(neon_abd_f32, i32, i32, i32, ptr)
DEF_HELPER_3(neon_ceq_f32, i32, i32, i32, ptr)

View File

@@ -236,6 +236,171 @@ uint64_t HELPER(neon_qadd_s64)(CPUARMState *env, uint64_t src1, uint64_t src2)
return res;
}
/* Unsigned saturating accumulate of signed value
*
* Op1/Rn is treated as signed
* Op2/Rd is treated as unsigned
*
* Explicit casting is used to ensure the correct sign extension of
* inputs. The result is treated as a unsigned value and saturated as such.
*
* We use a macro for the 8/16 bit cases which expects signed integers of va,
* vb, and vr for interim calculation and an unsigned 32 bit result value r.
*/
#define USATACC(bits, shift) \
do { \
va = sextract32(a, shift, bits); \
vb = extract32(b, shift, bits); \
vr = va + vb; \
if (vr > UINT##bits##_MAX) { \
SET_QC(); \
vr = UINT##bits##_MAX; \
} else if (vr < 0) { \
SET_QC(); \
vr = 0; \
} \
r = deposit32(r, shift, bits, vr); \
} while (0)
uint32_t HELPER(neon_uqadd_s8)(CPUARMState *env, uint32_t a, uint32_t b)
{
int16_t va, vb, vr;
uint32_t r = 0;
USATACC(8, 0);
USATACC(8, 8);
USATACC(8, 16);
USATACC(8, 24);
return r;
}
uint32_t HELPER(neon_uqadd_s16)(CPUARMState *env, uint32_t a, uint32_t b)
{
int32_t va, vb, vr;
uint64_t r = 0;
USATACC(16, 0);
USATACC(16, 16);
return r;
}
#undef USATACC
uint32_t HELPER(neon_uqadd_s32)(CPUARMState *env, uint32_t a, uint32_t b)
{
int64_t va = (int32_t)a;
int64_t vb = (uint32_t)b;
int64_t vr = va + vb;
if (vr > UINT32_MAX) {
SET_QC();
vr = UINT32_MAX;
} else if (vr < 0) {
SET_QC();
vr = 0;
}
return vr;
}
uint64_t HELPER(neon_uqadd_s64)(CPUARMState *env, uint64_t a, uint64_t b)
{
uint64_t res;
res = a + b;
/* We only need to look at the pattern of SIGN bits to detect
* +ve/-ve saturation
*/
if (~a & b & ~res & SIGNBIT64) {
SET_QC();
res = UINT64_MAX;
} else if (a & ~b & res & SIGNBIT64) {
SET_QC();
res = 0;
}
return res;
}
/* Signed saturating accumulate of unsigned value
*
* Op1/Rn is treated as unsigned
* Op2/Rd is treated as signed
*
* The result is treated as a signed value and saturated as such
*
* We use a macro for the 8/16 bit cases which expects signed integers of va,
* vb, and vr for interim calculation and an unsigned 32 bit result value r.
*/
#define SSATACC(bits, shift) \
do { \
va = extract32(a, shift, bits); \
vb = sextract32(b, shift, bits); \
vr = va + vb; \
if (vr > INT##bits##_MAX) { \
SET_QC(); \
vr = INT##bits##_MAX; \
} else if (vr < INT##bits##_MIN) { \
SET_QC(); \
vr = INT##bits##_MIN; \
} \
r = deposit32(r, shift, bits, vr); \
} while (0)
uint32_t HELPER(neon_sqadd_u8)(CPUARMState *env, uint32_t a, uint32_t b)
{
int16_t va, vb, vr;
uint32_t r = 0;
SSATACC(8, 0);
SSATACC(8, 8);
SSATACC(8, 16);
SSATACC(8, 24);
return r;
}
uint32_t HELPER(neon_sqadd_u16)(CPUARMState *env, uint32_t a, uint32_t b)
{
int32_t va, vb, vr;
uint32_t r = 0;
SSATACC(16, 0);
SSATACC(16, 16);
return r;
}
#undef SSATACC
uint32_t HELPER(neon_sqadd_u32)(CPUARMState *env, uint32_t a, uint32_t b)
{
int64_t res;
int64_t op1 = (uint32_t)a;
int64_t op2 = (int32_t)b;
res = op1 + op2;
if (res > INT32_MAX) {
SET_QC();
res = INT32_MAX;
} else if (res < INT32_MIN) {
SET_QC();
res = INT32_MIN;
}
return res;
}
uint64_t HELPER(neon_sqadd_u64)(CPUARMState *env, uint64_t a, uint64_t b)
{
uint64_t res;
res = a + b;
/* We only need to look at the pattern of SIGN bits to detect an overflow */
if (((a & res)
| (~b & res)
| (a & ~b)) & SIGNBIT64) {
SET_QC();
res = INT64_MAX;
}
return res;
}
#define NEON_USAT(dest, src1, src2, type) do { \
uint32_t tmp = (uint32_t)src1 - (uint32_t)src2; \
if (tmp != (type)tmp) { \
@@ -1776,6 +1941,28 @@ uint32_t HELPER(neon_qneg_s32)(CPUARMState *env, uint32_t x)
return x;
}
uint64_t HELPER(neon_qabs_s64)(CPUARMState *env, uint64_t x)
{
if (x == SIGNBIT64) {
SET_QC();
x = ~SIGNBIT64;
} else if ((int64_t)x < 0) {
x = -x;
}
return x;
}
uint64_t HELPER(neon_qneg_s64)(CPUARMState *env, uint64_t x)
{
if (x == SIGNBIT64) {
SET_QC();
x = ~SIGNBIT64;
} else {
x = -x;
}
return x;
}
/* NEON Float helpers. */
uint32_t HELPER(neon_abd_f32)(uint32_t a, uint32_t b, void *fpstp)
{

File diff suppressed because it is too large Load Diff

View File

@@ -6682,17 +6682,33 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
break;
}
case NEON_2RM_VRECPE:
gen_helper_recpe_u32(tmp, tmp, cpu_env);
{
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
gen_helper_recpe_u32(tmp, tmp, fpstatus);
tcg_temp_free_ptr(fpstatus);
break;
}
case NEON_2RM_VRSQRTE:
gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
{
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
tcg_temp_free_ptr(fpstatus);
break;
}
case NEON_2RM_VRECPE_F:
gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
{
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
tcg_temp_free_ptr(fpstatus);
break;
}
case NEON_2RM_VRSQRTE_F:
gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
{
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
tcg_temp_free_ptr(fpstatus);
break;
}
case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
gen_vfp_sito(0, 1);
break;
@@ -10654,6 +10670,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
dc->cp_regs = cpu->cp_regs;
dc->current_pl = arm_current_pl(env);
dc->features = env->features;
cpu_F0s = tcg_temp_new_i32();
cpu_F1s = tcg_temp_new_i32();

View File

@@ -26,6 +26,7 @@ typedef struct DisasContext {
int aarch64;
int current_pl;
GHashTable *cp_regs;
uint64_t features; /* CPU features bits */
#define TMP_A64_MAX 16
int tmp_a64_count;
TCGv_i64 tmp_a64[TMP_A64_MAX];
@@ -33,6 +34,11 @@ typedef struct DisasContext {
extern TCGv_ptr cpu_env;
static inline int arm_dc_feature(DisasContext *dc, int feature)
{
return (dc->features & (1ULL << feature)) != 0;
}
/* target-specific extra values for is_jmp */
/* These instructions trap after executing, so the A32/T32 decoder must
* defer them until after the conditional execution state has been updated.

View File

@@ -1180,7 +1180,10 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type)
obj = object_new(TYPE_QEMU_CONSOLE);
s = QEMU_CONSOLE(obj);
object_property_add_link(obj, "device", TYPE_DEVICE,
(Object **)&s->device, &local_err);
(Object **)&s->device,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&local_err);
object_property_add_uint32_ptr(obj, "head",
&s->head, &local_err);

6
vl.c
View File

@@ -58,6 +58,7 @@ int main(int argc, char **argv)
#include <glib.h>
#include "qemu/sockets.h"
#include "hw/hw.h"
#include "hw/boards.h"
#include "hw/usb.h"
@@ -103,7 +104,6 @@ int main(int argc, char **argv)
#include "disas/disas.h"
#include "qemu/sockets.h"
#include "slirp/libslirp.h"
@@ -1587,14 +1587,16 @@ static void machine_class_init(ObjectClass *oc, void *data)
int qemu_register_machine(QEMUMachine *m)
{
char *name = g_strconcat(m->name, TYPE_MACHINE_SUFFIX, NULL);
TypeInfo ti = {
.name = g_strconcat(m->name, TYPE_MACHINE_SUFFIX, NULL),
.name = name,
.parent = TYPE_MACHINE,
.class_init = machine_class_init,
.class_data = (void *)m,
};
type_register(&ti);
g_free(name);
return 0;
}