Compare commits

...

432 Commits

Author SHA1 Message Date
Gerd Hoffmann
62232bf484 virtio-gpu/2d: add virtio gpu core code
This patch adds the core code for virtio gpu emulation,
covering 2d support.

Written by Dave Airlie and Gerd Hoffmann.

Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-06-10 11:02:00 +02:00
Gerd Hoffmann
53476e07d2 virtio: update headers, add virtio-gpu (2d)
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-06-10 11:02:00 +02:00
Gerd Hoffmann
220869e12d stdvga: factor out mmio subregion init
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-06-10 11:02:00 +02:00
Gerd Hoffmann
cf45ec6a52 stdvga: pass VGACommonState instead of PCIVGAState
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-06-10 11:01:59 +02:00
Gerd Hoffmann
24cdff7c82 stdvga: fix offset in pci_vga_ioport_read
Simliar to pci_vga_ioport_write.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-06-10 11:01:59 +02:00
Peter Maydell
b0411142f4 Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20150609' into staging
Collected TCG patches

# gpg: Signature made Tue Jun  9 15:06:18 2015 BST using RSA key ID 4DD0279B
# gpg: Good signature from "Richard Henderson <rth7680@gmail.com>"
# gpg:                 aka "Richard Henderson <rth@redhat.com>"
# gpg:                 aka "Richard Henderson <rth@twiddle.net>"

* remotes/rth/tags/pull-tcg-20150609:
  tcg/optimize: rename tcg_constant_folding
  tcg/optimize: fold constant test in tcg_opt_gen_mov
  tcg/optimize: fold temp copies test in tcg_opt_gen_mov
  tcg/optimize: remove opc argument from tcg_opt_gen_mov
  tcg/optimize: remove opc argument from tcg_opt_gen_movi
  tcg: fix dead computation for repeated input arguments
  tcg: fix register allocation with two aliased dead inputs
  tcg: Handle MO_AMASK in tcg_dump_ops
  tcg: Mask TCGMemOp appropriately for indexing

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-09 15:29:34 +01:00
Aurelien Jarno
36e60ef6ac tcg/optimize: rename tcg_constant_folding
The tcg_constant_folding folding ends up doing all the optimizations
(which is a good thing to avoid looping on all ops multiple time), so
make it clear and just rename it tcg_optimize.

Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Message-Id: <1433447607-31184-6-git-send-email-aurelien@aurel32.net>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-06-09 07:00:56 -07:00
Aurelien Jarno
97a79eb70d tcg/optimize: fold constant test in tcg_opt_gen_mov
Most of the calls to tcg_opt_gen_mov are preceeded by a test to check if
the source temp is a constant. Fold that into the tcg_opt_gen_mov
function.

Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Message-Id: <1433495958-9508-1-git-send-email-aurelien@aurel32.net>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-06-09 07:00:56 -07:00
Aurelien Jarno
5365718a9a tcg/optimize: fold temp copies test in tcg_opt_gen_mov
Each call to tcg_opt_gen_mov is preceeded by a test to check if the
source and destination temps are copies. Fold that into the
tcg_opt_gen_mov function.

Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Message-Id: <1433447607-31184-4-git-send-email-aurelien@aurel32.net>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-06-09 07:00:56 -07:00
Aurelien Jarno
8d6a91602e tcg/optimize: remove opc argument from tcg_opt_gen_mov
We can get the opcode using the TCGOp pointer. It needs to be
dereferenced, but it's anyway done a few lines below to write
the new value.

Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Message-Id: <1433447607-31184-3-git-send-email-aurelien@aurel32.net>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-06-09 07:00:56 -07:00
Aurelien Jarno
ebd27391b0 tcg/optimize: remove opc argument from tcg_opt_gen_movi
We can get the opcode using the TCGOp pointer. It needs to be
dereferenced, but it's anyway done a few lines below to write
the new value.

Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Message-Id: <1433447607-31184-2-git-send-email-aurelien@aurel32.net>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-06-09 07:00:56 -07:00
Aurelien Jarno
c19f47bf5e tcg: fix dead computation for repeated input arguments
When the same temp is used twice or more as an input argument to a TCG
instruction, the dead computation code doesn't recognize the second use
as a dead temp. This is because the temp is marked as live in the same
loop where dead inputs are checked.

The fix is to split the loop in two parts. This avoid emitting a move
and using a register for the movcond instruction when used as "move if
true" on x86-64. This might bring more improvements on RISC TCG targets
which don't have outputs aliased to inputs.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Message-Id: <1433447228-29425-3-git-send-email-aurelien@aurel32.net>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-06-09 06:42:27 -07:00
Aurelien Jarno
7e1df267a7 tcg: fix register allocation with two aliased dead inputs
For TCG ops with two outputs registers (add2, sub2, div2, div2u), when
the same input temp is used for the two inputs aliased to the two
outputs, and when these inputs are both dead, the register allocation
code wrongly assigned the same register to the same output.

This happens for example with sub2 t1, t2, t3, t3, t4, t5, when t3 is
not used anymore after the TCG op.  In that case the same register is
used for t1, t2 and t3.

The fix is to look for already allocated aliased input when allocating
a dead aliased input and check that the register is not already
used.

Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Message-Id: <1433447228-29425-2-git-send-email-aurelien@aurel32.net>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-06-09 06:42:27 -07:00
Richard Henderson
59c4b7e8df tcg: Handle MO_AMASK in tcg_dump_ops
Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>
Tested-by: Yongbok Kim <yongbok.kim@imgtec.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-06-09 06:35:53 -07:00
Richard Henderson
2b7ec66f02 tcg: Mask TCGMemOp appropriately for indexing
The addition of MO_AMASK means that places that used inverted masks
need to be changed to use positive masks, and places that failed to
mask the intended bits need updating.

Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>
Tested-by: Yongbok Kim <yongbok.kim@imgtec.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-06-09 06:35:29 -07:00
Peter Maydell
44ee94e486 Merge remote-tracking branch 'remotes/borntraeger/tags/s390x-20150609' into staging
s390x/virtio-ccw: migration and virtio for 2.4

1. Migration fixups
2. virtio 9pfs

# gpg: Signature made Tue Jun  9 09:00:05 2015 BST using RSA key ID B5A61C7C
# gpg: Good signature from "Christian Borntraeger (IBM) <borntraeger@de.ibm.com>"

* remotes/borntraeger/tags/s390x-20150609:
  s390x/migration: add comment about floating point migration
  s390x/kvm: always ignore empty vcpu interrupt state
  virtio-ccw/migration: Migrate config vector for virtio devices
  virtio-ccw: add support for 9pfs

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-09 11:07:41 +01:00
Peter Maydell
b781a60b10 Merge remote-tracking branch 'remotes/armbru/tags/pull-error-2015-06-09' into staging
Error reporting patches

# gpg: Signature made Tue Jun  9 06:42:15 2015 BST using RSA key ID EB918653
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>"
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>"

* remotes/armbru/tags/pull-error-2015-06-09:
  vhost-user: Improve -netdev/netdev_add/-net/... error reporting
  QemuOpts: Convert qemu_opt_foreach() to Error
  QemuOpts: Drop qemu_opt_foreach() parameter abort_on_failure
  blkdebug: Simplify passing of Error through qemu_opts_foreach()
  QemuOpts: Convert qemu_opts_foreach() to Error
  QemuOpts: Drop qemu_opts_foreach() parameter abort_on_failure
  vl: Fail right after first bad -object
  vl: Print -device help at most once
  vl: Report failure to sandbox at most once

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-09 10:05:29 +01:00
Christian Borntraeger
6028ef0757 s390x/migration: add comment about floating point migration
commit 46c804def4 ("s390x: move fpu regs into a subsection
of the vmstate") moved the fprs into a subsection and bumped
the version number. This will allow to not transfer fprs in
the future if necessary. Add a comment to mark the return true
as intentional.

CC: Juan Quintela <quintela@redhat.com>
CC: David Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Message-Id: <1433758884-2997-1-git-send-email-borntraeger@de.ibm.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
2015-06-09 09:54:57 +02:00
Markus Armbruster
8190483196 vhost-user: Improve -netdev/netdev_add/-net/... error reporting
When -netdev vhost-user fails, it first reports a specific error, then
one or more generic ones, like this:

    $ qemu-system-x86_64 -netdev vhost-user,id=foo,chardev=xxx
    qemu-system-x86_64: -netdev vhost-user,id=foo,chardev=xxx: chardev "xxx" not found
    qemu-system-x86_64: -netdev vhost-user,id=foo,chardev=xxx: No suitable chardev found
    qemu-system-x86_64: -netdev vhost-user,id=foo,chardev=xxx: Device 'vhost-user' could not be initialized

With the command line, the messages go to stderr.  In HMP, they go to
the monitor.  In QMP, the last one becomes the error reply, and the
others go to stderr.

Convert net_init_vhost_user() and its helpers to Error.  This
suppresses the unwanted unspecific error messages, and makes the
specific error the QMP error reply.

Cc: Stefan Hajnoczi <stefanha@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2015-06-09 07:40:24 +02:00
Markus Armbruster
71df1d8337 QemuOpts: Convert qemu_opt_foreach() to Error
Retain the function value for now, to permit selective conversion of
its callers.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-06-09 07:40:23 +02:00
Markus Armbruster
1640b200d5 QemuOpts: Drop qemu_opt_foreach() parameter abort_on_failure
When the argument is non-zero, qemu_opt_foreach() stops on callback
returning non-zero, and returns that value.

When the argument is zero, it doesn't stop, and returns the callback's
value from the last iteration.

The two callers that pass zero could just as well pass one:

* qemu_spice_init()'s callback add_channel() either returns zero or
  exit()s.

* config_write_opts()'s callback config_write_opt() always returns
  zero.

Drop the parameter, and always stop.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-06-09 07:40:23 +02:00
Markus Armbruster
8809cfc38e blkdebug: Simplify passing of Error through qemu_opts_foreach()
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: qemu-block@nongnu.org
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: Kevin Wolf <kwolf@redhat.com>
2015-06-09 07:40:23 +02:00
Markus Armbruster
28d0de7a4f QemuOpts: Convert qemu_opts_foreach() to Error
Retain the function value for now, to permit selective conversion of
its callers.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: Kevin Wolf <kwolf@redhat.com>
2015-06-09 07:37:37 +02:00
Markus Armbruster
a4c7367f7d QemuOpts: Drop qemu_opts_foreach() parameter abort_on_failure
When the argument is non-zero, qemu_opts_foreach() stops on callback
returning non-zero, and returns that value.

When the argument is zero, it doesn't stop, and returns the bit-wise
inclusive or of all the return values.  Funky :)

The callers that pass zero could just as well pass one, because their
callbacks can't return anything but zero:

* qemu_add_globals()'s callback qdev_add_one_global()

* qemu_config_write()'s callback config_write_opts()

* main()'s callbacks default_driver_check(), drive_enable_snapshot(),
  vnc_init_func()

Drop the parameter, and always stop.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: Kevin Wolf <kwolf@redhat.com>
2015-06-08 19:33:20 +02:00
Markus Armbruster
8122928a52 vl: Fail right after first bad -object
Failure to create an object with -object is a fatal error.  However,
we delay the actual exit until all -object are processed.  On the one
hand, this permits detection of genuine additional errors.  On the
other hand, it can muddy the waters with uninteresting additional
errors, e.g. when a later -object tries to reference a prior one that
failed.

We generally stop right on the first bad option, so do that for
-object as well.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-06-08 19:33:20 +02:00
Markus Armbruster
8416abb3b0 vl: Print -device help at most once
We print it once for each -device help.  Not helpful.  Stop after the
first one.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-06-08 19:33:20 +02:00
Markus Armbruster
092b21aa7e vl: Report failure to sandbox at most once
It's reported once per -sandbox on.  Stop on the first failure, like
we do for other options.

Not fixed: "-sandbox on -sandbox off" should leave the sandbox off.
It doesn't.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-06-08 19:33:20 +02:00
Peter Maydell
ee09f84e6b Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* KVM error improvement from Laurent
* CONFIG_PARALLEL fix from Mirek
* Atomic/optimized dirty bitmap access from myself and Stefan
* BUILD_DIR convenience/bugfix from Peter C
* Memory leak fix from Shannon
* SMM improvements (though still TCG only) from myself and Gerd, acked by mst

# gpg: Signature made Fri Jun  5 18:45:20 2015 BST using RSA key ID 78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* remotes/bonzini/tags/for-upstream: (62 commits)
  update Linux headers from kvm/next
  atomics: add explicit compiler fence in __atomic memory barriers
  ich9: implement SMI_LOCK
  q35: implement TSEG
  q35: add test for SMRAM.D_LCK
  q35: implement SMRAM.D_LCK
  q35: add config space wmask for SMRAM and ESMRAMC
  q35: fix ESMRAMC default
  q35: implement high SMRAM
  hw/i386: remove smram_update
  target-i386: use memory API to implement SMRAM
  hw/i386: add a separate region that tracks the SMRAME bit
  target-i386: create a separate AddressSpace for each CPU
  vl: run "late" notifiers immediately
  qom: add object_property_add_const_link
  vl: allow full-blown QemuOpts syntax for -global
  pflash_cfi01: add secure property
  pflash_cfi01: change to new-style MMIO accessors
  pflash_cfi01: change big-endian property to BIT type
  target-i386: wake up processors that receive an SMI
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-08 15:57:41 +01:00
Peter Maydell
2e29dd7c44 Merge remote-tracking branch 'remotes/jnsnow/tags/ide-pull-request' into staging
# gpg: Signature made Fri Jun  5 20:59:07 2015 BST using RSA key ID AAFC390E
# gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: FAEB 9711 A12C F475 812F  18F2 88A9 064D 1835 61EB
#      Subkey fingerprint: F9B7 ABDB BCAC DF95 BE76  CBD0 7DEF 8106 AAFC 390E

* remotes/jnsnow/tags/ide-pull-request:
  macio: remove remainder_len DBDMA_io property
  macio: update comment/constants to reflect the new code
  macio: switch pmac_dma_write() over to new offset/len implementation
  macio: switch pmac_dma_read() over to new offset/len implementation
  fdc-test: Test state for existing cases more thoroughly
  fdc: Fix MSR.RQM flag
  fdc: Disentangle phases in fdctrl_read_data()
  fdc: Code cleanup in fdctrl_write_data()
  fdc: Use phase in fdctrl_write_data()
  fdc: Introduce fdctrl->phase
  fdc: Rename fdctrl_set_fifo() to fdctrl_to_result_phase()
  fdc: Rename fdctrl_reset_fifo() to fdctrl_to_command_phase()

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-08 14:07:32 +01:00
Alexander Graf
0daba1f037 machine: Drop use of DEFAULT_RAM_SIZE in help text
As of commit 076b35b5a (machine: add default_ram_size to machine
class) we no longer have a global default ram size, but instead
machine specific defaults.  When invoking qemu --help we don't know
which machine you selected, so we can't tell the user the default RAM
size in the help text anymore now.

Thus I don't see an easy way to expose the default ram size to the
user in the help text.  The easiest option IMHO is to just drop this
piece of information.

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Acked-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Acked-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Message-id: 1433495103-62084-1-git-send-email-agraf@suse.de
[PMM: rewrapped long commit message lines]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-08 13:31:34 +01:00
Markus Armbruster
779cec4d20 monitor: Fix QMP ABI breakage around "id"
Commit 65207c5 accidentally dropped a line of code we need along with
a comment that became wrong then.  This made QMP reject "id":

    {"execute": "system_reset", "id": "1"}
    {"error": {"class": "GenericError", "desc": "QMP input object member 'id' is unexpected"}}

Put the lost line right back, so QMP again accepts and returns "id",
as promised by the ABI:

    {"execute": "system_reset", "id": "1"}
    {"return": {}, "id": "1"}

Reported-by: Fabio Fantoni <fabio.fantoni@m2r.biz>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Don Slutz <dslutz@verizon.com>
Tested-by: Fabio Fantoni <fabio.fantoni@m2r.biz>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
Tested-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1433753070-12632-2-git-send-email-armbru@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-08 12:12:11 +01:00
Paolo Bonzini
24a3142692 update Linux headers from kvm/next
This is kvm.git commit 05ff30bb56c6b3d3000519d6e02ed35678ddae3b.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 19:45:13 +02:00
Paolo Bonzini
3bbf572345 atomics: add explicit compiler fence in __atomic memory barriers
__atomic_thread_fence does not include a compiler barrier; in the
C++11 memory model, fences take effect in combination with other
atomic operations.  GCC implements this by making __atomic_load and
__atomic_store access memory as if the pointer was volatile, and
leaves no trace whatsoever of acquire and release fences in the
compiler's intermediate representation.

In QEMU, we want memory barriers to act on all memory, but at the same
time we would like to use __atomic_thread_fence for portability reasons.
Add compiler barriers manually around the __atomic_thread_fence.

Message-Id: <1433334080-14912-1-git-send-email-pbonzini@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 19:45:13 +02:00
Gerd Hoffmann
11e66a15a0 ich9: implement SMI_LOCK
Add write mask for the smi enable register, so we can disable write
access to certain bits.  Open all bits on reset.  Disable write access
to GBL_SMI_EN when SMI_LOCK (in ich9 lpc pci config space) is set.
Write access to SMI_LOCK itself is disabled too.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 19:45:13 +02:00
Gerd Hoffmann
bafc90bdc5 q35: implement TSEG
TSEG provides larger amounts of SMRAM than the 128 KB available with
legacy SMRAM and high SMRAM.

Route access to tseg into nowhere when enabled, for both cpus and
busmaster dma, and add tseg window to smram region, so cpus can access
it in smm mode.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 19:45:13 +02:00
Gerd Hoffmann
66e2ec2417 q35: add test for SMRAM.D_LCK
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
[Fix compilation of the newly introduced test. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 19:45:09 +02:00
Gerd Hoffmann
68c77acfb1 q35: implement SMRAM.D_LCK
Once the SMRAM.D_LCK bit has been set by the guest several bits in SMRAM
and ESMRAMC become readonly until the next machine reset.  Implement
this by updating the wmask accordingly when the guest sets the lock bit.
As the lock it itself is locked down too we don't need to worry about
the guest clearing the lock bit.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:36:40 +02:00
Gerd Hoffmann
b66a67d751 q35: add config space wmask for SMRAM and ESMRAMC
Not all bits in SMRAM and ESMRAMC can be changed by the guest.
Add wmask defines accordingly and set them in mch_reset().

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:36:39 +02:00
Gerd Hoffmann
7744752402 q35: fix ESMRAMC default
The cache bits in ESMRAMC are hardcoded to 1 (=disabled) according to
the q35 mch specs.  Add and use a define with this default.

While being at it also update the SMRAM default to use the name (no code
change, just makes things a bit more readable).

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:36:39 +02:00
Paolo Bonzini
64130fa4a1 q35: implement high SMRAM
When H_SMRAME is 1, low memory at 0xa0000 is left alone by
SMM, and instead the chipset maps the 0xa0000-0xbffff window at
0xfeda0000-0xfedbffff.  This affects both the "non-SMM" view controlled
by D_OPEN and the SMM view controlled by G_SMRAME, so add two new
MemoryRegions and toggle the enabled/disabled state of all four
in mch_update_smram.

Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:36:39 +02:00
Paolo Bonzini
3de70c0899 hw/i386: remove smram_update
It's easier to inline it now that most of its work is done by the CPU
(rather than the chipset) through /machine/smram and the memory API.

Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:36:39 +02:00
Paolo Bonzini
f809c60512 target-i386: use memory API to implement SMRAM
Remove cpu_smm_register and cpu_smm_update.  Instead, each CPU
address space gets an extra region which is an alias of
/machine/smram.  This extra region is enabled or disabled
as the CPU enters/exits SMM.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:36:39 +02:00
Paolo Bonzini
fe6567d5fd hw/i386: add a separate region that tracks the SMRAME bit
This region is exported at /machine/smram.  It is "empty" if
SMRAME=0 and points to SMRAM if SMRAME=1.  The CPU will
enable/disable it as it enters or exits SMRAM.

While touching nearby code, the existing memory region setup was
slightly inconsistent.  The smram_region is *disabled* in order to open
SMRAM (because the smram_region shows the low VRAM instead of the RAM
at 0xa0000).  Because SMRAM is closed at startup, the smram_region must
be enabled when creating the i440fx or q35 devices.

Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:36:39 +02:00
Paolo Bonzini
2001d0cd6d target-i386: create a separate AddressSpace for each CPU
Different CPUs can be in SMM or not at the same time, thus they
will see different things where the chipset places SMRAM.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:36:39 +02:00
Paolo Bonzini
71cdd1cb91 vl: run "late" notifiers immediately
If a machine_init_done notifier is added late, as part of a hot-plugged
device, run it immediately.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:36:39 +02:00
Paolo Bonzini
fb9e7e334b qom: add object_property_add_const_link
Suggested-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:36:39 +02:00
Paolo Bonzini
3751d7c43f vl: allow full-blown QemuOpts syntax for -global
-global does not work for drivers that have a dot in their name, such as
cfi.pflash01.  This is just a parsing limitation, because such globals
can be declared easily inside a -readconfig file.

To allow this usage, support the full QemuOpts key/value syntax for -global
too, for example "-global driver=cfi.pflash01,property=secure,value=on".
The two formats do not conflict, because the key/value syntax does not have
a period before the first equal sign.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:36:39 +02:00
Paolo Bonzini
f71e42a5c9 pflash_cfi01: add secure property
When this property is set, MMIO accesses are only allowed with the
MEMTXATTRS_SECURE attribute.  This is used for secure access to UEFI
variables stored in flash.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:36:39 +02:00
Paolo Bonzini
5aa113f0a2 pflash_cfi01: change to new-style MMIO accessors
This is a required step to implement read_with_attrs and write_with_attrs.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:36:39 +02:00
Paolo Bonzini
e98094221e pflash_cfi01: change big-endian property to BIT type
Make this consistent with the secure property, added in the next patch.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:36:31 +02:00
Paolo Bonzini
a9bad65d2c target-i386: wake up processors that receive an SMI
An SMI should definitely wake up a processor in halted state!
This lets OVMF boot with SMM on multiprocessor systems, although
it halts very soon after that with a "CpuIndex != BspIndex"
assertion failure.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:01 +02:00
Paolo Bonzini
b4854f1384 target-i386: set G=1 in SMM big real mode selectors
Because the limit field's bits 31:20 is 1, G should be 1.
VMX actually enforces this, let's do it for completeness
in QEMU as well.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:01 +02:00
Paolo Bonzini
9982f74bad target-i386: mask NMIs on entry to SMM
QEMU is not blocking NMIs on entry to SMM.  Implementing this has to
cover a few corner cases, because:

- NMIs can then be enabled by an IRET instruction and there
is no mechanism to _set_ the "NMIs masked" flag on exit from SMM:
"A special case can occur if an SMI handler nests inside an NMI handler
and then another NMI occurs. [...] When the processor enters SMM while
executing an NMI handler, the processor saves the SMRAM state save map
but does not save the attribute to keep NMI interrupts disabled.

- However, there is some hidden state, because "If NMIs were blocked
before the SMI occurred [and no IRET is executed while in SMM], they
are blocked after execution of RSM."  This is represented by the new
HF2_SMM_INSIDE_NMI_MASK bit.  If it is zero, NMIs are _unblocked_
on exit from RSM.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:01 +02:00
Paolo Bonzini
3f7d846486 target-i386: Use correct memory attributes for ioport accesses
In order to do this, stop using the cpu_in*/out* helpers, and instead
access address_space_io directly.

cpu_in* and cpu_out* remain for usage in the monitor, in qtest, and
in Xen.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Paolo Bonzini
b216aa6c0f target-i386: Use correct memory attributes for memory accesses
These include page table walks, SVM accesses and SMM state save accesses.

The bulk of the patch is obtained with

   sed -i 's/\(\<[a-z_]*_phys\(_notdirty\)\?\>(cs\)->as,/x86_\1,/'

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Paolo Bonzini
f794aa4a2f target-i386: introduce cpu_get_mem_attrs
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Victor CLEMENT
d7a0f71d9a icount: print a warning if there is no more deadline in sleep=no mode
While qemu is running in sleep=no mode, a warning will be printed
when no timer deadline is set.
As this mode is intended for getting deterministic virtual time, if no
timer is set on the virtual clock this determinism is broken.

Signed-off-by: Victor CLEMENT <victor.clement@openwide.fr>
Message-Id: <1432912446-9811-4-git-send-email-victor.clement@openwide.fr>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Victor CLEMENT
f1f4b57e88 icount: add sleep parameter to the icount option to set icount_sleep mode
The 'sleep' parameter sets the icount_sleep mode, which is enabled by
default. To disable it, add the 'sleep=no' parameter (or 'nosleep') to the
qemu -icount option.

Signed-off-by: Victor CLEMENT <victor.clement@openwide.fr>
Message-Id: <1432912446-9811-3-git-send-email-victor.clement@openwide.fr>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Victor CLEMENT
5045e9d912 icount: implement a new icount_sleep mode toggleing real-time cpu sleep
When the icount_sleep mode is disabled, the QEMU_VIRTUAL_CLOCK runs at the
maximum possible speed by warping the sleep times of the virtual cpu to the
soonest clock deadline. The virtual clock will be updated only according
the instruction counter.

Signed-off-by: Victor CLEMENT <victor.clement@openwide.fr>
Message-Id: <1432912446-9811-2-git-send-email-victor.clement@openwide.fr>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Paolo Bonzini
ec05ec26f9 memory: use mr->ram_addr in "is this RAM?" assertions
mr->terminates alone doesn't guarantee that we are looking at a RAM region.
mr->ram_addr also has to be checked, in order to distinguish RAM and I/O
regions.

So, do the following:

1) add a new define RAM_ADDR_INVALID, and test it in the assertions
instead of mr->terminates

2) IOMMU regions were not setting mr->ram_addr to a bogus value, initialize
it in the instance_init function so that the new assertions would fire
for IOMMU regions as well.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Stefan Hajnoczi
5f2cb94688 memory: make cpu_physical_memory_sync_dirty_bitmap() fully atomic
The fast path of cpu_physical_memory_sync_dirty_bitmap() directly
manipulates the dirty bitmap.  Use atomic_xchg() to make the
test-and-clear atomic.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <1417519399-3166-7-git-send-email-stefanha@redhat.com>
[Only do xchg on nonzero words. - Paolo]
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Stefan Hajnoczi
03eebc9e32 memory: replace cpu_physical_memory_reset_dirty() with test-and-clear
The cpu_physical_memory_reset_dirty() function is sometimes used
together with cpu_physical_memory_get_dirty().  This is not atomic since
two separate accesses to the dirty memory bitmap are made.

Turn cpu_physical_memory_reset_dirty() and
cpu_physical_memory_clear_dirty_range_type() into the atomic
cpu_physical_memory_test_and_clear_dirty().

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <1417519399-3166-6-git-send-email-stefanha@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Stefan Hajnoczi
20015f72bd migration: move dirty bitmap sync to ram_addr.h
The dirty memory bitmap is managed by ram_addr.h and copied to
migration_bitmap[] periodically during live migration.

Move the code to sync the bitmap to ram_addr.h where related code lives.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <1417519399-3166-5-git-send-email-stefanha@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Stefan Hajnoczi
d114875b9a memory: use atomic ops for setting dirty memory bits
Use set_bit_atomic() and bitmap_set_atomic() so that multiple threads
can dirty memory without race conditions.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <1417519399-3166-4-git-send-email-stefanha@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Stefan Hajnoczi
36546e5b80 bitmap: add atomic test and clear
The new bitmap_test_and_clear_atomic() function clears a range and
returns whether or not the bits were set.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <1417519399-3166-3-git-send-email-stefanha@redhat.com>
[Test before xchg; then a full barrier is needed at the end just like
 in the previous patch.  The barrier can be avoided if we did at least
 one xchg.  - Paolo]
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Stefan Hajnoczi
9f02cfc84b bitmap: add atomic set functions
Use atomic_or() for atomic bitmaps where several threads may set bits at
the same time.  This avoids the race condition between threads loading
an element, bitwise ORing, and then storing the element.

When setting all bits in a word we can avoid atomic ops and instead just
use an smp_mb() at the end.

Most bitmap users don't need atomicity so introduce new functions.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <1417519399-3166-2-git-send-email-stefanha@redhat.com>
[Avoid barrier in the single word case, use full barrier instead of write.
 - Paolo]
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Paolo Bonzini
9460dee4b2 memory: do not touch code dirty bitmap unless TCG is enabled
cpu_physical_memory_set_dirty_lebitmap unconditionally syncs the
DIRTY_MEMORY_CODE bitmap.  This however is unused unless TCG is
enabled.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Paolo Bonzini
e87f7778b6 exec: only check relevant bitmaps for cleanliness
Most of the time, not all bitmaps have to be marked as dirty;
do not do anything if the interesting ones are already dirty.
Previously, any clean bitmap would have cause all the bitmaps to be
marked dirty.

In fact, unless running TCG most of the time bitmap operations need
not be done at all, because memory_region_is_logging returns zero.
In this case, skip the call to cpu_physical_memory_range_includes_clean
altogether as well.

With this patch, cpu_physical_memory_set_dirty_range is called
unconditionally, so there need not be anymore a separate call to
xen_modified_memory.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:10:00 +02:00
Paolo Bonzini
72b47e79ce exec: invert return value of cpu_physical_memory_get_clean, rename
While it is obvious that cpu_physical_memory_get_dirty returns true even if
a single page is dirty, the same is not true for cpu_physical_memory_get_clean;
one would expect that it returns true only if all the pages are clean, but
it actually looks for even one clean page.  (By contrast, the caller of that
function, cpu_physical_memory_range_includes_clean, has a good name).

To clarify, rename the function to cpu_physical_memory_all_dirty and return
true if _all_ the pages are dirty.  This is the opposite of the previous
meaning, because "all are 1" is the same as "not (any is 0)", so we have to
modify cpu_physical_memory_range_includes_clean as well.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
58d2707e87 exec: pass client mask to cpu_physical_memory_set_dirty_range
This cuts in half the cost of bitmap operations (which will become more
expensive when made atomic) during migration on non-VRAM regions.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
fc377bcf61 translate-all: make less of tb_invalidate_phys_page_range depend on is_cpu_write_access
is_cpu_write_access is only set if tb_invalidate_phys_page_range is called
from tb_invalidate_phys_page_fast, and hence from notdirty_mem_write.
However:

- the code bitmap can be built directly in tb_invalidate_phys_page_fast
  (unconditionally, since is_cpu_write_access would always be passed as 1);

- the virtual address is not needed to mark the page as "not containing
  code" (dirty code bitmap = 1), so we can also remove that use of
  is_cpu_write_access.  For calls of tb_invalidate_phys_page_range
  that do not come from notdirty_mem_write, the next call to
  notdirty_mem_write will notice that the page does not contain code
  anymore, and will fix up the TLB entry.

The parameter needs to remain in order to guard accesses to cpu->mem_io_pc.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
9564f52da7 cputlb: remove useless arguments to tlb_unprotect_code_phys, rename
These days modification of the TLB is done in notdirty_mem_write,
so the virtual address and env pointer as unnecessary.

The new name of the function, tlb_unprotect_code, is consistent with
tlb_protect_code.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
358653391b translate-all: remove unnecessary argument to tb_invalidate_phys_range
The is_cpu_write_access argument is always 0, remove it.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
1652b97476 exec: move functions to translate-all.h
Remove them from the sundry exec-all.h header, since they are only used by
the TCG runtime in exec.c and user-exec.c.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
845b6214a3 exec: use memory_region_get_dirty_log_mask to optimize dirty tracking
The memory API can now return the exact set of bitmaps that have to
be tracked.  Use it instead of the in_migration variable.

In the next patches, we will also use it to set only DIRTY_MEMORY_VGA
or DIRTY_MEMORY_MIGRATION if necessary.  This can make a difference
for dataplane, especially after the dirty bitmap is changed to use
more expensive atomic operations.

Of some interest is the change to stl_phys_notdirty.  When migration
was introduced, stl_phys_notdirty was changed to effectively behave
as stl_phys during migration.  In fact, if one looks at the function as it
was in the beginning (commit 8df1cd0, physical memory access functions,
2005-01-28), at the time the dirty bitmap was the equivalent of
DIRTY_MEMORY_CODE nowadays; hence, the function simply should not touch
the dirty code bits.  This patch changes it to do the intended thing.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
49dfcec403 ram_addr: tweaks to xen_modified_memory
Invoke xen_modified_memory from cpu_physical_memory_set_dirty_range_nocode;
it is akin to DIRTY_MEMORY_MIGRATION, so set it together with that bitmap.
The remaining call from invalidate_and_set_dirty's "else" branch will go
away soon.

Second, fix the second argument to the function in the
cpu_physical_memory_set_dirty_lebitmap call site.  That function is only used
by KVM, but it is better to be clean anyway.

Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
1bfbac4ee1 kvm: remove special handling of DIRTY_MEMORY_MIGRATION in the dirty log mask
One recent example is commit 4cc856f (kvm-all: Sync dirty-bitmap from
kvm before kvm destroy the corresponding dirty_bitmap, 2015-04-02).
Another performance problem is that KVM keeps tracking dirty pages
after a failed live migration, which causes bad performance due to
disallowing huge page mapping.

Thanks to the previous patch, KVM can now stop hooking into
log_global_start/stop.  This simplifies the KVM code noticeably.

Reported-by: Wanpeng Li <wanpeng.li@linux.intel.com>
Reported-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
6f6a5ef3e4 memory: include DIRTY_MEMORY_MIGRATION in the dirty log mask
The separate handling of DIRTY_MEMORY_MIGRATION, which does not
call log_start/log_stop callbacks when it changes in a region's
dirty logging mask, has caused several bugs.

One recent example is commit 4cc856f (kvm-all: Sync dirty-bitmap from
kvm before kvm destroy the corresponding dirty_bitmap, 2015-04-02).
Another performance problem is that KVM keeps tracking dirty pages
after a failed live migration, which causes bad performance due to
disallowing huge page mapping.

This patch removes the root cause of the problem by reporting
DIRTY_MEMORY_MIGRATION changes via log_start and log_stop.
Note that we now have to rebuild the FlatView when global dirty
logging is enabled or disabled; this ensures that log_start and
log_stop callbacks are invoked.

This will also be used to make the setting of bitmaps conditional.
In general, this patch lets users of the memory API ignore the
global state of dirty logging if they handle dirty logging
generically per region.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
ea8cb1a8d9 kvm: accept non-mapped memory in kvm_dirty_pages_log_change
It is okay if memory is not mapped into the guest but has dirty logging
enabled.  When this happens, KVM will not do anything and only accesses
from the host will be logged.

This can be triggered by iofuzz.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
677e7805cf memory: track DIRTY_MEMORY_CODE in mr->dirty_log_mask
DIRTY_MEMORY_CODE is only needed for TCG.  By adding it directly to
mr->dirty_log_mask, we avoid testing for TCG everywhere a region is
checked for the enabled/disabled state of dirty logging.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
42af3e3a02 ui/console: remove dpy_gfx_update_dirty
dpy_gfx_update_dirty expects DIRTY_MEMORY_VGA logging to be always on,
but that will not be the case soon.  Because it computes the memory
region on the fly for every update (with memory_region_find), it cannot
enable/disable logging by itself.

We could always treat updates as invalidations if dirty logging is
not enabled, assuming that the board will enable logging on the
RAM region that includes the framebuffer.

However, the function is unused, so just drop it.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
d55d42078b framebuffer: check memory_region_is_logging
framebuffer.c expects DIRTY_MEMORY_VGA logging to be always on, but that
will not be the case soon.  Because framebuffer.c computes the memory
region on the fly for every update (with memory_region_find), it cannot
enable/disable logging by itself.

Instead, always treat updates as invalidations if dirty logging is
not enabled, assuming that the board will enable logging on the
RAM region that includes the framebuffer.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
b2dfd71c48 memory: prepare for multiple bits in the dirty log mask
When the dirty log mask will also cover other bits than DIRTY_MEMORY_VGA,
some listeners may be interested in the overall zero/non-zero value of
the dirty log mask; others may be interested in the value of single bits.

For this reason, always call log_start/log_stop if bits have respectively
appeared or disappeared, and pass the old and new values of the dirty log
mask so that listeners can distinguish the kinds of change.

For example, KVM checks if dirty logging used to be completely disabled
(in log_start) or is now completely disabled (in log_stop).  On the
other hand, Xen has to check manually if DIRTY_MEMORY_VGA changed,
since that is the only bit it cares about.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:59 +02:00
Paolo Bonzini
2d1a35bef0 memory: differentiate memory_region_is_logging and memory_region_get_dirty_log_mask
For now memory regions only track DIRTY_MEMORY_VGA individually, but
this will change soon.  To support this, split memory_region_is_logging
in two functions: one that returns a given bit from dirty_log_mask,
and one that returns the entire mask.  memory_region_is_logging gets an
extra parameter so that the compiler flags misuse.

While VGA-specific users (including the Xen listener!) will want to keep
checking that bit, KVM and vhost check for "any bit except migration"
(because migration is handled via the global start/stop listener
callbacks).

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:58 +02:00
Paolo Bonzini
5299c0f2cf display: add memory_region_sync_dirty_bitmap calls
These are strictly speaking only needed for KVM and Xen, but it's still
nice to be consistent.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:58 +02:00
Paolo Bonzini
74259ae55b display: enable DIRTY_MEMORY_VGA tracking explicitly
This will be required soon by the memory core.

Tested-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:58 +02:00
Paolo Bonzini
086f90e890 g364fb: remove pointless call to memory_region_set_coalescing
Coalescing work on MMIO, not RAM, thus this call has no effect.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:58 +02:00
Paolo Bonzini
dbddac6da0 memory: the only dirty memory flag for users is DIRTY_MEMORY_VGA
DIRTY_MEMORY_MIGRATION is triggered by memory_global_dirty_log_start
and memory_global_dirty_log_stop, so it cannot be used with
memory_region_set_log.

Specify this in the documentation and assert it.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:58 +02:00
Peter Crosthwaite
6b4ad3b28d Makefile.target: set master BUILD_DIR
make can be invoked in the individual build dirs to build an individual
target or just a single file of a target. e.g.

touch translate-all.c
make -C microblazeel-softmmu translate-all.o

There is however a small bug when using the pixman submodule.
config-host.mak will ref BUILD_DIR for the pixman -I CFLAGS:

grep BUILD_DIR config-host.mak
QEMU_CFLAGS=-I$(SRC_PATH)/pixman/pixman -I$(BUILD_DIR)/pixman/pixman ...

This causes a build failure as -I/pixman/pixman (BUILD_DIR=="") will
not be found.

BUILD_DIR is usually set by the top level Makefile. Just lazy-set it in
Makefile.target to the parent directory.

Granted, this will not work if the pixman submodule is not prebuilt,
but it at least means you can do incremental partial builds once you
have done your initial full build (or attempt) from the top level.

The next step would be refactor make infrastructure to rebuild pixman
on a submake like the one above.

Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Message-Id: <1432618686-16077-1-git-send-email-crosthwaite.peter@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:58 +02:00
Paolo Bonzini
db94604b20 exec: optimize phys_page_set_level
phys_page_set_level is writing zeroes to a struct that has just been
filled in by phys_map_node_alloc.  Instead, tell phys_map_node_alloc
whether to fill in the page "as a leaf" or "as a non-leaf".

memcpy is faster than struct assignment, which copies each bitfield
individually.  A compiler bug (https://gcc.gnu.org/PR66391), and
small memcpys like this one are special-cased anyway, and optimized
to a register move, so just use the memcpy.

This cuts the cost of phys_page_set_level from 25% to 5% when
booting qboot.

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:58 +02:00
Fam Zheng
e4afbf4fb4 qemu-nbd: Switch to qemu_set_fd_handler
Achieved by:

- Remembering the server fd with a global variable, in order to access
  it from nbd_client_closed.

- Checking nbd_can_accept() and updating server_fd handler whenever
  client connects or disconnects.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <1432032670-15124-3-git-send-email-famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:58 +02:00
Laurent Vivier
dae02ba55a ppc: add helpful message when KVM fails to start VCPU
On POWER8 systems, KVM checks if VCPU is running on primary threads,
and that secondary threads are offline. If this is not the case,
ioctl() fails with errno set to EBUSY.

QEMU aborts with a non explicit error message:
$ ./qemu-system-ppc64 --nographic -machine pseries,accel=kvm
error: kvm run failed Device or resource busy

To help user to diagnose the problem, this patch adds an informative
error message.

There is no easy way to check if SMT is enabled before starting the VCPU,
and as this case is the only one setting errno to EBUSY, we just check
the errno value to display a message.

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Message-Id: <1431976007-20503-1-git-send-email-lvivier@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:58 +02:00
Miroslav Rezanina
9157eee1b1 Move parallel_hds_isa_init to hw/isa/isa-bus.c
Disabling CONFIG_PARALLEL cause removing parallel_hds_isa_init defined in
parallel.c. This function is called during initialization of some boards so
disabling CONFIG_PARALLEL cause build failure.

This patch moves parallel_hds_isa_init to hw/isa/isa-bus.c so it is included
in case of disabled CONFIG_PARALLEL. Build is successful but qemu will abort
with "Unknown device" error when function is called.

Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
Message-Id: <1431509970-32154-1-git-send-email-mrezanin@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2015-06-05 17:09:58 +02:00
Peter Maydell
00967f4e0b Merge remote-tracking branch 'remotes/agraf/tags/signed-s390-for-upstream' into staging
Patch queue for s390 - 2015-06-05

This time there are a lot of s390x TCG emulation bug fixes - almost all
of them from Aurelien, who returned from nirvana :).

# gpg: Signature made Fri Jun  5 00:39:27 2015 BST using RSA key ID 03FEDC60
# gpg: Good signature from "Alexander Graf <agraf@suse.de>"
# gpg:                 aka "Alexander Graf <alex@csgraf.de>"

* remotes/agraf/tags/signed-s390-for-upstream: (34 commits)
  target-s390x: Only access allocated storage keys
  target-s390x: fix MVC instruction when areas overlap
  target-s390x: use softmmu functions for mvcp/mvcs
  target-s390x: support non current ASC in s390_cpu_handle_mmu_fault
  target-s390x: add a cpu_mmu_idx_to_asc function
  target-s390x: implement high-word facility
  target-s390x: implement load-and-trap facility
  target-s390x: implement miscellaneous-instruction-extensions facility
  target-s390x: implement LPDFR and LNDFR instructions
  target-s390x: implement TRANSLATE EXTENDED instruction
  target-s390x: implement TRANSLATE AND TEST instruction
  target-s390x: implement LOAD FP INTEGER instructions
  target-s390x: move SET DFP ROUNDING MODE to the correct facility
  target-s390x: move STORE CLOCK FAST to the correct facility
  target-s390x: change CHRL and CGHRL format to RIL-b
  target-s390x: fix CLGIT instruction
  target-s390x: fix exception for invalid operation code
  target-s390x: implement LAY and LAEY instructions
  target-s390x: move a few instructions to the correct facility
  target-s390x: detect tininess before rounding for FP operations
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-05 12:04:42 +01:00
Mark Cave-Ayland
0ba98885a0 macio: remove remainder_len DBDMA_io property
Since the block alignment code is now effectively independent of the DMA
implementation, this variable is no longer required and can be removed.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1433455177-21243-5-git-send-email-mark.cave-ayland@ilande.co.uk
Signed-off-by: John Snow <jsnow@redhat.com>
2015-06-04 20:25:39 -04:00
Mark Cave-Ayland
b01d44cd06 macio: update comment/constants to reflect the new code
With the offset/len functions taking care of all of the alignment mapping
in isolation from the DMA tranasaction, many comments are now unnecessary.
Remove these and tidy up a few constants at the same time.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1433455177-21243-4-git-send-email-mark.cave-ayland@ilande.co.uk
Signed-off-by: John Snow <jsnow@redhat.com>
2015-06-04 20:25:39 -04:00
Mark Cave-Ayland
ac58fe7b2c macio: switch pmac_dma_write() over to new offset/len implementation
In particular, this fixes a bug whereby chains of overlapping head/tail chains
would incorrectly write over each other's remainder cache. This is the access
pattern used by OS X/Darwin and fixes an issue with a corrupt Darwin
installation in my local tests.

While we are here, rename the DBDMA_io struct property remainder to
head_remainder for clarification.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1433455177-21243-3-git-send-email-mark.cave-ayland@ilande.co.uk
Signed-off-by: John Snow <jsnow@redhat.com>
2015-06-04 20:25:39 -04:00
Mark Cave-Ayland
0389b8f8c7 macio: switch pmac_dma_read() over to new offset/len implementation
For better handling of unaligned block device accesses.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1433455177-21243-2-git-send-email-mark.cave-ayland@ilande.co.uk
Signed-off-by: John Snow <jsnow@redhat.com>
2015-06-04 20:25:39 -04:00
Alexander Graf
9814fed0af target-s390x: Only access allocated storage keys
We allocate ram_size / PAGE_SIZE storage keys, so we need to make sure that
we only access that many. Unfortunately the code can overrun this array by
one, potentially overwriting unrelated memory.

Fix it by limiting storage keys to their scope.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
2015-06-05 01:38:00 +02:00
Aurelien Jarno
068593deea target-s390x: fix MVC instruction when areas overlap
The MVC instruction and the memmove C funtion do not have the same
semantic when memory areas overlap:

MVC: When the operands overlap, the result is obtained as if the
operands were processed one byte at a time and each result byte were
stored immediately after fetching the necessary operand byte.

memmove: Copying takes place as though the bytes in src are first copied
into a temporary array that does not overlap src or dest, and the bytes
are then copied from the temporary array to dest.

The behaviour is therefore the same when the destination is at a lower
address than the source, but not in the other case. This is actually a
trick for propagating a value to an area. While the current code detects
that and call memset in that case, it only does for 1-byte value. This
trick can and is used for propagating two or more bytes to an area.

In the softmmu case, the call to mvc_fast_memmove is correct as the
above tests verify that source and destination are each within a page,
and both in a different page. The part doing the move 8 bytes by 8 bytes
is wrong and we need to check that if the source and destination
overlap, they do with a distance of minimum 8 bytes before copying 8
bytes at a time.

In the user code, we should check check that the destination is at a
lower address than source or than the end of the source is at a lower
address than the destination before calling memmove. In the opposite
case we fallback to the same code as the softmmu one. Note that l
represents (length - 1).

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:59 +02:00
Aurelien Jarno
a3084e8055 target-s390x: use softmmu functions for mvcp/mvcs
mvcp and mvcs helper get access to the physical memory by a call to
mmu_translate for the virtual to real conversion and then using ldb_phys
and stb_phys to physically access the data. In practice this is quite
slow because it bypasses the QEMU softmmu TLB and because stb_phys calls
try to invalidate the corresponding memory for each access.

Instead use cpu_ldb_{primary,secondary} for the loads and
cpu_stb_{primary,secondary} for the stores. Ideally this should be
further optimized by a call to memcpy, but that already improves the
boot time of a guest by a factor 1.8.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:59 +02:00
Aurelien Jarno
c255ac6012 target-s390x: support non current ASC in s390_cpu_handle_mmu_fault
s390_cpu_handle_mmu_fault currently looks at the current ASC mode
defined in PSW mask instead of the MMU index. This prevent emulating
easily instructions using a specific ASC mode. Fix that by using the
MMU index converted back to ASC using the just added cpu_mmu_idx_to_asc
function.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:59 +02:00
Aurelien Jarno
4decd76d71 target-s390x: add a cpu_mmu_idx_to_asc function
Use constants to define the MMU indexes, and add a function to do
the reverse conversion of cpu_mmu_index.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:59 +02:00
Aurelien Jarno
a1f12d855b target-s390x: implement high-word facility
Besides RISBHG and RISBLG, all high-word instructions are not
implemented. Fix that.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:59 +02:00
Aurelien Jarno
782a847952 target-s390x: implement load-and-trap facility
At the same time move the trap code from op_ct into gen_trap and use it
for all new functions. The value needs to be stored back to register
before the exception, but also before the brcond (as we don't use
temp locals). That's why we can't use wout helper.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:59 +02:00
Aurelien Jarno
375ee58bed target-s390x: implement miscellaneous-instruction-extensions facility
RISBGN is the same as RISBG, but without setting the condition code.
CLT and CLGT are the same as CLRT and CLGRT, but using memory for the
second operand.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:59 +02:00
Aurelien Jarno
df46283ce7 target-s390x: implement LPDFR and LNDFR instructions
This complete the floating point support sign handling facility.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:59 +02:00
Aurelien Jarno
3f4de6756c target-s390x: implement TRANSLATE EXTENDED instruction
It is part of the basic zArchitecture instructions.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:59 +02:00
Aurelien Jarno
54f0077509 target-s390x: implement TRANSLATE AND TEST instruction
It is part of the basic zArchitecture instructions. Allow it to be call
from EXECUTE.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:59 +02:00
Aurelien Jarno
ed0bcecec1 target-s390x: implement LOAD FP INTEGER instructions
This is needed to pass the gcc.c-torture/execute/ieee/20010114-2.c test
in the gcc testsuite.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:59 +02:00
Aurelien Jarno
9182886d79 target-s390x: move SET DFP ROUNDING MODE to the correct facility
It belongs to the DFP rounding facility.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:59 +02:00
Aurelien Jarno
f7c2114067 target-s390x: move STORE CLOCK FAST to the correct facility
STORE CLOCK FAST should be in the SCF facility.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:58 +02:00
Aurelien Jarno
74266b4a58 target-s390x: change CHRL and CGHRL format to RIL-b
Change to match the PoP. In practice both format RIL-a and RIL-b have
the same fields. They differ on the way we decode the fields, and it's
done correctly in QEMU.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:58 +02:00
Aurelien Jarno
1dedb9b76f target-s390x: fix CLGIT instruction
The COMPARE LOGICAL IMMEDIATE AND TRAP instruction should compare the
numbers as unsigned, as its name implies.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:58 +02:00
Aurelien Jarno
111d7f4a69 target-s390x: fix exception for invalid operation code
When an operation code is not recognized (ie invalid instruction) an
operation exception should be generated instead of a specification
exception. The latter is for valid opcode, with invalid operands or
modifiers.

This give a very basic GDB support in the guest, as it uses the invalid
opcode 0x0001 to generate a trap.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:58 +02:00
Aurelien Jarno
a1c7610a68 target-s390x: implement LAY and LAEY instructions
This complete the general-instructions-extension facility, enable it.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
[agraf: remove facility bit]
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:58 +02:00
Aurelien Jarno
92892330e7 target-s390x: move a few instructions to the correct facility
LY is part of the long-displacement facility.
RISBHG and RISBLG are part of the high-word facility.
STCMH is part of the z/Architecture.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:58 +02:00
Aurelien Jarno
4a33565f9f target-s390x: detect tininess before rounding for FP operations
The s390x floating point unit detects tininess before rounding, so set
the softfloat fp_status up appropriately.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:58 +02:00
Aurelien Jarno
f821135cdd target-s390x: silence NaNs for LOAD LENGTHENED and LOAD ROUNDED
LOAD LENGTHENED and LOAD ROUNDED are considered as FP operations and
thus need to convert input sNaN into corresponding qNaN.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:58 +02:00
Aurelien Jarno
2daea9c16f target-s390x: define default NaN values
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:58 +02:00
Aurelien Jarno
1f65958d9c target-s390x: fix MMU index computation
The cpu_mmu_index function wrongly looks at PSW P bit to determine the
MMU index, while this bit actually only control the use of priviledge
instructions. The addressing mode is detected by looking at the PSW ASC
bits instead.

This used to work more or less correctly up to kernel 3.6 as the kernel
was running in primary space and userland in secondary space. Since
kernel 3.7 the default is to run the kernel in home space and userland
in primary space. While the current QEMU code seems to work it open some
security issues, like accessing the lowcore memory in R/W mode from a
userspace process once it has been accessed by the kernel (it is then
cached by the QEMU TLB).

At the same time change the MMU_USER_IDX value so that it matches the
value used in recent kernels.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:58 +02:00
Aurelien Jarno
9bebf9863b target-s390x: fix PSW value on dynamical exception from helpers
runtime_exception computes the psw.addr value using the actual exception
address and the instruction length computed by calling the get_ilen
function. However as explained above the get_ilen code, it returns the
actual instruction length, and not the ILC. Therefore there is no need to
multiply the value by 2.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:58 +02:00
Aurelien Jarno
aa752a4afc target-s390x: fix LOAD MULTIPLE instruction on page boundary
When consecutive memory locations are on page boundary a page fault
might occur when using the LOAD MULTIPLE instruction. In that case real
hardware doesn't load any register.

This is an important detail in case the base register is in the list
of registers to be loaded. If a page fault occurs this register might be
overwritten and when the instruction is later restarted the wrong
base register value is useD.

Fix this by first loading the first and last value from memory, hence
triggering all possible page faults, and then the remaining registers.

This fixes random segmentation faults seen in the guest.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:58 +02:00
Aurelien Jarno
b8ae94bd39 target-s390x: implement STPT helper
Save the timer target value in the SPT helper, so that the STPT helper
can compute the remaining time.

This allow the Linux kernel to correctly do time accounting.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:57 +02:00
Aurelien Jarno
aa9e14e684 target-s390x: implement STCKC helper
The STCKC instruction just returns the last written clock comparator
value and KVM already provides the corresponding variable.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:57 +02:00
Aurelien Jarno
d9d55f1108 target-s390x: streamline STCK helper
Now that clock_value is only used in one place, we can inline it in
the STCK helper.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:57 +02:00
Aurelien Jarno
c941f07485 target-s390x: simplify SCKC helper
The clock comparator and the QEMU timer work the same way, triggering
at a given time, they just differ by the origin and the scale. It is
therefore possible to go from one to another without using the current
clock value. This spares two calls to qemu_clock_get_ns, which probably
return slightly different values, possibly reducing the accuracy.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:57 +02:00
Aurelien Jarno
9cb32c442e target-s390x: add a tod2time function
Add a tod2time function similar to the time2tod one, instead of open
coding the conversion.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:57 +02:00
Aurelien Jarno
a91a1b20a2 target-s390x: remove unused helpers
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:57 +02:00
Aurelien Jarno
d30107814c target-s390x: optimize (negative-) abs computation
Now that movcond exists, it's easy to write (negative-) absolute value
using TCG code instead of an helper.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:57 +02:00
Aurelien Jarno
2aaa194068 target-s390x: fix CC computation for LOAD POSITIVE instructions
LOAD POSITIVE instructions (LPR, LPGR and LPGFR) set the following
condition code:
  0: Result zero; no overflow
  1: --
  2: Result greater than zero; no overflow
  3: Overflow

The current code wrongly returns 1 instead of 2 in case of a result
greater than 0. This patches fixes that. This fixes the marshalling of
the value '0L' in Python.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:57 +02:00
Aurelien Jarno
ee0d0be168 target-s390x: fix CC computation for EX instruction
Commit 7a6c7067f optimized CC computation by only saving cc_op before
calling helpers as they either don't touch the CC or generate a new
static value. This however doesn't work for the EX instruction as the
helper changes or not the CC value depending on the actual executed
instruction (e.g. MVC vs CLC).

This patches force a CC computation before calling the helper. This
fixes random memory corruption occuring in guests.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
[agraf: remove set_cc_static in op_ex as suggested by rth]
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-05 01:37:57 +02:00
Peter Maydell
d6688ba17b Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc, acpi, virtio, tpm

This includes pxb support by Marcel, as well as multiple enhancements all over
the place.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Thu Jun  4 11:51:02 2015 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream: (28 commits)
  vhost: logs sharing
  hw/acpi: piix4_pm_init(): take fw_cfg object no more
  hw/acpi: move "etc/system-states" fw_cfg file from PIIX4 to core
  hw/acpi: acpi_pm1_cnt_init(): take "disable_s3" and "disable_s4"
  pc-dimm: don't assert if pc-dimm alignment != hotpluggable mem range size
  docs: Add PXB documentation
  apci: fix PXB behaviour if used with unsupported BIOS
  hw/pxb: add numa_node parameter
  hw/pci: add support for NUMA nodes
  hw/pxb: add map_irq func
  hw/pci: inform bios if the system has extra pci root buses
  hw/pci: introduce PCI Expander Bridge (PXB)
  hw/pci: removed 'rootbus nr is 0' assumption from qmp_pci_query
  hw/acpi: remove from root bus 0 the crs resources used by other buses.
  hw/acpi: add _CRS method for extra root busses
  hw/apci: add _PRT method for extra PCI root busses
  hw/acpi: add support for i440fx 'snooping' root busses
  hw/pci: extend PCI config access to support devices behind PXB
  hw/i386: query only for q35/pc when looking for pci host bridge
  hw/pci: made pci_bus_num a PCIBusClass method
  ...

Conflicts:
	hw/i386/pc_piix.c

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-04 18:33:24 +01:00
Peter Maydell
3b730f570c Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging
Patch queue for ppc - 2015-06-03

Highlights this time around:

  - sPAPR: endian fixes, speedups, bug fixes, hotplug basics
  - add default ram size capability for machines (sPAPR defaults to 512MB now)

# gpg: Signature made Wed Jun  3 22:59:09 2015 BST using RSA key ID 03FEDC60
# gpg: Good signature from "Alexander Graf <agraf@suse.de>"
# gpg:                 aka "Alexander Graf <alex@csgraf.de>"

* remotes/agraf/tags/signed-ppc-for-upstream: (40 commits)
  softmmu: support up to 12 MMU modes
  tcg: add TCG_TARGET_TLB_DISPLACEMENT_BITS
  tci: do not use CPUArchState in tcg-target.h
  Add David Gibson for sPAPR in MAINTAINERS file
  pseries: Enable in-kernel H_LOGICAL_CI_{LOAD, STORE} implementations
  spapr: override default ram size to 512MB
  machine: add default_ram_size to machine class
  spapr_pci: emit hotplug add/remove events during hotplug
  spapr_pci: enable basic hotplug operations
  pci: make pci_bar useable outside pci.c
  spapr_pci: create DRConnectors for each PCI slot during PHB realize
  spapr_pci: add dynamic-reconfiguration option for spapr-pci-host-bridge
  spapr_drc: add spapr_drc_populate_dt()
  spapr_events: event-scan RTAS interface
  spapr_events: re-use EPOW event infrastructure for hotplug events
  spapr_rtas: add ibm, configure-connector RTAS interface
  spapr: add rtas_st_buffer_direct() helper
  spapr_rtas: add get-sensor-state RTAS interface
  spapr_rtas: add set-indicator RTAS interface
  spapr_rtas: add get/set-power-level RTAS interfaces
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-04 14:04:14 +01:00
Peter Maydell
2700a976db Merge remote-tracking branch 'remotes/mjt/tags/pull-trivial-patches-2015-06-03' into staging
trivial patches for 2015-06-03

# gpg: Signature made Wed Jun  3 14:07:47 2015 BST using RSA key ID A4C3D7DB
# gpg: Good signature from "Michael Tokarev <mjt@tls.msk.ru>"
# gpg:                 aka "Michael Tokarev <mjt@corpit.ru>"
# gpg:                 aka "Michael Tokarev <mjt@debian.org>"

* remotes/mjt/tags/pull-trivial-patches-2015-06-03: (30 commits)
  configure: postfix --extra-cflags to QEMU_CFLAGS
  cadence_gem: Fix Rx buffer size field mask
  slirp: use less predictable directory name in /tmp for smb config (CVE-2015-4037)
  translate-all: delete prototype for non-existent function
  Add -incoming help text
  hw/display/tc6393xb.c: Fix misusing qemu_allocate_irqs for single irq
  hw/arm/nseries.c: Fix misusing qemu_allocate_irqs for single irq
  hw/alpha/typhoon.c: Fix misusing qemu_allocate_irqs for single irq
  hw/unicore32/puv3.c: Fix misusing qemu_allocate_irqs for single irq
  hw/lm32/milkymist.c: Fix misusing qemu_allocate_irqs for single irq
  hw/lm32/lm32_boards.c: Fix misusing qemu_allocate_irqs for single irq
  hw/ppc/prep.c: Fix misusing qemu_allocate_irqs for single irq
  hw/sparc/sun4m.c: Fix misusing qemu_allocate_irqs for single irq
  hw/timer/arm_timer.c: Fix misusing qemu_allocate_irqs for single irq
  hw/isa/i82378.c: Fix misusing qemu_allocate_irqs for single irq
  hw/isa/lpc_ich9.c: Fix misusing qemu_allocate_irqs for single irq
  hw/i386/pc: Fix misusing qemu_allocate_irqs for single irq
  hw/intc/exynos4210_gic.c: Fix memory leak by adjusting order
  hw/arm/omap_sx1.c: Fix memory leak spotted by valgrind
  hw/ppc/e500.c: Fix memory leak
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-04 12:49:15 +01:00
Jason Wang
309750fad5 vhost: logs sharing
Currently we allocate one vhost log per vhost device. This is sub
optimal when:

- Guest has several device with vhost as backend
- Guest has multiqueue devices

In the above cases, we can avoid the memory allocation by sharing a
single vhost log among all the vhost devices. This is done through:

- Introducing a new vhost_log structure with refcnt inside.
- Using a global pointer to vhost_log structure that will be used. And
  introduce helper to get the log with expected log size and helper to
- drop the refcnt to the old log.
- Each vhost device still keep track of a pointer to the log that was
  used.

With above, if no resize happens, all vhost device will share a single
vhost log. During resize, a new vhost_log structure will be allocated
and made for the global pointer. And each vhost devices will drop the
refcnt to the old log.

Tested by doing scp during migration for a 2 queues virtio-net-pci.

Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-04 12:44:49 +02:00
Peter Maydell
6fa6b31276 Merge remote-tracking branch 'remotes/ehabkost/tags/x86-pull-request' into staging
X86 queue 2015-06-02

# gpg: Signature made Tue Jun  2 20:21:17 2015 BST using RSA key ID 984DC5A6
# gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF  D1AA 2807 936F 984D C5A6

* remotes/ehabkost/tags/x86-pull-request:
  arch_init: Drop target-x86_64.conf
  target-i386: Register QOM properties for feature flags
  apic: convert ->busdev.qdev casts to C casts
  target-i386: Fix signedness of MSR_IA32_APICBASE_BASE
  pc: Ensure non-zero CPU ref count after attaching to ICC bus

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-04 11:44:32 +01:00
Laszlo Ersek
6e7d82497d hw/acpi: piix4_pm_init(): take fw_cfg object no more
This PIIX4 init function has no more reason to receive a pointer to the
FwCfg object. Remove the parameter from the prototype, and update callers.

As a result, the pc_init1() function no longer needs to save the return
value of pc_memory_init() and xen_load_linux(), which makes it more
similar to pc_q35_init().

The return type & value of pc_memory_init() and xen_load_linux() are not
changed themselves; maybe we'll need their return values sometime later.

RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1204696
Cc: Amit Shah <amit.shah@redhat.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Leon Alrae <leon.alrae@imgtec.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2015-06-04 11:25:42 +02:00
Laszlo Ersek
e3845e7c47 hw/acpi: move "etc/system-states" fw_cfg file from PIIX4 to core
The acpi_pm1_cnt_init() core function is responsible for setting up the
register block that will ultimately react to S3 and S4 requests (see
acpi_pm1_cnt_write()). It makes sense to advertise this configuration to
the guest firmware via an easy to parse fw_cfg file (ACPI is too complex
for firmware to parse), and indeed PIIX4 does that. However, since
acpi_pm1_cnt_init() is not specific to PIIX4, neither should be the fw_cfg
file.

This patch makes "etc/system-states" appear on all chipsets modified in
the previous patch, not just PIIX4 (assuming they have fw_cfg at all).

RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1204696
Cc: Amit Shah <amit.shah@redhat.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Leon Alrae <leon.alrae@imgtec.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2015-06-04 11:25:42 +02:00
Laszlo Ersek
9a10bbb4e8 hw/acpi: acpi_pm1_cnt_init(): take "disable_s3" and "disable_s4"
This patch only modifies the function prototype and updates all chipset
code that calls acpi_pm1_cnt_init() to pass in their own disable_s3 and
disable_s4 settings. vt82c686 is assumed to be fixed "S3 and S4 enabled".

RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1204696
Cc: Amit Shah <amit.shah@redhat.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Leon Alrae <leon.alrae@imgtec.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
2015-06-04 11:25:42 +02:00
Peter Maydell
d2ceeb1d68 Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20150602' into staging
target-arm queue:
 * more EL2 preparation patches
 * revert a no-longer-necessary workaround for old glib versions
 * add GICv2m support to virt board (MSI support)
 * pl061: fix wrong calculation of GPIOMIS register
 * support MSI via irqfd
 * remove a confusing v8_ prefix from some variable names
 * add dynamic sysbus device support to the virt board

# gpg: Signature made Tue Jun  2 17:30:38 2015 BST using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"

* remotes/pmaydell/tags/pull-target-arm-20150602: (22 commits)
  hw/arm/virt: change indentation in a15memmap
  hw/arm/virt: add dynamic sysbus device support
  hw/arm/boot: arm_load_kernel implemented as a machine init done notifier
  hw/arm/sysbus-fdt: helpers for platform bus nodes addition
  target-arm: Remove v8_ prefix from names of non-v8-specific cpreg arrays
  arm_gicv2m: set kvm_gsi_direct_mapping and kvm_msi_via_irqfd_allowed
  kvm: introduce kvm_arch_msi_data_to_gsi
  pl061: fix wrong calculation of GPIOMIS register
  target-arm: Add the GICv2m to the virt board
  target-arm: Extend the gic node properties
  arm_gicv2m: Add GICv2m widget to support MSIs
  target-arm: Add GIC phandle to VirtBoardInfo
  Revert "target-arm: Avoid g_hash_table_get_keys()"
  target-arm: Add TLBI_VAE2{IS}
  target-arm: Add TLBI_ALLE2
  target-arm: Add TLBI_ALLE1{IS}
  target-arm: Add TTBR0_EL2
  target-arm: Add TPIDR_EL2
  target-arm: Add SCTLR_EL2
  target-arm: Add TCR_EL2
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-04 10:21:52 +01:00
Igor Mammedov
b5d3b03922 pc-dimm: don't assert if pc-dimm alignment != hotpluggable mem range size
Drop superfluous pc-dimm alignment on hot-pluggable mem
range size assert, since it causes QEMU crash during hotplug
when hotplugging pc-dimm with alignment bigger than
an alignment of hot-pluggable mem range size.

Instead allow pc_dimm_get_free_addr() find free address
and bail out gracefully later in that function during
checking if pc-dimm will fit in hot-pluggable mem range.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-04 11:20:34 +02:00
Paolo Bonzini
1de29aef17 softmmu: support up to 12 MMU modes
At 8k per TLB (for 64-bit host or target), 8 or more modes
make the TLBs bigger than 64k, and some RISC TCG backends do
not like that.  On the affected hosts, cut the TLB size in
half---there is still a measurable speedup on PPC with the
next patch.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <1424436345-37924-3-git-send-email-pbonzini@redhat.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:56 +02:00
Paolo Bonzini
006f8638c6 tcg: add TCG_TARGET_TLB_DISPLACEMENT_BITS
This will be used to size the TLB when more than 8 MMU modes are
used by the target.  Limitations come from the limited size of
the immediate fields (which sometimes, as in the case of Aarch64,
extend to instructions that shift the immediate).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <1424436345-37924-2-git-send-email-pbonzini@redhat.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:56 +02:00
Paolo Bonzini
5a58e884d1 tci: do not use CPUArchState in tcg-target.h
tcg-target.h does not use any QEMU-specific symbols, save for tci's usage
of CPUArchState.  Pull that up to tcg/tcg.h.

This will make it possible to include tcg-target.h in cpu-defs.h.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:55 +02:00
David Gibson
085eb217df Add David Gibson for sPAPR in MAINTAINERS file
At Alex Graf's request I'm now acting as sub-maintainer for the sPAPR
(-machine pseries) code.  This updates MAINTAINERS accordingly.

While we're at it, change the label to mention pseries since that's the
actual name of the machine type, even if most of the C files use the sPAPR
name.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:55 +02:00
David Gibson
026bfd89cb pseries: Enable in-kernel H_LOGICAL_CI_{LOAD, STORE} implementations
qemu currently implements the hypercalls H_LOGICAL_CI_LOAD and
H_LOGICAL_CI_STORE as PAPR extensions.  These are used by the SLOF firmware
for IO, because performing cache inhibited MMIO accesses with the MMU off
(real mode) is very awkward on POWER.

This approach breaks when SLOF needs to access IO devices implemented
within KVM instead of in qemu.  The simplest example would be virtio-blk
using an iothread, because the iothread / dataplane mechanism relies on
an in-kernel implementation of the virtio queue notification MMIO.

To fix this, an in-kernel implementation of these hypercalls has been made,
(kernel commit 99342cf "kvmppc: Implement H_LOGICAL_CI_{LOAD,STORE} in KVM"
however, the hypercalls still need to be enabled from qemu.  This performs
the necessary calls to do so.

It would be nice to provide some warning if we encounter a problematic
device with a kernel which doesn't support the new calls.  Unfortunately,
I can't see a way to detect this case which won't either warn in far too
many cases that will probably work, or which is horribly invasive.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:55 +02:00
Nikunj A Dadhania
a34944fe2e spapr: override default ram size to 512MB
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:55 +02:00
Nikunj A Dadhania
076b35b5a5 machine: add default_ram_size to machine class
Machines types can have different requirement for default ram
size. Introduce a member in the machine class and set the current
default_ram_size to 128MB.

For QEMUMachine types override the value during the registration of
the machine and for MachineClass introduce the generic class init
setting the default_ram_size.

Add helpers [K,M,G,T,P,E]_BYTE for better readability and easy usage

Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:55 +02:00
Tyrel Datwyler
c5bc152bc3 spapr_pci: emit hotplug add/remove events during hotplug
This uses extension of existing EPOW interrupt/event mechanism
to notify userspace tools like librtas/drmgr to handle
in-guest configuration/cleanup operations in response to
device_add/device_del.

Userspace tools that don't implement this extension will need
to be run manually in response/advance of device_add/device_del,
respectively.

Signed-off-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:55 +02:00
Michael Roth
7454c7af91 spapr_pci: enable basic hotplug operations
This enables hotplug of PCI devices to a PHB. Upon hotplug we
generate the OF-nodes required by PAPR specification and
IEEE 1275-1994 "PCI Bus Binding to Open Firmware" for the
device.

We associate the corresponding FDT for these nodes with the DRC
corresponding to the slot, which will be fetched via
ibm,configure-connector RTAS calls by the guest as described by PAPR
specification.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:54 +02:00
Michael Roth
cf8c704d5a pci: make pci_bar useable outside pci.c
We need to work with PCI BARs to generate OF properties
during PCI hotplug for sPAPR guests.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:54 +02:00
Michael Roth
62083979b0 spapr_pci: create DRConnectors for each PCI slot during PHB realize
These will be used to support hotplug/unplug of PCI devices to the PCI
bus associated with a particular PHB.

We also set up device-tree properties in each PHBs initial FDT to
describe the DRCs associated with them. This advertises to guests that
each PHB is DR-capable device with physical hotpluggable slots, each
managed by the corresponding DRC. This is necessary for allowing
hotplugging of devices to it later via bus rescan or guest rpaphp
hotplug module.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:54 +02:00
Michael Roth
7619c7b00c spapr_pci: add dynamic-reconfiguration option for spapr-pci-host-bridge
This option enables/disables PCI hotplug for a particular PHB.

Also add machine compatibility code to disable it by default for machine
types prior to pseries-2.4.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
[agraf: move commas for compat fields]
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:54 +02:00
Michael Roth
e4b798bb53 spapr_drc: add spapr_drc_populate_dt()
This function handles generation of ibm,drc-* array device tree
properties to describe DRC topology to guests. This will by used
by the guest to direct RTAS calls to manage any dynamic resources
we associate with a particular DR Connector as part of
hotplug/unplug.

Since general management of boot-time device trees are handled
outside of sPAPRDRConnector, we insert these values blindly given
an FDT and offset. A mask of sPAPRDRConnector types is given to
instruct us on what types of connectors entries should be generated
for, since descriptions for different connectors may live in
different parts of the device tree.

Based on code originally written by Nathan Fontenot.

Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:54 +02:00
Tyrel Datwyler
79853e18d9 spapr_events: event-scan RTAS interface
We don't actually rely on this interface to surface hotplug events, and
instead rely on the similar-but-interrupt-driven check-exception RTAS
interface used for EPOW events. However, the existence of this interface
is needed to ensure guest kernels initialize the event-reporting
interfaces which will in turn be used by userspace tools to handle these
events, so we implement this interface here.

Since events surfaced by this call are mutually exclusive to those
surfaced via check-exception, we also update the RTAS event queue code
to accept a boolean to mark/filter for events accordingly.

Events of this sort are not currently generated by QEMU, but the interface
has been tested by surfacing hotplug events via event-scan in place
of check-exception.

Signed-off-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:53 +02:00
Nathan Fontenot
31fe14d15d spapr_events: re-use EPOW event infrastructure for hotplug events
This extends the data structures currently used to report EPOW events to
guests via the check-exception RTAS interfaces to also include event types
for hotplug/unplug events.

This is currently undocumented and being finalized for inclusion in PAPR
specification, but we implement this here as an extension for guest
userspace tools to implement (existing guest kernels simply log these
events via a sysfs interface that's read by rtas_errd, and current
versions of rtas_errd/powerpc-utils already support the use of this
mechanism for initiating hotplug operations).

We also add support for queues of pending RTAS events, since in the
case of hotplug there's chance for multiple events being in-flight
at any point in time.

Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:53 +02:00
Michael Roth
46503c2bc0 spapr_rtas: add ibm, configure-connector RTAS interface
This interface is used to fetch an OF device-tree nodes that describes a
newly-attached device to guest. It is called multiple times to walk the
device-tree node and fetch individual properties into a 'workarea'/buffer
provided by the guest.

The device-tree is generated by QEMU and passed to an sPAPRDRConnector during
the initial hotplug operation, and the state of these RTAS calls is tracked by
the sPAPRDRConnector. When the last of these properties is successfully
fetched, we report as special return value to the guest and transition
the device to a 'configured' state on the QEMU/DRC side.

See docs/specs/ppc-spapr-hotplug.txt for a complete description of
this interface.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:53 +02:00
Michael Roth
ab316865db spapr: add rtas_st_buffer_direct() helper
This is similar to the existing rtas_st_buffer(), but for cases
where the guest is not expecting a length-encoded byte array.
Namely, for calls where a "work area" buffer is used to pass
around arbitrary fields/data.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:53 +02:00
Mike Day
886445a6ee spapr_rtas: add get-sensor-state RTAS interface
This interface allows a guest to read various platform/device sensors.
initially, we only implement support necessary to support hotplug:
reading of the dr-entity-sense sensor, which communicates the state of
a hotplugged resource/device to the guest (EMPTY/PRESENT/UNUSABLE).

See docs/specs/ppc-spapr-hotplug.txt for a complete description of
this interface.

Signed-off-by: Mike Day <ncmike@ncultra.org>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:53 +02:00
Mike Day
8c8639df32 spapr_rtas: add set-indicator RTAS interface
This interface allows a guest to control various platform/device
sensors. Initially, we only implement support necessary to control
sensors that are required for hotplug: DR connector indicators/LEDs,
resource allocation state, and resource isolation state.

See docs/specs/ppc-spapr-hotplug.txt for a complete description of
this interface.

Signed-off-by: Mike Day <ncmike@ncultra.org>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:53 +02:00
Nathan Fontenot
094d20585e spapr_rtas: add get/set-power-level RTAS interfaces
These interfaces manage the power domains that guest devices are
assigned to and are used to power on/off devices. Currently we
only utilize 1 power domain, the 'live-insertion' domain, which
automates power management of plugged/unplugged devices, essentially
making these calls no-ops, but the RTAS interfaces are still required
by guest hotplug code and PAPR+.

See docs/specs/ppc-spapr-hotplug.txt for a complete description of
these interfaces.

Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:52 +02:00
Michael Roth
bbf5c878ab spapr_drc: initial implementation of sPAPRDRConnector device
This device emulates a firmware abstraction used by pSeries guests to
manage hotplug/dynamic-reconfiguration of host-bridges, PCI devices,
memory, and CPUs. It is conceptually similar to an SHPC device,
complete with LED indicators to identify individual slots to physical
physical users and indicate when it is safe to remove a device. In
some cases it is also used to manage virtualized resources, such a
memory, CPUs, and physical-host bridges, which in the case of pSeries
guests are virtualized resources where the physical components are
managed by the host.

Guests communicate with these DR Connectors using RTAS calls,
generally by addressing the unique DRC index associated with a
particular connector for a particular resource. For introspection
purposes we expose this state initially as QOM properties, and
in subsequent patches will introduce the RTAS calls that make use of
it. This constitutes to the 'guest' interface.

On the QEMU side we provide an attach/detach interface to associate
or cleanup a DeviceState with a particular sPAPRDRConnector in
response to hotplug/unplug, respectively. This constitutes the
'physical' interface to the DR Connector.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:52 +02:00
Michael Roth
11eec063f2 docs: add sPAPR hotplug/dynamic-reconfiguration documentation
This adds a general overview of hotplug/dynamic-reconfiguration
for sPAPR/pSeries guest.

As specified in PAPR+ v2.7.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:52 +02:00
Thomas Huth
730fce593b hw/ppc/spapr: Use error_report() instead of hw_error()
hw_error() is designed for printing CPU-related error messages
(e.g. it also prints a full CPU register dump). For error messages
that are not directly related to CPU problems, a function like
error_report() should be used instead.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:52 +02:00
Thomas Huth
68fea5a0d7 hw/ppc/spapr: Fix error message when firmware could not be loaded
When specifying a non-existing file with the "-bios" parameter, QEMU
complained that it "could not find LPAR rtas". That's obviously a
copy-n-paste bug from the code which loads the spapr-rtas.bin, it
should complain about a missing firmware file instead.
Additionally the error message was printed with hw_error() - which
also dumps the whole CPU state. However, this does not make much
sense here since the CPU is not running yet and thus the registers
only contain zeroes. So let's use error_report() here instead.
And while we're at it, let's also bail out if the firmware file
had zero length.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:52 +02:00
David Gibson
a1a4561243 pseries: Add pseries-2.4 machine type
Now that 2.4 development has opened, create a new pseries machine type
variant.  For now it is identical to the pseries-2.3 machine type, but
a number of new features are coming that will need to set backwards
compatibility options.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:52 +02:00
Thomas Huth
f9ce8e0aa3 hw/ppc/spapr_iommu: Fix the check for invalid upper bits in liobn
The check "liobn & 0xFFFFFFFF00000000ULL" in spapr_tce_find_by_liobn()
is completely useless since liobn is only declared as an uint32_t
parameter. Fix this by using target_ulong instead (this is what most
of the callers of this function are using, too).

Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:51 +02:00
Alexey Kardashevskiy
dea1b3ce75 spapr_iommu: Give unique QOM name to TCE table
Useful for debugging.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:51 +02:00
Alexey Kardashevskiy
ccf9ff8527 spapr_pci: Rework device-tree rendering
This replaces object_child_foreach() and callback with existing
SPAPR_PCI_LIOBN() and spapr_tce_find_by_liobn() to make the code easier
to read.

This is a mechanical patch so no behaviour change is expected.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:51 +02:00
Alexey Kardashevskiy
fae807a2b1 spapr_iommu: Make spapr_tce_find_by_liobn() public
At the moment spapr_tce_find_by_liobn() is used by H_PUT_TCE/...
handlers to find an IOMMU by LIOBN.

We are going to implement Dynamic DMA windows (DDW), new code
will go to a new file and we will use spapr_tce_find_by_liobn()
there too so let's make it public.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:51 +02:00
Alexey Kardashevskiy
46c5874e9c spapr_pci: Make find_phb()/find_dev() public
This makes find_phb()/find_dev() public and changed its names
to spapr_pci_find_phb()/spapr_pci_find_dev() as they are going to
be used from other parts of QEMU such as VFIO DDW (dynamic DMA window)
or VFIO PCI error injection or VFIO EEH handling - in all these
cases there are RTAS calls which are addressed to BUID+config_addr
in IEEE1275 format.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:51 +02:00
Alexey Kardashevskiy
d9d96a3cc7 spapr_iommu: Add separate trace points for PCI DMA operations
This is to reduce VIO noise while debugging PCI DMA.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:51 +02:00
Alexey Kardashevskiy
3e1a01cb55 spapr_pci: Define default DMA window size as a macro
This gets rid of a magic constant describing the default DMA window size
for an emulated PHB.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:50 +02:00
Alexey Kardashevskiy
4290ca49ee spapr_vio: Introduce a liobn number generating macros
This introduces a macro which makes up a LIOBN from fixed prefix and
VIO device address (@reg property).

This is to keep LIOBN macros rendering consistent - the same macro for
PCI has been added by the previous patch.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:50 +02:00
Alexey Kardashevskiy
c8545818b3 spapr_pci: Introduce a liobn number generating macros
We are going to have multiple DMA windows per PHB and we want them to
migrate so we need a predictable way of assigning LIOBNs.

This introduces a macro which makes up a LIOBN from fixed prefix,
PHB index (unique PHB id) and window number.

This introduces a SPAPR_PCI_DMA_WINDOW_NUM() to know the window number
from LIOBN. It is used to distinguish the default 32bit windows from
dynamic windows and avoid picking default DMA window properties from
a wrong TCE table.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:50 +02:00
Alexey Kardashevskiy
f1215ea702 spapr_iommu: Make H_PUT_TCE_INDIRECT endian-safe
PAPR is defined as big endian so TCEs need an adjustment so
does this patch.

This changes code to have ldq_be_phys() in one place.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:50 +02:00
Alexey Kardashevskiy
12fd285358 spapr_iommu: Disable in-kernel IOMMU tables for >4GB windows
The existing KVM_CREATE_SPAPR_TCE ioctl only support 4G windows max as
the window size parameter to the kernel ioctl() is 32-bit so
there's no way of expressing a TCE window > 4GB.

We are going to add huge DMA windows support so this will create small
window and unexpectedly fail later.

This disables KVM_CREATE_SPAPR_TCE for windows bigger that 4GB.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:50 +02:00
David Gibson
421b1b27f6 spapr_pci: Fix unsafe signed/unsigned comparisons
spapr_pci.c contains a number of expressions of the form (uval == -1) or
(uval != -1), where 'uval' is an unsigned value.

This mostly works in practice, because as long as the width of uval is
greater or equal than that of (int), the -1 will be promoted to the
unsigned type, which is the expected outcome.

However, at least for the cases where uval is uint32_t, this would break
on platforms where sizeof(int) > 4 (and a few such do exist), because then
the uint32_t value would be promoted to the larger int type, and never be
equal to -1.

This patch fixes these errors.  The fixes for the (uint32_t) cases are
necessary as described above.  I've made similar fixes to (uint64_t) and
(hwaddr) cases.  Those are strictly theoretical, since I don't know of any
platforms where sizeof(int) > 8, but hey, it's not that hard so we might
as well be strictly C standard compliant.

Reported-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:50 +02:00
Thomas Huth
31ce0adb79 configure: Check for libfdt version 1.4.0
Some recent patches require a function from libfdt version 1.4.0,
so we should check for this version during the configure step
already. Unfortunately, there does not seem to be a proper #define
for the version number in the libfdt headers. So alternatively,
we check for the availability of the required function
fdt_get_property_by_offset() instead instead.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:49 +02:00
Thomas Huth
28f490b24a dtc: Update dtc / libfdt submodule to version 1.4.0
Since some recent patches require libfdt version 1.4.0,
let's update the dtc submodule to this version.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:49 +02:00
Markus Armbruster
62e9cd771c macio: Convert to realize()
Convert device models "macio-oldworld" and "macio-newworld".

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
2015-06-03 23:56:49 +02:00
Marcel Apfelbaum
814550d73a docs: Add PXB documentation
Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:19 +02:00
Marcel Apfelbaum
0f6dd8e1d5 apci: fix PXB behaviour if used with unsupported BIOS
PXB does not work with unsupported bioses, but should
not interfere with normal OS operation.
We don't ship them anymore, but it's reasonable
to keep the work-around until we update the bios in qemu.

Fix this by not adding PXB mem/IO chunks to _CRS
if they weren't configured by BIOS.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:18 +02:00
Marcel Apfelbaum
0e79e51a7d hw/pxb: add numa_node parameter
The pxb can be attach to and existing numa node by specifying
numa_node option that equals the desired numa nodeid.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:18 +02:00
Marcel Apfelbaum
6a3042b23b hw/pci: add support for NUMA nodes
PCI root buses can be attached to a specific NUMA node.
PCI buses are not attached by default to a NUMA node.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:18 +02:00
Marcel Apfelbaum
0639b00d05 hw/pxb: add map_irq func
The bios does not index the pxb slot number when
it computes the IRQ because it resides on bus 0
and not on the current bus.
However Qemu routes the irq through bus 0 and adds
the pxb slot to the IRQ computation of the PXB device.

Synchronize between bios and Qemu by canceling
pxb's effect.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:18 +02:00
Marcel Apfelbaum
2118196bb3 hw/pci: inform bios if the system has extra pci root buses
The bios looks for 'etc/extra-pci-roots' to decide if
is going to scan further buses after bus 0 tree.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:18 +02:00
Marcel Apfelbaum
40d14bef80 hw/pci: introduce PCI Expander Bridge (PXB)
PXB is a "light-weight" host bridge whose purpose is to enable
the main host bridge to support multiple PCI root buses
for pc machines.

As oposed to PCI-2-PCI bridge's secondary bus, PXB's bus
is a primary bus and can be associated with a NUMA node
(different from the main host bridge) allowing the guest OS
to recognize the proximity of a pass-through device to
other resources as RAM and CPUs.

The PXB is composed from:
 - A primary PCI bus (can be associated with a NUMA node)
   Acts like a normal pci bus and from the functionality point
   of view is an "expansion" of the bus behind the
   main host bridge.
 - A pci-2-pci bridge behind the primary PCI bus where the actual
   devices will be attached.
 - A host-bridge PCI device
   Situated on the bus behind the main host bridge, allows
   the BIOS to configure the bus number and IO/mem resources.
   It does not have its own config/data register for configuration
   cycles, this being handled by the main host bridge.
-  A host-bridge sysbus to comply with QEMU current design.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:18 +02:00
Marcel Apfelbaum
cb2ed8b3c6 hw/pci: removed 'rootbus nr is 0' assumption from qmp_pci_query
Use the newer pci_bus_num to correctly get the root bus number.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:17 +02:00
Marcel Apfelbaum
dcdca29655 hw/acpi: remove from root bus 0 the crs resources used by other buses.
If multiple root buses are used, root bus 0 cannot use all the
pci holes ranges. Remove the IO/mem ranges used by the other
primary buses.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:17 +02:00
Marcel Apfelbaum
a43c6e2762 hw/acpi: add _CRS method for extra root busses
Save the IO/mem/bus numbers ranges assigned to the extra root busses
to be removed from the root bus 0 range.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:17 +02:00
Marcel Apfelbaum
0d8935e337 hw/apci: add _PRT method for extra PCI root busses
Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:17 +02:00
Marcel Apfelbaum
a4894206e3 hw/acpi: add support for i440fx 'snooping' root busses
If the machine has extra root busses that are snooping to
the i440fx host bridge, we need to add them to
acpi in order to be properly detected by guests.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:17 +02:00
Marcel Apfelbaum
09e5b81922 hw/pci: extend PCI config access to support devices behind PXB
PXB buses are assumed to be children of bus 0. Look for them
while scanning the buses.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:17 +02:00
Marcel Apfelbaum
ca6c18556c hw/i386: query only for q35/pc when looking for pci host bridge
Because of the PXB hosts we cannot simply query TYPE_PCI_HOST_BRIDGE anymore.
On i386 arch we only have two pci hosts, so we can look only for them.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:16 +02:00
Marcel Apfelbaum
602141d997 hw/pci: made pci_bus_num a PCIBusClass method
Refactoring it as a method of PCIBusClass will allow
different implementations for subclasses.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:16 +02:00
Marcel Apfelbaum
ce6a28ee05 hw/pci: made pci_bus_is_root a PCIBusClass method
Refactoring it as a method of PCIBusClass will allow
different implementations for subclasses.

Removed the assumption that the root bus does not
have a parent device because is specific only
to the default class implementation.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:16 +02:00
Marcel Apfelbaum
32d9ca15ba acpi: add implementation of aml_while() term
Commit 68e6b0af7 (acpi: add aml_while() term) added
the definition of aml_while without the actual implementation.
Implement the term.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
2015-06-03 18:19:16 +02:00
Zhu Guihua
ca9b46bcec acpi: add acpi_send_gpe_event() to rise sci for hotplug
Add a new API named acpi_send_gpe_event() to send hotplug SCI.
This API can be used by pci, cpu and memory hotplug.

This patch is rebased on master.

Signed-off-by: Zhu Guihua <zhugh.fnst@cn.fujitsu.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
2015-06-03 18:19:16 +02:00
Gerd Hoffmann
d5aaa1b045 virtio: 64bit features fixups.
Commit "019a3ed virtio: make features 64bit wide" missed a few changes,
as I've noticed while trying to rebase the virtio-1 branch to latest
master.  This patch adds them.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-03 18:19:16 +02:00
Juan Quintela
977ad992f1 TPM: fix build with tpm disabled
Failure was included on commit

Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-03 18:19:15 +02:00
Jason Wang
6652d0811c virtio-pci: don't try to mask or unmask vqs without notifiers
We should validate the vq index against nvqs_with_notifiers. Otherwise we may
try to mask or unmask vector for vqs without notifiers (e.g control vq). This
will lead qemu abort on kvm_irqchip_commit_routes() when trying to boot win8.1
guest.

Fixes 851c2a75a6 ("virtio-pci: speedup MSI-X
masking and unmasking")

Reported-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-03 18:19:15 +02:00
Marcel Apfelbaum
557772f26b hw/q35: fix floppy controller definition in ich9
In DSDT FDC0 declares the IO region as IO(Decode16, 0x03F2, 0x03F2, 0x00, 0x04).
Use the same in lpc_ich9 initialization code.
Now the floppy drive is detected correctly on Windows.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-03 18:19:15 +02:00
Michael S. Tsirkin
cb3d37a93c acpi: add missing ssdt
commit 5cb18b3d7b
    TPM2 ACPI table support

was missing a file, so build with iasl fails
(build without iasl works since it uses the generated
 hex files).

Reported-by: "Daniel P. Berrange" <berrange@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-03 18:19:15 +02:00
Sascha Silbe
b853d4cbf2 s390x/kvm: always ignore empty vcpu interrupt state
kvm_s390_vcpu_interrupt_pre_save() and
kvm_s390_vcpu_interrupt_post_load() are essentially no-ops on hosts
without KVM_CAP_S390_IRQ_STATE. Move the capability check after the
check for saved IRQ state in kvm_s390_vcpu_interrupt_post_load() so that
migration between hosts without KVM_CAP_S390_IRQ_STATE (including save /
restore on the same host) continues to work.

Fixes: 3cda44f7ba ("s390x/kvm: migrate vcpu interrupt state")
Signed-off-by: Sascha Silbe <silbe@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2015-06-03 18:07:09 +02:00
Jason J. Herne
2a72ea5f66 virtio-ccw/migration: Migrate config vector for virtio devices
virtio_ccw_{save|load}_config are missing code to save and restore a vdev's
config_vector value. This causes some virtio devices to become disabled
following a migration.

This patch fixes a bug whereby the qmp/hmp balloon command (virsh setmem)
silently fails to update the guest's available memory because the device was not
properly migrated.

This will break compatibility, but vmstate_s390_cpu was bumped from
version 2 to version 4 between v2.3.0 and v2.4.0 without a compat
handler. Furthermore, there is no production environment yet so
migration is fenced anyway between any relevant version of 2.3 and 2.4.

Signed-off-by: Jason J. Herne <jjherne@linux.vnet.ibm.com>
Message-Id: <1433343843-803-1-git-send-email-jjherne@linux.vnet.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2015-06-03 18:07:05 +02:00
Pierre Morel
de6a92185e virtio-ccw: add support for 9pfs
This patch adds 9pfs support for virtio-ccw
by registering the virtio_ccw_9p_info type
and adding associated callbacks.

Signed-off-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
2015-06-03 18:06:45 +02:00
Alex Bennée
de3852877f configure: postfix --extra-cflags to QEMU_CFLAGS
It makes sense that extra-cflags should be appended after the normal
CFLAGS so they don't get overridden by default behaviour. This way if
you specify something like:

  ./configure --extra-cflags="-O0"

You will see the requested behaviour.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 16:04:39 +03:00
Sai Pavan Boddu
2801339f2f cadence_gem: Fix Rx buffer size field mask
This patch corrects the Rx buffer size field mask to mask bits 23 to 16
to match Xilinx UG585 documentation.

Signed-off-by: Sai Pavan Boddu <saipava@xilinx.com>
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 16:03:03 +03:00
Michael Tokarev
8b8f1c7e9d slirp: use less predictable directory name in /tmp for smb config (CVE-2015-4037)
In this version I used mkdtemp(3) which is:

        _BSD_SOURCE
        || /* Since glibc 2.10: */
            (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)

(POSIX.1-2008), so should be available on systems we care about.

While at it, reset the resulting directory name within smb structure
on error so cleanup function wont try to remove directory which we
failed to create.

Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
2015-06-03 14:21:45 +03:00
Paolo Bonzini
b6b099541d translate-all: delete prototype for non-existent function
Missed in commit 3a808cc40

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Dr. David Alan Gilbert
1597051b84 Add -incoming help text
The help/man text for

-incoming defer

didn't make it through the merge of the code that implemented it.

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
26c8acb3f3 hw/display/tc6393xb.c: Fix misusing qemu_allocate_irqs for single irq
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
294972ce54 hw/arm/nseries.c: Fix misusing qemu_allocate_irqs for single irq
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
5429273615 hw/alpha/typhoon.c: Fix misusing qemu_allocate_irqs for single irq
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
2c85fad022 hw/unicore32/puv3.c: Fix misusing qemu_allocate_irqs for single irq
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
a9c8a0d8d4 hw/lm32/milkymist.c: Fix misusing qemu_allocate_irqs for single irq
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
d4ef00af25 hw/lm32/lm32_boards.c: Fix misusing qemu_allocate_irqs for single irq
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
aaaee0b273 hw/ppc/prep.c: Fix misusing qemu_allocate_irqs for single irq
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
ca43b97b5f hw/sparc/sun4m.c: Fix misusing qemu_allocate_irqs for single irq
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
b64127244d hw/timer/arm_timer.c: Fix misusing qemu_allocate_irqs for single irq
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
5105505e65 hw/isa/i82378.c: Fix misusing qemu_allocate_irqs for single irq
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
aff0d5e57a hw/isa/lpc_ich9.c: Fix misusing qemu_allocate_irqs for single irq
Since ich9_lpc_pm_init only requests one irq, so let it just call
qemu_allocate_irq.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
0b0cc076b7 hw/i386/pc: Fix misusing qemu_allocate_irqs for single irq
Since pc_allocate_cpu_irq only requests one irq, so let it just call
qemu_allocate_irq.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
9ff7f5bddb hw/intc/exynos4210_gic.c: Fix memory leak by adjusting order
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
9f9b026dc6 hw/arm/omap_sx1.c: Fix memory leak spotted by valgrind
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
f19377bf23 hw/ppc/e500.c: Fix memory leak
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
c18f855697 hw/alpha/dp264.c: Fix memory leak spotted by valgrind
valgrind complains about:
==7055== 58 bytes in 1 blocks are definitely lost in loss record 1,471 of 2,192
==7055==    at 0x4C2845D: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==7055==    by 0x24410F: malloc_and_trace (vl.c:2556)
==7055==    by 0x64C770E: g_malloc (in /usr/lib64/libglib-2.0.so.0.3600.3)
==7055==    by 0x64DEFD7: g_strndup (in /usr/lib64/libglib-2.0.so.0.3600.3)
==7055==    by 0x650181A: g_vasprintf (in /usr/lib64/libglib-2.0.so.0.3600.3)
==7055==    by 0x64DF0CC: g_strdup_vprintf (in /usr/lib64/libglib-2.0.so.0.3600.3)
==7055==    by 0x64DF188: g_strdup_printf (in /usr/lib64/libglib-2.0.so.0.3600.3)
==7055==    by 0x242F81: qemu_find_file (vl.c:2121)
==7055==    by 0x217A32: clipper_init (dp264.c:105)
==7055==    by 0x2484DA: main (vl.c:4249)

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
bd4baf6eeb vl: fix memory leak spotted by valgrind
valgrind complains about:
==9276== 13 bytes in 1 blocks are definitely lost in loss record 1,046 of 3,673
==9276==    at 0x4C2845D: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==9276==    by 0x2EAFBB: malloc_and_trace (vl.c:2556)
==9276==    by 0x64C770E: g_malloc (in /usr/lib64/libglib-2.0.so.0.3600.3)
==9276==    by 0x4A28BD: addr_to_string (vnc.c:123)
==9276==    by 0x4A29AD: vnc_socket_local_addr (vnc.c:139)
==9276==    by 0x4A9AFE: vnc_display_local_addr (vnc.c:3240)
==9276==    by 0x2EF4FE: main (vl.c:4321)

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Peter Crosthwaite
7df057bac3 device-tree: Make a common-obj
There is no reason for device tree API to be built per-target.
common-obj it. There is an extraneous inclusion of config.h that
needs to be removed.

Cc: Alexander Graf <agraf@suse.de>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
d370dfa9f3 hw/i386/acpi-build: decref after use
valgrind complains about:
==16447== 48 bytes in 2 blocks are definitely lost in loss record 2,033 of 3,310
==16447==    at 0x4C2845D: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==16447==    by 0x2E4FD7: malloc_and_trace (vl.c:2546)
==16447==    by 0x64C770E: g_malloc (in /usr/lib64/libglib-2.0.so.0.3600.3)
==16447==    by 0x53EC3F: qint_from_int (qint.c:33)
==16447==    by 0x53B426: qmp_output_type_int (qmp-output-visitor.c:162)
==16447==    by 0x539257: visit_type_uint32 (qapi-visit-core.c:147)
==16447==    by 0x471D07: property_get_uint32_ptr (object.c:1651)
==16447==    by 0x47000C: object_property_get (object.c:822)
==16447==    by 0x472428: object_property_get_qobject (qom-qobject.c:37)
==16447==    by 0x25701A: build_append_pci_bus_devices (acpi-build.c:520)
==16447==    by 0x25902E: build_ssdt (acpi-build.c:1004)
==16447==    by 0x25A0A8: acpi_build (acpi-build.c:1420)

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
6e38a4ba78 hw/ide/pci: Fix memory leak
valgrind complains about:
==16447== 16 bytes in 2 blocks are definitely lost in loss record 1,304 of 3,310
==16447==    at 0x4C2845D: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==16447==    by 0x2E4FD7: malloc_and_trace (vl.c:2546)
==16447==    by 0x64C770E: g_malloc (in /usr/lib64/libglib-2.0.so.0.3600.3)
==16447==    by 0x36FB47: qemu_extend_irqs (irq.c:55)
==16447==    by 0x36FBD3: qemu_allocate_irqs (irq.c:64)
==16447==    by 0x3B4B44: bmdma_init (pci.c:464)
==16447==    by 0x3B547B: pci_piix_init_ports (piix.c:144)
==16447==    by 0x3B55D2: pci_piix_ide_realize (piix.c:164)
==16447==    by 0x3EAEC6: pci_qdev_realize (pci.c:1790)
==16447==    by 0x36C685: device_set_realized (qdev.c:1058)
==16447==    by 0x47179E: property_set_bool (object.c:1514)
==16447==    by 0x470098: object_property_set (object.c:837)

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Marcel Apfelbaum <marcel@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:24 +03:00
Shannon Zhao
2ba154cf4e hw/i386/pc_piix: Fix memory leak
valgrind complains about:
==16447== 8 bytes in 1 blocks are definitely lost in loss record 552 of 3,310
==16447==    at 0x4C2845D: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==16447==    by 0x2E4FD7: malloc_and_trace (vl.c:2546)
==16447==    by 0x64C770E: g_malloc (in /usr/lib64/libglib-2.0.so.0.3600.3)
==16447==    by 0x36FB47: qemu_extend_irqs (irq.c:55)
==16447==    by 0x36FBD3: qemu_allocate_irqs (irq.c:64)
==16447==    by 0x24E622: pc_init1 (pc_piix.c:287)
==16447==    by 0x24E76A: pc_init_pci (pc_piix.c:310)
==16447==    by 0x2E9360: main (vl.c:4226)

==16447== 128 bytes in 1 blocks are definitely lost in loss record 2,569 of 3,310
==16447==    at 0x4C2845D: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==16447==    by 0x2E4FD7: malloc_and_trace (vl.c:2546)
==16447==    by 0x64C770E: g_malloc (in /usr/lib64/libglib-2.0.so.0.3600.3)
==16447==    by 0x36FB47: qemu_extend_irqs (irq.c:55)
==16447==    by 0x36FBD3: qemu_allocate_irqs (irq.c:64)
==16447==    by 0x25BEB2: kvm_i8259_init (i8259.c:133)
==16447==    by 0x24E1F1: pc_init1 (pc_piix.c:219)
==16447==    by 0x24E76A: pc_init_pci (pc_piix.c:310)
==16447==    by 0x2E9360: main (vl.c:4226)

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Marcel Apfelbaum <marcel@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:23 +03:00
Chen Hanxiao
5708b2b736 docs/writing-qmp-commands: fix a typo
s/interation/iteration

Signed-off-by: Chen Hanxiao <chenhanxiao@cn.fujitsu.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:23 +03:00
Peter Krempa
b8981dc9aa util: socket: Add missing localaddr and localport option for DGRAM socket
The 'socket_optslist' structure does not contain the 'localaddr' and
'localport' options that are parsed in case you are creating a
'connect' type UDP character device.

I've noticed it happening after commit f43e47dbf6
made qemu abort() after seeing the invalid option.

A minimal reproducer for the case is:
$ qemu-system-x86_64 -chardev udp,id=charrng0,host=127.0.0.1,port=1234,localaddr=,localport=1234
qemu-system-x86_64: -chardev udp,id=charrng0,host=127.0.0.1,port=1234,localaddr=,localport=1234: Invalid parameter 'localaddr'
Aborted (core dumped)

Prior to the commit mentioned above the error would be printed but the
value for localaddr and localport was simply ignored. I did not go
through the code to find out when it was broken.

Add the two fields so that the options can again be parsed correctly and
qemu doesn't abort().

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1220252

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:23 +03:00
Peter Crosthwaite
a2f533da00 microblaze: cpu: Delete MMAP_SHIFT definition
Just fallback on the default of 12 like other architectures. This
allows changing the system-mode-affecting definition of
TARGET_PAGE_BITS without affecting microblaze linux-user.

Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:23 +03:00
Fam Zheng
44f192f364 iscsi: Remove pointless runtime check of macro value
raw_bsd already has QEMU_BUILD_BUG_ON(BDRV_SECTOR_SIZE != 512), so iscsi
should relax.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2015-06-03 14:21:23 +03:00
Ikey Doherty
1b93c9a104 arch_init: Drop target-x86_64.conf
The target-x86_64.conf sysconfig file has been empty and essentially ignored
now for several years. This change removes the unused file to enable moving
towards a stateless configuration.

Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-06-02 15:15:52 -03:00
Eduardo Habkost
38e5c119c2 target-i386: Register QOM properties for feature flags
This uses the feature name arrays to register QOM properties for feature
flags. This simply adds properties that can be configured using -global,
but doesn't change x86_cpu_parse_featurestr() to use them yet.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-06-02 15:15:52 -03:00
Zhu Guihua
be9f8a0872 apic: convert ->busdev.qdev casts to C casts
Use C casts to avoid accessing ICCDevice's qdev field
directly.

Signed-off-by: Zhu Guihua <zhugh.fnst@cn.fujitsu.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Acked-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-06-02 15:15:52 -03:00
Eduardo Habkost
458cf469f4 target-i386: Fix signedness of MSR_IA32_APICBASE_BASE
Existing definition triggers the following when using clang
-fsanitize=undefined:

    hw/intc/apic_common.c:314:55: runtime error: left shift of 1048575 by 12
        places cannot be represented in type 'int'

Fix it so we won't try to shift a 1 to the sign bit of a signed integer.

Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-06-02 15:15:52 -03:00
Andreas Färber
0e3bd56294 pc: Ensure non-zero CPU ref count after attaching to ICC bus
Setting the parent bus of a device increases its ref count, which we
ultimately want to level out. However it is only safe to do so after the
last reference to the device in local code, as qom-set or similar operations
might decrease the ref count.

Therefore move the object_unref() from pc_new_cpu() into its callers.

The APIC operations on the last CPU in pc_cpus_init() are still potentially
insecure, but that is beyond the scope of this code movement.

Signed-off-by: Andreas Färber <afaerber@suse.de>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-06-02 15:15:52 -03:00
Kevin Wolf
4964e18e49 fdc-test: Test state for existing cases more thoroughly
This just adds a few additional checks of the MSR and interrupt pin to
the already existing test cases.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1432214378-31891-9-git-send-email-kwolf@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2015-06-02 13:34:45 -04:00
Kevin Wolf
6cc8a11c84 fdc: Fix MSR.RQM flag
The RQM bit in MSR should be set whenever the guest is supposed to
access the FIFO, and it should be cleared in all other cases. This is
important so the guest can't continue writing/reading the FIFO beyond
the length that it's suppossed to access (see CVE-2015-3456).

Commit e9077462 fixed the CVE by adding code that avoids the buffer
overflow; however it doesn't correct the wrong behaviour of the floppy
controller which should already have cleared RQM.

Currently, RQM stays set all the time and during all phases while a
command is being processed. This is error-prone because the command has
to explicitly clear the flag if it doesn't need data (and indeed, the
two buggy commands that are the culprits for the CVE just forgot to do
that).

This patch clears RQM immediately as soon as all bytes that are expected
have been received. If the the FIFO is used in the next phase, the flag
has to be set explicitly there.

It also clear RQM after receiving all bytes even if the phase transition
immediately sets it again. While it's technically not necessary at the
moment because the state between clearing and setting RQM is not
observable by the guest, this is more explicit and matches how real
hardware works. It will actually become necessary in qemu once
asynchronous code paths are introduced.

This alone should have been enough to fix the CVE, but now we have two
lines of defense - even better.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1432214378-31891-8-git-send-email-kwolf@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2015-06-02 13:34:44 -04:00
Kevin Wolf
f6c2d1d842 fdc: Disentangle phases in fdctrl_read_data()
This commit makes similar improvements as have already been made to the
write function: Instead of relying on a flag in the MSR to distinguish
controller phases, use the explicit phase that we store now. Assertions
of the right MSR flags are added.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1432214378-31891-7-git-send-email-kwolf@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2015-06-02 13:34:44 -04:00
Kevin Wolf
d275b33d76 fdc: Code cleanup in fdctrl_write_data()
Factor out a few common lines of code, reformat, improve comments.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1432214378-31891-6-git-send-email-kwolf@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2015-06-02 13:34:44 -04:00
Kevin Wolf
5b0a25e8d2 fdc: Use phase in fdctrl_write_data()
Instead of relying on a flag in the MSR to distinguish controller phases,
use the explicit phase that we store now. Assertions of the right MSR
flags are added.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1432214378-31891-5-git-send-email-kwolf@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2015-06-02 13:34:44 -04:00
Kevin Wolf
85d291a08c fdc: Introduce fdctrl->phase
The floppy controller spec describes three different controller phases,
which are currently not explicitly modelled in our emulation. Instead,
each phase is represented by a combination of flags in registers.

This patch makes explicit in which phase the controller currently is.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Acked-by: John Snow <jsnow@redhat.com>
Message-id: 1432214378-31891-4-git-send-email-kwolf@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2015-06-02 13:34:44 -04:00
Kevin Wolf
83a260135f fdc: Rename fdctrl_set_fifo() to fdctrl_to_result_phase()
What callers really do with this function is to switch from execution
phase (including data transfers) to result phase where the guest can
read out one or more status bytes from the FIFO (the number depends on
the command).

Rename the function accordingly.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1432214378-31891-3-git-send-email-kwolf@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2015-06-02 13:34:44 -04:00
Kevin Wolf
07e415f239 fdc: Rename fdctrl_reset_fifo() to fdctrl_to_command_phase()
What all callers of fdctrl_reset_fifo() really want to do is to start
the command phase, where writes to the data port initiate a new command.

The function doesn't only clear the FIFO, but also sets up the state so
that a new command can be received. Rename it to reflect this.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1432214378-31891-2-git-send-email-kwolf@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
2015-06-02 13:34:44 -04:00
Peter Maydell
a67bfbb9e4 Merge remote-tracking branch 'remotes/armbru/tags/pull-monitor-2015-06-02' into staging
Monitor patches

# gpg: Signature made Tue Jun  2 09:16:07 2015 BST using RSA key ID EB918653
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>"
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>"

* remotes/armbru/tags/pull-monitor-2015-06-02: (21 commits)
  monitor: Change return type of monitor_cur_is_qmp() to bool
  monitor: Rename monitor_ctrl_mode() to monitor_is_qmp()
  monitor: Turn int command_mode into bool in_command_mode
  monitor: Drop do_qmp_capabilities()'s superfluous QMP check
  monitor: Unbox Monitor member mc and rename to qmp
  monitor: Rename monitor_control_read(), monitor_control_event()
  monitor: Rename handle_user_command() to handle_hmp_command()
  monitor: Limit QError use to command handlers
  monitor: Inline monitor_has_error() into its only caller
  monitor: Wean monitor_protocol_emitter() off mon->error
  monitor: Propagate errors through invalid_qmp_mode()
  monitor: Propagate errors through qmp_check_input_obj()
  monitor: Propagate errors through qmp_check_client_args()
  monitor: Drop unused "new" HMP command interface
  monitor: Use trad. command interface for HMP pcie_aer_inject_error
  monitor: Use traditional command interface for HMP device_add
  monitor: Use traditional command interface for HMP drive_del
  monitor: Convert client_migrate_info to QAPI
  monitor: Improve and document client_migrate_info protocol error
  monitor: Clean up after previous commit
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 18:23:28 +01:00
Peter Maydell
42d58e7c67 Merge remote-tracking branch 'remotes/sstabellini/tags/xen-15-06-02-tag' into staging
XSA 128 129 130 131

# gpg: Signature made Tue Jun  2 16:46:38 2015 BST using RSA key ID 70E1AE90
# gpg: Good signature from "Stefano Stabellini <stefano.stabellini@eu.citrix.com>"

* remotes/sstabellini/tags/xen-15-06-02-tag:
  xen/pt: unknown PCI config space fields should be read-only
  xen/pt: add a few PCI config space field descriptions
  xen/pt: mark reserved bits in PCI config space fields
  xen/pt: mark all PCIe capability bits read-only
  xen/pt: split out calculation of throughable mask in PCI config space handling
  xen/pt: correctly handle PM status bit
  xen/pt: consolidate PM capability emu_mask
  xen/MSI: don't open-code pass-through of enable bit modifications
  xen/MSI-X: limit error messages
  xen: don't allow guest to control MSI mask register
  xen: properly gate host writes of modified PCI CFG contents

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 16:47:31 +01:00
Eric Auger
94edf02c4c hw/arm/virt: change indentation in a15memmap
Re-indent in a15memmap after VIRT_PLATFORM_BUS introduction

Signed-off-by: Eric Auger <eric.auger@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Shannon Zhao <shannon.zhao@linaro.org>
Message-id: 1433244554-12898-5-git-send-email-eric.auger@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 16:31:18 +01:00
Eric Auger
5f7a5a0edc hw/arm/virt: add dynamic sysbus device support
Allows sysbus devices to be instantiated from command line by
using -device option. Machvirt creates a platform bus at init.
The dynamic sysbus devices are attached to this platform bus device.

The platform bus device registers a machine init done notifier
whose role will be to bind the dynamic sysbus devices. Indeed
dynamic sysbus devices are created after machine init.

machvirt also registers a notifier that will build the device
tree nodes for the platform bus and its children dynamic sysbus
devices.

Signed-off-by: Eric Auger <eric.auger@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1433244554-12898-4-git-send-email-eric.auger@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 16:31:18 +01:00
Eric Auger
ac9d32e396 hw/arm/boot: arm_load_kernel implemented as a machine init done notifier
Device tree nodes for the platform bus and its children dynamic sysbus
devices are added in a machine init done notifier. To load the dtb once,
after those latter nodes are built and before ROM freeze, the actual
arm_load_kernel existing code is moved into a notifier notify function,
arm_load_kernel_notify. arm_load_kernel now only registers the
corresponding notifier.

Machine files that do not support platform bus stay unchanged. Machine
files willing to support dynamic sysbus devices must call arm_load_kernel
before sysbus-fdt arm_register_platform_bus_fdt_creator to make sure
dynamic sysbus device nodes are integrated in the dtb.

Signed-off-by: Eric Auger <eric.auger@linaro.org>
Reviewed-by: Shannon Zhao <zhaoshenglong@huawei.com>
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1433244554-12898-3-git-send-email-eric.auger@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 16:31:17 +01:00
Jan Beulich
c25bbf1545 xen/pt: unknown PCI config space fields should be read-only
... by default. Add a per-device "permissive" mode similar to pciback's
to allow restoring previous behavior (and hence break security again,
i.e. should be used only for trusted guests).

This is part of XSA-131.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>)
2015-06-02 15:07:01 +00:00
Jan Beulich
a88a3f8871 xen/pt: add a few PCI config space field descriptions
Since the next patch will turn all not explicitly described fields
read-only by default, those fields that have guest writable bits need
to be given explicit descriptors.

This is a preparatory patch for XSA-131.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
2015-06-02 15:07:01 +00:00
Jan Beulich
0ad3393ad0 xen/pt: mark reserved bits in PCI config space fields
The adjustments are solely to make the subsequent patches work right
(and hence make the patch set consistent), namely if permissive mode
(introduced by the last patch) gets used (as both reserved registers
and reserved fields must be similarly protected from guest access in
default mode, but the guest should be allowed access to them in
permissive mode).

This is a preparatory patch for XSA-131.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
2015-06-02 15:07:01 +00:00
Jan Beulich
45ebe3916a xen/pt: mark all PCIe capability bits read-only
xen_pt_emu_reg_pcie[]'s PCI_EXP_DEVCAP needs to cover all bits as read-
only to avoid unintended write-back (just a precaution, the field ought
to be read-only in hardware).

This is a preparatory patch for XSA-131.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
2015-06-02 15:07:01 +00:00
Jan Beulich
0e7ef22136 xen/pt: split out calculation of throughable mask in PCI config space handling
This is just to avoid having to adjust that calculation later in
multiple places.

Note that including ->ro_mask in get_throughable_mask()'s calculation
is only an apparent (i.e. benign) behavioral change: For r/o fields it
doesn't matter > whether they get passed through - either the same flag
is also set in emu_mask (then there's no change at all) or the field is
r/o in hardware (and hence a write won't change it anyway).

This is a preparatory patch for XSA-131.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>
2015-06-02 15:07:01 +00:00
Jan Beulich
c4ff1e68c6 xen/pt: correctly handle PM status bit
xen_pt_pmcsr_reg_write() needs an adjustment to deal with the RW1C
nature of the not passed through bit 15 (PCI_PM_CTRL_PME_STATUS).

This is a preparatory patch for XSA-131.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
2015-06-02 15:07:01 +00:00
Jan Beulich
d61bb2482d xen/pt: consolidate PM capability emu_mask
There's no point in xen_pt_pmcsr_reg_{read,write}() each ORing
PCI_PM_CTRL_STATE_MASK and PCI_PM_CTRL_NO_SOFT_RESET into a local
emu_mask variable - we can have the same effect by setting the field
descriptor's emu_mask member suitably right away. Note that
xen_pt_pmcsr_reg_write() is being retained in order to allow later
patches to be less intrusive.

This is a preparatory patch for XSA-131.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
2015-06-02 15:07:01 +00:00
Jan Beulich
d1d35cf4ff xen/MSI: don't open-code pass-through of enable bit modifications
Without this the actual XSA-131 fix would cause the enable bit to not
get set anymore (due to the write back getting suppressed there based
on the OR of emu_mask, ro_mask, and res_mask).

Note that the fiddling with the enable bit shouldn't really be done by
qemu, but making this work right (via libxc and the hypervisor) will
require more extensive changes, which can be postponed until after the
security issue got addressed.

This is a preparatory patch for XSA-131.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
2015-06-02 15:07:01 +00:00
Jan Beulich
b38ec5ee7a xen/MSI-X: limit error messages
Limit error messages resulting from bad guest behavior to avoid allowing
the guest to cause the control domain's disk to fill.

The first message in pci_msix_write() can simply be deleted, as this
is indeed bad guest behavior, but such out of bounds writes don't
really need to be logged.

The second one is more problematic, as there guest behavior may only
appear to be wrong: For one, the old logic didn't take the mask-all bit
into account. And then this shouldn't depend on host device state (i.e.
the host may have masked the entry without the guest having done so).
Plus these writes shouldn't be dropped even when an entry is unmasked.
Instead, if they can't be made take effect right away, they should take
effect on the next unmasking or enabling operation - the specification
explicitly describes such caching behavior. Until we can validly drop
the message (implementing such caching/latching behavior), issue the
message just once per MSI-X table entry.

Note that the log message in pci_msix_read() similar to the one being
removed here is not an issue: "addr" being of unsigned type, and the
maximum size of the MSI-X table being 32k, entry_nr simply can't be
negative and hence the conditonal guarding issuing of the message will
never be true.

This is XSA-130.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
2015-06-02 15:07:00 +00:00
Jan Beulich
7611dae8a6 xen: don't allow guest to control MSI mask register
It's being used by the hypervisor. For now simply mimic a device not
capable of masking, and fully emulate any accesses a guest may issue
nevertheless as simple reads/writes without side effects.

This is XSA-129.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
2015-06-02 15:07:00 +00:00
Jan Beulich
5c83b2f5b4 xen: properly gate host writes of modified PCI CFG contents
The old logic didn't work as intended when an access spanned multiple
fields (for example a 32-bit access to the location of the MSI Message
Data field with the high 16 bits not being covered by any known field).
Remove it and derive which fields not to write to from the accessed
fields' emulation masks: When they're all ones, there's no point in
doing any host write.

This fixes a secondary issue at once: We obviously shouldn't make any
host write attempt when already the host read failed.

This is XSA-128.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
2015-06-02 15:07:00 +00:00
Eric Auger
11d306b9df hw/arm/sysbus-fdt: helpers for platform bus nodes addition
This new C module will be used by ARM machine files to generate
platform bus node and their dynamic sysbus device tree nodes.

Dynamic sysbus device node addition is done in a machine init
done notifier. arm_register_platform_bus_fdt_creator does the
registration of this latter and is supposed to be called by
ARM machine files that support platform bus and their dynamic
sysbus. Addition of dynamic sysbus nodes is done only if the
user did not provide any dtb.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Eric Auger <eric.auger@linaro.org>
Reviewed-by: Shannon Zhao <zhaoshenglong@huawei.com>
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1433244554-12898-2-git-send-email-eric.auger@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 15:44:28 +01:00
Peter Maydell
4771cd01da target-arm: Remove v8_ prefix from names of non-v8-specific cpreg arrays
The ARMCPRegInfo arrays v8_el3_no_el2_cp_reginfo and v8_el2_cp_reginfo
are actually used on non-v8 CPUs as well. Remove the incorrect v8_
prefix from their names.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 1433182716-6400-1-git-send-email-peter.maydell@linaro.org
2015-06-02 15:32:43 +01:00
Eric Auger
9718e4ae36 arm_gicv2m: set kvm_gsi_direct_mapping and kvm_msi_via_irqfd_allowed
After introduction of kvm_arch_msi_data_to_gsi, kvm_gsi_direct_mapping
now can be set on ARM. Also kvm_msi_via_irqfd_allowed can be set,
depending on kernel irqfd support, hence enabling VIRTIO-PCI with
vhost back-end.

Signed-off-by: Eric Auger <eric.auger@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Eric Auger
1850b6b7d0 kvm: introduce kvm_arch_msi_data_to_gsi
On ARM the MSI data corresponds to the shared peripheral interrupt (SPI)
ID. This latter equals to the SPI index + 32. to retrieve the SPI index,
matching the gsi, an architecture specific function is introduced.

Signed-off-by: Eric Auger <eric.auger@linaro.org>
Acked-by: Christoffer Dall <christoffer.dall@linaro.org>
Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Victor CLEMENT
0b2ff2ceb8 pl061: fix wrong calculation of GPIOMIS register
The masked interrupt status register should be the state of the interrupt
after masking.
There should be a logical AND instead of a logical OR between the
interrupt status and the interrupt mask.

Signed-off-by: Victor CLEMENT <victor.clement@openwide.fr>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 1433154824-6927-1-git-send-email-victor.clement@openwide.fr
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Christoffer Dall
bd204e63a7 target-arm: Add the GICv2m to the virt board
Add a GICv2m device to the virt board to enable MSIs on the generic PCI
host controller.  We allocate 64 SPIs in the IRQ space for now (this can
be increased/decreased later) and map the GICv2m right after the GIC in
the memory map.

Reviewed-by: Eric Auger <eric.auger@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Message-id: 1432897270-7780-5-git-send-email-christoffer.dall@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Christoffer Dall
dfd90a8715 target-arm: Extend the gic node properties
In preparation for adding the GICv2m which requires address specifiers
and is a subnode of the gic, we extend the gic DT definition to specify
the #address-cells and #size-cells properties and add an empty ranges
property properties of the DT node, since this is required to add the
v2m node as a child of the gic node.

Note that we must also expand the irq-map to reference the gic with the
right address-cells as a consequence of this change.

Reviewed-by: Eric Auger <eric.auger@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Message-id: 1432897270-7780-4-git-send-email-christoffer.dall@linaro.org
Suggested-by: Shanker Donthineni <shankerd@codeaurora.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Christoffer Dall
770c58f8d1 arm_gicv2m: Add GICv2m widget to support MSIs
The ARM GICv2m widget is a little device that handles MSI interrupt
writes to a trigger register and ties them to a range of interrupt lines
wires to the GIC.  It has a few status/id registers and the interrupt wires,
and that's about it.

A board instantiates the device by setting the base SPI number and
number SPIs for the frame.  The base-spi parameter is indexed in the SPI
number space only, so base-spi == 0, means IRQ number 32.  When a device
(the PCI host controller) writes to the trigger register, the payload is
the GIC IRQ number, so we have to subtract 32 from that and then index
into our frame of SPIs.

When instantiating a GICv2m device, tell PCI that we have instantiated
something that can deal with MSIs.  We rely on the board actually wiring
up the GICv2m to the PCI host controller.

Reviewed-by: Eric Auger <eric.auger@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Message-id: 1432897270-7780-3-git-send-email-christoffer.dall@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Christoffer Dall
747d009dca target-arm: Add GIC phandle to VirtBoardInfo
Instead of passing the GIC phandle around between functions, add it to
the VirtBoardInfo just like we do for the clock_phandle.  We are about
to add the v2m phandle as well, and it's easier not having to pass
around a bunch of phandles, return multiple values from functions, etc.

Reviewed-by: Eric Auger <eric.auger@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Message-id: 1432897270-7780-2-git-send-email-christoffer.dall@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Markus Armbruster
57b6d95eb4 Revert "target-arm: Avoid g_hash_table_get_keys()"
Since we now require GLib 2.22+ (commit f40685c), we don't have to
work around lack of g_hash_table_get_keys() anymore.

This reverts commit 82a3a11897.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-id: 1432749090-4698-1-git-send-email-armbru@redhat.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Edgar E. Iglesias
8742d49d6f target-arm: Add TLBI_VAE2{IS}
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1432881807-18164-11-git-send-email-edgar.iglesias@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Edgar E. Iglesias
51da90140b target-arm: Add TLBI_ALLE2
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1432881807-18164-10-git-send-email-edgar.iglesias@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Edgar E. Iglesias
bdb9e2d66a target-arm: Add TLBI_ALLE1{IS}
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1432881807-18164-9-git-send-email-edgar.iglesias@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Edgar E. Iglesias
a57633c08f target-arm: Add TTBR0_EL2
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1432881807-18164-8-git-send-email-edgar.iglesias@gmail.com
[PMM: Switch to preferred opc1/crm order for 64-bit AArch32 cpregs;
 drop unneeded use of vmsa_ttbr_writefn]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Edgar E. Iglesias
ff05f37bab target-arm: Add TPIDR_EL2
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1432881807-18164-7-git-send-email-edgar.iglesias@gmail.com
[PMM: reordered fields into preferred opc0/opc1/crn/crm/opc2 order]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Edgar E. Iglesias
b9cb5323bb target-arm: Add SCTLR_EL2
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1432881807-18164-6-git-send-email-edgar.iglesias@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Edgar E. Iglesias
06ec4c8c9f target-arm: Add TCR_EL2
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1432881807-18164-5-git-send-email-edgar.iglesias@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Edgar E. Iglesias
95f949ac3d target-arm: Add MAIR_EL2
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1432881807-18164-4-git-send-email-edgar.iglesias@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Edgar E. Iglesias
a903c449b4 target-arm: Break down TLB_LOCKDOWN
Break down the overly broad wildcard definition of TLB_LOCKDOWN
down to v7 level.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1432881807-18164-3-git-send-email-edgar.iglesias@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 14:56:25 +01:00
Edgar E. Iglesias
3fc827d591 target-arm: Correct check for non-EL3
This fixes a compile warning from clang 3.5 (the assertion
could never fire).

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1432881807-18164-2-git-send-email-edgar.iglesias@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: John Snow <jsnow@redhat.com>
[PMM: added note in commit message that this is fixing a build warning]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 13:22:29 +01:00
Peter Maydell
25611aa12b Merge remote-tracking branch 'remotes/kraxel/tags/pull-input-20150602-1' into staging
virtio-input: two small fixups

# gpg: Signature made Tue Jun  2 09:32:51 2015 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-input-20150602-1:
  virtio-input: make virtio devices follow usual naming convention
  virtio-input: const_le16 and const_le32 not build time constant

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 11:25:12 +01:00
Peter Maydell
ef99b3ee06 Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc build fix

My last pull breaks build on systems with iasl.
Fix this up.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Mon Jun  1 20:41:08 2015 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream:
  acpi: add missing ssdt

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-02 10:20:03 +01:00
Gerd Hoffmann
e63d114b8a virtio-input: make virtio devices follow usual naming convention
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-06-02 10:31:29 +02:00
Michael Mueller
16c9d46d32 virtio-input: const_le16 and const_le32 not build time constant
As the implementation of const_le16 and const_le32 is not build time constant
on big endian systems this need to be fixed.

  CC    hw/input/virtio-input-hid.o
hw/input/virtio-input-hid.c:340:13: error: initializer element is not constant
hw/input/virtio-input-hid.c:340:13: error: (near initialization for ‘virtio_keyboard_config[1].u.ids.bustype’)
...

Signed-off-by: Michael Mueller <mimu@linux.vnet.ibm.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-06-02 10:29:54 +02:00
Markus Armbruster
489653b5db monitor: Change return type of monitor_cur_is_qmp() to bool
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 10:07:16 +02:00
Markus Armbruster
9f3982f2dc monitor: Rename monitor_ctrl_mode() to monitor_is_qmp()
... and change return type to bool.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 10:07:16 +02:00
Markus Armbruster
f994b2587f monitor: Turn int command_mode into bool in_command_mode
While there, inline the pointless qmp_cmd_mode() wrapper.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 10:07:16 +02:00
Markus Armbruster
6a50636f35 monitor: Drop do_qmp_capabilities()'s superfluous QMP check
Superfluous since commit 30f5041 removed it from HMP.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 10:07:15 +02:00
Markus Armbruster
74358f2a16 monitor: Unbox Monitor member mc and rename to qmp
While there, rename its type as well, from MonitorControl to
MonitorQMP.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 10:07:15 +02:00
Markus Armbruster
c83fe23b58 monitor: Rename monitor_control_read(), monitor_control_event()
... to monitor_qmp_read(), monitor_qmp_event().

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 10:07:15 +02:00
Markus Armbruster
7ef6cf6341 monitor: Rename handle_user_command() to handle_hmp_command()
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 10:07:15 +02:00
Markus Armbruster
710aec915d monitor: Limit QError use to command handlers
The previous commits narrowed use of QError to handle_qmp_command()
and its helpers monitor_protocol_emitter(), build_qmp_error_dict().
Narrow it further to just the command handler call: instead of
converting Error to QError throughout handle_qmp_command(), convert
the QError gotten from the command handler to Error, and switch the
helpers from QError to Error.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 10:07:15 +02:00
Markus Armbruster
452e0300a3 monitor: Inline monitor_has_error() into its only caller
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 09:59:14 +02:00
Markus Armbruster
70ea0c5899 monitor: Wean monitor_protocol_emitter() off mon->error
Move mon->error handling to its caller handle_qmp_command().

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 09:59:14 +02:00
Markus Armbruster
4086182fcd monitor: Propagate errors through invalid_qmp_mode()
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 09:59:14 +02:00
Markus Armbruster
ba0510aad4 monitor: Propagate errors through qmp_check_input_obj()
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 09:59:14 +02:00
Markus Armbruster
326283aa5d monitor: Propagate errors through qmp_check_client_args()
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 09:59:14 +02:00
Markus Armbruster
8a4f501c09 monitor: Drop unused "new" HMP command interface
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 09:59:13 +02:00
Markus Armbruster
04e00c92ef monitor: Use trad. command interface for HMP pcie_aer_inject_error
All QMP commands use the "new" handler interface (mhandler.cmd_new).
Most HMP commands still use the traditional interface (mhandler.cmd),
but a few use the "new" one.  Complicates handle_user_command() for no
gain, so I'm converting these to the traditional interface.

pcie_aer_inject_error's implementation is split into the
hmp_pcie_aer_inject_error() and pcie_aer_inject_error_print().  The
former is a peculiar crossbreed between HMP and QMP handler.  On
success, it works like a QMP handler: store QDict through ret_data
parameter, return 0.  Printing the QDict is left to
pcie_aer_inject_error_print().  On failure, it works more like an HMP
handler: print error to monitor, return negative number.

To convert to the traditional interface, turn
pcie_aer_inject_error_print() into a command handler wrapping around
hmp_pcie_aer_inject_error().  By convention, this command handler
should be called hmp_pcie_aer_inject_error(), so rename the existing
hmp_pcie_aer_inject_error() to do_pcie_aer_inject_error().

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 09:59:13 +02:00
Markus Armbruster
318660f84a monitor: Use traditional command interface for HMP device_add
All QMP commands use the "new" handler interface (mhandler.cmd_new).
Most HMP commands still use the traditional interface (mhandler.cmd),
but a few use the "new" one.  Complicates handle_user_command() for no
gain, so I'm converting these to the traditional interface.

For device_add, that's easy: just wrap the obvious hmp_device_add()
around do_device_add().

monitor_user_noop() is now unused, drop it.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 09:59:13 +02:00
Markus Armbruster
072ebe6b03 monitor: Use traditional command interface for HMP drive_del
All QMP commands use the "new" handler interface (mhandler.cmd_new).
Most HMP commands still use the traditional interface (mhandler.cmd),
but a few use the "new" one.  Complicates handle_user_command() for no
gain, so I'm converting these to the traditional interface.

For drive_del, that's easy: hmp_drive_del() sheds its unused last
parameter, and its return value, which the caller ignored anyway.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 09:59:13 +02:00
Markus Armbruster
b8a185bc9a monitor: Convert client_migrate_info to QAPI
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 09:59:13 +02:00
Markus Armbruster
13cadefbda monitor: Improve and document client_migrate_info protocol error
Protocol must be spice, vnc isn't implemented.  Fix up documentation.

Attempts to use vnc or any other unknown protocol yield the misleading
error message "Invalid parameter 'protocol'".  Improve it to
"Parameter 'protocol' expects spice".

Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by. Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 09:59:13 +02:00
Markus Armbruster
84add864eb monitor: Clean up after previous commit
Inline qmp_call_cmd() along with its helper handler_audit() into its
only caller handle_qmp_command(), and simplify the result.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 09:59:13 +02:00
Markus Armbruster
65207c59d9 monitor: Drop broken, unused asynchronous command interface
The asynchronous monitor command interface goes back to commit 940cc30
(Jan 2010).  Added a third case to command execution.  The hope back
then according to the commit message was that all commands get
converted to the asynchronous interface, killing off the other two
cases.  Didn't happen.

The initial asynchronous commands balloon and info balloon were
converted back to synchronous long ago (commit 96637bc and d72f32),
with commit messages calling the asynchronous interface "not fully
working" and "deprecated".  The only other user went away in commit
3b5704b.

New code generally uses synchronous commands and asynchronous events.

What exactly is still "not fully working" with asynchronous commands?
Well, here's a bug that defeats actual asynchronous use pretty
reliably: the reply's ID is wrong (and has always been wrong) unless
you use the command synchronously!  To reproduce, we need an
asynchronous command, so we have to go back before commit 3b5704b.
Run QEMU with spice:

    $ qemu-system-x86_64 -nodefaults -S -spice port=5900,disable-ticketing -qmp stdio
    {"QMP": {"version": {"qemu": {"micro": 94, "minor": 2, "major": 2}, "package": ""}, "capabilities": []}}

Connect a spice client in another terminal:

    $ remote-viewer spice://localhost:5900

Set up a migration destination dummy in a third terminal:

    $ socat TCP-LISTEN:12345 STDIO

Now paste the following into the QMP monitor:

    { "execute": "qmp_capabilities", "id": "i0" }
    { "execute": "client_migrate_info", "id": "i1", "arguments": { "protocol": "spice", "hostname": "localhost", "port": 12345 } }
    { "execute": "query-kvm", "id": "i2" }

Produces two replies immediately, one to qmp_capabilities, and one to
query-kvm:

    {"return": {}, "id": "i0"}
    {"return": {"enabled": false, "present": true}, "id": "i2"}

Both are correct.  Two lines of debug output from libspice-server not
shown.

Now EOF socat's standard input to make it close the connection.  This
makes the asynchronous client_migrate_info complete.  It replies:

    {"return": {}}

Bug: "id": "i1" is missing.  Two lines of debug output from
libspice-server not shown.  Cherry on top: storage for the missing ID
is leaked.

Get rid of this stuff before somebody hurts himself with it.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-02 09:59:13 +02:00
Michael S. Tsirkin
9e472263b0 acpi: add missing ssdt
commit 5cb18b3d7b
    TPM2 ACPI table support

was missing a file, so build with iasl fails
(build without iasl works since it uses the generated
 hex files).

Reported-by: "Daniel P. Berrange" <berrange@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-01 21:40:22 +02:00
Peter Maydell
b821cbe274 Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc, pci, tpm, virtio, vhost enhancements and fixes

A bunch of cleanups and fixes all over the place,
enhancements in TPM, virtio and vhost.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Mon Jun  1 13:19:48 2015 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream: (60 commits)
  vhost-user: add multi queue support
  virtio: make features 64bit wide
  qdev: add 64bit properties
  virtio-mmio: ioeventfd support
  hw/acpi/aml-build: Fix memory leak
  acpi: add aml_while() term
  acpi: add aml_increment() term
  acpi: add aml_shiftright() term
  acpi: add aml_shiftleft() term
  acpi: add aml_index() term
  acpi: add aml_lless() term
  acpi: add aml_add() term
  TPM2 ACPI table support
  tpm: Probe for connected TPM 1.2 or TPM 2
  Extend TPM TIS interface to support TPM 2
  Add stream ID to MSI write
  acpi: Simplify printing to dynamic string
  i386: drop FDC in pc-q35-2.4+ if neither it nor floppy drives are wanted
  i386/pc_q35: don't insist on board FDC if there's no default floppy
  i386/pc: '-drive if=floppy' should imply a board-default FDC
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-01 15:22:46 +01:00
Ouyang Changchun
830d70db69 vhost-user: add multi queue support
Based on patch by Nikolay Nikolaev:
Vhost-user will implement the multi queue support in a similar way
to what vhost already has - a separate thread for each queue.
To enable the multi queue functionality - a new command line parameter
"queues" is introduced for the vhost-user netdev.

Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-01 14:18:55 +02:00
Gerd Hoffmann
019a3edbb2 virtio: make features 64bit wide
Make features 64bit wide everywhere.

On migration a full 64bit guest_features field is sent if one of the
high bits is set, in addition to the lower 32bit guest_features field
which must stay for compatibility reasons.  That way we send the lower
32 feature bits twice, but the code is simpler because we don't have
to split and compose the 64bit features into two 32bit fields.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-01 14:18:55 +02:00
Gerd Hoffmann
fdba6d967e qdev: add 64bit properties
Needed for virtio features which go from 32bit to 64bit with virtio 1.0

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-01 14:18:55 +02:00
Ying-Shiuan Pan
434027badb virtio-mmio: ioeventfd support
set_host_notifier and set_guest_notifiers supported by virtio-mmio now.
Most code copied from virtio-pci.

This makes it possible to use vhost-net with virtio-mmio,
improving performance by about 30%.

The kvm-arm does not yet support irqfd, need to fix the hard-coded part after
kvm-arm gets irqfd support.

Signed-off-by: Ying-Shiuan Pan <yingshiuan.pan@gmail.com>
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-01 14:18:55 +02:00
Shannon Zhao
afcf905cff hw/acpi/aml-build: Fix memory leak
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
2015-06-01 14:18:54 +02:00
Marcel Apfelbaum
68e6b0af78 acpi: add aml_while() term
Add encoding for ACPI DefWhile Opcode.

Reviewed-by: Shannon Zhao <zhaoshenglong@huawei.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-01 14:18:54 +02:00
Marcel Apfelbaum
af39d5363f acpi: add aml_increment() term
Add encoding for ACPI DefIncrement Opcode.

Reviewed-by: Shannon Zhao <zhaoshenglong@huawei.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-01 14:18:54 +02:00
Marcel Apfelbaum
f7bd7b8eb6 acpi: add aml_shiftright() term
Add encoding for ACPI DefShiftRight Opcode.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Shannon Zhao <shannon.zhao@linaro.org>
2015-06-01 14:18:54 +02:00
Marcel Apfelbaum
a57dddddd2 acpi: add aml_shiftleft() term
Add encoding for ACPI DefShiftLeft Opcode.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Shannon Zhao <shannon.zhao@linaro.org>
2015-06-01 14:18:54 +02:00
Marcel Apfelbaum
928b899657 acpi: add aml_index() term
Add encoding for ACPI DefIndex Opcode.

Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Shannon Zhao <shannon.zhao@linaro.org>
2015-06-01 14:18:54 +02:00
Marcel Apfelbaum
96396e2858 acpi: add aml_lless() term
Add encoding for ACPI DefLLess Opcode.

Reviewed-by: Shannon Zhao <zhaoshenglong@huawei.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-01 14:18:54 +02:00
Marcel Apfelbaum
c08cf07042 acpi: add aml_add() term
Add encoding for ACPI DefAdd Opcode.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Marcel Apfelbaum <marcel@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Shannon Zhao <shannon.zhao@linaro.org>
2015-06-01 14:18:54 +02:00
Stefan Berger
5cb18b3d7b TPM2 ACPI table support
Add a TPM2 ACPI table if a TPM 2 is used in the backend.
Also add an SSDT for the TPM 2.

Rename tpm_find() to tpm_get_version() and have this function
return the version of the TPM found, TPMVersion_Unspec if
no TPM is found. Use the version number to build version
specific ACPI tables.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-06-01 14:18:54 +02:00
Peter Maydell
9657cafceb Merge remote-tracking branch 'remotes/bkoppelmann/tags/pull-tricore-20150530' into staging
TriCore bugfixes

# gpg: Signature made Sat May 30 15:50:49 2015 BST using RSA key ID 6B69CA14
# gpg: Good signature from "Bastian Koppelmann <kbastian@mail.uni-paderborn.de>"

* remotes/bkoppelmann/tags/pull-tricore-20150530:
  target-tricore: fix BOL_ST_H_LONGOFF using ld
  target-tricore: fix msub32_q producing the wrong overflow bit
  target-tricore: fix OPC2_32_RR_DVINIT_HU having write before use on the result

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-06-01 11:29:37 +01:00
Stefan Berger
56a3c24ffc tpm: Probe for connected TPM 1.2 or TPM 2
In the TPM passthrough backend driver, modify the probing code so
that we can check whether a TPM 1.2 or TPM 2 is being used
and adapt the behavior of the TPM TIS accordingly.

Move the code that tested for a TPM 1.2 into tpm_utils.c
and extend it with test for probing for TPM 2. Have the
function return the version of TPM found.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 20:29:02 +02:00
Stefan Berger
116694c34a Extend TPM TIS interface to support TPM 2
Following the recent upgrade to version 1.3, extend the TPM TIS
interface with capabilities introduced for support of a TPM 2.

TPM TIS for TPM 2 introduced the following extensions beyond the
TPM TIS 1.3 (used for TPM 1.2):

- A new 32bit interface Id register was introduced.
- New flags for the status (STS) register were defined.
- New flags for the capability flags were defined.

Support the above if a TPM TIS 1.3 for TPM 2 is used with a TPM 2
on the backend side. Support the old TPM TIS 1.3 configuration if a
TPM 1.2 is being used. A subsequent patch will then determine which
TPM version is being used in the backend.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 20:29:02 +02:00
Pavel Fedin
38d40ff10f Add stream ID to MSI write
GICv3 ITS distinguishes between devices by using hardwired device IDs passed on the bus.
This patch implements passing these IDs in qemu.
SMMU is also known to use stream IDs, therefore this addition can also be useful for
implementing platforms with SMMU.

Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>

 Changes from v1:
- Added bus number to the stream ID
- Added stream ID not only to MSI-X, but also to plain MSI. Some common code was made into
msi_send_message() function.
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 20:29:02 +02:00
Markus Armbruster
c3bdc56c18 acpi: Simplify printing to dynamic string
build_append_namestringv() and aml_string() first calculate the
resulting string's length with vsnprintf(NULL, ...), then allocate,
then print for real.  Simply use g_strdup_vprintf() or g_vasprintf()
instead.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
2015-05-31 20:24:07 +02:00
Laszlo Ersek
ea96bc629c i386: drop FDC in pc-q35-2.4+ if neither it nor floppy drives are wanted
It is Very annoying to carry forward an outdatEd coNtroller with a mOdern
Machine type.

Hence, let us not instantiate the FDC when all of the following apply:
- the machine type is pc-q35-2.4 or later,
- "-device isa-fdc" is not passed on the command line (nor in the config
  file),
- no "-drive if=floppy,..." is requested.

Cc: Markus Armbruster <armbru@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: John Snow <jsnow@redhat.com>
Cc: "Gabriel L. Somlo" <gsomlo@gmail.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: qemu-block@nongnu.org
Suggested-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
2015-05-31 20:24:07 +02:00
Laszlo Ersek
6cd2234ccb i386/pc_q35: don't insist on board FDC if there's no default floppy
The "no_floppy = 1" machine class setting causes "default_floppy" in
main() to become zero. Consequently, default_drive() will not call
drive_add() and drive_new() for IF_FLOPPY, index=0, meaning that no
default floppy drive will be created for the virtual machine. In that
case, board code should also not insist on the creation of the
board-default FDC.

The board-default FDC will still be created if the user requests a floppy
drive with "-drive if=floppy".

Additionally, separate FDCs can be specified manually with "-device
isa-fdc". They allow the

  -device isa-fdc,driveA=...

syntax that is more flexible than the one required by the board-default
FDC:

  -global isa-fdc.driveA=...

This patch doesn't change the behavior observably, as all Q35 machine
types have "no_floppy = 0".

Cc: Markus Armbruster <armbru@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: John Snow <jsnow@redhat.com>
Cc: "Gabriel L. Somlo" <gsomlo@gmail.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: qemu-block@nongnu.org
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
2015-05-31 20:24:06 +02:00
Laszlo Ersek
936a7c1cf7 i386/pc: '-drive if=floppy' should imply a board-default FDC
Even if board code decides not to request the creation of the FDC (keyed
off board-level factors, to be determined later), we should create the FDC
nevertheless if the user passes '-drive if=floppy' on the command line.

Otherwise '-drive if=floppy' would break without explicit '-device
isa-fdc' on such boards.

Cc: Markus Armbruster <armbru@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: John Snow <jsnow@redhat.com>
Cc: "Gabriel L. Somlo" <gsomlo@gmail.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: qemu-block@nongnu.org
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
2015-05-31 20:24:06 +02:00
Laszlo Ersek
fd53c87cf6 i386/pc: pc_basic_device_init(): delegate FDC creation request
This patch introduces no observable change, but it allows the callers of
pc_basic_device_init(), ie. pc_init1() and pc_q35_init(), to request (or
not request) the creation of the FDC explicitly.

At the moment both callers pass constant create_fdctrl=true (hence no
observable change).

Assuming a board passes create_fdctrl=false, "floppy" will be NULL on
output, and (beyond the FDC not being created) that NULL will be passed on
to pc_cmos_init(). Luckily, pc_cmos_init() already handles that case.

Cc: Markus Armbruster <armbru@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: John Snow <jsnow@redhat.com>
Cc: "Gabriel L. Somlo" <gsomlo@gmail.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: qemu-block@nongnu.org
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
2015-05-31 20:24:06 +02:00
Jason Wang
b829c2a98f virtio: increase the queue limit to 1024
Increase the queue limit to 1024. But virtio-ccw and s390-virtio won't
support this, this is done through failing device_plugged() for those
two transports if the number of virtqueues is greater than 64.

Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:50:10 +02:00
Jason Wang
87b3bd1c85 virtio: rename VIRTIO_PCI_QUEUE_MAX to VIRTIO_QUEUE_MAX
VIRTIO_PCI_QUEUE_MAX is not only used for pci, so rename it be generic.

Cc: Amit Shah <amit.shah@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:50:10 +02:00
Jason Wang
d820331a0b virtio-s390: introduce virtio_s390_device_plugged()
This patch introduce a virtio-s390 specific device_plugged() function
and doing the number of virtqueue validation inside.

Cc: Alexander Graf <agraf@suse.de>
Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:47:50 +02:00
Jason Wang
74c85296dc virtio-s390: introduce virito s390 queue limit
Cc: Alexander Graf <agraf@suse.de>
Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:45:38 +02:00
Jason Wang
10ceaa1e8f virtio-ccw: validate the number of queues against bus limitation
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Alexander Graf <agraf@suse.de>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:45:38 +02:00
Jason Wang
8dfbaa6ac4 virtio-ccw: introduce ccw specific queue limit
Cc: Alexander Graf <agraf@suse.de>
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:45:38 +02:00
Jason Wang
8ad176aaed virtio: introduce virtio_get_num_queues()
This patch introduces virtio_get_num_queues() which iterates the vqs
array and return the number of virtqueues used by device.

Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:45:38 +02:00
Jason Wang
e83980455c virtio: device_plugged() can fail
This patch passes error pointer to transport specific device_plugged()
callback. Through this way, device_plugged() can do some transport
specific check and fail. This will be uesd by following patches that
check the number of virtqueues against the transport limitation.

Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Alexander Graf <agraf@suse.de>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:44:12 +02:00
Jason Wang
da51a335aa virtio-net: adding all queues in .realize()
Instead of adding queues for multiqueue during feature set. This patch
did this in .realize(), this will help the following patches that
count the number of virtqueues used in .device_plugged() callback.

Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:40:48 +02:00
Cornelia Huck
cf34f533a1 virtio: move VIRTIO_F_NOTIFY_ON_EMPTY into core
Nearly all transports have been offering VIRTIO_F_NOTIFY_ON_EMPTY,
s390-virtio being the exception. There's no reason why it shouldn't
offer it as well, though (handling is done in core anyway), so let's
move it to the common virtio features.

While we're changing it anyway, fix the indentation for the
DEFINE_VIRTIO_COMMON_FEATURES macro.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:27:25 +02:00
Cornelia Huck
13644819c5 virtio-ccw: Don't advertise VIRTIO_F_BAD_FEATURE
This was copied from virtio-pci, but it doesn't make much sense for
ccw, as it doesn't have to handle the broken implementations this bit
is supposed to deal with. Remove it.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:27:23 +02:00
Cornelia Huck
6b8f102054 virtio: move host_features
Move host_features from the individual transport proxies into
the virtio device. Transports may continue to add feature bits
during device plugging.

This should it make easier to offer different sets of host features
for virtio-1/transitional support.

Tested-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:27:18 +02:00
Radim Krčmář
2332333c97 pc: acpi: fix pvpanic for buggy guests
In the old times, we always had pvpanic in ACPI and a _STA method told
the guest not to use it.  Automatic generation dropped the _STA method
as the specification says that missing _STA means enabled and working.
Some guests (Linux) had buggy drivers and this change made them unable
to utilize pvpanic.

A Linux patch is posted as well, but I think it's worth to make pvpanic
useable on old guests at the price of three lines and few bytes of SSDT.

The old _STA method was
  Method (_STA, 0, NotSerialized) {
      Store (PEST, Local0)
      If (LEqual (Local0, Zero)) {
          Return (Zero) }
      Else {
          Return (0x0F) }}

Igor pointed out that we don't need to use a method to return a constant
and that 0xB (don't show in UI) is the common definition now.

Also, the device used to be PEVT.  (PEVT as in "panic event"?)

Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:42 +02:00
Eduardo Habkost
99fbeafee8 pc: Generate init functions with a macro
All pc-i440fx and pc-q35 init functions simply call the corresponding
compat function and then call the main init function. Use a macro to
generate that code.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:42 +02:00
Eduardo Habkost
211b5b1d0a piix: Eliminate pc_init_pci()
The function is not needed anymore, we can simply call pc_init1()
directly.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:42 +02:00
Eduardo Habkost
72d164aa73 piix: Add kvmclock_enabled, pci_enabled globals
This looks like a step backwards, but it will allow pc-0.1[0123] and
isapc to follow the same compat+init pattern used by the other
machine-types, allowing us to generate all init function using the same
macro later.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:42 +02:00
Eduardo Habkost
d48f4fa69e machine: Remove unused fields from QEMUMachine
This removes the following fields from QEMUMachine: family, alias,
reset, hot_add_cpu, units_per_default_bus, no_serial, no_parallel,
use_virtcon, use_sclp, no_floppy, no_cdrom, default_display,
compat_props, and hw_version.

The only users of those fields were already converted to use QOM and
MachineClass directly, so they are not needed anymore.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:42 +02:00
Eduardo Habkost
d644b11657 pc: Remove qemu_register_pc_machine() function
The helper is not needed anymore, as the PC machine classes are
registered using QOM directly.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:42 +02:00
Eduardo Habkost
865906f7fd pc: Don't use QEMUMachine anymore
Now that we have a DEFINE_PC_MACHINE helper macro that just requires an
initialization function, it is trivial to convert them to register a QOM
machine class directly, instead of using QEMUMachine.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:42 +02:00
Eduardo Habkost
25519b062c pc: Move compat_props setting inside *_machine_options() functions
This will simplify the DEFINE_PC_MACHINE macro, and will help us to
implement reuse of PC_COMPAT_* macros through class_init function reuse,
in the future.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:42 +02:00
Eduardo Habkost
fddd179ab9 pc: Convert *_MACHINE_OPTIONS macros into functions
By now the new functions will get QEMUMachine as argument, but they will
be later converted to initialize a MachineClass struct directly.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:42 +02:00
Eduardo Habkost
61f219dfb0 pc: Define machines using a DEFINE_PC_MACHINE macro
This will automatically generate the existing QEMUMachine structs based
on the *_MACHINE_OPTIONS macros, and automatically add registration code
for them.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:42 +02:00
Eduardo Habkost
b6b5c8e492 pc: Define MACHINE_OPTIONS macros consistently for all machines
Define a MACHINE_OPTIONS macro for each PC machine, and move every field
inside the QEMUMachine structs to the macros, except for name, init, and
compat_props.

This also ensures that all MACHINE_OPTIONS inherit the fields from the
next version, so their definitions carry only the changes that exist
between one version and the next one.

Comments about specific cases:

pc-*-2.1:

  Existing PC_*_2_1_MACHINE_OPTIONS macros were defined as:
      PC_*_MACHINE_OPTIONS,
      .default_machine_opts = "firmware=bios-256k.bin"

  PC_*_2_2_MACHINE_OPTIONS is:
      PC_*_2_3_MACHINE_OPTIONS
  which is expanded to:
      PC_*_MACHINE_OPTIONS,
      .default_machine_opts = "firmware=bios-256k.bin",
      .default_display = "std"

  The only difference between 2_1 and 2_2 is .default_display, that's why
  we didn't reuse PC_*_2_2_MACHINE_OPTIONS. The good news is that having
  multiple initializers for a field is allowed by C99, and the last
  initializer overrides the previous ones.

  So we can reuse the 2_2 macro in 2_1 and define PC_*_2_1_MACHINE_OPTIONS
  as:
      PC_*_2_2_MACHINE_OPTIONS,
      .default_display = NULL

pc-*-1.7:

  PC_*_1_7_MACHINE_OPTIONS was defined as:
      PC_*_MACHINE_OPTIONS

  PC_*_2_0_MACHINE_OPTIONS is defined as:
      PC_*_2_1_MACHINE_OPTIONS
  which is expanded to:
      PC_*_2_2_MACHINE_OPTIONS,
      .default_display = NULL
  which is expanded to:
      PC_*_2_3_MACHINE_OPTIONS,
      .default_display = NULL
  which is expanded to:
      PC_*_MACHINE_OPTIONS,
      .default_machine_opts = "firmware=bios-256k.bin",
      .default_display = "std",
      .default_display = NULL  /* overrides the previous line */

  So, the only difference between PC_*_1_7_MACHINE_OPTIONS and
  PC_*_2_0_MACHINE_OPTIONS is .default_machine_opts (as .default_display
  is not explicitly set by PC_*_MACHINE_OPTIONS so it is NULL).

  So we can keep the macro reuse pattern and define
  PC_*_2_0_MACHINE_OPTIONS as:
      PC_*_2_0_MACHINE_OPTIONS,
      .default_machine_opts = NULL

pc-*-2.4 (alias and is_default fields):

  Set alias and is_default fields inside the 2.4 MACHINE_OPTIONS macro,
  and clear it in the 2.3 macro (that reuses the 2.4 macro).

hw_machine:

  As all the machines older than v1.0 set hw_version explicitly, we can
  safely move the field to the MACHINE_OPTIONS macros without affecting
  the other versions that reuse them.

init function:

  Some machines had the init function set inside the MACHINE_OPTIONS
  macro. Move it to the QEMUMachine declaration, to keep it consistent
  with the other machines.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:42 +02:00
Eduardo Habkost
f6d5a0bad2 piix: Define PC_COMPAT_0_10
Move compat_props from pc-0.10 to the macro, to make it consistent with
the other machines.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:41 +02:00
Eduardo Habkost
faf7e4254f piix: Move pc-0.1[23] rombar compat props to PC_COMPAT_0_13
The VGA and vmware-svga rombar compat properties were added by commit
281a26b15b, but only to pc-0.13 and
pc-0.12. This breaks the PC_COMPAT_* nesting pattern we currently
follow.

The new variables will now be inherited by pc-0.11 and older, but
pc-0.11 and pc-0.10 already have PCI.rombar=0 on compat_props, so they
shouldn't be affected at all.

Cc: Stefan Weil <sw@weilnetz.de>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:41 +02:00
Eduardo Habkost
d765519bef piix: Move pc-0.13 virtio-9p-pci compat to PC_COMPAT_0_13
The compat property was added by commit
9dbcca5aa1, and the pc-0.12 and older
machine-types were not changed because virtio-9p-pci was introduced on QEMU
0.13 (commit 9f10751365). The only problem is
that this breaks the PC_COMPAT_* nesting pattern we currently use.

So, move the property to PC_COMPAT_0_13. This make pc-0.12 and older inherit
it, but that shouldn't be an issue as QEMU 0.12 didn't have virtio-9p-pci.

Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:41 +02:00
Eduardo Habkost
d5303df710 piix: Move pc-0.11 drive version compat props to PC_COMPAT_0_11
The current code setting ide-drive.ver and scsi-disk.ver on pc-0.11
breaks the PC_COMPAT_* nesting pattern we currently use.

As those variables are overwritten in pc-0.10 too, they can be inherited
by pc-0.10 with no side-effects at all.

Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:41 +02:00
Eduardo Habkost
bb08d8829b piix: Move pc-0.14 qxl compat properties to PC_COMPAT_0_14
Those properties were introduced by commit
3827cdb1c3. They were not duplicated into
pc-0.13 and older because 0.14 was the first QEMU version supporting
qxl. The only problem is that this breaks the PC_COMPAT_* nesting
pattern we currently use.

So, move the properties to PC_COMPAT_0_14. This makes pc-0.13 and older
inherit them, but that shouldn't be an issue as QEMU 0.13 didn't support
qxl.

Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:41 +02:00
Eduardo Habkost
38ff32c6e6 spapr: define SPAPR_COMPAT_2_3
Don't add the pseries-2.3 machine yet, but define the corresponding
SPAPR_COMPAT macro to make sure both pseries-2.2 and pseries-2.1 will
inherit HW_COMPAT_2_3.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:41 +02:00
Eduardo Habkost
4dfd8eaa19 spapr: Use HW_COMPAT_* inside SPAPR_COMPAT_* macros
SPAPR_COMPAT_2_1 will need to include both HW_COMPAT_2_2 and
HW_COMPAT_2_1, so include HW_COMPAT_2_1 inside SPAPR_COMPAT_2_1 and
HW_COMPAT_2_2 inside SPAPR_COMPAT_2_2.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:41 +02:00
Eduardo Habkost
42134ac9d7 pc: Define PC_COMPAT_2_[123] macros
Once we start adding compat code for pc-2.3, the usage of HW_COMPAT_2_1
in pc-*-2.2 won't be enough, as it also has to include PC_COMPAT_2_3
inside it. To ensure that, define PC_COMPAT_2_3, PC_COMPAT_2_2, and
PC_COMPAT_2_1 macros.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:41 +02:00
Eduardo Habkost
1edbde82b8 hw: Define empty HW_COMPAT_2_[23] macros
Now we can make everything consistent and define the macros even if they
are still empty.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:41 +02:00
Eduardo Habkost
dd754baf46 spapr: Move commas inside SPAPR_COMPAT_* macros
Changing the convention to include commas inside the macros will allow
macros containing empty lists to be defined and used without compilation
errors.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:41 +02:00
Eduardo Habkost
a7cde24dc2 pc: Move commas inside PC_COMPAT_* macros
Changing the convention to include commas inside the macros will allow
macros containing empty lists to be defined and used without compilation
errors.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:41 +02:00
Eduardo Habkost
f27086a731 hw: Move commas inside HW_COMPAT_2_1 macro
Changing the convention to include commas inside the macros will allow
macros containing empty lists to be defined and used without compilation
errors.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:41 +02:00
Eduardo Habkost
4974920ab8 pc: Replace tab with spaces
Coding style change only.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-05-31 16:26:41 +02:00
Shannon Zhao
ecfa60e374 hw/s390x/virtio-ccw: use alias property for virtio-balloon-ccw
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
2015-05-31 16:26:41 +02:00
Shannon Zhao
39b87c7b9f hw/virtio/virtio-pci: use alias property for virtio-balloon-pci
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
2015-05-31 16:26:41 +02:00
Shannon Zhao
1190044ea5 hw/virtio/virtio-balloon: move adding property to virtio_balloon_instance_init
This is in preparation for using alias property in virtio-balloon-pci
and virtio-balloon-ccw.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
2015-05-31 16:26:41 +02:00
Bastian Koppelmann
07e15486fa target-tricore: fix BOL_ST_H_LONGOFF using ld
Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Message-Id: <1432289758-6250-4-git-send-email-kbastian@mail.uni-paderborn.de>
2015-05-30 16:49:19 +02:00
Bastian Koppelmann
9bbd4843c0 target-tricore: fix msub32_q producing the wrong overflow bit
The inversion of the overflow bit as a special case, which was needed for the
madd32_q instructions, does not apply for msub32_q instructions. So remove it.

Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Message-Id: <1432289758-6250-3-git-send-email-kbastian@mail.uni-paderborn.de>
2015-05-30 16:49:17 +02:00
Bastian Koppelmann
05b6ca9bbc target-tricore: fix OPC2_32_RR_DVINIT_HU having write before use on the result
If the argument r1 was the same as the extended result register r3+1, we would
overwrite r1 and then use it.

Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Message-Id: <1432289758-6250-2-git-send-email-kbastian@mail.uni-paderborn.de>
2015-05-30 16:49:14 +02:00
Peter Maydell
97af820f53 Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20150529' into staging
target-arm:
 * Support ACPI for ARMv8 systems using the 'virt' board
   (and a UEFI boot image, typically)
 * avoid buffer overrun in some UNPREDICTABLE ldrd/strd cases
 * further work preparing for 64-bit EL2/EL3 support

# gpg: Signature made Fri May 29 12:14:06 2015 BST using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"

* remotes/pmaydell/tags/pull-target-arm-20150529: (39 commits)
  target-arm: Avoid buffer overrun on UNPREDICTABLE ldrd/strd
  hw/arm/virt: Enable dynamic generation of ACPI v5.1 tables
  ACPI: split CONFIG_ACPI into 4 pieces
  hw/arm/virt-acpi-build: Add PCIe controller in ACPI DSDT table
  hw/acpi/aml-build: Add Unicode macro
  hw/acpi/aml-build: Add aml_dword_io() term
  hw/acpi/aml-build: Add aml_create_dword_field() term
  hw/acpi/aml-build: Add aml_else() term
  hw/acpi/aml-build: Add aml_lnot() term
  hw/acpi/aml-build: Add aml_or() term
  hw/acpi/aml-build: Add ToUUID macro
  hw/acpi/aml-build: Make aml_buffer() definition consistent with the spec
  hw/arm/virt-acpi-build: Generate MCFG table
  hw/arm/virt-acpi-build: Generate RSDP table
  hw/arm/virt-acpi-build: Generate RSDT table
  hw/arm/virt-acpi-build: Generate GTDT table
  hw/arm/virt-acpi-build: Generate MADT table
  hw/arm/virt-acpi-build: Generate FADT table and update ACPI headers
  hw/arm/virt-acpi-build: Generation of DSDT table for virt devices
  hw/acpi/aml-build: Add aml_interrupt() term
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 17:10:57 +01:00
Peter Maydell
2cc3bdbe2d Merge remote-tracking branch 'remotes/armbru/tags/pull-block-2015-05-29' into staging
Block QAPI, monitor, command line patches

# gpg: Signature made Fri May 29 12:02:32 2015 BST using RSA key ID EB918653
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>"
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>"

* remotes/armbru/tags/pull-block-2015-05-29:
  qapi: add dirty bitmap status

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 15:32:15 +01:00
Peter Maydell
2a90c454a1 Merge remote-tracking branch 'remotes/kraxel/tags/pull-gtk-20150529-1' into staging
gtk: add opengl rendering support.
small bugfixes for gtk and opengl ui code.

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

* remotes/kraxel/tags/pull-gtk-20150529-1:
  gtk: Replace gdk_cursor_new()
  gtk: add opengl support, using egl
  ui: add egl-helpers
  ui: shader.h protect against double inclusion
  ui: use libexpoxy

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 14:24:35 +01:00
John Snow
9abe3bdc45 qapi: add dirty bitmap status
Bitmaps can be in a handful of different states with potentially
more to come as we tool around with migration and persistence patches.

Management applications may need to know why certain bitmaps are
unavailable for various commands, e.g. busy in another operation,
busy being migrated, etc.

Right now, all we offer is BlockDirtyInfo's boolean member 'frozen'.
Instead of adding more booleans, replace it by an enumeration member
'status' with values 'active' and 'frozen'.  Then add new value
'disabled'.

Incompatible change.  Fine because the changed part hasn't been
released so far.

Suggested-by: Eric Blake <eblake@redhat.com>
Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[Commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-05-29 12:53:12 +02:00
Peter Maydell
3960c336ad target-arm: Avoid buffer overrun on UNPREDICTABLE ldrd/strd
A LDRD or STRD where rd is not an even number is UNPREDICTABLE.
We were letting this fall through, which is OK unless rd is 15,
in which case we would attempt to do a load_reg or store_reg
to a nonexistent r16 for the second half of the double-word.
Catch the odd-numbered-rd cases and UNDEF them instead.

To do this we rearrange the structure of the code a little
so we can put the UNDEF catches at the top before we've
allocated TCG temporaries.

Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1431348973-21315-1-git-send-email-peter.maydell@linaro.org
2015-05-29 11:29:00 +01:00
Shannon Zhao
d7c2e2db28 hw/arm/virt: Enable dynamic generation of ACPI v5.1 tables
Initialize VirtGuestInfoState and register a machine_init_done notify to
call virt_acpi_build().

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Message-id: 1432522520-8068-25-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:59 +01:00
Shannon Zhao
135a67a692 ACPI: split CONFIG_ACPI into 4 pieces
As core.c, piix4.c, ich9.c and pcihp.c are for x86, add CONFIG_ACPI_X86
to make it only for x86. ARM doesn't support cpu and memory hotplug, add
CONFIG_ACPI_CPU_HOTPLUG and CONFIG_ACPI_MEMORY_HOTPLUG to exclude them
for target-arm.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1432522520-8068-24-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:59 +01:00
Shannon Zhao
d4e5de1ae0 hw/arm/virt-acpi-build: Add PCIe controller in ACPI DSDT table
Add PCIe controller in ACPI DSDT table, so the guest can detect
the PCIe.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Message-id: 1432522520-8068-23-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:59 +01:00
Shannon Zhao
e1f776c434 hw/acpi/aml-build: Add Unicode macro
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-id: 1432522520-8068-22-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:59 +01:00
Shannon Zhao
616ef329ad hw/acpi/aml-build: Add aml_dword_io() term
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-id: 1432522520-8068-21-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:58 +01:00
Shannon Zhao
ed8176a37a hw/acpi/aml-build: Add aml_create_dword_field() term
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-id: 1432522520-8068-20-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:58 +01:00
Shannon Zhao
467b07dfae hw/acpi/aml-build: Add aml_else() term
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-id: 1432522520-8068-19-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:58 +01:00
Shannon Zhao
ea7df04a02 hw/acpi/aml-build: Add aml_lnot() term
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-id: 1432522520-8068-18-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:58 +01:00
Shannon Zhao
922cc8823e hw/acpi/aml-build: Add aml_or() term
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-id: 1432522520-8068-17-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:58 +01:00
Shannon Zhao
b930fb9db4 hw/acpi/aml-build: Add ToUUID macro
Add ToUUID macro, this is useful for generating PCIe ACPI table.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-id: 1432522520-8068-16-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:57 +01:00
Shannon Zhao
ed8b5847e4 hw/acpi/aml-build: Make aml_buffer() definition consistent with the spec
According to ACPI spec, DefBuffer can take two parameters: BufferSize
and ByteList. Make it consistent with the spec. Uninitialized buffer
could be requested by passing ByteList as NULL to reserve space.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-id: 1432522520-8068-15-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:57 +01:00
Shannon Zhao
8434488400 hw/arm/virt-acpi-build: Generate MCFG table
Generate MCFG table for PCIe controller.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1432522520-8068-14-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:57 +01:00
Shannon Zhao
d4bec5d876 hw/arm/virt-acpi-build: Generate RSDP table
RSDP points to RSDT which in turn points to other tables.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1432522520-8068-13-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:56 +01:00
Shannon Zhao
243bdb79fb hw/arm/virt-acpi-build: Generate RSDT table
RSDT points to other tables FADT, MADT, GTDT. This code is shared with x86.

Here we still use RSDT as UEFI puts ACPI tables below 4G address space,
and UEFI ignore the RSDT or XSDT.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1432522520-8068-12-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:56 +01:00
Shannon Zhao
ee246400c1 hw/arm/virt-acpi-build: Generate GTDT table
ACPI v5.1 defines GTDT for ARM devices as a place to describe timer
related information in the system. The Arch Timer interrupts must
be provided for GTDT.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1432522520-8068-11-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:56 +01:00
Shannon Zhao
982d06c561 hw/arm/virt-acpi-build: Generate MADT table
MADT describes GIC enabled ARM platforms. The GICC and GICD
subtables are used to define the GIC regions.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1432522520-8068-10-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:56 +01:00
Shannon Zhao
c2f7c0c306 hw/arm/virt-acpi-build: Generate FADT table and update ACPI headers
In the case of mach virt, it is used to set the Hardware Reduced bit
and enable PSCI SMP booting through HVC. So ignore FACS and FADT
points to DSDT.

Update the header definitions for FADT taking into account the new
additions of ACPI v5.1 in `include/hw/acpi/acpi-defs.h`

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Message-id: 1432522520-8068-9-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:55 +01:00
Shannon Zhao
dfccd8cfd7 hw/arm/virt-acpi-build: Generation of DSDT table for virt devices
DSDT consists of the usual common table header plus a definition
block in AML encoding which describes all devices in the platform.

After initializing DSDT with header information the namespace is
created which is followed by the device encodings. The devices are
described using the Resource Template for the 32-Bit Fixed Memory
Range and the Extended Interrupt Descriptors.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1432522520-8068-8-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:55 +01:00
Shannon Zhao
205d1d1c04 hw/acpi/aml-build: Add aml_interrupt() term
Add aml_interrupt() for describing device interrupt in resource template.
These can be used to generating DSDT table for ACPI on ARM.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-id: 1432522520-8068-7-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:55 +01:00
Shannon Zhao
dc17ab1de5 hw/acpi/aml-build: Add aml_memory32_fixed() term
Add aml_memory32_fixed() for describing device mmio region in resource
template. These can be used to generating DSDT table for ACPI on ARM.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-id: 1432522520-8068-6-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:55 +01:00
Shannon Zhao
f5d8c8cd79 hw/arm/virt-acpi-build: Basic framework for building ACPI tables on ARM
Introduce a preliminary framework in virt-acpi-build.c with the main
ACPI build functions. It exposes the generated ACPI contents to
guest over fw_cfg.

The required ACPI v5.1 tables for ARM are:
- RSDP: Initial table that points to XSDT
- RSDT: Points to FADT GTDT MADT tables
- FADT: Generic information about the machine
- GTDT: Generic timer description table
- MADT: Multiple APIC description table
- DSDT: Holds all information about system devices/peripherals, pointed by FADT

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-id: 1432522520-8068-5-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:54 +01:00
Shannon Zhao
6a1f001be3 hw/arm/virt: Record PCIe ranges in MemMapEntry array
To generate ACPI table for PCIe controller, we need the base and size of
the PCIe ranges. Record these ranges in MemMapEntry array, then we could
share and use them for generating ACPI table.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Message-id: 1432522520-8068-4-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:54 +01:00
Shannon Zhao
afe0b3803f hw/arm/virt: Move common definitions to virt.h
Move some common definitions to virt.h. These will be used by
generating ACPI tables.

Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 1432522520-8068-3-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:54 +01:00
Shannon Zhao
ff80dc7fa8 hw/acpi/aml-build: Make enum values to be upper case to match coding style
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Message-id: 1432522520-8068-2-git-send-email-zhaoshenglong@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:54 +01:00
Greg Bellows
b1eced713d target-arm: Add WFx instruction trap support
Add support for trapping WFI and WFE instructions to the proper EL when
SCTLR/SCR/HCR settings apply.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
[PMM: removed unnecessary tweaking of syn_wfx() prototype;
 use raise_exception();
 don't trap on WFE (and add comment explaining why not);
 remove unnecessary ARM_FEATURE checks;
 trap to EL3, not EL1, if in S-EL0 and SCTLR check fires]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2015-05-29 11:28:53 +01:00
Peter Maydell
84549b6dcf target-arm: Don't halt on WFI unless we don't have any work
Just NOP the WFI instruction if we have work to do.
This doesn't make much difference currently (though it does avoid
jumping out to the top level loop and immediately restarting),
but the distinction between "halt" and "don't halt" will become
more important when the decision to halt requires us to trap
to a higher exception level instead.

Suggested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2015-05-29 11:28:53 +01:00
Peter Maydell
647f767ba3 target-arm: Move TB flags down to fill gap
Deleting the now-unused ARM_TBFLAG_CPACR_FPEN left a gap in the
bit usage; move the following ARM_TBFLAG_XSCALE_CPAR and
ARM_TBFLAG_NS_SHIFT down 3 bits to fill the gap.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2015-05-29 11:28:53 +01:00
Greg Bellows
9dbbc748d6 target-arm: Extend FP checks to use an EL
Extend the ARM disassemble context to take a target exception EL instead of a
boolean enable. This change reverses the polarity of the check making a value
of 0 indicate floating point enabled (no exception).

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
[PMM: Use a common TB flag field for AArch32 and AArch64;
 CPTR_EL2 exists in v7; CPTR_EL2 should trap for EL2 accesses;
 CPTR_EL2 should not trap for secure accesses; CPTR_EL3
 should trap for EL3 accesses; CPACR traps for secure
 accesses should trap to EL3 if EL3 is AArch32]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2015-05-29 11:28:53 +01:00
Peter Maydell
3cf6a0fced target-arm: Make singlestate TB flags common between AArch32/64
Currently we keep the TB flags PSTATE_SS and SS_ACTIVE in different
bit positions for AArch64 and AArch32. Replace these separate
definitions with a single common flag in the upper part of the
flags word.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2015-05-29 11:28:52 +01:00
Greg Bellows
c6f191642a target-arm: Add AArch64 CPTR registers
Adds CPTR_EL2/3 system registers definitions and access function.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
[PMM: merge CPTR_EL2 and HCPTR definitions into a single
 def using STATE_BOTH;
 don't use readfn/writefn to implement RAZ/WI registers;
 don't use accessfn for the no-EL2 CPTR_EL2;
 fix cpacr_access logic to catch EL2 accesses to CPACR being
 trapped to EL3;
 use new CP_ACCESS_TRAP_EL[23] rather than setting
 exception.target_el directly]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2015-05-29 11:28:52 +01:00
Peter Maydell
38836a2cd4 target-arm: Allow cp access functions to indicate traps to EL2 or EL3
Some coprocessor access functions will need to indicate that the
instruction should trap to EL2 or EL3 rather than the default
target exception level; add corresponding CPAccessResult enum
entries and handling code.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2015-05-29 11:28:52 +01:00
Greg Bellows
012a906b19 target-arm: Update interrupt handling to use target EL
Updated the interrupt handling to utilize and report through the target EL
exception field.  This includes consolidating and cleaning up code where
needed. Target EL is now calculated once in arm_cpu_exec_interrupt() and
do_interrupt was updated to use the target_el exception field.  The
necessary code from arm_excp_target_el() was merged in where needed and the
function removed.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1429722561-12651-4-git-send-email-greg.bellows@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:51 +01:00
Peter Maydell
c63285991b target-arm: Make raise_exception() take syndrome and target EL
Rather than making every caller of raise_exception set the
syndrome and target EL by hand, make these arguments to
raise_exception() and have that do the job.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2015-05-29 11:28:51 +01:00
Peter Maydell
863b6589d7 target-arm: Set exception target EL in tlb_fill
Set the exception target EL for MMU faults in tlb_fill.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2015-05-29 11:28:51 +01:00
Peter Maydell
8c6084bf10 target-arm: Move setting of exception info into tlb_fill
Move the code which sets exception information out of
arm_cpu_handle_mmu_fault and into tlb_fill. tlb_fill
is the only caller which wants to raise_exception()
so it makes more sense for it to handle the whole of
the exception setup.

As part of this cleanup, move the user-mode-only
implementation function for the handle_mmu_fault CPU
method into cpu.c so we don't need to make it globally
visible, and rename the softmmu-only utility function
arm_cpu_handle_mmu_fault to arm_tlb_fill so it's clear
that it's not the same thing.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2015-05-29 11:28:51 +01:00
Peter Maydell
f2932df777 target-arm: Set correct syndrome for faults on MSR DAIF*, imm
If the SCTLR.UMA trap bit is set then attempts by EL0 to update
the PSTATE DAIF bits via "MSR DAIFSet, imm" and "MSR DAIFClr, imm"
instructions will raise an exception. We were failing to set
the syndrome information for this exception, which meant that
it would be reported as a repeat of whatever the previous
exception was. Set the correct syndrome information.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2015-05-29 11:28:50 +01:00
Greg Bellows
e3b1d48099 target-arm: Extend helpers to route exceptions
Updated the various helper routines to set the target EL as needed using a
dedicated function.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1429722561-12651-3-git-send-email-greg.bellows@linaro.org
[PMM: Also set target_el in fault cases in access_check_cp_reg()]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:50 +01:00
Greg Bellows
7371036198 target-arm: Add exception target el infrastructure
Add a CPU state exception target EL field that will be used for communicating
the EL to which an exception should be routed.

Add a disassembly context field for tracking the EL3 architecture needed for
determining the target exception EL.

Add a target EL argument to the generic exception helper for callers to specify
the EL to which the exception should be routed.  Extended the helper to set
the newly added CPU state exception target el.

Added a function for setting the target exception EL and updated calls to helpers
to call it.

Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1429722561-12651-2-git-send-email-greg.bellows@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:28:50 +01:00
Peter Maydell
9441aa282b Merge remote-tracking branch 'remotes/kraxel/tags/pull-input-20150529-1' into staging
kbd: add support for brazilian keyboard (two extra keys).
input: add virtio-input devices.

# gpg: Signature made Fri May 29 10:09:02 2015 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-input-20150529-1:
  virtio-input: emulated devices [device]
  virtio-input: core code & base class [device]
  virtio-input: add linux/input.h
  kbd: add brazil kbd keys to x11 evdev map
  kbd: add brazil kbd keys to qemu

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 11:23:07 +01:00
Max Reitz
63c67b6d44 gtk: Replace gdk_cursor_new()
gdk_cursor_new() has been deprecated in GTK 3.16, it is recommended to
use gdk_cursor_new_for_display() instead, so do that.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Cole Robinson <crobinso@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-05-29 11:43:29 +02:00
Gerd Hoffmann
97edf3bd5e gtk: add opengl support, using egl
This adds opengl rendering support to the gtk ui, using egl.
It's off by default for now, use 'qemu -display gtk,gl=on'
to play with this.

Note that gtk got native opengl support with release 3.16.
There most likely will be a separate implementation for 3.16+,
using the native gtk opengl support.  This patch covers older
versions (and for the time being 3.16 too, hopefully without
rendering quirks).

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-05-29 11:43:29 +02:00
Peter Maydell
ba7c388963 Merge remote-tracking branch 'remotes/spice/tags/pull-spice-20150529-1' into staging
spice: misc fixes.

# gpg: Signature made Fri May 29 09:16:29 2015 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/spice/tags/pull-spice-20150529-1:
  spice: fix spice_chr_add_watch() pre-condition
  spice: don't update mm_time when spice-server is stopped.
  spice-char: notify the server when chardev is writable
  virtio-console: notify chardev when writable

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-05-29 10:17:49 +01:00
Gerd Hoffmann
7ced9e9f6d ui: add egl-helpers
Add helper functions to initialize OpenGL using egl.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2015-05-29 11:11:38 +02:00
Gerd Hoffmann
896e1a050a ui: shader.h protect against double inclusion
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2015-05-29 11:11:38 +02:00
Gerd Hoffmann
dcf30025c3 ui: use libexpoxy
libepoxy does the opengl extension handling for us.

It also is helpful for trouble-shooting as it prints nice error messages
instead of silently failing or segfaulting in case we do something
wrong, like using gl commands not supported by the current context.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2015-05-29 11:11:38 +02:00
Marc-André Lureau
f7a8beb5e6 spice: fix spice_chr_add_watch() pre-condition
Since e02bc6de30, add_watch() is called
with G_IO_HUP. Even if spice-qemu-char ignores this flag, the
precondition must be changed.

https://bugzilla.redhat.com/show_bug.cgi?id=1128992

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-05-29 09:56:01 +02:00
Gerd Hoffmann
641381c1fc spice: don't update mm_time when spice-server is stopped.
Skip mm_time updates (in qxl device memory) in case the guest is stopped.
Guest isn't able to look anyway, and it causes problems with migration.

Also make sure the initial state for spice server is stopped.

Reported-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-05-29 09:56:01 +02:00
Marc-André Lureau
e95e203c08 spice-char: notify the server when chardev is writable
The spice server is polling on write, unless
SPICE_CHAR_DEVICE_NOTIFY_WRITABLE flag is set. In this case, qemu must
call spice_server_char_device_wakeup() when the frontend is writable.

Signed-off-by: Marc-André Lureau <marcandre.lureau@gmail.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-05-29 09:56:01 +02:00
Marc-André Lureau
246ca55faf virtio-console: notify chardev when writable
When the virtio serial is writable, notify the chardev backend
with qemu_chr_accept_input().

Signed-off-by: Marc-André Lureau <marcandre.lureau@gmail.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-05-29 09:56:01 +02:00
319 changed files with 13214 additions and 4232 deletions

View File

@@ -486,7 +486,8 @@ F: hw/ppc/prep.c
F: hw/pci-host/prep.[hc] F: hw/pci-host/prep.[hc]
F: hw/isa/pc87312.[hc] F: hw/isa/pc87312.[hc]
sPAPR sPAPR (pseries)
M: David Gibson <david@gibson.dropbear.id.au>
M: Alexander Graf <agraf@suse.de> M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org L: qemu-ppc@nongnu.org
S: Supported S: Supported

View File

@@ -389,13 +389,8 @@ ifneq (,$(findstring qemu-ga,$(TOOLS)))
endif endif
endif endif
install-confdir:
$(INSTALL_DIR) "$(DESTDIR)$(qemu_confdir)"
install-sysconfig: install-datadir install-confdir install: all $(if $(BUILD_DOCS),install-doc) \
$(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/target-x86_64.conf "$(DESTDIR)$(qemu_confdir)"
install: all $(if $(BUILD_DOCS),install-doc) install-sysconfig \
install-datadir install-localstatedir install-datadir install-localstatedir
ifneq ($(TOOLS),) ifneq ($(TOOLS),)
$(call install-prog,$(TOOLS),$(DESTDIR)$(bindir)) $(call install-prog,$(TOOLS),$(DESTDIR)$(bindir))

View File

@@ -76,6 +76,8 @@ common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y) common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y)
common-obj-$(CONFIG_FDT) += device_tree.o
###################################################################### ######################################################################
# qapi # qapi

View File

@@ -1,5 +1,7 @@
# -*- Mode: makefile -*- # -*- Mode: makefile -*-
BUILD_DIR?=$(CURDIR)/..
include ../config-host.mak include ../config-host.mak
include config-target.mak include config-target.mak
include config-devices.mak include config-devices.mak
@@ -129,7 +131,6 @@ ifdef CONFIG_SOFTMMU
obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o numa.o obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o numa.o
obj-y += qtest.o bootdevice.o obj-y += qtest.o bootdevice.o
obj-y += hw/ obj-y += hw/
obj-$(CONFIG_FDT) += device_tree.o
obj-$(CONFIG_KVM) += kvm-all.o obj-$(CONFIG_KVM) += kvm-all.o
obj-y += memory.o savevm.o cputlb.o obj-y += memory.o savevm.o cputlb.o
obj-y += memory_mapping.o obj-y += memory_mapping.o

View File

@@ -136,7 +136,6 @@ static struct defconfig_file {
bool userconfig; bool userconfig;
} default_config_files[] = { } default_config_files[] = {
{ CONFIG_QEMU_CONFDIR "/qemu.conf", true }, { CONFIG_QEMU_CONFDIR "/qemu.conf", true },
{ CONFIG_QEMU_CONFDIR "/target-" TARGET_NAME ".conf", true },
{ NULL }, /* end of list */ { NULL }, /* end of list */
}; };
@@ -610,52 +609,10 @@ ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
return (next - base) << TARGET_PAGE_BITS; return (next - base) << TARGET_PAGE_BITS;
} }
static inline bool migration_bitmap_set_dirty(ram_addr_t addr)
{
bool ret;
int nr = addr >> TARGET_PAGE_BITS;
ret = test_and_set_bit(nr, migration_bitmap);
if (!ret) {
migration_dirty_pages++;
}
return ret;
}
static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length) static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length)
{ {
ram_addr_t addr; migration_dirty_pages +=
unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS); cpu_physical_memory_sync_dirty_bitmap(migration_bitmap, start, length);
/* start address is aligned at the start of a word? */
if (((page * BITS_PER_LONG) << TARGET_PAGE_BITS) == start) {
int k;
int nr = BITS_TO_LONGS(length >> TARGET_PAGE_BITS);
unsigned long *src = ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION];
for (k = page; k < page + nr; k++) {
if (src[k]) {
unsigned long new_dirty;
new_dirty = ~migration_bitmap[k];
migration_bitmap[k] |= src[k];
new_dirty &= src[k];
migration_dirty_pages += ctpopl(new_dirty);
src[k] = 0;
}
}
} else {
for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) {
if (cpu_physical_memory_get_dirty(start + addr,
TARGET_PAGE_SIZE,
DIRTY_MEMORY_MIGRATION)) {
cpu_physical_memory_reset_dirty(start + addr,
TARGET_PAGE_SIZE,
DIRTY_MEMORY_MIGRATION);
migration_bitmap_set_dirty(start + addr);
}
}
}
} }

View File

@@ -96,6 +96,20 @@ bool tpm_backend_get_tpm_established_flag(TPMBackend *s)
return k->ops->get_tpm_established_flag(s); return k->ops->get_tpm_established_flag(s);
} }
int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
return k->ops->reset_tpm_established_flag(s, locty);
}
TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
return k->ops->get_tpm_version(s);
}
static bool tpm_backend_prop_get_opened(Object *obj, Error **errp) static bool tpm_backend_prop_get_opened(Object *obj, Error **errp)
{ {
TPMBackend *s = TPM_BACKEND(obj); TPMBackend *s = TPM_BACKEND(obj);

13
block.c
View File

@@ -3116,6 +3116,17 @@ bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap)
return !(bitmap->disabled || bitmap->successor); return !(bitmap->disabled || bitmap->successor);
} }
DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap)
{
if (bdrv_dirty_bitmap_frozen(bitmap)) {
return DIRTY_BITMAP_STATUS_FROZEN;
} else if (!bdrv_dirty_bitmap_enabled(bitmap)) {
return DIRTY_BITMAP_STATUS_DISABLED;
} else {
return DIRTY_BITMAP_STATUS_ACTIVE;
}
}
/** /**
* Create a successor bitmap destined to replace this bitmap after an operation. * Create a successor bitmap destined to replace this bitmap after an operation.
* Requires that the bitmap is not frozen and has no successor. * Requires that the bitmap is not frozen and has no successor.
@@ -3256,7 +3267,7 @@ BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
info->granularity = bdrv_dirty_bitmap_granularity(bm); info->granularity = bdrv_dirty_bitmap_granularity(bm);
info->has_name = !!bm->name; info->has_name = !!bm->name;
info->name = g_strdup(bm->name); info->name = g_strdup(bm->name);
info->frozen = bdrv_dirty_bitmap_frozen(bm); info->status = bdrv_dirty_bitmap_status(bm);
entry->value = info; entry->value = info;
*plist = entry; *plist = entry;
plist = &entry->next; plist = &entry->next;

View File

@@ -216,10 +216,9 @@ static int get_event_by_name(const char *name, BlkDebugEvent *event)
struct add_rule_data { struct add_rule_data {
BDRVBlkdebugState *s; BDRVBlkdebugState *s;
int action; int action;
Error **errp;
}; };
static int add_rule(QemuOpts *opts, void *opaque) static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
{ {
struct add_rule_data *d = opaque; struct add_rule_data *d = opaque;
BDRVBlkdebugState *s = d->s; BDRVBlkdebugState *s = d->s;
@@ -230,10 +229,10 @@ static int add_rule(QemuOpts *opts, void *opaque)
/* Find the right event for the rule */ /* Find the right event for the rule */
event_name = qemu_opt_get(opts, "event"); event_name = qemu_opt_get(opts, "event");
if (!event_name) { if (!event_name) {
error_setg(d->errp, "Missing event name for rule"); error_setg(errp, "Missing event name for rule");
return -1; return -1;
} else if (get_event_by_name(event_name, &event) < 0) { } else if (get_event_by_name(event_name, &event) < 0) {
error_setg(d->errp, "Invalid event name \"%s\"", event_name); error_setg(errp, "Invalid event name \"%s\"", event_name);
return -1; return -1;
} }
@@ -319,8 +318,7 @@ static int read_config(BDRVBlkdebugState *s, const char *filename,
d.s = s; d.s = s;
d.action = ACTION_INJECT_ERROR; d.action = ACTION_INJECT_ERROR;
d.errp = &local_err; qemu_opts_foreach(&inject_error_opts, add_rule, &d, &local_err);
qemu_opts_foreach(&inject_error_opts, add_rule, &d, 1);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
ret = -EINVAL; ret = -EINVAL;
@@ -328,7 +326,7 @@ static int read_config(BDRVBlkdebugState *s, const char *filename,
} }
d.action = ACTION_SET_STATE; d.action = ACTION_SET_STATE;
qemu_opts_foreach(&set_state_opts, add_rule, &d, 1); qemu_opts_foreach(&set_state_opts, add_rule, &d, &local_err);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
ret = -EINVAL; ret = -EINVAL;

View File

@@ -1323,13 +1323,6 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
const char *filename; const char *filename;
int i, ret = 0; int i, ret = 0;
if ((BDRV_SECTOR_SIZE % 512) != 0) {
error_setg(errp, "iSCSI: Invalid BDRV_SECTOR_SIZE. "
"BDRV_SECTOR_SIZE(%lld) is not a multiple "
"of 512", BDRV_SECTOR_SIZE);
return -EINVAL;
}
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err); qemu_opts_absorb_qdict(opts, options, &local_err);
if (local_err) { if (local_err) {

View File

@@ -2113,7 +2113,7 @@ void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
aio_context_release(aio_context); aio_context_release(aio_context);
} }
int hmp_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) void hmp_drive_del(Monitor *mon, const QDict *qdict)
{ {
const char *id = qdict_get_str(qdict, "id"); const char *id = qdict_get_str(qdict, "id");
BlockBackend *blk; BlockBackend *blk;
@@ -2124,14 +2124,14 @@ int hmp_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
blk = blk_by_name(id); blk = blk_by_name(id);
if (!blk) { if (!blk) {
error_report("Device '%s' not found", id); error_report("Device '%s' not found", id);
return -1; return;
} }
bs = blk_bs(blk); bs = blk_bs(blk);
if (!blk_legacy_dinfo(blk)) { if (!blk_legacy_dinfo(blk)) {
error_report("Deleting device added with blockdev-add" error_report("Deleting device added with blockdev-add"
" is not supported"); " is not supported");
return -1; return;
} }
aio_context = bdrv_get_aio_context(bs); aio_context = bdrv_get_aio_context(bs);
@@ -2140,7 +2140,7 @@ int hmp_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) { if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) {
error_report_err(local_err); error_report_err(local_err);
aio_context_release(aio_context); aio_context_release(aio_context);
return -1; return;
} }
/* quiesce block driver; prevent further io */ /* quiesce block driver; prevent further io */
@@ -2163,7 +2163,6 @@ int hmp_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
} }
aio_context_release(aio_context); aio_context_release(aio_context);
return 0;
} }
void qmp_block_resize(bool has_device, const char *device, void qmp_block_resize(bool has_device, const char *device,

View File

@@ -108,10 +108,6 @@ void cpu_list_unlock(void)
/***********************************************************/ /***********************************************************/
/* CPUX86 core interface */ /* CPUX86 core interface */
void cpu_smm_update(CPUX86State *env)
{
}
uint64_t cpu_get_tsc(CPUX86State *env) uint64_t cpu_get_tsc(CPUX86State *env)
{ {
return cpu_get_real_ticks(); return cpu_get_real_ticks();

12
configure vendored
View File

@@ -353,7 +353,7 @@ for opt do
;; ;;
--cpu=*) cpu="$optarg" --cpu=*) cpu="$optarg"
;; ;;
--extra-cflags=*) QEMU_CFLAGS="$optarg $QEMU_CFLAGS" --extra-cflags=*) QEMU_CFLAGS="$QEMU_CFLAGS $optarg"
EXTRA_CFLAGS="$optarg" EXTRA_CFLAGS="$optarg"
;; ;;
--extra-ldflags=*) LDFLAGS="$optarg $LDFLAGS" --extra-ldflags=*) LDFLAGS="$optarg $LDFLAGS"
@@ -3115,9 +3115,11 @@ fi
if test "$fdt" != "no" ; then if test "$fdt" != "no" ; then
fdt_libs="-lfdt" fdt_libs="-lfdt"
# explicitly check for libfdt_env.h as it is missing in some stable installs # explicitly check for libfdt_env.h as it is missing in some stable installs
# and test for required functions to make sure we are on a version >= 1.4.0
cat > $TMPC << EOF cat > $TMPC << EOF
#include <libfdt.h>
#include <libfdt_env.h> #include <libfdt_env.h>
int main(void) { return 0; } int main(void) { fdt_get_property_by_offset(0, 0, 0); return 0; }
EOF EOF
if compile_prog "" "$fdt_libs" ; then if compile_prog "" "$fdt_libs" ; then
# system DTC is good - use it # system DTC is good - use it
@@ -3135,7 +3137,7 @@ EOF
fdt_libs="-L\$(BUILD_DIR)/dtc/libfdt $fdt_libs" fdt_libs="-L\$(BUILD_DIR)/dtc/libfdt $fdt_libs"
elif test "$fdt" = "yes" ; then elif test "$fdt" = "yes" ; then
# have neither and want - prompt for system/submodule install # have neither and want - prompt for system/submodule install
error_exit "DTC (libfdt) not present. Your options:" \ error_exit "DTC (libfdt) version >= 1.4.0 not present. Your options:" \
" (1) Preferred: Install the DTC (libfdt) devel package" \ " (1) Preferred: Install the DTC (libfdt) devel package" \
" (2) Fetch the DTC submodule, using:" \ " (2) Fetch the DTC submodule, using:" \
" git submodule update --init dtc" " git submodule update --init dtc"
@@ -3166,14 +3168,14 @@ else
fi fi
if test "$opengl" != "no" ; then if test "$opengl" != "no" ; then
opengl_pkgs="gl glesv2" opengl_pkgs="gl glesv2 epoxy egl"
if $pkg_config $opengl_pkgs x11 && test "$have_glx" = "yes"; then if $pkg_config $opengl_pkgs x11 && test "$have_glx" = "yes"; then
opengl_cflags="$($pkg_config --cflags $opengl_pkgs) $x11_cflags" opengl_cflags="$($pkg_config --cflags $opengl_pkgs) $x11_cflags"
opengl_libs="$($pkg_config --libs $opengl_pkgs) $x11_libs" opengl_libs="$($pkg_config --libs $opengl_pkgs) $x11_libs"
opengl=yes opengl=yes
else else
if test "$opengl" = "yes" ; then if test "$opengl" = "yes" ; then
feature_not_found "opengl" "Install GL devel (e.g. MESA)" feature_not_found "opengl" "Please install opengl (mesa) devel pkgs: $opengl_pkgs"
fi fi
opengl_cflags="" opengl_cflags=""
opengl_libs="" opengl_libs=""

84
cpus.c
View File

@@ -105,6 +105,7 @@ static bool all_cpu_threads_idle(void)
/* Protected by TimersState seqlock */ /* Protected by TimersState seqlock */
static bool icount_sleep = true;
static int64_t vm_clock_warp_start = -1; static int64_t vm_clock_warp_start = -1;
/* Conversion factor from emulated instructions to virtual clock ticks. */ /* Conversion factor from emulated instructions to virtual clock ticks. */
static int icount_time_shift; static int icount_time_shift;
@@ -393,15 +394,18 @@ void qemu_clock_warp(QEMUClockType type)
return; return;
} }
/* if (icount_sleep) {
* If the CPUs have been sleeping, advance QEMU_CLOCK_VIRTUAL timer now. /*
* This ensures that the deadline for the timer is computed correctly below. * If the CPUs have been sleeping, advance QEMU_CLOCK_VIRTUAL timer now.
* This also makes sure that the insn counter is synchronized before the * This ensures that the deadline for the timer is computed correctly
* CPU starts running, in case the CPU is woken by an event other than * below.
* the earliest QEMU_CLOCK_VIRTUAL timer. * This also makes sure that the insn counter is synchronized before
*/ * the CPU starts running, in case the CPU is woken by an event other
icount_warp_rt(NULL); * than the earliest QEMU_CLOCK_VIRTUAL timer.
timer_del(icount_warp_timer); */
icount_warp_rt(NULL);
timer_del(icount_warp_timer);
}
if (!all_cpu_threads_idle()) { if (!all_cpu_threads_idle()) {
return; return;
} }
@@ -415,6 +419,11 @@ void qemu_clock_warp(QEMUClockType type)
clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT); clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT);
deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL); deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
if (deadline < 0) { if (deadline < 0) {
static bool notified;
if (!icount_sleep && !notified) {
error_report("WARNING: icount sleep disabled and no active timers");
notified = true;
}
return; return;
} }
@@ -425,23 +434,35 @@ void qemu_clock_warp(QEMUClockType type)
* interrupt to wake it up, but the interrupt never comes because * interrupt to wake it up, but the interrupt never comes because
* the vCPU isn't running any insns and thus doesn't advance the * the vCPU isn't running any insns and thus doesn't advance the
* QEMU_CLOCK_VIRTUAL. * QEMU_CLOCK_VIRTUAL.
*
* An extreme solution for this problem would be to never let VCPUs
* sleep in icount mode if there is a pending QEMU_CLOCK_VIRTUAL
* timer; rather time could just advance to the next QEMU_CLOCK_VIRTUAL
* event. Instead, we do stop VCPUs and only advance QEMU_CLOCK_VIRTUAL
* after some "real" time, (related to the time left until the next
* event) has passed. The QEMU_CLOCK_VIRTUAL_RT clock will do this.
* This avoids that the warps are visible externally; for example,
* you will not be sending network packets continuously instead of
* every 100ms.
*/ */
seqlock_write_lock(&timers_state.vm_clock_seqlock); if (!icount_sleep) {
if (vm_clock_warp_start == -1 || vm_clock_warp_start > clock) { /*
vm_clock_warp_start = clock; * We never let VCPUs sleep in no sleep icount mode.
* If there is a pending QEMU_CLOCK_VIRTUAL timer we just advance
* to the next QEMU_CLOCK_VIRTUAL event and notify it.
* It is useful when we want a deterministic execution time,
* isolated from host latencies.
*/
seqlock_write_lock(&timers_state.vm_clock_seqlock);
timers_state.qemu_icount_bias += deadline;
seqlock_write_unlock(&timers_state.vm_clock_seqlock);
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
} else {
/*
* We do stop VCPUs and only advance QEMU_CLOCK_VIRTUAL after some
* "real" time, (related to the time left until the next event) has
* passed. The QEMU_CLOCK_VIRTUAL_RT clock will do this.
* This avoids that the warps are visible externally; for example,
* you will not be sending network packets continuously instead of
* every 100ms.
*/
seqlock_write_lock(&timers_state.vm_clock_seqlock);
if (vm_clock_warp_start == -1 || vm_clock_warp_start > clock) {
vm_clock_warp_start = clock;
}
seqlock_write_unlock(&timers_state.vm_clock_seqlock);
timer_mod_anticipate(icount_warp_timer, clock + deadline);
} }
seqlock_write_unlock(&timers_state.vm_clock_seqlock);
timer_mod_anticipate(icount_warp_timer, clock + deadline);
} else if (deadline == 0) { } else if (deadline == 0) {
qemu_clock_notify(QEMU_CLOCK_VIRTUAL); qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
} }
@@ -504,9 +525,18 @@ void configure_icount(QemuOpts *opts, Error **errp)
} }
return; return;
} }
icount_sleep = qemu_opt_get_bool(opts, "sleep", true);
if (icount_sleep) {
icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
icount_warp_rt, NULL);
}
icount_align_option = qemu_opt_get_bool(opts, "align", false); icount_align_option = qemu_opt_get_bool(opts, "align", false);
icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
icount_warp_rt, NULL); if (icount_align_option && !icount_sleep) {
error_setg(errp, "align=on and sleep=no are incompatible");
}
if (strcmp(option, "auto") != 0) { if (strcmp(option, "auto") != 0) {
errno = 0; errno = 0;
icount_time_shift = strtol(option, &rem_str, 0); icount_time_shift = strtol(option, &rem_str, 0);
@@ -517,6 +547,8 @@ void configure_icount(QemuOpts *opts, Error **errp)
return; return;
} else if (icount_align_option) { } else if (icount_align_option) {
error_setg(errp, "shift=auto and align=on are incompatible"); error_setg(errp, "shift=auto and align=on are incompatible");
} else if (!icount_sleep) {
error_setg(errp, "shift=auto and sleep=no are incompatible");
} }
use_icount = 2; use_icount = 2;

View File

@@ -125,14 +125,13 @@ void tlb_flush_page(CPUState *cpu, target_ulong addr)
can be detected */ can be detected */
void tlb_protect_code(ram_addr_t ram_addr) void tlb_protect_code(ram_addr_t ram_addr)
{ {
cpu_physical_memory_reset_dirty(ram_addr, TARGET_PAGE_SIZE, cpu_physical_memory_test_and_clear_dirty(ram_addr, TARGET_PAGE_SIZE,
DIRTY_MEMORY_CODE); DIRTY_MEMORY_CODE);
} }
/* update the TLB so that writes in physical page 'phys_addr' are no longer /* update the TLB so that writes in physical page 'phys_addr' are no longer
tested for self modifying code */ tested for self modifying code */
void tlb_unprotect_code_phys(CPUState *cpu, ram_addr_t ram_addr, void tlb_unprotect_code(ram_addr_t ram_addr)
target_ulong vaddr)
{ {
cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_CODE); cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_CODE);
} }

View File

@@ -101,3 +101,4 @@ CONFIG_ALLWINNER_A10=y
CONFIG_XIO3130=y CONFIG_XIO3130=y
CONFIG_IOH3420=y CONFIG_IOH3420=y
CONFIG_I82801B11=y CONFIG_I82801B11=y
CONFIG_ACPI=y

View File

@@ -15,6 +15,9 @@ CONFIG_PCSPK=y
CONFIG_PCKBD=y CONFIG_PCKBD=y
CONFIG_FDC=y CONFIG_FDC=y
CONFIG_ACPI=y CONFIG_ACPI=y
CONFIG_ACPI_X86=y
CONFIG_ACPI_MEMORY_HOTPLUG=y
CONFIG_ACPI_CPU_HOTPLUG=y
CONFIG_APM=y CONFIG_APM=y
CONFIG_I8257=y CONFIG_I8257=y
CONFIG_IDE_ISA=y CONFIG_IDE_ISA=y

View File

@@ -15,6 +15,9 @@ CONFIG_PCSPK=y
CONFIG_PCKBD=y CONFIG_PCKBD=y
CONFIG_FDC=y CONFIG_FDC=y
CONFIG_ACPI=y CONFIG_ACPI=y
CONFIG_ACPI_X86=y
CONFIG_ACPI_MEMORY_HOTPLUG=y
CONFIG_ACPI_CPU_HOTPLUG=y
CONFIG_APM=y CONFIG_APM=y
CONFIG_I8257=y CONFIG_I8257=y
CONFIG_PIIX4=y CONFIG_PIIX4=y

View File

@@ -15,6 +15,9 @@ CONFIG_PCSPK=y
CONFIG_PCKBD=y CONFIG_PCKBD=y
CONFIG_FDC=y CONFIG_FDC=y
CONFIG_ACPI=y CONFIG_ACPI=y
CONFIG_ACPI_X86=y
CONFIG_ACPI_MEMORY_HOTPLUG=y
CONFIG_ACPI_CPU_HOTPLUG=y
CONFIG_APM=y CONFIG_APM=y
CONFIG_I8257=y CONFIG_I8257=y
CONFIG_PIIX4=y CONFIG_PIIX4=y

View File

@@ -15,6 +15,9 @@ CONFIG_PCSPK=y
CONFIG_PCKBD=y CONFIG_PCKBD=y
CONFIG_FDC=y CONFIG_FDC=y
CONFIG_ACPI=y CONFIG_ACPI=y
CONFIG_ACPI_X86=y
CONFIG_ACPI_MEMORY_HOTPLUG=y
CONFIG_ACPI_CPU_HOTPLUG=y
CONFIG_APM=y CONFIG_APM=y
CONFIG_I8257=y CONFIG_I8257=y
CONFIG_PIIX4=y CONFIG_PIIX4=y

View File

@@ -15,6 +15,9 @@ CONFIG_PCSPK=y
CONFIG_PCKBD=y CONFIG_PCKBD=y
CONFIG_FDC=y CONFIG_FDC=y
CONFIG_ACPI=y CONFIG_ACPI=y
CONFIG_ACPI_X86=y
CONFIG_ACPI_MEMORY_HOTPLUG=y
CONFIG_ACPI_CPU_HOTPLUG=y
CONFIG_APM=y CONFIG_APM=y
CONFIG_I8257=y CONFIG_I8257=y
CONFIG_PIIX4=y CONFIG_PIIX4=y

View File

@@ -15,6 +15,9 @@ CONFIG_PCSPK=y
CONFIG_PCKBD=y CONFIG_PCKBD=y
CONFIG_FDC=y CONFIG_FDC=y
CONFIG_ACPI=y CONFIG_ACPI=y
CONFIG_ACPI_X86=y
CONFIG_ACPI_MEMORY_HOTPLUG=y
CONFIG_ACPI_CPU_HOTPLUG=y
CONFIG_APM=y CONFIG_APM=y
CONFIG_I8257=y CONFIG_I8257=y
CONFIG_IDE_ISA=y CONFIG_IDE_ISA=y

View File

@@ -18,7 +18,6 @@
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include "config.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "sysemu/device_tree.h" #include "sysemu/device_tree.h"

View File

@@ -0,0 +1,58 @@
PCI EXPANDER BRIDGE (PXB)
=========================
Description
===========
PXB is a "light-weight" host bridge in the same PCI domain
as the main host bridge whose purpose is to enable
the main host bridge to support multiple PCI root buses.
It is implemented only for i440fx and can be placed only
on bus 0 (pci.0).
As opposed to PCI-2-PCI bridge's secondary bus, PXB's bus
is a primary bus and can be associated with a NUMA node
(different from the main host bridge) allowing the guest OS
to recognize the proximity of a pass-through device to
other resources as RAM and CPUs.
Usage
=====
A detailed command line would be:
[qemu-bin + storage options]
-m 2G
-object memory-backend-ram,size=1024M,policy=bind,host-nodes=0,id=ram-node0 -numa node,nodeid=0,cpus=0,memdev=ram-node0
-object memory-backend-ram,size=1024M,policy=bind,host-nodes=1,id=ram-node1 -numa node,nodeid=1,cpus=1,memdev=ram-node1
-device pxb,id=bridge1,bus=pci.0,numa_node=1,bus_nr=4 -netdev user,id=nd-device e1000,bus=bridge1,addr=0x4,netdev=nd
-device pxb,id=bridge2,bus=pci.0,numa_node=0,bus_nr=8,bus=pci.0 -device e1000,bus=bridge2,addr=0x3
-device pxb,id=bridge3,bus=pci.0,bus_nr=40,bus=pci.0 -drive if=none,id=drive0,file=[img] -device virtio-blk-pci,drive=drive0,scsi=off,bus=bridge3,addr=1
Here you have:
- 2 NUMA nodes for the guest, 0 and 1. (both mapped to the same NUMA node in host, but you can and should put it in different host NUMA nodes)
- a pxb host bridge attached to NUMA 1 with an e1000 behind it
- a pxb host bridge attached to NUMA 0 with an e1000 behind it
- a pxb host bridge not attached to any NUMA with a hard drive behind it.
Limitations
===========
Please observe that we specified the bus "pci.0" for the second and third pxb.
This is because when no bus is given, another pxb can be selected by QEMU as default bus,
however, PXBs can be placed only under the root bus.
Implementation
==============
The PXB is composed by:
- HostBridge (TYPE_PXB_HOST)
The host bridge allows to register and query the PXB's rPCI root bus in QEMU.
- PXBDev(TYPE_PXB_DEVICE)
It is a regular PCI Device that resides on the piix host-bridge bus and its bus uses the same PCI domain.
However, the bus behind is exposed through ACPI as a primary PCI bus and starts a new PCI hierarchy.
The interrupts from devices behind the PXB are routed through this device the same as if it were a
PCI-2-PCI bridge. The _PRT follows the i440fx model.
- PCIBridgeDev(TYPE_PCI_BRIDGE_DEV)
Created automatically as part of init sequence.
When adding a device to PXB it is attached to the bridge for two reasons:
- Using the bridge will enable hotplug support
- All the devices behind the bridge will use bridge's IO/MEM windows compacting
the PCI address space.

View File

@@ -0,0 +1,287 @@
= sPAPR Dynamic Reconfiguration =
sPAPR/"pseries" guests make use of a facility called dynamic-reconfiguration
to handle hotplugging of dynamic "physical" resources like PCI cards, or
"logical"/paravirtual resources like memory, CPUs, and "physical"
host-bridges, which are generally managed by the host/hypervisor and provided
to guests as virtualized resources. The specifics of dynamic-reconfiguration
are documented extensively in PAPR+ v2.7, Section 13.1. This document
provides a summary of that information as it applies to the implementation
within QEMU.
== Dynamic-reconfiguration Connectors ==
To manage hotplug/unplug of these resources, a firmware abstraction known as
a Dynamic Resource Connector (DRC) is used to assign a particular dynamic
resource to the guest, and provide an interface for the guest to manage
configuration/removal of the resource associated with it.
== Device-tree description of DRCs ==
A set of 4 Open Firmware device tree array properties are used to describe
the name/index/power-domain/type of each DRC allocated to a guest at
boot-time. There may be multiple sets of these arrays, rooted at different
paths in the device tree depending on the type of resource the DRCs manage.
In some cases, the DRCs themselves may be provided by a dynamic resource,
such as the DRCs managing PCI slots on a hotplugged PHB. In this case the
arrays would be fetched as part of the device tree retrieval interfaces
for hotplugged resources described under "Guest->Host interface".
The array properties are described below. Each entry/element in an array
describes the DRC identified by the element in the corresponding position
of ibm,drc-indexes:
ibm,drc-names:
first 4-bytes: BE-encoded integer denoting the number of entries
each entry: a NULL-terminated <name> string encoded as a byte array
<name> values for logical/virtual resources are defined in PAPR+ v2.7,
Section 13.5.2.4, and basically consist of the type of the resource
followed by a space and a numerical value that's unique across resources
of that type.
<name> values for "physical" resources such as PCI or VIO devices are
defined as being "location codes", which are the "location labels" of
each encapsulating device, starting from the chassis down to the
individual slot for the device, concatenated by a hyphen. This provides
a mapping of resources to a physical location in a chassis for debugging
purposes. For QEMU, this mapping is less important, so we assign a
location code that conforms to naming specifications, but is simply a
location label for the slot by itself to simplify the implementation.
The naming convention for location labels is documented in detail in
PAPR+ v2.7, Section 12.3.1.5, and in our case amounts to using "C<n>"
for PCI/VIO device slots, where <n> is unique across all PCI/VIO
device slots.
ibm,drc-indexes:
first 4-bytes: BE-encoded integer denoting the number of entries
each 4-byte entry: BE-encoded <index> integer that is unique across all DRCs
in the machine
<index> is arbitrary, but in the case of QEMU we try to maintain the
convention used to assign them to pSeries guests on pHyp:
bit[31:28]: integer encoding of <type>, where <type> is:
1 for CPU resource
2 for PHB resource
3 for VIO resource
4 for PCI resource
8 for Memory resource
bit[27:0]: integer encoding of <id>, where <id> is unique across
all resources of specified type
ibm,drc-power-domains:
first 4-bytes: BE-encoded integer denoting the number of entries
each 4-byte entry: 32-bit, BE-encoded <index> integer that specifies the
power domain the resource will be assigned to. In the case of QEMU
we associated all resources with a "live insertion" domain, where the
power is assumed to be managed automatically. The integer value for
this domain is a special value of -1.
ibm,drc-types:
first 4-bytes: BE-encoded integer denoting the number of entries
each entry: a NULL-terminated <type> string encoded as a byte array
<type> is assigned as follows:
"CPU" for a CPU
"PHB" for a physical host-bridge
"SLOT" for a VIO slot
"28" for a PCI slot
"MEM" for memory resource
== Guest->Host interface to manage dynamic resources ==
Each DRC is given a globally unique DRC Index, and resources associated with
a particular DRC are configured/managed by the guest via a number of RTAS
calls which reference individual DRCs based on the DRC index. This can be
considered the guest->host interface.
rtas-set-power-level:
arg[0]: integer identifying power domain
arg[1]: new power level for the domain, 0-100
output[0]: status, 0 on success
output[1]: power level after command
Set the power level for a specified power domain
rtas-get-power-level:
arg[0]: integer identifying power domain
output[0]: status, 0 on success
output[1]: current power level
Get the power level for a specified power domain
rtas-set-indicator:
arg[0]: integer identifying sensor/indicator type
arg[1]: index of sensor, for DR-related sensors this is generally the
DRC index
arg[2]: desired sensor value
output[0]: status, 0 on success
Set the state of an indicator or sensor. For the purpose of this document we
focus on the indicator/sensor types associated with a DRC. The types are:
9001: isolation-state, controls/indicates whether a device has been made
accessible to a guest
supported sensor values:
0: isolate, device is made unaccessible by guest OS
1: unisolate, device is made available to guest OS
9002: dr-indicator, controls "visual" indicator associated with device
supported sensor values:
0: inactive, resource may be safely removed
1: active, resource is in use and cannot be safely removed
2: identify, used to visually identify slot for interactive hotplug
3: action, in most cases, used in the same manner as identify
9003: allocation-state, generally only used for "logical" DR resources to
request the allocation/deallocation of a resource prior to acquiring
it via isolation-state->unisolate, or after releasing it via
isolation-state->isolate, respectively. for "physical" DR (like PCI
hotplug/unplug) the pre-allocation of the resource is implied and
this sensor is unused.
supported sensor values:
0: unusable, tell firmware/system the resource can be
unallocated/reclaimed and added back to the system resource pool
1: usable, request the resource be allocated/reserved for use by
guest OS
2: exchange, used to allocate a spare resource to use for fail-over
in certain situations. unused in QEMU
3: recover, used to reclaim a previously allocated resource that's
not currently allocated to the guest OS. unused in QEMU
rtas-get-sensor-state:
arg[0]: integer identifying sensor/indicator type
arg[1]: index of sensor, for DR-related sensors this is generally the
DRC index
output[0]: status, 0 on success
Used to read an indicator or sensor value.
For DR-related operations, the only noteworthy sensor is dr-entity-sense,
which has a type value of 9003, as allocation-state does in the case of
rtas-set-indicator. The semantics/encodings of the sensor values are distinct
however:
supported sensor values for dr-entity-sense (9003) sensor:
0: empty,
for physical resources: DRC/slot is empty
for logical resources: unused
1: present,
for physical resources: DRC/slot is populated with a device/resource
for logical resources: resource has been allocated to the DRC
2: unusable,
for physical resources: unused
for logical resources: DRC has no resource allocated to it
3: exchange,
for physical resources: unused
for logical resources: resource available for exchange (see
allocation-state sensor semantics above)
4: recovery,
for physical resources: unused
for logical resources: resource available for recovery (see
allocation-state sensor semantics above)
rtas-ibm-configure-connector:
arg[0]: guest physical address of 4096-byte work area buffer
arg[1]: 0, or address of additional 4096-byte work area buffer. only non-zero
if a prior RTAS response indicated a need for additional memory
output[0]: status:
0: completed transmittal of device-tree node
1: instruct guest to prepare for next DT sibling node
2: instruct guest to prepare for next DT child node
3: instruct guest to prepare for next DT property
4: instruct guest to ascend to parent DT node
5: instruct guest to provide additional work-area buffer
via arg[1]
990x: instruct guest that operation took too long and to try
again later
Used to fetch an OF device-tree description of the resource associated with
a particular DRC. The DRC index is encoded in the first 4-bytes of the first
work area buffer.
Work area layout, using 4-byte offsets:
wa[0]: DRC index of the DRC to fetch device-tree nodes from
wa[1]: 0 (hard-coded)
wa[2]: for next-sibling/next-child response:
wa offset of null-terminated string denoting the new node's name
for next-property response:
wa offset of null-terminated string denoting new property's name
wa[3]: for next-property response (unused otherwise):
byte-length of new property's value
wa[4]: for next-property response (unused otherwise):
new property's value, encoded as an OFDT-compatible byte array
== hotplug/unplug events ==
For most DR operations, the hypervisor will issue host->guest add/remove events
using the EPOW/check-exception notification framework, where the host issues a
check-exception interrupt, then provides an RTAS event log via an
rtas-check-exception call issued by the guest in response. This framework is
documented by PAPR+ v2.7, and already use in by QEMU for generating powerdown
requests via EPOW events.
For DR, this framework has been extended to include hotplug events, which were
previously unneeded due to direct manipulation of DR-related guest userspace
tools by host-level management such as an HMC. This level of management is not
applicable to PowerKVM, hence the reason for extending the notification
framework to support hotplug events.
Note that these events are not yet formally part of the PAPR+ specification,
but support for this format has already been implemented in DR-related
guest tools such as powerpc-utils/librtas, as well as kernel patches that have
been submitted to handle in-kernel processing of memory/cpu-related hotplug
events[1], and is planned for formal inclusion is PAPR+ specification. The
hotplug-specific payload is QEMU implemented as follows (with all values
encoded in big-endian format):
struct rtas_event_log_v6_hp {
#define SECTION_ID_HOTPLUG 0x4850 /* HP */
struct section_header {
uint16_t section_id; /* set to SECTION_ID_HOTPLUG */
uint16_t section_length; /* sizeof(rtas_event_log_v6_hp),
* plus the length of the DRC name
* if a DRC name identifier is
* specified for hotplug_identifier
*/
uint8_t section_version; /* version 1 */
uint8_t section_subtype; /* unused */
uint16_t creator_component_id; /* unused */
} hdr;
#define RTAS_LOG_V6_HP_TYPE_CPU 1
#define RTAS_LOG_V6_HP_TYPE_MEMORY 2
#define RTAS_LOG_V6_HP_TYPE_SLOT 3
#define RTAS_LOG_V6_HP_TYPE_PHB 4
#define RTAS_LOG_V6_HP_TYPE_PCI 5
uint8_t hotplug_type; /* type of resource/device */
#define RTAS_LOG_V6_HP_ACTION_ADD 1
#define RTAS_LOG_V6_HP_ACTION_REMOVE 2
uint8_t hotplug_action; /* action (add/remove) */
#define RTAS_LOG_V6_HP_ID_DRC_NAME 1
#define RTAS_LOG_V6_HP_ID_DRC_INDEX 2
#define RTAS_LOG_V6_HP_ID_DRC_COUNT 3
uint8_t hotplug_identifier; /* type of the resource identifier,
* which serves as the discriminator
* for the 'drc' union field below
*/
uint8_t reserved;
union {
uint32_t index; /* DRC index of resource to take action
* on
*/
uint32_t count; /* number of DR resources to take
* action on (guest chooses which)
*/
char name[1]; /* string representing the name of the
* DRC to take action on
*/
} drc;
} QEMU_PACKED;
[1] http://thread.gmane.org/gmane.linux.ports.ppc.embedded/75350/focus=106867

View File

@@ -127,6 +127,11 @@ in the ancillary data:
If Master is unable to send the full message or receives a wrong reply it will If Master is unable to send the full message or receives a wrong reply it will
close the connection. An optional reconnection mechanism can be implemented. close the connection. An optional reconnection mechanism can be implemented.
Multi queue support
-------------------
The protocol supports multiple queues by setting all index fields in the sent
messages to a properly calculated value.
Message types Message types
------------- -------------

View File

@@ -598,7 +598,7 @@ stored in its "value" member. In our example, the "value" member is a pointer
to an TimerAlarmMethod instance. to an TimerAlarmMethod instance.
Notice that the "current" variable is used as "true" only in the first Notice that the "current" variable is used as "true" only in the first
interation of the loop. That's because the alarm timer method in use is the iteration of the loop. That's because the alarm timer method in use is the
first element of the alarm_timers array. Also notice that QAPI lists are handled first element of the alarm_timers array. Also notice that QAPI lists are handled
by hand and we return the head of the list. by hand and we return the head of the list.

2
dtc

Submodule dtc updated: bc895d6d09...65cc4d2748

123
exec.c
View File

@@ -59,8 +59,6 @@
//#define DEBUG_SUBPAGE //#define DEBUG_SUBPAGE
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
static bool in_migration;
/* ram_list is read under rcu_read_lock()/rcu_read_unlock(). Writes /* ram_list is read under rcu_read_lock()/rcu_read_unlock(). Writes
* are protected by the ramlist lock. * are protected by the ramlist lock.
*/ */
@@ -173,17 +171,22 @@ static void phys_map_node_reserve(PhysPageMap *map, unsigned nodes)
} }
} }
static uint32_t phys_map_node_alloc(PhysPageMap *map) static uint32_t phys_map_node_alloc(PhysPageMap *map, bool leaf)
{ {
unsigned i; unsigned i;
uint32_t ret; uint32_t ret;
PhysPageEntry e;
PhysPageEntry *p;
ret = map->nodes_nb++; ret = map->nodes_nb++;
p = map->nodes[ret];
assert(ret != PHYS_MAP_NODE_NIL); assert(ret != PHYS_MAP_NODE_NIL);
assert(ret != map->nodes_nb_alloc); assert(ret != map->nodes_nb_alloc);
e.skip = leaf ? 0 : 1;
e.ptr = leaf ? PHYS_SECTION_UNASSIGNED : PHYS_MAP_NODE_NIL;
for (i = 0; i < P_L2_SIZE; ++i) { for (i = 0; i < P_L2_SIZE; ++i) {
map->nodes[ret][i].skip = 1; memcpy(&p[i], &e, sizeof(e));
map->nodes[ret][i].ptr = PHYS_MAP_NODE_NIL;
} }
return ret; return ret;
} }
@@ -193,21 +196,12 @@ static void phys_page_set_level(PhysPageMap *map, PhysPageEntry *lp,
int level) int level)
{ {
PhysPageEntry *p; PhysPageEntry *p;
int i;
hwaddr step = (hwaddr)1 << (level * P_L2_BITS); hwaddr step = (hwaddr)1 << (level * P_L2_BITS);
if (lp->skip && lp->ptr == PHYS_MAP_NODE_NIL) { if (lp->skip && lp->ptr == PHYS_MAP_NODE_NIL) {
lp->ptr = phys_map_node_alloc(map); lp->ptr = phys_map_node_alloc(map, level == 0);
p = map->nodes[lp->ptr];
if (level == 0) {
for (i = 0; i < P_L2_SIZE; i++) {
p[i].skip = 0;
p[i].ptr = PHYS_SECTION_UNASSIGNED;
}
}
} else {
p = map->nodes[lp->ptr];
} }
p = map->nodes[lp->ptr];
lp = &p[(*index >> (level * P_L2_BITS)) & (P_L2_SIZE - 1)]; lp = &p[(*index >> (level * P_L2_BITS)) & (P_L2_SIZE - 1)];
while (*nb && lp < &p[P_L2_SIZE]) { while (*nb && lp < &p[P_L2_SIZE]) {
@@ -858,21 +852,27 @@ static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t length)
} }
/* Note: start and end must be within the same ram block. */ /* Note: start and end must be within the same ram block. */
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t length, bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start,
unsigned client) ram_addr_t length,
unsigned client)
{ {
if (length == 0) unsigned long end, page;
return; bool dirty;
cpu_physical_memory_clear_dirty_range_type(start, length, client);
if (tcg_enabled()) { if (length == 0) {
return false;
}
end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
page = start >> TARGET_PAGE_BITS;
dirty = bitmap_test_and_clear_atomic(ram_list.dirty_memory[client],
page, end - page);
if (dirty && tcg_enabled()) {
tlb_reset_dirty_range_all(start, length); tlb_reset_dirty_range_all(start, length);
} }
}
static void cpu_physical_memory_set_dirty_tracking(bool enable) return dirty;
{
in_migration = enable;
} }
/* Called from RCU critical section */ /* Called from RCU critical section */
@@ -1362,7 +1362,8 @@ int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp)
cpu_physical_memory_clear_dirty_range(block->offset, block->used_length); cpu_physical_memory_clear_dirty_range(block->offset, block->used_length);
block->used_length = newsize; block->used_length = newsize;
cpu_physical_memory_set_dirty_range(block->offset, block->used_length); cpu_physical_memory_set_dirty_range(block->offset, block->used_length,
DIRTY_CLIENTS_ALL);
memory_region_set_size(block->mr, newsize); memory_region_set_size(block->mr, newsize);
if (block->resized) { if (block->resized) {
block->resized(block->idstr, newsize, block->host); block->resized(block->idstr, newsize, block->host);
@@ -1436,7 +1437,8 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp)
} }
} }
cpu_physical_memory_set_dirty_range(new_block->offset, cpu_physical_memory_set_dirty_range(new_block->offset,
new_block->used_length); new_block->used_length,
DIRTY_CLIENTS_ALL);
if (new_block->host) { if (new_block->host) {
qemu_ram_setup_dump(new_block->host, new_block->max_length); qemu_ram_setup_dump(new_block->host, new_block->max_length);
@@ -1824,7 +1826,11 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
default: default:
abort(); abort();
} }
cpu_physical_memory_set_dirty_range_nocode(ram_addr, size); /* Set both VGA and migration bits for simplicity and to remove
* the notdirty callback faster.
*/
cpu_physical_memory_set_dirty_range(ram_addr, size,
DIRTY_CLIENTS_NOCODE);
/* we remove the notdirty callback only if the code has been /* we remove the notdirty callback only if the code has been
flushed */ flushed */
if (!cpu_physical_memory_is_clean(ram_addr)) { if (!cpu_physical_memory_is_clean(ram_addr)) {
@@ -2165,22 +2171,6 @@ static void tcg_commit(MemoryListener *listener)
} }
} }
static void core_log_global_start(MemoryListener *listener)
{
cpu_physical_memory_set_dirty_tracking(true);
}
static void core_log_global_stop(MemoryListener *listener)
{
cpu_physical_memory_set_dirty_tracking(false);
}
static MemoryListener core_memory_listener = {
.log_global_start = core_log_global_start,
.log_global_stop = core_log_global_stop,
.priority = 1,
};
void address_space_init_dispatch(AddressSpace *as) void address_space_init_dispatch(AddressSpace *as)
{ {
as->dispatch = NULL; as->dispatch = NULL;
@@ -2220,8 +2210,6 @@ static void memory_map_init(void)
memory_region_init_io(system_io, NULL, &unassigned_io_ops, NULL, "io", memory_region_init_io(system_io, NULL, &unassigned_io_ops, NULL, "io",
65536); 65536);
address_space_init(&address_space_io, system_io, "I/O"); address_space_init(&address_space_io, system_io, "I/O");
memory_listener_register(&core_memory_listener, &address_space_memory);
} }
MemoryRegion *get_system_memory(void) MemoryRegion *get_system_memory(void)
@@ -2279,14 +2267,23 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
#else #else
static void invalidate_and_set_dirty(hwaddr addr, static void invalidate_and_set_dirty(MemoryRegion *mr, hwaddr addr,
hwaddr length) hwaddr length)
{ {
if (cpu_physical_memory_range_includes_clean(addr, length)) { uint8_t dirty_log_mask = memory_region_get_dirty_log_mask(mr);
tb_invalidate_phys_range(addr, addr + length, 0); /* No early return if dirty_log_mask is or becomes 0, because
cpu_physical_memory_set_dirty_range_nocode(addr, length); * cpu_physical_memory_set_dirty_range will still call
* xen_modified_memory.
*/
if (dirty_log_mask) {
dirty_log_mask =
cpu_physical_memory_range_includes_clean(addr, length, dirty_log_mask);
} }
xen_modified_memory(addr, length); if (dirty_log_mask & (1 << DIRTY_MEMORY_CODE)) {
tb_invalidate_phys_range(addr, addr + length);
dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
}
cpu_physical_memory_set_dirty_range(addr, length, dirty_log_mask);
} }
static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr) static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)
@@ -2371,7 +2368,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
/* RAM case */ /* RAM case */
ptr = qemu_get_ram_ptr(addr1); ptr = qemu_get_ram_ptr(addr1);
memcpy(ptr, buf, l); memcpy(ptr, buf, l);
invalidate_and_set_dirty(addr1, l); invalidate_and_set_dirty(mr, addr1, l);
} }
} else { } else {
if (!memory_access_is_direct(mr, is_write)) { if (!memory_access_is_direct(mr, is_write)) {
@@ -2468,7 +2465,7 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as,
switch (type) { switch (type) {
case WRITE_DATA: case WRITE_DATA:
memcpy(ptr, buf, l); memcpy(ptr, buf, l);
invalidate_and_set_dirty(addr1, l); invalidate_and_set_dirty(mr, addr1, l);
break; break;
case FLUSH_CACHE: case FLUSH_CACHE:
flush_icache_range((uintptr_t)ptr, (uintptr_t)ptr + l); flush_icache_range((uintptr_t)ptr, (uintptr_t)ptr + l);
@@ -2693,7 +2690,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
mr = qemu_ram_addr_from_host(buffer, &addr1); mr = qemu_ram_addr_from_host(buffer, &addr1);
assert(mr != NULL); assert(mr != NULL);
if (is_write) { if (is_write) {
invalidate_and_set_dirty(addr1, access_len); invalidate_and_set_dirty(mr, addr1, access_len);
} }
if (xen_enabled()) { if (xen_enabled()) {
xen_invalidate_map_cache_entry(buffer); xen_invalidate_map_cache_entry(buffer);
@@ -3022,6 +3019,7 @@ void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
hwaddr l = 4; hwaddr l = 4;
hwaddr addr1; hwaddr addr1;
MemTxResult r; MemTxResult r;
uint8_t dirty_log_mask;
rcu_read_lock(); rcu_read_lock();
mr = address_space_translate(as, addr, &addr1, &l, mr = address_space_translate(as, addr, &addr1, &l,
@@ -3033,14 +3031,9 @@ void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
ptr = qemu_get_ram_ptr(addr1); ptr = qemu_get_ram_ptr(addr1);
stl_p(ptr, val); stl_p(ptr, val);
if (unlikely(in_migration)) { dirty_log_mask = memory_region_get_dirty_log_mask(mr);
if (cpu_physical_memory_is_clean(addr1)) { dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
/* invalidate code */ cpu_physical_memory_set_dirty_range(addr1, 4, dirty_log_mask);
tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
/* set dirty bit */
cpu_physical_memory_set_dirty_range_nocode(addr1, 4);
}
}
r = MEMTX_OK; r = MEMTX_OK;
} }
if (result) { if (result) {
@@ -3096,7 +3089,7 @@ static inline void address_space_stl_internal(AddressSpace *as,
stl_p(ptr, val); stl_p(ptr, val);
break; break;
} }
invalidate_and_set_dirty(addr1, 4); invalidate_and_set_dirty(mr, addr1, 4);
r = MEMTX_OK; r = MEMTX_OK;
} }
if (result) { if (result) {
@@ -3200,7 +3193,7 @@ static inline void address_space_stw_internal(AddressSpace *as,
stw_p(ptr, val); stw_p(ptr, val);
break; break;
} }
invalidate_and_set_dirty(addr1, 2); invalidate_and_set_dirty(mr, addr1, 2);
r = MEMTX_OK; r = MEMTX_OK;
} }
if (result) { if (result) {

View File

@@ -113,7 +113,7 @@ const float16 float16_default_nan = const_float16(0xFE00);
#if defined(TARGET_SPARC) #if defined(TARGET_SPARC)
const float32 float32_default_nan = const_float32(0x7FFFFFFF); const float32 float32_default_nan = const_float32(0x7FFFFFFF);
#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \ #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
defined(TARGET_XTENSA) defined(TARGET_XTENSA) || defined(TARGET_S390X)
const float32 float32_default_nan = const_float32(0x7FC00000); const float32 float32_default_nan = const_float32(0x7FC00000);
#elif SNAN_BIT_IS_ONE #elif SNAN_BIT_IS_ONE
const float32 float32_default_nan = const_float32(0x7FBFFFFF); const float32 float32_default_nan = const_float32(0x7FBFFFFF);
@@ -126,7 +126,8 @@ const float32 float32_default_nan = const_float32(0xFFC00000);
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#if defined(TARGET_SPARC) #if defined(TARGET_SPARC)
const float64 float64_default_nan = const_float64(LIT64( 0x7FFFFFFFFFFFFFFF )); const float64 float64_default_nan = const_float64(LIT64( 0x7FFFFFFFFFFFFFFF ));
#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
defined(TARGET_S390X)
const float64 float64_default_nan = const_float64(LIT64( 0x7FF8000000000000 )); const float64 float64_default_nan = const_float64(LIT64( 0x7FF8000000000000 ));
#elif SNAN_BIT_IS_ONE #elif SNAN_BIT_IS_ONE
const float64 float64_default_nan = const_float64(LIT64(0x7FF7FFFFFFFFFFFF)); const float64 float64_default_nan = const_float64(LIT64(0x7FF7FFFFFFFFFFFF));
@@ -155,6 +156,9 @@ const floatx80 floatx80_default_nan
#if SNAN_BIT_IS_ONE #if SNAN_BIT_IS_ONE
#define float128_default_nan_high LIT64(0x7FFF7FFFFFFFFFFF) #define float128_default_nan_high LIT64(0x7FFF7FFFFFFFFFFF)
#define float128_default_nan_low LIT64(0xFFFFFFFFFFFFFFFF) #define float128_default_nan_low LIT64(0xFFFFFFFFFFFFFFFF)
#elif defined(TARGET_S390X)
#define float128_default_nan_high LIT64( 0x7FFF800000000000 )
#define float128_default_nan_low LIT64( 0x0000000000000000 )
#else #else
#define float128_default_nan_high LIT64( 0xFFFF800000000000 ) #define float128_default_nan_high LIT64( 0xFFFF800000000000 )
#define float128_default_nan_low LIT64( 0x0000000000000000 ) #define float128_default_nan_low LIT64( 0x0000000000000000 )

View File

@@ -178,8 +178,7 @@ ETEXI
.args_type = "id:B", .args_type = "id:B",
.params = "device", .params = "device",
.help = "remove host block device", .help = "remove host block device",
.user_print = monitor_user_noop, .mhandler.cmd = hmp_drive_del,
.mhandler.cmd_new = hmp_drive_del,
}, },
STEXI STEXI
@@ -654,8 +653,7 @@ ETEXI
.args_type = "device:O", .args_type = "device:O",
.params = "driver[,prop=value][,...]", .params = "driver[,prop=value][,...]",
.help = "add device, like -device on the command line", .help = "add device, like -device on the command line",
.user_print = monitor_user_noop, .mhandler.cmd = hmp_device_add,
.mhandler.cmd_new = do_device_add,
.command_completion = device_add_completion, .command_completion = device_add_completion,
}, },
@@ -1011,17 +1009,16 @@ ETEXI
.name = "client_migrate_info", .name = "client_migrate_info",
.args_type = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?", .args_type = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
.params = "protocol hostname port tls-port cert-subject", .params = "protocol hostname port tls-port cert-subject",
.help = "send migration info to spice/vnc client", .help = "set migration information for remote display",
.user_print = monitor_user_noop, .mhandler.cmd = hmp_client_migrate_info,
.mhandler.cmd_new = client_migrate_info,
}, },
STEXI STEXI
@item client_migrate_info @var{protocol} @var{hostname} @var{port} @var{tls-port} @var{cert-subject} @item client_migrate_info @var{protocol} @var{hostname} @var{port} @var{tls-port} @var{cert-subject}
@findex client_migrate_info @findex client_migrate_info
Set the spice/vnc connection info for the migration target. The spice/vnc Set migration information for remote display. This makes the server
server will ask the spice/vnc client to automatically reconnect using the ask the client to automatically reconnect using the new parameters
new parameters (if specified) once the vm migration finished successfully. once migration finished successfully. Only implemented for SPICE.
ETEXI ETEXI
{ {
@@ -1186,8 +1183,7 @@ ETEXI
"<error_status> = error string or 32bit\n\t\t\t" "<error_status> = error string or 32bit\n\t\t\t"
"<tlb header> = 32bit x 4\n\t\t\t" "<tlb header> = 32bit x 4\n\t\t\t"
"<tlb header prefix> = 32bit x 4", "<tlb header prefix> = 32bit x 4",
.user_print = pcie_aer_inject_error_print, .mhandler.cmd = hmp_pcie_aer_inject_error,
.mhandler.cmd_new = hmp_pcie_aer_inject_error,
}, },
STEXI STEXI

23
hmp.c
View File

@@ -22,6 +22,7 @@
#include "qmp-commands.h" #include "qmp-commands.h"
#include "qemu/sockets.h" #include "qemu/sockets.h"
#include "monitor/monitor.h" #include "monitor/monitor.h"
#include "monitor/qdev.h"
#include "qapi/opts-visitor.h" #include "qapi/opts-visitor.h"
#include "qapi/string-output-visitor.h" #include "qapi/string-output-visitor.h"
#include "qapi-visit.h" #include "qapi-visit.h"
@@ -1250,6 +1251,23 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
} }
} }
void hmp_client_migrate_info(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
const char *protocol = qdict_get_str(qdict, "protocol");
const char *hostname = qdict_get_str(qdict, "hostname");
bool has_port = qdict_haskey(qdict, "port");
int port = qdict_get_try_int(qdict, "port", -1);
bool has_tls_port = qdict_haskey(qdict, "tls-port");
int tls_port = qdict_get_try_int(qdict, "tls-port", -1);
const char *cert_subject = qdict_get_try_str(qdict, "cert-subject");
qmp_client_migrate_info(protocol, hostname,
has_port, port, has_tls_port, tls_port,
!!cert_subject, cert_subject, &err);
hmp_handle_error(mon, &err);
}
void hmp_set_password(Monitor *mon, const QDict *qdict) void hmp_set_password(Monitor *mon, const QDict *qdict)
{ {
const char *protocol = qdict_get_str(qdict, "protocol"); const char *protocol = qdict_get_str(qdict, "protocol");
@@ -1482,6 +1500,11 @@ void hmp_migrate(Monitor *mon, const QDict *qdict)
} }
} }
void hmp_device_add(Monitor *mon, const QDict *qdict)
{
do_device_add(mon, qdict, NULL);
}
void hmp_device_del(Monitor *mon, const QDict *qdict) void hmp_device_del(Monitor *mon, const QDict *qdict)
{ {
const char *id = qdict_get_str(qdict, "id"); const char *id = qdict_get_str(qdict, "id");

2
hmp.h
View File

@@ -67,6 +67,7 @@ void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict); void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict);
void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict); void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict);
void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict); void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict);
void hmp_client_migrate_info(Monitor *mon, const QDict *qdict);
void hmp_set_password(Monitor *mon, const QDict *qdict); void hmp_set_password(Monitor *mon, const QDict *qdict);
void hmp_expire_password(Monitor *mon, const QDict *qdict); void hmp_expire_password(Monitor *mon, const QDict *qdict);
void hmp_eject(Monitor *mon, const QDict *qdict); void hmp_eject(Monitor *mon, const QDict *qdict);
@@ -79,6 +80,7 @@ void hmp_block_job_pause(Monitor *mon, const QDict *qdict);
void hmp_block_job_resume(Monitor *mon, const QDict *qdict); void hmp_block_job_resume(Monitor *mon, const QDict *qdict);
void hmp_block_job_complete(Monitor *mon, const QDict *qdict); void hmp_block_job_complete(Monitor *mon, const QDict *qdict);
void hmp_migrate(Monitor *mon, const QDict *qdict); void hmp_migrate(Monitor *mon, const QDict *qdict);
void hmp_device_add(Monitor *mon, const QDict *qdict);
void hmp_device_del(Monitor *mon, const QDict *qdict); void hmp_device_del(Monitor *mon, const QDict *qdict);
void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict); void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict);
void hmp_netdev_add(Monitor *mon, const QDict *qdict); void hmp_netdev_add(Monitor *mon, const QDict *qdict);

View File

@@ -21,7 +21,7 @@
#include "virtio-9p-coth.h" #include "virtio-9p-coth.h"
#include "hw/virtio/virtio-access.h" #include "hw/virtio/virtio-access.h"
static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features) static uint64_t virtio_9p_get_features(VirtIODevice *vdev, uint64_t features)
{ {
virtio_add_feature(&features, VIRTIO_9P_MOUNT_TAG); virtio_add_feature(&features, VIRTIO_9P_MOUNT_TAG);
return features; return features;

View File

@@ -1,5 +1,6 @@
common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o pcihp.o cpu_hotplug.o common-obj-$(CONFIG_ACPI_X86) += core.o piix4.o ich9.o pcihp.o
common-obj-$(CONFIG_ACPI) += memory_hotplug.o common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o
common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o
common-obj-$(CONFIG_ACPI) += acpi_interface.o common-obj-$(CONFIG_ACPI) += acpi_interface.o
common-obj-$(CONFIG_ACPI) += bios-linker-loader.o common-obj-$(CONFIG_ACPI) += bios-linker-loader.o
common-obj-$(CONFIG_ACPI) += aml-build.o common-obj-$(CONFIG_ACPI) += aml-build.o

View File

@@ -19,6 +19,7 @@
* with this program; if not, see <http://www.gnu.org/licenses/>. * with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
#include <glib/gprintf.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <assert.h> #include <assert.h>
@@ -26,6 +27,7 @@
#include <string.h> #include <string.h>
#include "hw/acpi/aml-build.h" #include "hw/acpi/aml-build.h"
#include "qemu/bswap.h" #include "qemu/bswap.h"
#include "qemu/bitops.h"
#include "hw/acpi/bios-linker-loader.h" #include "hw/acpi/bios-linker-loader.h"
static GArray *build_alloc_array(void) static GArray *build_alloc_array(void)
@@ -58,7 +60,6 @@ static void build_append_array(GArray *array, GArray *val)
static void static void
build_append_nameseg(GArray *array, const char *seg) build_append_nameseg(GArray *array, const char *seg)
{ {
/* It would be nicer to use g_string_vprintf but it's only there in 2.22 */
int len; int len;
len = strlen(seg); len = strlen(seg);
@@ -72,22 +73,12 @@ build_append_nameseg(GArray *array, const char *seg)
static void GCC_FMT_ATTR(2, 0) static void GCC_FMT_ATTR(2, 0)
build_append_namestringv(GArray *array, const char *format, va_list ap) build_append_namestringv(GArray *array, const char *format, va_list ap)
{ {
/* It would be nicer to use g_string_vprintf but it's only there in 2.22 */
char *s; char *s;
int len;
va_list va_len;
char **segs; char **segs;
char **segs_iter; char **segs_iter;
int seg_count = 0; int seg_count = 0;
va_copy(va_len, ap); s = g_strdup_vprintf(format, ap);
len = vsnprintf(NULL, 0, format, va_len);
va_end(va_len);
len += 1;
s = g_new(typeof(*s), len);
len = vsnprintf(s, len, format, ap);
segs = g_strsplit(s, ".", 0); segs = g_strsplit(s, ".", 0);
g_free(s); g_free(s);
@@ -305,6 +296,7 @@ static void aml_free(gpointer data, gpointer user_data)
{ {
Aml *var = data; Aml *var = data;
build_free_array(var->buf); build_free_array(var->buf);
g_free(var);
} }
Aml *init_aml_allocator(void) Aml *init_aml_allocator(void)
@@ -454,6 +446,73 @@ Aml *aml_and(Aml *arg1, Aml *arg2)
return var; return var;
} }
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefOr */
Aml *aml_or(Aml *arg1, Aml *arg2)
{
Aml *var = aml_opcode(0x7D /* OrOp */);
aml_append(var, arg1);
aml_append(var, arg2);
build_append_byte(var->buf, 0x00 /* NullNameOp */);
return var;
}
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefShiftLeft */
Aml *aml_shiftleft(Aml *arg1, Aml *count)
{
Aml *var = aml_opcode(0x79 /* ShiftLeftOp */);
aml_append(var, arg1);
aml_append(var, count);
build_append_byte(var->buf, 0x00); /* NullNameOp */
return var;
}
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefShiftRight */
Aml *aml_shiftright(Aml *arg1, Aml *count)
{
Aml *var = aml_opcode(0x7A /* ShiftRightOp */);
aml_append(var, arg1);
aml_append(var, count);
build_append_byte(var->buf, 0x00); /* NullNameOp */
return var;
}
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLLess */
Aml *aml_lless(Aml *arg1, Aml *arg2)
{
Aml *var = aml_opcode(0x95 /* LLessOp */);
aml_append(var, arg1);
aml_append(var, arg2);
return var;
}
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAdd */
Aml *aml_add(Aml *arg1, Aml *arg2)
{
Aml *var = aml_opcode(0x72 /* AddOp */);
aml_append(var, arg1);
aml_append(var, arg2);
build_append_byte(var->buf, 0x00 /* NullNameOp */);
return var;
}
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefIncrement */
Aml *aml_increment(Aml *arg)
{
Aml *var = aml_opcode(0x75 /* IncrementOp */);
aml_append(var, arg);
return var;
}
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefIndex */
Aml *aml_index(Aml *arg1, Aml *idx)
{
Aml *var = aml_opcode(0x88 /* IndexOp */);
aml_append(var, arg1);
aml_append(var, idx);
build_append_byte(var->buf, 0x00 /* NullNameOp */);
return var;
}
/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefNotify */ /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefNotify */
Aml *aml_notify(Aml *arg1, Aml *arg2) Aml *aml_notify(Aml *arg1, Aml *arg2)
{ {
@@ -505,6 +564,60 @@ Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4)
return var; return var;
} }
/*
* ACPI 1.0b: 6.4.3.4 32-Bit Fixed Location Memory Range Descriptor
* (Type 1, Large Item Name 0x6)
*/
Aml *aml_memory32_fixed(uint32_t addr, uint32_t size,
AmlReadAndWrite read_and_write)
{
Aml *var = aml_alloc();
build_append_byte(var->buf, 0x86); /* Memory32Fixed Resource Descriptor */
build_append_byte(var->buf, 9); /* Length, bits[7:0] value = 9 */
build_append_byte(var->buf, 0); /* Length, bits[15:8] value = 0 */
build_append_byte(var->buf, read_and_write); /* Write status, 1 rw 0 ro */
/* Range base address */
build_append_byte(var->buf, extract32(addr, 0, 8)); /* bits[7:0] */
build_append_byte(var->buf, extract32(addr, 8, 8)); /* bits[15:8] */
build_append_byte(var->buf, extract32(addr, 16, 8)); /* bits[23:16] */
build_append_byte(var->buf, extract32(addr, 24, 8)); /* bits[31:24] */
/* Range length */
build_append_byte(var->buf, extract32(size, 0, 8)); /* bits[7:0] */
build_append_byte(var->buf, extract32(size, 8, 8)); /* bits[15:8] */
build_append_byte(var->buf, extract32(size, 16, 8)); /* bits[23:16] */
build_append_byte(var->buf, extract32(size, 24, 8)); /* bits[31:24] */
return var;
}
/*
* ACPI 5.0: 6.4.3.6 Extended Interrupt Descriptor
* Type 1, Large Item Name 0x9
*/
Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro,
AmlLevelAndEdge level_and_edge,
AmlActiveHighAndLow high_and_low, AmlShared shared,
uint32_t irq)
{
Aml *var = aml_alloc();
uint8_t irq_flags = con_and_pro | (level_and_edge << 1)
| (high_and_low << 2) | (shared << 3);
build_append_byte(var->buf, 0x89); /* Extended irq descriptor */
build_append_byte(var->buf, 6); /* Length, bits[7:0] minimum value = 6 */
build_append_byte(var->buf, 0); /* Length, bits[15:8] minimum value = 0 */
build_append_byte(var->buf, irq_flags); /* Interrupt Vector Information. */
build_append_byte(var->buf, 0x01); /* Interrupt table length = 1 */
/* Interrupt Number */
build_append_byte(var->buf, extract32(irq, 0, 8)); /* bits[7:0] */
build_append_byte(var->buf, extract32(irq, 8, 8)); /* bits[15:8] */
build_append_byte(var->buf, extract32(irq, 16, 8)); /* bits[23:16] */
build_append_byte(var->buf, extract32(irq, 24, 8)); /* bits[31:24] */
return var;
}
/* ACPI 1.0b: 6.4.2.5 I/O Port Descriptor */ /* ACPI 1.0b: 6.4.2.5 I/O Port Descriptor */
Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base, Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base,
uint8_t aln, uint8_t len) uint8_t aln, uint8_t len)
@@ -542,6 +655,14 @@ Aml *aml_irq_no_flags(uint8_t irq)
return var; return var;
} }
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLNot */
Aml *aml_lnot(Aml *arg)
{
Aml *var = aml_opcode(0x92 /* LNotOp */);
aml_append(var, arg);
return var;
}
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLEqual */ /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLEqual */
Aml *aml_equal(Aml *arg1, Aml *arg2) Aml *aml_equal(Aml *arg1, Aml *arg2)
{ {
@@ -559,6 +680,21 @@ Aml *aml_if(Aml *predicate)
return var; return var;
} }
/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefElse */
Aml *aml_else(void)
{
Aml *var = aml_bundle(0xA1 /* ElseOp */, AML_PACKAGE);
return var;
}
/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefWhile */
Aml *aml_while(Aml *predicate)
{
Aml *var = aml_bundle(0xA2 /* WhileOp */, AML_PACKAGE);
aml_append(var, predicate);
return var;
}
/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMethod */ /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMethod */
Aml *aml_method(const char *name, int arg_count) Aml *aml_method(const char *name, int arg_count)
{ {
@@ -587,10 +723,22 @@ Aml *aml_resource_template(void)
return var; return var;
} }
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefBuffer */ /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefBuffer
Aml *aml_buffer(void) * Pass byte_list as NULL to request uninitialized buffer to reserve space.
*/
Aml *aml_buffer(int buffer_size, uint8_t *byte_list)
{ {
int i;
Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER); Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER);
for (i = 0; i < buffer_size; i++) {
if (byte_list == NULL) {
build_append_byte(var->buf, 0x0);
} else {
build_append_byte(var->buf, byte_list[i]);
}
}
return var; return var;
} }
@@ -646,26 +794,30 @@ Aml *aml_field(const char *name, AmlAccessType type, AmlUpdateRule rule)
return var; return var;
} }
/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefCreateDWordField */
Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name)
{
Aml *var = aml_alloc();
build_append_byte(var->buf, 0x8A); /* CreateDWordFieldOp */
aml_append(var, srcbuf);
aml_append(var, index);
build_append_namestring(var->buf, "%s", name);
return var;
}
/* ACPI 1.0b: 16.2.3 Data Objects Encoding: String */ /* ACPI 1.0b: 16.2.3 Data Objects Encoding: String */
Aml *aml_string(const char *name_format, ...) Aml *aml_string(const char *name_format, ...)
{ {
Aml *var = aml_opcode(0x0D /* StringPrefix */); Aml *var = aml_opcode(0x0D /* StringPrefix */);
va_list ap, va_len; va_list ap;
char *s; char *s;
int len; int len;
va_start(ap, name_format); va_start(ap, name_format);
va_copy(va_len, ap); len = g_vasprintf(&s, name_format, ap);
len = vsnprintf(NULL, 0, name_format, va_len);
va_end(va_len);
len += 1;
s = g_new0(typeof(*s), len);
len = vsnprintf(s, len, name_format, ap);
va_end(ap); va_end(ap);
g_array_append_vals(var->buf, s, len); g_array_append_vals(var->buf, s, len + 1);
build_append_byte(var->buf, 0x0); /* NullChar */
g_free(s); g_free(s);
return var; return var;
@@ -833,7 +985,7 @@ Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
uint16_t addr_trans, uint16_t len) uint16_t addr_trans, uint16_t len)
{ {
return aml_word_as_desc(aml_bus_number_range, min_fixed, max_fixed, dec, return aml_word_as_desc(AML_BUS_NUMBER_RANGE, min_fixed, max_fixed, dec,
addr_gran, addr_min, addr_max, addr_trans, len, 0); addr_gran, addr_min, addr_max, addr_trans, len, 0);
} }
@@ -850,7 +1002,25 @@ Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
uint16_t len) uint16_t len)
{ {
return aml_word_as_desc(aml_io_range, min_fixed, max_fixed, dec, return aml_word_as_desc(AML_IO_RANGE, min_fixed, max_fixed, dec,
addr_gran, addr_min, addr_max, addr_trans, len,
isa_ranges);
}
/*
* ACPI 1.0b: 6.4.3.5.4 ASL Macros for DWORD Address Descriptor
*
* More verbose description at:
* ACPI 5.0: 19.5.33 DWordIO (DWord IO Resource Descriptor Macro)
*/
Aml *aml_dword_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
AmlDecode dec, AmlISARanges isa_ranges,
uint32_t addr_gran, uint32_t addr_min,
uint32_t addr_max, uint32_t addr_trans,
uint32_t len)
{
return aml_dword_as_desc(AML_IO_RANGE, min_fixed, max_fixed, dec,
addr_gran, addr_min, addr_max, addr_trans, len, addr_gran, addr_min, addr_max, addr_trans, len,
isa_ranges); isa_ranges);
} }
@@ -862,7 +1032,7 @@ Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
* ACPI 5.0: 19.5.34 DWordMemory (DWord Memory Resource Descriptor Macro) * ACPI 5.0: 19.5.34 DWordMemory (DWord Memory Resource Descriptor Macro)
*/ */
Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed, Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed,
AmlMaxFixed max_fixed, AmlCacheble cacheable, AmlMaxFixed max_fixed, AmlCacheable cacheable,
AmlReadAndWrite read_and_write, AmlReadAndWrite read_and_write,
uint32_t addr_gran, uint32_t addr_min, uint32_t addr_gran, uint32_t addr_min,
uint32_t addr_max, uint32_t addr_trans, uint32_t addr_max, uint32_t addr_trans,
@@ -870,7 +1040,7 @@ Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed,
{ {
uint8_t flags = read_and_write | (cacheable << 1); uint8_t flags = read_and_write | (cacheable << 1);
return aml_dword_as_desc(aml_memory_range, min_fixed, max_fixed, return aml_dword_as_desc(AML_MEMORY_RANGE, min_fixed, max_fixed,
dec, addr_gran, addr_min, addr_max, dec, addr_gran, addr_min, addr_max,
addr_trans, len, flags); addr_trans, len, flags);
} }
@@ -882,7 +1052,7 @@ Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed,
* ACPI 5.0: 19.5.102 QWordMemory (QWord Memory Resource Descriptor Macro) * ACPI 5.0: 19.5.102 QWordMemory (QWord Memory Resource Descriptor Macro)
*/ */
Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed, Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
AmlMaxFixed max_fixed, AmlCacheble cacheable, AmlMaxFixed max_fixed, AmlCacheable cacheable,
AmlReadAndWrite read_and_write, AmlReadAndWrite read_and_write,
uint64_t addr_gran, uint64_t addr_min, uint64_t addr_gran, uint64_t addr_min,
uint64_t addr_max, uint64_t addr_trans, uint64_t addr_max, uint64_t addr_trans,
@@ -890,11 +1060,81 @@ Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
{ {
uint8_t flags = read_and_write | (cacheable << 1); uint8_t flags = read_and_write | (cacheable << 1);
return aml_qword_as_desc(aml_memory_range, min_fixed, max_fixed, return aml_qword_as_desc(AML_MEMORY_RANGE, min_fixed, max_fixed,
dec, addr_gran, addr_min, addr_max, dec, addr_gran, addr_min, addr_max,
addr_trans, len, flags); addr_trans, len, flags);
} }
static uint8_t Hex2Byte(const char *src)
{
int hi, lo;
hi = Hex2Digit(src[0]);
assert(hi >= 0);
assert(hi <= 15);
lo = Hex2Digit(src[1]);
assert(lo >= 0);
assert(lo <= 15);
return (hi << 4) | lo;
}
/*
* ACPI 3.0: 17.5.124 ToUUID (Convert String to UUID Macro)
* e.g. UUID: aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
* call aml_touuid("aabbccdd-eeff-gghh-iijj-kkllmmnnoopp");
*/
Aml *aml_touuid(const char *uuid)
{
Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER);
assert(strlen(uuid) == 36);
assert(uuid[8] == '-');
assert(uuid[13] == '-');
assert(uuid[18] == '-');
assert(uuid[23] == '-');
build_append_byte(var->buf, Hex2Byte(uuid + 6)); /* dd - at offset 00 */
build_append_byte(var->buf, Hex2Byte(uuid + 4)); /* cc - at offset 01 */
build_append_byte(var->buf, Hex2Byte(uuid + 2)); /* bb - at offset 02 */
build_append_byte(var->buf, Hex2Byte(uuid + 0)); /* aa - at offset 03 */
build_append_byte(var->buf, Hex2Byte(uuid + 11)); /* ff - at offset 04 */
build_append_byte(var->buf, Hex2Byte(uuid + 9)); /* ee - at offset 05 */
build_append_byte(var->buf, Hex2Byte(uuid + 16)); /* hh - at offset 06 */
build_append_byte(var->buf, Hex2Byte(uuid + 14)); /* gg - at offset 07 */
build_append_byte(var->buf, Hex2Byte(uuid + 19)); /* ii - at offset 08 */
build_append_byte(var->buf, Hex2Byte(uuid + 21)); /* jj - at offset 09 */
build_append_byte(var->buf, Hex2Byte(uuid + 24)); /* kk - at offset 10 */
build_append_byte(var->buf, Hex2Byte(uuid + 26)); /* ll - at offset 11 */
build_append_byte(var->buf, Hex2Byte(uuid + 28)); /* mm - at offset 12 */
build_append_byte(var->buf, Hex2Byte(uuid + 30)); /* nn - at offset 13 */
build_append_byte(var->buf, Hex2Byte(uuid + 32)); /* oo - at offset 14 */
build_append_byte(var->buf, Hex2Byte(uuid + 34)); /* pp - at offset 15 */
return var;
}
/*
* ACPI 2.0b: 16.2.3.6.4.3 Unicode Macro (Convert Ascii String To Unicode)
*/
Aml *aml_unicode(const char *str)
{
int i = 0;
Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER);
do {
build_append_byte(var->buf, str[i]);
build_append_byte(var->buf, 0);
i++;
} while (i <= strlen(str));
return var;
}
void void
build_header(GArray *linker, GArray *table_data, build_header(GArray *linker, GArray *table_data,
AcpiTableHeader *h, const char *sig, int len, uint8_t rev) AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
@@ -951,3 +1191,27 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
g_array_free(tables->table_data, true); g_array_free(tables->table_data, true);
g_array_free(tables->tcpalog, mfre); g_array_free(tables->tcpalog, mfre);
} }
/* Build rsdt table */
void
build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
{
AcpiRsdtDescriptorRev1 *rsdt;
size_t rsdt_len;
int i;
const int table_data_len = (sizeof(uint32_t) * table_offsets->len);
rsdt_len = sizeof(*rsdt) + table_data_len;
rsdt = acpi_data_push(table_data, rsdt_len);
memcpy(rsdt->table_offset_entry, table_offsets->data, table_data_len);
for (i = 0; i < table_offsets->len; ++i) {
/* rsdt->table_offset_entry to be filled by Guest linker */
bios_linker_loader_add_pointer(linker,
ACPI_BUILD_TABLE_FILE,
ACPI_BUILD_TABLE_FILE,
table_data, &rsdt->table_offset_entry[i],
sizeof(uint32_t));
}
build_header(linker, table_data,
(void *)rsdt, "RSDT", rsdt_len, 1);
}

View File

@@ -22,6 +22,7 @@
#include "hw/hw.h" #include "hw/hw.h"
#include "hw/i386/pc.h" #include "hw/i386/pc.h"
#include "hw/acpi/acpi.h" #include "hw/acpi/acpi.h"
#include "hw/nvram/fw_cfg.h"
#include "qemu/config-file.h" #include "qemu/config-file.h"
#include "qapi/opts-visitor.h" #include "qapi/opts-visitor.h"
#include "qapi/dealloc-visitor.h" #include "qapi/dealloc-visitor.h"
@@ -592,14 +593,26 @@ static const MemoryRegionOps acpi_pm_cnt_ops = {
.endianness = DEVICE_LITTLE_ENDIAN, .endianness = DEVICE_LITTLE_ENDIAN,
}; };
void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, uint8_t s4_val) void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent,
bool disable_s3, bool disable_s4, uint8_t s4_val)
{ {
FWCfgState *fw_cfg;
ar->pm1.cnt.s4_val = s4_val; ar->pm1.cnt.s4_val = s4_val;
ar->wakeup.notify = acpi_notify_wakeup; ar->wakeup.notify = acpi_notify_wakeup;
qemu_register_wakeup_notifier(&ar->wakeup); qemu_register_wakeup_notifier(&ar->wakeup);
memory_region_init_io(&ar->pm1.cnt.io, memory_region_owner(parent), memory_region_init_io(&ar->pm1.cnt.io, memory_region_owner(parent),
&acpi_pm_cnt_ops, ar, "acpi-cnt", 2); &acpi_pm_cnt_ops, ar, "acpi-cnt", 2);
memory_region_add_subregion(parent, 4, &ar->pm1.cnt.io); memory_region_add_subregion(parent, 4, &ar->pm1.cnt.io);
fw_cfg = fw_cfg_find();
if (fw_cfg) {
uint8_t suspend[6] = {128, 0, 0, 129, 128, 128};
suspend[3] = 1 | ((!disable_s3) << 7);
suspend[4] = s4_val | ((!disable_s4) << 7);
fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6);
}
} }
void acpi_pm1_cnt_reset(ACPIREGS *ar) void acpi_pm1_cnt_reset(ACPIREGS *ar)
@@ -666,6 +679,13 @@ uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr)
return val; return val;
} }
void acpi_send_gpe_event(ACPIREGS *ar, qemu_irq irq,
AcpiGPEStatusBits status)
{
ar->gpe.sts[0] |= status;
acpi_update_sci(ar, irq);
}
void acpi_update_sci(ACPIREGS *regs, qemu_irq irq) void acpi_update_sci(ACPIREGS *regs, qemu_irq irq)
{ {
int sci_level, pm1a_sts; int sci_level, pm1a_sts;

View File

@@ -59,8 +59,7 @@ void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq,
return; return;
} }
ar->gpe.sts[0] |= ACPI_CPU_HOTPLUG_STATUS; acpi_send_gpe_event(ar, irq, ACPI_CPU_HOTPLUG_STATUS);
acpi_update_sci(ar, irq);
} }
void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner, void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,

View File

@@ -94,7 +94,8 @@ static void ich9_smi_writel(void *opaque, hwaddr addr, uint64_t val,
ICH9LPCPMRegs *pm = opaque; ICH9LPCPMRegs *pm = opaque;
switch (addr) { switch (addr) {
case 0: case 0:
pm->smi_en = val; pm->smi_en &= ~pm->smi_en_wmask;
pm->smi_en |= (val & pm->smi_en_wmask);
break; break;
} }
} }
@@ -198,6 +199,7 @@ static void pm_reset(void *opaque)
* support SMM mode. */ * support SMM mode. */
pm->smi_en |= ICH9_PMIO_SMI_EN_APMC_EN; pm->smi_en |= ICH9_PMIO_SMI_EN_APMC_EN;
} }
pm->smi_en_wmask = ~0;
acpi_update_sci(&pm->acpi_regs, pm->irq); acpi_update_sci(&pm->acpi_regs, pm->irq);
} }
@@ -219,7 +221,8 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io); acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
acpi_pm1_evt_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io); acpi_pm1_evt_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, pm->s4_val); acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, pm->disable_s3, pm->disable_s4,
pm->s4_val);
acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN); acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
memory_region_init_io(&pm->io_gpe, OBJECT(lpc_pci), &ich9_gpe_ops, pm, memory_region_init_io(&pm->io_gpe, OBJECT(lpc_pci), &ich9_gpe_ops, pm,

View File

@@ -241,8 +241,7 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
mdev->is_inserting = true; mdev->is_inserting = true;
/* do ACPI magic */ /* do ACPI magic */
ar->gpe.sts[0] |= ACPI_MEMORY_HOTPLUG_STATUS; acpi_send_gpe_event(ar, irq, ACPI_MEMORY_HOTPLUG_STATUS);
acpi_update_sci(ar, irq);
return; return;
} }
@@ -260,8 +259,7 @@ void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq,
mdev->is_removing = true; mdev->is_removing = true;
/* Do ACPI magic */ /* Do ACPI magic */
ar->gpe.sts[0] |= ACPI_MEMORY_HOTPLUG_STATUS; acpi_send_gpe_event(ar, irq, ACPI_MEMORY_HOTPLUG_STATUS);
acpi_update_sci(ar, irq);
} }
void acpi_memory_unplug_cb(MemHotplugState *mem_st, void acpi_memory_unplug_cb(MemHotplugState *mem_st,

View File

@@ -45,7 +45,6 @@
# define ACPI_PCIHP_DPRINTF(format, ...) do { } while (0) # define ACPI_PCIHP_DPRINTF(format, ...) do { } while (0)
#endif #endif
#define ACPI_PCI_HOTPLUG_STATUS 2
#define ACPI_PCIHP_ADDR 0xae00 #define ACPI_PCIHP_ADDR 0xae00
#define ACPI_PCIHP_SIZE 0x0014 #define ACPI_PCIHP_SIZE 0x0014
#define ACPI_PCIHP_LEGACY_SIZE 0x000f #define ACPI_PCIHP_LEGACY_SIZE 0x000f
@@ -202,8 +201,7 @@ void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
s->acpi_pcihp_pci_status[bsel].up |= (1U << slot); s->acpi_pcihp_pci_status[bsel].up |= (1U << slot);
ar->gpe.sts[0] |= ACPI_PCI_HOTPLUG_STATUS; acpi_send_gpe_event(ar, irq, ACPI_PCI_HOTPLUG_STATUS);
acpi_update_sci(ar, irq);
} }
void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s, void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
@@ -220,8 +218,7 @@ void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
s->acpi_pcihp_pci_status[bsel].down |= (1U << slot); s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
ar->gpe.sts[0] |= ACPI_PCI_HOTPLUG_STATUS; acpi_send_gpe_event(ar, irq, ACPI_PCI_HOTPLUG_STATUS);
acpi_update_sci(ar, irq);
} }
static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size) static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)

View File

@@ -475,7 +475,7 @@ static void piix4_pm_realize(PCIDevice *dev, Error **errp)
acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io); acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io); acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
acpi_pm1_cnt_init(&s->ar, &s->io, s->s4_val); acpi_pm1_cnt_init(&s->ar, &s->io, s->disable_s3, s->disable_s4, s->s4_val);
acpi_gpe_init(&s->ar, GPE_LEN); acpi_gpe_init(&s->ar, GPE_LEN);
s->powerdown_notifier.notify = piix4_pm_powerdown_req; s->powerdown_notifier.notify = piix4_pm_powerdown_req;
@@ -503,8 +503,7 @@ Object *piix4_pm_find(void)
I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
qemu_irq sci_irq, qemu_irq smi_irq, qemu_irq sci_irq, qemu_irq smi_irq,
int kvm_enabled, FWCfgState *fw_cfg, int kvm_enabled, DeviceState **piix4_pm)
DeviceState **piix4_pm)
{ {
DeviceState *dev; DeviceState *dev;
PIIX4PMState *s; PIIX4PMState *s;
@@ -525,14 +524,6 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
qdev_init_nofail(dev); qdev_init_nofail(dev);
if (fw_cfg) {
uint8_t suspend[6] = {128, 0, 0, 129, 128, 128};
suspend[3] = 1 | ((!s->disable_s3) << 7);
suspend[4] = s->s4_val | ((!s->disable_s4) << 7);
fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6);
}
return s->smb.smbus; return s->smb.smbus;
} }

View File

@@ -55,7 +55,7 @@ static void clipper_init(MachineState *machine)
ISABus *isa_bus; ISABus *isa_bus;
qemu_irq rtc_irq; qemu_irq rtc_irq;
long size, i; long size, i;
const char *palcode_filename; char *palcode_filename;
uint64_t palcode_entry, palcode_low, palcode_high; uint64_t palcode_entry, palcode_low, palcode_high;
uint64_t kernel_entry, kernel_low, kernel_high; uint64_t kernel_entry, kernel_low, kernel_high;
@@ -101,8 +101,8 @@ static void clipper_init(MachineState *machine)
/* Load PALcode. Given that this is not "real" cpu palcode, /* Load PALcode. Given that this is not "real" cpu palcode,
but one explicitly written for the emulation, we might as but one explicitly written for the emulation, we might as
well load it directly from and ELF image. */ well load it directly from and ELF image. */
palcode_filename = (bios_name ? bios_name : "palcode-clipper"); palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, palcode_filename); bios_name ? bios_name : "palcode-clipper");
if (palcode_filename == NULL) { if (palcode_filename == NULL) {
hw_error("no palcode provided\n"); hw_error("no palcode provided\n");
exit(1); exit(1);
@@ -114,6 +114,7 @@ static void clipper_init(MachineState *machine)
hw_error("could not load palcode '%s'\n", palcode_filename); hw_error("could not load palcode '%s'\n", palcode_filename);
exit(1); exit(1);
} }
g_free(palcode_filename);
/* Start all cpus at the PALcode RESET entry point. */ /* Start all cpus at the PALcode RESET entry point. */
for (i = 0; i < smp_cpus; ++i) { for (i = 0; i < smp_cpus; ++i) {

View File

@@ -841,7 +841,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
} }
} }
*p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1); *p_rtc_irq = qemu_allocate_irq(typhoon_set_timer_irq, s, 0);
/* Main memory region, 0x00.0000.0000. Real hardware supports 32GB, /* Main memory region, 0x00.0000.0000. Real hardware supports 32GB,
but the address space hole reserved at this point is 8TB. */ but the address space hole reserved at this point is 8TB. */
@@ -918,11 +918,11 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
/* Init the ISA bus. */ /* Init the ISA bus. */
/* ??? Technically there should be a cy82c693ub pci-isa bridge. */ /* ??? Technically there should be a cy82c693ub pci-isa bridge. */
{ {
qemu_irq isa_pci_irq, *isa_irqs; qemu_irq *isa_irqs;
*isa_bus = isa_bus_new(NULL, get_system_memory(), &s->pchip.reg_io); *isa_bus = isa_bus_new(NULL, get_system_memory(), &s->pchip.reg_io);
isa_pci_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1); isa_irqs = i8259_init(*isa_bus,
isa_irqs = i8259_init(*isa_bus, isa_pci_irq); qemu_allocate_irq(typhoon_set_isa_irq, s, 0));
isa_bus_irqs(*isa_bus, isa_irqs); isa_bus_irqs(*isa_bus, isa_irqs);
} }

View File

@@ -3,7 +3,9 @@ obj-$(CONFIG_DIGIC) += digic_boards.o
obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o
obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
obj-$(CONFIG_ACPI) += virt-acpi-build.o
obj-y += netduino2.o obj-y += netduino2.o
obj-y += sysbus-fdt.o
obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
obj-$(CONFIG_DIGIC) += digic.o obj-$(CONFIG_DIGIC) += digic.o

View File

@@ -557,7 +557,7 @@ static void load_image_to_fw_cfg(FWCfgState *fw_cfg, uint16_t size_key,
fw_cfg_add_bytes(fw_cfg, data_key, data, size); fw_cfg_add_bytes(fw_cfg, data_key, data, size);
} }
void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) static void arm_load_kernel_notify(Notifier *notifier, void *data)
{ {
CPUState *cs; CPUState *cs;
int kernel_size; int kernel_size;
@@ -568,6 +568,11 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
hwaddr entry, kernel_load_offset; hwaddr entry, kernel_load_offset;
int big_endian; int big_endian;
static const ARMInsnFixup *primary_loader; static const ARMInsnFixup *primary_loader;
ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier,
notifier, notifier);
ARMCPU *cpu = n->cpu;
struct arm_boot_info *info =
container_of(n, struct arm_boot_info, load_kernel_notifier);
/* CPU objects (unlike devices) are not automatically reset on system /* CPU objects (unlike devices) are not automatically reset on system
* reset, so we must always register a handler to do so. If we're * reset, so we must always register a handler to do so. If we're
@@ -775,3 +780,10 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
ARM_CPU(cs)->env.boot_info = info; ARM_CPU(cs)->env.boot_info = info;
} }
} }
void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
{
info->load_kernel_notifier.cpu = cpu;
info->load_kernel_notifier.notifier.notify = arm_load_kernel_notify;
qemu_add_machine_init_done_notifier(&info->load_kernel_notifier.notifier);
}

View File

@@ -133,9 +133,8 @@ static void n800_mmc_cs_cb(void *opaque, int line, int level)
static void n8x0_gpio_setup(struct n800_s *s) static void n8x0_gpio_setup(struct n800_s *s)
{ {
qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->mpu->mmc, 1); qdev_connect_gpio_out(s->mpu->gpio, N8X0_MMC_CS_GPIO,
qdev_connect_gpio_out(s->mpu->gpio, N8X0_MMC_CS_GPIO, mmc_cs[0]); qemu_allocate_irq(n800_mmc_cs_cb, s->mpu->mmc, 0));
qemu_irq_lower(qdev_get_gpio_in(s->mpu->gpio, N800_BAT_COVER_GPIO)); qemu_irq_lower(qdev_get_gpio_in(s->mpu->gpio, N800_BAT_COVER_GPIO));
} }

View File

@@ -103,7 +103,6 @@ static void sx1_init(MachineState *machine, const int version)
struct omap_mpu_state_s *mpu; struct omap_mpu_state_s *mpu;
MemoryRegion *address_space = get_system_memory(); MemoryRegion *address_space = get_system_memory();
MemoryRegion *flash = g_new(MemoryRegion, 1); MemoryRegion *flash = g_new(MemoryRegion, 1);
MemoryRegion *flash_1 = g_new(MemoryRegion, 1);
MemoryRegion *cs = g_new(MemoryRegion, 4); MemoryRegion *cs = g_new(MemoryRegion, 4);
static uint32_t cs0val = 0x00213090; static uint32_t cs0val = 0x00213090;
static uint32_t cs1val = 0x00215070; static uint32_t cs1val = 0x00215070;
@@ -165,6 +164,7 @@ static void sx1_init(MachineState *machine, const int version)
if ((version == 1) && if ((version == 1) &&
(dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) { (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
MemoryRegion *flash_1 = g_new(MemoryRegion, 1);
memory_region_init_ram(flash_1, NULL, "omap_sx1.flash1-0", flash1_size, memory_region_init_ram(flash_1, NULL, "omap_sx1.flash1-0", flash1_size,
&error_abort); &error_abort);
vmstate_register_ram_global(flash_1); vmstate_register_ram_global(flash_1);

174
hw/arm/sysbus-fdt.c Normal file
View File

@@ -0,0 +1,174 @@
/*
* ARM Platform Bus device tree generation helpers
*
* Copyright (c) 2014 Linaro Limited
*
* Authors:
* Alex Graf <agraf@suse.de>
* Eric Auger <eric.auger@linaro.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2 or later, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "hw/arm/sysbus-fdt.h"
#include "qemu/error-report.h"
#include "sysemu/device_tree.h"
#include "hw/platform-bus.h"
#include "sysemu/sysemu.h"
/*
* internal struct that contains the information to create dynamic
* sysbus device node
*/
typedef struct PlatformBusFDTData {
void *fdt; /* device tree handle */
int irq_start; /* index of the first IRQ usable by platform bus devices */
const char *pbus_node_name; /* name of the platform bus node */
PlatformBusDevice *pbus;
} PlatformBusFDTData;
/*
* struct used when calling the machine init done notifier
* that constructs the fdt nodes of platform bus devices
*/
typedef struct PlatformBusFDTNotifierParams {
Notifier notifier;
ARMPlatformBusFDTParams *fdt_params;
} PlatformBusFDTNotifierParams;
/* struct that associates a device type name and a node creation function */
typedef struct NodeCreationPair {
const char *typename;
int (*add_fdt_node_fn)(SysBusDevice *sbdev, void *opaque);
} NodeCreationPair;
/* list of supported dynamic sysbus devices */
static const NodeCreationPair add_fdt_node_functions[] = {
{"", NULL}, /* last element */
};
/**
* add_fdt_node - add the device tree node of a dynamic sysbus device
*
* @sbdev: handle to the sysbus device
* @opaque: handle to the PlatformBusFDTData
*
* Checks the sysbus type belongs to the list of device types that
* are dynamically instantiable and if so call the node creation
* function.
*/
static int add_fdt_node(SysBusDevice *sbdev, void *opaque)
{
int i, ret;
for (i = 0; i < ARRAY_SIZE(add_fdt_node_functions); i++) {
if (!strcmp(object_get_typename(OBJECT(sbdev)),
add_fdt_node_functions[i].typename)) {
ret = add_fdt_node_functions[i].add_fdt_node_fn(sbdev, opaque);
assert(!ret);
return 0;
}
}
error_report("Device %s can not be dynamically instantiated",
qdev_fw_name(DEVICE(sbdev)));
exit(1);
}
/**
* add_all_platform_bus_fdt_nodes - create all the platform bus nodes
*
* builds the parent platform bus node and all the nodes of dynamic
* sysbus devices attached to it.
*/
static void add_all_platform_bus_fdt_nodes(ARMPlatformBusFDTParams *fdt_params)
{
const char platcomp[] = "qemu,platform\0simple-bus";
PlatformBusDevice *pbus;
DeviceState *dev;
gchar *node;
uint64_t addr, size;
int irq_start, dtb_size;
struct arm_boot_info *info = fdt_params->binfo;
const ARMPlatformBusSystemParams *params = fdt_params->system_params;
const char *intc = fdt_params->intc;
void *fdt = info->get_dtb(info, &dtb_size);
/*
* If the user provided a dtb, we assume the dynamic sysbus nodes
* already are integrated there. This corresponds to a use case where
* the dynamic sysbus nodes are complex and their generation is not yet
* supported. In that case the user can take charge of the guest dt
* while qemu takes charge of the qom stuff.
*/
if (info->dtb_filename) {
return;
}
assert(fdt);
node = g_strdup_printf("/platform@%"PRIx64, params->platform_bus_base);
addr = params->platform_bus_base;
size = params->platform_bus_size;
irq_start = params->platform_bus_first_irq;
/* Create a /platform node that we can put all devices into */
qemu_fdt_add_subnode(fdt, node);
qemu_fdt_setprop(fdt, node, "compatible", platcomp, sizeof(platcomp));
/* Our platform bus region is less than 32bits, so 1 cell is enough for
* address and size
*/
qemu_fdt_setprop_cells(fdt, node, "#size-cells", 1);
qemu_fdt_setprop_cells(fdt, node, "#address-cells", 1);
qemu_fdt_setprop_cells(fdt, node, "ranges", 0, addr >> 32, addr, size);
qemu_fdt_setprop_phandle(fdt, node, "interrupt-parent", intc);
dev = qdev_find_recursive(sysbus_get_default(), TYPE_PLATFORM_BUS_DEVICE);
pbus = PLATFORM_BUS_DEVICE(dev);
/* We can only create dt nodes for dynamic devices when they're ready */
assert(pbus->done_gathering);
PlatformBusFDTData data = {
.fdt = fdt,
.irq_start = irq_start,
.pbus_node_name = node,
.pbus = pbus,
};
/* Loop through all dynamic sysbus devices and create their node */
foreach_dynamic_sysbus_device(add_fdt_node, &data);
g_free(node);
}
static void platform_bus_fdt_notify(Notifier *notifier, void *data)
{
PlatformBusFDTNotifierParams *p = DO_UPCAST(PlatformBusFDTNotifierParams,
notifier, notifier);
add_all_platform_bus_fdt_nodes(p->fdt_params);
g_free(p->fdt_params);
g_free(p);
}
void arm_register_platform_bus_fdt_creator(ARMPlatformBusFDTParams *fdt_params)
{
PlatformBusFDTNotifierParams *p = g_new(PlatformBusFDTNotifierParams, 1);
p->fdt_params = fdt_params;
p->notifier.notify = platform_bus_fdt_notify;
qemu_add_machine_init_done_notifier(&p->notifier);
}

View File

@@ -525,7 +525,7 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name,
qdev_prop_set_uint64(dev, "sector-length", VEXPRESS_FLASH_SECT_SIZE); qdev_prop_set_uint64(dev, "sector-length", VEXPRESS_FLASH_SECT_SIZE);
qdev_prop_set_uint8(dev, "width", 4); qdev_prop_set_uint8(dev, "width", 4);
qdev_prop_set_uint8(dev, "device-width", 2); qdev_prop_set_uint8(dev, "device-width", 2);
qdev_prop_set_uint8(dev, "big-endian", 0); qdev_prop_set_bit(dev, "big-endian", false);
qdev_prop_set_uint16(dev, "id0", 0x89); qdev_prop_set_uint16(dev, "id0", 0x89);
qdev_prop_set_uint16(dev, "id1", 0x18); qdev_prop_set_uint16(dev, "id1", 0x18);
qdev_prop_set_uint16(dev, "id2", 0x00); qdev_prop_set_uint16(dev, "id2", 0x00);

644
hw/arm/virt-acpi-build.c Normal file
View File

@@ -0,0 +1,644 @@
/* Support for generating ACPI tables and passing them to Guests
*
* ARM virt ACPI generation
*
* Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net>
* Copyright (C) 2006 Fabrice Bellard
* Copyright (C) 2013 Red Hat Inc
*
* Author: Michael S. Tsirkin <mst@redhat.com>
*
* Copyright (c) 2015 HUAWEI TECHNOLOGIES CO.,LTD.
*
* Author: Shannon Zhao <zhaoshenglong@huawei.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu-common.h"
#include "hw/arm/virt-acpi-build.h"
#include "qemu/bitmap.h"
#include "trace.h"
#include "qom/cpu.h"
#include "target-arm/cpu.h"
#include "hw/acpi/acpi-defs.h"
#include "hw/acpi/acpi.h"
#include "hw/nvram/fw_cfg.h"
#include "hw/acpi/bios-linker-loader.h"
#include "hw/loader.h"
#include "hw/hw.h"
#include "hw/acpi/aml-build.h"
#include "hw/pci/pcie_host.h"
#include "hw/pci/pci.h"
#define ARM_SPI_BASE 32
typedef struct VirtAcpiCpuInfo {
DECLARE_BITMAP(found_cpus, VIRT_ACPI_CPU_ID_LIMIT);
} VirtAcpiCpuInfo;
static void virt_acpi_get_cpu_info(VirtAcpiCpuInfo *cpuinfo)
{
CPUState *cpu;
memset(cpuinfo->found_cpus, 0, sizeof cpuinfo->found_cpus);
CPU_FOREACH(cpu) {
set_bit(cpu->cpu_index, cpuinfo->found_cpus);
}
}
static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
{
uint16_t i;
for (i = 0; i < smp_cpus; i++) {
Aml *dev = aml_device("C%03x", i);
aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007")));
aml_append(dev, aml_name_decl("_UID", aml_int(i)));
aml_append(scope, dev);
}
}
static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
int uart_irq)
{
Aml *dev = aml_device("COM0");
aml_append(dev, aml_name_decl("_HID", aml_string("ARMH0011")));
aml_append(dev, aml_name_decl("_UID", aml_int(0)));
Aml *crs = aml_resource_template();
aml_append(crs, aml_memory32_fixed(uart_memmap->base,
uart_memmap->size, AML_READ_WRITE));
aml_append(crs,
aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
AML_EXCLUSIVE, uart_irq));
aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(scope, dev);
}
static void acpi_dsdt_add_rtc(Aml *scope, const MemMapEntry *rtc_memmap,
int rtc_irq)
{
Aml *dev = aml_device("RTC0");
aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0013")));
aml_append(dev, aml_name_decl("_UID", aml_int(0)));
Aml *crs = aml_resource_template();
aml_append(crs, aml_memory32_fixed(rtc_memmap->base,
rtc_memmap->size, AML_READ_WRITE));
aml_append(crs,
aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
AML_EXCLUSIVE, rtc_irq));
aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(scope, dev);
}
static void acpi_dsdt_add_flash(Aml *scope, const MemMapEntry *flash_memmap)
{
Aml *dev, *crs;
hwaddr base = flash_memmap->base;
hwaddr size = flash_memmap->size;
dev = aml_device("FLS0");
aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
aml_append(dev, aml_name_decl("_UID", aml_int(0)));
crs = aml_resource_template();
aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE));
aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(scope, dev);
dev = aml_device("FLS1");
aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
aml_append(dev, aml_name_decl("_UID", aml_int(1)));
crs = aml_resource_template();
aml_append(crs, aml_memory32_fixed(base + size, size, AML_READ_WRITE));
aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(scope, dev);
}
static void acpi_dsdt_add_virtio(Aml *scope,
const MemMapEntry *virtio_mmio_memmap,
int mmio_irq, int num)
{
hwaddr base = virtio_mmio_memmap->base;
hwaddr size = virtio_mmio_memmap->size;
int irq = mmio_irq;
int i;
for (i = 0; i < num; i++) {
Aml *dev = aml_device("VR%02u", i);
aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0005")));
aml_append(dev, aml_name_decl("_UID", aml_int(i)));
Aml *crs = aml_resource_template();
aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE));
aml_append(crs,
aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
AML_EXCLUSIVE, irq + i));
aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(scope, dev);
base += size;
}
}
static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq)
{
Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
int i, bus_no;
hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
hwaddr base_ecam = memmap[VIRT_PCIE_ECAM].base;
hwaddr size_ecam = memmap[VIRT_PCIE_ECAM].size;
int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
Aml *dev = aml_device("%s", "PCI0");
aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
aml_append(dev, aml_name_decl("_BBN", aml_int(0)));
aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
aml_append(dev, aml_name_decl("_UID", aml_string("PCI0")));
aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device")));
/* Declare the PCI Routing Table. */
Aml *rt_pkg = aml_package(nr_pcie_buses * PCI_NUM_PINS);
for (bus_no = 0; bus_no < nr_pcie_buses; bus_no++) {
for (i = 0; i < PCI_NUM_PINS; i++) {
int gsi = (i + bus_no) % PCI_NUM_PINS;
Aml *pkg = aml_package(4);
aml_append(pkg, aml_int((bus_no << 16) | 0xFFFF));
aml_append(pkg, aml_int(i));
aml_append(pkg, aml_name("GSI%d", gsi));
aml_append(pkg, aml_int(0));
aml_append(rt_pkg, pkg);
}
}
aml_append(dev, aml_name_decl("_PRT", rt_pkg));
/* Create GSI link device */
for (i = 0; i < PCI_NUM_PINS; i++) {
Aml *dev_gsi = aml_device("GSI%d", i);
aml_append(dev_gsi, aml_name_decl("_HID", aml_string("PNP0C0F")));
aml_append(dev_gsi, aml_name_decl("_UID", aml_int(0)));
crs = aml_resource_template();
aml_append(crs,
aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
AML_EXCLUSIVE, irq + i));
aml_append(dev_gsi, aml_name_decl("_PRS", crs));
crs = aml_resource_template();
aml_append(crs,
aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
AML_EXCLUSIVE, irq + i));
aml_append(dev_gsi, aml_name_decl("_CRS", crs));
method = aml_method("_SRS", 1);
aml_append(dev_gsi, method);
aml_append(dev, dev_gsi);
}
method = aml_method("_CBA", 0);
aml_append(method, aml_return(aml_int(base_ecam)));
aml_append(dev, method);
method = aml_method("_CRS", 0);
Aml *rbuf = aml_resource_template();
aml_append(rbuf,
aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
0x0000, 0x0000, nr_pcie_buses - 1, 0x0000,
nr_pcie_buses));
aml_append(rbuf,
aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, base_mmio,
base_mmio + size_mmio - 1, 0x0000, size_mmio));
aml_append(rbuf,
aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
AML_ENTIRE_RANGE, 0x0000, 0x0000, size_pio - 1, base_pio,
size_pio));
aml_append(method, aml_name_decl("RBUF", rbuf));
aml_append(method, aml_return(rbuf));
aml_append(dev, method);
/* Declare an _OSC (OS Control Handoff) method */
aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
method = aml_method("_OSC", 4);
aml_append(method,
aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
/* PCI Firmware Specification 3.0
* 4.5.1. _OSC Interface for PCI Host Bridge Devices
* The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is
* identified by the Universal Unique IDentifier (UUID)
* 33DB4D5B-1FF7-401C-9657-7441C03DD766
*/
UUID = aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766");
ifctx = aml_if(aml_equal(aml_arg(0), UUID));
aml_append(ifctx,
aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2"));
aml_append(ifctx,
aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3"));
aml_append(ifctx, aml_store(aml_name("CDW2"), aml_name("SUPP")));
aml_append(ifctx, aml_store(aml_name("CDW3"), aml_name("CTRL")));
aml_append(ifctx, aml_store(aml_and(aml_name("CTRL"), aml_int(0x1D)),
aml_name("CTRL")));
ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(0x1))));
aml_append(ifctx1, aml_store(aml_or(aml_name("CDW1"), aml_int(0x08)),
aml_name("CDW1")));
aml_append(ifctx, ifctx1);
ifctx1 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), aml_name("CTRL"))));
aml_append(ifctx1, aml_store(aml_or(aml_name("CDW1"), aml_int(0x10)),
aml_name("CDW1")));
aml_append(ifctx, ifctx1);
aml_append(ifctx, aml_store(aml_name("CTRL"), aml_name("CDW3")));
aml_append(ifctx, aml_return(aml_arg(3)));
aml_append(method, ifctx);
elsectx = aml_else();
aml_append(elsectx, aml_store(aml_or(aml_name("CDW1"), aml_int(4)),
aml_name("CDW1")));
aml_append(elsectx, aml_return(aml_arg(3)));
aml_append(method, elsectx);
aml_append(dev, method);
method = aml_method("_DSM", 4);
/* PCI Firmware Specification 3.0
* 4.6.1. _DSM for PCI Express Slot Information
* The UUID in _DSM in this context is
* {E5C937D0-3553-4D7A-9117-EA4D19C3434D}
*/
UUID = aml_touuid("E5C937D0-3553-4D7A-9117-EA4D19C3434D");
ifctx = aml_if(aml_equal(aml_arg(0), UUID));
ifctx1 = aml_if(aml_equal(aml_arg(2), aml_int(0)));
uint8_t byte_list[1] = {1};
buf = aml_buffer(1, byte_list);
aml_append(ifctx1, aml_return(buf));
aml_append(ifctx, ifctx1);
aml_append(method, ifctx);
byte_list[0] = 0;
buf = aml_buffer(1, byte_list);
aml_append(method, aml_return(buf));
aml_append(dev, method);
Aml *dev_rp0 = aml_device("%s", "RP0");
aml_append(dev_rp0, aml_name_decl("_ADR", aml_int(0)));
aml_append(dev, dev_rp0);
aml_append(scope, dev);
}
/* RSDP */
static GArray *
build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
{
AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, 16,
true /* fseg memory */);
memcpy(&rsdp->signature, "RSD PTR ", sizeof(rsdp->signature));
memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, sizeof(rsdp->oem_id));
rsdp->length = cpu_to_le32(sizeof(*rsdp));
rsdp->revision = 0x02;
/* Point to RSDT */
rsdp->rsdt_physical_address = cpu_to_le32(rsdt);
/* Address to be filled by Guest linker */
bios_linker_loader_add_pointer(linker, ACPI_BUILD_RSDP_FILE,
ACPI_BUILD_TABLE_FILE,
rsdp_table, &rsdp->rsdt_physical_address,
sizeof rsdp->rsdt_physical_address);
rsdp->checksum = 0;
/* Checksum to be filled by Guest linker */
bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
rsdp, rsdp, sizeof *rsdp, &rsdp->checksum);
return rsdp_table;
}
static void
build_mcfg(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
{
AcpiTableMcfg *mcfg;
const MemMapEntry *memmap = guest_info->memmap;
int len = sizeof(*mcfg) + sizeof(mcfg->allocation[0]);
mcfg = acpi_data_push(table_data, len);
mcfg->allocation[0].address = cpu_to_le64(memmap[VIRT_PCIE_ECAM].base);
/* Only a single allocation so no need to play with segments */
mcfg->allocation[0].pci_segment = cpu_to_le16(0);
mcfg->allocation[0].start_bus_number = 0;
mcfg->allocation[0].end_bus_number = (memmap[VIRT_PCIE_ECAM].size
/ PCIE_MMCFG_SIZE_MIN) - 1;
build_header(linker, table_data, (void *)mcfg, "MCFG", len, 5);
}
/* GTDT */
static void
build_gtdt(GArray *table_data, GArray *linker)
{
int gtdt_start = table_data->len;
AcpiGenericTimerTable *gtdt;
gtdt = acpi_data_push(table_data, sizeof *gtdt);
/* The interrupt values are the same with the device tree when adding 16 */
gtdt->secure_el1_interrupt = ARCH_TIMER_S_EL1_IRQ + 16;
gtdt->secure_el1_flags = ACPI_EDGE_SENSITIVE;
gtdt->non_secure_el1_interrupt = ARCH_TIMER_NS_EL1_IRQ + 16;
gtdt->non_secure_el1_flags = ACPI_EDGE_SENSITIVE;
gtdt->virtual_timer_interrupt = ARCH_TIMER_VIRT_IRQ + 16;
gtdt->virtual_timer_flags = ACPI_EDGE_SENSITIVE;
gtdt->non_secure_el2_interrupt = ARCH_TIMER_NS_EL2_IRQ + 16;
gtdt->non_secure_el2_flags = ACPI_EDGE_SENSITIVE;
build_header(linker, table_data,
(void *)(table_data->data + gtdt_start), "GTDT",
table_data->len - gtdt_start, 5);
}
/* MADT */
static void
build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info,
VirtAcpiCpuInfo *cpuinfo)
{
int madt_start = table_data->len;
const MemMapEntry *memmap = guest_info->memmap;
AcpiMultipleApicTable *madt;
AcpiMadtGenericDistributor *gicd;
int i;
madt = acpi_data_push(table_data, sizeof *madt);
for (i = 0; i < guest_info->smp_cpus; i++) {
AcpiMadtGenericInterrupt *gicc = acpi_data_push(table_data,
sizeof *gicc);
gicc->type = ACPI_APIC_GENERIC_INTERRUPT;
gicc->length = sizeof(*gicc);
gicc->base_address = memmap[VIRT_GIC_CPU].base;
gicc->cpu_interface_number = i;
gicc->arm_mpidr = i;
gicc->uid = i;
if (test_bit(i, cpuinfo->found_cpus)) {
gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED);
}
}
gicd = acpi_data_push(table_data, sizeof *gicd);
gicd->type = ACPI_APIC_GENERIC_DISTRIBUTOR;
gicd->length = sizeof(*gicd);
gicd->base_address = memmap[VIRT_GIC_DIST].base;
build_header(linker, table_data,
(void *)(table_data->data + madt_start), "APIC",
table_data->len - madt_start, 5);
}
/* FADT */
static void
build_fadt(GArray *table_data, GArray *linker, unsigned dsdt)
{
AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
/* Hardware Reduced = 1 and use PSCI 0.2+ and with HVC */
fadt->flags = cpu_to_le32(1 << ACPI_FADT_F_HW_REDUCED_ACPI);
fadt->arm_boot_flags = cpu_to_le16((1 << ACPI_FADT_ARM_USE_PSCI_G_0_2) |
(1 << ACPI_FADT_ARM_PSCI_USE_HVC));
/* ACPI v5.1 (fadt->revision.fadt->minor_revision) */
fadt->minor_revision = 0x1;
fadt->dsdt = cpu_to_le32(dsdt);
/* DSDT address to be filled by Guest linker */
bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
ACPI_BUILD_TABLE_FILE,
table_data, &fadt->dsdt,
sizeof fadt->dsdt);
build_header(linker, table_data,
(void *)fadt, "FACP", sizeof(*fadt), 5);
}
/* DSDT */
static void
build_dsdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
{
Aml *scope, *dsdt;
const MemMapEntry *memmap = guest_info->memmap;
const int *irqmap = guest_info->irqmap;
dsdt = init_aml_allocator();
/* Reserve space for header */
acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader));
scope = aml_scope("\\_SB");
acpi_dsdt_add_cpus(scope, guest_info->smp_cpus);
acpi_dsdt_add_uart(scope, &memmap[VIRT_UART],
(irqmap[VIRT_UART] + ARM_SPI_BASE));
acpi_dsdt_add_rtc(scope, &memmap[VIRT_RTC],
(irqmap[VIRT_RTC] + ARM_SPI_BASE));
acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]);
acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO],
(irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS);
acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE));
aml_append(dsdt, scope);
/* copy AML table into ACPI tables blob and patch header there */
g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
build_header(linker, table_data,
(void *)(table_data->data + table_data->len - dsdt->buf->len),
"DSDT", dsdt->buf->len, 5);
free_aml_allocator();
}
typedef
struct AcpiBuildState {
/* Copy of table in RAM (for patching). */
MemoryRegion *table_mr;
MemoryRegion *rsdp_mr;
MemoryRegion *linker_mr;
/* Is table patched? */
bool patched;
VirtGuestInfo *guest_info;
} AcpiBuildState;
static
void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables)
{
GArray *table_offsets;
unsigned dsdt, rsdt;
VirtAcpiCpuInfo cpuinfo;
GArray *tables_blob = tables->table_data;
virt_acpi_get_cpu_info(&cpuinfo);
table_offsets = g_array_new(false, true /* clear */,
sizeof(uint32_t));
bios_linker_loader_alloc(tables->linker, ACPI_BUILD_TABLE_FILE,
64, false /* high memory */);
/*
* The ACPI v5.1 tables for Hardware-reduced ACPI platform are:
* RSDP
* RSDT
* FADT
* GTDT
* MADT
* DSDT
*/
/* DSDT is pointed to by FADT */
dsdt = tables_blob->len;
build_dsdt(tables_blob, tables->linker, guest_info);
/* FADT MADT GTDT pointed to by RSDT */
acpi_add_table(table_offsets, tables_blob);
build_fadt(tables_blob, tables->linker, dsdt);
acpi_add_table(table_offsets, tables_blob);
build_madt(tables_blob, tables->linker, guest_info, &cpuinfo);
acpi_add_table(table_offsets, tables_blob);
build_gtdt(tables_blob, tables->linker);
acpi_add_table(table_offsets, tables_blob);
build_mcfg(tables_blob, tables->linker, guest_info);
/* RSDT is pointed to by RSDP */
rsdt = tables_blob->len;
build_rsdt(tables_blob, tables->linker, table_offsets);
/* RSDP is in FSEG memory, so allocate it separately */
build_rsdp(tables->rsdp, tables->linker, rsdt);
/* Cleanup memory that's no longer used. */
g_array_free(table_offsets, true);
}
static void acpi_ram_update(MemoryRegion *mr, GArray *data)
{
uint32_t size = acpi_data_len(data);
/* Make sure RAM size is correct - in case it got changed
* e.g. by migration */
memory_region_ram_resize(mr, size, &error_abort);
memcpy(memory_region_get_ram_ptr(mr), data->data, size);
memory_region_set_dirty(mr, 0, size);
}
static void virt_acpi_build_update(void *build_opaque, uint32_t offset)
{
AcpiBuildState *build_state = build_opaque;
AcpiBuildTables tables;
/* No state to update or already patched? Nothing to do. */
if (!build_state || build_state->patched) {
return;
}
build_state->patched = true;
acpi_build_tables_init(&tables);
virt_acpi_build(build_state->guest_info, &tables);
acpi_ram_update(build_state->table_mr, tables.table_data);
acpi_ram_update(build_state->rsdp_mr, tables.rsdp);
acpi_ram_update(build_state->linker_mr, tables.linker);
acpi_build_tables_cleanup(&tables, true);
}
static void virt_acpi_build_reset(void *build_opaque)
{
AcpiBuildState *build_state = build_opaque;
build_state->patched = false;
}
static MemoryRegion *acpi_add_rom_blob(AcpiBuildState *build_state,
GArray *blob, const char *name,
uint64_t max_size)
{
return rom_add_blob(name, blob->data, acpi_data_len(blob), max_size, -1,
name, virt_acpi_build_update, build_state);
}
static const VMStateDescription vmstate_virt_acpi_build = {
.name = "virt_acpi_build",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_BOOL(patched, AcpiBuildState),
VMSTATE_END_OF_LIST()
},
};
void virt_acpi_setup(VirtGuestInfo *guest_info)
{
AcpiBuildTables tables;
AcpiBuildState *build_state;
if (!guest_info->fw_cfg) {
trace_virt_acpi_setup();
return;
}
if (!acpi_enabled) {
trace_virt_acpi_setup();
return;
}
build_state = g_malloc0(sizeof *build_state);
build_state->guest_info = guest_info;
acpi_build_tables_init(&tables);
virt_acpi_build(build_state->guest_info, &tables);
/* Now expose it all to Guest */
build_state->table_mr = acpi_add_rom_blob(build_state, tables.table_data,
ACPI_BUILD_TABLE_FILE,
ACPI_BUILD_TABLE_MAX_SIZE);
assert(build_state->table_mr != NULL);
build_state->linker_mr =
acpi_add_rom_blob(build_state, tables.linker, "etc/table-loader", 0);
fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
tables.tcpalog->data, acpi_data_len(tables.tcpalog));
build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp,
ACPI_BUILD_RSDP_FILE, 0);
qemu_register_reset(virt_acpi_build_reset, build_state);
virt_acpi_build_reset(build_state);
vmstate_register(NULL, 0, &vmstate_virt_acpi_build, build_state);
/* Cleanup tables but don't free the memory: we track it
* in build_state.
*/
acpi_build_tables_cleanup(&tables, false);
}

View File

@@ -31,6 +31,7 @@
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "hw/arm/arm.h" #include "hw/arm/arm.h"
#include "hw/arm/primecell.h" #include "hw/arm/primecell.h"
#include "hw/arm/virt.h"
#include "hw/devices.h" #include "hw/devices.h"
#include "net/net.h" #include "net/net.h"
#include "sysemu/block-backend.h" #include "sysemu/block-backend.h"
@@ -43,11 +44,12 @@
#include "qemu/bitops.h" #include "qemu/bitops.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "hw/pci-host/gpex.h" #include "hw/pci-host/gpex.h"
#include "hw/arm/virt-acpi-build.h"
#define NUM_VIRTIO_TRANSPORTS 32 #include "hw/arm/sysbus-fdt.h"
#include "hw/platform-bus.h"
/* Number of external interrupt lines to configure the GIC with */ /* Number of external interrupt lines to configure the GIC with */
#define NUM_IRQS 128 #define NUM_IRQS 256
#define GIC_FDT_IRQ_TYPE_SPI 0 #define GIC_FDT_IRQ_TYPE_SPI 0
#define GIC_FDT_IRQ_TYPE_PPI 1 #define GIC_FDT_IRQ_TYPE_PPI 1
@@ -60,23 +62,9 @@
#define GIC_FDT_IRQ_PPI_CPU_START 8 #define GIC_FDT_IRQ_PPI_CPU_START 8
#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8 #define GIC_FDT_IRQ_PPI_CPU_WIDTH 8
enum { #define PLATFORM_BUS_NUM_IRQS 64
VIRT_FLASH,
VIRT_MEM,
VIRT_CPUPERIPHS,
VIRT_GIC_DIST,
VIRT_GIC_CPU,
VIRT_UART,
VIRT_MMIO,
VIRT_RTC,
VIRT_FW_CFG,
VIRT_PCIE,
};
typedef struct MemMapEntry { static ARMPlatformBusSystemParams platform_bus_params;
hwaddr base;
hwaddr size;
} MemMapEntry;
typedef struct VirtBoardInfo { typedef struct VirtBoardInfo {
struct arm_boot_info bootinfo; struct arm_boot_info bootinfo;
@@ -87,6 +75,8 @@ typedef struct VirtBoardInfo {
void *fdt; void *fdt;
int fdt_size; int fdt_size;
uint32_t clock_phandle; uint32_t clock_phandle;
uint32_t gic_phandle;
uint32_t v2m_phandle;
} VirtBoardInfo; } VirtBoardInfo;
typedef struct { typedef struct {
@@ -121,25 +111,22 @@ typedef struct {
*/ */
static const MemMapEntry a15memmap[] = { static const MemMapEntry a15memmap[] = {
/* Space up to 0x8000000 is reserved for a boot ROM */ /* Space up to 0x8000000 is reserved for a boot ROM */
[VIRT_FLASH] = { 0, 0x08000000 }, [VIRT_FLASH] = { 0, 0x08000000 },
[VIRT_CPUPERIPHS] = { 0x08000000, 0x00020000 }, [VIRT_CPUPERIPHS] = { 0x08000000, 0x00020000 },
/* GIC distributor and CPU interfaces sit inside the CPU peripheral space */ /* GIC distributor and CPU interfaces sit inside the CPU peripheral space */
[VIRT_GIC_DIST] = { 0x08000000, 0x00010000 }, [VIRT_GIC_DIST] = { 0x08000000, 0x00010000 },
[VIRT_GIC_CPU] = { 0x08010000, 0x00010000 }, [VIRT_GIC_CPU] = { 0x08010000, 0x00010000 },
[VIRT_UART] = { 0x09000000, 0x00001000 }, [VIRT_GIC_V2M] = { 0x08020000, 0x00001000 },
[VIRT_RTC] = { 0x09010000, 0x00001000 }, [VIRT_UART] = { 0x09000000, 0x00001000 },
[VIRT_FW_CFG] = { 0x09020000, 0x0000000a }, [VIRT_RTC] = { 0x09010000, 0x00001000 },
[VIRT_MMIO] = { 0x0a000000, 0x00000200 }, [VIRT_FW_CFG] = { 0x09020000, 0x0000000a },
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
/* [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
* PCIE verbose map: [VIRT_PCIE_MMIO] = { 0x10000000, 0x2eff0000 },
* [VIRT_PCIE_PIO] = { 0x3eff0000, 0x00010000 },
* MMIO window { 0x10000000, 0x2eff0000 }, [VIRT_PCIE_ECAM] = { 0x3f000000, 0x01000000 },
* PIO window { 0x3eff0000, 0x00010000 }, [VIRT_MEM] = { 0x40000000, 30ULL * 1024 * 1024 * 1024 },
* ECAM { 0x3f000000, 0x01000000 },
*/
[VIRT_PCIE] = { 0x10000000, 0x30000000 },
[VIRT_MEM] = { 0x40000000, 30ULL * 1024 * 1024 * 1024 },
}; };
static const int a15irqmap[] = { static const int a15irqmap[] = {
@@ -147,6 +134,8 @@ static const int a15irqmap[] = {
[VIRT_RTC] = 2, [VIRT_RTC] = 2,
[VIRT_PCIE] = 3, /* ... to 6 */ [VIRT_PCIE] = 3, /* ... to 6 */
[VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */ [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
[VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */
[VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */
}; };
static VirtBoardInfo machines[] = { static VirtBoardInfo machines[] = {
@@ -289,10 +278,10 @@ static void fdt_add_timer_nodes(const VirtBoardInfo *vbi)
"arm,armv7-timer"); "arm,armv7-timer");
} }
qemu_fdt_setprop_cells(vbi->fdt, "/timer", "interrupts", qemu_fdt_setprop_cells(vbi->fdt, "/timer", "interrupts",
GIC_FDT_IRQ_TYPE_PPI, 13, irqflags, GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_S_EL1_IRQ, irqflags,
GIC_FDT_IRQ_TYPE_PPI, 14, irqflags, GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL1_IRQ, irqflags,
GIC_FDT_IRQ_TYPE_PPI, 11, irqflags, GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_VIRT_IRQ, irqflags,
GIC_FDT_IRQ_TYPE_PPI, 10, irqflags); GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL2_IRQ, irqflags);
} }
static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi) static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
@@ -322,12 +311,23 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
} }
} }
static uint32_t fdt_add_gic_node(const VirtBoardInfo *vbi) static void fdt_add_v2m_gic_node(VirtBoardInfo *vbi)
{ {
uint32_t gic_phandle; vbi->v2m_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
qemu_fdt_add_subnode(vbi->fdt, "/intc/v2m");
qemu_fdt_setprop_string(vbi->fdt, "/intc/v2m", "compatible",
"arm,gic-v2m-frame");
qemu_fdt_setprop(vbi->fdt, "/intc/v2m", "msi-controller", NULL, 0);
qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc/v2m", "reg",
2, vbi->memmap[VIRT_GIC_V2M].base,
2, vbi->memmap[VIRT_GIC_V2M].size);
qemu_fdt_setprop_cell(vbi->fdt, "/intc/v2m", "phandle", vbi->v2m_phandle);
}
gic_phandle = qemu_fdt_alloc_phandle(vbi->fdt); static void fdt_add_gic_node(VirtBoardInfo *vbi)
qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", gic_phandle); {
vbi->gic_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", vbi->gic_phandle);
qemu_fdt_add_subnode(vbi->fdt, "/intc"); qemu_fdt_add_subnode(vbi->fdt, "/intc");
/* 'cortex-a15-gic' means 'GIC v2' */ /* 'cortex-a15-gic' means 'GIC v2' */
@@ -340,12 +340,32 @@ static uint32_t fdt_add_gic_node(const VirtBoardInfo *vbi)
2, vbi->memmap[VIRT_GIC_DIST].size, 2, vbi->memmap[VIRT_GIC_DIST].size,
2, vbi->memmap[VIRT_GIC_CPU].base, 2, vbi->memmap[VIRT_GIC_CPU].base,
2, vbi->memmap[VIRT_GIC_CPU].size); 2, vbi->memmap[VIRT_GIC_CPU].size);
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", gic_phandle); qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#address-cells", 0x2);
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#size-cells", 0x2);
return gic_phandle; qemu_fdt_setprop(vbi->fdt, "/intc", "ranges", NULL, 0);
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", vbi->gic_phandle);
} }
static uint32_t create_gic(const VirtBoardInfo *vbi, qemu_irq *pic) static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic)
{
int i;
int irq = vbi->irqmap[VIRT_GIC_V2M];
DeviceState *dev;
dev = qdev_create(NULL, "arm-gicv2m");
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vbi->memmap[VIRT_GIC_V2M].base);
qdev_prop_set_uint32(dev, "base-spi", irq);
qdev_prop_set_uint32(dev, "num-spi", NUM_GICV2M_SPIS);
qdev_init_nofail(dev);
for (i = 0; i < NUM_GICV2M_SPIS; i++) {
sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
}
fdt_add_v2m_gic_node(vbi);
}
static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic)
{ {
/* We create a standalone GIC v2 */ /* We create a standalone GIC v2 */
DeviceState *gicdev; DeviceState *gicdev;
@@ -394,7 +414,9 @@ static uint32_t create_gic(const VirtBoardInfo *vbi, qemu_irq *pic)
pic[i] = qdev_get_gpio_in(gicdev, i); pic[i] = qdev_get_gpio_in(gicdev, i);
} }
return fdt_add_gic_node(vbi); fdt_add_gic_node(vbi);
create_v2m(vbi, pic);
} }
static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic) static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
@@ -533,7 +555,7 @@ static void create_one_flash(const char *name, hwaddr flashbase,
qdev_prop_set_uint64(dev, "sector-length", sectorlength); qdev_prop_set_uint64(dev, "sector-length", sectorlength);
qdev_prop_set_uint8(dev, "width", 4); qdev_prop_set_uint8(dev, "width", 4);
qdev_prop_set_uint8(dev, "device-width", 2); qdev_prop_set_uint8(dev, "device-width", 2);
qdev_prop_set_uint8(dev, "big-endian", 0); qdev_prop_set_bit(dev, "big-endian", false);
qdev_prop_set_uint16(dev, "id0", 0x89); qdev_prop_set_uint16(dev, "id0", 0x89);
qdev_prop_set_uint16(dev, "id1", 0x18); qdev_prop_set_uint16(dev, "id1", 0x18);
qdev_prop_set_uint16(dev, "id2", 0x00); qdev_prop_set_uint16(dev, "id2", 0x00);
@@ -610,7 +632,7 @@ static void create_pcie_irq_map(const VirtBoardInfo *vbi, uint32_t gic_phandle,
int first_irq, const char *nodename) int first_irq, const char *nodename)
{ {
int devfn, pin; int devfn, pin;
uint32_t full_irq_map[4 * 4 * 8] = { 0 }; uint32_t full_irq_map[4 * 4 * 10] = { 0 };
uint32_t *irq_map = full_irq_map; uint32_t *irq_map = full_irq_map;
for (devfn = 0; devfn <= 0x18; devfn += 0x8) { for (devfn = 0; devfn <= 0x18; devfn += 0x8) {
@@ -623,13 +645,13 @@ static void create_pcie_irq_map(const VirtBoardInfo *vbi, uint32_t gic_phandle,
uint32_t map[] = { uint32_t map[] = {
devfn << 8, 0, 0, /* devfn */ devfn << 8, 0, 0, /* devfn */
pin + 1, /* PCI pin */ pin + 1, /* PCI pin */
gic_phandle, irq_type, irq_nr, irq_level }; /* GIC irq */ gic_phandle, 0, 0, irq_type, irq_nr, irq_level }; /* GIC irq */
/* Convert map to big endian */ /* Convert map to big endian */
for (i = 0; i < 8; i++) { for (i = 0; i < 10; i++) {
irq_map[i] = cpu_to_be32(map[i]); irq_map[i] = cpu_to_be32(map[i]);
} }
irq_map += 8; irq_map += 10;
} }
} }
@@ -641,19 +663,16 @@ static void create_pcie_irq_map(const VirtBoardInfo *vbi, uint32_t gic_phandle,
0x7 /* PCI irq */); 0x7 /* PCI irq */);
} }
static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic, static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic)
uint32_t gic_phandle)
{ {
hwaddr base = vbi->memmap[VIRT_PCIE].base; hwaddr base_mmio = vbi->memmap[VIRT_PCIE_MMIO].base;
hwaddr size = vbi->memmap[VIRT_PCIE].size; hwaddr size_mmio = vbi->memmap[VIRT_PCIE_MMIO].size;
hwaddr end = base + size; hwaddr base_pio = vbi->memmap[VIRT_PCIE_PIO].base;
hwaddr size_mmio; hwaddr size_pio = vbi->memmap[VIRT_PCIE_PIO].size;
hwaddr size_ioport = 64 * 1024; hwaddr base_ecam = vbi->memmap[VIRT_PCIE_ECAM].base;
int nr_pcie_buses = 16; hwaddr size_ecam = vbi->memmap[VIRT_PCIE_ECAM].size;
hwaddr size_ecam = PCIE_MMCFG_SIZE_MIN * nr_pcie_buses; hwaddr base = base_mmio;
hwaddr base_mmio = base; int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
hwaddr base_ioport;
hwaddr base_ecam;
int irq = vbi->irqmap[VIRT_PCIE]; int irq = vbi->irqmap[VIRT_PCIE];
MemoryRegion *mmio_alias; MemoryRegion *mmio_alias;
MemoryRegion *mmio_reg; MemoryRegion *mmio_reg;
@@ -663,10 +682,6 @@ static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic,
char *nodename; char *nodename;
int i; int i;
base_ecam = QEMU_ALIGN_DOWN(end - size_ecam, size_ecam);
base_ioport = QEMU_ALIGN_DOWN(base_ecam - size_ioport, size_ioport);
size_mmio = base_ioport - base;
dev = qdev_create(NULL, TYPE_GPEX_HOST); dev = qdev_create(NULL, TYPE_GPEX_HOST);
qdev_init_nofail(dev); qdev_init_nofail(dev);
@@ -689,7 +704,7 @@ static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic,
memory_region_add_subregion(get_system_memory(), base_mmio, mmio_alias); memory_region_add_subregion(get_system_memory(), base_mmio, mmio_alias);
/* Map IO port space */ /* Map IO port space */
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_ioport); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio);
for (i = 0; i < GPEX_NUM_IRQS; i++) { for (i = 0; i < GPEX_NUM_IRQS; i++) {
sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
@@ -705,20 +720,63 @@ static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic,
qemu_fdt_setprop_cells(vbi->fdt, nodename, "bus-range", 0, qemu_fdt_setprop_cells(vbi->fdt, nodename, "bus-range", 0,
nr_pcie_buses - 1); nr_pcie_buses - 1);
qemu_fdt_setprop_cells(vbi->fdt, nodename, "msi-parent", vbi->v2m_phandle);
qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
2, base_ecam, 2, size_ecam); 2, base_ecam, 2, size_ecam);
qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "ranges", qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "ranges",
1, FDT_PCI_RANGE_IOPORT, 2, 0, 1, FDT_PCI_RANGE_IOPORT, 2, 0,
2, base_ioport, 2, size_ioport, 2, base_pio, 2, size_pio,
1, FDT_PCI_RANGE_MMIO, 2, base_mmio, 1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
2, base_mmio, 2, size_mmio); 2, base_mmio, 2, size_mmio);
qemu_fdt_setprop_cell(vbi->fdt, nodename, "#interrupt-cells", 1); qemu_fdt_setprop_cell(vbi->fdt, nodename, "#interrupt-cells", 1);
create_pcie_irq_map(vbi, gic_phandle, irq, nodename); create_pcie_irq_map(vbi, vbi->gic_phandle, irq, nodename);
g_free(nodename); g_free(nodename);
} }
static void create_platform_bus(VirtBoardInfo *vbi, qemu_irq *pic)
{
DeviceState *dev;
SysBusDevice *s;
int i;
ARMPlatformBusFDTParams *fdt_params = g_new(ARMPlatformBusFDTParams, 1);
MemoryRegion *sysmem = get_system_memory();
platform_bus_params.platform_bus_base = vbi->memmap[VIRT_PLATFORM_BUS].base;
platform_bus_params.platform_bus_size = vbi->memmap[VIRT_PLATFORM_BUS].size;
platform_bus_params.platform_bus_first_irq = vbi->irqmap[VIRT_PLATFORM_BUS];
platform_bus_params.platform_bus_num_irqs = PLATFORM_BUS_NUM_IRQS;
fdt_params->system_params = &platform_bus_params;
fdt_params->binfo = &vbi->bootinfo;
fdt_params->intc = "/intc";
/*
* register a machine init done notifier that creates the device tree
* nodes of the platform bus and its children dynamic sysbus devices
*/
arm_register_platform_bus_fdt_creator(fdt_params);
dev = qdev_create(NULL, TYPE_PLATFORM_BUS_DEVICE);
dev->id = TYPE_PLATFORM_BUS_DEVICE;
qdev_prop_set_uint32(dev, "num_irqs",
platform_bus_params.platform_bus_num_irqs);
qdev_prop_set_uint32(dev, "mmio_size",
platform_bus_params.platform_bus_size);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
for (i = 0; i < platform_bus_params.platform_bus_num_irqs; i++) {
int irqn = platform_bus_params.platform_bus_first_irq + i;
sysbus_connect_irq(s, i, pic[irqn]);
}
memory_region_add_subregion(sysmem,
platform_bus_params.platform_bus_base,
sysbus_mmio_get_region(s, 0));
}
static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size) static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
{ {
const VirtBoardInfo *board = (const VirtBoardInfo *)binfo; const VirtBoardInfo *board = (const VirtBoardInfo *)binfo;
@@ -727,6 +785,14 @@ static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
return board->fdt; return board->fdt;
} }
static
void virt_guest_info_machine_done(Notifier *notifier, void *data)
{
VirtGuestInfoState *guest_info_state = container_of(notifier,
VirtGuestInfoState, machine_done);
virt_acpi_setup(&guest_info_state->info);
}
static void machvirt_init(MachineState *machine) static void machvirt_init(MachineState *machine)
{ {
VirtMachineState *vms = VIRT_MACHINE(machine); VirtMachineState *vms = VIRT_MACHINE(machine);
@@ -736,7 +802,8 @@ static void machvirt_init(MachineState *machine)
MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *ram = g_new(MemoryRegion, 1);
const char *cpu_model = machine->cpu_model; const char *cpu_model = machine->cpu_model;
VirtBoardInfo *vbi; VirtBoardInfo *vbi;
uint32_t gic_phandle; VirtGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
VirtGuestInfo *guest_info = &guest_info_state->info;
char **cpustr; char **cpustr;
if (!cpu_model) { if (!cpu_model) {
@@ -813,13 +880,13 @@ static void machvirt_init(MachineState *machine)
create_flash(vbi); create_flash(vbi);
gic_phandle = create_gic(vbi, pic); create_gic(vbi, pic);
create_uart(vbi, pic); create_uart(vbi, pic);
create_rtc(vbi, pic); create_rtc(vbi, pic);
create_pcie(vbi, pic, gic_phandle); create_pcie(vbi, pic);
/* Create mmio transports, so the user can create virtio backends /* Create mmio transports, so the user can create virtio backends
* (which will be automatically plugged in to the transports). If * (which will be automatically plugged in to the transports). If
@@ -828,6 +895,14 @@ static void machvirt_init(MachineState *machine)
create_virtio_devices(vbi, pic); create_virtio_devices(vbi, pic);
create_fw_cfg(vbi); create_fw_cfg(vbi);
rom_set_fw(fw_cfg_find());
guest_info->smp_cpus = smp_cpus;
guest_info->fw_cfg = fw_cfg_find();
guest_info->memmap = vbi->memmap;
guest_info->irqmap = vbi->irqmap;
guest_info_state->machine_done.notify = virt_guest_info_machine_done;
qemu_add_machine_init_done_notifier(&guest_info_state->machine_done);
vbi->bootinfo.ram_size = machine->ram_size; vbi->bootinfo.ram_size = machine->ram_size;
vbi->bootinfo.kernel_filename = machine->kernel_filename; vbi->bootinfo.kernel_filename = machine->kernel_filename;
@@ -839,6 +914,14 @@ static void machvirt_init(MachineState *machine)
vbi->bootinfo.get_dtb = machvirt_dtb; vbi->bootinfo.get_dtb = machvirt_dtb;
vbi->bootinfo.firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0); vbi->bootinfo.firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
arm_load_kernel(ARM_CPU(first_cpu), &vbi->bootinfo); arm_load_kernel(ARM_CPU(first_cpu), &vbi->bootinfo);
/*
* arm_load_kernel machine init done notifier registration must
* happen before the platform_bus_create call. In this latter,
* another notifier is registered which adds platform bus nodes.
* Notifiers are executed in registration reverse order.
*/
create_platform_bus(vbi, pic);
} }
static bool virt_get_secure(Object *obj, Error **errp) static bool virt_get_secure(Object *obj, Error **errp)
@@ -877,6 +960,7 @@ static void virt_class_init(ObjectClass *oc, void *data)
mc->desc = "ARM Virtual Machine", mc->desc = "ARM Virtual Machine",
mc->init = machvirt_init; mc->init = machvirt_init;
mc->max_cpus = 8; mc->max_cpus = 8;
mc->has_dynamic_sysbus = true;
} }
static const TypeInfo machvirt_info = { static const TypeInfo machvirt_info = {

View File

@@ -324,7 +324,7 @@ static void fd_revalidate(FDrive *drv)
/* Intel 82078 floppy disk controller emulation */ /* Intel 82078 floppy disk controller emulation */
static void fdctrl_reset(FDCtrl *fdctrl, int do_irq); static void fdctrl_reset(FDCtrl *fdctrl, int do_irq);
static void fdctrl_reset_fifo(FDCtrl *fdctrl); static void fdctrl_to_command_phase(FDCtrl *fdctrl);
static int fdctrl_transfer_handler (void *opaque, int nchan, static int fdctrl_transfer_handler (void *opaque, int nchan,
int dma_pos, int dma_len); int dma_pos, int dma_len);
static void fdctrl_raise_irq(FDCtrl *fdctrl); static void fdctrl_raise_irq(FDCtrl *fdctrl);
@@ -495,6 +495,33 @@ enum {
FD_DIR_DSKCHG = 0x80, FD_DIR_DSKCHG = 0x80,
}; };
/*
* See chapter 5.0 "Controller phases" of the spec:
*
* Command phase:
* The host writes a command and its parameters into the FIFO. The command
* phase is completed when all parameters for the command have been supplied,
* and execution phase is entered.
*
* Execution phase:
* Data transfers, either DMA or non-DMA. For non-DMA transfers, the FIFO
* contains the payload now, otherwise it's unused. When all bytes of the
* required data have been transferred, the state is switched to either result
* phase (if the command produces status bytes) or directly back into the
* command phase for the next command.
*
* Result phase:
* The host reads out the FIFO, which contains one or more result bytes now.
*/
enum {
/* Only for migration: reconstruct phase from registers like qemu 2.3 */
FD_PHASE_RECONSTRUCT = 0,
FD_PHASE_COMMAND = 1,
FD_PHASE_EXECUTION = 2,
FD_PHASE_RESULT = 3,
};
#define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI) #define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI)
#define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT) #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT)
@@ -504,6 +531,7 @@ struct FDCtrl {
/* Controller state */ /* Controller state */
QEMUTimer *result_timer; QEMUTimer *result_timer;
int dma_chann; int dma_chann;
uint8_t phase;
/* Controller's identification */ /* Controller's identification */
uint8_t version; uint8_t version;
/* HW */ /* HW */
@@ -744,6 +772,28 @@ static const VMStateDescription vmstate_fdrive = {
} }
}; };
/*
* Reconstructs the phase from register values according to the logic that was
* implemented in qemu 2.3. This is the default value that is used if the phase
* subsection is not present on migration.
*
* Don't change this function to reflect newer qemu versions, it is part of
* the migration ABI.
*/
static int reconstruct_phase(FDCtrl *fdctrl)
{
if (fdctrl->msr & FD_MSR_NONDMA) {
return FD_PHASE_EXECUTION;
} else if ((fdctrl->msr & FD_MSR_RQM) == 0) {
/* qemu 2.3 disabled RQM only during DMA transfers */
return FD_PHASE_EXECUTION;
} else if (fdctrl->msr & FD_MSR_DIO) {
return FD_PHASE_RESULT;
} else {
return FD_PHASE_COMMAND;
}
}
static void fdc_pre_save(void *opaque) static void fdc_pre_save(void *opaque)
{ {
FDCtrl *s = opaque; FDCtrl *s = opaque;
@@ -751,12 +801,24 @@ static void fdc_pre_save(void *opaque)
s->dor_vmstate = s->dor | GET_CUR_DRV(s); s->dor_vmstate = s->dor | GET_CUR_DRV(s);
} }
static int fdc_pre_load(void *opaque)
{
FDCtrl *s = opaque;
s->phase = FD_PHASE_RECONSTRUCT;
return 0;
}
static int fdc_post_load(void *opaque, int version_id) static int fdc_post_load(void *opaque, int version_id)
{ {
FDCtrl *s = opaque; FDCtrl *s = opaque;
SET_CUR_DRV(s, s->dor_vmstate & FD_DOR_SELMASK); SET_CUR_DRV(s, s->dor_vmstate & FD_DOR_SELMASK);
s->dor = s->dor_vmstate & ~FD_DOR_SELMASK; s->dor = s->dor_vmstate & ~FD_DOR_SELMASK;
if (s->phase == FD_PHASE_RECONSTRUCT) {
s->phase = reconstruct_phase(s);
}
return 0; return 0;
} }
@@ -794,11 +856,29 @@ static const VMStateDescription vmstate_fdc_result_timer = {
} }
}; };
static bool fdc_phase_needed(void *opaque)
{
FDCtrl *fdctrl = opaque;
return reconstruct_phase(fdctrl) != fdctrl->phase;
}
static const VMStateDescription vmstate_fdc_phase = {
.name = "fdc/phase",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT8(phase, FDCtrl),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_fdc = { static const VMStateDescription vmstate_fdc = {
.name = "fdc", .name = "fdc",
.version_id = 2, .version_id = 2,
.minimum_version_id = 2, .minimum_version_id = 2,
.pre_save = fdc_pre_save, .pre_save = fdc_pre_save,
.pre_load = fdc_pre_load,
.post_load = fdc_post_load, .post_load = fdc_post_load,
.fields = (VMStateField[]) { .fields = (VMStateField[]) {
/* Controller State */ /* Controller State */
@@ -838,6 +918,9 @@ static const VMStateDescription vmstate_fdc = {
} , { } , {
.vmsd = &vmstate_fdc_result_timer, .vmsd = &vmstate_fdc_result_timer,
.needed = fdc_result_timer_needed, .needed = fdc_result_timer_needed,
} , {
.vmsd = &vmstate_fdc_phase,
.needed = fdc_phase_needed,
} , { } , {
/* empty */ /* empty */
} }
@@ -918,7 +1001,7 @@ static void fdctrl_reset(FDCtrl *fdctrl, int do_irq)
fdctrl->data_dir = FD_DIR_WRITE; fdctrl->data_dir = FD_DIR_WRITE;
for (i = 0; i < MAX_FD; i++) for (i = 0; i < MAX_FD; i++)
fd_recalibrate(&fdctrl->drives[i]); fd_recalibrate(&fdctrl->drives[i]);
fdctrl_reset_fifo(fdctrl); fdctrl_to_command_phase(fdctrl);
if (do_irq) { if (do_irq) {
fdctrl->status0 |= FD_SR0_RDYCHG; fdctrl->status0 |= FD_SR0_RDYCHG;
fdctrl_raise_irq(fdctrl); fdctrl_raise_irq(fdctrl);
@@ -1134,17 +1217,22 @@ static uint32_t fdctrl_read_dir(FDCtrl *fdctrl)
return retval; return retval;
} }
/* FIFO state control */ /* Clear the FIFO and update the state for receiving the next command */
static void fdctrl_reset_fifo(FDCtrl *fdctrl) static void fdctrl_to_command_phase(FDCtrl *fdctrl)
{ {
fdctrl->phase = FD_PHASE_COMMAND;
fdctrl->data_dir = FD_DIR_WRITE; fdctrl->data_dir = FD_DIR_WRITE;
fdctrl->data_pos = 0; fdctrl->data_pos = 0;
fdctrl->data_len = 1; /* Accept command byte, adjust for params later */
fdctrl->msr &= ~(FD_MSR_CMDBUSY | FD_MSR_DIO); fdctrl->msr &= ~(FD_MSR_CMDBUSY | FD_MSR_DIO);
fdctrl->msr |= FD_MSR_RQM;
} }
/* Set FIFO status for the host to read */ /* Update the state to allow the guest to read out the command status.
static void fdctrl_set_fifo(FDCtrl *fdctrl, int fifo_len) * @fifo_len is the number of result bytes to be read out. */
static void fdctrl_to_result_phase(FDCtrl *fdctrl, int fifo_len)
{ {
fdctrl->phase = FD_PHASE_RESULT;
fdctrl->data_dir = FD_DIR_READ; fdctrl->data_dir = FD_DIR_READ;
fdctrl->data_len = fifo_len; fdctrl->data_len = fifo_len;
fdctrl->data_pos = 0; fdctrl->data_pos = 0;
@@ -1157,7 +1245,7 @@ static void fdctrl_unimplemented(FDCtrl *fdctrl, int direction)
qemu_log_mask(LOG_UNIMP, "fdc: unimplemented command 0x%02x\n", qemu_log_mask(LOG_UNIMP, "fdc: unimplemented command 0x%02x\n",
fdctrl->fifo[0]); fdctrl->fifo[0]);
fdctrl->fifo[0] = FD_SR0_INVCMD; fdctrl->fifo[0] = FD_SR0_INVCMD;
fdctrl_set_fifo(fdctrl, 1); fdctrl_to_result_phase(fdctrl, 1);
} }
/* Seek to next sector /* Seek to next sector
@@ -1238,7 +1326,7 @@ static void fdctrl_stop_transfer(FDCtrl *fdctrl, uint8_t status0,
fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO; fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
fdctrl->msr &= ~FD_MSR_NONDMA; fdctrl->msr &= ~FD_MSR_NONDMA;
fdctrl_set_fifo(fdctrl, 7); fdctrl_to_result_phase(fdctrl, 7);
fdctrl_raise_irq(fdctrl); fdctrl_raise_irq(fdctrl);
} }
@@ -1352,7 +1440,7 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
} }
} }
FLOPPY_DPRINTF("start non-DMA transfer\n"); FLOPPY_DPRINTF("start non-DMA transfer\n");
fdctrl->msr |= FD_MSR_NONDMA; fdctrl->msr |= FD_MSR_NONDMA | FD_MSR_RQM;
if (direction != FD_DIR_WRITE) if (direction != FD_DIR_WRITE)
fdctrl->msr |= FD_MSR_DIO; fdctrl->msr |= FD_MSR_DIO;
/* IO based transfer: calculate len */ /* IO based transfer: calculate len */
@@ -1505,9 +1593,16 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
FLOPPY_DPRINTF("error: controller not ready for reading\n"); FLOPPY_DPRINTF("error: controller not ready for reading\n");
return 0; return 0;
} }
/* If data_len spans multiple sectors, the current position in the FIFO
* wraps around while fdctrl->data_pos is the real position in the whole
* request. */
pos = fdctrl->data_pos; pos = fdctrl->data_pos;
pos %= FD_SECTOR_LEN; pos %= FD_SECTOR_LEN;
if (fdctrl->msr & FD_MSR_NONDMA) {
switch (fdctrl->phase) {
case FD_PHASE_EXECUTION:
assert(fdctrl->msr & FD_MSR_NONDMA);
if (pos == 0) { if (pos == 0) {
if (fdctrl->data_pos != 0) if (fdctrl->data_pos != 0)
if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) { if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) {
@@ -1523,20 +1618,28 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
memset(fdctrl->fifo, 0, FD_SECTOR_LEN); memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
} }
} }
}
retval = fdctrl->fifo[pos]; if (++fdctrl->data_pos == fdctrl->data_len) {
if (++fdctrl->data_pos == fdctrl->data_len) { fdctrl->msr &= ~FD_MSR_RQM;
fdctrl->data_pos = 0;
/* Switch from transfer mode to status mode
* then from status mode to command mode
*/
if (fdctrl->msr & FD_MSR_NONDMA) {
fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
} else { }
fdctrl_reset_fifo(fdctrl); break;
case FD_PHASE_RESULT:
assert(!(fdctrl->msr & FD_MSR_NONDMA));
if (++fdctrl->data_pos == fdctrl->data_len) {
fdctrl->msr &= ~FD_MSR_RQM;
fdctrl_to_command_phase(fdctrl);
fdctrl_reset_irq(fdctrl); fdctrl_reset_irq(fdctrl);
} }
break;
case FD_PHASE_COMMAND:
default:
abort();
} }
retval = fdctrl->fifo[pos];
FLOPPY_DPRINTF("data register: 0x%02x\n", retval); FLOPPY_DPRINTF("data register: 0x%02x\n", retval);
return retval; return retval;
@@ -1606,7 +1709,7 @@ static void fdctrl_handle_lock(FDCtrl *fdctrl, int direction)
{ {
fdctrl->lock = (fdctrl->fifo[0] & 0x80) ? 1 : 0; fdctrl->lock = (fdctrl->fifo[0] & 0x80) ? 1 : 0;
fdctrl->fifo[0] = fdctrl->lock << 4; fdctrl->fifo[0] = fdctrl->lock << 4;
fdctrl_set_fifo(fdctrl, 1); fdctrl_to_result_phase(fdctrl, 1);
} }
static void fdctrl_handle_dumpreg(FDCtrl *fdctrl, int direction) static void fdctrl_handle_dumpreg(FDCtrl *fdctrl, int direction)
@@ -1631,20 +1734,20 @@ static void fdctrl_handle_dumpreg(FDCtrl *fdctrl, int direction)
(cur_drv->perpendicular << 2); (cur_drv->perpendicular << 2);
fdctrl->fifo[8] = fdctrl->config; fdctrl->fifo[8] = fdctrl->config;
fdctrl->fifo[9] = fdctrl->precomp_trk; fdctrl->fifo[9] = fdctrl->precomp_trk;
fdctrl_set_fifo(fdctrl, 10); fdctrl_to_result_phase(fdctrl, 10);
} }
static void fdctrl_handle_version(FDCtrl *fdctrl, int direction) static void fdctrl_handle_version(FDCtrl *fdctrl, int direction)
{ {
/* Controller's version */ /* Controller's version */
fdctrl->fifo[0] = fdctrl->version; fdctrl->fifo[0] = fdctrl->version;
fdctrl_set_fifo(fdctrl, 1); fdctrl_to_result_phase(fdctrl, 1);
} }
static void fdctrl_handle_partid(FDCtrl *fdctrl, int direction) static void fdctrl_handle_partid(FDCtrl *fdctrl, int direction)
{ {
fdctrl->fifo[0] = 0x41; /* Stepping 1 */ fdctrl->fifo[0] = 0x41; /* Stepping 1 */
fdctrl_set_fifo(fdctrl, 1); fdctrl_to_result_phase(fdctrl, 1);
} }
static void fdctrl_handle_restore(FDCtrl *fdctrl, int direction) static void fdctrl_handle_restore(FDCtrl *fdctrl, int direction)
@@ -1667,7 +1770,7 @@ static void fdctrl_handle_restore(FDCtrl *fdctrl, int direction)
fdctrl->config = fdctrl->fifo[11]; fdctrl->config = fdctrl->fifo[11];
fdctrl->precomp_trk = fdctrl->fifo[12]; fdctrl->precomp_trk = fdctrl->fifo[12];
fdctrl->pwrd = fdctrl->fifo[13]; fdctrl->pwrd = fdctrl->fifo[13];
fdctrl_reset_fifo(fdctrl); fdctrl_to_command_phase(fdctrl);
} }
static void fdctrl_handle_save(FDCtrl *fdctrl, int direction) static void fdctrl_handle_save(FDCtrl *fdctrl, int direction)
@@ -1697,7 +1800,7 @@ static void fdctrl_handle_save(FDCtrl *fdctrl, int direction)
fdctrl->fifo[12] = fdctrl->pwrd; fdctrl->fifo[12] = fdctrl->pwrd;
fdctrl->fifo[13] = 0; fdctrl->fifo[13] = 0;
fdctrl->fifo[14] = 0; fdctrl->fifo[14] = 0;
fdctrl_set_fifo(fdctrl, 15); fdctrl_to_result_phase(fdctrl, 15);
} }
static void fdctrl_handle_readid(FDCtrl *fdctrl, int direction) static void fdctrl_handle_readid(FDCtrl *fdctrl, int direction)
@@ -1746,7 +1849,7 @@ static void fdctrl_handle_specify(FDCtrl *fdctrl, int direction)
else else
fdctrl->dor |= FD_DOR_DMAEN; fdctrl->dor |= FD_DOR_DMAEN;
/* No result back */ /* No result back */
fdctrl_reset_fifo(fdctrl); fdctrl_to_command_phase(fdctrl);
} }
static void fdctrl_handle_sense_drive_status(FDCtrl *fdctrl, int direction) static void fdctrl_handle_sense_drive_status(FDCtrl *fdctrl, int direction)
@@ -1762,7 +1865,7 @@ static void fdctrl_handle_sense_drive_status(FDCtrl *fdctrl, int direction)
(cur_drv->head << 2) | (cur_drv->head << 2) |
GET_CUR_DRV(fdctrl) | GET_CUR_DRV(fdctrl) |
0x28; 0x28;
fdctrl_set_fifo(fdctrl, 1); fdctrl_to_result_phase(fdctrl, 1);
} }
static void fdctrl_handle_recalibrate(FDCtrl *fdctrl, int direction) static void fdctrl_handle_recalibrate(FDCtrl *fdctrl, int direction)
@@ -1772,7 +1875,7 @@ static void fdctrl_handle_recalibrate(FDCtrl *fdctrl, int direction)
SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
cur_drv = get_cur_drv(fdctrl); cur_drv = get_cur_drv(fdctrl);
fd_recalibrate(cur_drv); fd_recalibrate(cur_drv);
fdctrl_reset_fifo(fdctrl); fdctrl_to_command_phase(fdctrl);
/* Raise Interrupt */ /* Raise Interrupt */
fdctrl->status0 |= FD_SR0_SEEK; fdctrl->status0 |= FD_SR0_SEEK;
fdctrl_raise_irq(fdctrl); fdctrl_raise_irq(fdctrl);
@@ -1788,7 +1891,7 @@ static void fdctrl_handle_sense_interrupt_status(FDCtrl *fdctrl, int direction)
fdctrl->reset_sensei--; fdctrl->reset_sensei--;
} else if (!(fdctrl->sra & FD_SRA_INTPEND)) { } else if (!(fdctrl->sra & FD_SRA_INTPEND)) {
fdctrl->fifo[0] = FD_SR0_INVCMD; fdctrl->fifo[0] = FD_SR0_INVCMD;
fdctrl_set_fifo(fdctrl, 1); fdctrl_to_result_phase(fdctrl, 1);
return; return;
} else { } else {
fdctrl->fifo[0] = fdctrl->fifo[0] =
@@ -1797,7 +1900,7 @@ static void fdctrl_handle_sense_interrupt_status(FDCtrl *fdctrl, int direction)
} }
fdctrl->fifo[1] = cur_drv->track; fdctrl->fifo[1] = cur_drv->track;
fdctrl_set_fifo(fdctrl, 2); fdctrl_to_result_phase(fdctrl, 2);
fdctrl_reset_irq(fdctrl); fdctrl_reset_irq(fdctrl);
fdctrl->status0 = FD_SR0_RDYCHG; fdctrl->status0 = FD_SR0_RDYCHG;
} }
@@ -1808,7 +1911,7 @@ static void fdctrl_handle_seek(FDCtrl *fdctrl, int direction)
SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
cur_drv = get_cur_drv(fdctrl); cur_drv = get_cur_drv(fdctrl);
fdctrl_reset_fifo(fdctrl); fdctrl_to_command_phase(fdctrl);
/* The seek command just sends step pulses to the drive and doesn't care if /* The seek command just sends step pulses to the drive and doesn't care if
* there is a medium inserted of if it's banging the head against the drive. * there is a medium inserted of if it's banging the head against the drive.
*/ */
@@ -1825,7 +1928,7 @@ static void fdctrl_handle_perpendicular_mode(FDCtrl *fdctrl, int direction)
if (fdctrl->fifo[1] & 0x80) if (fdctrl->fifo[1] & 0x80)
cur_drv->perpendicular = fdctrl->fifo[1] & 0x7; cur_drv->perpendicular = fdctrl->fifo[1] & 0x7;
/* No result back */ /* No result back */
fdctrl_reset_fifo(fdctrl); fdctrl_to_command_phase(fdctrl);
} }
static void fdctrl_handle_configure(FDCtrl *fdctrl, int direction) static void fdctrl_handle_configure(FDCtrl *fdctrl, int direction)
@@ -1833,20 +1936,20 @@ static void fdctrl_handle_configure(FDCtrl *fdctrl, int direction)
fdctrl->config = fdctrl->fifo[2]; fdctrl->config = fdctrl->fifo[2];
fdctrl->precomp_trk = fdctrl->fifo[3]; fdctrl->precomp_trk = fdctrl->fifo[3];
/* No result back */ /* No result back */
fdctrl_reset_fifo(fdctrl); fdctrl_to_command_phase(fdctrl);
} }
static void fdctrl_handle_powerdown_mode(FDCtrl *fdctrl, int direction) static void fdctrl_handle_powerdown_mode(FDCtrl *fdctrl, int direction)
{ {
fdctrl->pwrd = fdctrl->fifo[1]; fdctrl->pwrd = fdctrl->fifo[1];
fdctrl->fifo[0] = fdctrl->fifo[1]; fdctrl->fifo[0] = fdctrl->fifo[1];
fdctrl_set_fifo(fdctrl, 1); fdctrl_to_result_phase(fdctrl, 1);
} }
static void fdctrl_handle_option(FDCtrl *fdctrl, int direction) static void fdctrl_handle_option(FDCtrl *fdctrl, int direction)
{ {
/* No result back */ /* No result back */
fdctrl_reset_fifo(fdctrl); fdctrl_to_command_phase(fdctrl);
} }
static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direction) static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direction)
@@ -1862,15 +1965,15 @@ static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direct
fdctrl->fifo[0] = fdctrl->fifo[1]; fdctrl->fifo[0] = fdctrl->fifo[1];
fdctrl->fifo[2] = 0; fdctrl->fifo[2] = 0;
fdctrl->fifo[3] = 0; fdctrl->fifo[3] = 0;
fdctrl_set_fifo(fdctrl, 4); fdctrl_to_result_phase(fdctrl, 4);
} else { } else {
fdctrl_reset_fifo(fdctrl); fdctrl_to_command_phase(fdctrl);
} }
} else if (fdctrl->data_len > 7) { } else if (fdctrl->data_len > 7) {
/* ERROR */ /* ERROR */
fdctrl->fifo[0] = 0x80 | fdctrl->fifo[0] = 0x80 |
(cur_drv->head << 2) | GET_CUR_DRV(fdctrl); (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
fdctrl_set_fifo(fdctrl, 1); fdctrl_to_result_phase(fdctrl, 1);
} }
} }
@@ -1887,7 +1990,7 @@ static void fdctrl_handle_relative_seek_in(FDCtrl *fdctrl, int direction)
fd_seek(cur_drv, cur_drv->head, fd_seek(cur_drv, cur_drv->head,
cur_drv->track + fdctrl->fifo[2], cur_drv->sect, 1); cur_drv->track + fdctrl->fifo[2], cur_drv->sect, 1);
} }
fdctrl_reset_fifo(fdctrl); fdctrl_to_command_phase(fdctrl);
/* Raise Interrupt */ /* Raise Interrupt */
fdctrl->status0 |= FD_SR0_SEEK; fdctrl->status0 |= FD_SR0_SEEK;
fdctrl_raise_irq(fdctrl); fdctrl_raise_irq(fdctrl);
@@ -1905,20 +2008,25 @@ static void fdctrl_handle_relative_seek_out(FDCtrl *fdctrl, int direction)
fd_seek(cur_drv, cur_drv->head, fd_seek(cur_drv, cur_drv->head,
cur_drv->track - fdctrl->fifo[2], cur_drv->sect, 1); cur_drv->track - fdctrl->fifo[2], cur_drv->sect, 1);
} }
fdctrl_reset_fifo(fdctrl); fdctrl_to_command_phase(fdctrl);
/* Raise Interrupt */ /* Raise Interrupt */
fdctrl->status0 |= FD_SR0_SEEK; fdctrl->status0 |= FD_SR0_SEEK;
fdctrl_raise_irq(fdctrl); fdctrl_raise_irq(fdctrl);
} }
static const struct { /*
* Handlers for the execution phase of each command
*/
typedef struct FDCtrlCommand {
uint8_t value; uint8_t value;
uint8_t mask; uint8_t mask;
const char* name; const char* name;
int parameters; int parameters;
void (*handler)(FDCtrl *fdctrl, int direction); void (*handler)(FDCtrl *fdctrl, int direction);
int direction; int direction;
} handlers[] = { } FDCtrlCommand;
static const FDCtrlCommand handlers[] = {
{ FD_CMD_READ, 0x1f, "READ", 8, fdctrl_start_transfer, FD_DIR_READ }, { FD_CMD_READ, 0x1f, "READ", 8, fdctrl_start_transfer, FD_DIR_READ },
{ FD_CMD_WRITE, 0x3f, "WRITE", 8, fdctrl_start_transfer, FD_DIR_WRITE }, { FD_CMD_WRITE, 0x3f, "WRITE", 8, fdctrl_start_transfer, FD_DIR_WRITE },
{ FD_CMD_SEEK, 0xff, "SEEK", 2, fdctrl_handle_seek }, { FD_CMD_SEEK, 0xff, "SEEK", 2, fdctrl_handle_seek },
@@ -1955,9 +2063,19 @@ static const struct {
/* Associate command to an index in the 'handlers' array */ /* Associate command to an index in the 'handlers' array */
static uint8_t command_to_handler[256]; static uint8_t command_to_handler[256];
static const FDCtrlCommand *get_command(uint8_t cmd)
{
int idx;
idx = command_to_handler[cmd];
FLOPPY_DPRINTF("%s command\n", handlers[idx].name);
return &handlers[idx];
}
static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value) static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
{ {
FDrive *cur_drv; FDrive *cur_drv;
const FDCtrlCommand *cmd;
uint32_t pos; uint32_t pos;
/* Reset mode */ /* Reset mode */
@@ -1970,12 +2088,27 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
return; return;
} }
fdctrl->dsr &= ~FD_DSR_PWRDOWN; fdctrl->dsr &= ~FD_DSR_PWRDOWN;
/* Is it write command time ? */
if (fdctrl->msr & FD_MSR_NONDMA) { FLOPPY_DPRINTF("%s: %02x\n", __func__, value);
/* If data_len spans multiple sectors, the current position in the FIFO
* wraps around while fdctrl->data_pos is the real position in the whole
* request. */
pos = fdctrl->data_pos++;
pos %= FD_SECTOR_LEN;
fdctrl->fifo[pos] = value;
if (fdctrl->data_pos == fdctrl->data_len) {
fdctrl->msr &= ~FD_MSR_RQM;
}
switch (fdctrl->phase) {
case FD_PHASE_EXECUTION:
/* For DMA requests, RQM should be cleared during execution phase, so
* we would have errored out above. */
assert(fdctrl->msr & FD_MSR_NONDMA);
/* FIFO data write */ /* FIFO data write */
pos = fdctrl->data_pos++;
pos %= FD_SECTOR_LEN;
fdctrl->fifo[pos] = value;
if (pos == FD_SECTOR_LEN - 1 || if (pos == FD_SECTOR_LEN - 1 ||
fdctrl->data_pos == fdctrl->data_len) { fdctrl->data_pos == fdctrl->data_len) {
cur_drv = get_cur_drv(fdctrl); cur_drv = get_cur_drv(fdctrl);
@@ -1983,45 +2116,54 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
< 0) { < 0) {
FLOPPY_DPRINTF("error writing sector %d\n", FLOPPY_DPRINTF("error writing sector %d\n",
fd_sector(cur_drv)); fd_sector(cur_drv));
return; break;
} }
if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) { if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) {
FLOPPY_DPRINTF("error seeking to next sector %d\n", FLOPPY_DPRINTF("error seeking to next sector %d\n",
fd_sector(cur_drv)); fd_sector(cur_drv));
return; break;
} }
} }
/* Switch from transfer mode to status mode
* then from status mode to command mode
*/
if (fdctrl->data_pos == fdctrl->data_len)
fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
return;
}
if (fdctrl->data_pos == 0) {
/* Command */
pos = command_to_handler[value & 0xff];
FLOPPY_DPRINTF("%s command\n", handlers[pos].name);
fdctrl->data_len = handlers[pos].parameters + 1;
fdctrl->msr |= FD_MSR_CMDBUSY;
}
FLOPPY_DPRINTF("%s: %02x\n", __func__, value); /* Switch to result phase when done with the transfer */
pos = fdctrl->data_pos++; if (fdctrl->data_pos == fdctrl->data_len) {
pos %= FD_SECTOR_LEN; fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
fdctrl->fifo[pos] = value; }
if (fdctrl->data_pos == fdctrl->data_len) { break;
/* We now have all parameters
* and will be able to treat the command case FD_PHASE_COMMAND:
*/ assert(!(fdctrl->msr & FD_MSR_NONDMA));
if (fdctrl->data_state & FD_STATE_FORMAT) { assert(fdctrl->data_pos < FD_SECTOR_LEN);
fdctrl_format_sector(fdctrl);
return; if (pos == 0) {
/* The first byte specifies the command. Now we start reading
* as many parameters as this command requires. */
cmd = get_command(value);
fdctrl->data_len = cmd->parameters + 1;
if (cmd->parameters) {
fdctrl->msr |= FD_MSR_RQM;
}
fdctrl->msr |= FD_MSR_CMDBUSY;
} }
pos = command_to_handler[fdctrl->fifo[0] & 0xff]; if (fdctrl->data_pos == fdctrl->data_len) {
FLOPPY_DPRINTF("treat %s command\n", handlers[pos].name); /* We have all parameters now, execute the command */
(*handlers[pos].handler)(fdctrl, handlers[pos].direction); fdctrl->phase = FD_PHASE_EXECUTION;
if (fdctrl->data_state & FD_STATE_FORMAT) {
fdctrl_format_sector(fdctrl);
break;
}
cmd = get_command(fdctrl->fifo[0]);
FLOPPY_DPRINTF("Calling handler for '%s'\n", cmd->name);
cmd->handler(fdctrl, cmd->direction);
}
break;
case FD_PHASE_RESULT:
default:
abort();
} }
} }

View File

@@ -64,6 +64,9 @@ do { \
#define TYPE_CFI_PFLASH01 "cfi.pflash01" #define TYPE_CFI_PFLASH01 "cfi.pflash01"
#define CFI_PFLASH01(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH01) #define CFI_PFLASH01(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH01)
#define PFLASH_BE 0
#define PFLASH_SECURE 1
struct pflash_t { struct pflash_t {
/*< private >*/ /*< private >*/
SysBusDevice parent_obj; SysBusDevice parent_obj;
@@ -75,7 +78,7 @@ struct pflash_t {
uint8_t bank_width; uint8_t bank_width;
uint8_t device_width; /* If 0, device width not specified. */ uint8_t device_width; /* If 0, device width not specified. */
uint8_t max_device_width; /* max device width in bytes */ uint8_t max_device_width; /* max device width in bytes */
uint8_t be; uint32_t features;
uint8_t wcycle; /* if 0, the flash is read normally */ uint8_t wcycle; /* if 0, the flash is read normally */
int ro; int ro;
uint8_t cmd; uint8_t cmd;
@@ -235,12 +238,57 @@ static uint32_t pflash_devid_query(pflash_t *pfl, hwaddr offset)
return resp; return resp;
} }
static uint32_t pflash_data_read(pflash_t *pfl, hwaddr offset,
int width, int be)
{
uint8_t *p;
uint32_t ret;
p = pfl->storage;
switch (width) {
case 1:
ret = p[offset];
DPRINTF("%s: data offset " TARGET_FMT_plx " %02x\n",
__func__, offset, ret);
break;
case 2:
if (be) {
ret = p[offset] << 8;
ret |= p[offset + 1];
} else {
ret = p[offset];
ret |= p[offset + 1] << 8;
}
DPRINTF("%s: data offset " TARGET_FMT_plx " %04x\n",
__func__, offset, ret);
break;
case 4:
if (be) {
ret = p[offset] << 24;
ret |= p[offset + 1] << 16;
ret |= p[offset + 2] << 8;
ret |= p[offset + 3];
} else {
ret = p[offset];
ret |= p[offset + 1] << 8;
ret |= p[offset + 2] << 16;
ret |= p[offset + 3] << 24;
}
DPRINTF("%s: data offset " TARGET_FMT_plx " %08x\n",
__func__, offset, ret);
break;
default:
DPRINTF("BUG in %s\n", __func__);
abort();
}
return ret;
}
static uint32_t pflash_read (pflash_t *pfl, hwaddr offset, static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
int width, int be) int width, int be)
{ {
hwaddr boff; hwaddr boff;
uint32_t ret; uint32_t ret;
uint8_t *p;
ret = -1; ret = -1;
@@ -257,43 +305,7 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
/* fall through to read code */ /* fall through to read code */
case 0x00: case 0x00:
/* Flash area read */ /* Flash area read */
p = pfl->storage; ret = pflash_data_read(pfl, offset, width, be);
switch (width) {
case 1:
ret = p[offset];
DPRINTF("%s: data offset " TARGET_FMT_plx " %02x\n",
__func__, offset, ret);
break;
case 2:
if (be) {
ret = p[offset] << 8;
ret |= p[offset + 1];
} else {
ret = p[offset];
ret |= p[offset + 1] << 8;
}
DPRINTF("%s: data offset " TARGET_FMT_plx " %04x\n",
__func__, offset, ret);
break;
case 4:
if (be) {
ret = p[offset] << 24;
ret |= p[offset + 1] << 16;
ret |= p[offset + 2] << 8;
ret |= p[offset + 3];
} else {
ret = p[offset];
ret |= p[offset + 1] << 8;
ret |= p[offset + 2] << 16;
ret |= p[offset + 3] << 24;
}
DPRINTF("%s: data offset " TARGET_FMT_plx " %08x\n",
__func__, offset, ret);
break;
default:
DPRINTF("BUG in %s\n", __func__);
}
break; break;
case 0x10: /* Single byte program */ case 0x10: /* Single byte program */
case 0x20: /* Block erase */ case 0x20: /* Block erase */
@@ -648,101 +660,37 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
} }
static uint32_t pflash_readb_be(void *opaque, hwaddr addr) static MemTxResult pflash_mem_read_with_attrs(void *opaque, hwaddr addr, uint64_t *value,
{ unsigned len, MemTxAttrs attrs)
return pflash_read(opaque, addr, 1, 1);
}
static uint32_t pflash_readb_le(void *opaque, hwaddr addr)
{
return pflash_read(opaque, addr, 1, 0);
}
static uint32_t pflash_readw_be(void *opaque, hwaddr addr)
{ {
pflash_t *pfl = opaque; pflash_t *pfl = opaque;
bool be = !!(pfl->features & (1 << PFLASH_BE));
return pflash_read(pfl, addr, 2, 1); if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
*value = pflash_data_read(opaque, addr, len, be);
} else {
*value = pflash_read(opaque, addr, len, be);
}
return MEMTX_OK;
} }
static uint32_t pflash_readw_le(void *opaque, hwaddr addr) static MemTxResult pflash_mem_write_with_attrs(void *opaque, hwaddr addr, uint64_t value,
unsigned len, MemTxAttrs attrs)
{ {
pflash_t *pfl = opaque; pflash_t *pfl = opaque;
bool be = !!(pfl->features & (1 << PFLASH_BE));
return pflash_read(pfl, addr, 2, 0); if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
return MEMTX_ERROR;
} else {
pflash_write(opaque, addr, value, len, be);
return MEMTX_OK;
}
} }
static uint32_t pflash_readl_be(void *opaque, hwaddr addr) static const MemoryRegionOps pflash_cfi01_ops = {
{ .read_with_attrs = pflash_mem_read_with_attrs,
pflash_t *pfl = opaque; .write_with_attrs = pflash_mem_write_with_attrs,
return pflash_read(pfl, addr, 4, 1);
}
static uint32_t pflash_readl_le(void *opaque, hwaddr addr)
{
pflash_t *pfl = opaque;
return pflash_read(pfl, addr, 4, 0);
}
static void pflash_writeb_be(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_write(opaque, addr, value, 1, 1);
}
static void pflash_writeb_le(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_write(opaque, addr, value, 1, 0);
}
static void pflash_writew_be(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_t *pfl = opaque;
pflash_write(pfl, addr, value, 2, 1);
}
static void pflash_writew_le(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_t *pfl = opaque;
pflash_write(pfl, addr, value, 2, 0);
}
static void pflash_writel_be(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_t *pfl = opaque;
pflash_write(pfl, addr, value, 4, 1);
}
static void pflash_writel_le(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_t *pfl = opaque;
pflash_write(pfl, addr, value, 4, 0);
}
static const MemoryRegionOps pflash_cfi01_ops_be = {
.old_mmio = {
.read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, },
.write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, },
},
.endianness = DEVICE_NATIVE_ENDIAN,
};
static const MemoryRegionOps pflash_cfi01_ops_le = {
.old_mmio = {
.read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, },
.write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, },
},
.endianness = DEVICE_NATIVE_ENDIAN, .endianness = DEVICE_NATIVE_ENDIAN,
}; };
@@ -773,7 +721,8 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
memory_region_init_rom_device( memory_region_init_rom_device(
&pfl->mem, OBJECT(dev), &pfl->mem, OBJECT(dev),
pfl->be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl, &pflash_cfi01_ops,
pfl,
pfl->name, total_len, &local_err); pfl->name, total_len, &local_err);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
@@ -925,7 +874,8 @@ static Property pflash_cfi01_properties[] = {
DEFINE_PROP_UINT8("width", struct pflash_t, bank_width, 0), DEFINE_PROP_UINT8("width", struct pflash_t, bank_width, 0),
DEFINE_PROP_UINT8("device-width", struct pflash_t, device_width, 0), DEFINE_PROP_UINT8("device-width", struct pflash_t, device_width, 0),
DEFINE_PROP_UINT8("max-device-width", struct pflash_t, max_device_width, 0), DEFINE_PROP_UINT8("max-device-width", struct pflash_t, max_device_width, 0),
DEFINE_PROP_UINT8("big-endian", struct pflash_t, be, 0), DEFINE_PROP_BIT("big-endian", struct pflash_t, features, PFLASH_BE, 0),
DEFINE_PROP_BIT("secure", struct pflash_t, features, PFLASH_SECURE, 0),
DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0), DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0), DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0), DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0),
@@ -975,7 +925,7 @@ pflash_t *pflash_cfi01_register(hwaddr base,
qdev_prop_set_uint32(dev, "num-blocks", nb_blocs); qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
qdev_prop_set_uint64(dev, "sector-length", sector_len); qdev_prop_set_uint64(dev, "sector-length", sector_len);
qdev_prop_set_uint8(dev, "width", bank_width); qdev_prop_set_uint8(dev, "width", bank_width);
qdev_prop_set_uint8(dev, "big-endian", !!be); qdev_prop_set_bit(dev, "big-endian", !!be);
qdev_prop_set_uint16(dev, "id0", id0); qdev_prop_set_uint16(dev, "id0", id0);
qdev_prop_set_uint16(dev, "id1", id1); qdev_prop_set_uint16(dev, "id1", id1);
qdev_prop_set_uint16(dev, "id2", id2); qdev_prop_set_uint16(dev, "id2", id2);

View File

@@ -718,7 +718,7 @@ static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
aio_context_release(blk_get_aio_context(s->blk)); aio_context_release(blk_get_aio_context(s->blk));
} }
static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features) static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features)
{ {
VirtIOBlock *s = VIRTIO_BLK(vdev); VirtIOBlock *s = VIRTIO_BLK(vdev);

View File

@@ -641,28 +641,3 @@ static void parallel_register_types(void)
} }
type_init(parallel_register_types) type_init(parallel_register_types)
static void parallel_init(ISABus *bus, int index, CharDriverState *chr)
{
DeviceState *dev;
ISADevice *isadev;
isadev = isa_create(bus, "isa-parallel");
dev = DEVICE(isadev);
qdev_prop_set_uint32(dev, "index", index);
qdev_prop_set_chr(dev, "chardev", chr);
qdev_init_nofail(dev);
}
void parallel_hds_isa_init(ISABus *bus, int n)
{
int i;
assert(n <= MAX_PARALLEL_PORTS);
for (i = 0; i < n; i++) {
if (parallel_hds[i]) {
parallel_init(bus, i, parallel_hds[i]);
}
}
}

View File

@@ -95,6 +95,15 @@ static void set_guest_connected(VirtIOSerialPort *port, int guest_connected)
} }
} }
static void guest_writable(VirtIOSerialPort *port)
{
VirtConsole *vcon = VIRTIO_CONSOLE(port);
if (vcon->chr) {
qemu_chr_accept_input(vcon->chr);
}
}
/* Readiness of the guest to accept data on a port */ /* Readiness of the guest to accept data on a port */
static int chr_can_read(void *opaque) static int chr_can_read(void *opaque)
{ {
@@ -188,6 +197,7 @@ static void virtserialport_class_init(ObjectClass *klass, void *data)
k->unrealize = virtconsole_unrealize; k->unrealize = virtconsole_unrealize;
k->have_data = flush_buf; k->have_data = flush_buf;
k->set_guest_connected = set_guest_connected; k->set_guest_connected = set_guest_connected;
k->guest_writable = guest_writable;
dc->props = virtserialport_properties; dc->props = virtserialport_properties;
} }

View File

@@ -498,7 +498,7 @@ static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
} }
} }
static uint32_t get_features(VirtIODevice *vdev, uint32_t features) static uint64_t get_features(VirtIODevice *vdev, uint64_t features)
{ {
VirtIOSerial *vser; VirtIOSerial *vser;
@@ -973,7 +973,7 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp)
} }
/* Each port takes 2 queues, and one pair is for the control queue */ /* Each port takes 2 queues, and one pair is for the control queue */
max_supported_ports = VIRTIO_PCI_QUEUE_MAX / 2 - 1; max_supported_ports = VIRTIO_QUEUE_MAX / 2 - 1;
if (vser->serial.max_virtserial_ports > max_supported_ports) { if (vser->serial.max_virtserial_ports > max_supported_ports) {
error_setg(errp, "maximum ports supported: %u", max_supported_ports); error_setg(errp, "maximum ports supported: %u", max_supported_ports);

View File

@@ -294,6 +294,14 @@ static void machine_init_notify(Notifier *notifier, void *data)
foreach_dynamic_sysbus_device(error_on_sysbus_device, NULL); foreach_dynamic_sysbus_device(error_on_sysbus_device, NULL);
} }
static void machine_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
/* Default 128 MB as guest ram size */
mc->default_ram_size = 128 * M_BYTE;
}
static void machine_initfn(Object *obj) static void machine_initfn(Object *obj)
{ {
MachineState *ms = MACHINE(obj); MachineState *ms = MACHINE(obj);
@@ -463,6 +471,7 @@ static const TypeInfo machine_info = {
.parent = TYPE_OBJECT, .parent = TYPE_OBJECT,
.abstract = true, .abstract = true,
.class_size = sizeof(MachineClass), .class_size = sizeof(MachineClass),
.class_init = machine_class_init,
.instance_size = sizeof(MachineState), .instance_size = sizeof(MachineState),
.instance_init = machine_initfn, .instance_init = machine_initfn,
.instance_finalize = machine_finalize, .instance_finalize = machine_finalize,

View File

@@ -389,7 +389,7 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
nd->instantiated = 1; nd->instantiated = 1;
} }
static int qdev_add_one_global(QemuOpts *opts, void *opaque) static int qdev_add_one_global(void *opaque, QemuOpts *opts, Error **errp)
{ {
GlobalProperty *g; GlobalProperty *g;
@@ -404,5 +404,6 @@ static int qdev_add_one_global(QemuOpts *opts, void *opaque)
void qemu_add_globals(void) void qemu_add_globals(void)
{ {
qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0); qemu_opts_foreach(qemu_find_opts("global"),
qdev_add_one_global, NULL, NULL);
} }

View File

@@ -125,6 +125,64 @@ PropertyInfo qdev_prop_bit = {
.set = prop_set_bit, .set = prop_set_bit,
}; };
/* Bit64 */
static uint64_t qdev_get_prop_mask64(Property *prop)
{
assert(prop->info == &qdev_prop_bit);
return 0x1 << prop->bitnr;
}
static void bit64_prop_set(DeviceState *dev, Property *props, bool val)
{
uint64_t *p = qdev_get_prop_ptr(dev, props);
uint64_t mask = qdev_get_prop_mask64(props);
if (val) {
*p |= mask;
} else {
*p &= ~mask;
}
}
static void prop_get_bit64(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
uint64_t *p = qdev_get_prop_ptr(dev, prop);
bool value = (*p & qdev_get_prop_mask64(prop)) != 0;
visit_type_bool(v, &value, name, errp);
}
static void prop_set_bit64(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
Error *local_err = NULL;
bool value;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
visit_type_bool(v, &value, name, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
bit64_prop_set(dev, prop, value);
}
PropertyInfo qdev_prop_bit64 = {
.name = "bool",
.description = "on/off",
.get = prop_get_bit64,
.set = prop_set_bit64,
};
/* --- bool --- */ /* --- bool --- */
static void get_bool(Object *obj, Visitor *v, void *opaque, static void get_bool(Object *obj, Visitor *v, void *opaque,

View File

@@ -34,3 +34,5 @@ obj-$(CONFIG_CG3) += cg3.o
obj-$(CONFIG_VGA) += vga.o obj-$(CONFIG_VGA) += vga.o
common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o
obj-$(CONFIG_VIRTIO) += virtio-gpu.o

View File

@@ -106,6 +106,7 @@ static void cg3_update_display(void *opaque)
pix = memory_region_get_ram_ptr(&s->vram_mem); pix = memory_region_get_ram_ptr(&s->vram_mem);
data = (uint32_t *)surface_data(surface); data = (uint32_t *)surface_data(surface);
memory_region_sync_dirty_bitmap(&s->vram_mem);
for (y = 0; y < height; y++) { for (y = 0; y < height; y++) {
int update = s->full_update; int update = s->full_update;
@@ -309,6 +310,7 @@ static void cg3_realizefn(DeviceState *dev, Error **errp)
memory_region_init_ram(&s->vram_mem, NULL, "cg3.vram", s->vram_size, memory_region_init_ram(&s->vram_mem, NULL, "cg3.vram", s->vram_size,
&error_abort); &error_abort);
memory_region_set_log(&s->vram_mem, true, DIRTY_MEMORY_VGA);
vmstate_register_ram_global(&s->vram_mem); vmstate_register_ram_global(&s->vram_mem);
sysbus_init_mmio(sbd, &s->vram_mem); sysbus_init_mmio(sbd, &s->vram_mem);

View File

@@ -1109,6 +1109,12 @@ static inline int fimd_get_buffer_id(Exynos4210fimdWindow *w)
} }
} }
static void exynos4210_fimd_invalidate(void *opaque)
{
Exynos4210fimdState *s = (Exynos4210fimdState *)opaque;
s->invalidate = true;
}
/* Updates specified window's MemorySection based on values of WINCON, /* Updates specified window's MemorySection based on values of WINCON,
* VIDOSDA, VIDOSDB, VIDWADDx and SHADOWCON registers */ * VIDOSDA, VIDOSDB, VIDWADDx and SHADOWCON registers */
static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win) static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win)
@@ -1136,7 +1142,11 @@ static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win)
/* TODO: add .exit and unref the region there. Not needed yet since sysbus /* TODO: add .exit and unref the region there. Not needed yet since sysbus
* does not support hot-unplug. * does not support hot-unplug.
*/ */
memory_region_unref(w->mem_section.mr); if (w->mem_section.mr) {
memory_region_set_log(w->mem_section.mr, false, DIRTY_MEMORY_VGA);
memory_region_unref(w->mem_section.mr);
}
w->mem_section = memory_region_find(sysbus_address_space(sbd), w->mem_section = memory_region_find(sysbus_address_space(sbd),
fb_start_addr, w->fb_len); fb_start_addr, w->fb_len);
assert(w->mem_section.mr); assert(w->mem_section.mr);
@@ -1162,6 +1172,8 @@ static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win)
cpu_physical_memory_unmap(w->host_fb_addr, fb_mapped_len, 0, 0); cpu_physical_memory_unmap(w->host_fb_addr, fb_mapped_len, 0, 0);
goto error_return; goto error_return;
} }
memory_region_set_log(w->mem_section.mr, true, DIRTY_MEMORY_VGA);
exynos4210_fimd_invalidate(s);
return; return;
error_return: error_return:
@@ -1224,12 +1236,6 @@ static void exynos4210_fimd_update_irq(Exynos4210fimdState *s)
} }
} }
static void exynos4210_fimd_invalidate(void *opaque)
{
Exynos4210fimdState *s = (Exynos4210fimdState *)opaque;
s->invalidate = true;
}
static void exynos4210_update_resolution(Exynos4210fimdState *s) static void exynos4210_update_resolution(Exynos4210fimdState *s)
{ {
DisplaySurface *surface = qemu_console_surface(s->console); DisplaySurface *surface = qemu_console_surface(s->console);

View File

@@ -63,6 +63,10 @@ void framebuffer_update_display(
assert(mem_section.offset_within_address_space == base); assert(mem_section.offset_within_address_space == base);
memory_region_sync_dirty_bitmap(mem); memory_region_sync_dirty_bitmap(mem);
if (!memory_region_is_logging(mem, DIRTY_MEMORY_VGA)) {
invalidate = true;
}
src_base = cpu_physical_memory_map(base, &src_len, 0); src_base = cpu_physical_memory_map(base, &src_len, 0);
/* If we can't map the framebuffer then bail. We could try harder, /* If we can't map the framebuffer then bail. We could try harder,
but it's not really worth it as dirty flag tracking will probably but it's not really worth it as dirty flag tracking will probably

View File

@@ -260,6 +260,7 @@ static void g364fb_update_display(void *opaque)
qemu_console_resize(s->con, s->width, s->height); qemu_console_resize(s->con, s->width, s->height);
} }
memory_region_sync_dirty_bitmap(&s->mem_vram);
if (s->ctla & CTLA_FORCE_BLANK) { if (s->ctla & CTLA_FORCE_BLANK) {
g364fb_draw_blank(s); g364fb_draw_blank(s);
} else if (s->depth == 8) { } else if (s->depth == 8) {
@@ -489,7 +490,7 @@ static void g364fb_init(DeviceState *dev, G364State *s)
memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram", memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram",
s->vram_size, s->vram); s->vram_size, s->vram);
vmstate_register_ram(&s->mem_vram, dev); vmstate_register_ram(&s->mem_vram, dev);
memory_region_set_coalescing(&s->mem_vram); memory_region_set_log(&s->mem_vram, true, DIRTY_MEMORY_VGA);
} }
#define TYPE_G364 "sysbus-g364" #define TYPE_G364 "sysbus-g364"

View File

@@ -504,6 +504,10 @@ static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
{ {
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
if (!qemu_spice_display_is_running(&qxl->ssd)) {
return;
}
trace_qxl_interface_set_mm_time(qxl->id, mm_time); trace_qxl_interface_set_mm_time(qxl->id, mm_time);
qxl->shadow_rom.mm_clock = cpu_to_le32(mm_time); qxl->shadow_rom.mm_clock = cpu_to_le32(mm_time);
qxl->rom->mm_clock = cpu_to_le32(mm_time); qxl->rom->mm_clock = cpu_to_le32(mm_time);

View File

@@ -1322,6 +1322,7 @@ static void sm501_draw_crt(SM501State * s)
} }
/* draw each line according to conditions */ /* draw each line according to conditions */
memory_region_sync_dirty_bitmap(&s->local_mem_region);
for (y = 0; y < height; y++) { for (y = 0; y < height; y++) {
int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0; int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0;
int update = full_update || update_hwc; int update = full_update || update_hwc;
@@ -1412,6 +1413,7 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
memory_region_init_ram(&s->local_mem_region, NULL, "sm501.local", memory_region_init_ram(&s->local_mem_region, NULL, "sm501.local",
local_mem_bytes, &error_abort); local_mem_bytes, &error_abort);
vmstate_register_ram_global(&s->local_mem_region); vmstate_register_ram_global(&s->local_mem_region);
memory_region_set_log(&s->local_mem_region, true, DIRTY_MEMORY_VGA);
s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region); s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region);
memory_region_add_subregion(address_space_mem, base, &s->local_mem_region); memory_region_add_subregion(address_space_mem, base, &s->local_mem_region);

View File

@@ -571,7 +571,7 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)
s->irq = irq; s->irq = irq;
s->gpio_in = qemu_allocate_irqs(tc6393xb_gpio_set, s, TC6393XB_GPIOS); s->gpio_in = qemu_allocate_irqs(tc6393xb_gpio_set, s, TC6393XB_GPIOS);
s->l3v = *qemu_allocate_irqs(tc6393xb_l3v, s, 1); s->l3v = qemu_allocate_irq(tc6393xb_l3v, s, 0);
s->blanked = 1; s->blanked = 1;
s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS); s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS);

View File

@@ -353,6 +353,7 @@ static void tcx_update_display(void *opaque)
return; return;
} }
memory_region_sync_dirty_bitmap(&ts->vram_mem);
for (y = 0; y < ts->height; page += TARGET_PAGE_SIZE) { for (y = 0; y < ts->height; page += TARGET_PAGE_SIZE) {
if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE, if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE,
DIRTY_MEMORY_VGA)) { DIRTY_MEMORY_VGA)) {
@@ -446,6 +447,7 @@ static void tcx24_update_display(void *opaque)
dd = surface_stride(surface); dd = surface_stride(surface);
ds = 1024; ds = 1024;
memory_region_sync_dirty_bitmap(&ts->vram_mem);
for (y = 0; y < ts->height; page += TARGET_PAGE_SIZE, for (y = 0; y < ts->height; page += TARGET_PAGE_SIZE,
page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) { page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) {
if (tcx24_check_dirty(ts, page, page24, cpage)) { if (tcx24_check_dirty(ts, page, page24, cpage)) {
@@ -1006,6 +1008,7 @@ static void tcx_realizefn(DeviceState *dev, Error **errp)
memory_region_init_ram(&s->vram_mem, OBJECT(s), "tcx.vram", memory_region_init_ram(&s->vram_mem, OBJECT(s), "tcx.vram",
s->vram_size * (1 + 4 + 4), &error_abort); s->vram_size * (1 + 4 + 4), &error_abort);
vmstate_register_ram_global(&s->vram_mem); vmstate_register_ram_global(&s->vram_mem);
memory_region_set_log(&s->vram_mem, true, DIRTY_MEMORY_VGA);
vram_base = memory_region_get_ram_ptr(&s->vram_mem); vram_base = memory_region_get_ram_ptr(&s->vram_mem);
/* 10/ROM : FCode ROM */ /* 10/ROM : FCode ROM */

View File

@@ -54,9 +54,7 @@ typedef struct PCIVGAState {
VGACommonState vga; VGACommonState vga;
uint32_t flags; uint32_t flags;
MemoryRegion mmio; MemoryRegion mmio;
MemoryRegion ioport; MemoryRegion mrs[3];
MemoryRegion bochs;
MemoryRegion qext;
} PCIVGAState; } PCIVGAState;
#define TYPE_PCI_VGA "pci-vga" #define TYPE_PCI_VGA "pci-vga"
@@ -76,16 +74,16 @@ static const VMStateDescription vmstate_vga_pci = {
static uint64_t pci_vga_ioport_read(void *ptr, hwaddr addr, static uint64_t pci_vga_ioport_read(void *ptr, hwaddr addr,
unsigned size) unsigned size)
{ {
PCIVGAState *d = ptr; VGACommonState *s = ptr;
uint64_t ret = 0; uint64_t ret = 0;
switch (size) { switch (size) {
case 1: case 1:
ret = vga_ioport_read(&d->vga, addr); ret = vga_ioport_read(s, addr + 0x3c0);
break; break;
case 2: case 2:
ret = vga_ioport_read(&d->vga, addr); ret = vga_ioport_read(s, addr + 0x3c0);
ret |= vga_ioport_read(&d->vga, addr+1) << 8; ret |= vga_ioport_read(s, addr + 0x3c1) << 8;
break; break;
} }
return ret; return ret;
@@ -94,11 +92,11 @@ static uint64_t pci_vga_ioport_read(void *ptr, hwaddr addr,
static void pci_vga_ioport_write(void *ptr, hwaddr addr, static void pci_vga_ioport_write(void *ptr, hwaddr addr,
uint64_t val, unsigned size) uint64_t val, unsigned size)
{ {
PCIVGAState *d = ptr; VGACommonState *s = ptr;
switch (size) { switch (size) {
case 1: case 1:
vga_ioport_write(&d->vga, addr + 0x3c0, val); vga_ioport_write(s, addr + 0x3c0, val);
break; break;
case 2: case 2:
/* /*
@@ -106,8 +104,8 @@ static void pci_vga_ioport_write(void *ptr, hwaddr addr,
* indexed registers with a single word write because the * indexed registers with a single word write because the
* index byte is updated first. * index byte is updated first.
*/ */
vga_ioport_write(&d->vga, addr + 0x3c0, val & 0xff); vga_ioport_write(s, addr + 0x3c0, val & 0xff);
vga_ioport_write(&d->vga, addr + 0x3c1, (val >> 8) & 0xff); vga_ioport_write(s, addr + 0x3c1, (val >> 8) & 0xff);
break; break;
} }
} }
@@ -125,21 +123,21 @@ static const MemoryRegionOps pci_vga_ioport_ops = {
static uint64_t pci_vga_bochs_read(void *ptr, hwaddr addr, static uint64_t pci_vga_bochs_read(void *ptr, hwaddr addr,
unsigned size) unsigned size)
{ {
PCIVGAState *d = ptr; VGACommonState *s = ptr;
int index = addr >> 1; int index = addr >> 1;
vbe_ioport_write_index(&d->vga, 0, index); vbe_ioport_write_index(s, 0, index);
return vbe_ioport_read_data(&d->vga, 0); return vbe_ioport_read_data(s, 0);
} }
static void pci_vga_bochs_write(void *ptr, hwaddr addr, static void pci_vga_bochs_write(void *ptr, hwaddr addr,
uint64_t val, unsigned size) uint64_t val, unsigned size)
{ {
PCIVGAState *d = ptr; VGACommonState *s = ptr;
int index = addr >> 1; int index = addr >> 1;
vbe_ioport_write_index(&d->vga, 0, index); vbe_ioport_write_index(s, 0, index);
vbe_ioport_write_data(&d->vga, 0, val); vbe_ioport_write_data(s, 0, val);
} }
static const MemoryRegionOps pci_vga_bochs_ops = { static const MemoryRegionOps pci_vga_bochs_ops = {
@@ -154,13 +152,13 @@ static const MemoryRegionOps pci_vga_bochs_ops = {
static uint64_t pci_vga_qext_read(void *ptr, hwaddr addr, unsigned size) static uint64_t pci_vga_qext_read(void *ptr, hwaddr addr, unsigned size)
{ {
PCIVGAState *d = ptr; VGACommonState *s = ptr;
switch (addr) { switch (addr) {
case PCI_VGA_QEXT_REG_SIZE: case PCI_VGA_QEXT_REG_SIZE:
return PCI_VGA_QEXT_SIZE; return PCI_VGA_QEXT_SIZE;
case PCI_VGA_QEXT_REG_BYTEORDER: case PCI_VGA_QEXT_REG_BYTEORDER:
return d->vga.big_endian_fb ? return s->big_endian_fb ?
PCI_VGA_QEXT_BIG_ENDIAN : PCI_VGA_QEXT_LITTLE_ENDIAN; PCI_VGA_QEXT_BIG_ENDIAN : PCI_VGA_QEXT_LITTLE_ENDIAN;
default: default:
return 0; return 0;
@@ -170,15 +168,15 @@ static uint64_t pci_vga_qext_read(void *ptr, hwaddr addr, unsigned size)
static void pci_vga_qext_write(void *ptr, hwaddr addr, static void pci_vga_qext_write(void *ptr, hwaddr addr,
uint64_t val, unsigned size) uint64_t val, unsigned size)
{ {
PCIVGAState *d = ptr; VGACommonState *s = ptr;
switch (addr) { switch (addr) {
case PCI_VGA_QEXT_REG_BYTEORDER: case PCI_VGA_QEXT_REG_BYTEORDER:
if (val == PCI_VGA_QEXT_BIG_ENDIAN) { if (val == PCI_VGA_QEXT_BIG_ENDIAN) {
d->vga.big_endian_fb = true; s->big_endian_fb = true;
} }
if (val == PCI_VGA_QEXT_LITTLE_ENDIAN) { if (val == PCI_VGA_QEXT_LITTLE_ENDIAN) {
d->vga.big_endian_fb = false; s->big_endian_fb = false;
} }
break; break;
} }
@@ -206,10 +204,34 @@ static const MemoryRegionOps pci_vga_qext_ops = {
.endianness = DEVICE_LITTLE_ENDIAN, .endianness = DEVICE_LITTLE_ENDIAN,
}; };
static void pci_std_vga_mmio_region_init(VGACommonState *s,
MemoryRegion *parent,
MemoryRegion *subs,
bool qext)
{
memory_region_init_io(&subs[0], NULL, &pci_vga_ioport_ops, s,
"vga ioports remapped", PCI_VGA_IOPORT_SIZE);
memory_region_add_subregion(parent, PCI_VGA_IOPORT_OFFSET,
&subs[0]);
memory_region_init_io(&subs[1], NULL, &pci_vga_bochs_ops, s,
"bochs dispi interface", PCI_VGA_BOCHS_SIZE);
memory_region_add_subregion(parent, PCI_VGA_BOCHS_OFFSET,
&subs[1]);
if (qext) {
memory_region_init_io(&subs[2], NULL, &pci_vga_qext_ops, s,
"qemu extended regs", PCI_VGA_QEXT_SIZE);
memory_region_add_subregion(parent, PCI_VGA_QEXT_OFFSET,
&subs[2]);
}
}
static void pci_std_vga_realize(PCIDevice *dev, Error **errp) static void pci_std_vga_realize(PCIDevice *dev, Error **errp)
{ {
PCIVGAState *d = PCI_VGA(dev); PCIVGAState *d = PCI_VGA(dev);
VGACommonState *s = &d->vga; VGACommonState *s = &d->vga;
bool qext = false;
/* vga + console init */ /* vga + console init */
vga_common_init(s, OBJECT(dev), true); vga_common_init(s, OBJECT(dev), true);
@@ -224,23 +246,12 @@ static void pci_std_vga_realize(PCIDevice *dev, Error **errp)
/* mmio bar for vga register access */ /* mmio bar for vga register access */
if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_MMIO)) { if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_MMIO)) {
memory_region_init(&d->mmio, NULL, "vga.mmio", 4096); memory_region_init(&d->mmio, NULL, "vga.mmio", 4096);
memory_region_init_io(&d->ioport, NULL, &pci_vga_ioport_ops, d,
"vga ioports remapped", PCI_VGA_IOPORT_SIZE);
memory_region_init_io(&d->bochs, NULL, &pci_vga_bochs_ops, d,
"bochs dispi interface", PCI_VGA_BOCHS_SIZE);
memory_region_add_subregion(&d->mmio, PCI_VGA_IOPORT_OFFSET,
&d->ioport);
memory_region_add_subregion(&d->mmio, PCI_VGA_BOCHS_OFFSET,
&d->bochs);
if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_QEXT)) { if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_QEXT)) {
memory_region_init_io(&d->qext, NULL, &pci_vga_qext_ops, d, qext = true;
"qemu extended regs", PCI_VGA_QEXT_SIZE);
memory_region_add_subregion(&d->mmio, PCI_VGA_QEXT_OFFSET,
&d->qext);
pci_set_byte(&d->dev.config[PCI_REVISION_ID], 2); pci_set_byte(&d->dev.config[PCI_REVISION_ID], 2);
} }
pci_std_vga_mmio_region_init(s, &d->mmio, d->mrs, qext);
pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
} }
@@ -262,6 +273,7 @@ static void pci_secondary_vga_realize(PCIDevice *dev, Error **errp)
{ {
PCIVGAState *d = PCI_VGA(dev); PCIVGAState *d = PCI_VGA(dev);
VGACommonState *s = &d->vga; VGACommonState *s = &d->vga;
bool qext = false;
/* vga + console init */ /* vga + console init */
vga_common_init(s, OBJECT(dev), false); vga_common_init(s, OBJECT(dev), false);
@@ -269,23 +281,12 @@ static void pci_secondary_vga_realize(PCIDevice *dev, Error **errp)
/* mmio bar */ /* mmio bar */
memory_region_init(&d->mmio, OBJECT(dev), "vga.mmio", 4096); memory_region_init(&d->mmio, OBJECT(dev), "vga.mmio", 4096);
memory_region_init_io(&d->ioport, OBJECT(dev), &pci_vga_ioport_ops, d,
"vga ioports remapped", PCI_VGA_IOPORT_SIZE);
memory_region_init_io(&d->bochs, OBJECT(dev), &pci_vga_bochs_ops, d,
"bochs dispi interface", PCI_VGA_BOCHS_SIZE);
memory_region_add_subregion(&d->mmio, PCI_VGA_IOPORT_OFFSET,
&d->ioport);
memory_region_add_subregion(&d->mmio, PCI_VGA_BOCHS_OFFSET,
&d->bochs);
if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_QEXT)) { if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_QEXT)) {
memory_region_init_io(&d->qext, NULL, &pci_vga_qext_ops, d, qext = true;
"qemu extended regs", PCI_VGA_QEXT_SIZE);
memory_region_add_subregion(&d->mmio, PCI_VGA_QEXT_OFFSET,
&d->qext);
pci_set_byte(&d->dev.config[PCI_REVISION_ID], 2); pci_set_byte(&d->dev.config[PCI_REVISION_ID], 2);
} }
pci_std_vga_mmio_region_init(s, &d->mmio, d->mrs, qext);
pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);

918
hw/display/virtio-gpu.c Normal file
View File

@@ -0,0 +1,918 @@
/*
* Virtio GPU Device
*
* Copyright Red Hat, Inc. 2013-2014
*
* Authors:
* Dave Airlie <airlied@redhat.com>
* Gerd Hoffmann <kraxel@redhat.com>
*
* This work is licensed under the terms of the GNU GPL, version 2.
* See the COPYING file in the top-level directory.
*/
#include "qemu-common.h"
#include "qemu/iov.h"
#include "ui/console.h"
#include "trace.h"
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-gpu.h"
#include "hw/virtio/virtio-bus.h"
static struct virtio_gpu_simple_resource*
virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
static void update_cursor_data_simple(VirtIOGPU *g,
struct virtio_gpu_scanout *s,
uint32_t resource_id)
{
struct virtio_gpu_simple_resource *res;
uint32_t pixels;
res = virtio_gpu_find_resource(g, resource_id);
if (!res) {
return;
}
if (pixman_image_get_width(res->image) != s->current_cursor->width ||
pixman_image_get_height(res->image) != s->current_cursor->height) {
return;
}
pixels = s->current_cursor->width * s->current_cursor->height;
memcpy(s->current_cursor->data,
pixman_image_get_data(res->image),
pixels * sizeof(uint32_t));
}
static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor)
{
struct virtio_gpu_scanout *s;
if (cursor->pos.scanout_id >= g->conf.max_outputs) {
return;
}
s = &g->scanout[cursor->pos.scanout_id];
if (cursor->hdr.type != VIRTIO_GPU_CMD_MOVE_CURSOR) {
if (!s->current_cursor) {
s->current_cursor = cursor_alloc(64, 64);
}
s->current_cursor->hot_x = cursor->hot_x;
s->current_cursor->hot_y = cursor->hot_y;
if (cursor->resource_id > 0) {
update_cursor_data_simple(g, s, cursor->resource_id);
}
dpy_cursor_define(s->con, s->current_cursor);
}
dpy_mouse_set(s->con, cursor->pos.x, cursor->pos.y,
cursor->resource_id ? 1 : 0);
}
static void virtio_gpu_get_config(VirtIODevice *vdev, uint8_t *config)
{
VirtIOGPU *g = VIRTIO_GPU(vdev);
memcpy(config, &g->virtio_config, sizeof(g->virtio_config));
}
static void virtio_gpu_set_config(VirtIODevice *vdev, const uint8_t *config)
{
VirtIOGPU *g = VIRTIO_GPU(vdev);
struct virtio_gpu_config vgconfig;
memcpy(&vgconfig, config, sizeof(g->virtio_config));
if (vgconfig.events_clear) {
g->virtio_config.events_read &= ~vgconfig.events_clear;
}
}
static uint64_t virtio_gpu_get_features(VirtIODevice *vdev, uint64_t features)
{
return features;
}
static void virtio_gpu_notify_event(VirtIOGPU *g, uint32_t event_type)
{
g->virtio_config.events_read |= event_type;
virtio_notify_config(&g->parent_obj);
}
static struct virtio_gpu_simple_resource *
virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id)
{
struct virtio_gpu_simple_resource *res;
QTAILQ_FOREACH(res, &g->reslist, next) {
if (res->resource_id == resource_id) {
return res;
}
}
return NULL;
}
void virtio_gpu_ctrl_response(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd,
struct virtio_gpu_ctrl_hdr *resp,
size_t resp_len)
{
size_t s;
if (cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE) {
resp->flags |= VIRTIO_GPU_FLAG_FENCE;
resp->fence_id = cmd->cmd_hdr.fence_id;
resp->ctx_id = cmd->cmd_hdr.ctx_id;
}
s = iov_from_buf(cmd->elem.in_sg, cmd->elem.in_num, 0, resp, resp_len);
if (s != resp_len) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: response size incorrect %zu vs %zu\n",
__func__, s, resp_len);
}
virtqueue_push(cmd->vq, &cmd->elem, s);
virtio_notify(VIRTIO_DEVICE(g), cmd->vq);
cmd->finished = true;
}
void virtio_gpu_ctrl_response_nodata(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd,
enum virtio_gpu_ctrl_type type)
{
struct virtio_gpu_ctrl_hdr resp;
memset(&resp, 0, sizeof(resp));
resp.type = type;
virtio_gpu_ctrl_response(g, cmd, &resp, sizeof(resp));
}
static void
virtio_gpu_fill_display_info(VirtIOGPU *g,
struct virtio_gpu_resp_display_info *dpy_info)
{
int i;
for (i = 0; i < g->conf.max_outputs; i++) {
if (g->enabled_output_bitmask & (1 << i)) {
dpy_info->pmodes[i].enabled = 1;
dpy_info->pmodes[i].r.width = g->req_state[i].width;
dpy_info->pmodes[i].r.height = g->req_state[i].height;
}
}
}
void virtio_gpu_get_display_info(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
struct virtio_gpu_resp_display_info display_info;
trace_virtio_gpu_cmd_get_display_info();
memset(&display_info, 0, sizeof(display_info));
display_info.hdr.type = VIRTIO_GPU_RESP_OK_DISPLAY_INFO;
virtio_gpu_fill_display_info(g, &display_info);
virtio_gpu_ctrl_response(g, cmd, &display_info.hdr,
sizeof(display_info));
}
static pixman_format_code_t get_pixman_format(uint32_t virtio_gpu_format)
{
switch (virtio_gpu_format) {
#ifdef HOST_WORDS_BIGENDIAN
case VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM:
return PIXMAN_b8g8r8x8;
case VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM:
return PIXMAN_b8g8r8a8;
case VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM:
return PIXMAN_x8r8g8b8;
case VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM:
return PIXMAN_a8r8g8b8;
case VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM:
return PIXMAN_r8g8b8x8;
case VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM:
return PIXMAN_r8g8b8a8;
case VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM:
return PIXMAN_x8b8g8r8;
case VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM:
return PIXMAN_a8b8g8r8;
#else
case VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM:
return PIXMAN_x8r8g8b8;
case VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM:
return PIXMAN_a8r8g8b8;
case VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM:
return PIXMAN_b8g8r8x8;
case VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM:
return PIXMAN_b8g8r8a8;
case VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM:
return PIXMAN_x8b8g8r8;
case VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM:
return PIXMAN_a8b8g8r8;
case VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM:
return PIXMAN_r8g8b8x8;
case VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM:
return PIXMAN_r8g8b8a8;
#endif
default:
return 0;
}
}
static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
pixman_format_code_t pformat;
struct virtio_gpu_simple_resource *res;
struct virtio_gpu_resource_create_2d c2d;
VIRTIO_GPU_FILL_CMD(c2d);
trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format,
c2d.width, c2d.height);
if (c2d.resource_id == 0) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
__func__);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
res = virtio_gpu_find_resource(g, c2d.resource_id);
if (res) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
__func__, c2d.resource_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
res = g_new0(struct virtio_gpu_simple_resource, 1);
res->width = c2d.width;
res->height = c2d.height;
res->format = c2d.format;
res->resource_id = c2d.resource_id;
pformat = get_pixman_format(c2d.format);
if (!pformat) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: host couldn't handle guest format %d\n",
__func__, c2d.format);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
return;
}
res->image = pixman_image_create_bits(pformat,
c2d.width,
c2d.height,
NULL, 0);
if (!res->image) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: resource creation failed %d %d %d\n",
__func__, c2d.resource_id, c2d.width, c2d.height);
g_free(res);
cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
return;
}
QTAILQ_INSERT_HEAD(&g->reslist, res, next);
}
static void virtio_gpu_resource_destroy(VirtIOGPU *g,
struct virtio_gpu_simple_resource *res)
{
pixman_image_unref(res->image);
QTAILQ_REMOVE(&g->reslist, res, next);
g_free(res);
}
static void virtio_gpu_resource_unref(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
struct virtio_gpu_simple_resource *res;
struct virtio_gpu_resource_unref unref;
VIRTIO_GPU_FILL_CMD(unref);
trace_virtio_gpu_cmd_res_unref(unref.resource_id);
res = virtio_gpu_find_resource(g, unref.resource_id);
if (!res) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
__func__, unref.resource_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
virtio_gpu_resource_destroy(g, res);
}
static void virtio_gpu_transfer_to_host_2d(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
struct virtio_gpu_simple_resource *res;
int h;
uint32_t src_offset, dst_offset, stride;
int bpp;
pixman_format_code_t format;
struct virtio_gpu_transfer_to_host_2d t2d;
VIRTIO_GPU_FILL_CMD(t2d);
trace_virtio_gpu_cmd_res_xfer_toh_2d(t2d.resource_id);
res = virtio_gpu_find_resource(g, t2d.resource_id);
if (!res || !res->iov) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
__func__, t2d.resource_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
if (t2d.r.x > res->width ||
t2d.r.y > res->height ||
t2d.r.width > res->width ||
t2d.r.height > res->height ||
t2d.r.x + t2d.r.width > res->width ||
t2d.r.y + t2d.r.height > res->height) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: transfer bounds outside resource"
" bounds for resource %d: %d %d %d %d vs %d %d\n",
__func__, t2d.resource_id, t2d.r.x, t2d.r.y,
t2d.r.width, t2d.r.height, res->width, res->height);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
return;
}
format = pixman_image_get_format(res->image);
bpp = (PIXMAN_FORMAT_BPP(format) + 7) / 8;
stride = pixman_image_get_stride(res->image);
if (t2d.offset || t2d.r.x || t2d.r.y ||
t2d.r.width != pixman_image_get_width(res->image)) {
void *img_data = pixman_image_get_data(res->image);
for (h = 0; h < t2d.r.height; h++) {
src_offset = t2d.offset + stride * h;
dst_offset = (t2d.r.y + h) * stride + (t2d.r.x * bpp);
iov_to_buf(res->iov, res->iov_cnt, src_offset,
(uint8_t *)img_data
+ dst_offset, t2d.r.width * bpp);
}
} else {
iov_to_buf(res->iov, res->iov_cnt, 0,
pixman_image_get_data(res->image),
pixman_image_get_stride(res->image)
* pixman_image_get_height(res->image));
}
}
static void virtio_gpu_resource_flush(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
struct virtio_gpu_simple_resource *res;
struct virtio_gpu_resource_flush rf;
pixman_region16_t flush_region;
int i;
VIRTIO_GPU_FILL_CMD(rf);
trace_virtio_gpu_cmd_res_flush(rf.resource_id,
rf.r.width, rf.r.height, rf.r.x, rf.r.y);
res = virtio_gpu_find_resource(g, rf.resource_id);
if (!res) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
__func__, rf.resource_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
if (rf.r.x > res->width ||
rf.r.y > res->height ||
rf.r.width > res->width ||
rf.r.height > res->height ||
rf.r.x + rf.r.width > res->width ||
rf.r.y + rf.r.height > res->height) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: flush bounds outside resource"
" bounds for resource %d: %d %d %d %d vs %d %d\n",
__func__, rf.resource_id, rf.r.x, rf.r.y,
rf.r.width, rf.r.height, res->width, res->height);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
return;
}
pixman_region_init_rect(&flush_region,
rf.r.x, rf.r.y, rf.r.width, rf.r.height);
for (i = 0; i < VIRTIO_GPU_MAX_SCANOUT; i++) {
struct virtio_gpu_scanout *scanout;
pixman_region16_t region, finalregion;
pixman_box16_t *extents;
if (!(res->scanout_bitmask & (1 << i))) {
continue;
}
scanout = &g->scanout[i];
pixman_region_init(&finalregion);
pixman_region_init_rect(&region, scanout->x, scanout->y,
scanout->width, scanout->height);
pixman_region_intersect(&finalregion, &flush_region, &region);
pixman_region_translate(&finalregion, -scanout->x, -scanout->y);
extents = pixman_region_extents(&finalregion);
/* work out the area we need to update for each console */
dpy_gfx_update(g->scanout[i].con,
extents->x1, extents->y1,
extents->x2 - extents->x1,
extents->y2 - extents->y1);
pixman_region_fini(&region);
pixman_region_fini(&finalregion);
}
pixman_region_fini(&flush_region);
}
static void virtio_gpu_set_scanout(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
struct virtio_gpu_simple_resource *res;
struct virtio_gpu_scanout *scanout;
pixman_format_code_t format;
uint32_t offset;
int bpp;
struct virtio_gpu_set_scanout ss;
VIRTIO_GPU_FILL_CMD(ss);
trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id,
ss.r.width, ss.r.height, ss.r.x, ss.r.y);
g->enable = 1;
if (ss.resource_id == 0) {
scanout = &g->scanout[ss.scanout_id];
if (scanout->resource_id) {
res = virtio_gpu_find_resource(g, scanout->resource_id);
if (res) {
res->scanout_bitmask &= ~(1 << ss.scanout_id);
}
}
if (ss.scanout_id == 0 ||
ss.scanout_id >= g->conf.max_outputs) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: illegal scanout id specified %d",
__func__, ss.scanout_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
return;
}
dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, NULL);
scanout->ds = NULL;
scanout->width = 0;
scanout->height = 0;
return;
}
/* create a surface for this scanout */
if (ss.scanout_id >= VIRTIO_GPU_MAX_SCANOUT ||
ss.scanout_id >= g->conf.max_outputs) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
__func__, ss.scanout_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
return;
}
res = virtio_gpu_find_resource(g, ss.resource_id);
if (!res) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
__func__, ss.resource_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
if (ss.r.x > res->width ||
ss.r.y > res->height ||
ss.r.width > res->width ||
ss.r.height > res->height ||
ss.r.x + ss.r.width > res->width ||
ss.r.y + ss.r.height > res->height) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
" resource %d, (%d,%d)+%d,%d vs %d %d\n",
__func__, ss.scanout_id, ss.resource_id, ss.r.x, ss.r.y,
ss.r.width, ss.r.height, res->width, res->height);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
return;
}
scanout = &g->scanout[ss.scanout_id];
format = pixman_image_get_format(res->image);
bpp = (PIXMAN_FORMAT_BPP(format) + 7) / 8;
offset = (ss.r.x * bpp) + ss.r.y * pixman_image_get_stride(res->image);
if (!scanout->ds || surface_data(scanout->ds)
!= ((uint8_t *)pixman_image_get_data(res->image) + offset) ||
scanout->width != ss.r.width ||
scanout->height != ss.r.height) {
/* realloc the surface ptr */
scanout->ds = qemu_create_displaysurface_from
(ss.r.width, ss.r.height, format,
pixman_image_get_stride(res->image),
(uint8_t *)pixman_image_get_data(res->image) + offset);
if (!scanout->ds) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;
}
dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, scanout->ds);
}
res->scanout_bitmask |= (1 << ss.scanout_id);
scanout->resource_id = ss.resource_id;
scanout->x = ss.r.x;
scanout->y = ss.r.y;
scanout->width = ss.r.width;
scanout->height = ss.r.height;
}
int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
struct virtio_gpu_ctrl_command *cmd,
struct iovec **iov)
{
struct virtio_gpu_mem_entry *ents;
size_t esize, s;
int i;
if (ab->nr_entries > 16384) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: nr_entries is too big (%d > 1024)\n",
__func__, ab->nr_entries);
return -1;
}
esize = sizeof(*ents) * ab->nr_entries;
ents = g_malloc(esize);
s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
sizeof(*ab), ents, esize);
if (s != esize) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: command data size incorrect %zu vs %zu\n",
__func__, s, esize);
g_free(ents);
return -1;
}
*iov = g_malloc0(sizeof(struct iovec) * ab->nr_entries);
for (i = 0; i < ab->nr_entries; i++) {
hwaddr len = ents[i].length;
(*iov)[i].iov_len = ents[i].length;
(*iov)[i].iov_base = cpu_physical_memory_map(ents[i].addr, &len, 1);
if (!(*iov)[i].iov_base || len != ents[i].length) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
" resource %d element %d\n",
__func__, ab->resource_id, i);
virtio_gpu_cleanup_mapping_iov(*iov, i);
g_free(ents);
g_free(*iov);
*iov = NULL;
return -1;
}
}
g_free(ents);
return 0;
}
void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count)
{
int i;
for (i = 0; i < count; i++) {
cpu_physical_memory_unmap(iov[i].iov_base, iov[i].iov_len, 1,
iov[i].iov_len);
}
}
static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res)
{
virtio_gpu_cleanup_mapping_iov(res->iov, res->iov_cnt);
g_free(res->iov);
res->iov = NULL;
res->iov_cnt = 0;
}
static void
virtio_gpu_resource_attach_backing(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
struct virtio_gpu_simple_resource *res;
struct virtio_gpu_resource_attach_backing ab;
int ret;
VIRTIO_GPU_FILL_CMD(ab);
trace_virtio_gpu_cmd_res_back_attach(ab.resource_id);
res = virtio_gpu_find_resource(g, ab.resource_id);
if (!res) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
__func__, ab.resource_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->iov);
if (ret != 0) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;
}
res->iov_cnt = ab.nr_entries;
}
static void
virtio_gpu_resource_detach_backing(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
struct virtio_gpu_simple_resource *res;
struct virtio_gpu_resource_detach_backing detach;
VIRTIO_GPU_FILL_CMD(detach);
trace_virtio_gpu_cmd_res_back_detach(detach.resource_id);
res = virtio_gpu_find_resource(g, detach.resource_id);
if (!res || !res->iov) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
__func__, detach.resource_id);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
virtio_gpu_cleanup_mapping(res);
}
static void virtio_gpu_simple_process_cmd(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr);
switch (cmd->cmd_hdr.type) {
case VIRTIO_GPU_CMD_GET_DISPLAY_INFO:
virtio_gpu_get_display_info(g, cmd);
break;
case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D:
virtio_gpu_resource_create_2d(g, cmd);
break;
case VIRTIO_GPU_CMD_RESOURCE_UNREF:
virtio_gpu_resource_unref(g, cmd);
break;
case VIRTIO_GPU_CMD_RESOURCE_FLUSH:
virtio_gpu_resource_flush(g, cmd);
break;
case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D:
virtio_gpu_transfer_to_host_2d(g, cmd);
break;
case VIRTIO_GPU_CMD_SET_SCANOUT:
virtio_gpu_set_scanout(g, cmd);
break;
case VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING:
virtio_gpu_resource_attach_backing(g, cmd);
break;
case VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING:
virtio_gpu_resource_detach_backing(g, cmd);
break;
default:
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
break;
}
if (!cmd->finished) {
virtio_gpu_ctrl_response_nodata(g, cmd, cmd->error ? cmd->error :
VIRTIO_GPU_RESP_OK_NODATA);
}
}
static void virtio_gpu_handle_ctrl_cb(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOGPU *g = VIRTIO_GPU(vdev);
qemu_bh_schedule(g->ctrl_bh);
}
static void virtio_gpu_handle_cursor_cb(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOGPU *g = VIRTIO_GPU(vdev);
qemu_bh_schedule(g->cursor_bh);
}
static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOGPU *g = VIRTIO_GPU(vdev);
struct virtio_gpu_ctrl_command *cmd;
if (!virtio_queue_ready(vq)) {
return;
}
cmd = g_new(struct virtio_gpu_ctrl_command, 1);
while (virtqueue_pop(vq, &cmd->elem)) {
cmd->vq = vq;
cmd->error = 0;
cmd->finished = false;
g->stats.requests++;
virtio_gpu_simple_process_cmd(g, cmd);
if (!cmd->finished) {
QTAILQ_INSERT_TAIL(&g->fenceq, cmd, next);
g->stats.inflight++;
if (g->stats.max_inflight < g->stats.inflight) {
g->stats.max_inflight = g->stats.inflight;
}
fprintf(stderr, "inflight: %3d (+)\r", g->stats.inflight);
cmd = g_new(struct virtio_gpu_ctrl_command, 1);
}
}
g_free(cmd);
}
static void virtio_gpu_ctrl_bh(void *opaque)
{
VirtIOGPU *g = opaque;
virtio_gpu_handle_ctrl(&g->parent_obj, g->ctrl_vq);
}
static void virtio_gpu_handle_cursor(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOGPU *g = VIRTIO_GPU(vdev);
VirtQueueElement elem;
size_t s;
struct virtio_gpu_update_cursor cursor_info;
if (!virtio_queue_ready(vq)) {
return;
}
while (virtqueue_pop(vq, &elem)) {
s = iov_to_buf(elem.out_sg, elem.out_num, 0,
&cursor_info, sizeof(cursor_info));
if (s != sizeof(cursor_info)) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: cursor size incorrect %zu vs %zu\n",
__func__, s, sizeof(cursor_info));
} else {
update_cursor(g, &cursor_info);
}
virtqueue_push(vq, &elem, 0);
virtio_notify(vdev, vq);
}
}
static void virtio_gpu_cursor_bh(void *opaque)
{
VirtIOGPU *g = opaque;
virtio_gpu_handle_cursor(&g->parent_obj, g->cursor_vq);
}
static void virtio_gpu_invalidate_display(void *opaque)
{
}
static void virtio_gpu_update_display(void *opaque)
{
}
static void virtio_gpu_text_update(void *opaque, console_ch_t *chardata)
{
}
static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
{
VirtIOGPU *g = opaque;
if (idx > g->conf.max_outputs) {
return -1;
}
g->req_state[idx].x = info->xoff;
g->req_state[idx].y = info->yoff;
g->req_state[idx].width = info->width;
g->req_state[idx].height = info->height;
if (info->width && info->height) {
g->enabled_output_bitmask |= (1 << idx);
} else {
g->enabled_output_bitmask &= ~(1 << idx);
}
/* send event to guest */
virtio_gpu_notify_event(g, VIRTIO_GPU_EVENT_DISPLAY);
return 0;
}
const GraphicHwOps virtio_gpu_ops = {
.invalidate = virtio_gpu_invalidate_display,
.gfx_update = virtio_gpu_update_display,
.text_update = virtio_gpu_text_update,
.ui_info = virtio_gpu_ui_info,
};
static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
VirtIOGPU *g = VIRTIO_GPU(qdev);
int i;
g->config_size = sizeof(struct virtio_gpu_config);
g->virtio_config.num_scanouts = g->conf.max_outputs;
virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU,
g->config_size);
g->req_state[0].width = 1024;
g->req_state[0].height = 768;
g->ctrl_vq = virtio_add_queue(vdev, 64, virtio_gpu_handle_ctrl_cb);
g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb);
g->ctrl_bh = qemu_bh_new(virtio_gpu_ctrl_bh, g);
g->cursor_bh = qemu_bh_new(virtio_gpu_cursor_bh, g);
QTAILQ_INIT(&g->reslist);
QTAILQ_INIT(&g->fenceq);
g->enabled_output_bitmask = 1;
g->qdev = qdev;
for (i = 0; i < g->conf.max_outputs; i++) {
g->scanout[i].con =
graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g);
if (i > 0) {
dpy_gfx_replace_surface(g->scanout[i].con, NULL);
}
}
}
static void virtio_gpu_instance_init(Object *obj)
{
}
static void virtio_gpu_reset(VirtIODevice *vdev)
{
VirtIOGPU *g = VIRTIO_GPU(vdev);
struct virtio_gpu_simple_resource *res, *tmp;
int i;
g->enable = 0;
QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) {
virtio_gpu_resource_destroy(g, res);
}
for (i = 0; i < g->conf.max_outputs; i++) {
#if 0
g->req_state[i].x = 0;
g->req_state[i].y = 0;
if (i == 0) {
g->req_state[0].width = 1024;
g->req_state[0].height = 768;
} else {
g->req_state[i].width = 0;
g->req_state[i].height = 0;
}
#endif
g->scanout[i].resource_id = 0;
g->scanout[i].width = 0;
g->scanout[i].height = 0;
g->scanout[i].x = 0;
g->scanout[i].y = 0;
g->scanout[i].ds = NULL;
}
g->enabled_output_bitmask = 1;
}
static Property virtio_gpu_properties[] = {
DEFINE_VIRTIO_GPU_PROPERTIES(VirtIOGPU, conf),
DEFINE_PROP_END_OF_LIST(),
};
static void virtio_gpu_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
vdc->realize = virtio_gpu_device_realize;
vdc->get_config = virtio_gpu_get_config;
vdc->set_config = virtio_gpu_set_config;
vdc->get_features = virtio_gpu_get_features;
vdc->reset = virtio_gpu_reset;
dc->props = virtio_gpu_properties;
}
static const TypeInfo virtio_gpu_info = {
.name = TYPE_VIRTIO_GPU,
.parent = TYPE_VIRTIO_DEVICE,
.instance_size = sizeof(VirtIOGPU),
.instance_init = virtio_gpu_instance_init,
.class_init = virtio_gpu_class_init,
};
static void virtio_register_types(void)
{
type_register_static(&virtio_gpu_info);
}
type_init(virtio_register_types)
QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctrl_hdr) != 24);
QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_update_cursor) != 56);
QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_unref) != 32);
QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_2d) != 40);
QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_set_scanout) != 48);
QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_flush) != 48);
QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_to_host_2d) != 56);
QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_mem_entry) != 16);
QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_attach_backing) != 32);
QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_detach_backing) != 32);
QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_display_info) != 408);

View File

@@ -1124,7 +1124,7 @@ static void vmsvga_update_display(void *opaque)
* Is it more efficient to look at vram VGA-dirty bits or wait * Is it more efficient to look at vram VGA-dirty bits or wait
* for the driver to issue SVGA_CMD_UPDATE? * for the driver to issue SVGA_CMD_UPDATE?
*/ */
if (memory_region_is_logging(&s->vga.vram)) { if (memory_region_is_logging(&s->vga.vram, DIRTY_MEMORY_VGA)) {
vga_sync_dirty_bitmap(&s->vga); vga_sync_dirty_bitmap(&s->vga);
dirty = memory_region_get_dirty(&s->vga.vram, 0, dirty = memory_region_get_dirty(&s->vga.vram, 0,
surface_stride(surface) * surface_height(surface), surface_stride(surface) * surface_height(surface),

View File

@@ -173,7 +173,7 @@ static uint64_t pl061_read(void *opaque, hwaddr offset,
case 0x414: /* Raw interrupt status */ case 0x414: /* Raw interrupt status */
return s->istate; return s->istate;
case 0x418: /* Masked interrupt status */ case 0x418: /* Masked interrupt status */
return s->istate | s->im; return s->istate & s->im;
case 0x420: /* Alternate function select */ case 0x420: /* Alternate function select */
return s->afsel; return s->afsel;
case 0x500: /* 2mA drive */ case 0x500: /* 2mA drive */

View File

@@ -1,6 +1,6 @@
common-obj-y += core.o smbus.o smbus_eeprom.o common-obj-y += core.o smbus.o smbus_eeprom.o
common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o
common-obj-$(CONFIG_ACPI) += smbus_ich9.o common-obj-$(CONFIG_ACPI_X86) += smbus_ich9.o
common-obj-$(CONFIG_APM) += pm_smbus.o common-obj-$(CONFIG_APM) += pm_smbus.o
common-obj-$(CONFIG_BITBANG_I2C) += bitbang_i2c.o common-obj-$(CONFIG_BITBANG_I2C) += bitbang_i2c.o
common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o

View File

@@ -9,7 +9,7 @@ obj-y += kvmvapic.o
obj-y += acpi-build.o obj-y += acpi-build.o
hw/i386/acpi-build.o: hw/i386/acpi-build.c \ hw/i386/acpi-build.o: hw/i386/acpi-build.c \
hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \ hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \
hw/i386/ssdt-tpm.hex hw/i386/ssdt-tpm.hex hw/i386/ssdt-tpm2.hex
iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \ iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
; then echo "$(2)"; else echo "$(3)"; fi ;) ; then echo "$(2)"; else echo "$(3)"; fi ;)

View File

@@ -41,6 +41,7 @@
#include "hw/acpi/memory_hotplug.h" #include "hw/acpi/memory_hotplug.h"
#include "sysemu/tpm.h" #include "sysemu/tpm.h"
#include "hw/acpi/tpm.h" #include "hw/acpi/tpm.h"
#include "sysemu/tpm_backend.h"
/* Supported chipsets: */ /* Supported chipsets: */
#include "hw/acpi/piix4.h" #include "hw/acpi/piix4.h"
@@ -106,7 +107,7 @@ typedef struct AcpiPmInfo {
typedef struct AcpiMiscInfo { typedef struct AcpiMiscInfo {
bool has_hpet; bool has_hpet;
bool has_tpm; TPMVersion tpm_version;
const unsigned char *dsdt_code; const unsigned char *dsdt_code;
unsigned dsdt_size; unsigned dsdt_size;
uint16_t pvpanic_port; uint16_t pvpanic_port;
@@ -234,18 +235,37 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
static void acpi_get_misc_info(AcpiMiscInfo *info) static void acpi_get_misc_info(AcpiMiscInfo *info)
{ {
info->has_hpet = hpet_find(); info->has_hpet = hpet_find();
info->has_tpm = tpm_find(); info->tpm_version = tpm_get_version();
info->pvpanic_port = pvpanic_port(); info->pvpanic_port = pvpanic_port();
info->applesmc_io_base = applesmc_port(); info->applesmc_io_base = applesmc_port();
} }
/*
* Because of the PXB hosts we cannot simply query TYPE_PCI_HOST_BRIDGE.
* On i386 arch we only have two pci hosts, so we can look only for them.
*/
static Object *acpi_get_i386_pci_host(void)
{
PCIHostState *host;
host = OBJECT_CHECK(PCIHostState,
object_resolve_path("/machine/i440fx", NULL),
TYPE_PCI_HOST_BRIDGE);
if (!host) {
host = OBJECT_CHECK(PCIHostState,
object_resolve_path("/machine/q35", NULL),
TYPE_PCI_HOST_BRIDGE);
}
return OBJECT(host);
}
static void acpi_get_pci_info(PcPciInfo *info) static void acpi_get_pci_info(PcPciInfo *info)
{ {
Object *pci_host; Object *pci_host;
bool ambiguous;
pci_host = object_resolve_path_type("", TYPE_PCI_HOST_BRIDGE, &ambiguous);
g_assert(!ambiguous); pci_host = acpi_get_i386_pci_host();
g_assert(pci_host); g_assert(pci_host);
info->w32.begin = object_property_get_int(pci_host, info->w32.begin = object_property_get_int(pci_host,
@@ -414,6 +434,7 @@ build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu,
} }
#include "hw/i386/ssdt-tpm.hex" #include "hw/i386/ssdt-tpm.hex"
#include "hw/i386/ssdt-tpm2.hex"
/* Assign BSEL property to all buses. In the future, this can be changed /* Assign BSEL property to all buses. In the future, this can be changed
* to only assign to buses that support hotplug. * to only assign to buses that support hotplug.
@@ -594,6 +615,291 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
} }
} }
aml_append(parent_scope, method); aml_append(parent_scope, method);
qobject_decref(bsel);
}
/*
* initialize_route - Initialize the interrupt routing rule
* through a specific LINK:
* if (lnk_idx == idx)
* route using link 'link_name'
*/
static Aml *initialize_route(Aml *route, const char *link_name,
Aml *lnk_idx, int idx)
{
Aml *if_ctx = aml_if(aml_equal(lnk_idx, aml_int(idx)));
Aml *pkg = aml_package(4);
aml_append(pkg, aml_int(0));
aml_append(pkg, aml_int(0));
aml_append(pkg, aml_name("%s", link_name));
aml_append(pkg, aml_int(0));
aml_append(if_ctx, aml_store(pkg, route));
return if_ctx;
}
/*
* build_prt - Define interrupt rounting rules
*
* Returns an array of 128 routes, one for each device,
* based on device location.
* The main goal is to equaly distribute the interrupts
* over the 4 existing ACPI links (works only for i440fx).
* The hash function is (slot + pin) & 3 -> "LNK[D|A|B|C]".
*
*/
static Aml *build_prt(void)
{
Aml *method, *while_ctx, *pin, *res;
method = aml_method("_PRT", 0);
res = aml_local(0);
pin = aml_local(1);
aml_append(method, aml_store(aml_package(128), res));
aml_append(method, aml_store(aml_int(0), pin));
/* while (pin < 128) */
while_ctx = aml_while(aml_lless(pin, aml_int(128)));
{
Aml *slot = aml_local(2);
Aml *lnk_idx = aml_local(3);
Aml *route = aml_local(4);
/* slot = pin >> 2 */
aml_append(while_ctx,
aml_store(aml_shiftright(pin, aml_int(2)), slot));
/* lnk_idx = (slot + pin) & 3 */
aml_append(while_ctx,
aml_store(aml_and(aml_add(pin, slot), aml_int(3)), lnk_idx));
/* route[2] = "LNK[D|A|B|C]", selection based on pin % 3 */
aml_append(while_ctx, initialize_route(route, "LNKD", lnk_idx, 0));
aml_append(while_ctx, initialize_route(route, "LNKA", lnk_idx, 1));
aml_append(while_ctx, initialize_route(route, "LNKB", lnk_idx, 2));
aml_append(while_ctx, initialize_route(route, "LNKC", lnk_idx, 3));
/* route[0] = 0x[slot]FFFF */
aml_append(while_ctx,
aml_store(aml_or(aml_shiftleft(slot, aml_int(16)), aml_int(0xFFFF)),
aml_index(route, aml_int(0))));
/* route[1] = pin & 3 */
aml_append(while_ctx,
aml_store(aml_and(pin, aml_int(3)), aml_index(route, aml_int(1))));
/* res[pin] = route */
aml_append(while_ctx, aml_store(route, aml_index(res, pin)));
/* pin++ */
aml_append(while_ctx, aml_increment(pin));
}
aml_append(method, while_ctx);
/* return res*/
aml_append(method, aml_return(res));
return method;
}
typedef struct CrsRangeEntry {
uint64_t base;
uint64_t limit;
} CrsRangeEntry;
static void crs_range_insert(GPtrArray *ranges, uint64_t base, uint64_t limit)
{
CrsRangeEntry *entry;
entry = g_malloc(sizeof(*entry));
entry->base = base;
entry->limit = limit;
g_ptr_array_add(ranges, entry);
}
static void crs_range_free(gpointer data)
{
CrsRangeEntry *entry = (CrsRangeEntry *)data;
g_free(entry);
}
static gint crs_range_compare(gconstpointer a, gconstpointer b)
{
CrsRangeEntry *entry_a = *(CrsRangeEntry **)a;
CrsRangeEntry *entry_b = *(CrsRangeEntry **)b;
return (int64_t)entry_a->base - (int64_t)entry_b->base;
}
/*
* crs_replace_with_free_ranges - given the 'used' ranges within [start - end]
* interval, computes the 'free' ranges from the same interval.
* Example: If the input array is { [a1 - a2],[b1 - b2] }, the function
* will return { [base - a1], [a2 - b1], [b2 - limit] }.
*/
static void crs_replace_with_free_ranges(GPtrArray *ranges,
uint64_t start, uint64_t end)
{
GPtrArray *free_ranges = g_ptr_array_new_with_free_func(crs_range_free);
uint64_t free_base = start;
int i;
g_ptr_array_sort(ranges, crs_range_compare);
for (i = 0; i < ranges->len; i++) {
CrsRangeEntry *used = g_ptr_array_index(ranges, i);
if (free_base < used->base) {
crs_range_insert(free_ranges, free_base, used->base - 1);
}
free_base = used->limit + 1;
}
if (free_base < end) {
crs_range_insert(free_ranges, free_base, end);
}
g_ptr_array_set_size(ranges, 0);
for (i = 0; i < free_ranges->len; i++) {
g_ptr_array_add(ranges, g_ptr_array_index(free_ranges, i));
}
g_ptr_array_free(free_ranges, false);
}
static Aml *build_crs(PCIHostState *host,
GPtrArray *io_ranges, GPtrArray *mem_ranges)
{
Aml *crs = aml_resource_template();
uint8_t max_bus = pci_bus_num(host->bus);
uint8_t type;
int devfn;
for (devfn = 0; devfn < ARRAY_SIZE(host->bus->devices); devfn++) {
int i;
uint64_t range_base, range_limit;
PCIDevice *dev = host->bus->devices[devfn];
if (!dev) {
continue;
}
for (i = 0; i < PCI_NUM_REGIONS; i++) {
PCIIORegion *r = &dev->io_regions[i];
range_base = r->addr;
range_limit = r->addr + r->size - 1;
/*
* Work-around for old bioses
* that do not support multiple root buses
*/
if (!range_base || range_base > range_limit) {
continue;
}
if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
aml_append(crs,
aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
AML_POS_DECODE, AML_ENTIRE_RANGE,
0,
range_base,
range_limit,
0,
range_limit - range_base + 1));
crs_range_insert(io_ranges, range_base, range_limit);
} else { /* "memory" */
aml_append(crs,
aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
AML_MAX_FIXED, AML_NON_CACHEABLE,
AML_READ_WRITE,
0,
range_base,
range_limit,
0,
range_limit - range_base + 1));
crs_range_insert(mem_ranges, range_base, range_limit);
}
}
type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
if (type == PCI_HEADER_TYPE_BRIDGE) {
uint8_t subordinate = dev->config[PCI_SUBORDINATE_BUS];
if (subordinate > max_bus) {
max_bus = subordinate;
}
range_base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO);
range_limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO);
/*
* Work-around for old bioses
* that do not support multiple root buses
*/
if (range_base || range_base > range_limit) {
aml_append(crs,
aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
AML_POS_DECODE, AML_ENTIRE_RANGE,
0,
range_base,
range_limit,
0,
range_limit - range_base + 1));
crs_range_insert(io_ranges, range_base, range_limit);
}
range_base =
pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
range_limit =
pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
/*
* Work-around for old bioses
* that do not support multiple root buses
*/
if (range_base || range_base > range_limit) {
aml_append(crs,
aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
AML_MAX_FIXED, AML_NON_CACHEABLE,
AML_READ_WRITE,
0,
range_base,
range_limit,
0,
range_limit - range_base + 1));
crs_range_insert(mem_ranges, range_base, range_limit);
}
range_base =
pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
range_limit =
pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
/*
* Work-around for old bioses
* that do not support multiple root buses
*/
if (range_base || range_base > range_limit) {
aml_append(crs,
aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
AML_MAX_FIXED, AML_NON_CACHEABLE,
AML_READ_WRITE,
0,
range_base,
range_limit,
0,
range_limit - range_base + 1));
crs_range_insert(mem_ranges, range_base, range_limit);
}
}
}
aml_append(crs,
aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
0,
pci_bus_num(host->bus),
max_bus,
0,
max_bus - pci_bus_num(host->bus) + 1));
return crs;
} }
static void static void
@@ -605,6 +911,11 @@ build_ssdt(GArray *table_data, GArray *linker,
uint32_t nr_mem = machine->ram_slots; uint32_t nr_mem = machine->ram_slots;
unsigned acpi_cpus = guest_info->apic_id_limit; unsigned acpi_cpus = guest_info->apic_id_limit;
Aml *ssdt, *sb_scope, *scope, *pkg, *dev, *method, *crs, *field, *ifctx; Aml *ssdt, *sb_scope, *scope, *pkg, *dev, *method, *crs, *field, *ifctx;
PCIBus *bus = NULL;
GPtrArray *io_ranges = g_ptr_array_new_with_free_func(crs_range_free);
GPtrArray *mem_ranges = g_ptr_array_new_with_free_func(crs_range_free);
CrsRangeEntry *entry;
int root_bus_limit = 0xFF;
int i; int i;
ssdt = init_aml_allocator(); ssdt = init_aml_allocator();
@@ -616,35 +927,85 @@ build_ssdt(GArray *table_data, GArray *linker,
/* Reserve space for header */ /* Reserve space for header */
acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader)); acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
/* Extra PCI root buses are implemented only for i440fx */
bus = find_i440fx();
if (bus) {
QLIST_FOREACH(bus, &bus->child, sibling) {
uint8_t bus_num = pci_bus_num(bus);
uint8_t numa_node = pci_bus_numa_node(bus);
/* look only for expander root buses */
if (!pci_bus_is_root(bus)) {
continue;
}
if (bus_num < root_bus_limit) {
root_bus_limit = bus_num - 1;
}
scope = aml_scope("\\_SB");
dev = aml_device("PC%.02X", bus_num);
aml_append(dev,
aml_name_decl("_UID", aml_string("PC%.02X", bus_num)));
aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A03")));
aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
if (numa_node != NUMA_NODE_UNASSIGNED) {
aml_append(dev, aml_name_decl("_PXM", aml_int(numa_node)));
}
aml_append(dev, build_prt());
crs = build_crs(PCI_HOST_BRIDGE(BUS(bus)->parent),
io_ranges, mem_ranges);
aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(scope, dev);
aml_append(ssdt, scope);
}
}
scope = aml_scope("\\_SB.PCI0"); scope = aml_scope("\\_SB.PCI0");
/* build PCI0._CRS */ /* build PCI0._CRS */
crs = aml_resource_template(); crs = aml_resource_template();
aml_append(crs, aml_append(crs,
aml_word_bus_number(aml_min_fixed, aml_max_fixed, aml_pos_decode, aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
0x0000, 0x0000, 0x00FF, 0x0000, 0x0100)); 0x0000, 0x0, root_bus_limit,
aml_append(crs, aml_io(aml_decode16, 0x0CF8, 0x0CF8, 0x01, 0x08)); 0x0000, root_bus_limit + 1));
aml_append(crs, aml_io(AML_DECODE16, 0x0CF8, 0x0CF8, 0x01, 0x08));
aml_append(crs, aml_append(crs,
aml_word_io(aml_min_fixed, aml_max_fixed, aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
aml_pos_decode, aml_entire_range, AML_POS_DECODE, AML_ENTIRE_RANGE,
0x0000, 0x0000, 0x0CF7, 0x0000, 0x0CF8)); 0x0000, 0x0000, 0x0CF7, 0x0000, 0x0CF8));
crs_replace_with_free_ranges(io_ranges, 0x0D00, 0xFFFF);
for (i = 0; i < io_ranges->len; i++) {
entry = g_ptr_array_index(io_ranges, i);
aml_append(crs,
aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
AML_POS_DECODE, AML_ENTIRE_RANGE,
0x0000, entry->base, entry->limit,
0x0000, entry->limit - entry->base + 1));
}
aml_append(crs, aml_append(crs,
aml_word_io(aml_min_fixed, aml_max_fixed, aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
aml_pos_decode, aml_entire_range, AML_CACHEABLE, AML_READ_WRITE,
0x0000, 0x0D00, 0xFFFF, 0x0000, 0xF300));
aml_append(crs,
aml_dword_memory(aml_pos_decode, aml_min_fixed, aml_max_fixed,
aml_cacheable, aml_ReadWrite,
0, 0x000A0000, 0x000BFFFF, 0, 0x00020000)); 0, 0x000A0000, 0x000BFFFF, 0, 0x00020000));
aml_append(crs,
aml_dword_memory(aml_pos_decode, aml_min_fixed, aml_max_fixed, crs_replace_with_free_ranges(mem_ranges, pci->w32.begin, pci->w32.end - 1);
aml_non_cacheable, aml_ReadWrite, for (i = 0; i < mem_ranges->len; i++) {
0, pci->w32.begin, pci->w32.end - 1, 0, entry = g_ptr_array_index(mem_ranges, i);
pci->w32.end - pci->w32.begin)); aml_append(crs,
aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
AML_NON_CACHEABLE, AML_READ_WRITE,
0, entry->base, entry->limit,
0, entry->limit - entry->base + 1));
}
if (pci->w64.begin) { if (pci->w64.begin) {
aml_append(crs, aml_append(crs,
aml_qword_memory(aml_pos_decode, aml_min_fixed, aml_max_fixed, aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
aml_cacheable, aml_ReadWrite, AML_CACHEABLE, AML_READ_WRITE,
0, pci->w64.begin, pci->w64.end - 1, 0, 0, pci->w64.begin, pci->w64.end - 1, 0,
pci->w64.end - pci->w64.begin)); pci->w64.end - pci->w64.begin));
} }
@@ -658,11 +1019,14 @@ build_ssdt(GArray *table_data, GArray *linker,
aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
crs = aml_resource_template(); crs = aml_resource_template();
aml_append(crs, aml_append(crs,
aml_io(aml_decode16, pm->gpe0_blk, pm->gpe0_blk, 1, pm->gpe0_blk_len) aml_io(AML_DECODE16, pm->gpe0_blk, pm->gpe0_blk, 1, pm->gpe0_blk_len)
); );
aml_append(dev, aml_name_decl("_CRS", crs)); aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(scope, dev); aml_append(scope, dev);
g_ptr_array_free(io_ranges, true);
g_ptr_array_free(mem_ranges, true);
/* reserve PCIHP resources */ /* reserve PCIHP resources */
if (pm->pcihp_io_len) { if (pm->pcihp_io_len) {
dev = aml_device("PHPR"); dev = aml_device("PHPR");
@@ -673,7 +1037,7 @@ build_ssdt(GArray *table_data, GArray *linker,
aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
crs = aml_resource_template(); crs = aml_resource_template();
aml_append(crs, aml_append(crs,
aml_io(aml_decode16, pm->pcihp_io_base, pm->pcihp_io_base, 1, aml_io(AML_DECODE16, pm->pcihp_io_base, pm->pcihp_io_base, 1,
pm->pcihp_io_len) pm->pcihp_io_len)
); );
aml_append(dev, aml_name_decl("_CRS", crs)); aml_append(dev, aml_name_decl("_CRS", crs));
@@ -720,7 +1084,7 @@ build_ssdt(GArray *table_data, GArray *linker,
crs = aml_resource_template(); crs = aml_resource_template();
aml_append(crs, aml_append(crs,
aml_io(aml_decode16, misc->applesmc_io_base, misc->applesmc_io_base, aml_io(AML_DECODE16, misc->applesmc_io_base, misc->applesmc_io_base,
0x01, APPLESMC_MAX_DATA_LENGTH) 0x01, APPLESMC_MAX_DATA_LENGTH)
); );
aml_append(crs, aml_irq_no_flags(6)); aml_append(crs, aml_irq_no_flags(6));
@@ -733,21 +1097,24 @@ build_ssdt(GArray *table_data, GArray *linker,
if (misc->pvpanic_port) { if (misc->pvpanic_port) {
scope = aml_scope("\\_SB.PCI0.ISA"); scope = aml_scope("\\_SB.PCI0.ISA");
dev = aml_device("PEVR"); dev = aml_device("PEVT");
aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0001"))); aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0001")));
crs = aml_resource_template(); crs = aml_resource_template();
aml_append(crs, aml_append(crs,
aml_io(aml_decode16, misc->pvpanic_port, misc->pvpanic_port, 1, 1) aml_io(AML_DECODE16, misc->pvpanic_port, misc->pvpanic_port, 1, 1)
); );
aml_append(dev, aml_name_decl("_CRS", crs)); aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(dev, aml_operation_region("PEOR", aml_system_io, aml_append(dev, aml_operation_region("PEOR", AML_SYSTEM_IO,
misc->pvpanic_port, 1)); misc->pvpanic_port, 1));
field = aml_field("PEOR", aml_byte_acc, aml_preserve); field = aml_field("PEOR", AML_BYTE_ACC, AML_PRESERVE);
aml_append(field, aml_named_field("PEPT", 8)); aml_append(field, aml_named_field("PEPT", 8));
aml_append(dev, field); aml_append(dev, field);
/* device present, functioning, decoding, not shown in UI */
aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
method = aml_method("RDPT", 0); method = aml_method("RDPT", 0);
aml_append(method, aml_store(aml_name("PEPT"), aml_local(0))); aml_append(method, aml_store(aml_name("PEPT"), aml_local(0)));
aml_append(method, aml_return(aml_local(0))); aml_append(method, aml_return(aml_local(0)));
@@ -773,15 +1140,15 @@ build_ssdt(GArray *table_data, GArray *linker,
aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
crs = aml_resource_template(); crs = aml_resource_template();
aml_append(crs, aml_append(crs,
aml_io(aml_decode16, pm->cpu_hp_io_base, pm->cpu_hp_io_base, 1, aml_io(AML_DECODE16, pm->cpu_hp_io_base, pm->cpu_hp_io_base, 1,
pm->cpu_hp_io_len) pm->cpu_hp_io_len)
); );
aml_append(dev, aml_name_decl("_CRS", crs)); aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(sb_scope, dev); aml_append(sb_scope, dev);
/* declare CPU hotplug MMIO region and PRS field to access it */ /* declare CPU hotplug MMIO region and PRS field to access it */
aml_append(sb_scope, aml_operation_region( aml_append(sb_scope, aml_operation_region(
"PRST", aml_system_io, pm->cpu_hp_io_base, pm->cpu_hp_io_len)); "PRST", AML_SYSTEM_IO, pm->cpu_hp_io_base, pm->cpu_hp_io_len));
field = aml_field("PRST", aml_byte_acc, aml_preserve); field = aml_field("PRST", AML_BYTE_ACC, AML_PRESERVE);
aml_append(field, aml_named_field("PRS", 256)); aml_append(field, aml_named_field("PRS", 256));
aml_append(sb_scope, field); aml_append(sb_scope, field);
@@ -845,18 +1212,18 @@ build_ssdt(GArray *table_data, GArray *linker,
crs = aml_resource_template(); crs = aml_resource_template();
aml_append(crs, aml_append(crs,
aml_io(aml_decode16, pm->mem_hp_io_base, pm->mem_hp_io_base, 0, aml_io(AML_DECODE16, pm->mem_hp_io_base, pm->mem_hp_io_base, 0,
pm->mem_hp_io_len) pm->mem_hp_io_len)
); );
aml_append(scope, aml_name_decl("_CRS", crs)); aml_append(scope, aml_name_decl("_CRS", crs));
aml_append(scope, aml_operation_region( aml_append(scope, aml_operation_region(
stringify(MEMORY_HOTPLUG_IO_REGION), aml_system_io, stringify(MEMORY_HOTPLUG_IO_REGION), AML_SYSTEM_IO,
pm->mem_hp_io_base, pm->mem_hp_io_len) pm->mem_hp_io_base, pm->mem_hp_io_len)
); );
field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_dword_acc, field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), AML_DWORD_ACC,
aml_preserve); AML_PRESERVE);
aml_append(field, /* read only */ aml_append(field, /* read only */
aml_named_field(stringify(MEMORY_SLOT_ADDR_LOW), 32)); aml_named_field(stringify(MEMORY_SLOT_ADDR_LOW), 32));
aml_append(field, /* read only */ aml_append(field, /* read only */
@@ -869,8 +1236,8 @@ build_ssdt(GArray *table_data, GArray *linker,
aml_named_field(stringify(MEMORY_SLOT_PROXIMITY), 32)); aml_named_field(stringify(MEMORY_SLOT_PROXIMITY), 32));
aml_append(scope, field); aml_append(scope, field);
field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_byte_acc, field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), AML_BYTE_ACC,
aml_write_as_zeros); AML_WRITE_AS_ZEROS);
aml_append(field, aml_reserved_field(160 /* bits, Offset(20) */)); aml_append(field, aml_reserved_field(160 /* bits, Offset(20) */));
aml_append(field, /* 1 if enabled, read only */ aml_append(field, /* 1 if enabled, read only */
aml_named_field(stringify(MEMORY_SLOT_ENABLED), 1)); aml_named_field(stringify(MEMORY_SLOT_ENABLED), 1));
@@ -885,8 +1252,8 @@ build_ssdt(GArray *table_data, GArray *linker,
aml_named_field(stringify(MEMORY_SLOT_EJECT), 1)); aml_named_field(stringify(MEMORY_SLOT_EJECT), 1));
aml_append(scope, field); aml_append(scope, field);
field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_dword_acc, field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), AML_DWORD_ACC,
aml_preserve); AML_PRESERVE);
aml_append(field, /* DIMM selector, write only */ aml_append(field, /* DIMM selector, write only */
aml_named_field(stringify(MEMORY_SLOT_SLECTOR), 32)); aml_named_field(stringify(MEMORY_SLOT_SLECTOR), 32));
aml_append(field, /* _OST event code, write only */ aml_append(field, /* _OST event code, write only */
@@ -952,10 +1319,9 @@ build_ssdt(GArray *table_data, GArray *linker,
{ {
Object *pci_host; Object *pci_host;
PCIBus *bus = NULL; PCIBus *bus = NULL;
bool ambiguous;
pci_host = object_resolve_path_type("", TYPE_PCI_HOST_BRIDGE, &ambiguous); pci_host = acpi_get_i386_pci_host();
if (!ambiguous && pci_host) { if (pci_host) {
bus = PCI_HOST_BRIDGE(pci_host)->bus; bus = PCI_HOST_BRIDGE(pci_host)->bus;
} }
@@ -1026,6 +1392,25 @@ build_tpm_ssdt(GArray *table_data, GArray *linker)
memcpy(tpm_ptr, ssdt_tpm_aml, sizeof(ssdt_tpm_aml)); memcpy(tpm_ptr, ssdt_tpm_aml, sizeof(ssdt_tpm_aml));
} }
static void
build_tpm2(GArray *table_data, GArray *linker)
{
Acpi20TPM2 *tpm2_ptr;
void *tpm_ptr;
tpm_ptr = acpi_data_push(table_data, sizeof(ssdt_tpm2_aml));
memcpy(tpm_ptr, ssdt_tpm2_aml, sizeof(ssdt_tpm2_aml));
tpm2_ptr = acpi_data_push(table_data, sizeof *tpm2_ptr);
tpm2_ptr->platform_class = cpu_to_le16(TPM2_ACPI_CLASS_CLIENT);
tpm2_ptr->control_area_address = cpu_to_le64(0);
tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO);
build_header(linker, table_data,
(void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4);
}
typedef enum { typedef enum {
MEM_AFFINITY_NOFLAGS = 0, MEM_AFFINITY_NOFLAGS = 0,
MEM_AFFINITY_ENABLED = (1 << 0), MEM_AFFINITY_ENABLED = (1 << 0),
@@ -1208,30 +1593,6 @@ build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
misc->dsdt_size, 1); misc->dsdt_size, 1);
} }
/* Build final rsdt table */
static void
build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
{
AcpiRsdtDescriptorRev1 *rsdt;
size_t rsdt_len;
int i;
rsdt_len = sizeof(*rsdt) + sizeof(uint32_t) * table_offsets->len;
rsdt = acpi_data_push(table_data, rsdt_len);
memcpy(rsdt->table_offset_entry, table_offsets->data,
sizeof(uint32_t) * table_offsets->len);
for (i = 0; i < table_offsets->len; ++i) {
/* rsdt->table_offset_entry to be filled by Guest linker */
bios_linker_loader_add_pointer(linker,
ACPI_BUILD_TABLE_FILE,
ACPI_BUILD_TABLE_FILE,
table_data, &rsdt->table_offset_entry[i],
sizeof(uint32_t));
}
build_header(linker, table_data,
(void *)rsdt, "RSDT", rsdt_len, 1);
}
static GArray * static GArray *
build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt) build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
{ {
@@ -1272,10 +1633,8 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
{ {
Object *pci_host; Object *pci_host;
QObject *o; QObject *o;
bool ambiguous;
pci_host = object_resolve_path_type("", TYPE_PCI_HOST_BRIDGE, &ambiguous); pci_host = acpi_get_i386_pci_host();
g_assert(!ambiguous);
g_assert(pci_host); g_assert(pci_host);
o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL); o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
@@ -1364,12 +1723,21 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
acpi_add_table(table_offsets, tables_blob); acpi_add_table(table_offsets, tables_blob);
build_hpet(tables_blob, tables->linker); build_hpet(tables_blob, tables->linker);
} }
if (misc.has_tpm) { if (misc.tpm_version != TPM_VERSION_UNSPEC) {
acpi_add_table(table_offsets, tables_blob); acpi_add_table(table_offsets, tables_blob);
build_tpm_tcpa(tables_blob, tables->linker, tables->tcpalog); build_tpm_tcpa(tables_blob, tables->linker, tables->tcpalog);
acpi_add_table(table_offsets, tables_blob); acpi_add_table(table_offsets, tables_blob);
build_tpm_ssdt(tables_blob, tables->linker); switch (misc.tpm_version) {
case TPM_VERSION_1_2:
build_tpm_ssdt(tables_blob, tables->linker);
break;
case TPM_VERSION_2_0:
build_tpm2(tables_blob, tables->linker);
break;
default:
assert(false);
}
} }
if (guest_info->numa_nodes) { if (guest_info->numa_nodes) {
acpi_add_table(table_offsets, tables_blob); acpi_add_table(table_offsets, tables_blob);

View File

@@ -30,6 +30,7 @@
#include "hw/block/fdc.h" #include "hw/block/fdc.h"
#include "hw/ide.h" #include "hw/ide.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "hw/pci/pci_bus.h"
#include "monitor/monitor.h" #include "monitor/monitor.h"
#include "hw/nvram/fw_cfg.h" #include "hw/nvram/fw_cfg.h"
#include "hw/timer/hpet.h" #include "hw/timer/hpet.h"
@@ -163,27 +164,6 @@ uint64_t cpu_get_tsc(CPUX86State *env)
return cpu_get_ticks(); return cpu_get_ticks();
} }
/* SMM support */
static cpu_set_smm_t smm_set;
static void *smm_arg;
void cpu_smm_register(cpu_set_smm_t callback, void *arg)
{
assert(smm_set == NULL);
assert(smm_arg == NULL);
smm_set = callback;
smm_arg = arg;
}
void cpu_smm_update(CPUX86State *env)
{
if (smm_set && smm_arg && CPU(x86_env_get_cpu(env)) == first_cpu) {
smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
}
}
/* IRQ handling */ /* IRQ handling */
int cpu_get_pic_interrupt(CPUX86State *env) int cpu_get_pic_interrupt(CPUX86State *env)
{ {
@@ -1006,7 +986,6 @@ static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id,
} }
qdev_set_parent_bus(DEVICE(cpu), qdev_get_child_bus(icc_bridge, "icc")); qdev_set_parent_bus(DEVICE(cpu), qdev_get_child_bus(icc_bridge, "icc"));
object_unref(OBJECT(cpu));
object_property_set_int(OBJECT(cpu), apic_id, "apic-id", &local_err); object_property_set_int(OBJECT(cpu), apic_id, "apic-id", &local_err);
object_property_set_bool(OBJECT(cpu), true, "realized", &local_err); object_property_set_bool(OBJECT(cpu), true, "realized", &local_err);
@@ -1025,7 +1004,9 @@ static const char *current_cpu_model;
void pc_hot_add_cpu(const int64_t id, Error **errp) void pc_hot_add_cpu(const int64_t id, Error **errp)
{ {
DeviceState *icc_bridge; DeviceState *icc_bridge;
X86CPU *cpu;
int64_t apic_id = x86_cpu_apic_id_from_index(id); int64_t apic_id = x86_cpu_apic_id_from_index(id);
Error *local_err = NULL;
if (id < 0) { if (id < 0) {
error_setg(errp, "Invalid CPU id: %" PRIi64, id); error_setg(errp, "Invalid CPU id: %" PRIi64, id);
@@ -1053,7 +1034,12 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
icc_bridge = DEVICE(object_resolve_path_type("icc-bridge", icc_bridge = DEVICE(object_resolve_path_type("icc-bridge",
TYPE_ICC_BRIDGE, NULL)); TYPE_ICC_BRIDGE, NULL));
pc_new_cpu(current_cpu_model, apic_id, icc_bridge, errp); cpu = pc_new_cpu(current_cpu_model, apic_id, icc_bridge, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
object_unref(OBJECT(cpu));
} }
void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
@@ -1087,6 +1073,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
error_report_err(error); error_report_err(error);
exit(1); exit(1);
} }
object_unref(OBJECT(cpu));
} }
/* map APIC MMIO area if CPU has APIC */ /* map APIC MMIO area if CPU has APIC */
@@ -1119,6 +1106,25 @@ void pc_guest_info_machine_done(Notifier *notifier, void *data)
PcGuestInfoState *guest_info_state = container_of(notifier, PcGuestInfoState *guest_info_state = container_of(notifier,
PcGuestInfoState, PcGuestInfoState,
machine_done); machine_done);
PCIBus *bus = find_i440fx();
if (bus) {
int extra_hosts = 0;
QLIST_FOREACH(bus, &bus->child, sibling) {
/* look for expander root buses */
if (pci_bus_is_root(bus)) {
extra_hosts++;
}
}
if (extra_hosts && guest_info_state->info.fw_cfg) {
uint64_t *val = g_malloc(sizeof(*val));
*val = cpu_to_le64(extra_hosts);
fw_cfg_add_file(guest_info_state->info.fw_cfg,
"etc/extra-pci-roots", val, sizeof(*val));
}
}
acpi_setup(&guest_info_state->info); acpi_setup(&guest_info_state->info);
} }
@@ -1345,9 +1351,9 @@ FWCfgState *pc_memory_init(MachineState *machine,
return fw_cfg; return fw_cfg;
} }
qemu_irq *pc_allocate_cpu_irq(void) qemu_irq pc_allocate_cpu_irq(void)
{ {
return qemu_allocate_irqs(pic_irq_request, NULL, 1); return qemu_allocate_irq(pic_irq_request, NULL, 0);
} }
DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus) DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
@@ -1395,6 +1401,7 @@ static const MemoryRegionOps ioportF0_io_ops = {
void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
ISADevice **rtc_state, ISADevice **rtc_state,
bool create_fdctrl,
ISADevice **floppy, ISADevice **floppy,
bool no_vmport, bool no_vmport,
uint32 hpet_irqs) uint32 hpet_irqs)
@@ -1489,8 +1496,9 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
for(i = 0; i < MAX_FD; i++) { for(i = 0; i < MAX_FD; i++) {
fd[i] = drive_get(IF_FLOPPY, 0, i); fd[i] = drive_get(IF_FLOPPY, 0, i);
create_fdctrl |= !!fd[i];
} }
*floppy = fdctrl_init_isa(isa_bus, fd); *floppy = create_fdctrl ? fdctrl_init_isa(isa_bus, fd) : NULL;
} }
void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus) void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus)
@@ -1543,51 +1551,6 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
} }
} }
static void pc_generic_machine_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
QEMUMachine *qm = data;
mc->family = qm->family;
mc->name = qm->name;
mc->alias = qm->alias;
mc->desc = qm->desc;
mc->init = qm->init;
mc->reset = qm->reset;
mc->hot_add_cpu = qm->hot_add_cpu;
mc->kvm_type = qm->kvm_type;
mc->block_default_type = qm->block_default_type;
mc->units_per_default_bus = qm->units_per_default_bus;
mc->max_cpus = qm->max_cpus;
mc->no_serial = qm->no_serial;
mc->no_parallel = qm->no_parallel;
mc->use_virtcon = qm->use_virtcon;
mc->use_sclp = qm->use_sclp;
mc->no_floppy = qm->no_floppy;
mc->no_cdrom = qm->no_cdrom;
mc->no_sdcard = qm->no_sdcard;
mc->is_default = qm->is_default;
mc->default_machine_opts = qm->default_machine_opts;
mc->default_boot_order = qm->default_boot_order;
mc->default_display = qm->default_display;
mc->compat_props = qm->compat_props;
mc->hw_version = qm->hw_version;
}
void qemu_register_pc_machine(QEMUMachine *m)
{
char *name = g_strconcat(m->name, TYPE_MACHINE_SUFFIX, NULL);
TypeInfo ti = {
.name = name,
.parent = TYPE_PC_MACHINE,
.class_init = pc_generic_machine_class_init,
.class_data = (void *)m,
};
type_register(&ti);
g_free(name);
}
static void pc_dimm_plug(HotplugHandler *hotplug_dev, static void pc_dimm_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp) DeviceState *dev, Error **errp)
{ {

View File

@@ -59,6 +59,7 @@ static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 }; static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
static const int ide_irq[MAX_IDE_BUS] = { 14, 15 }; static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
static bool pci_enabled = true;
static bool has_acpi_build = true; static bool has_acpi_build = true;
static bool rsdp_in_ram = true; static bool rsdp_in_ram = true;
static int legacy_acpi_table_size; static int legacy_acpi_table_size;
@@ -71,11 +72,10 @@ static bool smbios_uuid_encoded = true;
*/ */
static bool gigabyte_align = true; static bool gigabyte_align = true;
static bool has_reserved_memory = true; static bool has_reserved_memory = true;
static bool kvmclock_enabled = true;
/* PC hardware initialisation */ /* PC hardware initialisation */
static void pc_init1(MachineState *machine, static void pc_init1(MachineState *machine)
int pci_enabled,
int kvmclock_enabled)
{ {
PCMachineState *pc_machine = PC_MACHINE(machine); PCMachineState *pc_machine = PC_MACHINE(machine);
MemoryRegion *system_memory = get_system_memory(); MemoryRegion *system_memory = get_system_memory();
@@ -86,10 +86,9 @@ static void pc_init1(MachineState *machine,
ISABus *isa_bus; ISABus *isa_bus;
PCII440FXState *i440fx_state; PCII440FXState *i440fx_state;
int piix3_devfn = -1; int piix3_devfn = -1;
qemu_irq *cpu_irq;
qemu_irq *gsi; qemu_irq *gsi;
qemu_irq *i8259; qemu_irq *i8259;
qemu_irq *smi_irq; qemu_irq smi_irq;
GSIState *gsi_state; GSIState *gsi_state;
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
BusState *idebus[MAX_IDE_BUS]; BusState *idebus[MAX_IDE_BUS];
@@ -99,7 +98,6 @@ static void pc_init1(MachineState *machine,
MemoryRegion *pci_memory; MemoryRegion *pci_memory;
MemoryRegion *rom_memory; MemoryRegion *rom_memory;
DeviceState *icc_bridge; DeviceState *icc_bridge;
FWCfgState *fw_cfg = NULL;
PcGuestInfo *guest_info; PcGuestInfo *guest_info;
ram_addr_t lowmem; ram_addr_t lowmem;
@@ -180,16 +178,16 @@ static void pc_init1(MachineState *machine,
/* allocate ram and load rom/bios */ /* allocate ram and load rom/bios */
if (!xen_enabled()) { if (!xen_enabled()) {
fw_cfg = pc_memory_init(machine, system_memory, pc_memory_init(machine, system_memory,
below_4g_mem_size, above_4g_mem_size, below_4g_mem_size, above_4g_mem_size,
rom_memory, &ram_memory, guest_info); rom_memory, &ram_memory, guest_info);
} else if (machine->kernel_filename != NULL) { } else if (machine->kernel_filename != NULL) {
/* For xen HVM direct kernel boot, load linux here */ /* For xen HVM direct kernel boot, load linux here */
fw_cfg = xen_load_linux(machine->kernel_filename, xen_load_linux(machine->kernel_filename,
machine->kernel_cmdline, machine->kernel_cmdline,
machine->initrd_filename, machine->initrd_filename,
below_4g_mem_size, below_4g_mem_size,
guest_info); guest_info);
} }
gsi_state = g_malloc0(sizeof(*gsi_state)); gsi_state = g_malloc0(sizeof(*gsi_state));
@@ -220,13 +218,13 @@ static void pc_init1(MachineState *machine,
} else if (xen_enabled()) { } else if (xen_enabled()) {
i8259 = xen_interrupt_controller_init(); i8259 = xen_interrupt_controller_init();
} else { } else {
cpu_irq = pc_allocate_cpu_irq(); i8259 = i8259_init(isa_bus, pc_allocate_cpu_irq());
i8259 = i8259_init(isa_bus, cpu_irq[0]);
} }
for (i = 0; i < ISA_NUM_IRQS; i++) { for (i = 0; i < ISA_NUM_IRQS; i++) {
gsi_state->i8259_irq[i] = i8259[i]; gsi_state->i8259_irq[i] = i8259[i];
} }
g_free(i8259);
if (pci_enabled) { if (pci_enabled) {
ioapic_init_gsi(gsi_state, "i440fx"); ioapic_init_gsi(gsi_state, "i440fx");
} }
@@ -242,7 +240,7 @@ static void pc_init1(MachineState *machine,
} }
/* init basic PC hardware */ /* init basic PC hardware */
pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, pc_basic_device_init(isa_bus, gsi, &rtc_state, true, &floppy,
(pc_machine->vmport != ON_OFF_AUTO_ON), 0x4); (pc_machine->vmport != ON_OFF_AUTO_ON), 0x4);
pc_nic_init(isa_bus, pci_bus); pc_nic_init(isa_bus, pci_bus);
@@ -284,11 +282,11 @@ static void pc_init1(MachineState *machine,
DeviceState *piix4_pm; DeviceState *piix4_pm;
I2CBus *smbus; I2CBus *smbus;
smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1); smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0);
/* TODO: Populate SPD eeprom data. */ /* TODO: Populate SPD eeprom data. */
smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
gsi[9], *smi_irq, gsi[9], smi_irq,
kvm_enabled(), fw_cfg, &piix4_pm); kvm_enabled(), &piix4_pm);
smbus_eeprom_init(smbus, 8, NULL, 0); smbus_eeprom_init(smbus, 8, NULL, 0);
object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP, object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
@@ -305,11 +303,6 @@ static void pc_init1(MachineState *machine,
} }
} }
static void pc_init_pci(MachineState *machine)
{
pc_init1(machine, 1, 1);
}
static void pc_compat_2_3(MachineState *machine) static void pc_compat_2_3(MachineState *machine)
{ {
} }
@@ -418,76 +411,16 @@ static void pc_compat_1_2(MachineState *machine)
x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI); x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI);
} }
static void pc_init_pci_2_3(MachineState *machine) /* PC compat function for pc-0.10 to pc-0.13 */
{ static void pc_compat_0_13(MachineState *machine)
pc_compat_2_3(machine);
pc_init_pci(machine);
}
static void pc_init_pci_2_2(MachineState *machine)
{
pc_compat_2_2(machine);
pc_init_pci(machine);
}
static void pc_init_pci_2_1(MachineState *machine)
{
pc_compat_2_1(machine);
pc_init_pci(machine);
}
static void pc_init_pci_2_0(MachineState *machine)
{
pc_compat_2_0(machine);
pc_init_pci(machine);
}
static void pc_init_pci_1_7(MachineState *machine)
{
pc_compat_1_7(machine);
pc_init_pci(machine);
}
static void pc_init_pci_1_6(MachineState *machine)
{
pc_compat_1_6(machine);
pc_init_pci(machine);
}
static void pc_init_pci_1_5(MachineState *machine)
{
pc_compat_1_5(machine);
pc_init_pci(machine);
}
static void pc_init_pci_1_4(MachineState *machine)
{
pc_compat_1_4(machine);
pc_init_pci(machine);
}
static void pc_init_pci_1_3(MachineState *machine)
{
pc_compat_1_3(machine);
pc_init_pci(machine);
}
/* PC machine init function for pc-0.14 to pc-1.2 */
static void pc_init_pci_1_2(MachineState *machine)
{ {
pc_compat_1_2(machine); pc_compat_1_2(machine);
pc_init_pci(machine); kvmclock_enabled = false;
}
/* PC init function for pc-0.10 to pc-0.13 */
static void pc_init_pci_no_kvmclock(MachineState *machine)
{
pc_compat_1_2(machine);
pc_init1(machine, 1, 0);
} }
static void pc_init_isa(MachineState *machine) static void pc_init_isa(MachineState *machine)
{ {
pci_enabled = false;
has_acpi_build = false; has_acpi_build = false;
smbios_defaults = false; smbios_defaults = false;
gigabyte_align = false; gigabyte_align = false;
@@ -500,7 +433,7 @@ static void pc_init_isa(MachineState *machine)
} }
x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI); x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI);
enable_compat_apic_id_mode(); enable_compat_apic_id_mode();
pc_init1(machine, 0, 1); pc_init1(machine);
} }
#ifdef CONFIG_XEN #ifdef CONFIG_XEN
@@ -508,7 +441,7 @@ static void pc_xen_hvm_init(MachineState *machine)
{ {
PCIBus *bus; PCIBus *bus;
pc_init_pci(machine); pc_init1(machine);
bus = pci_find_primary_bus(); bus = pci_find_primary_bus();
if (bus != NULL) { if (bus != NULL) {
@@ -517,118 +450,126 @@ static void pc_xen_hvm_init(MachineState *machine)
} }
#endif #endif
#define PC_I440FX_MACHINE_OPTIONS \ #define DEFINE_I440FX_MACHINE(suffix, name, compatfn, optionfn) \
PC_DEFAULT_MACHINE_OPTIONS, \ static void pc_init_##suffix(MachineState *machine) \
.family = "pc_piix", \ { \
.desc = "Standard PC (i440FX + PIIX, 1996)", \ void (*compat)(MachineState *m) = (compatfn); \
.hot_add_cpu = pc_hot_add_cpu if (compat) { \
compat(machine); \
} \
pc_init1(machine); \
} \
DEFINE_PC_MACHINE(suffix, name, pc_init_##suffix, optionfn)
#define PC_I440FX_2_4_MACHINE_OPTIONS \ static void pc_i440fx_machine_options(MachineClass *m)
PC_I440FX_MACHINE_OPTIONS, \ {
.default_machine_opts = "firmware=bios-256k.bin", \ pc_default_machine_options(m);
.default_display = "std" m->family = "pc_piix";
m->desc = "Standard PC (i440FX + PIIX, 1996)";
m->hot_add_cpu = pc_hot_add_cpu;
}
static void pc_i440fx_2_4_machine_options(MachineClass *m)
{
pc_i440fx_machine_options(m);
m->default_machine_opts = "firmware=bios-256k.bin";
m->default_display = "std";
m->alias = "pc";
m->is_default = 1;
}
DEFINE_I440FX_MACHINE(v2_4, "pc-i440fx-2.4", NULL,
pc_i440fx_2_4_machine_options)
static QEMUMachine pc_i440fx_machine_v2_4 = { static void pc_i440fx_2_3_machine_options(MachineClass *m)
PC_I440FX_2_4_MACHINE_OPTIONS, {
.name = "pc-i440fx-2.4", pc_i440fx_machine_options(m);
.alias = "pc", m->alias = NULL;
.init = pc_init_pci, m->is_default = 0;
.is_default = 1, SET_MACHINE_COMPAT(m, PC_COMPAT_2_3);
}; }
#define PC_I440FX_2_3_MACHINE_OPTIONS PC_I440FX_2_4_MACHINE_OPTIONS DEFINE_I440FX_MACHINE(v2_3, "pc-i440fx-2.3", pc_compat_2_3,
pc_i440fx_2_3_machine_options);
static QEMUMachine pc_i440fx_machine_v2_3 = {
PC_I440FX_2_3_MACHINE_OPTIONS,
.name = "pc-i440fx-2.3",
.init = pc_init_pci_2_3,
};
#define PC_I440FX_2_2_MACHINE_OPTIONS PC_I440FX_2_3_MACHINE_OPTIONS static void pc_i440fx_2_2_machine_options(MachineClass *m)
{
pc_i440fx_2_3_machine_options(m);
SET_MACHINE_COMPAT(m, PC_COMPAT_2_2);
}
static QEMUMachine pc_i440fx_machine_v2_2 = { DEFINE_I440FX_MACHINE(v2_2, "pc-i440fx-2.2", pc_compat_2_2,
PC_I440FX_2_2_MACHINE_OPTIONS, pc_i440fx_2_2_machine_options);
.name = "pc-i440fx-2.2",
.init = pc_init_pci_2_2,
};
#define PC_I440FX_2_1_MACHINE_OPTIONS \
PC_I440FX_MACHINE_OPTIONS, \
.default_machine_opts = "firmware=bios-256k.bin"
static QEMUMachine pc_i440fx_machine_v2_1 = { static void pc_i440fx_2_1_machine_options(MachineClass *m)
PC_I440FX_2_1_MACHINE_OPTIONS, {
.name = "pc-i440fx-2.1", pc_i440fx_2_2_machine_options(m);
.init = pc_init_pci_2_1, m->default_display = NULL;
.compat_props = (GlobalProperty[]) { SET_MACHINE_COMPAT(m, PC_COMPAT_2_1);
HW_COMPAT_2_1, }
{ /* end of list */ }
},
};
#define PC_I440FX_2_0_MACHINE_OPTIONS PC_I440FX_2_1_MACHINE_OPTIONS DEFINE_I440FX_MACHINE(v2_1, "pc-i440fx-2.1", pc_compat_2_1,
pc_i440fx_2_1_machine_options);
static QEMUMachine pc_i440fx_machine_v2_0 = {
PC_I440FX_2_0_MACHINE_OPTIONS,
.name = "pc-i440fx-2.0",
.init = pc_init_pci_2_0,
.compat_props = (GlobalProperty[]) {
PC_COMPAT_2_0,
{ /* end of list */ }
},
};
#define PC_I440FX_1_7_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
static QEMUMachine pc_i440fx_machine_v1_7 = { static void pc_i440fx_2_0_machine_options(MachineClass *m)
PC_I440FX_1_7_MACHINE_OPTIONS, {
.name = "pc-i440fx-1.7", pc_i440fx_2_1_machine_options(m);
.init = pc_init_pci_1_7, SET_MACHINE_COMPAT(m, PC_COMPAT_2_0);
.compat_props = (GlobalProperty[]) { }
PC_COMPAT_1_7,
{ /* end of list */ }
},
};
#define PC_I440FX_1_6_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS DEFINE_I440FX_MACHINE(v2_0, "pc-i440fx-2.0", pc_compat_2_0,
pc_i440fx_2_0_machine_options);
static QEMUMachine pc_i440fx_machine_v1_6 = {
PC_I440FX_1_6_MACHINE_OPTIONS,
.name = "pc-i440fx-1.6",
.init = pc_init_pci_1_6,
.compat_props = (GlobalProperty[]) {
PC_COMPAT_1_6,
{ /* end of list */ }
},
};
static QEMUMachine pc_i440fx_machine_v1_5 = { static void pc_i440fx_1_7_machine_options(MachineClass *m)
PC_I440FX_1_6_MACHINE_OPTIONS, {
.name = "pc-i440fx-1.5", pc_i440fx_2_0_machine_options(m);
.init = pc_init_pci_1_5, m->default_machine_opts = NULL;
.compat_props = (GlobalProperty[]) { SET_MACHINE_COMPAT(m, PC_COMPAT_1_7);
PC_COMPAT_1_5, }
{ /* end of list */ }
},
};
#define PC_I440FX_1_4_MACHINE_OPTIONS \ DEFINE_I440FX_MACHINE(v1_7, "pc-i440fx-1.7", pc_compat_1_7,
PC_I440FX_1_6_MACHINE_OPTIONS, \ pc_i440fx_1_7_machine_options);
.hot_add_cpu = NULL
static void pc_i440fx_1_6_machine_options(MachineClass *m)
{
pc_i440fx_1_7_machine_options(m);
SET_MACHINE_COMPAT(m, PC_COMPAT_1_6);
}
DEFINE_I440FX_MACHINE(v1_6, "pc-i440fx-1.6", pc_compat_1_6,
pc_i440fx_1_6_machine_options);
static void pc_i440fx_1_5_machine_options(MachineClass *m)
{
pc_i440fx_1_6_machine_options(m);
SET_MACHINE_COMPAT(m, PC_COMPAT_1_5);
}
DEFINE_I440FX_MACHINE(v1_5, "pc-i440fx-1.5", pc_compat_1_5,
pc_i440fx_1_5_machine_options);
static void pc_i440fx_1_4_machine_options(MachineClass *m)
{
pc_i440fx_1_5_machine_options(m);
m->hot_add_cpu = NULL;
SET_MACHINE_COMPAT(m, PC_COMPAT_1_4);
}
DEFINE_I440FX_MACHINE(v1_4, "pc-i440fx-1.4", pc_compat_1_4,
pc_i440fx_1_4_machine_options);
static QEMUMachine pc_i440fx_machine_v1_4 = {
PC_I440FX_1_4_MACHINE_OPTIONS,
.name = "pc-i440fx-1.4",
.init = pc_init_pci_1_4,
.compat_props = (GlobalProperty[]) {
PC_COMPAT_1_4,
{ /* end of list */ }
},
};
#define PC_COMPAT_1_3 \ #define PC_COMPAT_1_3 \
PC_COMPAT_1_4, \ PC_COMPAT_1_4 \
{\ {\
.driver = "usb-tablet",\ .driver = "usb-tablet",\
.property = "usb_version",\ .property = "usb_version",\
@@ -645,20 +586,21 @@ static QEMUMachine pc_i440fx_machine_v1_4 = {
.driver = "e1000",\ .driver = "e1000",\
.property = "autonegotiation",\ .property = "autonegotiation",\
.value = "off",\ .value = "off",\
} },
static void pc_i440fx_1_3_machine_options(MachineClass *m)
{
pc_i440fx_1_4_machine_options(m);
SET_MACHINE_COMPAT(m, PC_COMPAT_1_3);
}
DEFINE_I440FX_MACHINE(v1_3, "pc-1.3", pc_compat_1_3,
pc_i440fx_1_3_machine_options);
static QEMUMachine pc_machine_v1_3 = {
PC_I440FX_1_4_MACHINE_OPTIONS,
.name = "pc-1.3",
.init = pc_init_pci_1_3,
.compat_props = (GlobalProperty[]) {
PC_COMPAT_1_3,
{ /* end of list */ }
},
};
#define PC_COMPAT_1_2 \ #define PC_COMPAT_1_2 \
PC_COMPAT_1_3,\ PC_COMPAT_1_3 \
{\ {\
.driver = "nec-usb-xhci",\ .driver = "nec-usb-xhci",\
.property = "msi",\ .property = "msi",\
@@ -683,23 +625,20 @@ static QEMUMachine pc_machine_v1_3 = {
.driver = "VGA",\ .driver = "VGA",\
.property = "mmio",\ .property = "mmio",\
.value = "off",\ .value = "off",\
} },
#define PC_I440FX_1_2_MACHINE_OPTIONS \ static void pc_i440fx_1_2_machine_options(MachineClass *m)
PC_I440FX_1_4_MACHINE_OPTIONS, \ {
.init = pc_init_pci_1_2 pc_i440fx_1_3_machine_options(m);
SET_MACHINE_COMPAT(m, PC_COMPAT_1_2);
}
DEFINE_I440FX_MACHINE(v1_2, "pc-1.2", pc_compat_1_2,
pc_i440fx_1_2_machine_options);
static QEMUMachine pc_machine_v1_2 = {
PC_I440FX_1_2_MACHINE_OPTIONS,
.name = "pc-1.2",
.compat_props = (GlobalProperty[]) {
PC_COMPAT_1_2,
{ /* end of list */ }
},
};
#define PC_COMPAT_1_1 \ #define PC_COMPAT_1_1 \
PC_COMPAT_1_2,\ PC_COMPAT_1_2 \
{\ {\
.driver = "virtio-scsi-pci",\ .driver = "virtio-scsi-pci",\
.property = "hotplug",\ .property = "hotplug",\
@@ -728,19 +667,20 @@ static QEMUMachine pc_machine_v1_2 = {
.driver = "virtio-blk-pci",\ .driver = "virtio-blk-pci",\
.property = "config-wce",\ .property = "config-wce",\
.value = "off",\ .value = "off",\
} },
static void pc_i440fx_1_1_machine_options(MachineClass *m)
{
pc_i440fx_1_2_machine_options(m);
SET_MACHINE_COMPAT(m, PC_COMPAT_1_1);
}
DEFINE_I440FX_MACHINE(v1_1, "pc-1.1", pc_compat_1_2,
pc_i440fx_1_1_machine_options);
static QEMUMachine pc_machine_v1_1 = {
PC_I440FX_1_2_MACHINE_OPTIONS,
.name = "pc-1.1",
.compat_props = (GlobalProperty[]) {
PC_COMPAT_1_1,
{ /* end of list */ }
},
};
#define PC_COMPAT_1_0 \ #define PC_COMPAT_1_0 \
PC_COMPAT_1_1,\ PC_COMPAT_1_1 \
{\ {\
.driver = TYPE_ISA_FDC,\ .driver = TYPE_ISA_FDC,\
.property = "check_media_rate",\ .property = "check_media_rate",\
@@ -757,33 +697,35 @@ static QEMUMachine pc_machine_v1_1 = {
.driver = TYPE_USB_DEVICE,\ .driver = TYPE_USB_DEVICE,\
.property = "full-path",\ .property = "full-path",\
.value = "no",\ .value = "no",\
} },
static void pc_i440fx_1_0_machine_options(MachineClass *m)
{
pc_i440fx_1_1_machine_options(m);
m->hw_version = "1.0";
SET_MACHINE_COMPAT(m, PC_COMPAT_1_0);
}
DEFINE_I440FX_MACHINE(v1_0, "pc-1.0", pc_compat_1_2,
pc_i440fx_1_0_machine_options);
static QEMUMachine pc_machine_v1_0 = {
PC_I440FX_1_2_MACHINE_OPTIONS,
.name = "pc-1.0",
.compat_props = (GlobalProperty[]) {
PC_COMPAT_1_0,
{ /* end of list */ }
},
.hw_version = "1.0",
};
#define PC_COMPAT_0_15 \ #define PC_COMPAT_0_15 \
PC_COMPAT_1_0 PC_COMPAT_1_0
static QEMUMachine pc_machine_v0_15 = { static void pc_i440fx_0_15_machine_options(MachineClass *m)
PC_I440FX_1_2_MACHINE_OPTIONS, {
.name = "pc-0.15", pc_i440fx_1_0_machine_options(m);
.compat_props = (GlobalProperty[]) { m->hw_version = "0.15";
PC_COMPAT_0_15, SET_MACHINE_COMPAT(m, PC_COMPAT_0_15);
{ /* end of list */ } }
},
.hw_version = "0.15", DEFINE_I440FX_MACHINE(v0_15, "pc-0.15", pc_compat_1_2,
}; pc_i440fx_0_15_machine_options);
#define PC_COMPAT_0_14 \ #define PC_COMPAT_0_14 \
PC_COMPAT_0_15,\ PC_COMPAT_0_15 \
{\ {\
.driver = "virtio-blk-pci",\ .driver = "virtio-blk-pci",\
.property = "event_idx",\ .property = "event_idx",\
@@ -800,29 +742,29 @@ static QEMUMachine pc_machine_v0_15 = {
.driver = "virtio-balloon-pci",\ .driver = "virtio-balloon-pci",\
.property = "event_idx",\ .property = "event_idx",\
.value = "off",\ .value = "off",\
} },{\
.driver = "qxl",\
static QEMUMachine pc_machine_v0_14 = { .property = "revision",\
PC_I440FX_1_2_MACHINE_OPTIONS, .value = stringify(2),\
.name = "pc-0.14", },{\
.compat_props = (GlobalProperty[]) { .driver = "qxl-vga",\
PC_COMPAT_0_14, .property = "revision",\
{ .value = stringify(2),\
.driver = "qxl",
.property = "revision",
.value = stringify(2),
},{
.driver = "qxl-vga",
.property = "revision",
.value = stringify(2),
}, },
{ /* end of list */ }
}, static void pc_i440fx_0_14_machine_options(MachineClass *m)
.hw_version = "0.14", {
}; pc_i440fx_0_15_machine_options(m);
m->hw_version = "0.14";
SET_MACHINE_COMPAT(m, PC_COMPAT_0_14);
}
DEFINE_I440FX_MACHINE(v0_14, "pc-0.14", pc_compat_1_2,
pc_i440fx_0_14_machine_options);
#define PC_COMPAT_0_13 \ #define PC_COMPAT_0_13 \
PC_COMPAT_0_14,\ PC_COMPAT_0_14 \
{\ {\
.driver = TYPE_PCI_DEVICE,\ .driver = TYPE_PCI_DEVICE,\
.property = "command_serr_enable",\ .property = "command_serr_enable",\
@@ -831,37 +773,33 @@ static QEMUMachine pc_machine_v0_14 = {
.driver = "AC97",\ .driver = "AC97",\
.property = "use_broken_id",\ .property = "use_broken_id",\
.value = stringify(1),\ .value = stringify(1),\
} },{\
.driver = "virtio-9p-pci",\
#define PC_I440FX_0_13_MACHINE_OPTIONS \ .property = "vectors",\
PC_I440FX_1_2_MACHINE_OPTIONS, \ .value = stringify(0),\
.init = pc_init_pci_no_kvmclock },{\
.driver = "VGA",\
static QEMUMachine pc_machine_v0_13 = { .property = "rombar",\
PC_I440FX_0_13_MACHINE_OPTIONS, .value = stringify(0),\
.name = "pc-0.13", },{\
.compat_props = (GlobalProperty[]) { .driver = "vmware-svga",\
PC_COMPAT_0_13, .property = "rombar",\
{ .value = stringify(0),\
.driver = "virtio-9p-pci",
.property = "vectors",
.value = stringify(0),
},{
.driver = "VGA",
.property = "rombar",
.value = stringify(0),
},{
.driver = "vmware-svga",
.property = "rombar",
.value = stringify(0),
}, },
{ /* end of list */ }
}, static void pc_i440fx_0_13_machine_options(MachineClass *m)
.hw_version = "0.13", {
}; pc_i440fx_0_14_machine_options(m);
m->hw_version = "0.13";
SET_MACHINE_COMPAT(m, PC_COMPAT_0_13);
}
DEFINE_I440FX_MACHINE(v0_13, "pc-0.13", pc_compat_0_13,
pc_i440fx_0_13_machine_options);
#define PC_COMPAT_0_12 \ #define PC_COMPAT_0_12 \
PC_COMPAT_0_13,\ PC_COMPAT_0_13 \
{\ {\
.driver = "virtio-serial-pci",\ .driver = "virtio-serial-pci",\
.property = "max_ports",\ .property = "max_ports",\
@@ -882,29 +820,21 @@ static QEMUMachine pc_machine_v0_13 = {
.driver = "usb-kbd",\ .driver = "usb-kbd",\
.property = "serial",\ .property = "serial",\
.value = "1",\ .value = "1",\
}
static QEMUMachine pc_machine_v0_12 = {
PC_I440FX_0_13_MACHINE_OPTIONS,
.name = "pc-0.12",
.compat_props = (GlobalProperty[]) {
PC_COMPAT_0_12,
{
.driver = "VGA",
.property = "rombar",
.value = stringify(0),
},{
.driver = "vmware-svga",
.property = "rombar",
.value = stringify(0),
}, },
{ /* end of list */ }
}, static void pc_i440fx_0_12_machine_options(MachineClass *m)
.hw_version = "0.12", {
}; pc_i440fx_0_13_machine_options(m);
m->hw_version = "0.12";
SET_MACHINE_COMPAT(m, PC_COMPAT_0_12);
}
DEFINE_I440FX_MACHINE(v0_12, "pc-0.12", pc_compat_0_13,
pc_i440fx_0_12_machine_options);
#define PC_COMPAT_0_11 \ #define PC_COMPAT_0_11 \
PC_COMPAT_0_12,\ PC_COMPAT_0_12 \
{\ {\
.driver = "virtio-blk-pci",\ .driver = "virtio-blk-pci",\
.property = "vectors",\ .property = "vectors",\
@@ -913,106 +843,83 @@ static QEMUMachine pc_machine_v0_12 = {
.driver = TYPE_PCI_DEVICE,\ .driver = TYPE_PCI_DEVICE,\
.property = "rombar",\ .property = "rombar",\
.value = stringify(0),\ .value = stringify(0),\
} },{\
.driver = "ide-drive",\
static QEMUMachine pc_machine_v0_11 = { .property = "ver",\
PC_I440FX_0_13_MACHINE_OPTIONS, .value = "0.11",\
.name = "pc-0.11", },{\
.compat_props = (GlobalProperty[]) { .driver = "scsi-disk",\
PC_COMPAT_0_11, .property = "ver",\
{ .value = "0.11",\
.driver = "ide-drive",
.property = "ver",
.value = "0.11",
},{
.driver = "scsi-disk",
.property = "ver",
.value = "0.11",
}, },
{ /* end of list */ }
},
.hw_version = "0.11",
};
static QEMUMachine pc_machine_v0_10 = { static void pc_i440fx_0_11_machine_options(MachineClass *m)
PC_I440FX_0_13_MACHINE_OPTIONS,
.name = "pc-0.10",
.compat_props = (GlobalProperty[]) {
PC_COMPAT_0_11,
{
.driver = "virtio-blk-pci",
.property = "class",
.value = stringify(PCI_CLASS_STORAGE_OTHER),
},{
.driver = "virtio-serial-pci",
.property = "class",
.value = stringify(PCI_CLASS_DISPLAY_OTHER),
},{
.driver = "virtio-net-pci",
.property = "vectors",
.value = stringify(0),
},{
.driver = "ide-drive",
.property = "ver",
.value = "0.10",
},{
.driver = "scsi-disk",
.property = "ver",
.value = "0.10",
},
{ /* end of list */ }
},
.hw_version = "0.10",
};
static QEMUMachine isapc_machine = {
PC_COMMON_MACHINE_OPTIONS,
.name = "isapc",
.desc = "ISA-only PC",
.init = pc_init_isa,
.max_cpus = 1,
.compat_props = (GlobalProperty[]) {
{ /* end of list */ }
},
};
#ifdef CONFIG_XEN
static QEMUMachine xenfv_machine = {
PC_COMMON_MACHINE_OPTIONS,
.name = "xenfv",
.desc = "Xen Fully-virtualized PC",
.init = pc_xen_hvm_init,
.max_cpus = HVM_MAX_VCPUS,
.default_machine_opts = "accel=xen",
.hot_add_cpu = pc_hot_add_cpu,
};
#endif
static void pc_machine_init(void)
{ {
qemu_register_pc_machine(&pc_i440fx_machine_v2_4); pc_i440fx_0_12_machine_options(m);
qemu_register_pc_machine(&pc_i440fx_machine_v2_3); m->hw_version = "0.11";
qemu_register_pc_machine(&pc_i440fx_machine_v2_2); SET_MACHINE_COMPAT(m, PC_COMPAT_0_11);
qemu_register_pc_machine(&pc_i440fx_machine_v2_1);
qemu_register_pc_machine(&pc_i440fx_machine_v2_0);
qemu_register_pc_machine(&pc_i440fx_machine_v1_7);
qemu_register_pc_machine(&pc_i440fx_machine_v1_6);
qemu_register_pc_machine(&pc_i440fx_machine_v1_5);
qemu_register_pc_machine(&pc_i440fx_machine_v1_4);
qemu_register_pc_machine(&pc_machine_v1_3);
qemu_register_pc_machine(&pc_machine_v1_2);
qemu_register_pc_machine(&pc_machine_v1_1);
qemu_register_pc_machine(&pc_machine_v1_0);
qemu_register_pc_machine(&pc_machine_v0_15);
qemu_register_pc_machine(&pc_machine_v0_14);
qemu_register_pc_machine(&pc_machine_v0_13);
qemu_register_pc_machine(&pc_machine_v0_12);
qemu_register_pc_machine(&pc_machine_v0_11);
qemu_register_pc_machine(&pc_machine_v0_10);
qemu_register_pc_machine(&isapc_machine);
#ifdef CONFIG_XEN
qemu_register_pc_machine(&xenfv_machine);
#endif
} }
machine_init(pc_machine_init); DEFINE_I440FX_MACHINE(v0_11, "pc-0.11", pc_compat_0_13,
pc_i440fx_0_11_machine_options);
#define PC_COMPAT_0_10 \
PC_COMPAT_0_11 \
{\
.driver = "virtio-blk-pci",\
.property = "class",\
.value = stringify(PCI_CLASS_STORAGE_OTHER),\
},{\
.driver = "virtio-serial-pci",\
.property = "class",\
.value = stringify(PCI_CLASS_DISPLAY_OTHER),\
},{\
.driver = "virtio-net-pci",\
.property = "vectors",\
.value = stringify(0),\
},{\
.driver = "ide-drive",\
.property = "ver",\
.value = "0.10",\
},{\
.driver = "scsi-disk",\
.property = "ver",\
.value = "0.10",\
},
static void pc_i440fx_0_10_machine_options(MachineClass *m)
{
pc_i440fx_0_11_machine_options(m);
m->hw_version = "0.10";
SET_MACHINE_COMPAT(m, PC_COMPAT_0_10);
}
DEFINE_I440FX_MACHINE(v0_10, "pc-0.10", pc_compat_0_13,
pc_i440fx_0_10_machine_options);
static void isapc_machine_options(MachineClass *m)
{
pc_common_machine_options(m);
m->desc = "ISA-only PC";
m->max_cpus = 1;
}
DEFINE_PC_MACHINE(isapc, "isapc", pc_init_isa,
isapc_machine_options);
#ifdef CONFIG_XEN
static void xenfv_machine_options(MachineClass *m)
{
pc_common_machine_options(m);
m->desc = "Xen Fully-virtualized PC";
m->max_cpus = HVM_MAX_VCPUS;
m->default_machine_opts = "accel=xen";
m->hot_add_cpu = pc_hot_add_cpu;
}
DEFINE_PC_MACHINE(xenfv, "xenfv", pc_xen_hvm_init,
xenfv_machine_options);
#endif

View File

@@ -79,7 +79,6 @@ static void pc_q35_init(MachineState *machine)
GSIState *gsi_state; GSIState *gsi_state;
ISABus *isa_bus; ISABus *isa_bus;
int pci_enabled = 1; int pci_enabled = 1;
qemu_irq *cpu_irq;
qemu_irq *gsi; qemu_irq *gsi;
qemu_irq *i8259; qemu_irq *i8259;
int i; int i;
@@ -89,6 +88,7 @@ static void pc_q35_init(MachineState *machine)
PcGuestInfo *guest_info; PcGuestInfo *guest_info;
ram_addr_t lowmem; ram_addr_t lowmem;
DriveInfo *hd[MAX_SATA_PORTS]; DriveInfo *hd[MAX_SATA_PORTS];
MachineClass *mc = MACHINE_GET_CLASS(machine);
/* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory
* and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping * and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping
@@ -163,7 +163,6 @@ static void pc_q35_init(MachineState *machine)
guest_info->legacy_acpi_table_size = 0; guest_info->legacy_acpi_table_size = 0;
if (smbios_defaults) { if (smbios_defaults) {
MachineClass *mc = MACHINE_GET_CLASS(machine);
/* These values are guest ABI, do not change */ /* These values are guest ABI, do not change */
smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)", smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
mc->name, smbios_legacy_mode, smbios_uuid_encoded); mc->name, smbios_legacy_mode, smbios_uuid_encoded);
@@ -230,8 +229,7 @@ static void pc_q35_init(MachineState *machine)
} else if (xen_enabled()) { } else if (xen_enabled()) {
i8259 = xen_interrupt_controller_init(); i8259 = xen_interrupt_controller_init();
} else { } else {
cpu_irq = pc_allocate_cpu_irq(); i8259 = i8259_init(isa_bus, pc_allocate_cpu_irq());
i8259 = i8259_init(isa_bus, cpu_irq[0]);
} }
for (i = 0; i < ISA_NUM_IRQS; i++) { for (i = 0; i < ISA_NUM_IRQS; i++) {
@@ -250,7 +248,7 @@ static void pc_q35_init(MachineState *machine)
} }
/* init basic PC hardware */ /* init basic PC hardware */
pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, pc_basic_device_init(isa_bus, gsi, &rtc_state, !mc->no_floppy, &floppy,
(pc_machine->vmport != ON_OFF_AUTO_ON), 0xff0104); (pc_machine->vmport != ON_OFF_AUTO_ON), 0xff0104);
/* connect pm stuff to lpc */ /* connect pm stuff to lpc */
@@ -366,174 +364,119 @@ static void pc_compat_1_4(MachineState *machine)
x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
} }
static void pc_q35_init_2_3(MachineState *machine) #define DEFINE_Q35_MACHINE(suffix, name, compatfn, optionfn) \
static void pc_init_##suffix(MachineState *machine) \
{ \
void (*compat)(MachineState *m) = (compatfn); \
if (compat) { \
compat(machine); \
} \
pc_q35_init(machine); \
} \
DEFINE_PC_MACHINE(suffix, name, pc_init_##suffix, optionfn)
static void pc_q35_machine_options(MachineClass *m)
{ {
pc_compat_2_3(machine); pc_default_machine_options(m);
pc_q35_init(machine); m->family = "pc_q35";
m->desc = "Standard PC (Q35 + ICH9, 2009)";
m->hot_add_cpu = pc_hot_add_cpu;
m->units_per_default_bus = 1;
} }
static void pc_q35_init_2_2(MachineState *machine) static void pc_q35_2_4_machine_options(MachineClass *m)
{ {
pc_compat_2_2(machine); pc_q35_machine_options(m);
pc_q35_init(machine); m->default_machine_opts = "firmware=bios-256k.bin";
m->default_display = "std";
m->no_floppy = 1;
m->alias = "q35";
} }
static void pc_q35_init_2_1(MachineState *machine) DEFINE_Q35_MACHINE(v2_4, "pc-q35-2.4", NULL,
pc_q35_2_4_machine_options);
static void pc_q35_2_3_machine_options(MachineClass *m)
{ {
pc_compat_2_1(machine); pc_q35_2_4_machine_options(m);
pc_q35_init(machine); m->alias = NULL;
SET_MACHINE_COMPAT(m, PC_COMPAT_2_3);
} }
static void pc_q35_init_2_0(MachineState *machine) DEFINE_Q35_MACHINE(v2_3, "pc-q35-2.3", pc_compat_2_3,
pc_q35_2_3_machine_options);
static void pc_q35_2_2_machine_options(MachineClass *m)
{ {
pc_compat_2_0(machine); pc_q35_2_3_machine_options(m);
pc_q35_init(machine); SET_MACHINE_COMPAT(m, PC_COMPAT_2_2);
} }
static void pc_q35_init_1_7(MachineState *machine) DEFINE_Q35_MACHINE(v2_2, "pc-q35-2.2", pc_compat_2_2,
pc_q35_2_2_machine_options);
static void pc_q35_2_1_machine_options(MachineClass *m)
{ {
pc_compat_1_7(machine); pc_q35_2_2_machine_options(m);
pc_q35_init(machine); m->default_display = NULL;
SET_MACHINE_COMPAT(m, PC_COMPAT_2_1);
} }
static void pc_q35_init_1_6(MachineState *machine) DEFINE_Q35_MACHINE(v2_1, "pc-q35-2.1", pc_compat_2_1,
pc_q35_2_1_machine_options);
static void pc_q35_2_0_machine_options(MachineClass *m)
{ {
pc_compat_1_6(machine); pc_q35_2_1_machine_options(m);
pc_q35_init(machine); SET_MACHINE_COMPAT(m, PC_COMPAT_2_0);
} }
static void pc_q35_init_1_5(MachineState *machine) DEFINE_Q35_MACHINE(v2_0, "pc-q35-2.0", pc_compat_2_0,
pc_q35_2_0_machine_options);
static void pc_q35_1_7_machine_options(MachineClass *m)
{ {
pc_compat_1_5(machine); pc_q35_2_0_machine_options(m);
pc_q35_init(machine); m->default_machine_opts = NULL;
SET_MACHINE_COMPAT(m, PC_COMPAT_1_7);
} }
static void pc_q35_init_1_4(MachineState *machine) DEFINE_Q35_MACHINE(v1_7, "pc-q35-1.7", pc_compat_1_7,
pc_q35_1_7_machine_options);
static void pc_q35_1_6_machine_options(MachineClass *m)
{ {
pc_compat_1_4(machine); pc_q35_machine_options(m);
pc_q35_init(machine); SET_MACHINE_COMPAT(m, PC_COMPAT_1_6);
} }
#define PC_Q35_MACHINE_OPTIONS \ DEFINE_Q35_MACHINE(v1_6, "pc-q35-1.6", pc_compat_1_6,
PC_DEFAULT_MACHINE_OPTIONS, \ pc_q35_1_6_machine_options);
.family = "pc_q35", \
.desc = "Standard PC (Q35 + ICH9, 2009)", \
.hot_add_cpu = pc_hot_add_cpu, \
.units_per_default_bus = 1
#define PC_Q35_2_4_MACHINE_OPTIONS \
PC_Q35_MACHINE_OPTIONS, \
.default_machine_opts = "firmware=bios-256k.bin", \
.default_display = "std"
static QEMUMachine pc_q35_machine_v2_4 = { static void pc_q35_1_5_machine_options(MachineClass *m)
PC_Q35_2_4_MACHINE_OPTIONS,
.name = "pc-q35-2.4",
.alias = "q35",
.init = pc_q35_init,
};
#define PC_Q35_2_3_MACHINE_OPTIONS PC_Q35_2_4_MACHINE_OPTIONS
static QEMUMachine pc_q35_machine_v2_3 = {
PC_Q35_2_3_MACHINE_OPTIONS,
.name = "pc-q35-2.3",
.init = pc_q35_init_2_3,
};
#define PC_Q35_2_2_MACHINE_OPTIONS PC_Q35_2_3_MACHINE_OPTIONS
static QEMUMachine pc_q35_machine_v2_2 = {
PC_Q35_2_2_MACHINE_OPTIONS,
.name = "pc-q35-2.2",
.init = pc_q35_init_2_2,
};
#define PC_Q35_2_1_MACHINE_OPTIONS \
PC_Q35_MACHINE_OPTIONS, \
.default_machine_opts = "firmware=bios-256k.bin"
static QEMUMachine pc_q35_machine_v2_1 = {
PC_Q35_2_1_MACHINE_OPTIONS,
.name = "pc-q35-2.1",
.init = pc_q35_init_2_1,
.compat_props = (GlobalProperty[]) {
HW_COMPAT_2_1,
{ /* end of list */ }
},
};
#define PC_Q35_2_0_MACHINE_OPTIONS PC_Q35_2_1_MACHINE_OPTIONS
static QEMUMachine pc_q35_machine_v2_0 = {
PC_Q35_2_0_MACHINE_OPTIONS,
.name = "pc-q35-2.0",
.init = pc_q35_init_2_0,
.compat_props = (GlobalProperty[]) {
PC_COMPAT_2_0,
{ /* end of list */ }
},
};
#define PC_Q35_1_7_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
static QEMUMachine pc_q35_machine_v1_7 = {
PC_Q35_1_7_MACHINE_OPTIONS,
.name = "pc-q35-1.7",
.init = pc_q35_init_1_7,
.compat_props = (GlobalProperty[]) {
PC_COMPAT_1_7,
{ /* end of list */ }
},
};
#define PC_Q35_1_6_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
static QEMUMachine pc_q35_machine_v1_6 = {
PC_Q35_1_6_MACHINE_OPTIONS,
.name = "pc-q35-1.6",
.init = pc_q35_init_1_6,
.compat_props = (GlobalProperty[]) {
PC_COMPAT_1_6,
{ /* end of list */ }
},
};
static QEMUMachine pc_q35_machine_v1_5 = {
PC_Q35_1_6_MACHINE_OPTIONS,
.name = "pc-q35-1.5",
.init = pc_q35_init_1_5,
.compat_props = (GlobalProperty[]) {
PC_COMPAT_1_5,
{ /* end of list */ }
},
};
#define PC_Q35_1_4_MACHINE_OPTIONS \
PC_Q35_1_6_MACHINE_OPTIONS, \
.hot_add_cpu = NULL
static QEMUMachine pc_q35_machine_v1_4 = {
PC_Q35_1_4_MACHINE_OPTIONS,
.name = "pc-q35-1.4",
.init = pc_q35_init_1_4,
.compat_props = (GlobalProperty[]) {
PC_COMPAT_1_4,
{ /* end of list */ }
},
};
static void pc_q35_machine_init(void)
{ {
qemu_register_pc_machine(&pc_q35_machine_v2_4); pc_q35_1_6_machine_options(m);
qemu_register_pc_machine(&pc_q35_machine_v2_3); SET_MACHINE_COMPAT(m, PC_COMPAT_1_5);
qemu_register_pc_machine(&pc_q35_machine_v2_2);
qemu_register_pc_machine(&pc_q35_machine_v2_1);
qemu_register_pc_machine(&pc_q35_machine_v2_0);
qemu_register_pc_machine(&pc_q35_machine_v1_7);
qemu_register_pc_machine(&pc_q35_machine_v1_6);
qemu_register_pc_machine(&pc_q35_machine_v1_5);
qemu_register_pc_machine(&pc_q35_machine_v1_4);
} }
machine_init(pc_q35_machine_init); DEFINE_Q35_MACHINE(v1_5, "pc-q35-1.5", pc_compat_1_5,
pc_q35_1_5_machine_options);
static void pc_q35_1_4_machine_options(MachineClass *m)
{
pc_q35_1_5_machine_options(m);
m->hot_add_cpu = NULL;
SET_MACHINE_COMPAT(m, PC_COMPAT_1_4);
}
DEFINE_Q35_MACHINE(v1_4, "pc-q35-1.4", pc_compat_1_4,
pc_q35_1_4_machine_options);

View File

@@ -0,0 +1,36 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* Common parts for TPM 1.2 and TPM 2 (with slight differences for PPI)
* to be #included
*/
External(\_SB.PCI0.ISA, DeviceObj)
Scope(\_SB.PCI0.ISA) {
/* TPM with emulated TPM TIS interface */
Device (TPM) {
Name (_HID, EisaID ("PNP0C31"))
Name (_CRS, ResourceTemplate ()
{
Memory32Fixed (ReadWrite, TPM_TIS_ADDR_BASE, TPM_TIS_ADDR_SIZE)
IRQNoFlags () {TPM_TIS_IRQ}
})
Method (_STA, 0, NotSerialized) {
Return (0x0F)
}
}
}

View File

@@ -25,19 +25,5 @@ DefinitionBlock (
0x1 // OEM Revision 0x1 // OEM Revision
) )
{ {
Scope(\_SB) { #include "ssdt-tpm-common.dsl"
/* TPM with emulated TPM TIS interface */
Device (TPM) {
Name (_HID, EisaID ("PNP0C31"))
Name (_CRS, ResourceTemplate ()
{
Memory32Fixed (ReadWrite, TPM_TIS_ADDR_BASE, TPM_TIS_ADDR_SIZE)
// older Linux tpm_tis drivers do not work with IRQ
//IRQNoFlags () {TPM_TIS_IRQ}
})
Method (_STA, 0, NotSerialized) {
Return (0x0F)
}
}
}
} }

View File

@@ -3,12 +3,12 @@ static unsigned char ssdt_tpm_aml[] = {
0x53, 0x53,
0x44, 0x44,
0x54, 0x54,
0x5d, 0x6b,
0x0, 0x0,
0x0, 0x0,
0x0, 0x0,
0x1, 0x1,
0x1c, 0x37,
0x42, 0x42,
0x58, 0x58,
0x50, 0x50,
@@ -36,15 +36,26 @@ static unsigned char ssdt_tpm_aml[] = {
0x14, 0x14,
0x20, 0x20,
0x10, 0x10,
0x38, 0x46,
0x4,
0x5c, 0x5c,
0x2f,
0x3,
0x5f, 0x5f,
0x53, 0x53,
0x42, 0x42,
0x5f, 0x5f,
0x50,
0x43,
0x49,
0x30,
0x49,
0x53,
0x41,
0x5f,
0x5b, 0x5b,
0x82, 0x82,
0x30, 0x33,
0x54, 0x54,
0x50, 0x50,
0x4d, 0x4d,
@@ -65,9 +76,9 @@ static unsigned char ssdt_tpm_aml[] = {
0x52, 0x52,
0x53, 0x53,
0x11, 0x11,
0x11, 0x14,
0xa, 0xa,
0xe, 0x11,
0x86, 0x86,
0x9, 0x9,
0x0, 0x0,
@@ -80,6 +91,9 @@ static unsigned char ssdt_tpm_aml[] = {
0x50, 0x50,
0x0, 0x0,
0x0, 0x0,
0x22,
0x20,
0x0,
0x79, 0x79,
0x0, 0x0,
0x14, 0x14,

29
hw/i386/ssdt-tpm2.dsl Normal file
View File

@@ -0,0 +1,29 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "hw/acpi/tpm.h"
ACPI_EXTRACT_ALL_CODE ssdt_tpm2_aml
DefinitionBlock (
"ssdt-tpm2.aml", // Output Filename
"SSDT", // Signature
0x01, // SSDT Compliance Revision
"BXPC", // OEMID
"BXSSDT", // TABLE ID
0x1 // OEM Revision
)
{
#include "ssdt-tpm-common.dsl"
}

View File

@@ -0,0 +1,109 @@
static unsigned char ssdt_tpm2_aml[] = {
0x53,
0x53,
0x44,
0x54,
0x6b,
0x0,
0x0,
0x0,
0x1,
0x37,
0x42,
0x58,
0x50,
0x43,
0x0,
0x0,
0x42,
0x58,
0x53,
0x53,
0x44,
0x54,
0x0,
0x0,
0x1,
0x0,
0x0,
0x0,
0x49,
0x4e,
0x54,
0x4c,
0x7,
0x11,
0x14,
0x20,
0x10,
0x46,
0x4,
0x5c,
0x2f,
0x3,
0x5f,
0x53,
0x42,
0x5f,
0x50,
0x43,
0x49,
0x30,
0x49,
0x53,
0x41,
0x5f,
0x5b,
0x82,
0x33,
0x54,
0x50,
0x4d,
0x5f,
0x8,
0x5f,
0x48,
0x49,
0x44,
0xc,
0x41,
0xd0,
0xc,
0x31,
0x8,
0x5f,
0x43,
0x52,
0x53,
0x11,
0x14,
0xa,
0x11,
0x86,
0x9,
0x0,
0x1,
0x0,
0x0,
0xd4,
0xfe,
0x0,
0x50,
0x0,
0x0,
0x22,
0x20,
0x0,
0x79,
0x0,
0x14,
0x9,
0x5f,
0x53,
0x54,
0x41,
0x0,
0xa4,
0xa,
0xf
};

View File

@@ -51,8 +51,15 @@ static const int debug_macio = 0;
#define MACIO_PAGE_SIZE 4096 #define MACIO_PAGE_SIZE 4096
/*
* Unaligned DMA read/write access functions required for OS X/Darwin which
* don't perform DMA transactions on sector boundaries. These functions are
* modelled on bdrv_co_do_preadv()/bdrv_co_do_pwritev() and so should be
* easy to remove if the unaligned block APIs are ever exposed.
*/
static void pmac_dma_read(BlockBackend *blk, static void pmac_dma_read(BlockBackend *blk,
int64_t sector_num, int nb_sectors, int64_t offset, unsigned int bytes,
void (*cb)(void *opaque, int ret), void *opaque) void (*cb)(void *opaque, int ret), void *opaque)
{ {
DBDMA_io *io = opaque; DBDMA_io *io = opaque;
@@ -60,76 +67,48 @@ static void pmac_dma_read(BlockBackend *blk,
IDEState *s = idebus_active_if(&m->bus); IDEState *s = idebus_active_if(&m->bus);
dma_addr_t dma_addr, dma_len; dma_addr_t dma_addr, dma_len;
void *mem; void *mem;
int nsector, remainder; int64_t sector_num;
int nsector;
uint64_t align = BDRV_SECTOR_SIZE;
size_t head_bytes, tail_bytes;
qemu_iovec_destroy(&io->iov); qemu_iovec_destroy(&io->iov);
qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1); qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1);
if (io->remainder_len > 0) { sector_num = (offset >> 9);
/* Return remainder of request */ nsector = (io->len >> 9);
int transfer = MIN(io->remainder_len, io->len);
MACIO_DPRINTF("--- DMA read pop - bounce addr: %p addr: %" MACIO_DPRINTF("--- DMA read transfer (0x%" HWADDR_PRIx ",0x%x): "
HWADDR_PRIx " remainder_len: %x\n", "sector_num: %" PRId64 ", nsector: %d\n", io->addr, io->len,
&io->remainder + (0x200 - transfer), io->addr, sector_num, nsector);
io->remainder_len);
cpu_physical_memory_write(io->addr,
&io->remainder + (0x200 - transfer),
transfer);
io->remainder_len -= transfer;
io->len -= transfer;
io->addr += transfer;
s->io_buffer_index += transfer;
s->io_buffer_size -= transfer;
if (io->remainder_len != 0) {
/* Still waiting for remainder */
return;
}
if (io->len == 0) {
MACIO_DPRINTF("--- finished all read processing; go and finish\n");
cb(opaque, 0);
return;
}
}
if (s->drive_kind == IDE_CD) {
sector_num = (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9);
} else {
sector_num = ide_get_sector(s) + (s->io_buffer_index >> 9);
}
nsector = ((io->len + 0x1ff) >> 9);
remainder = (nsector << 9) - io->len;
MACIO_DPRINTF("--- DMA read transfer - addr: %" HWADDR_PRIx " len: %x\n",
io->addr, io->len);
dma_addr = io->addr; dma_addr = io->addr;
dma_len = io->len; dma_len = io->len;
mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len, mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
DMA_DIRECTION_FROM_DEVICE); DMA_DIRECTION_FROM_DEVICE);
if (!remainder) { if (offset & (align - 1)) {
MACIO_DPRINTF("--- DMA read aligned - addr: %" HWADDR_PRIx head_bytes = offset & (align - 1);
" len: %x\n", io->addr, io->len);
qemu_iovec_add(&io->iov, mem, io->len);
} else {
MACIO_DPRINTF("--- DMA read unaligned - addr: %" HWADDR_PRIx
" len: %x\n", io->addr, io->len);
qemu_iovec_add(&io->iov, mem, io->len);
MACIO_DPRINTF("--- DMA read push - bounce addr: %p " MACIO_DPRINTF("--- DMA unaligned head: sector %" PRId64 ", "
"remainder_len: %x\n", "discarding %zu bytes\n", sector_num, head_bytes);
&io->remainder + 0x200 - remainder, remainder);
qemu_iovec_add(&io->iov, &io->remainder + 0x200 - remainder,
remainder);
io->remainder_len = remainder; qemu_iovec_add(&io->iov, &io->head_remainder, head_bytes);
bytes += offset & (align - 1);
offset = offset & ~(align - 1);
}
qemu_iovec_add(&io->iov, mem, io->len);
if ((offset + bytes) & (align - 1)) {
tail_bytes = (offset + bytes) & (align - 1);
MACIO_DPRINTF("--- DMA unaligned tail: sector %" PRId64 ", "
"discarding bytes %zu\n", sector_num, tail_bytes);
qemu_iovec_add(&io->iov, &io->tail_remainder, align - tail_bytes);
bytes = ROUND_UP(bytes, align);
} }
s->io_buffer_size -= io->len; s->io_buffer_size -= io->len;
@@ -137,15 +116,15 @@ static void pmac_dma_read(BlockBackend *blk,
io->len = 0; io->len = 0;
MACIO_DPRINTF("--- Block read transfer - sector_num: %"PRIx64" " MACIO_DPRINTF("--- Block read transfer - sector_num: %" PRIx64 " "
"nsector: %x\n", "nsector: %x\n", (offset >> 9), (bytes >> 9));
sector_num, nsector);
m->aiocb = blk_aio_readv(blk, sector_num, &io->iov, nsector, cb, io); m->aiocb = blk_aio_readv(blk, (offset >> 9), &io->iov, (bytes >> 9),
cb, io);
} }
static void pmac_dma_write(BlockBackend *blk, static void pmac_dma_write(BlockBackend *blk,
int64_t sector_num, int nb_sectors, int64_t offset, int bytes,
void (*cb)(void *opaque, int ret), void *opaque) void (*cb)(void *opaque, int ret), void *opaque)
{ {
DBDMA_io *io = opaque; DBDMA_io *io = opaque;
@@ -153,53 +132,20 @@ static void pmac_dma_write(BlockBackend *blk,
IDEState *s = idebus_active_if(&m->bus); IDEState *s = idebus_active_if(&m->bus);
dma_addr_t dma_addr, dma_len; dma_addr_t dma_addr, dma_len;
void *mem; void *mem;
int nsector, remainder; int64_t sector_num;
int extra = 0; int nsector;
uint64_t align = BDRV_SECTOR_SIZE;
size_t head_bytes, tail_bytes;
bool unaligned_head = false, unaligned_tail = false;
qemu_iovec_destroy(&io->iov); qemu_iovec_destroy(&io->iov);
qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1); qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1);
if (io->remainder_len > 0) { sector_num = (offset >> 9);
/* Return remainder of request */
int transfer = MIN(io->remainder_len, io->len);
MACIO_DPRINTF("--- processing write remainder %x\n", transfer);
cpu_physical_memory_read(io->addr,
&io->remainder + (0x200 - transfer),
transfer);
io->remainder_len -= transfer;
io->len -= transfer;
io->addr += transfer;
s->io_buffer_index += transfer;
s->io_buffer_size -= transfer;
if (io->remainder_len != 0) {
/* Still waiting for remainder */
return;
}
MACIO_DPRINTF("--> prepending bounce buffer with size 0x200\n");
/* Sector transfer complete - prepend to request */
qemu_iovec_add(&io->iov, &io->remainder, 0x200);
extra = 1;
}
if (s->drive_kind == IDE_CD) {
sector_num = (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9);
} else {
sector_num = ide_get_sector(s) + (s->io_buffer_index >> 9);
}
nsector = (io->len >> 9); nsector = (io->len >> 9);
remainder = io->len - (nsector << 9);
MACIO_DPRINTF("--- DMA write transfer - addr: %" HWADDR_PRIx " len: %x\n", MACIO_DPRINTF("--- DMA write transfer (0x%" HWADDR_PRIx ",0x%x): "
io->addr, io->len); "sector_num: %" PRId64 ", nsector: %d\n", io->addr, io->len,
MACIO_DPRINTF("xxx remainder: %x\n", remainder);
MACIO_DPRINTF("xxx sector_num: %"PRIx64" nsector: %x\n",
sector_num, nsector); sector_num, nsector);
dma_addr = io->addr; dma_addr = io->addr;
@@ -207,36 +153,59 @@ static void pmac_dma_write(BlockBackend *blk,
mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len, mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
DMA_DIRECTION_TO_DEVICE); DMA_DIRECTION_TO_DEVICE);
if (!remainder) { if (offset & (align - 1)) {
MACIO_DPRINTF("--- DMA write aligned - addr: %" HWADDR_PRIx head_bytes = offset & (align - 1);
" len: %x\n", io->addr, io->len); sector_num = ((offset & ~(align - 1)) >> 9);
MACIO_DPRINTF("--- DMA unaligned head: pre-reading head sector %"
PRId64 "\n", sector_num);
blk_pread(s->blk, (sector_num << 9), &io->head_remainder, align);
qemu_iovec_add(&io->iov, &io->head_remainder, head_bytes);
qemu_iovec_add(&io->iov, mem, io->len); qemu_iovec_add(&io->iov, mem, io->len);
} else {
/* Write up to last complete sector */
MACIO_DPRINTF("--- DMA write unaligned - addr: %" HWADDR_PRIx
" len: %x\n", io->addr, (nsector << 9));
qemu_iovec_add(&io->iov, mem, (nsector << 9));
MACIO_DPRINTF("--- DMA write read - bounce addr: %p " bytes += offset & (align - 1);
"remainder_len: %x\n", &io->remainder, remainder); offset = offset & ~(align - 1);
cpu_physical_memory_read(io->addr + (nsector << 9), &io->remainder,
remainder);
io->remainder_len = 0x200 - remainder; unaligned_head = true;
MACIO_DPRINTF("xxx remainder_len: %x\n", io->remainder_len);
} }
s->io_buffer_size -= ((nsector + extra) << 9); if ((offset + bytes) & (align - 1)) {
s->io_buffer_index += ((nsector + extra) << 9); tail_bytes = (offset + bytes) & (align - 1);
sector_num = (((offset + bytes) & ~(align - 1)) >> 9);
MACIO_DPRINTF("--- DMA unaligned tail: pre-reading tail sector %"
PRId64 "\n", sector_num);
blk_pread(s->blk, (sector_num << 9), &io->tail_remainder, align);
if (!unaligned_head) {
qemu_iovec_add(&io->iov, mem, io->len);
}
qemu_iovec_add(&io->iov, &io->tail_remainder + tail_bytes,
align - tail_bytes);
bytes = ROUND_UP(bytes, align);
unaligned_tail = true;
}
if (!unaligned_head && !unaligned_tail) {
qemu_iovec_add(&io->iov, mem, io->len);
}
s->io_buffer_size -= io->len;
s->io_buffer_index += io->len;
io->len = 0; io->len = 0;
MACIO_DPRINTF("--- Block write transfer - sector_num: %"PRIx64" " MACIO_DPRINTF("--- Block write transfer - sector_num: %" PRIx64 " "
"nsector: %x\n", sector_num, nsector + extra); "nsector: %x\n", (offset >> 9), (bytes >> 9));
m->aiocb = blk_aio_writev(blk, sector_num, &io->iov, nsector + extra, cb, m->aiocb = blk_aio_writev(blk, (offset >> 9), &io->iov, (bytes >> 9),
io); cb, io);
} }
static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
@@ -244,19 +213,12 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
DBDMA_io *io = opaque; DBDMA_io *io = opaque;
MACIOIDEState *m = io->opaque; MACIOIDEState *m = io->opaque;
IDEState *s = idebus_active_if(&m->bus); IDEState *s = idebus_active_if(&m->bus);
int64_t sector_num; int64_t offset;
int nsector, remainder;
MACIO_DPRINTF("\ns is %p\n", s); MACIO_DPRINTF("pmac_ide_atapi_transfer_cb\n");
MACIO_DPRINTF("io_buffer_index: %x\n", s->io_buffer_index);
MACIO_DPRINTF("io_buffer_size: %x packet_transfer_size: %x\n",
s->io_buffer_size, s->packet_transfer_size);
MACIO_DPRINTF("lba: %x\n", s->lba);
MACIO_DPRINTF("io_addr: %" HWADDR_PRIx " io_len: %x\n", io->addr,
io->len);
if (ret < 0) { if (ret < 0) {
MACIO_DPRINTF("THERE WAS AN ERROR! %d\n", ret); MACIO_DPRINTF("DMA error: %d\n", ret);
ide_atapi_io_error(s, ret); ide_atapi_io_error(s, ret);
goto done; goto done;
} }
@@ -270,6 +232,7 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
} }
if (s->io_buffer_size <= 0) { if (s->io_buffer_size <= 0) {
MACIO_DPRINTF("End of IDE transfer\n");
ide_atapi_cmd_ok(s); ide_atapi_cmd_ok(s);
m->dma_active = false; m->dma_active = false;
goto done; goto done;
@@ -289,19 +252,13 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
goto done; goto done;
} }
/* Calculate number of sectors */ /* Calculate current offset */
sector_num = (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9); offset = (int64_t)(s->lba << 11) + s->io_buffer_index;
nsector = (io->len + 0x1ff) >> 9;
remainder = io->len & 0x1ff;
MACIO_DPRINTF("nsector: %d remainder: %x\n", nsector, remainder); pmac_dma_read(s->blk, offset, io->len, pmac_ide_atapi_transfer_cb, io);
MACIO_DPRINTF("sector: %"PRIx64" %zx\n", sector_num, io->iov.size / 512);
pmac_dma_read(s->blk, sector_num, nsector, pmac_ide_atapi_transfer_cb, io);
return; return;
done: done:
MACIO_DPRINTF("done DMA\n\n");
block_acct_done(blk_get_stats(s->blk), &s->acct); block_acct_done(blk_get_stats(s->blk), &s->acct);
io->dma_end(opaque); io->dma_end(opaque);
@@ -313,16 +270,14 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
DBDMA_io *io = opaque; DBDMA_io *io = opaque;
MACIOIDEState *m = io->opaque; MACIOIDEState *m = io->opaque;
IDEState *s = idebus_active_if(&m->bus); IDEState *s = idebus_active_if(&m->bus);
int64_t sector_num; int64_t offset;
int nsector, remainder;
MACIO_DPRINTF("pmac_ide_transfer_cb\n"); MACIO_DPRINTF("pmac_ide_transfer_cb\n");
if (ret < 0) { if (ret < 0) {
MACIO_DPRINTF("DMA error\n"); MACIO_DPRINTF("DMA error: %d\n", ret);
m->aiocb = NULL; m->aiocb = NULL;
ide_dma_error(s); ide_dma_error(s);
io->remainder_len = 0;
goto done; goto done;
} }
@@ -335,7 +290,7 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
} }
if (s->io_buffer_size <= 0) { if (s->io_buffer_size <= 0) {
MACIO_DPRINTF("end of transfer\n"); MACIO_DPRINTF("End of IDE transfer\n");
s->status = READY_STAT | SEEK_STAT; s->status = READY_STAT | SEEK_STAT;
ide_set_irq(s->bus); ide_set_irq(s->bus);
m->dma_active = false; m->dma_active = false;
@@ -348,24 +303,16 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
} }
/* Calculate number of sectors */ /* Calculate number of sectors */
sector_num = ide_get_sector(s) + (s->io_buffer_index >> 9); offset = (ide_get_sector(s) << 9) + s->io_buffer_index;
nsector = (io->len + 0x1ff) >> 9;
remainder = io->len & 0x1ff;
s->nsector -= nsector;
MACIO_DPRINTF("nsector: %d remainder: %x\n", nsector, remainder);
MACIO_DPRINTF("sector: %"PRIx64" %x\n", sector_num, nsector);
switch (s->dma_cmd) { switch (s->dma_cmd) {
case IDE_DMA_READ: case IDE_DMA_READ:
pmac_dma_read(s->blk, sector_num, nsector, pmac_ide_transfer_cb, io); pmac_dma_read(s->blk, offset, io->len, pmac_ide_transfer_cb, io);
break; break;
case IDE_DMA_WRITE: case IDE_DMA_WRITE:
pmac_dma_write(s->blk, sector_num, nsector, pmac_ide_transfer_cb, io); pmac_dma_write(s->blk, offset, io->len, pmac_ide_transfer_cb, io);
break; break;
case IDE_DMA_TRIM: case IDE_DMA_TRIM:
MACIO_DPRINTF("TRIM command issued!");
break; break;
} }
@@ -561,15 +508,12 @@ static void ide_dbdma_start(IDEDMA *dma, IDEState *s,
BlockCompletionFunc *cb) BlockCompletionFunc *cb)
{ {
MACIOIDEState *m = container_of(dma, MACIOIDEState, dma); MACIOIDEState *m = container_of(dma, MACIOIDEState, dma);
DBDMAState *dbdma = m->dbdma;
DBDMA_io *io;
int i;
s->io_buffer_index = 0; s->io_buffer_index = 0;
if (s->drive_kind == IDE_CD) { if (s->drive_kind == IDE_CD) {
s->io_buffer_size = s->packet_transfer_size; s->io_buffer_size = s->packet_transfer_size;
} else { } else {
s->io_buffer_size = s->nsector * 0x200; s->io_buffer_size = s->nsector * BDRV_SECTOR_SIZE;
} }
MACIO_DPRINTF("\n\n------------ IDE transfer\n"); MACIO_DPRINTF("\n\n------------ IDE transfer\n");
@@ -578,15 +522,6 @@ static void ide_dbdma_start(IDEDMA *dma, IDEState *s,
MACIO_DPRINTF("lba: %x size: %x\n", s->lba, s->io_buffer_size); MACIO_DPRINTF("lba: %x size: %x\n", s->lba, s->io_buffer_size);
MACIO_DPRINTF("-------------------------\n"); MACIO_DPRINTF("-------------------------\n");
for (i = 0; i < DBDMA_CHANNELS; i++) {
io = &dbdma->channels[i].io;
if (io->opaque == m) {
io->remainder_len = 0;
}
}
MACIO_DPRINTF("\n");
m->dma_active = true; m->dma_active = true;
DBDMA_kick(m->dbdma); DBDMA_kick(m->dbdma);
} }

View File

@@ -452,8 +452,6 @@ static const struct IDEDMAOps bmdma_ops = {
void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d) void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d)
{ {
qemu_irq *irq;
if (bus->dma == &bm->dma) { if (bus->dma == &bm->dma) {
return; return;
} }
@@ -461,8 +459,7 @@ void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d)
bm->dma.ops = &bmdma_ops; bm->dma.ops = &bmdma_ops;
bus->dma = &bm->dma; bus->dma = &bm->dma;
bm->irq = bus->irq; bm->irq = bus->irq;
irq = qemu_allocate_irqs(bmdma_irq, bm, 1); bus->irq = qemu_allocate_irq(bmdma_irq, bm, 0);
bus->irq = *irq;
bm->pci_dev = d; bm->pci_dev = d;
} }

View File

@@ -166,7 +166,7 @@ static void virtio_input_set_config(VirtIODevice *vdev,
virtio_notify_config(vdev); virtio_notify_config(vdev);
} }
static uint32_t virtio_input_get_features(VirtIODevice *vdev, uint32_t f) static uint64_t virtio_input_get_features(VirtIODevice *vdev, uint64_t f)
{ {
return f; return f;
} }

View File

@@ -11,6 +11,7 @@ common-obj-$(CONFIG_SLAVIO) += slavio_intctl.o
common-obj-$(CONFIG_IOAPIC) += ioapic_common.o common-obj-$(CONFIG_IOAPIC) += ioapic_common.o
common-obj-$(CONFIG_ARM_GIC) += arm_gic_common.o common-obj-$(CONFIG_ARM_GIC) += arm_gic_common.o
common-obj-$(CONFIG_ARM_GIC) += arm_gic.o common-obj-$(CONFIG_ARM_GIC) += arm_gic.o
common-obj-$(CONFIG_ARM_GIC) += arm_gicv2m.o
common-obj-$(CONFIG_OPENPIC) += openpic.o common-obj-$(CONFIG_OPENPIC) += openpic.o
obj-$(CONFIG_APIC) += apic.o apic_common.o obj-$(CONFIG_APIC) += apic.o apic_common.o

View File

@@ -370,13 +370,14 @@ static int apic_irq_pending(APICCommonState *s)
static void apic_update_irq(APICCommonState *s) static void apic_update_irq(APICCommonState *s)
{ {
CPUState *cpu; CPUState *cpu;
DeviceState *dev = (DeviceState *)s;
cpu = CPU(s->cpu); cpu = CPU(s->cpu);
if (!qemu_cpu_is_self(cpu)) { if (!qemu_cpu_is_self(cpu)) {
cpu_interrupt(cpu, CPU_INTERRUPT_POLL); cpu_interrupt(cpu, CPU_INTERRUPT_POLL);
} else if (apic_irq_pending(s) > 0) { } else if (apic_irq_pending(s) > 0) {
cpu_interrupt(cpu, CPU_INTERRUPT_HARD); cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
} else if (!apic_accept_pic_intr(&s->busdev.qdev) || !pic_get_output(isa_pic)) { } else if (!apic_accept_pic_intr(dev) || !pic_get_output(isa_pic)) {
cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD); cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
} }
} }
@@ -549,10 +550,12 @@ static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode,
static bool apic_check_pic(APICCommonState *s) static bool apic_check_pic(APICCommonState *s)
{ {
if (!apic_accept_pic_intr(&s->busdev.qdev) || !pic_get_output(isa_pic)) { DeviceState *dev = (DeviceState *)s;
if (!apic_accept_pic_intr(dev) || !pic_get_output(isa_pic)) {
return false; return false;
} }
apic_deliver_pic_intr(&s->busdev.qdev, 1); apic_deliver_pic_intr(dev, 1);
return true; return true;
} }

192
hw/intc/arm_gicv2m.c Normal file
View File

@@ -0,0 +1,192 @@
/*
* GICv2m extension for MSI/MSI-x support with a GICv2-based system
*
* Copyright (C) 2015 Linaro, All rights reserved.
*
* Author: Christoffer Dall <christoffer.dall@linaro.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
/* This file implements an emulated GICv2m widget as described in the ARM
* Server Base System Architecture (SBSA) specification Version 2.2
* (ARM-DEN-0029 v2.2) pages 35-39 without any optional implementation defined
* identification registers and with a single non-secure MSI register frame.
*/
#include "hw/sysbus.h"
#include "hw/pci/msi.h"
#define TYPE_ARM_GICV2M "arm-gicv2m"
#define ARM_GICV2M(obj) OBJECT_CHECK(ARMGICv2mState, (obj), TYPE_ARM_GICV2M)
#define GICV2M_NUM_SPI_MAX 128
#define V2M_MSI_TYPER 0x008
#define V2M_MSI_SETSPI_NS 0x040
#define V2M_MSI_IIDR 0xFCC
#define V2M_IIDR0 0xFD0
#define V2M_IIDR11 0xFFC
#define PRODUCT_ID_QEMU 0x51 /* ASCII code Q */
typedef struct ARMGICv2mState {
SysBusDevice parent_obj;
MemoryRegion iomem;
qemu_irq spi[GICV2M_NUM_SPI_MAX];
uint32_t base_spi;
uint32_t num_spi;
} ARMGICv2mState;
static void gicv2m_set_irq(void *opaque, int irq)
{
ARMGICv2mState *s = (ARMGICv2mState *)opaque;
qemu_irq_pulse(s->spi[irq]);
}
static uint64_t gicv2m_read(void *opaque, hwaddr offset,
unsigned size)
{
ARMGICv2mState *s = (ARMGICv2mState *)opaque;
uint32_t val;
if (size != 4) {
qemu_log_mask(LOG_GUEST_ERROR, "gicv2m_read: bad size %u\n", size);
return 0;
}
switch (offset) {
case V2M_MSI_TYPER:
val = (s->base_spi + 32) << 16;
val |= s->num_spi;
return val;
case V2M_MSI_IIDR:
/* We don't have any valid implementor so we leave that field as zero
* and we return 0 in the arch revision as per the spec.
*/
return (PRODUCT_ID_QEMU << 20);
case V2M_IIDR0 ... V2M_IIDR11:
/* We do not implement any optional identification registers and the
* mandatory MSI_PIDR2 register reads as 0x0, so we capture all
* implementation defined registers here.
*/
return 0;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"gicv2m_read: Bad offset %x\n", (int)offset);
return 0;
}
}
static void gicv2m_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
ARMGICv2mState *s = (ARMGICv2mState *)opaque;
if (size != 2 && size != 4) {
qemu_log_mask(LOG_GUEST_ERROR, "gicv2m_write: bad size %u\n", size);
return;
}
switch (offset) {
case V2M_MSI_SETSPI_NS: {
int spi;
spi = (value & 0x3ff) - (s->base_spi + 32);
if (spi >= 0 && spi < s->num_spi) {
gicv2m_set_irq(s, spi);
}
return;
}
default:
qemu_log_mask(LOG_GUEST_ERROR,
"gicv2m_write: Bad offset %x\n", (int)offset);
}
}
static const MemoryRegionOps gicv2m_ops = {
.read = gicv2m_read,
.write = gicv2m_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static void gicv2m_realize(DeviceState *dev, Error **errp)
{
ARMGICv2mState *s = ARM_GICV2M(dev);
int i;
if (s->num_spi > GICV2M_NUM_SPI_MAX) {
error_setg(errp,
"requested %u SPIs exceeds GICv2m frame maximum %d",
s->num_spi, GICV2M_NUM_SPI_MAX);
return;
}
if (s->base_spi + 32 > 1020 - s->num_spi) {
error_setg(errp,
"requested base SPI %u+%u exceeds max. number 1020",
s->base_spi + 32, s->num_spi);
return;
}
for (i = 0; i < s->num_spi; i++) {
sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->spi[i]);
}
msi_supported = true;
kvm_gsi_direct_mapping = true;
kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
}
static void gicv2m_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
ARMGICv2mState *s = ARM_GICV2M(obj);
memory_region_init_io(&s->iomem, OBJECT(s), &gicv2m_ops, s,
"gicv2m", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
}
static Property gicv2m_properties[] = {
DEFINE_PROP_UINT32("base-spi", ARMGICv2mState, base_spi, 0),
DEFINE_PROP_UINT32("num-spi", ARMGICv2mState, num_spi, 64),
DEFINE_PROP_END_OF_LIST(),
};
static void gicv2m_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->props = gicv2m_properties;
dc->realize = gicv2m_realize;
}
static const TypeInfo gicv2m_info = {
.name = TYPE_ARM_GICV2M,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ARMGICv2mState),
.instance_init = gicv2m_init,
.class_init = gicv2m_class_init,
};
static void gicv2m_register_types(void)
{
type_register_static(&gicv2m_info);
}
type_init(gicv2m_register_types)

View File

@@ -213,9 +213,6 @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
uint32_t grp, bit, irq_id, n; uint32_t grp, bit, irq_id, n;
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) { for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
s->ext_combiner_irq[n]);
irq_id = 0; irq_id = 0;
if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) || if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) { n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
@@ -230,8 +227,10 @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
if (irq_id) { if (irq_id) {
s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n], s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
s->ext_gic_irq[irq_id-32]); s->ext_gic_irq[irq_id-32]);
} else {
s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
s->ext_combiner_irq[n]);
} }
} }
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) { for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
/* these IDs are passed to Internal Combiner and External GIC */ /* these IDs are passed to Internal Combiner and External GIC */

View File

@@ -65,7 +65,6 @@ static void i82378_realize(PCIDevice *pci, Error **errp)
uint8_t *pci_conf; uint8_t *pci_conf;
ISABus *isabus; ISABus *isabus;
ISADevice *isa; ISADevice *isa;
qemu_irq *out0_irq;
pci_conf = pci->config; pci_conf = pci->config;
pci_set_word(pci_conf + PCI_COMMAND, pci_set_word(pci_conf + PCI_COMMAND,
@@ -88,11 +87,9 @@ static void i82378_realize(PCIDevice *pci, Error **errp)
All devices accept byte access only, except timer All devices accept byte access only, except timer
*/ */
/* Workaround the fact that i8259 is not qdev'ified... */
out0_irq = qemu_allocate_irqs(i82378_request_out0_irq, s, 1);
/* 2 82C59 (irq) */ /* 2 82C59 (irq) */
s->i8259 = i8259_init(isabus, *out0_irq); s->i8259 = i8259_init(isabus,
qemu_allocate_irq(i82378_request_out0_irq, s, 0));
isa_bus_irqs(isabus, s->i8259); isa_bus_irqs(isabus, s->i8259);
/* 1 82C54 (pit) */ /* 1 82C54 (pit) */

View File

@@ -21,6 +21,7 @@
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "hw/isa/isa.h" #include "hw/isa/isa.h"
#include "hw/i386/pc.h"
static ISABus *isabus; static ISABus *isabus;
@@ -267,3 +268,28 @@ MemoryRegion *isa_address_space_io(ISADevice *dev)
} }
type_init(isabus_register_types) type_init(isabus_register_types)
static void parallel_init(ISABus *bus, int index, CharDriverState *chr)
{
DeviceState *dev;
ISADevice *isadev;
isadev = isa_create(bus, "isa-parallel");
dev = DEVICE(isadev);
qdev_prop_set_uint32(dev, "index", index);
qdev_prop_set_chr(dev, "chardev", chr);
qdev_init_nofail(dev);
}
void parallel_hds_isa_init(ISABus *bus, int n)
{
int i;
assert(n <= MAX_PARALLEL_PORTS);
for (i = 0; i < n; i++) {
if (parallel_hds[i]) {
parallel_init(bus, i, parallel_hds[i]);
}
}
}

View File

@@ -360,11 +360,8 @@ static void ich9_set_sci(void *opaque, int irq_num, int level)
void ich9_lpc_pm_init(PCIDevice *lpc_pci) void ich9_lpc_pm_init(PCIDevice *lpc_pci)
{ {
ICH9LPCState *lpc = ICH9_LPC_DEVICE(lpc_pci); ICH9LPCState *lpc = ICH9_LPC_DEVICE(lpc_pci);
qemu_irq *sci_irq;
sci_irq = qemu_allocate_irqs(ich9_set_sci, lpc, 1);
ich9_pm_init(lpc_pci, &lpc->pm, sci_irq[0]);
ich9_pm_init(lpc_pci, &lpc->pm, qemu_allocate_irq(ich9_set_sci, lpc, 0));
ich9_lpc_reset(&lpc->d.qdev); ich9_lpc_reset(&lpc->d.qdev);
} }
@@ -410,12 +407,28 @@ static void ich9_lpc_rcba_update(ICH9LPCState *lpc, uint32_t rbca_old)
} }
} }
/* config:GEN_PMCON* */
static void
ich9_lpc_pmcon_update(ICH9LPCState *lpc)
{
uint16_t gen_pmcon_1 = pci_get_word(lpc->d.config + ICH9_LPC_GEN_PMCON_1);
uint16_t wmask;
if (gen_pmcon_1 & ICH9_LPC_GEN_PMCON_1_SMI_LOCK) {
wmask = pci_get_word(lpc->d.wmask + ICH9_LPC_GEN_PMCON_1);
wmask &= ~ICH9_LPC_GEN_PMCON_1_SMI_LOCK;
pci_set_word(lpc->d.wmask + ICH9_LPC_GEN_PMCON_1, wmask);
lpc->pm.smi_en_wmask &= ~1;
}
}
static int ich9_lpc_post_load(void *opaque, int version_id) static int ich9_lpc_post_load(void *opaque, int version_id)
{ {
ICH9LPCState *lpc = opaque; ICH9LPCState *lpc = opaque;
ich9_lpc_pmbase_update(lpc); ich9_lpc_pmbase_update(lpc);
ich9_lpc_rcba_update(lpc, 0 /* disabled ICH9_LPC_RBCA_EN */); ich9_lpc_rcba_update(lpc, 0 /* disabled ICH9_LPC_RBCA_EN */);
ich9_lpc_pmcon_update(lpc);
return 0; return 0;
} }
@@ -438,6 +451,9 @@ static void ich9_lpc_config_write(PCIDevice *d,
if (ranges_overlap(addr, len, ICH9_LPC_PIRQE_ROUT, 4)) { if (ranges_overlap(addr, len, ICH9_LPC_PIRQE_ROUT, 4)) {
pci_bus_fire_intx_routing_notifier(lpc->d.bus); pci_bus_fire_intx_routing_notifier(lpc->d.bus);
} }
if (ranges_overlap(addr, len, ICH9_LPC_GEN_PMCON_1, 8)) {
ich9_lpc_pmcon_update(lpc);
}
} }
static void ich9_lpc_reset(DeviceState *qdev) static void ich9_lpc_reset(DeviceState *qdev)
@@ -494,7 +510,7 @@ static void ich9_lpc_machine_ready(Notifier *n, void *opaque)
/* lpt */ /* lpt */
pci_conf[0x82] |= 0x04; pci_conf[0x82] |= 0x04;
} }
if (memory_region_present(io_as, 0x3f0)) { if (memory_region_present(io_as, 0x3f2)) {
/* floppy */ /* floppy */
pci_conf[0x82] |= 0x08; pci_conf[0x82] |= 0x08;
} }

View File

@@ -356,7 +356,7 @@ static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp)
acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io); acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io); acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
acpi_pm1_cnt_init(&s->ar, &s->io, 2); acpi_pm1_cnt_init(&s->ar, &s->io, false, false, 2);
} }
I2CBus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, I2CBus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,

View File

@@ -78,7 +78,7 @@ static void lm32_evr_init(MachineState *machine)
DriveInfo *dinfo; DriveInfo *dinfo;
MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *phys_ram = g_new(MemoryRegion, 1); MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
qemu_irq *cpu_irq, irq[32]; qemu_irq irq[32];
ResetInfo *reset_info; ResetInfo *reset_info;
int i; int i;
@@ -123,8 +123,7 @@ static void lm32_evr_init(MachineState *machine)
1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1); 1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
/* create irq lines */ /* create irq lines */
cpu_irq = qemu_allocate_irqs(cpu_irq_handler, cpu, 1); env->pic_state = lm32_pic_init(qemu_allocate_irq(cpu_irq_handler, cpu, 0));
env->pic_state = lm32_pic_init(*cpu_irq);
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
irq[i] = qdev_get_gpio_in(env->pic_state, i); irq[i] = qdev_get_gpio_in(env->pic_state, i);
} }
@@ -173,7 +172,7 @@ static void lm32_uclinux_init(MachineState *machine)
DriveInfo *dinfo; DriveInfo *dinfo;
MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *phys_ram = g_new(MemoryRegion, 1); MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
qemu_irq *cpu_irq, irq[32]; qemu_irq irq[32];
HWSetup *hw; HWSetup *hw;
ResetInfo *reset_info; ResetInfo *reset_info;
int i; int i;
@@ -225,8 +224,7 @@ static void lm32_uclinux_init(MachineState *machine)
1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1); 1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
/* create irq lines */ /* create irq lines */
cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1); env->pic_state = lm32_pic_init(qemu_allocate_irq(cpu_irq_handler, env, 0));
env->pic_state = lm32_pic_init(*cpu_irq);
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
irq[i] = qdev_get_gpio_in(env->pic_state, i); irq[i] = qdev_get_gpio_in(env->pic_state, i);
} }

View File

@@ -86,7 +86,7 @@ milkymist_init(MachineState *machine)
DriveInfo *dinfo; DriveInfo *dinfo;
MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *phys_sdram = g_new(MemoryRegion, 1); MemoryRegion *phys_sdram = g_new(MemoryRegion, 1);
qemu_irq irq[32], *cpu_irq; qemu_irq irq[32];
int i; int i;
char *bios_filename; char *bios_filename;
ResetInfo *reset_info; ResetInfo *reset_info;
@@ -130,8 +130,7 @@ milkymist_init(MachineState *machine)
2, 0x00, 0x89, 0x00, 0x1d, 1); 2, 0x00, 0x89, 0x00, 0x1d, 1);
/* create irq lines */ /* create irq lines */
cpu_irq = qemu_allocate_irqs(cpu_irq_handler, cpu, 1); env->pic_state = lm32_pic_init(qemu_allocate_irq(cpu_irq_handler, cpu, 0));
env->pic_state = lm32_pic_init(*cpu_irq);
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
irq[i] = qdev_get_gpio_in(env->pic_state, i); irq[i] = qdev_get_gpio_in(env->pic_state, i);
} }

View File

@@ -211,7 +211,6 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
uint64_t address_space_end = address_space_start + address_space_size; uint64_t address_space_end = address_space_start + address_space_size;
g_assert(QEMU_ALIGN_UP(address_space_start, align) == address_space_start); g_assert(QEMU_ALIGN_UP(address_space_start, align) == address_space_start);
g_assert(QEMU_ALIGN_UP(address_space_size, align) == address_space_size);
if (!address_space_size) { if (!address_space_size) {
error_setg(errp, "memory hotplug is not enabled, " error_setg(errp, "memory hotplug is not enabled, "

View File

@@ -1161,7 +1161,7 @@ void mips_malta_init(MachineState *machine)
pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1); pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci"); pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci");
smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
isa_get_irq(NULL, 9), NULL, 0, NULL, NULL); isa_get_irq(NULL, 9), NULL, 0, NULL);
smbus_eeprom_init(smbus, 8, smbus_eeprom_buf, smbus_eeprom_size); smbus_eeprom_init(smbus, 8, smbus_eeprom_buf, smbus_eeprom_size);
g_free(smbus_eeprom_buf); g_free(smbus_eeprom_buf);
pit = pit_init(isa_bus, 0x40, 0, NULL); pit = pit_init(isa_bus, 0x40, 0, NULL);

View File

@@ -126,17 +126,18 @@ static void macio_bar_setup(MacIOState *macio_state)
} }
} }
static int macio_common_initfn(PCIDevice *d) static void macio_common_realize(PCIDevice *d, Error **errp)
{ {
MacIOState *s = MACIO(d); MacIOState *s = MACIO(d);
SysBusDevice *sysbus_dev; SysBusDevice *sysbus_dev;
int ret; Error *err = NULL;
d->config[0x3d] = 0x01; // interrupt on pin 1 d->config[0x3d] = 0x01; // interrupt on pin 1
ret = qdev_init(DEVICE(&s->cuda)); object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err);
if (ret < 0) { if (err) {
return ret; error_propagate(errp, err);
return;
} }
sysbus_dev = SYS_BUS_DEVICE(&s->cuda); sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
memory_region_add_subregion(&s->bar, 0x16000, memory_region_add_subregion(&s->bar, 0x16000,
@@ -144,12 +145,11 @@ static int macio_common_initfn(PCIDevice *d)
macio_bar_setup(s); macio_bar_setup(s);
pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar); pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar);
return 0;
} }
static int macio_initfn_ide(MacIOState *s, MACIOIDEState *ide, qemu_irq irq0, static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide,
qemu_irq irq1, int dmaid) qemu_irq irq0, qemu_irq irq1, int dmaid,
Error **errp)
{ {
SysBusDevice *sysbus_dev; SysBusDevice *sysbus_dev;
@@ -157,27 +157,31 @@ static int macio_initfn_ide(MacIOState *s, MACIOIDEState *ide, qemu_irq irq0,
sysbus_connect_irq(sysbus_dev, 0, irq0); sysbus_connect_irq(sysbus_dev, 0, irq0);
sysbus_connect_irq(sysbus_dev, 1, irq1); sysbus_connect_irq(sysbus_dev, 1, irq1);
macio_ide_register_dma(ide, s->dbdma, dmaid); macio_ide_register_dma(ide, s->dbdma, dmaid);
return qdev_init(DEVICE(ide)); object_property_set_bool(OBJECT(ide), true, "realized", errp);
} }
static int macio_oldworld_initfn(PCIDevice *d) static void macio_oldworld_realize(PCIDevice *d, Error **errp)
{ {
MacIOState *s = MACIO(d); MacIOState *s = MACIO(d);
OldWorldMacIOState *os = OLDWORLD_MACIO(d); OldWorldMacIOState *os = OLDWORLD_MACIO(d);
Error *err = NULL;
SysBusDevice *sysbus_dev; SysBusDevice *sysbus_dev;
int i; int i;
int cur_irq = 0; int cur_irq = 0;
int ret = macio_common_initfn(d);
if (ret < 0) { macio_common_realize(d, &err);
return ret; if (err) {
error_propagate(errp, err);
return;
} }
sysbus_dev = SYS_BUS_DEVICE(&s->cuda); sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]); sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]);
ret = qdev_init(DEVICE(&os->nvram)); object_property_set_bool(OBJECT(&os->nvram), true, "realized", &err);
if (ret < 0) { if (err) {
return ret; error_propagate(errp, err);
return;
} }
sysbus_dev = SYS_BUS_DEVICE(&os->nvram); sysbus_dev = SYS_BUS_DEVICE(&os->nvram);
memory_region_add_subregion(&s->bar, 0x60000, memory_region_add_subregion(&s->bar, 0x60000,
@@ -194,13 +198,12 @@ static int macio_oldworld_initfn(PCIDevice *d)
qemu_irq irq0 = os->irqs[cur_irq++]; qemu_irq irq0 = os->irqs[cur_irq++];
qemu_irq irq1 = os->irqs[cur_irq++]; qemu_irq irq1 = os->irqs[cur_irq++];
ret = macio_initfn_ide(s, &os->ide[i], irq0, irq1, 0x16 + (i * 4)); macio_realize_ide(s, &os->ide[i], irq0, irq1, 0x16 + (i * 4), &err);
if (ret < 0) { if (err) {
return ret; error_propagate(errp, err);
return;
} }
} }
return 0;
} }
static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, size_t ide_size, static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, size_t ide_size,
@@ -268,17 +271,20 @@ static const MemoryRegionOps timer_ops = {
.endianness = DEVICE_LITTLE_ENDIAN, .endianness = DEVICE_LITTLE_ENDIAN,
}; };
static int macio_newworld_initfn(PCIDevice *d) static void macio_newworld_realize(PCIDevice *d, Error **errp)
{ {
MacIOState *s = MACIO(d); MacIOState *s = MACIO(d);
NewWorldMacIOState *ns = NEWWORLD_MACIO(d); NewWorldMacIOState *ns = NEWWORLD_MACIO(d);
Error *err = NULL;
SysBusDevice *sysbus_dev; SysBusDevice *sysbus_dev;
MemoryRegion *timer_memory = NULL; MemoryRegion *timer_memory = NULL;
int i; int i;
int cur_irq = 0; int cur_irq = 0;
int ret = macio_common_initfn(d);
if (ret < 0) { macio_common_realize(d, &err);
return ret; if (err) {
error_propagate(errp, err);
return;
} }
sysbus_dev = SYS_BUS_DEVICE(&s->cuda); sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
@@ -294,9 +300,10 @@ static int macio_newworld_initfn(PCIDevice *d)
qemu_irq irq0 = ns->irqs[cur_irq++]; qemu_irq irq0 = ns->irqs[cur_irq++];
qemu_irq irq1 = ns->irqs[cur_irq++]; qemu_irq irq1 = ns->irqs[cur_irq++];
ret = macio_initfn_ide(s, &ns->ide[i], irq0, irq1, 0x16 + (i * 4)); macio_realize_ide(s, &ns->ide[i], irq0, irq1, 0x16 + (i * 4), &err);
if (ret < 0) { if (err) {
return ret; error_propagate(errp, err);
return;
} }
} }
@@ -305,8 +312,6 @@ static int macio_newworld_initfn(PCIDevice *d)
memory_region_init_io(timer_memory, OBJECT(s), &timer_ops, NULL, "timer", memory_region_init_io(timer_memory, OBJECT(s), &timer_ops, NULL, "timer",
0x1000); 0x1000);
memory_region_add_subregion(&s->bar, 0x15000, timer_memory); memory_region_add_subregion(&s->bar, 0x15000, timer_memory);
return 0;
} }
static void macio_newworld_init(Object *obj) static void macio_newworld_init(Object *obj)
@@ -352,7 +357,7 @@ static void macio_oldworld_class_init(ObjectClass *oc, void *data)
PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc); PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
DeviceClass *dc = DEVICE_CLASS(oc); DeviceClass *dc = DEVICE_CLASS(oc);
pdc->init = macio_oldworld_initfn; pdc->realize = macio_oldworld_realize;
pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201; pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201;
dc->vmsd = &vmstate_macio_oldworld; dc->vmsd = &vmstate_macio_oldworld;
} }
@@ -372,7 +377,7 @@ static void macio_newworld_class_init(ObjectClass *oc, void *data)
PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc); PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
DeviceClass *dc = DEVICE_CLASS(oc); DeviceClass *dc = DEVICE_CLASS(oc);
pdc->init = macio_newworld_initfn; pdc->realize = macio_newworld_realize;
pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL; pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL;
dc->vmsd = &vmstate_macio_newworld; dc->vmsd = &vmstate_macio_newworld;
} }

Some files were not shown because too many files have changed in this diff Show More