Compare commits

..

45 Commits

Author SHA1 Message Date
Martin Wilck
bb49963e7a qemu-binfmt-conf.sh: allow overriding SUSE-specific argv[0] handling
Git-commit: 0000000000000000000000000000000000000000
References: bsc#1186256

Since abbc0ce ("qemu-binfmt-conf: use qemu-ARCH-binfmt"),
qemu-binfmt-conf.sh automatically replaces the default qemu binfmt wrapper
qemu-$ARCH with qemu-$ARCH-binfmt in order to ensure that argv[0] is
preserved; qemu-$ARCH-binfmt is a link to qemu-binfmt, which is just a
simple wrapper that mangles argv to achieve the desired result.

This is inconvenient in some situations. In particular for running
foreign-arch containers, it's useful to use the binfmt_misc "F" ("fix
binary") flag to pre-load the qemu wrapper in the kernel. That way,
foreign-arch containers can be run just like native containers, without
having to bind-mount interpreters into the container. But that's impossible
with the SUSE binfmt wrapper that needs to exec() a different (native)
executable.

As the qemu-binfmt-conf script supports the --qemu-suffix option anyway,
use it to set the "-binfmt" suffix, thus allowing admins to override the
SUSE default with the option "--qemu-suffix ''".

Signed-off-by: Martin Wilck <mwilck@suse.com>
Acked-by: Jose R Ziviani <jose.ziviani@suse.com>
2021-08-27 14:09:34 -03:00
Bruce Rogers
eb0b8351b3 doc: add our support doc to the main project doc for x86 and s390x
Include-If: %if %{legacy_qemu_kvm}

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
eb550cfa27 qom: handle case of chardev-spice module unavailability
When qemu is built with modules, but a given module doesn't load
qemu should handle that gracefully. When chardev-spice.so isn't
able to be loaded and qemu is invoked with -display spice-app,
qemu will reach an abort call. Explicitly detect these conditions
and error out in a normal way before we reach the abort.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
eff1edaa6e usb: Help compiler out to avoid a warning on x86 compilation
Include-If: %ifarch %arm %ix86 ppc

There is an assert present which already should give the compiler
enough information about the value of i as used in the snprintf,
but if I remember right, for x86, because memory is tighter some of
the compiler smarts are turned off, so we get the uninformed warning
there and not on other archs. So on x86 only we'll add some code to
help the compiler out, so we can again compile qemu with
--enable-werror.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
bc79800b52 roms/Makefile: add --cross-file to qboot meson setup for aarch64
Include-If: %ifarch aarch64

We conditionally add a --cross-file reference so that we can do
cross compilation of qboot from an aarch64 build.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
450581fbe9 Makefile: Don't check pc-bios as pre-requisite for config-host.mak
This check isn't needed when we know this is a fresh build, which of
course it is when we are building the qemu packages.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
fa25473a51 Revert "roms/efirom, tests/uefi-test-tools: update edk2's own submodules first"
This reverts commit ec87b5daca.

No need. In our build system submodules are checked out.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
e27c27d1fc meson: install ivshmem-client and ivshmem-server
Turn on the meson install flag for these executables

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
3c23642c50 qht: Revert some constification in qht.c
This change partially addresses https://bugs.launchpad.net/qemu/+bug/1886155
where a pre-release gcc 11 warns about const qualifier abuse.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
86477c4d87 Revert "qht: constify qht_statistics_init"
This reverts commit 6579f10779.

This change partially addresses https://bugs.launchpad.net/qemu/+bug/1886155
where a pre-release gcc 11 warns about const qualifier abuse.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
61a9dcd6d6 configure: remove $pkgversion from CONFIG_STAMP input to broaden compatibility
As part of the effort to close the gap with Leap I think we are fine
removing the $pkgversion component to creating a unique CONFIG_STAMP.
This stamp is only used in creating a unique symbol used in ensuring the
dynamically loaded modules correspond correctly to the loading qemu.
The default inputs to producing this unique symbol are somewhat reasonable
as a generic mechanism, but specific packaging and maintenance practices
might require the default to be modified for best use. This is an example
of that.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
8f8e36578c test: add mapping from arch of i686 to qemu_arch=i386
While we don't specifically set QEMU_PROG, the code which detects the
host architecture needs a little help mapping the output of uname -m to
what the qemu project uses to reference that architecture.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
6a1fd511e7 roms: change cross compiler naming to be suse specific
Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
ed800d77f9 pc-bios/s390-ccw/net: avoid warning about packed structure members
This is hopefully temporary. Simply disable the warning about taking
the address of packed structure members which is new in gcc9.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
64a33bde90 configure: only populate roms if softmmu
Currently roms are mistakenly getting built in a linux-user only
configuration. Add check for softmmu in all places where our list of
roms is being added to.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
bd75213aab hw/intc/exynos4210_gic: provide more room when formatting alias names
sprintf related parameter validation complains about the size of the
buffer being written to in exynos4210_gic_realize(). Provide a bit more
space to avoid the following warning:
/home/abuild/rpmbuild/BUILD/qemu-4.0.0/hw/intc/exynos4210_gic.c: In function 'exynos4210_gic_realize':
/home/abuild/rpmbuild/BUILD/qemu-4.0.0/hw/intc/exynos4210_gic.c:316:36: error: '%x' directive writing between 1 and 7 bytes into a region of size between 4 and 28 [-Werror=format-overflow=]
  316 |         sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
      |                                    ^~
/home/abuild/rpmbuild/BUILD/qemu-4.0.0/hw/intc/exynos4210_gic.c:316:33: note: directive argument in the range [0, 29020050]
  316 |         sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
      |                                 ^~~~~~
In file included from /usr/include/stdio.h:867,
                 from /home/abuild/rpmbuild/BUILD/qemu-4.0.0/include/qemu/osdep.h:99,
                 from /home/abuild/rpmbuild/BUILD/qemu-4.0.0/hw/intc/exynos4210_gic.c:23:
/usr/include/bits/stdio2.h:36:10: note: '__builtin___sprintf_chk' output between 2 and 32 bytes into a destination of size 28
   36 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   37 |       __bos (__s), __fmt, __va_arg_pack ());
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/abuild/rpmbuild/BUILD/qemu-4.0.0/hw/intc/exynos4210_gic.c:326:37: error: '%x' directive writing between 1 and 7 bytes into a region of size between 3 and 28 [-Werror=format-overflow=]
  326 |         sprintf(dist_alias_name, "%s%x", dist_prefix, i);
      |                                     ^~
/home/abuild/rpmbuild/BUILD/qemu-4.0.0/hw/intc/exynos4210_gic.c:326:34: note: directive argument in the range [0, 29020050]
  326 |         sprintf(dist_alias_name, "%s%x", dist_prefix, i);
      |                                  ^~~~~~
In file included from /usr/include/stdio.h:867,
                 from /home/abuild/rpmbuild/BUILD/qemu-4.0.0/include/qemu/osdep.h:99,
                 from /home/abuild/rpmbuild/BUILD/qemu-4.0.0/hw/intc/exynos4210_gic.c:23:
/usr/include/bits/stdio2.h:36:10: note: '__builtin___sprintf_chk' output between 2 and 33 bytes into a destination of size 28
   36 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   37 |       __bos (__s), __fmt, __va_arg_pack ());
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
d696bc43f4 tests: change error message in test 162
Since we have a quite restricted execution environment, as far as
networking is concerned, we need to change the error message we expect
in test 162. There is actually no routing set up so the error we get is
"Network is unreachable". Change the expected output accordingly.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Olaf Hering
faec9bd571 xen: ignore live parameter from xen-save-devices-state
References: bsc#1079730, bsc#1101982, bsc#1063993

The final step of xl migrate|save for an HVM domU is saving the state of
qemu. This also involves releasing all block devices. While releasing
backends ought to be a separate step, such functionality is not
implemented.

Unfortunately, releasing the block devices depends on the optional
'live' option. This breaks offline migration with 'virsh migrate domU
dom0' because the sending side does not release the disks, as a result
the receiving side can not properly claim write access to the disks.

As a minimal fix, remove the dependency on the 'live' option. Upstream
may fix this in a different way, like removing the newly added 'live'
parameter entirely.

Fixes: 5d6c599fe1 ("migration, xen: Fix block image lock issue on live migration")

Signed-off-by: Olaf Hering <olaf@aepfle.de>
Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
545d9ba686 tests: Fix block tests to be compatible with membarrier configuration
The use of membarriers collides with the block test's practice of
SIGKILLing test vm's. Have them quit politely. Tests: 130, 153 - and
though test 161 seems to have the same issue, it is not yet fixed, but
just marked here as possibly needing a fix.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
3f88874b73 tests/qemu-iotests: Triple timeout of i/o tests due to obs environment
Executing tests in obs is very fickle, since you aren't guaranteed
reliable cpu time. Triple the timeout for each test to help ensure
we don't fail a test because the stars align against us.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
7c080edff1 xen: add block resize support for xen disks
Provide monitor naming of xen disks, and plumb guest driver
notification through xenstore of resizing instigated via the
monitor.

[BR: minor edits to pass qemu's checkpatch script]
[BR: significant rework needed due to upstream xen disk qdevification]
[BR: At this point, monitor_add_blk call is all we need to add!]
Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
462c886b82 hw/smbios: handle both file formats regardless of machine type
References: bsc#994082, bsc#1084316, boo#1131894

It's easy enough to handle either per-spec or legacy smbios structures
in the smbios file input without regard to the machine type used, by
simply applying the basic smbios formatting rules. then depending on
what is detected. terminal numm bytes are added or removed for machine
type specific processing.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
c2b57e3310 Make installed scripts explicitly python3
References: bsc#1077564

We want to explicitly reference python3 in the scripts we install.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Andreas Färber
3f6a29c5f1 acpi_piix4: Fix migration from SLE11 SP2
References: bnc#812836

qemu-kvm 0.15 uses the same GPE format as qemu 1.4, but as version 2
rather than 3.

Signed-off-by: Andreas Färber <afaerber@suse.de>
2021-08-26 00:25:35 -03:00
Andreas Färber
28357266e7 i8254: Fix migration from SLE11 SP2
References: bnc#812836

qemu-kvm 0.15 had a VMSTATE_UINT32(flags, PITState) field that
qemu 1.4 does not have.

Signed-off-by: Andreas Färber <afaerber@suse.de>
2021-08-26 00:25:35 -03:00
Bruce Rogers
da746bd16f increase x86_64 physical bits to 42
Allow for guests with higher amounts of ram. The current thought
is that 2TB specified on qemu commandline would be an appropriate
limit. Note that this requires the next higher bit value since
the highest address is actually more than 2TB due to the pci
memory hole.

Signed-off-by: Bruce Rogers <brogers@suse.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2021-08-26 00:25:35 -03:00
Andreas Färber
aa068b36b8 Raise soft address space limit to hard limit
For SLES we want users to be able to use large memory configurations
with KVM without fiddling with ulimit -Sv.

Signed-off-by: Andreas Färber <afaerber@suse.de>
[BR: add include for sys/resource.h]
Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Bruce Rogers
60f574d90d roms/Makefile: pass a packaging timestamp to subpackages with date info
References: bsc#1011213

Certain rom subpackages build from qemu git-submodules call the date
program to include date information in the packaged binaries. This
causes repeated builds of the package to be different, wkere the only
real difference is due to the fact that time build timestamp has
changed. To promote reproducible builds and avoid customers being
prompted to update packages needlessly, we'll use the timestamp of the
VERSION file as the packaging timestamp for all packages that build in a
timestamp for whatever reason.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
49a58be1c5 qemu-binfmt-conf: use qemu-ARCH-binfmt
Signed-off-by: Andreas Schwab <schwab@suse.de>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2021-08-26 00:25:35 -03:00
Bruce Rogers
925bacc65a qemu-bridge-helper: reduce security profile
References: boo#988279

Change from using glib alloc and free routines to those
from libc. Also perform safety measure of dropping privs
to user if configured no-caps.

Signed-off-by: Bruce Rogers <brogers@suse.com>
[AF: Rebased for v2.7.0-rc2]
Signed-off-by: Andreas Färber <afaerber@suse.de>
2021-08-26 00:25:35 -03:00
Bruce Rogers
54773d64dd xen_disk: Add suse specific flush disable handling and map to QEMU equiv
Add code to read the suse specific suse-diskcache-disable-flush flag out
of xenstore, and set the equivalent flag within QEMU.

Patch taken from Xen's patch queue, Olaf Hering being the original author.
[bsc#879425]

[BR: minor edits to pass qemu's checkpatch script]
[BR: With qdevification of xen-block, code has changed significantly]
Signed-off-by: Bruce Rogers <brogers@suse.com>
Signed-off-by: Olaf Hering <olaf@aepfle.de>
2021-08-26 00:25:35 -03:00
Alexander Graf
57e20eba3e AIO: Reduce number of threads for 32bit hosts
On hosts with limited virtual address space (32bit pointers), we can very
easily run out of virtual memory with big thread pools.

Instead, we should limit ourselves to small pools to keep memory footprint
low on those systems.

This patch fixes random VM stalls like

  (process:25114): GLib-ERROR **: gmem.c:103: failed to allocate 1048576 bytes

on 32bit ARM systems for me.

Signed-off-by: Alexander Graf <agraf@suse.de>
2021-08-26 00:25:35 -03:00
Alexander Graf
4696456c06 linux-user: lseek: explicitly cast non-set offsets to signed
When doing lseek, SEEK_SET indicates that the offset is an unsigned variable.
Other seek types have parameters that can be negative.

When converting from 32bit to 64bit parameters, we need to take this into
account and enable SEEK_END and SEEK_CUR to be negative, while SEEK_SET stays
absolute positioned which we need to maintain as unsigned.

Signed-off-by: Alexander Graf <agraf@suse.de>
2021-08-26 00:25:35 -03:00
Alexander Graf
28c46cf74d Make char muxer more robust wrt small FIFOs
Virtio-Console can only process one character at a time. Using it on S390
gave me strange "lags" where I got the character I pressed before when
pressing one. So I typed in "abc" and only received "a", then pressed "d"
but the guest received "b" and so on.

While the stdio driver calls a poll function that just processes on its
queue in case virtio-console can't take multiple characters at once, the
muxer does not have such callbacks, so it can't empty its queue.

To work around that limitation, I introduced a new timer that only gets
active when the guest can not receive any more characters. In that case
it polls again after a while to check if the guest is now receiving input.

This patch fixes input when using -nographic on s390 for me.

[AF: Rebased for v2.7.0-rc2]
[BR: minor edits to pass qemu's checkpatch script]
Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Alexander Graf
32f35459b4 linux-user: use target_ulong
Linux syscalls pass pointers or data length or other information of that sort
to the kernel. This is all stuff you don't want to have sign extended.
Otherwise a host 64bit variable parameter with a size parameter will extend
it to a negative number, breaking lseek for example.

Pass syscall arguments as ulong always.

Signed-off-by: Alexander Graf <agraf@suse.de>
2021-08-26 00:25:35 -03:00
Alexander Graf
b44b6bbc4e linux-user: Fake /proc/cpuinfo
Fedora 17 for ARM reads /proc/cpuinfo and fails if it doesn't contain
ARM related contents. This patch implements a quick hack to expose real
/proc/cpuinfo data taken from a real world machine.

The real fix would be to generate at least the flags automatically based
on the selected CPU. Please do not submit this patch upstream until this
has happened.

Signed-off-by: Alexander Graf <agraf@suse.de>
[AF: Rebased for v1.6 and v1.7]
Signed-off-by: Andreas Färber <afaerber@suse.de>
2021-08-26 00:25:35 -03:00
Alexander Graf
762eda2ea8 linux-user: binfmt: support host binaries
When we have a working host binary equivalent for the guest binary we're
trying to run, let's just use that instead as it will be a lot faster.

Signed-off-by: Alexander Graf <agraf@suse.de>
2021-08-26 00:25:35 -03:00
Alexander Graf
1ca867af23 PPC: KVM: Disable mmu notifier check
When using hugetlbfs (which is required for HV mode KVM on 970), we
check for MMU notifiers that on 970 can not be implemented properly.

So disable the check for mmu notifiers on PowerPC guests, making
KVM guests work there, even if possibly racy in some odd circumstances.

Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Alexander Graf
1f4874b88d linux-user: add binfmt wrapper for argv[0] handling
When using qemu's linux-user binaries through binfmt, argv[0] gets lost
along the execution because qemu only gets passed in the full file name
to the executable while argv[0] can be something completely different.

This breaks in some subtile situations, such as the grep and make test
suites.

This patch adds a wrapper binary called qemu-$TARGET-binfmt that can be
used with binfmt's P flag which passes the full path _and_ argv[0] to
the binfmt handler.

The binary would be smart enough to be versatile and only exist in the
system once, creating the qemu binary path names from its own argv[0].
However, this seemed like it didn't fit the make system too well, so
we're currently creating a new binary for each target archictecture.

CC: Reinhard Max <max@suse.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
[AF: Rebased onto new Makefile infrastructure, twice]
[AF: Updated for aarch64 for v2.0.0-rc1]
[AF: Rebased onto Makefile changes for v2.1.0-rc0]
[AF: Rebased onto script rewrite for v2.7.0-rc2 - to be fixed]
Signed-off-by: Andreas Färber <afaerber@suse.de>
2021-08-26 00:25:35 -03:00
Alexander Graf
17e3d8112f qemu-cvs-ioctl_nodirection
the direction given in the ioctl should be correct so we can assume the
communication is uni-directional. The alsa developers did not like this
concept though and declared ioctls IOC_R and IOC_W even though they were
IOC_RW.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Ulrich Hecht <uli@suse.de>
[BR: minor edits to pass qemu's checkpatch script]
Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Alexander Graf
76d1f2d635 qemu-cvs-ioctl_debug
Extends unsupported ioctl debug output.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Ulrich Hecht <uli@suse.de>
[BR: minor edits to pass qemu's checkpatch script]
Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Ulrich Hecht
2b4f96273e qemu-cvs-gettimeofday
No clue what this is for.

[BR: minor edits to pass qemu's checkpatch script]
Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Andreas Färber
0a185570c4 qemu-binfmt-conf: Modify default path
Change QEMU_PATH from /usr/local/bin to /usr/bin prefix.

Signed-off-by: Andreas Färber <afaerber@suse.de>
2021-08-26 00:25:35 -03:00
Alexander Graf
b127c336e7 XXX dont dump core on sigabort
Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:35 -03:00
Prasad J Pandit
4f233a610e net: vmxnet3: validate configuration values during activate (CVE-2021-20203)
Git-commit: 0000000000000000000000000000000000000000
References: bsc#1181639

While activating device in vmxnet3_acticate_device(), it does not
validate guest supplied configuration values against predefined
minimum - maximum limits. This may lead to integer overflow or
OOB access issues. Add checks to avoid it.

Fixes: CVE-2021-20203
Buglink: https://bugs.launchpad.net/qemu/+bug/1913873
Reported-by: Gaoning Pan <pgn@zju.edu.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Signed-off-by: Bruce Rogers <brogers@suse.com>
2021-08-26 00:25:32 -03:00
4343 changed files with 137474 additions and 307582 deletions

View File

@@ -10,9 +10,9 @@ windows_msys2_task:
memory: 8G
env:
CIRRUS_SHELL: powershell
MSYS: winsymlinks:native
MSYS: winsymlinks:nativestrict
MSYSTEM: MINGW64
MSYS2_URL: https://github.com/msys2/msys2-installer/releases/download/2022-06-03/msys2-base-x86_64-20220603.sfx.exe
MSYS2_URL: https://github.com/msys2/msys2-installer/releases/download/2021-04-19/msys2-base-x86_64-20210419.sfx.exe
MSYS2_FINGERPRINT: 0
MSYS2_PACKAGES: "
diffutils git grep make pkg-config sed
@@ -32,6 +32,7 @@ windows_msys2_task:
mingw-w64-x86_64-libgcrypt
mingw-w64-x86_64-libpng
mingw-w64-x86_64-libssh
mingw-w64-x86_64-libxml2
mingw-w64-x86_64-snappy
mingw-w64-x86_64-libusb
mingw-w64-x86_64-usbredir

1
.gitattributes vendored
View File

@@ -1,4 +1,3 @@
*.c.inc diff=c
*.h.inc diff=c
*.m diff=objc
*.py diff=python

34
.github/lockdown.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
# Configuration for Repo Lockdown - https://github.com/dessant/repo-lockdown
# Close issues and pull requests
close: true
# Lock issues and pull requests
lock: true
issues:
comment: |
Thank you for your interest in the QEMU project.
This repository is a read-only mirror of the project's repostories hosted
at https://gitlab.com/qemu-project/qemu.git.
The project does not process issues filed on GitHub.
The project issues are tracked on GitLab:
https://gitlab.com/qemu-project/qemu/-/issues
QEMU welcomes bug report contributions. You can file new ones on:
https://gitlab.com/qemu-project/qemu/-/issues/new
pulls:
comment: |
Thank you for your interest in the QEMU project.
This repository is a read-only mirror of the project's repostories hosted
on https://gitlab.com/qemu-project/qemu.git.
The project does not process merge requests filed on GitHub.
QEMU welcomes contributions of code (either fixing bugs or adding new
functionality). However, we get a lot of patches, and so we have some
guidelines about contributing on the project website:
https://www.qemu.org/contribute/

View File

@@ -1,30 +0,0 @@
# Configuration for Repo Lockdown - https://github.com/dessant/repo-lockdown
name: 'Repo Lockdown'
on:
pull_request_target:
types: opened
permissions:
pull-requests: write
jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: dessant/repo-lockdown@v2
with:
pr-comment: |
Thank you for your interest in the QEMU project.
This repository is a read-only mirror of the project's repostories hosted
on https://gitlab.com/qemu-project/qemu.git.
The project does not process merge requests filed on GitHub.
QEMU welcomes contributions of code (either fixing bugs or adding new
functionality). However, we get a lot of patches, and so we have some
guidelines about contributing on the project website:
https://www.qemu.org/contribute/
lock-pr: true
close-pr: true

1
.gitignore vendored
View File

@@ -15,4 +15,3 @@ GTAGS
*.depend_raw
*.swp
*.patch
*.gcov

View File

@@ -1,72 +0,0 @@
# The order of rules defined here is critically important.
# They are evaluated in order and first match wins.
#
# Thus we group them into a number of stages, ordered from
# most restrictive to least restrictive
#
.base_job_template:
rules:
#############################################################
# Stage 1: exclude scenarios where we definitely don't
# want jobs to run
#############################################################
# Cirrus jobs can't run unless the creds / target repo are set
- if: '$QEMU_JOB_CIRRUS && ($CIRRUS_GITHUB_REPO == null || $CIRRUS_API_TOKEN == null)'
when: never
# Publishing jobs should only run on the default branch in upstream
- if: '$QEMU_JOB_PUBLISH == "1" && $CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
when: never
# Non-publishing jobs should only run on staging branches in upstream
- if: '$QEMU_JOB_PUBLISH != "1" && $CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH !~ /staging/'
when: never
# Jobs only intended for forks should always be skipped on upstream
- if: '$QEMU_JOB_ONLY_FORKS == "1" && $CI_PROJECT_NAMESPACE == "qemu-project"'
when: never
# Forks don't get pipelines unless QEMU_CI=1 or QEMU_CI=2 is set
- if: '$QEMU_CI != "1" && $QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
when: never
# Avocado jobs don't run in forks unless $QEMU_CI_AVOCADO_TESTING is set
- if: '$QEMU_JOB_AVOCADO && $QEMU_CI_AVOCADO_TESTING != "1" && $CI_PROJECT_NAMESPACE != "qemu-project"'
when: never
#############################################################
# Stage 2: fine tune execution of jobs in specific scenarios
# where the catch all logic is inapprorpaite
#############################################################
# Optional jobs should not be run unless manually triggered
- if: '$QEMU_JOB_OPTIONAL'
when: manual
allow_failure: true
# Skipped jobs should not be run unless manually triggered
- if: '$QEMU_JOB_SKIPPED'
when: manual
allow_failure: true
# Avocado jobs can be manually start in forks if $QEMU_CI_AVOCADO_TESTING is unset
- if: '$QEMU_JOB_AVOCADO && $CI_PROJECT_NAMESPACE != "qemu-project"'
when: manual
allow_failure: true
#############################################################
# Stage 3: catch all logic applying to any job not matching
# an earlier criteria
#############################################################
# Forks pipeline jobs don't start automatically unless
# QEMU_CI=2 is set
- if: '$QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
when: manual
# Jobs can run if any jobs they depend on were successfull
- when: on_success

View File

@@ -1,5 +1,4 @@
.native_build_job_template:
extends: .base_job_template
stage: build
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
before_script:
@@ -27,8 +26,7 @@
make -j"$JOBS" $MAKE_CHECK_ARGS ;
fi
.common_test_job_template:
extends: .base_job_template
.native_test_job_template:
stage: test
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
script:
@@ -39,18 +37,8 @@
# Avoid recompiling by hiding ninja with NINJA=":"
- make NINJA=":" $MAKE_CHECK_ARGS
.native_test_job_template:
extends: .common_test_job_template
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
expire_in: 7 days
paths:
- build/meson-logs/testlog.txt
reports:
junit: build/meson-logs/testlog.junit.xml
.avocado_test_job_template:
extends: .common_test_job_template
.acceptance_test_job_template:
extends: .native_test_job_template
cache:
key: "${CI_JOB_NAME}-cache"
paths:
@@ -79,5 +67,15 @@
after_script:
- cd build
- du -chs ${CI_PROJECT_DIR}/avocado-cache
variables:
QEMU_JOB_AVOCADO: 1
rules:
# Only run these jobs if running on the mainstream namespace,
# or if the user set the QEMU_CI_AVOCADO_TESTING variable (either
# in its namespace setting or via git-push option, see documentation
# in /.gitlab-ci.yml of this repository).
- if: '$CI_PROJECT_NAMESPACE == "qemu-project"'
when: on_success
- if: '$QEMU_CI_AVOCADO_TESTING'
when: on_success
# Otherwise, set to manual (the jobs are created but not run).
- when: manual
allow_failure: true

View File

@@ -24,16 +24,16 @@ check-system-alpine:
artifacts: true
variables:
IMAGE: alpine
MAKE_CHECK_ARGS: check-unit check-qtest
MAKE_CHECK_ARGS: check
avocado-system-alpine:
extends: .avocado_test_job_template
acceptance-system-alpine:
extends: .acceptance_test_job_template
needs:
- job: build-system-alpine
artifacts: true
variables:
IMAGE: alpine
MAKE_CHECK_ARGS: check-avocado
MAKE_CHECK_ARGS: check-acceptance
build-system-ubuntu:
extends: .native_build_job_template
@@ -42,7 +42,6 @@ build-system-ubuntu:
variables:
IMAGE: ubuntu2004
CONFIGURE_ARGS: --enable-docs --enable-fdt=system --enable-slirp=system
--enable-capstone
TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
microblazeel-softmmu mips64el-softmmu
MAKE_CHECK_ARGS: check-build
@@ -60,14 +59,14 @@ check-system-ubuntu:
IMAGE: ubuntu2004
MAKE_CHECK_ARGS: check
avocado-system-ubuntu:
extends: .avocado_test_job_template
acceptance-system-ubuntu:
extends: .acceptance_test_job_template
needs:
- job: build-system-ubuntu
artifacts: true
variables:
IMAGE: ubuntu2004
MAKE_CHECK_ARGS: check-avocado
MAKE_CHECK_ARGS: check-acceptance
build-system-debian:
extends: .native_build_job_template
@@ -75,6 +74,7 @@ build-system-debian:
job: amd64-debian-container
variables:
IMAGE: debian-amd64
CONFIGURE_ARGS: --enable-fdt=system
TARGETS: arm-softmmu avr-softmmu i386-softmmu mipsel-softmmu
riscv64-softmmu sh4eb-softmmu sparc-softmmu xtensaeb-softmmu
MAKE_CHECK_ARGS: check-build
@@ -92,26 +92,14 @@ check-system-debian:
IMAGE: debian-amd64
MAKE_CHECK_ARGS: check
avocado-system-debian:
extends: .avocado_test_job_template
acceptance-system-debian:
extends: .acceptance_test_job_template
needs:
- job: build-system-debian
artifacts: true
variables:
IMAGE: debian-amd64
MAKE_CHECK_ARGS: check-avocado
crash-test-debian:
extends: .native_test_job_template
needs:
- job: build-system-debian
artifacts: true
variables:
IMAGE: debian-amd64
script:
- cd build
- make check-venv
- tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-i386
MAKE_CHECK_ARGS: check-acceptance
build-system-fedora:
extends: .native_build_job_template
@@ -120,7 +108,7 @@ build-system-fedora:
variables:
IMAGE: fedora
CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs
--enable-fdt=system --enable-slirp=system --enable-capstone
--enable-fdt=system --enable-slirp=system --enable-capstone=system
TARGETS: tricore-softmmu microblaze-softmmu mips-softmmu
xtensa-softmmu m68k-softmmu riscv32-softmmu ppc-softmmu sparc64-softmmu
MAKE_CHECK_ARGS: check-build
@@ -138,27 +126,14 @@ check-system-fedora:
IMAGE: fedora
MAKE_CHECK_ARGS: check
avocado-system-fedora:
extends: .avocado_test_job_template
acceptance-system-fedora:
extends: .acceptance_test_job_template
needs:
- job: build-system-fedora
artifacts: true
variables:
IMAGE: fedora
MAKE_CHECK_ARGS: check-avocado
crash-test-fedora:
extends: .native_test_job_template
needs:
- job: build-system-fedora
artifacts: true
variables:
IMAGE: fedora
script:
- cd build
- make check-venv
- tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-ppc
- tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-riscv32
MAKE_CHECK_ARGS: check-acceptance
build-system-centos:
extends: .native_build_job_template
@@ -167,8 +142,7 @@ build-system-centos:
variables:
IMAGE: centos8
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-fdt=system
--enable-modules --enable-trace-backends=dtrace --enable-docs
--enable-vfio-user-server
--enable-modules --enable-trace-backends=dtrace
TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
x86_64-softmmu rx-softmmu sh4-softmmu nios2-softmmu
MAKE_CHECK_ARGS: check-build
@@ -186,14 +160,14 @@ check-system-centos:
IMAGE: centos8
MAKE_CHECK_ARGS: check
avocado-system-centos:
extends: .avocado_test_job_template
acceptance-system-centos:
extends: .acceptance_test_job_template
needs:
- job: build-system-centos
artifacts: true
variables:
IMAGE: centos8
MAKE_CHECK_ARGS: check-avocado
MAKE_CHECK_ARGS: check-acceptance
build-system-opensuse:
extends: .native_build_job_template
@@ -218,16 +192,95 @@ check-system-opensuse:
IMAGE: opensuse-leap
MAKE_CHECK_ARGS: check
avocado-system-opensuse:
extends: .avocado_test_job_template
acceptance-system-opensuse:
extends: .acceptance_test_job_template
needs:
- job: build-system-opensuse
artifacts: true
variables:
IMAGE: opensuse-leap
MAKE_CHECK_ARGS: check-avocado
MAKE_CHECK_ARGS: check-acceptance
build-disabled:
extends: .native_build_job_template
needs:
job: amd64-fedora-container
variables:
IMAGE: fedora
CONFIGURE_ARGS:
--disable-attr
--disable-auth-pam
--disable-avx2
--disable-bochs
--disable-brlapi
--disable-bzip2
--disable-cap-ng
--disable-capstone
--disable-cloop
--disable-coroutine-pool
--disable-curl
--disable-curses
--disable-dmg
--disable-docs
--disable-gcrypt
--disable-glusterfs
--disable-gnutls
--disable-gtk
--disable-guest-agent
--disable-iconv
--disable-keyring
--disable-kvm
--disable-libiscsi
--disable-libpmem
--disable-libssh
--disable-libudev
--disable-libusb
--disable-libxml2
--disable-linux-aio
--disable-live-block-migration
--disable-lzo
--disable-malloc-trim
--disable-mpath
--disable-nettle
--disable-numa
--disable-opengl
--disable-parallels
--disable-pie
--disable-qcow1
--disable-qed
--disable-qom-cast-debug
--disable-rbd
--disable-rdma
--disable-replication
--disable-sdl
--disable-seccomp
--disable-slirp
--disable-smartcard
--disable-snappy
--disable-sparse
--disable-spice
--disable-strip
--disable-tpm
--disable-usb-redir
--disable-vdi
--disable-vhost-crypto
--disable-vhost-net
--disable-vhost-scsi
--disable-vhost-kernel
--disable-vhost-user
--disable-vhost-vdpa
--disable-vhost-vsock
--disable-virglrenderer
--disable-vnc
--disable-vte
--disable-vvfat
--disable-xen
--disable-zstd
TARGETS: arm-softmmu i386-softmmu ppc64-softmmu mips64-softmmu
s390x-softmmu i386-linux-user
MAKE_CHECK_ARGS: check-qtest SPEED=slow
# This jobs explicitly disable TCG (--disable-tcg), KVM is detected by
# the configure script. The container doesn't contain Xen headers so
# Xen accelerator is not detected / selected. As result it build the
@@ -252,11 +305,11 @@ build-tcg-disabled:
- cd tests/qemu-iotests/
- ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048
052 063 077 086 101 104 106 113 148 150 151 152 157 159 160 163
170 171 183 184 192 194 208 221 226 227 236 253 277 image-fleecing
170 171 183 184 192 194 208 221 222 226 227 236 253 277
- ./check -qcow2 028 051 056 057 058 065 068 082 085 091 095 096 102 122
124 132 139 142 144 145 151 152 155 157 165 194 196 200 202
208 209 216 218 227 234 246 247 248 250 254 255 257 258
260 261 262 263 264 270 272 273 277 279 image-fleecing
208 209 216 218 222 227 234 246 247 248 250 254 255 257 258
260 261 262 263 264 270 272 273 277 279
build-user:
extends: .native_build_job_template
@@ -344,7 +397,7 @@ clang-user:
# This can be accomplished by using -enable-slirp=git, which avoids the use of
# a system-wide version of the library
#
# Split in three sets of build/check/avocado to limit the execution time of each
# Split in three sets of build/check/acceptance to limit the execution time of each
# job
build-cfi-aarch64:
extends: .native_build_job_template
@@ -358,15 +411,17 @@ build-cfi-aarch64:
--enable-safe-stack --enable-slirp=git
TARGETS: aarch64-softmmu
MAKE_CHECK_ARGS: check-build
# FIXME: This job is often failing, likely due to out-of-memory problems in
# the constrained containers of the shared runners. Thus this is marked as
# skipped until the situation has been solved.
QEMU_JOB_SKIPPED: 1
timeout: 90m
timeout: 70m
artifacts:
expire_in: 2 days
paths:
- build
rules:
# FIXME: This job is often failing, likely due to out-of-memory problems in
# the constrained containers of the shared runners. Thus this is marked as
# manual until the situation has been solved.
- when: manual
allow_failure: true
check-cfi-aarch64:
extends: .native_test_job_template
@@ -377,14 +432,14 @@ check-cfi-aarch64:
IMAGE: fedora
MAKE_CHECK_ARGS: check
avocado-cfi-aarch64:
extends: .avocado_test_job_template
acceptance-cfi-aarch64:
extends: .acceptance_test_job_template
needs:
- job: build-cfi-aarch64
artifacts: true
variables:
IMAGE: fedora
MAKE_CHECK_ARGS: check-avocado
MAKE_CHECK_ARGS: check-acceptance
build-cfi-ppc64-s390x:
extends: .native_build_job_template
@@ -398,15 +453,17 @@ build-cfi-ppc64-s390x:
--enable-safe-stack --enable-slirp=git
TARGETS: ppc64-softmmu s390x-softmmu
MAKE_CHECK_ARGS: check-build
# FIXME: This job is often failing, likely due to out-of-memory problems in
# the constrained containers of the shared runners. Thus this is marked as
# skipped until the situation has been solved.
QEMU_JOB_SKIPPED: 1
timeout: 80m
timeout: 70m
artifacts:
expire_in: 2 days
paths:
- build
rules:
# FIXME: This job is often failing, likely due to out-of-memory problems in
# the constrained containers of the shared runners. Thus this is marked as
# manual until the situation has been solved.
- when: manual
allow_failure: true
check-cfi-ppc64-s390x:
extends: .native_test_job_template
@@ -417,14 +474,14 @@ check-cfi-ppc64-s390x:
IMAGE: fedora
MAKE_CHECK_ARGS: check
avocado-cfi-ppc64-s390x:
extends: .avocado_test_job_template
acceptance-cfi-ppc64-s390x:
extends: .acceptance_test_job_template
needs:
- job: build-cfi-ppc64-s390x
artifacts: true
variables:
IMAGE: fedora
MAKE_CHECK_ARGS: check-avocado
MAKE_CHECK_ARGS: check-acceptance
build-cfi-x86_64:
extends: .native_build_job_template
@@ -453,14 +510,14 @@ check-cfi-x86_64:
IMAGE: fedora
MAKE_CHECK_ARGS: check
avocado-cfi-x86_64:
extends: .avocado_test_job_template
acceptance-cfi-x86_64:
extends: .acceptance_test_job_template
needs:
- job: build-cfi-x86_64
artifacts: true
variables:
IMAGE: fedora
MAKE_CHECK_ARGS: check-avocado
MAKE_CHECK_ARGS: check-acceptance
tsan-build:
extends: .native_build_job_template
@@ -473,6 +530,33 @@ tsan-build:
TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user
MAKE_CHECK_ARGS: bench V=1
# These targets are on the way out
build-deprecated:
extends: .native_build_job_template
needs:
job: amd64-debian-user-cross-container
variables:
IMAGE: debian-all-test-cross
CONFIGURE_ARGS: --disable-tools
MAKE_CHECK_ARGS: build-tcg
TARGETS: ppc64abi32-linux-user
artifacts:
expire_in: 2 days
paths:
- build
# We split the check-tcg step as test failures are expected but we still
# want to catch the build breaking.
check-deprecated:
extends: .native_test_job_template
needs:
- job: build-deprecated
artifacts: true
variables:
IMAGE: debian-all-test-cross
MAKE_CHECK_ARGS: check-tcg
allow_failure: true
# gprof/gcov are GCC features
build-gprof-gcov:
extends: .native_build_job_template
@@ -515,6 +599,8 @@ build-oss-fuzz:
echo Testing ${fuzzer} ... ;
"${fuzzer}" -runs=1 -seed=1 || exit 1 ;
done
# Unrelated to fuzzer: run some tests with -fsanitize=address
- cd build-oss-fuzz && make check-qtest-i386 check-unit
build-tci:
extends: .native_build_job_template
@@ -563,26 +649,20 @@ build-without-default-devices:
build-without-default-features:
extends: .native_build_job_template
needs:
job: amd64-fedora-container
job: amd64-debian-container
variables:
IMAGE: fedora
CONFIGURE_ARGS:
--without-default-features
--disable-capstone
--disable-pie
--disable-qom-cast-debug
--disable-slirp
--disable-strip
TARGETS: avr-softmmu i386-softmmu mips64-softmmu s390x-softmmu sh4-softmmu
sparc64-softmmu hexagon-linux-user i386-linux-user s390x-linux-user
MAKE_CHECK_ARGS: check-unit check-qtest SPEED=slow
IMAGE: debian-amd64
CONFIGURE_ARGS: --without-default-features --disable-user
--target-list-exclude=arm-softmmu,i386-softmmu,mipsel-softmmu,mips64-softmmu,ppc-softmmu
MAKE_CHECK_ARGS: check-unit
build-libvhost-user:
extends: .base_job_template
stage: build
image: $CI_REGISTRY_IMAGE/qemu/fedora:latest
needs:
job: amd64-fedora-container
before_script:
- dnf install -y meson ninja-build
script:
- mkdir subprojects/libvhost-user/build
- cd subprojects/libvhost-user/build
@@ -595,13 +675,10 @@ build-tools-and-docs-debian:
extends: .native_build_job_template
needs:
job: amd64-debian-container
# when running on 'master' we use pre-existing container
optional: true
variables:
IMAGE: debian-amd64
MAKE_CHECK_ARGS: check-unit ctags TAGS cscope
MAKE_CHECK_ARGS: check-unit check-softfloat ctags TAGS cscope
CONFIGURE_ARGS: --disable-system --disable-user --enable-docs --enable-tools
QEMU_JOB_PUBLISH: 1
artifacts:
expire_in: 2 days
paths:
@@ -621,7 +698,6 @@ build-tools-and-docs-debian:
# that users can see the results of their commits, regardless
# of what topic branch they're currently using
pages:
extends: .base_job_template
image: $CI_REGISTRY_IMAGE/qemu/debian-amd64:latest
stage: test
needs:
@@ -639,5 +715,10 @@ pages:
artifacts:
paths:
- public
variables:
QEMU_JOB_PUBLISH: 1
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: on_success
- if: '$CI_PROJECT_NAMESPACE == "qemu-project"'
when: never
- if: '$CI_PROJECT_NAMESPACE != "qemu-project"'
when: on_success

View File

@@ -11,11 +11,9 @@
# special care, because we can't just override it at the GitLab CI job
# definition level or we risk breaking it completely.
.cirrus_build_job:
extends: .base_job_template
stage: build
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
needs: []
timeout: 80m
allow_failure: true
script:
- source .gitlab-ci.d/cirrus/$NAME.vars
@@ -37,12 +35,12 @@
-e "s|[@]PIP3@|$PIP3|g"
-e "s|[@]PYPI_PKGS@|$PYPI_PKGS|g"
-e "s|[@]CONFIGURE_ARGS@|$CONFIGURE_ARGS|g"
-e "s|[@]TEST_TARGETS@|$TEST_TARGETS|g"
-e "s|[@]TEST_TARGETSS@|$TEST_TARGETSS|g"
<.gitlab-ci.d/cirrus/build.yml >.gitlab-ci.d/cirrus/$NAME.yml
- cat .gitlab-ci.d/cirrus/$NAME.yml
- cirrus-run -v --show-build-log always .gitlab-ci.d/cirrus/$NAME.yml
variables:
QEMU_JOB_CIRRUS: 1
rules:
- if: "$CIRRUS_GITHUB_REPO && $CIRRUS_API_TOKEN"
x64-freebsd-12-build:
extends: .cirrus_build_job
@@ -50,11 +48,14 @@ x64-freebsd-12-build:
NAME: freebsd-12
CIRRUS_VM_INSTANCE_TYPE: freebsd_instance
CIRRUS_VM_IMAGE_SELECTOR: image_family
CIRRUS_VM_IMAGE_NAME: freebsd-12-3
CIRRUS_VM_IMAGE_NAME: freebsd-12-2
CIRRUS_VM_CPUS: 8
CIRRUS_VM_RAM: 8G
UPDATE_COMMAND: pkg update
INSTALL_COMMAND: pkg install -y
# TODO: Enable gnutls again once FreeBSD's libtasn1 got fixed
# See: https://gitlab.com/gnutls/libtasn1/-/merge_requests/71
CONFIGURE_ARGS: --disable-gnutls
TEST_TARGETS: check
x64-freebsd-13-build:
@@ -84,40 +85,3 @@ x64-macos-11-base-build:
PATH_EXTRA: /usr/local/opt/ccache/libexec:/usr/local/opt/gettext/bin
PKG_CONFIG_PATH: /usr/local/opt/curl/lib/pkgconfig:/usr/local/opt/ncurses/lib/pkgconfig:/usr/local/opt/readline/lib/pkgconfig
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
# The following jobs run VM-based tests via KVM on a Linux-based Cirrus-CI job
.cirrus_kvm_job:
extends: .base_job_template
stage: build
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
needs: []
timeout: 80m
script:
- sed -e "s|[@]CI_REPOSITORY_URL@|$CI_REPOSITORY_URL|g"
-e "s|[@]CI_COMMIT_REF_NAME@|$CI_COMMIT_REF_NAME|g"
-e "s|[@]CI_COMMIT_SHA@|$CI_COMMIT_SHA|g"
-e "s|[@]NAME@|$NAME|g"
-e "s|[@]CONFIGURE_ARGS@|$CONFIGURE_ARGS|g"
-e "s|[@]TEST_TARGETS@|$TEST_TARGETS|g"
<.gitlab-ci.d/cirrus/kvm-build.yml >.gitlab-ci.d/cirrus/$NAME.yml
- cat .gitlab-ci.d/cirrus/$NAME.yml
- cirrus-run -v --show-build-log always .gitlab-ci.d/cirrus/$NAME.yml
variables:
QEMU_JOB_CIRRUS: 1
QEMU_JOB_OPTIONAL: 1
x86-netbsd:
extends: .cirrus_kvm_job
variables:
NAME: netbsd
CONFIGURE_ARGS: --target-list=x86_64-softmmu,ppc64-softmmu,aarch64-softmmu
TEST_TARGETS: check
x86-openbsd:
extends: .cirrus_kvm_job
variables:
NAME: openbsd
CONFIGURE_ARGS: --target-list=i386-softmmu,riscv64-softmmu,mips64-softmmu
TEST_TARGETS: check

View File

@@ -13,7 +13,6 @@ env:
PYTHON: "@PYTHON@"
MAKE: "@MAKE@"
CONFIGURE_ARGS: "@CONFIGURE_ARGS@"
TEST_TARGETS: "@TEST_TARGETS@"
build_task:
install_script:
@@ -32,6 +31,5 @@ build_task:
- $MAKE -j$(sysctl -n hw.ncpu)
- for TARGET in $TEST_TARGETS ;
do
$MAKE -j$(sysctl -n hw.ncpu) $TARGET V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;
$MAKE -j$(sysctl -n hw.ncpu) $TARGET V=1 ;
done

View File

@@ -2,15 +2,12 @@
#
# $ lcitool variables freebsd-12 qemu
#
# https://gitlab.com/libvirt/libvirt-ci
# https://gitlab.com/libvirt/libvirt-ci/-/commit/c7e275ab27ac0dcd09da290817b9adeea1fd1eb1
PACKAGING_COMMAND='pkg'
CCACHE='/usr/local/bin/ccache'
CPAN_PKGS=''
CROSS_PKGS=''
MAKE='/usr/local/bin/gmake'
NINJA='/usr/local/bin/ninja'
PACKAGING_COMMAND='pkg'
PIP3='/usr/local/bin/pip-3.8'
PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage cmocka ctags curl cyrus-sasl dbus diffutils dtc fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv perl5 pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd'
PYPI_PKGS=''
PYTHON='/usr/local/bin/python3'
PIP3='/usr/local/bin/pip-3.8'
PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage ctags curl cyrus-sasl dbus diffutils gettext git glib gmake gnutls gsed gtk3 libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 libxml2 llvm lttng-ust lzo2 meson ncurses nettle ninja opencv p5-Test-Harness perl5 pixman pkgconf png py38-numpy py38-pillow py38-pip py38-sphinx py38-sphinx_rtd_theme py38-virtualenv py38-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd'

View File

@@ -2,15 +2,12 @@
#
# $ lcitool variables freebsd-13 qemu
#
# https://gitlab.com/libvirt/libvirt-ci
# https://gitlab.com/libvirt/libvirt-ci/-/commit/c7e275ab27ac0dcd09da290817b9adeea1fd1eb1
PACKAGING_COMMAND='pkg'
CCACHE='/usr/local/bin/ccache'
CPAN_PKGS=''
CROSS_PKGS=''
MAKE='/usr/local/bin/gmake'
NINJA='/usr/local/bin/ninja'
PACKAGING_COMMAND='pkg'
PIP3='/usr/local/bin/pip-3.8'
PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage cmocka ctags curl cyrus-sasl dbus diffutils dtc fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv perl5 pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd'
PYPI_PKGS=''
PYTHON='/usr/local/bin/python3'
PIP3='/usr/local/bin/pip-3.8'
PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage ctags curl cyrus-sasl dbus diffutils gettext git glib gmake gnutls gsed gtk3 libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 libxml2 llvm lttng-ust lzo2 meson ncurses nettle ninja opencv p5-Test-Harness perl5 pixman pkgconf png py38-numpy py38-pillow py38-pip py38-sphinx py38-sphinx_rtd_theme py38-virtualenv py38-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd'

View File

@@ -1,31 +0,0 @@
container:
image: fedora:35
cpu: 4
memory: 8Gb
kvm: true
env:
CIRRUS_CLONE_DEPTH: 1
CI_REPOSITORY_URL: "@CI_REPOSITORY_URL@"
CI_COMMIT_REF_NAME: "@CI_COMMIT_REF_NAME@"
CI_COMMIT_SHA: "@CI_COMMIT_SHA@"
@NAME@_task:
@NAME@_vm_cache:
folder: $HOME/.cache/qemu-vm
install_script:
- dnf update -y
- dnf install -y git make openssh-clients qemu-img qemu-system-x86 wget
clone_script:
- git clone --depth 100 "$CI_REPOSITORY_URL" .
- git fetch origin "$CI_COMMIT_REF_NAME"
- git reset --hard "$CI_COMMIT_SHA"
build_script:
- if [ -f $HOME/.cache/qemu-vm/images/@NAME@.img ]; then
make vm-build-@NAME@ J=$(getconf _NPROCESSORS_ONLN)
EXTRA_CONFIGURE_OPTS="@CONFIGURE_ARGS@"
BUILD_TARGET="@TEST_TARGETS@" ;
else
make vm-build-@NAME@ J=$(getconf _NPROCESSORS_ONLN) BUILD_TARGET=help
EXTRA_CONFIGURE_OPTS="--disable-system --disable-user --disable-tools" ;
fi

View File

@@ -2,15 +2,14 @@
#
# $ lcitool variables macos-11 qemu
#
# https://gitlab.com/libvirt/libvirt-ci
# https://gitlab.com/libvirt/libvirt-ci/-/commit/c7e275ab27ac0dcd09da290817b9adeea1fd1eb1
PACKAGING_COMMAND='brew'
CCACHE='/usr/local/bin/ccache'
CPAN_PKGS=''
CROSS_PKGS=''
MAKE='/usr/local/bin/gmake'
NINJA='/usr/local/bin/ninja'
PACKAGING_COMMAND='brew'
PIP3='/usr/local/bin/pip3'
PKGS='bash bc bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson ncurses nettle ninja perl pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy sparse spice-protocol tesseract texinfo usbredir vde vte3 zlib zstd'
PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme'
PYTHON='/usr/local/bin/python3'
PIP3='/usr/local/bin/pip3'
PKGS='bash bc bzip2 capstone ccache cpanminus ctags curl dbus diffutils gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb libxml2 llvm lzo make meson ncurses nettle ninja perl pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy sparse spice-protocol tesseract texinfo usbredir vde vte3 zlib zstd'
PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme virtualenv'
CPAN_PKGS='Test::Harness'

View File

@@ -1,52 +1,64 @@
alpha-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-alpha-cross
amd64-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-amd64-cross
amd64-debian-user-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-all-test-cross
arm64-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-arm64-cross
arm64-test-debian-cross-container:
extends: .container_job_template
stage: containers-layer2
needs: ['amd64-debian11-container']
variables:
NAME: debian-arm64-test-cross
armel-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-armel-cross
armhf-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-armhf-cross
# We never want to build hexagon in the CI system and by default we
# always want to refer to the master registry where it lives.
hexagon-cross-container:
extends: .base_job_template
image: docker:stable
stage: containers
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project"'
when: never
- when: always
variables:
NAME: debian-hexagon-cross
GIT_DEPTH: 1
QEMU_JOB_ONLY_FORKS: 1
services:
- docker:dind
before_script:
@@ -65,96 +77,91 @@ hexagon-cross-container:
hppa-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-hppa-cross
m68k-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-m68k-cross
mips64-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-mips64-cross
mips64el-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-mips64el-cross
mips-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-mips-cross
mipsel-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-mipsel-cross
powerpc-test-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian11-container']
variables:
NAME: debian-powerpc-test-cross
ppc64el-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-ppc64el-cross
riscv64-debian-cross-container:
extends: .container_job_template
stage: containers
# as we are currently based on 'sid/unstable' we may break so...
allow_failure: true
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-riscv64-cross
# we can however build TCG tests using a non-sid base
riscv64-debian-test-cross-container:
extends: .container_job_template
stage: containers
needs: ['amd64-debian11-container']
variables:
NAME: debian-riscv64-test-cross
s390x-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-s390x-cross
sh4-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-sh4-cross
sparc64-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-sparc64-cross
tricore-debian-cross-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-tricore-cross

View File

@@ -1,5 +1,4 @@
.container_job_template:
extends: .base_job_template
image: docker:stable
stage: containers
services:

View File

@@ -14,15 +14,26 @@ amd64-debian11-container:
amd64-debian-container:
extends: .container_job_template
stage: containers
stage: containers-layer2
needs: ['amd64-debian10-container']
variables:
NAME: debian-amd64
amd64-ubuntu1804-container:
extends: .container_job_template
variables:
NAME: ubuntu1804
amd64-ubuntu2004-container:
extends: .container_job_template
variables:
NAME: ubuntu2004
amd64-ubuntu-container:
extends: .container_job_template
variables:
NAME: ubuntu
amd64-opensuse-leap-container:
extends: .container_job_template
variables:

View File

@@ -1,5 +1,4 @@
.cross_system_build_job:
extends: .base_job_template
stage: build
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
timeout: 80m
@@ -15,7 +14,7 @@
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
- if grep -q "EXESUF=.exe" config-host.mak;
then make installer;
version="$(git describe --match v[0-9]* 2>/dev/null || git rev-parse --short HEAD)";
version="$(git describe --match v[0-9]*)";
mv -v qemu-setup*.exe qemu-setup-${version}.exe;
fi
@@ -25,7 +24,6 @@
# KVM), and set extra options (such disabling other accelerators) via the
# $EXTRA_CONFIGURE_OPTS variable.
.cross_accel_build_job:
extends: .base_job_template
stage: build
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
timeout: 30m
@@ -38,7 +36,6 @@
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
.cross_user_build_job:
extends: .base_job_template
stage: build
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
script:

View File

@@ -62,8 +62,6 @@ cross-i386-user:
cross-i386-tci:
extends: .cross_accel_build_job
timeout: 60m
needs:
job: i386-fedora-cross-container
variables:
IMAGE: fedora-i386-cross
ACCEL: tcg-interpreter
@@ -126,25 +124,6 @@ cross-ppc64el-user:
variables:
IMAGE: debian-ppc64el-cross
# The riscv64 cross-builds currently use a 'sid' container to get
# compilers and libraries. Until something more stable is found we
# allow_failure so as not to block CI.
cross-riscv64-system:
extends: .cross_system_build_job
allow_failure: true
needs:
job: riscv64-debian-cross-container
variables:
IMAGE: debian-riscv64-cross
cross-riscv64-user:
extends: .cross_user_build_job
allow_failure: true
needs:
job: riscv64-debian-cross-container
variables:
IMAGE: debian-riscv64-cross
cross-s390x-system:
extends: .cross_system_build_job
needs:

View File

@@ -13,8 +13,226 @@
variables:
GIT_STRATEGY: clone
include:
- local: '/.gitlab-ci.d/custom-runners/ubuntu-20.04-s390x.yml'
- local: '/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml'
- local: '/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch32.yml'
- local: '/.gitlab-ci.d/custom-runners/centos-stream-8-x86_64.yml'
# All ubuntu-18.04 jobs should run successfully in an environment
# setup by the scripts/ci/setup/build-environment.yml task
# "Install basic packages to build QEMU on Ubuntu 18.04/20.04"
ubuntu-18.04-s390x-all-linux-static:
allow_failure: true
needs: []
stage: build
tags:
- ubuntu_18.04
- s390x
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$S390X_RUNNER_AVAILABLE"
script:
# --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763
# --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages
- mkdir build
- cd build
- ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1
- make --output-sync -j`nproc` check-tcg V=1
ubuntu-18.04-s390x-all:
allow_failure: true
needs: []
stage: build
tags:
- ubuntu_18.04
- s390x
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$S390X_RUNNER_AVAILABLE"
script:
- mkdir build
- cd build
- ../configure --disable-libssh
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1
ubuntu-18.04-s390x-alldbg:
allow_failure: true
needs: []
stage: build
tags:
- ubuntu_18.04
- s390x
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$S390X_RUNNER_AVAILABLE"
script:
- mkdir build
- cd build
- ../configure --enable-debug --disable-libssh
- make clean
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1
ubuntu-18.04-s390x-clang:
allow_failure: true
needs: []
stage: build
tags:
- ubuntu_18.04
- s390x
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
when: manual
- if: "$S390X_RUNNER_AVAILABLE"
when: manual
script:
- mkdir build
- cd build
- ../configure --disable-libssh --cc=clang --cxx=clang++ --enable-sanitizers
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1
ubuntu-18.04-s390x-tci:
allow_failure: true
needs: []
stage: build
tags:
- ubuntu_18.04
- s390x
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$S390X_RUNNER_AVAILABLE"
script:
- mkdir build
- cd build
- ../configure --disable-libssh --enable-tcg-interpreter
- make --output-sync -j`nproc`
ubuntu-18.04-s390x-notcg:
allow_failure: true
needs: []
stage: build
tags:
- ubuntu_18.04
- s390x
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
when: manual
- if: "$S390X_RUNNER_AVAILABLE"
when: manual
script:
- mkdir build
- cd build
- ../configure --disable-libssh --disable-tcg
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1
# All ubuntu-20.04 jobs should run successfully in an environment
# setup by the scripts/ci/setup/qemu/build-environment.yml task
# "Install basic packages to build QEMU on Ubuntu 18.04/20.04"
ubuntu-20.04-aarch64-all-linux-static:
allow_failure: true
needs: []
stage: build
tags:
- ubuntu_20.04
- aarch64
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$S390X_RUNNER_AVAILABLE"
script:
# --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763
# --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages
- mkdir build
- cd build
- ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1
- make --output-sync -j`nproc` check-tcg V=1
ubuntu-20.04-aarch64-all:
allow_failure: true
needs: []
stage: build
tags:
- ubuntu_20.04
- aarch64
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$S390X_RUNNER_AVAILABLE"
script:
- mkdir build
- cd build
- ../configure --disable-libssh
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1
ubuntu-20.04-aarch64-alldbg:
allow_failure: true
needs: []
stage: build
tags:
- ubuntu_20.04
- aarch64
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$S390X_RUNNER_AVAILABLE"
script:
- mkdir build
- cd build
- ../configure --enable-debug --disable-libssh
- make clean
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1
ubuntu-20.04-aarch64-clang:
allow_failure: true
needs: []
stage: build
tags:
- ubuntu_20.04
- aarch64
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
when: manual
- if: "$S390X_RUNNER_AVAILABLE"
when: manual
script:
- mkdir build
- cd build
- ../configure --disable-libssh --cc=clang-10 --cxx=clang++-10 --enable-sanitizers
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1
ubuntu-20.04-aarch64-tci:
allow_failure: true
needs: []
stage: build
tags:
- ubuntu_20.04
- aarch64
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$S390X_RUNNER_AVAILABLE"
script:
- mkdir build
- cd build
- ../configure --disable-libssh --enable-tcg-interpreter
- make --output-sync -j`nproc`
ubuntu-20.04-aarch64-notcg:
allow_failure: true
needs: []
stage: build
tags:
- ubuntu_20.04
- aarch64
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
when: manual
- if: "$S390X_RUNNER_AVAILABLE"
when: manual
script:
- mkdir build
- cd build
- ../configure --disable-libssh --disable-tcg
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1

View File

@@ -1,30 +0,0 @@
centos-stream-8-x86_64:
allow_failure: true
needs: []
stage: build
tags:
- centos_stream_8
- x86_64
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$CENTOS_STREAM_8_x86_64_RUNNER_AVAILABLE"
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
when: on_failure
expire_in: 7 days
paths:
- build/tests/results/latest/results.xml
- build/tests/results/latest/test-results
reports:
junit: build/tests/results/latest/results.xml
before_script:
- JOBS=$(expr $(nproc) + 1)
script:
- mkdir build
- cd build
- ../scripts/ci/org.centos/stream/8/x86_64/configure
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make -j"$JOBS"
- make NINJA=":" check
|| { cat meson-logs/testlog.txt; exit 1; } ;
- ../scripts/ci/org.centos/stream/8/x86_64/test-avocado

View File

@@ -1,25 +0,0 @@
# All ubuntu-20.04 jobs should run successfully in an environment
# setup by the scripts/ci/setup/qemu/build-environment.yml task
# "Install basic packages to build QEMU on Ubuntu 20.04"
ubuntu-20.04-aarch32-all:
needs: []
stage: build
tags:
- ubuntu_20.04
- aarch32
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
when: manual
allow_failure: true
- if: "$AARCH32_RUNNER_AVAILABLE"
when: manual
allow_failure: true
script:
- mkdir build
- cd build
- ../configure --cross-prefix=arm-linux-gnueabihf-
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc --ignore=40`
- make --output-sync -j`nproc --ignore=40` check V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;

View File

@@ -1,130 +0,0 @@
# All ubuntu-20.04 jobs should run successfully in an environment
# setup by the scripts/ci/setup/qemu/build-environment.yml task
# "Install basic packages to build QEMU on Ubuntu 20.04"
ubuntu-20.04-aarch64-all-linux-static:
needs: []
stage: build
tags:
- ubuntu_20.04
- aarch64
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$AARCH64_RUNNER_AVAILABLE"
script:
# --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763
# --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages
- mkdir build
- cd build
- ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc --ignore=40`
- make --output-sync -j`nproc --ignore=40` check V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;
- make --output-sync -j`nproc --ignore=40` check-tcg V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;
ubuntu-20.04-aarch64-all:
needs: []
stage: build
tags:
- ubuntu_20.04
- aarch64
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
when: manual
allow_failure: true
- if: "$AARCH64_RUNNER_AVAILABLE"
when: manual
allow_failure: true
script:
- mkdir build
- cd build
- ../configure --disable-libssh
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc --ignore=40`
- make --output-sync -j`nproc --ignore=40` check V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;
ubuntu-20.04-aarch64-alldbg:
needs: []
stage: build
tags:
- ubuntu_20.04
- aarch64
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$AARCH64_RUNNER_AVAILABLE"
script:
- mkdir build
- cd build
- ../configure --enable-debug --disable-libssh
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make clean
- make --output-sync -j`nproc --ignore=40`
- make --output-sync -j`nproc --ignore=40` check V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;
ubuntu-20.04-aarch64-clang:
needs: []
stage: build
tags:
- ubuntu_20.04
- aarch64
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
when: manual
allow_failure: true
- if: "$AARCH64_RUNNER_AVAILABLE"
when: manual
allow_failure: true
script:
- mkdir build
- cd build
- ../configure --disable-libssh --cc=clang-10 --cxx=clang++-10 --enable-sanitizers
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc --ignore=40`
- make --output-sync -j`nproc --ignore=40` check V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;
ubuntu-20.04-aarch64-tci:
needs: []
stage: build
tags:
- ubuntu_20.04
- aarch64
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
when: manual
allow_failure: true
- if: "$AARCH64_RUNNER_AVAILABLE"
when: manual
allow_failure: true
script:
- mkdir build
- cd build
- ../configure --disable-libssh --enable-tcg-interpreter
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc --ignore=40`
ubuntu-20.04-aarch64-notcg:
needs: []
stage: build
tags:
- ubuntu_20.04
- aarch64
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
when: manual
allow_failure: true
- if: "$AARCH64_RUNNER_AVAILABLE"
when: manual
allow_failure: true
script:
- mkdir build
- cd build
- ../configure --disable-libssh --disable-tcg
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc --ignore=40`
- make --output-sync -j`nproc --ignore=40` check V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;

View File

@@ -1,131 +0,0 @@
# All ubuntu-20.04 jobs should run successfully in an environment
# setup by the scripts/ci/setup/build-environment.yml task
# "Install basic packages to build QEMU on Ubuntu 20.04/20.04"
ubuntu-20.04-s390x-all-linux-static:
needs: []
stage: build
tags:
- ubuntu_20.04
- s390x
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$S390X_RUNNER_AVAILABLE"
script:
# --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763
# --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages
- mkdir build
- cd build
- ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;
- make --output-sync -j`nproc` check-tcg V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;
ubuntu-20.04-s390x-all:
needs: []
stage: build
tags:
- ubuntu_20.04
- s390x
timeout: 75m
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$S390X_RUNNER_AVAILABLE"
script:
- mkdir build
- cd build
- ../configure --disable-libssh
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;
ubuntu-20.04-s390x-alldbg:
needs: []
stage: build
tags:
- ubuntu_20.04
- s390x
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
when: manual
allow_failure: true
- if: "$S390X_RUNNER_AVAILABLE"
when: manual
allow_failure: true
script:
- mkdir build
- cd build
- ../configure --enable-debug --disable-libssh
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make clean
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;
ubuntu-20.04-s390x-clang:
needs: []
stage: build
tags:
- ubuntu_20.04
- s390x
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
when: manual
allow_failure: true
- if: "$S390X_RUNNER_AVAILABLE"
when: manual
allow_failure: true
script:
- mkdir build
- cd build
- ../configure --disable-libssh --cc=clang --cxx=clang++ --enable-sanitizers
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;
ubuntu-20.04-s390x-tci:
needs: []
stage: build
tags:
- ubuntu_20.04
- s390x
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
when: manual
allow_failure: true
- if: "$S390X_RUNNER_AVAILABLE"
when: manual
allow_failure: true
script:
- mkdir build
- cd build
- ../configure --disable-libssh --enable-tcg-interpreter
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc`
ubuntu-20.04-s390x-notcg:
needs: []
stage: build
tags:
- ubuntu_20.04
- s390x
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
when: manual
allow_failure: true
- if: "$S390X_RUNNER_AVAILABLE"
when: manual
allow_failure: true
script:
- mkdir build
- cd build
- ../configure --disable-libssh --disable-tcg
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc`
- make --output-sync -j`nproc` check V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;

View File

@@ -1,85 +1,56 @@
# All jobs needing docker-edk2 must use the same rules it uses.
.edk2_job_rules:
rules:
# Forks don't get pipelines unless QEMU_CI=1 or QEMU_CI=2 is set
- if: '$QEMU_CI != "1" && $QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
when: never
# In forks, if QEMU_CI=1 is set, then create manual job
# if any of the files affecting the build are touched
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project"'
changes:
- .gitlab-ci.d/edk2.yml
- .gitlab-ci.d/edk2/Dockerfile
- roms/edk2/*
when: manual
# In forks, if QEMU_CI=1 is set, then create manual job
# if the branch/tag starts with 'edk2'
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_REF_NAME =~ /^edk2/'
when: manual
# In forks, if QEMU_CI=1 is set, then create manual job
# if last commit msg contains 'EDK2' (case insensitive)
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_MESSAGE =~ /edk2/i'
when: manual
# Run if any files affecting the build output are touched
- changes:
- .gitlab-ci.d/edk2.yml
- .gitlab-ci.d/edk2/Dockerfile
- roms/edk2/*
when: on_success
# Run if the branch/tag starts with 'edk2'
- if: '$CI_COMMIT_REF_NAME =~ /^edk2/'
when: on_success
# Run if last commit msg contains 'EDK2' (case insensitive)
- if: '$CI_COMMIT_MESSAGE =~ /edk2/i'
when: on_success
rules: # Only run this job when ...
- changes:
# this file is modified
- .gitlab-ci.d/edk2.yml
# or the Dockerfile is modified
- .gitlab-ci.d/edk2/Dockerfile
# or roms/edk2/ is modified (submodule updated)
- roms/edk2/*
when: on_success
- if: '$CI_COMMIT_REF_NAME =~ /^edk2/' # or the branch/tag starts with 'edk2'
when: on_success
- if: '$CI_COMMIT_MESSAGE =~ /edk2/i' # or last commit description contains 'EDK2'
when: on_success
docker-edk2:
extends: .edk2_job_rules
stage: containers
image: docker:19.03.1
services:
- docker:19.03.1-dind
variables:
GIT_DEPTH: 3
IMAGE_TAG: $CI_REGISTRY_IMAGE:edk2-cross-build
# We don't use TLS
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker pull $IMAGE_TAG || true
- docker build --cache-from $IMAGE_TAG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
--tag $IMAGE_TAG .gitlab-ci.d/edk2
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- docker push $IMAGE_TAG
extends: .edk2_job_rules
stage: containers
image: docker:19.03.1
services:
- docker:19.03.1-dind
variables:
GIT_DEPTH: 3
IMAGE_TAG: $CI_REGISTRY_IMAGE:edk2-cross-build
# We don't use TLS
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker pull $IMAGE_TAG || true
- docker build --cache-from $IMAGE_TAG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
--tag $IMAGE_TAG .gitlab-ci.d/edk2
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- docker push $IMAGE_TAG
build-edk2:
extends: .edk2_job_rules
stage: build
needs: ['docker-edk2']
artifacts:
paths: # 'artifacts.zip' will contains the following files:
- pc-bios/edk2*bz2
- pc-bios/edk2-licenses.txt
- edk2-stdout.log
- edk2-stderr.log
image: $CI_REGISTRY_IMAGE:edk2-cross-build
variables:
GIT_DEPTH: 3
script: # Clone the required submodules and build EDK2
- git submodule update --init roms/edk2
- git -C roms/edk2 submodule update --init --
ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3
BaseTools/Source/C/BrotliCompress/brotli
CryptoPkg/Library/OpensslLib/openssl
MdeModulePkg/Library/BrotliCustomDecompressLib/brotli
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
- echo "=== Using ${JOBS} simultaneous jobs ==="
- make -j${JOBS} -C roms efi 2>&1 1>edk2-stdout.log | tee -a edk2-stderr.log >&2
extends: .edk2_job_rules
stage: build
needs: ['docker-edk2']
artifacts:
paths: # 'artifacts.zip' will contains the following files:
- pc-bios/edk2*bz2
- pc-bios/edk2-licenses.txt
- edk2-stdout.log
- edk2-stderr.log
image: $CI_REGISTRY_IMAGE:edk2-cross-build
variables:
GIT_DEPTH: 3
script: # Clone the required submodules and build EDK2
- git submodule update --init roms/edk2
- git -C roms/edk2 submodule update --init
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
- echo "=== Using ${JOBS} simultaneous jobs ==="
- make -j${JOBS} -C roms efi 2>&1 1>edk2-stdout.log | tee -a edk2-stderr.log >&2

View File

@@ -1,9 +1,9 @@
#
# Docker image to cross-compile EDK2 firmware binaries
#
FROM ubuntu:18.04
FROM ubuntu:16.04
MAINTAINER Philippe Mathieu-Daudé <f4bug@amsat.org>
MAINTAINER Philippe Mathieu-Daudé <philmd@redhat.com>
# Install packages required to build EDK2
RUN apt update \
@@ -20,7 +20,7 @@ RUN apt update \
iasl \
make \
nasm \
python3 \
python \
uuid-dev \
&& \
\

View File

@@ -1,85 +1,63 @@
# All jobs needing docker-opensbi must use the same rules it uses.
.opensbi_job_rules:
rules:
# Forks don't get pipelines unless QEMU_CI=1 or QEMU_CI=2 is set
- if: '$QEMU_CI != "1" && $QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
when: never
# In forks, if QEMU_CI=1 is set, then create manual job
# if any files affecting the build output are touched
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project"'
changes:
- .gitlab-ci.d/opensbi.yml
- .gitlab-ci.d/opensbi/Dockerfile
- roms/opensbi/*
when: manual
# In forks, if QEMU_CI=1 is set, then create manual job
# if the branch/tag starts with 'opensbi'
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_REF_NAME =~ /^opensbi/'
when: manual
# In forks, if QEMU_CI=1 is set, then create manual job
# if the last commit msg contains 'OpenSBI' (case insensitive)
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_MESSAGE =~ /opensbi/i'
when: manual
# Run if any files affecting the build output are touched
- changes:
- .gitlab-ci.d/opensbi.yml
- .gitlab-ci.d/opensbi/Dockerfile
- roms/opensbi/*
when: on_success
# Run if the branch/tag starts with 'opensbi'
- if: '$CI_COMMIT_REF_NAME =~ /^opensbi/'
when: on_success
# Run if the last commit msg contains 'OpenSBI' (case insensitive)
- if: '$CI_COMMIT_MESSAGE =~ /opensbi/i'
when: on_success
rules: # Only run this job when ...
- changes:
# this file is modified
- .gitlab-ci.d/opensbi.yml
# or the Dockerfile is modified
- .gitlab-ci.d/opensbi/Dockerfile
when: on_success
- changes: # or roms/opensbi/ is modified (submodule updated)
- roms/opensbi/*
when: on_success
- if: '$CI_COMMIT_REF_NAME =~ /^opensbi/' # or the branch/tag starts with 'opensbi'
when: on_success
- if: '$CI_COMMIT_MESSAGE =~ /opensbi/i' # or last commit description contains 'OpenSBI'
when: on_success
docker-opensbi:
extends: .opensbi_job_rules
stage: containers
image: docker:19.03.1
services:
- docker:19.03.1-dind
variables:
GIT_DEPTH: 3
IMAGE_TAG: $CI_REGISTRY_IMAGE:opensbi-cross-build
# We don't use TLS
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker pull $IMAGE_TAG || true
- docker build --cache-from $IMAGE_TAG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
--tag $IMAGE_TAG .gitlab-ci.d/opensbi
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- docker push $IMAGE_TAG
extends: .opensbi_job_rules
stage: containers
image: docker:19.03.1
services:
- docker:19.03.1-dind
variables:
GIT_DEPTH: 3
IMAGE_TAG: $CI_REGISTRY_IMAGE:opensbi-cross-build
# We don't use TLS
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker pull $IMAGE_TAG || true
- docker build --cache-from $IMAGE_TAG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
--tag $IMAGE_TAG .gitlab-ci.d/opensbi
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- docker push $IMAGE_TAG
build-opensbi:
extends: .opensbi_job_rules
stage: build
needs: ['docker-opensbi']
artifacts:
paths: # 'artifacts.zip' will contains the following files:
- pc-bios/opensbi-riscv32-generic-fw_dynamic.bin
- pc-bios/opensbi-riscv64-generic-fw_dynamic.bin
- opensbi32-generic-stdout.log
- opensbi32-generic-stderr.log
- opensbi64-generic-stdout.log
- opensbi64-generic-stderr.log
image: $CI_REGISTRY_IMAGE:opensbi-cross-build
variables:
GIT_DEPTH: 3
script: # Clone the required submodules and build OpenSBI
- git submodule update --init roms/opensbi
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
- echo "=== Using ${JOBS} simultaneous jobs ==="
- make -j${JOBS} -C roms/opensbi clean
- make -j${JOBS} -C roms opensbi32-generic 2>&1 1>opensbi32-generic-stdout.log | tee -a opensbi32-generic-stderr.log >&2
- make -j${JOBS} -C roms/opensbi clean
- make -j${JOBS} -C roms opensbi64-generic 2>&1 1>opensbi64-generic-stdout.log | tee -a opensbi64-generic-stderr.log >&2
extends: .opensbi_job_rules
stage: build
needs: ['docker-opensbi']
artifacts:
paths: # 'artifacts.zip' will contains the following files:
- pc-bios/opensbi-riscv32-generic-fw_dynamic.bin
- pc-bios/opensbi-riscv32-generic-fw_dynamic.elf
- pc-bios/opensbi-riscv64-generic-fw_dynamic.bin
- pc-bios/opensbi-riscv64-generic-fw_dynamic.elf
- opensbi32-generic-stdout.log
- opensbi32-generic-stderr.log
- opensbi64-generic-stdout.log
- opensbi64-generic-stderr.log
image: $CI_REGISTRY_IMAGE:opensbi-cross-build
variables:
GIT_DEPTH: 3
script: # Clone the required submodules and build OpenSBI
- git submodule update --init roms/opensbi
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
- echo "=== Using ${JOBS} simultaneous jobs ==="
- make -j${JOBS} -C roms/opensbi clean
- make -j${JOBS} -C roms opensbi32-generic 2>&1 1>opensbi32-generic-stdout.log | tee -a opensbi32-generic-stderr.log >&2
- make -j${JOBS} -C roms/opensbi clean
- make -j${JOBS} -C roms opensbi64-generic 2>&1 1>opensbi64-generic-stdout.log | tee -a opensbi64-generic-stderr.log >&2

View File

@@ -2,7 +2,6 @@
# https://gitlab.com/qemu-project/qemu/-/pipelines
include:
- local: '/.gitlab-ci.d/base.yml'
- local: '/.gitlab-ci.d/stages.yml'
- local: '/.gitlab-ci.d/edk2.yml'
- local: '/.gitlab-ci.d/opensbi.yml'
@@ -12,4 +11,3 @@ include:
- local: '/.gitlab-ci.d/static_checks.yml'
- local: '/.gitlab-ci.d/custom-runners.yml'
- local: '/.gitlab-ci.d/cirrus.yml'
- local: '/.gitlab-ci.d/windows.yml'

View File

@@ -3,5 +3,6 @@
# - test (for test stages, using build artefacts from a build stage)
stages:
- containers
- containers-layer2
- build
- test

View File

@@ -1,30 +1,32 @@
check-patch:
extends: .base_job_template
stage: build
image: python:3.10-alpine
needs: []
image: $CI_REGISTRY_IMAGE/qemu/centos8:latest
needs:
job: amd64-centos8-container
script:
- .gitlab-ci.d/check-patch.py
variables:
GIT_DEPTH: 1000
QEMU_JOB_ONLY_FORKS: 1
before_script:
- apk -U add git perl
allow_failure: true
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: never
- when: on_success
allow_failure: true
check-dco:
extends: .base_job_template
stage: build
image: python:3.10-alpine
needs: []
image: $CI_REGISTRY_IMAGE/qemu/centos8:latest
needs:
job: amd64-centos8-container
script: .gitlab-ci.d/check-dco.py
variables:
GIT_DEPTH: 1000
before_script:
- apk -U add git
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: never
- when: on_success
check-python-pipenv:
extends: .base_job_template
stage: test
image: $CI_REGISTRY_IMAGE/qemu/python:latest
script:
@@ -35,7 +37,6 @@ check-python-pipenv:
job: python-container
check-python-tox:
extends: .base_job_template
stage: test
image: $CI_REGISTRY_IMAGE/qemu/python:latest
script:
@@ -43,6 +44,6 @@ check-python-tox:
variables:
GIT_DEPTH: 1
QEMU_TOX_EXTRA_ARGS: --skip-missing-interpreters=false
QEMU_JOB_OPTIONAL: 1
needs:
job: python-container
allow_failure: true

View File

@@ -1,98 +0,0 @@
.shared_msys2_builder:
extends: .base_job_template
tags:
- shared-windows
- windows
- windows-1809
cache:
key: "${CI_JOB_NAME}-cache"
paths:
- ${CI_PROJECT_DIR}/msys64/var/cache
needs: []
stage: build
timeout: 70m
before_script:
- If ( !(Test-Path -Path msys64\var\cache ) ) {
mkdir msys64\var\cache
}
- If ( !(Test-Path -Path msys64\var\cache\msys2.exe ) ) {
Invoke-WebRequest
"https://github.com/msys2/msys2-installer/releases/download/2022-06-03/msys2-base-x86_64-20220603.sfx.exe"
-outfile "msys64\var\cache\msys2.exe"
}
- msys64\var\cache\msys2.exe -y
- ((Get-Content -path .\msys64\etc\\post-install\\07-pacman-key.post -Raw)
-replace '--refresh-keys', '--version') |
Set-Content -Path ${CI_PROJECT_DIR}\msys64\etc\\post-install\\07-pacman-key.post
- .\msys64\usr\bin\bash -lc "sed -i 's/^CheckSpace/#CheckSpace/g' /etc/pacman.conf"
- .\msys64\usr\bin\bash -lc 'pacman --noconfirm -Syuu' # Core update
- .\msys64\usr\bin\bash -lc 'pacman --noconfirm -Syuu' # Normal update
- taskkill /F /FI "MODULES eq msys-2.0.dll"
msys2-64bit:
extends: .shared_msys2_builder
script:
- .\msys64\usr\bin\bash -lc "pacman -Sy --noconfirm --needed
diffutils git grep make sed
mingw-w64-x86_64-capstone
mingw-w64-x86_64-curl
mingw-w64-x86_64-cyrus-sasl
mingw-w64-x86_64-gcc
mingw-w64-x86_64-glib2
mingw-w64-x86_64-gnutls
mingw-w64-x86_64-libnfs
mingw-w64-x86_64-libpng
mingw-w64-x86_64-libssh
mingw-w64-x86_64-libtasn1
mingw-w64-x86_64-libusb
mingw-w64-x86_64-nettle
mingw-w64-x86_64-ninja
mingw-w64-x86_64-pixman
mingw-w64-x86_64-pkgconf
mingw-w64-x86_64-python
mingw-w64-x86_64-SDL2
mingw-w64-x86_64-SDL2_image
mingw-w64-x86_64-snappy
mingw-w64-x86_64-usbredir
mingw-w64-x86_64-zstd "
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
- $env:MSYSTEM = 'MINGW64' # Start a 64 bit Mingw environment
- $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink
- .\msys64\usr\bin\bash -lc './configure --target-list=x86_64-softmmu
--enable-capstone --without-default-devices'
- .\msys64\usr\bin\bash -lc "sed -i '/^ROMS=/d' build/config-host.mak"
- .\msys64\usr\bin\bash -lc 'make -j2'
- .\msys64\usr\bin\bash -lc 'make check'
msys2-32bit:
extends: .shared_msys2_builder
script:
- .\msys64\usr\bin\bash -lc "pacman -Sy --noconfirm --needed
diffutils git grep make sed
mingw-w64-i686-capstone
mingw-w64-i686-curl
mingw-w64-i686-cyrus-sasl
mingw-w64-i686-gcc
mingw-w64-i686-glib2
mingw-w64-i686-gnutls
mingw-w64-i686-gtk3
mingw-w64-i686-libgcrypt
mingw-w64-i686-libjpeg-turbo
mingw-w64-i686-libssh
mingw-w64-i686-libtasn1
mingw-w64-i686-libusb
mingw-w64-i686-lzo2
mingw-w64-i686-ninja
mingw-w64-i686-pixman
mingw-w64-i686-pkgconf
mingw-w64-i686-python
mingw-w64-i686-snappy
mingw-w64-i686-usbredir "
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
- $env:MSYSTEM = 'MINGW32' # Start a 32-bit MinG environment
- $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink
- mkdir output
- cd output
- ..\msys64\usr\bin\bash -lc "../configure --target-list=ppc64-softmmu"
- ..\msys64\usr\bin\bash -lc 'make -j2'
- ..\msys64\usr\bin\bash -lc 'make check'

23
.gitmodules vendored
View File

@@ -1,12 +1,12 @@
[submodule "roms/seabios"]
path = roms/seabios
url = https://gitlab.suse.de/virtualization/qemu-seabios.git
url = https://gitlab.com/qemu-project/seabios.git/
[submodule "roms/SLOF"]
path = roms/SLOF
url = https://gitlab.com/qemu-project/SLOF.git
[submodule "roms/ipxe"]
path = roms/ipxe
url = https://gitlab.suse.de/virtualization/qemu-ipxe.git
url = https://gitlab.com/qemu-project/ipxe.git
[submodule "roms/openbios"]
path = roms/openbios
url = https://gitlab.com/qemu-project/openbios.git
@@ -15,7 +15,7 @@
url = https://gitlab.com/qemu-project/qemu-palcode.git
[submodule "roms/sgabios"]
path = roms/sgabios
url = https://gitlab.suse.de/virtualization/qemu-sgabios.git
url = https://gitlab.com/qemu-project/sgabios.git
[submodule "dtc"]
path = dtc
url = https://gitlab.com/qemu-project/dtc.git
@@ -24,13 +24,16 @@
url = https://gitlab.com/qemu-project/u-boot.git
[submodule "roms/skiboot"]
path = roms/skiboot
url = https://gitlab.suse.de/virtualization/qemu-skiboot.git
url = https://gitlab.com/qemu-project/skiboot.git
[submodule "roms/QemuMacDrivers"]
path = roms/QemuMacDrivers
url = https://gitlab.com/qemu-project/QemuMacDrivers.git
[submodule "ui/keycodemapdb"]
path = ui/keycodemapdb
url = https://gitlab.com/qemu-project/keycodemapdb.git
[submodule "capstone"]
path = capstone
url = https://gitlab.com/qemu-project/capstone.git
[submodule "roms/seabios-hppa"]
path = roms/seabios-hppa
url = https://gitlab.com/qemu-project/seabios-hppa.git
@@ -45,25 +48,19 @@
url = https://gitlab.com/qemu-project/berkeley-softfloat-3.git
[submodule "roms/edk2"]
path = roms/edk2
url = https://gitlab.suse.de/virtualization/qemu-edk2.git
url = https://gitlab.com/qemu-project/edk2.git
[submodule "slirp"]
path = slirp
url = https://gitlab.com/qemu-project/libslirp.git
[submodule "roms/opensbi"]
path = roms/opensbi
url = https://gitlab.suse.de/virtualization/qemu-opensbi.git
url = https://gitlab.com/qemu-project/opensbi.git
[submodule "roms/qboot"]
path = roms/qboot
url = https://gitlab.suse.de/virtualization/qemu-qboot.git
url = https://gitlab.com/qemu-project/qboot.git
[submodule "meson"]
path = meson
url = https://gitlab.com/qemu-project/meson.git
[submodule "roms/vbootrom"]
path = roms/vbootrom
url = https://gitlab.com/qemu-project/vbootrom.git
[submodule "tests/lcitool/libvirt-ci"]
path = tests/lcitool/libvirt-ci
url = https://gitlab.com/libvirt/libvirt-ci.git
[submodule "subprojects/libvfio-user"]
path = subprojects/libvfio-user
url = https://gitlab.com/qemu-project/libvfio-user.git

View File

@@ -28,11 +28,7 @@ Thiemo Seufer <ths@networkno.de> ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
malc <av1474@comtv.ru> malc <malc@c046a42c-6fe2-441c-8c8c-71466251a162>
# Corrupted Author fields
Aaron Larson <alarson@ddci.com> alarson@ddci.com
Andreas Färber <andreas.faerber@web.de> Andreas Färber <andreas.faerber>
Jason Wang <jasowang@redhat.com> Jason Wang <jasowang>
Marek Dolata <mkdolata@us.ibm.com> mkdolata@us.ibm.com <mkdolata@us.ibm.com>
Michael Ellerman <mpe@ellerman.id.au> michael@ozlabs.org <michael@ozlabs.org>
Nick Hudson <hnick@vmware.com> hnick@vmware.com <hnick@vmware.com>
# There is also a:
@@ -54,31 +50,25 @@ Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <arikalo@wavecomp.com>
Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <aleksandar.rikalo@rt-rk.com>
Alexander Graf <agraf@csgraf.de> <agraf@suse.de>
Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com>
Christian Borntraeger <borntraeger@linux.ibm.com> <borntraeger@de.ibm.com>
Filip Bozuta <filip.bozuta@syrmia.com> <filip.bozuta@rt-rk.com.com>
Frederic Konrad <konrad.frederic@yahoo.fr> <fred.konrad@greensocs.com>
Frederic Konrad <konrad.frederic@yahoo.fr> <konrad@adacore.com>
Frederic Konrad <konrad@adacore.com> <fred.konrad@greensocs.com>
Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>
Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
Leif Lindholm <leif@nuviainc.com> <leif.lindholm@linaro.org>
Radoslaw Biernacki <rad@semihalf.com> <radoslaw.biernacki@linaro.org>
Paul Burton <paulburton@kernel.org> <paul.burton@mips.com>
Paul Burton <paulburton@kernel.org> <paul.burton@imgtec.com>
Paul Burton <paulburton@kernel.org> <paul@archlinuxmips.org>
Paul Burton <paulburton@kernel.org> <pburton@wavecomp.com>
Philippe Mathieu-Daudé <f4bug@amsat.org> <philmd@redhat.com>
Stefan Brankovic <stefan.brankovic@syrmia.com> <stefan.brankovic@rt-rk.com.com>
Yongbok Kim <yongbok.kim@mips.com> <yongbok.kim@imgtec.com>
# Also list preferred name forms where people have changed their
# git author config, or had utf8/latin1 encoding issues.
Aaron Lindsay <aaron@os.amperecomputing.com>
Aaron Larson <alarson@ddci.com>
Alexey Gerasimenko <x1917x@gmail.com>
Alex Chen <alex.chen@huawei.com>
Alex Ivanov <void@aleksoft.net>
Andreas Färber <afaerber@suse.de>
Bandan Das <bsd@redhat.com>
@@ -109,11 +99,9 @@ Gautham R. Shenoy <ego@in.ibm.com>
Gautham R. Shenoy <ego@linux.vnet.ibm.com>
Gonglei (Arei) <arei.gonglei@huawei.com>
Guang Wang <wang.guang55@zte.com.cn>
Haibin Zhang <haibinzhang@tencent.com>
Hailiang Zhang <zhang.zhanghailiang@huawei.com>
Hanna Reitz <hreitz@redhat.com> <mreitz@redhat.com>
Hervé Poussineau <hpoussin@reactos.org>
Hyman Huang <huangy81@chinatelecom.cn>
Jakub Jermář <jakub@jermar.eu>
Jakub Jermář <jakub.jermar@kernkonzept.com>
Jean-Christophe Dubois <jcd@tribudubois.net>
@@ -147,11 +135,9 @@ Nicholas Thomas <nick@bytemark.co.uk>
Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Orit Wasserman <owasserm@redhat.com>
Paolo Bonzini <pbonzini@redhat.com>
Pan Nengyuan <pannengyuan@huawei.com>
Pavel Dovgaluk <dovgaluk@ispras.ru>
Pavel Dovgaluk <pavel.dovgaluk@gmail.com>
Pavel Dovgaluk <Pavel.Dovgaluk@ispras.ru>
Peter Chubb <peter.chubb@nicta.com.au>
Peter Crosthwaite <crosthwaite.peter@gmail.com>
Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Peter Crosthwaite <peter.crosthwaite@xilinx.com>

View File

@@ -1,22 +0,0 @@
pr_15sp5_workflow:
steps:
- branch_package:
source_project: Devel:Virt:SLE-15-SP5:Staging
source_package: qemu
target_project: Devel:Virt:SLE-15-SP5:Staging:PRs
filters:
event: pull_request
branches:
only:
- v7.1.0-sle15sp5
rebuild_15sp5_workflow:
steps:
# Will automatically rebuild the package
- trigger_services:
project: Devel:Virt:SLE-15-SP5:Staging
package: qemu
filters:
event: push
branches:
only:
- v7.1.0-sle15sp4

View File

@@ -1,3 +1,6 @@
# The current Travis default is a VM based 16.04 Xenial on GCE
# Additional builds with specific requirements for a full VM need to
# be added as additional matrix: entries later on
os: linux
dist: focal
language: c
@@ -187,7 +190,7 @@ jobs:
- name: "[s390x] GCC check-tcg"
arch: s390x
dist: focal
dist: bionic
addons:
apt_packages:
- libaio-dev
@@ -222,7 +225,7 @@ jobs:
- BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$?
- |
if [ "$BUILD_RC" -eq 0 ] ; then
mv pc-bios/s390-ccw/*.img qemu-bundle/usr/local/share/qemu ;
mv pc-bios/s390-ccw/*.img pc-bios/ ;
${TEST_CMD} ;
else
$(exit $BUILD_RC);
@@ -230,7 +233,7 @@ jobs:
- name: "[s390x] GCC (other-softmmu)"
arch: s390x
dist: focal
dist: bionic
addons:
apt_packages:
- libaio-dev
@@ -260,11 +263,10 @@ jobs:
- name: "[s390x] GCC (user)"
arch: s390x
dist: focal
dist: bionic
addons:
apt_packages:
- libgcrypt20-dev
- libglib2.0-dev
- libgnutls28-dev
- ninja-build
env:
@@ -272,7 +274,7 @@ jobs:
- name: "[s390x] Clang (disable-tcg)"
arch: s390x
dist: focal
dist: bionic
compiler: clang
addons:
apt_packages:
@@ -303,3 +305,26 @@ jobs:
- CONFIG="--disable-containers --disable-tcg --enable-kvm
--disable-tools --host-cc=clang --cxx=clang++"
- UNRELIABLE=true
# Release builds
# The make-release script expect a QEMU version, so our tag must start with a 'v'.
# This is the case when release candidate tags are created.
- name: "Release tarball"
if: tag IS present AND tag =~ /^v\d+\.\d+(\.\d+)?(-\S*)?$/
env:
# We want to build from the release tarball
- BUILD_DIR="release/build/dir" SRC_DIR="../../.."
- BASE_CONFIG="--prefix=$PWD/dist"
- CONFIG="--target-list=x86_64-softmmu,aarch64-softmmu,armeb-linux-user,ppc-linux-user"
- TEST_CMD="make install -j${JOBS}"
- QEMU_VERSION="${TRAVIS_TAG:1}"
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
script:
- make -C ${SRC_DIR} qemu-${QEMU_VERSION}.tar.bz2
- ls -l ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2
- tar -xf ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2 && cd qemu-${QEMU_VERSION}
- mkdir -p release-build && cd release-build
- ../configure ${BASE_CONFIG} ${CONFIG} || { cat config.log meson-logs/meson-log.txt && exit 1; }
- make install
allow_failures:
- env: UNRELIABLE=true

View File

@@ -22,12 +22,15 @@ config TPM
config VHOST_USER
bool
select VHOST
config VHOST_VDPA
bool
select VHOST
config VHOST_KERNEL
bool
select VHOST
config VIRTFS
bool
@@ -38,11 +41,3 @@ config PVRDMA
config MULTIPROCESS_ALLOWED
bool
imply MULTIPROCESS
config FUZZ
bool
select SPARSE_MEM
config VFIO_USER_SERVER_ALLOWED
bool
imply VFIO_USER_SERVER

File diff suppressed because it is too large Load Diff

View File

@@ -87,7 +87,7 @@ x := $(shell rm -rf meson-private meson-info meson-logs)
endif
# 1. ensure config-host.mak is up-to-date
config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/scripts/meson-buildoptions.sh $(SRC_PATH)/VERSION
config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/VERSION
@echo config-host.mak is out-of-date, running configure
@if test -f meson-private/coredata.dat; then \
./config.status --skip-meson; \
@@ -124,12 +124,6 @@ ifneq ($(MESON),)
Makefile.mtest: build.ninja scripts/mtest2make.py
$(MESON) introspect --targets --tests --benchmarks | $(PYTHON) scripts/mtest2make.py > $@
-include Makefile.mtest
.PHONY: update-buildoptions
all update-buildoptions: $(SRC_PATH)/scripts/meson-buildoptions.sh
$(SRC_PATH)/scripts/meson-buildoptions.sh: $(SRC_PATH)/meson_options.txt
$(MESON) introspect --buildoptions $(SRC_PATH)/meson.build | $(PYTHON) \
scripts/meson-buildoptions.py > $@.tmp && mv $@.tmp $@
endif
# 4. Rules to bridge to other makefiles
@@ -143,9 +137,9 @@ MAKE.q = $(findstring q,$(firstword $(filter-out --%,$(MAKEFLAGS))))
MAKE.nq = $(if $(word 2, $(MAKE.n) $(MAKE.q)),nq)
NINJAFLAGS = $(if $V,-v) $(if $(MAKE.n), -n) $(if $(MAKE.k), -k0) \
$(filter-out -j, $(lastword -j1 $(filter -l% -j%, $(MAKEFLAGS)))) \
-d keepdepfile
ninja-cmd-goals = $(or $(MAKECMDGOALS), all)
ninja-cmd-goals += $(foreach g, $(MAKECMDGOALS), $(.ninja-goals.$g))))
ninja-cmd-goals += $(foreach t, $(.tests), $(.test.deps.$t))
makefile-targets := build.ninja ctags TAGS cscope dist clean uninstall
# "ninja -t targets" also lists all prerequisites. If build system
@@ -159,12 +153,15 @@ $(ninja-targets): run-ninja
# --output-sync line.
run-ninja: config-host.mak
ifneq ($(filter $(ninja-targets), $(ninja-cmd-goals)),)
+$(if $(MAKE.nq),@:,$(quiet-@)$(NINJA) $(NINJAFLAGS) \
$(sort $(filter $(ninja-targets), $(ninja-cmd-goals))) | cat)
+$(quiet-@)$(if $(MAKE.nq),@:, $(NINJA) -d keepdepfile \
$(NINJAFLAGS) $(sort $(filter $(ninja-targets), $(ninja-cmd-goals))) | cat)
endif
endif
# Force configure to re-run if the API symbols are updated
ifeq ($(CONFIG_PLUGIN),y)
config-host.mak: $(SRC_PATH)/plugins/qemu-plugins.symbols
.PHONY: plugins
plugins:
$(call quiet-command,\
@@ -186,26 +183,30 @@ include $(SRC_PATH)/tests/Makefile.include
all: recurse-all
ROMS_RULES=$(foreach t, all clean, $(addsuffix /$(t), $(ROMS)))
.PHONY: $(ROMS_RULES)
$(ROMS_RULES):
ROM_DIRS = $(addprefix pc-bios/, $(ROMS))
ROM_DIRS_RULES=$(foreach t, all clean, $(addsuffix /$(t), $(ROM_DIRS)))
# Only keep -O and -g cflags
.PHONY: $(ROM_DIRS_RULES)
$(ROM_DIRS_RULES):
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" TARGET_DIR="$(dir $@)" $(notdir $@),)
.PHONY: recurse-all recurse-clean
recurse-all: $(addsuffix /all, $(ROMS))
recurse-clean: $(addsuffix /clean, $(ROMS))
recurse-all: $(addsuffix /all, $(ROM_DIRS))
recurse-clean: $(addsuffix /clean, $(ROM_DIRS))
######################################################################
clean: recurse-clean
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean || :
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) clean-ctlist || :
find . \( -name '*.so' -o -name '*.dll' -o \
-name '*.[oda]' -o -name '*.gcno' \) -type f \
# avoid old build problems by removing potentially incorrect old files
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
find . \( -name '*.so' -o -name '*.dll' -o -name '*.[oda]' \) -type f \
! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-aarch64.a \
! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-arm.a \
-exec rm {} +
rm -f TAGS cscope.* *~ */*~
rm -f TAGS cscope.* *.pod *~ */*~
rm -f fsdev/*.pod scsi/*.pod
VERSION = $(shell cat $(SRC_PATH)/VERSION)
@@ -216,10 +217,10 @@ qemu-%.tar.bz2:
distclean: clean
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean -g || :
rm -f config-host.mak qemu-bundle
rm -f config-host.mak config-host.h* config-poison.h
rm -f tests/tcg/config-*.mak
rm -f config.status
rm -f roms/seabios/config.mak
rm -f config-all-disas.mak config.status
rm -f roms/seabios/config.mak roms/vgabios/config.mak
rm -f qemu-plugins-ld.symbols qemu-plugins-ld64.symbols
rm -f *-config-target.h *-config-devices.mak *-config-devices.h
rm -rf meson-private meson-logs meson-info compile_commands.json
@@ -228,8 +229,7 @@ distclean: clean
rm -f linux-headers/asm
rm -Rf .sdk
find-src-path = find "$(SRC_PATH)" -path "$(SRC_PATH)/meson" -prune -o \
-type l -prune -o \( -name "*.[chsS]" -o -name "*.[ch].inc" \)
find-src-path = find "$(SRC_PATH)/" -path "$(SRC_PATH)/meson" -prune -o \( -name "*.[chsS]" -o -name "*.[ch].inc" \)
.PHONY: ctags
ctags:
@@ -250,7 +250,7 @@ gtags:
"GTAGS", "Remove old $@ files")
$(call quiet-command, \
(cd $(SRC_PATH) && \
$(find-src-path) -print | gtags -f -), \
$(find-src-path) | gtags -f -), \
"GTAGS", "Re-index $(SRC_PATH)")
.PHONY: TAGS
@@ -280,7 +280,6 @@ cscope:
# Needed by "meson install"
export DESTDIR
include $(SRC_PATH)/tests/lcitool/Makefile.include
include $(SRC_PATH)/tests/docker/Makefile.include
include $(SRC_PATH)/tests/vm/Makefile.include
@@ -310,7 +309,6 @@ endif
@echo 'Test targets:'
$(call print-help,check,Run all tests (check-help for details))
$(call print-help,bench,Run all benchmarks)
$(call print-help,lcitool-help,Help about targets for managing build environment manifests)
$(call print-help,docker-help,Help about targets running tests inside containers)
$(call print-help,vm-help,Help about targets running tests inside VM)
@echo ''

View File

@@ -39,7 +39,7 @@ Documentation can be found hosted online at
current development version that is available at
`<https://www.qemu.org/docs/master/>`_ is generated from the ``docs/``
folder in the source tree, and is built by `Sphinx
<https://www.sphinx-doc.org/en/master/>`_.
<https://www.sphinx-doc.org/en/master/>_`.
Building
@@ -59,9 +59,9 @@ of other UNIX targets. The simple steps to build QEMU are:
Additional information can also be found online via the QEMU website:
* `<https://wiki.qemu.org/Hosts/Linux>`_
* `<https://wiki.qemu.org/Hosts/Mac>`_
* `<https://wiki.qemu.org/Hosts/W32>`_
* `<https://qemu.org/Hosts/Linux>`_
* `<https://qemu.org/Hosts/Mac>`_
* `<https://qemu.org/Hosts/W32>`_
Submitting patches
@@ -78,14 +78,14 @@ format-patch' and/or 'git send-email' to format & send the mail to the
qemu-devel@nongnu.org mailing list. All patches submitted must contain
a 'Signed-off-by' line from the author. Patches should follow the
guidelines set out in the `style section
<https://www.qemu.org/docs/master/devel/style.html>`_ of
<https://www.qemu.org/docs/master/devel/style.html>` of
the Developers Guide.
Additional information on submitting patches can be found online via
the QEMU website
* `<https://wiki.qemu.org/Contribute/SubmitAPatch>`_
* `<https://wiki.qemu.org/Contribute/TrivialPatches>`_
* `<https://qemu.org/Contribute/SubmitAPatch>`_
* `<https://qemu.org/Contribute/TrivialPatches>`_
The QEMU website is also maintained under source control.
@@ -144,7 +144,7 @@ reported via GitLab.
For additional information on bug reporting consult:
* `<https://wiki.qemu.org/Contribute/ReportABug>`_
* `<https://qemu.org/Contribute/ReportABug>`_
ChangeLog
@@ -168,4 +168,4 @@ main methods being email and IRC
Information on additional methods of contacting the community can be
found online via the QEMU website:
* `<https://wiki.qemu.org/Contribute/StartHere>`_
* `<https://qemu.org/Contribute/StartHere>`_

View File

@@ -1 +1 @@
7.1.0
6.1.0

View File

@@ -49,14 +49,6 @@ AccelClass *accel_find(const char *opt_name)
return ac;
}
/* Return the name of the current accelerator */
const char *current_accel_name(void)
{
AccelClass *ac = ACCEL_GET_CLASS(current_accel());
return ac->name;
}
static void accel_init_cpu_int_aux(ObjectClass *klass, void *opaque)
{
CPUClass *cc = CPU_CLASS(klass);

View File

@@ -66,7 +66,6 @@ void accel_init_ops_interfaces(AccelClass *ac)
{
const char *ac_name;
char *ops_name;
ObjectClass *oc;
AccelOpsClass *ops;
ac_name = object_class_get_name(OBJECT_CLASS(ac));
@@ -74,13 +73,8 @@ void accel_init_ops_interfaces(AccelClass *ac)
ops_name = g_strdup_printf("%s" ACCEL_OPS_SUFFIX, ac_name);
ops = ACCEL_OPS_CLASS(module_object_class_by_name(ops_name));
oc = module_object_class_by_name(ops_name);
if (!oc) {
error_report("fatal: could not load module for type '%s'", ops_name);
exit(1);
}
g_free(ops_name);
ops = ACCEL_OPS_CLASS(oc);
/*
* all accelerators need to define ops, providing at least a mandatory
* non-NULL create_vcpu_thread operation.

View File

@@ -60,10 +60,6 @@
HVFState *hvf_state;
#ifdef __aarch64__
#define HV_VM_DEFAULT NULL
#endif
/* Memory slots */
hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t size)
@@ -120,12 +116,11 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
{
hvf_slot *mem;
MemoryRegion *area = section->mr;
bool writable = !area->readonly && !area->rom_device;
bool writeable = !area->readonly && !area->rom_device;
hv_memory_flags_t flags;
uint64_t page_size = qemu_real_host_page_size();
if (!memory_region_is_ram(area)) {
if (writable) {
if (writeable) {
return;
} else if (!memory_region_is_romd(area)) {
/*
@@ -136,12 +131,6 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
}
}
if (!QEMU_IS_ALIGNED(int128_get64(section->size), page_size) ||
!QEMU_IS_ALIGNED(section->offset_within_address_space, page_size)) {
/* Not page aligned, so we can not map as RAM */
add = false;
}
mem = hvf_find_overlap_slot(
section->offset_within_address_space,
int128_get64(section->size));
@@ -250,12 +239,12 @@ static void hvf_set_dirty_tracking(MemoryRegionSection *section, bool on)
if (on) {
slot->flags |= HVF_SLOT_LOG;
hv_vm_protect((uintptr_t)slot->start, (size_t)slot->size,
HV_MEMORY_READ | HV_MEMORY_EXEC);
HV_MEMORY_READ);
/* stop tracking region*/
} else {
slot->flags &= ~HVF_SLOT_LOG;
hv_vm_protect((uintptr_t)slot->start, (size_t)slot->size,
HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC);
HV_MEMORY_READ | HV_MEMORY_WRITE);
}
}
@@ -302,7 +291,6 @@ static void hvf_region_del(MemoryListener *listener,
}
static MemoryListener hvf_memory_listener = {
.name = "hvf",
.priority = 10,
.region_add = hvf_region_add,
.region_del = hvf_region_del,
@@ -328,7 +316,7 @@ static int hvf_accel_init(MachineState *ms)
s = g_new0(HVFState, 1);
s->num_slots = ARRAY_SIZE(s->slots);
s->num_slots = 32;
for (x = 0; x < s->num_slots; ++x) {
s->slots[x].size = 0;
s->slots[x].slot_id = x;
@@ -336,8 +324,7 @@ static int hvf_accel_init(MachineState *ms)
hvf_state = s;
memory_listener_register(&hvf_memory_listener, &address_space_memory);
return hvf_arch_init();
return 0;
}
static void hvf_accel_class_init(ObjectClass *oc, void *data)
@@ -378,20 +365,17 @@ static int hvf_init_vcpu(CPUState *cpu)
cpu->hvf = g_malloc0(sizeof(*cpu->hvf));
/* init cpu signals */
sigset_t set;
struct sigaction sigact;
memset(&sigact, 0, sizeof(sigact));
sigact.sa_handler = dummy_signal;
sigaction(SIG_IPI, &sigact, NULL);
pthread_sigmask(SIG_BLOCK, NULL, &cpu->hvf->unblock_ipi_mask);
sigdelset(&cpu->hvf->unblock_ipi_mask, SIG_IPI);
pthread_sigmask(SIG_BLOCK, NULL, &set);
sigdelset(&set, SIG_IPI);
#ifdef __aarch64__
r = hv_vcpu_create(&cpu->hvf->fd, (hv_vcpu_exit_t **)&cpu->hvf->exit, NULL);
#else
r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf->fd, HV_VCPU_DEFAULT);
#endif
cpu->vcpu_dirty = 1;
assert_hvf_ok(r);
@@ -467,7 +451,6 @@ static void hvf_accel_ops_class_init(ObjectClass *oc, void *data)
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
ops->create_vcpu_thread = hvf_start_vcpu_thread;
ops->kick_vcpu_thread = hvf_kick_vcpu_thread;
ops->synchronize_post_reset = hvf_cpu_synchronize_post_reset;
ops->synchronize_post_init = hvf_cpu_synchronize_post_init;

View File

@@ -9,6 +9,7 @@
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/error-report.h"
#include "sysemu/hvf.h"
#include "sysemu/hvf_int.h"

View File

@@ -74,23 +74,11 @@ static void kvm_start_vcpu_thread(CPUState *cpu)
cpu, QEMU_THREAD_JOINABLE);
}
static bool kvm_vcpu_thread_is_idle(CPUState *cpu)
{
return !kvm_halt_in_kernel();
}
static bool kvm_cpus_are_resettable(void)
{
return !kvm_enabled() || kvm_cpu_check_are_resettable();
}
static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
{
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
ops->create_vcpu_thread = kvm_start_vcpu_thread;
ops->cpu_thread_is_idle = kvm_vcpu_thread_is_idle;
ops->cpus_are_resettable = kvm_cpus_are_resettable;
ops->synchronize_post_reset = kvm_cpu_synchronize_post_reset;
ops->synchronize_post_init = kvm_cpu_synchronize_post_init;
ops->synchronize_state = kvm_cpu_synchronize_state;

View File

@@ -45,10 +45,8 @@
#include "qemu/guest-random.h"
#include "sysemu/hw_accel.h"
#include "kvm-cpus.h"
#include "sysemu/dirtylimit.h"
#include "hw/boards.h"
#include "monitor/stats.h"
/* This check must be after config-host.h is included */
#ifdef CONFIG_EVENTFD
@@ -61,11 +59,7 @@
#ifdef PAGE_SIZE
#undef PAGE_SIZE
#endif
#define PAGE_SIZE qemu_real_host_page_size()
#ifndef KVM_GUESTDBG_BLOCKIRQ
#define KVM_GUESTDBG_BLOCKIRQ 0
#endif
#define PAGE_SIZE qemu_real_host_page_size
//#define DEBUG_KVM
@@ -174,8 +168,6 @@ bool kvm_vm_attributes_allowed;
bool kvm_direct_msi_allowed;
bool kvm_ioeventfd_any_length_allowed;
bool kvm_msi_use_devid;
bool kvm_has_guest_debug;
int kvm_sstep_flags;
static bool kvm_immediate_exit;
static hwaddr kvm_max_slot_size = ~0;
@@ -326,14 +318,14 @@ static hwaddr kvm_align_section(MemoryRegionSection *section,
with sub-page size and unaligned start address. Pad the start
address to next and truncate size to previous page boundary. */
aligned = ROUND_UP(section->offset_within_address_space,
qemu_real_host_page_size());
qemu_real_host_page_size);
delta = aligned - section->offset_within_address_space;
*start = aligned;
if (delta > size) {
return 0;
}
return (size - delta) & qemu_real_host_page_mask();
return (size - delta) & qemu_real_host_page_mask;
}
int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
@@ -477,8 +469,6 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp)
cpu->kvm_fd = ret;
cpu->kvm_state = s;
cpu->vcpu_dirty = true;
cpu->dirty_pages = 0;
cpu->throttle_us_per_full = 0;
mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
if (mmap_size < 0) {
@@ -629,7 +619,7 @@ static void kvm_log_stop(MemoryListener *listener,
static void kvm_slot_sync_dirty_pages(KVMSlot *slot)
{
ram_addr_t start = slot->ram_start_offset;
ram_addr_t pages = slot->memory_size / qemu_real_host_page_size();
ram_addr_t pages = slot->memory_size / qemu_real_host_page_size;
cpu_physical_memory_set_dirty_lebitmap(slot->dirty_bmap, start, pages);
}
@@ -665,7 +655,7 @@ static void kvm_slot_init_dirty_bitmap(KVMSlot *mem)
* And mem->memory_size is aligned to it (otherwise this mem can't
* be registered to KVM).
*/
hwaddr bitmap_size = ALIGN(mem->memory_size / qemu_real_host_page_size(),
hwaddr bitmap_size = ALIGN(mem->memory_size / qemu_real_host_page_size,
/*HOST_LONG_BITS*/ 64) / 8;
mem->dirty_bmap = g_malloc0(bitmap_size);
mem->dirty_bmap_size = bitmap_size;
@@ -710,7 +700,7 @@ static void kvm_dirty_ring_mark_page(KVMState *s, uint32_t as_id,
mem = &kml->slots[slot_id];
if (!mem->memory_size || offset >=
(mem->memory_size / qemu_real_host_page_size())) {
(mem->memory_size / qemu_real_host_page_size)) {
return;
}
@@ -753,26 +743,22 @@ static uint32_t kvm_dirty_ring_reap_one(KVMState *s, CPUState *cpu)
count++;
}
cpu->kvm_fetch_index = fetch;
cpu->dirty_pages += count;
return count;
}
/* Must be with slots_lock held */
static uint64_t kvm_dirty_ring_reap_locked(KVMState *s, CPUState* cpu)
static uint64_t kvm_dirty_ring_reap_locked(KVMState *s)
{
int ret;
CPUState *cpu;
uint64_t total = 0;
int64_t stamp;
stamp = get_clock();
if (cpu) {
total = kvm_dirty_ring_reap_one(s, cpu);
} else {
CPU_FOREACH(cpu) {
total += kvm_dirty_ring_reap_one(s, cpu);
}
CPU_FOREACH(cpu) {
total += kvm_dirty_ring_reap_one(s, cpu);
}
if (total) {
@@ -793,7 +779,7 @@ static uint64_t kvm_dirty_ring_reap_locked(KVMState *s, CPUState* cpu)
* Currently for simplicity, we must hold BQL before calling this. We can
* consider to drop the BQL if we're clear with all the race conditions.
*/
static uint64_t kvm_dirty_ring_reap(KVMState *s, CPUState *cpu)
static uint64_t kvm_dirty_ring_reap(KVMState *s)
{
uint64_t total;
@@ -813,7 +799,7 @@ static uint64_t kvm_dirty_ring_reap(KVMState *s, CPUState *cpu)
* reset below.
*/
kvm_slots_lock();
total = kvm_dirty_ring_reap_locked(s, cpu);
total = kvm_dirty_ring_reap_locked(s);
kvm_slots_unlock();
return total;
@@ -860,7 +846,7 @@ static void kvm_dirty_ring_flush(void)
* vcpus out in a synchronous way.
*/
kvm_cpu_synchronize_kick_all();
kvm_dirty_ring_reap(kvm_state, NULL);
kvm_dirty_ring_reap(kvm_state);
trace_kvm_dirty_ring_flush(1);
}
@@ -901,7 +887,7 @@ static void kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml,
/* Alignment requirement for KVM_CLEAR_DIRTY_LOG - 64 pages */
#define KVM_CLEAR_LOG_SHIFT 6
#define KVM_CLEAR_LOG_ALIGN (qemu_real_host_page_size() << KVM_CLEAR_LOG_SHIFT)
#define KVM_CLEAR_LOG_ALIGN (qemu_real_host_page_size << KVM_CLEAR_LOG_SHIFT)
#define KVM_CLEAR_LOG_MASK (-KVM_CLEAR_LOG_ALIGN)
static int kvm_log_clear_one_slot(KVMSlot *mem, int as_id, uint64_t start,
@@ -910,7 +896,7 @@ static int kvm_log_clear_one_slot(KVMSlot *mem, int as_id, uint64_t start,
KVMState *s = kvm_state;
uint64_t end, bmap_start, start_delta, bmap_npages;
struct kvm_clear_dirty_log d;
unsigned long *bmap_clear = NULL, psize = qemu_real_host_page_size();
unsigned long *bmap_clear = NULL, psize = qemu_real_host_page_size;
int ret;
/*
@@ -1143,7 +1129,6 @@ static void kvm_coalesce_pio_del(MemoryListener *listener,
}
static MemoryListener kvm_coalesced_pio_listener = {
.name = "kvm-coalesced-pio",
.coalesced_io_add = kvm_coalesce_pio_add,
.coalesced_io_del = kvm_coalesce_pio_del,
};
@@ -1208,8 +1193,8 @@ void kvm_hwpoison_page_add(ram_addr_t ram_addr)
static uint32_t adjust_ioeventfd_endianness(uint32_t val, uint32_t size)
{
#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
/* The kernel expects ioeventfd values in HOST_BIG_ENDIAN
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
/* The kernel expects ioeventfd values in HOST_WORDS_BIGENDIAN
* endianness, but the memory core hands them in target endianness.
* For example, PPC is always treated as big-endian even if running
* on KVM and on PPC64LE. Correct here.
@@ -1341,7 +1326,7 @@ kvm_check_extension_list(KVMState *s, const KVMCapabilityInfo *list)
void kvm_set_max_memslot_size(hwaddr max_slot_size)
{
g_assert(
ROUND_UP(max_slot_size, qemu_real_host_page_size()) == max_slot_size
ROUND_UP(max_slot_size, qemu_real_host_page_size) == max_slot_size
);
kvm_max_slot_size = max_slot_size;
}
@@ -1352,13 +1337,13 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
KVMSlot *mem;
int err;
MemoryRegion *mr = section->mr;
bool writable = !mr->readonly && !mr->rom_device;
bool writeable = !mr->readonly && !mr->rom_device;
hwaddr start_addr, size, slot_size, mr_offset;
ram_addr_t ram_start_offset;
void *ram;
if (!memory_region_is_ram(mr)) {
if (writable || !kvm_readonly_mem_allowed) {
if (writeable || !kvm_readonly_mem_allowed) {
return;
} else if (!mr->romd_mode) {
/* If the memory device is not in romd_mode, then we actually want
@@ -1404,7 +1389,7 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
* Not easy. Let's cross the fingers until it's fixed.
*/
if (kvm_state->kvm_dirty_ring_size) {
kvm_dirty_ring_reap_locked(kvm_state, NULL);
kvm_dirty_ring_reap_locked(kvm_state);
} else {
kvm_slot_get_dirty_log(kvm_state, mem);
}
@@ -1472,16 +1457,11 @@ static void *kvm_dirty_ring_reaper_thread(void *data)
*/
sleep(1);
/* keep sleeping so that dirtylimit not be interfered by reaper */
if (dirtylimit_in_service()) {
continue;
}
trace_kvm_dirty_ring_reaper("wakeup");
r->reaper_state = KVM_DIRTY_RING_REAPER_REAPING;
qemu_mutex_lock_iothread();
kvm_dirty_ring_reap(s, NULL);
kvm_dirty_ring_reap(s);
qemu_mutex_unlock_iothread();
r->reaper_iteration++;
@@ -1653,11 +1633,11 @@ static void kvm_io_ioeventfd_del(MemoryListener *listener,
}
void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
AddressSpace *as, int as_id, const char *name)
AddressSpace *as, int as_id)
{
int i;
kml->slots = g_new0(KVMSlot, s->nr_slots);
kml->slots = g_malloc0(s->nr_slots * sizeof(KVMSlot));
kml->as_id = as_id;
for (i = 0; i < s->nr_slots; i++) {
@@ -1669,7 +1649,6 @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
kml->listener.log_start = kvm_log_start;
kml->listener.log_stop = kvm_log_stop;
kml->listener.priority = 10;
kml->listener.name = name;
if (s->kvm_dirty_ring_size) {
kml->listener.log_sync_global = kvm_log_sync_global;
@@ -1690,7 +1669,6 @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
}
static MemoryListener kvm_io_listener = {
.name = "kvm-io",
.eventfd_add = kvm_io_ioeventfd_add,
.eventfd_del = kvm_io_ioeventfd_del,
.priority = 10,
@@ -1952,7 +1930,7 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
return virq;
}
route = g_new0(KVMMSIRoute, 1);
route = g_malloc0(sizeof(KVMMSIRoute));
route->kroute.gsi = virq;
route->kroute.type = KVM_IRQ_ROUTING_MSI;
route->kroute.flags = 0;
@@ -1972,11 +1950,10 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
return kvm_set_irq(s, route->kroute.gsi, 1);
}
int kvm_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev)
int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
{
struct kvm_irq_routing_entry kroute = {};
int virq;
KVMState *s = c->s;
MSIMessage msg = {0, 0};
if (pci_available && dev) {
@@ -2016,7 +1993,7 @@ int kvm_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev)
kvm_add_routing_entry(s, &kroute);
kvm_arch_add_msi_route_post(&kroute, vector, dev);
c->changes++;
kvm_irqchip_commit_routes(s);
return virq;
}
@@ -2174,7 +2151,7 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
abort();
}
int kvm_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev)
int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
{
return -ENOSYS;
}
@@ -2265,7 +2242,7 @@ static void kvm_irqchip_create(KVMState *s)
ret = kvm_arch_irqchip_create(s);
if (ret == 0) {
if (s->kernel_irqchip_split == ON_OFF_AUTO_ON) {
error_report("Split IRQ chip mode not supported.");
perror("Split IRQ chip mode not supported.");
exit(1);
} else {
ret = kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP);
@@ -2316,20 +2293,6 @@ bool kvm_vcpu_id_is_valid(int vcpu_id)
return vcpu_id >= 0 && vcpu_id < kvm_max_vcpu_id(s);
}
bool kvm_dirty_ring_enabled(void)
{
return kvm_state->kvm_dirty_ring_size ? true : false;
}
static void query_stats_cb(StatsResultList **result, StatsTarget target,
strList *names, strList *targets, Error **errp);
static void query_stats_schemas_cb(StatsSchemaList **result, Error **errp);
uint32_t kvm_dirty_ring_size(void)
{
return kvm_state->kvm_dirty_ring_size;
}
static int kvm_init(MachineState *ms)
{
MachineClass *mc = MACHINE_GET_CLASS(ms);
@@ -2361,7 +2324,7 @@ static int kvm_init(MachineState *ms)
* even with KVM. TARGET_PAGE_SIZE is assumed to be the minimum
* page size for the system though.
*/
assert(TARGET_PAGE_SIZE <= qemu_real_host_page_size());
assert(TARGET_PAGE_SIZE <= qemu_real_host_page_size);
s->sigmask_len = 8;
@@ -2506,7 +2469,7 @@ static int kvm_init(MachineState *ms)
ret = kvm_vm_enable_cap(s, KVM_CAP_DIRTY_LOG_RING, 0, ring_bytes);
if (ret) {
error_report("Enabling of KVM dirty ring failed: %s. "
"Suggested minimum value is 1024.", strerror(-ret));
"Suggested mininum value is 1024.", strerror(-ret));
goto err;
}
@@ -2591,25 +2554,6 @@ static int kvm_init(MachineState *ms)
kvm_ioeventfd_any_length_allowed =
(kvm_check_extension(s, KVM_CAP_IOEVENTFD_ANY_LENGTH) > 0);
#ifdef KVM_CAP_SET_GUEST_DEBUG
kvm_has_guest_debug =
(kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG) > 0);
#endif
kvm_sstep_flags = 0;
if (kvm_has_guest_debug) {
kvm_sstep_flags = SSTEP_ENABLE;
#if defined KVM_CAP_SET_GUEST_DEBUG2
int guest_debug_flags =
kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG2);
if (guest_debug_flags & KVM_GUESTDBG_BLOCKIRQ) {
kvm_sstep_flags |= SSTEP_NOIRQ;
}
#endif
}
kvm_state = s;
ret = kvm_arch_init(ms, s);
@@ -2635,7 +2579,7 @@ static int kvm_init(MachineState *ms)
s->memory_listener.listener.coalesced_io_del = kvm_uncoalesce_mmio_region;
kvm_memory_listener_register(s, &s->memory_listener,
&address_space_memory, 0, "kvm-memory");
&address_space_memory, 0);
if (kvm_eventfds_allowed) {
memory_listener_register(&kvm_io_listener,
&address_space_io);
@@ -2658,11 +2602,6 @@ static int kvm_init(MachineState *ms)
}
}
if (kvm_check_extension(kvm_state, KVM_CAP_BINARY_STATS_FD)) {
add_stats_callbacks(STATS_PROVIDER_KVM, query_stats_cb,
query_stats_schemas_cb);
}
return 0;
err:
@@ -2982,19 +2921,8 @@ int kvm_cpu_exec(CPUState *cpu)
*/
trace_kvm_dirty_ring_full(cpu->cpu_index);
qemu_mutex_lock_iothread();
/*
* We throttle vCPU by making it sleep once it exit from kernel
* due to dirty ring full. In the dirtylimit scenario, reaping
* all vCPUs after a single vCPU dirty ring get full result in
* the miss of sleep, so just reap the ring-fulled vCPU.
*/
if (dirtylimit_in_service()) {
kvm_dirty_ring_reap(kvm_state, cpu);
} else {
kvm_dirty_ring_reap(kvm_state, NULL);
}
kvm_dirty_ring_reap(kvm_state);
qemu_mutex_unlock_iothread();
dirtylimit_vcpu_execute(cpu);
ret = 0;
break;
case KVM_EXIT_SYSTEM_EVENT:
@@ -3255,10 +3183,6 @@ int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap)
if (cpu->singlestep_enabled) {
data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
if (cpu->singlestep_enabled & SSTEP_NOIRQ) {
data.dbg.control |= KVM_GUESTDBG_BLOCKIRQ;
}
}
kvm_arch_update_guest_debug(cpu, &data.dbg);
@@ -3280,7 +3204,7 @@ int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr,
return 0;
}
bp = g_new(struct kvm_sw_breakpoint, 1);
bp = g_malloc(sizeof(struct kvm_sw_breakpoint));
bp->pc = addr;
bp->use_count = 1;
err = kvm_arch_insert_sw_breakpoint(cpu, bp);
@@ -3733,407 +3657,3 @@ static void kvm_type_init(void)
}
type_init(kvm_type_init);
typedef struct StatsArgs {
union StatsResultsType {
StatsResultList **stats;
StatsSchemaList **schema;
} result;
strList *names;
Error **errp;
} StatsArgs;
static StatsList *add_kvmstat_entry(struct kvm_stats_desc *pdesc,
uint64_t *stats_data,
StatsList *stats_list,
Error **errp)
{
Stats *stats;
uint64List *val_list = NULL;
/* Only add stats that we understand. */
switch (pdesc->flags & KVM_STATS_TYPE_MASK) {
case KVM_STATS_TYPE_CUMULATIVE:
case KVM_STATS_TYPE_INSTANT:
case KVM_STATS_TYPE_PEAK:
case KVM_STATS_TYPE_LINEAR_HIST:
case KVM_STATS_TYPE_LOG_HIST:
break;
default:
return stats_list;
}
switch (pdesc->flags & KVM_STATS_UNIT_MASK) {
case KVM_STATS_UNIT_NONE:
case KVM_STATS_UNIT_BYTES:
case KVM_STATS_UNIT_CYCLES:
case KVM_STATS_UNIT_SECONDS:
case KVM_STATS_UNIT_BOOLEAN:
break;
default:
return stats_list;
}
switch (pdesc->flags & KVM_STATS_BASE_MASK) {
case KVM_STATS_BASE_POW10:
case KVM_STATS_BASE_POW2:
break;
default:
return stats_list;
}
/* Alloc and populate data list */
stats = g_new0(Stats, 1);
stats->name = g_strdup(pdesc->name);
stats->value = g_new0(StatsValue, 1);;
if ((pdesc->flags & KVM_STATS_UNIT_MASK) == KVM_STATS_UNIT_BOOLEAN) {
stats->value->u.boolean = *stats_data;
stats->value->type = QTYPE_QBOOL;
} else if (pdesc->size == 1) {
stats->value->u.scalar = *stats_data;
stats->value->type = QTYPE_QNUM;
} else {
int i;
for (i = 0; i < pdesc->size; i++) {
QAPI_LIST_PREPEND(val_list, stats_data[i]);
}
stats->value->u.list = val_list;
stats->value->type = QTYPE_QLIST;
}
QAPI_LIST_PREPEND(stats_list, stats);
return stats_list;
}
static StatsSchemaValueList *add_kvmschema_entry(struct kvm_stats_desc *pdesc,
StatsSchemaValueList *list,
Error **errp)
{
StatsSchemaValueList *schema_entry = g_new0(StatsSchemaValueList, 1);
schema_entry->value = g_new0(StatsSchemaValue, 1);
switch (pdesc->flags & KVM_STATS_TYPE_MASK) {
case KVM_STATS_TYPE_CUMULATIVE:
schema_entry->value->type = STATS_TYPE_CUMULATIVE;
break;
case KVM_STATS_TYPE_INSTANT:
schema_entry->value->type = STATS_TYPE_INSTANT;
break;
case KVM_STATS_TYPE_PEAK:
schema_entry->value->type = STATS_TYPE_PEAK;
break;
case KVM_STATS_TYPE_LINEAR_HIST:
schema_entry->value->type = STATS_TYPE_LINEAR_HISTOGRAM;
schema_entry->value->bucket_size = pdesc->bucket_size;
schema_entry->value->has_bucket_size = true;
break;
case KVM_STATS_TYPE_LOG_HIST:
schema_entry->value->type = STATS_TYPE_LOG2_HISTOGRAM;
break;
default:
goto exit;
}
switch (pdesc->flags & KVM_STATS_UNIT_MASK) {
case KVM_STATS_UNIT_NONE:
break;
case KVM_STATS_UNIT_BOOLEAN:
schema_entry->value->has_unit = true;
schema_entry->value->unit = STATS_UNIT_BOOLEAN;
break;
case KVM_STATS_UNIT_BYTES:
schema_entry->value->has_unit = true;
schema_entry->value->unit = STATS_UNIT_BYTES;
break;
case KVM_STATS_UNIT_CYCLES:
schema_entry->value->has_unit = true;
schema_entry->value->unit = STATS_UNIT_CYCLES;
break;
case KVM_STATS_UNIT_SECONDS:
schema_entry->value->has_unit = true;
schema_entry->value->unit = STATS_UNIT_SECONDS;
break;
default:
goto exit;
}
schema_entry->value->exponent = pdesc->exponent;
if (pdesc->exponent) {
switch (pdesc->flags & KVM_STATS_BASE_MASK) {
case KVM_STATS_BASE_POW10:
schema_entry->value->has_base = true;
schema_entry->value->base = 10;
break;
case KVM_STATS_BASE_POW2:
schema_entry->value->has_base = true;
schema_entry->value->base = 2;
break;
default:
goto exit;
}
}
schema_entry->value->name = g_strdup(pdesc->name);
schema_entry->next = list;
return schema_entry;
exit:
g_free(schema_entry->value);
g_free(schema_entry);
return list;
}
/* Cached stats descriptors */
typedef struct StatsDescriptors {
const char *ident; /* cache key, currently the StatsTarget */
struct kvm_stats_desc *kvm_stats_desc;
struct kvm_stats_header *kvm_stats_header;
QTAILQ_ENTRY(StatsDescriptors) next;
} StatsDescriptors;
static QTAILQ_HEAD(, StatsDescriptors) stats_descriptors =
QTAILQ_HEAD_INITIALIZER(stats_descriptors);
/*
* Return the descriptors for 'target', that either have already been read
* or are retrieved from 'stats_fd'.
*/
static StatsDescriptors *find_stats_descriptors(StatsTarget target, int stats_fd,
Error **errp)
{
StatsDescriptors *descriptors;
const char *ident;
struct kvm_stats_desc *kvm_stats_desc;
struct kvm_stats_header *kvm_stats_header;
size_t size_desc;
ssize_t ret;
ident = StatsTarget_str(target);
QTAILQ_FOREACH(descriptors, &stats_descriptors, next) {
if (g_str_equal(descriptors->ident, ident)) {
return descriptors;
}
}
descriptors = g_new0(StatsDescriptors, 1);
/* Read stats header */
kvm_stats_header = g_malloc(sizeof(*kvm_stats_header));
ret = read(stats_fd, kvm_stats_header, sizeof(*kvm_stats_header));
if (ret != sizeof(*kvm_stats_header)) {
error_setg(errp, "KVM stats: failed to read stats header: "
"expected %zu actual %zu",
sizeof(*kvm_stats_header), ret);
g_free(descriptors);
return NULL;
}
size_desc = sizeof(*kvm_stats_desc) + kvm_stats_header->name_size;
/* Read stats descriptors */
kvm_stats_desc = g_malloc0_n(kvm_stats_header->num_desc, size_desc);
ret = pread(stats_fd, kvm_stats_desc,
size_desc * kvm_stats_header->num_desc,
kvm_stats_header->desc_offset);
if (ret != size_desc * kvm_stats_header->num_desc) {
error_setg(errp, "KVM stats: failed to read stats descriptors: "
"expected %zu actual %zu",
size_desc * kvm_stats_header->num_desc, ret);
g_free(descriptors);
g_free(kvm_stats_desc);
return NULL;
}
descriptors->kvm_stats_header = kvm_stats_header;
descriptors->kvm_stats_desc = kvm_stats_desc;
descriptors->ident = ident;
QTAILQ_INSERT_TAIL(&stats_descriptors, descriptors, next);
return descriptors;
}
static void query_stats(StatsResultList **result, StatsTarget target,
strList *names, int stats_fd, Error **errp)
{
struct kvm_stats_desc *kvm_stats_desc;
struct kvm_stats_header *kvm_stats_header;
StatsDescriptors *descriptors;
g_autofree uint64_t *stats_data = NULL;
struct kvm_stats_desc *pdesc;
StatsList *stats_list = NULL;
size_t size_desc, size_data = 0;
ssize_t ret;
int i;
descriptors = find_stats_descriptors(target, stats_fd, errp);
if (!descriptors) {
return;
}
kvm_stats_header = descriptors->kvm_stats_header;
kvm_stats_desc = descriptors->kvm_stats_desc;
size_desc = sizeof(*kvm_stats_desc) + kvm_stats_header->name_size;
/* Tally the total data size; read schema data */
for (i = 0; i < kvm_stats_header->num_desc; ++i) {
pdesc = (void *)kvm_stats_desc + i * size_desc;
size_data += pdesc->size * sizeof(*stats_data);
}
stats_data = g_malloc0(size_data);
ret = pread(stats_fd, stats_data, size_data, kvm_stats_header->data_offset);
if (ret != size_data) {
error_setg(errp, "KVM stats: failed to read data: "
"expected %zu actual %zu", size_data, ret);
return;
}
for (i = 0; i < kvm_stats_header->num_desc; ++i) {
uint64_t *stats;
pdesc = (void *)kvm_stats_desc + i * size_desc;
/* Add entry to the list */
stats = (void *)stats_data + pdesc->offset;
if (!apply_str_list_filter(pdesc->name, names)) {
continue;
}
stats_list = add_kvmstat_entry(pdesc, stats, stats_list, errp);
}
if (!stats_list) {
return;
}
switch (target) {
case STATS_TARGET_VM:
add_stats_entry(result, STATS_PROVIDER_KVM, NULL, stats_list);
break;
case STATS_TARGET_VCPU:
add_stats_entry(result, STATS_PROVIDER_KVM,
current_cpu->parent_obj.canonical_path,
stats_list);
break;
default:
g_assert_not_reached();
}
}
static void query_stats_schema(StatsSchemaList **result, StatsTarget target,
int stats_fd, Error **errp)
{
struct kvm_stats_desc *kvm_stats_desc;
struct kvm_stats_header *kvm_stats_header;
StatsDescriptors *descriptors;
struct kvm_stats_desc *pdesc;
StatsSchemaValueList *stats_list = NULL;
size_t size_desc;
int i;
descriptors = find_stats_descriptors(target, stats_fd, errp);
if (!descriptors) {
return;
}
kvm_stats_header = descriptors->kvm_stats_header;
kvm_stats_desc = descriptors->kvm_stats_desc;
size_desc = sizeof(*kvm_stats_desc) + kvm_stats_header->name_size;
/* Tally the total data size; read schema data */
for (i = 0; i < kvm_stats_header->num_desc; ++i) {
pdesc = (void *)kvm_stats_desc + i * size_desc;
stats_list = add_kvmschema_entry(pdesc, stats_list, errp);
}
add_stats_schema(result, STATS_PROVIDER_KVM, target, stats_list);
}
static void query_stats_vcpu(CPUState *cpu, run_on_cpu_data data)
{
StatsArgs *kvm_stats_args = (StatsArgs *) data.host_ptr;
int stats_fd = kvm_vcpu_ioctl(cpu, KVM_GET_STATS_FD, NULL);
Error *local_err = NULL;
if (stats_fd == -1) {
error_setg_errno(&local_err, errno, "KVM stats: ioctl failed");
error_propagate(kvm_stats_args->errp, local_err);
return;
}
query_stats(kvm_stats_args->result.stats, STATS_TARGET_VCPU,
kvm_stats_args->names, stats_fd, kvm_stats_args->errp);
close(stats_fd);
}
static void query_stats_schema_vcpu(CPUState *cpu, run_on_cpu_data data)
{
StatsArgs *kvm_stats_args = (StatsArgs *) data.host_ptr;
int stats_fd = kvm_vcpu_ioctl(cpu, KVM_GET_STATS_FD, NULL);
Error *local_err = NULL;
if (stats_fd == -1) {
error_setg_errno(&local_err, errno, "KVM stats: ioctl failed");
error_propagate(kvm_stats_args->errp, local_err);
return;
}
query_stats_schema(kvm_stats_args->result.schema, STATS_TARGET_VCPU, stats_fd,
kvm_stats_args->errp);
close(stats_fd);
}
static void query_stats_cb(StatsResultList **result, StatsTarget target,
strList *names, strList *targets, Error **errp)
{
KVMState *s = kvm_state;
CPUState *cpu;
int stats_fd;
switch (target) {
case STATS_TARGET_VM:
{
stats_fd = kvm_vm_ioctl(s, KVM_GET_STATS_FD, NULL);
if (stats_fd == -1) {
error_setg_errno(errp, errno, "KVM stats: ioctl failed");
return;
}
query_stats(result, target, names, stats_fd, errp);
close(stats_fd);
break;
}
case STATS_TARGET_VCPU:
{
StatsArgs stats_args;
stats_args.result.stats = result;
stats_args.names = names;
stats_args.errp = errp;
CPU_FOREACH(cpu) {
if (!apply_str_list_filter(cpu->parent_obj.canonical_path, targets)) {
continue;
}
run_on_cpu(cpu, query_stats_vcpu, RUN_ON_CPU_HOST_PTR(&stats_args));
}
break;
}
default:
break;
}
}
void query_stats_schemas_cb(StatsSchemaList **result, Error **errp)
{
StatsArgs stats_args;
KVMState *s = kvm_state;
int stats_fd;
stats_fd = kvm_vm_ioctl(s, KVM_GET_STATS_FD, NULL);
if (stats_fd == -1) {
error_setg_errno(errp, errno, "KVM stats: ioctl failed");
return;
}
query_stats_schema(result, STATS_TARGET_VM, stats_fd, errp);
close(stats_fd);
if (first_cpu) {
stats_args.result.schema = result;
stats_args.errp = errp;
run_on_cpu(first_cpu, query_stats_schema_vcpu, RUN_ON_CPU_HOST_PTR(&stats_args));
}
}

View File

@@ -3,5 +3,6 @@ kvm_ss.add(files(
'kvm-all.c',
'kvm-accel-ops.c',
))
kvm_ss.add(when: 'CONFIG_SEV', if_false: files('sev-stub.c'))
specific_ss.add_all(when: 'CONFIG_KVM', if_true: kvm_ss)

View File

@@ -12,7 +12,8 @@
*/
#include "qemu/osdep.h"
#include "sev.h"
#include "qemu-common.h"
#include "sysemu/sev.h"
int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
{

View File

@@ -2,14 +2,12 @@ specific_ss.add(files('accel-common.c'))
softmmu_ss.add(files('accel-softmmu.c'))
user_ss.add(files('accel-user.c'))
subdir('hvf')
subdir('qtest')
subdir('kvm')
subdir('tcg')
if have_system
subdir('hvf')
subdir('qtest')
subdir('kvm')
subdir('xen')
subdir('stubs')
endif
subdir('xen')
subdir('stubs')
dummy_ss = ss.source_set()
dummy_ss.add(files(

View File

@@ -20,6 +20,7 @@
#include "qemu/accel.h"
#include "sysemu/qtest.h"
#include "sysemu/cpus.h"
#include "sysemu/cpu-timers.h"
#include "qemu/guest-random.h"
#include "qemu/main-loop.h"
#include "hw/core/cpu.h"

View File

@@ -16,8 +16,6 @@
#include "qemu/osdep.h"
#include "sysemu/hax.h"
bool hax_allowed;
int hax_sync_vcpus(void)
{
return 0;

View File

@@ -12,7 +12,10 @@
#include "qemu/osdep.h"
#include "sysemu/kvm.h"
#ifndef CONFIG_USER_ONLY
#include "hw/pci/msi.h"
#endif
KVMState *kvm_state;
bool kvm_kernel_irqchip;
@@ -77,7 +80,8 @@ int kvm_on_sigbus(int code, void *addr)
return 1;
}
int kvm_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev)
#ifndef CONFIG_USER_ONLY
int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
{
return -ENOSYS;
}
@@ -143,13 +147,4 @@ bool kvm_arm_supports_user_irq(void)
{
return false;
}
bool kvm_dirty_ring_enabled(void)
{
return false;
}
uint32_t kvm_dirty_ring_size(void)
{
return 0;
}
#endif

View File

@@ -1,7 +1,4 @@
sysemu_stubs_ss = ss.source_set()
sysemu_stubs_ss.add(when: 'CONFIG_HAX', if_false: files('hax-stub.c'))
sysemu_stubs_ss.add(when: 'CONFIG_XEN', if_false: files('xen-stub.c'))
sysemu_stubs_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
sysemu_stubs_ss.add(when: 'CONFIG_TCG', if_false: files('tcg-stub.c'))
specific_ss.add_all(when: ['CONFIG_SOFTMMU'], if_true: sysemu_stubs_ss)
specific_ss.add(when: 'CONFIG_HAX', if_false: files('hax-stub.c'))
specific_ss.add(when: 'CONFIG_XEN', if_false: files('xen-stub.c'))
specific_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
specific_ss.add(when: 'CONFIG_TCG', if_false: files('tcg-stub.c'))

View File

@@ -21,13 +21,6 @@ void tlb_set_dirty(CPUState *cpu, target_ulong vaddr)
{
}
int probe_access_flags(CPUArchState *env, target_ulong addr,
MMUAccessType access_type, int mmu_idx,
bool nonfault, void **phost, uintptr_t retaddr)
{
g_assert_not_reached();
}
void *probe_access(CPUArchState *env, target_ulong addr, int size,
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
{
@@ -35,12 +28,12 @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
g_assert_not_reached();
}
G_NORETURN void cpu_loop_exit(CPUState *cpu)
void QEMU_NORETURN cpu_loop_exit(CPUState *cpu)
{
g_assert_not_reached();
}
G_NORETURN void cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc)
void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc)
{
g_assert_not_reached();
}

View File

@@ -13,23 +13,56 @@
* See the COPYING file in the top-level directory.
*/
static void atomic_trace_rmw_post(CPUArchState *env, target_ulong addr,
MemOpIdx oi)
static uint16_t atomic_trace_rmw_pre(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi)
{
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_RW);
CPUState *cpu = env_cpu(env);
uint16_t info = trace_mem_get_info(get_memop(oi), get_mmuidx(oi), false);
trace_guest_mem_before_exec(cpu, addr, info);
trace_guest_mem_before_exec(cpu, addr, info | TRACE_MEM_ST);
return info;
}
static void atomic_trace_rmw_post(CPUArchState *env, target_ulong addr,
uint16_t info)
{
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info);
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info | TRACE_MEM_ST);
}
#if HAVE_ATOMIC128
static void atomic_trace_ld_post(CPUArchState *env, target_ulong addr,
MemOpIdx oi)
static uint16_t atomic_trace_ld_pre(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi)
{
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
uint16_t info = trace_mem_get_info(get_memop(oi), get_mmuidx(oi), false);
trace_guest_mem_before_exec(env_cpu(env), addr, info);
return info;
}
static void atomic_trace_ld_post(CPUArchState *env, target_ulong addr,
uint16_t info)
{
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info);
}
static uint16_t atomic_trace_st_pre(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi)
{
uint16_t info = trace_mem_get_info(get_memop(oi), get_mmuidx(oi), true);
trace_guest_mem_before_exec(env_cpu(env), addr, info);
return info;
}
static void atomic_trace_st_post(CPUArchState *env, target_ulong addr,
MemOpIdx oi)
uint16_t info)
{
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info);
}
#endif

View File

@@ -19,6 +19,7 @@
*/
#include "qemu/plugin.h"
#include "trace/mem.h"
#if DATA_SIZE == 16
# define SUFFIX o
@@ -63,7 +64,7 @@
the ATOMIC_NAME macro, and redefined below. */
#if DATA_SIZE == 1
# define END
#elif HOST_BIG_ENDIAN
#elif defined(HOST_WORDS_BIGENDIAN)
# define END _be
#else
# define END _le
@@ -71,11 +72,12 @@
ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
ABI_TYPE cmpv, ABI_TYPE newv,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
PAGE_READ | PAGE_WRITE, retaddr);
DATA_TYPE ret;
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
#if DATA_SIZE == 16
ret = atomic16_cmpxchg(haddr, cmpv, newv);
@@ -83,60 +85,64 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
ret = qatomic_cmpxchg__nocheck(haddr, cmpv, newv);
#endif
ATOMIC_MMU_CLEANUP;
atomic_trace_rmw_post(env, addr, oi);
atomic_trace_rmw_post(env, addr, info);
return ret;
}
#if DATA_SIZE >= 16
#if HAVE_ATOMIC128
ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
PAGE_READ, retaddr);
DATA_TYPE val;
uint16_t info = atomic_trace_ld_pre(env, addr, oi);
val = atomic16_read(haddr);
ATOMIC_MMU_CLEANUP;
atomic_trace_ld_post(env, addr, oi);
atomic_trace_ld_post(env, addr, info);
return val;
}
void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
PAGE_WRITE, retaddr);
uint16_t info = atomic_trace_st_pre(env, addr, oi);
atomic16_set(haddr, val);
ATOMIC_MMU_CLEANUP;
atomic_trace_st_post(env, addr, oi);
atomic_trace_st_post(env, addr, info);
}
#endif
#else
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
PAGE_READ | PAGE_WRITE, retaddr);
DATA_TYPE ret;
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
ret = qatomic_xchg__nocheck(haddr, val);
ATOMIC_MMU_CLEANUP;
atomic_trace_rmw_post(env, addr, oi);
atomic_trace_rmw_post(env, addr, info);
return ret;
}
#define GEN_ATOMIC_HELPER(X) \
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \
ABI_TYPE val, TCGMemOpIdx oi, uintptr_t retaddr) \
{ \
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
PAGE_READ | PAGE_WRITE, retaddr); \
DATA_TYPE ret; \
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
ret = qatomic_##X(haddr, val); \
ATOMIC_MMU_CLEANUP; \
atomic_trace_rmw_post(env, addr, oi); \
atomic_trace_rmw_post(env, addr, info); \
return ret; \
}
@@ -161,11 +167,12 @@ GEN_ATOMIC_HELPER(xor_fetch)
*/
#define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \
ABI_TYPE xval, TCGMemOpIdx oi, uintptr_t retaddr) \
{ \
XDATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
PAGE_READ | PAGE_WRITE, retaddr); \
XDATA_TYPE cmp, old, new, val = xval; \
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
smp_mb(); \
cmp = qatomic_read__nocheck(haddr); \
do { \
@@ -173,7 +180,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
cmp = qatomic_cmpxchg__nocheck(haddr, old, new); \
} while (cmp != old); \
ATOMIC_MMU_CLEANUP; \
atomic_trace_rmw_post(env, addr, oi); \
atomic_trace_rmw_post(env, addr, info); \
return RET; \
}
@@ -196,7 +203,7 @@ GEN_ATOMIC_HELPER_FN(umax_fetch, MAX, DATA_TYPE, new)
/* Define reverse-host-endian atomic operations. Note that END is used
within the ATOMIC_NAME macro. */
#if HOST_BIG_ENDIAN
#ifdef HOST_WORDS_BIGENDIAN
# define END _le
#else
# define END _be
@@ -204,11 +211,12 @@ GEN_ATOMIC_HELPER_FN(umax_fetch, MAX, DATA_TYPE, new)
ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
ABI_TYPE cmpv, ABI_TYPE newv,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
PAGE_READ | PAGE_WRITE, retaddr);
DATA_TYPE ret;
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
#if DATA_SIZE == 16
ret = atomic16_cmpxchg(haddr, BSWAP(cmpv), BSWAP(newv));
@@ -216,61 +224,65 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
ret = qatomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv));
#endif
ATOMIC_MMU_CLEANUP;
atomic_trace_rmw_post(env, addr, oi);
atomic_trace_rmw_post(env, addr, info);
return BSWAP(ret);
}
#if DATA_SIZE >= 16
#if HAVE_ATOMIC128
ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
PAGE_READ, retaddr);
DATA_TYPE val;
uint16_t info = atomic_trace_ld_pre(env, addr, oi);
val = atomic16_read(haddr);
ATOMIC_MMU_CLEANUP;
atomic_trace_ld_post(env, addr, oi);
atomic_trace_ld_post(env, addr, info);
return BSWAP(val);
}
void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
PAGE_WRITE, retaddr);
uint16_t info = atomic_trace_st_pre(env, addr, oi);
val = BSWAP(val);
atomic16_set(haddr, val);
ATOMIC_MMU_CLEANUP;
atomic_trace_st_post(env, addr, oi);
atomic_trace_st_post(env, addr, info);
}
#endif
#else
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
PAGE_READ | PAGE_WRITE, retaddr);
ABI_TYPE ret;
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
ret = qatomic_xchg__nocheck(haddr, BSWAP(val));
ATOMIC_MMU_CLEANUP;
atomic_trace_rmw_post(env, addr, oi);
atomic_trace_rmw_post(env, addr, info);
return BSWAP(ret);
}
#define GEN_ATOMIC_HELPER(X) \
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \
ABI_TYPE val, TCGMemOpIdx oi, uintptr_t retaddr) \
{ \
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
PAGE_READ | PAGE_WRITE, retaddr); \
DATA_TYPE ret; \
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
ret = qatomic_##X(haddr, BSWAP(val)); \
ATOMIC_MMU_CLEANUP; \
atomic_trace_rmw_post(env, addr, oi); \
atomic_trace_rmw_post(env, addr, info); \
return BSWAP(ret); \
}
@@ -292,11 +304,12 @@ GEN_ATOMIC_HELPER(xor_fetch)
*/
#define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \
ABI_TYPE xval, TCGMemOpIdx oi, uintptr_t retaddr) \
{ \
XDATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
PAGE_READ | PAGE_WRITE, retaddr); \
XDATA_TYPE ldo, ldn, old, new, val = xval; \
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
smp_mb(); \
ldn = qatomic_read__nocheck(haddr); \
do { \
@@ -304,7 +317,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
ldn = qatomic_cmpxchg__nocheck(haddr, ldo, BSWAP(new)); \
} while (ldo != ldn); \
ATOMIC_MMU_CLEANUP; \
atomic_trace_rmw_post(env, addr, oi); \
atomic_trace_rmw_post(env, addr, info); \
return RET; \
}

View File

@@ -18,10 +18,8 @@
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/qemu-print.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-machine.h"
#include "qapi/type-helpers.h"
#include "hw/core/tcg-cpu-ops.h"
#include "trace.h"
#include "disas/disas.h"
@@ -40,7 +38,6 @@
#include "exec/cpu-all.h"
#include "sysemu/cpu-timers.h"
#include "sysemu/replay.h"
#include "sysemu/tcg.h"
#include "exec/helper-proto.h"
#include "tb-hash.h"
#include "tb-context.h"
@@ -214,19 +211,17 @@ static inline void log_cpu_exec(target_ulong pc, CPUState *cpu,
#if defined(DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
FILE *logfile = qemu_log_trylock();
if (logfile) {
int flags = 0;
FILE *logfile = qemu_log_lock();
int flags = 0;
if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
flags |= CPU_DUMP_FPU;
}
#if defined(TARGET_I386)
flags |= CPU_DUMP_CCOP;
#endif
cpu_dump_state(cpu, logfile, flags);
qemu_log_unlock(logfile);
if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
flags |= CPU_DUMP_FPU;
}
#if defined(TARGET_I386)
flags |= CPU_DUMP_CCOP;
#endif
log_cpu_state(cpu, flags);
qemu_log_unlock(logfile);
}
#endif /* DEBUG_DISAS */
}
@@ -388,17 +383,6 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
cc->set_pc(cpu, last_tb->pc);
}
}
/*
* If gdb single-step, and we haven't raised another exception,
* raise a debug exception. Single-step with another exception
* is handled in cpu_handle_exception.
*/
if (unlikely(cpu->singlestep_enabled) && cpu->exception_index == -1) {
cpu->exception_index = EXCP_DEBUG;
cpu_loop_exit(cpu);
}
return last_tb;
}
@@ -423,7 +407,7 @@ static void cpu_exec_exit(CPUState *cpu)
void cpu_exec_step_atomic(CPUState *cpu)
{
CPUArchState *env = cpu->env_ptr;
CPUArchState *env = (CPUArchState *)cpu->env_ptr;
TranslationBlock *tb;
target_ulong cs_base, pc;
uint32_t flags, cflags;
@@ -467,7 +451,6 @@ void cpu_exec_step_atomic(CPUState *cpu)
* memory.
*/
#ifndef CONFIG_SOFTMMU
clear_helper_retaddr();
tcg_debug_assert(!have_mmap_lock());
#endif
if (qemu_mutex_iothread_locked()) {
@@ -477,6 +460,7 @@ void cpu_exec_step_atomic(CPUState *cpu)
qemu_plugin_disable_mem_helpers(cpu);
}
/*
* As we start the exclusive region before codegen we must still
* be in the region if we longjump out of either the codegen or
@@ -533,7 +517,7 @@ TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
struct tb_desc desc;
uint32_t h;
desc.env = cpu->env_ptr;
desc.env = (CPUArchState *)cpu->env_ptr;
desc.cs_base = cs_base;
desc.flags = flags;
desc.cflags = cflags;
@@ -604,9 +588,8 @@ static inline void tb_add_jump(TranslationBlock *tb, int n,
static inline bool cpu_handle_halt(CPUState *cpu)
{
#ifndef CONFIG_USER_ONLY
if (cpu->halted) {
#if defined(TARGET_I386)
#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
X86CPU *x86_cpu = X86_CPU(cpu);
qemu_mutex_lock_iothread();
@@ -614,14 +597,13 @@ static inline bool cpu_handle_halt(CPUState *cpu)
cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
qemu_mutex_unlock_iothread();
}
#endif /* TARGET_I386 */
#endif
if (!cpu_has_work(cpu)) {
return true;
}
cpu->halted = 0;
}
#endif /* !CONFIG_USER_ONLY */
return false;
}
@@ -649,8 +631,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
if (replay_has_exception()
&& cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra == 0) {
/* Execute just one insn to trigger exception pending in the log */
cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT)
| CF_NOIRQ | 1;
cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT) | 1;
}
#endif
return false;
@@ -670,8 +651,8 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
loop */
#if defined(TARGET_I386)
CPUClass *cc = CPU_GET_CLASS(cpu);
cc->tcg_ops->fake_user_interrupt(cpu);
#endif /* TARGET_I386 */
cc->tcg_ops->do_interrupt(cpu);
#endif
*ret = cpu->exception_index;
cpu->exception_index = -1;
return true;
@@ -704,7 +685,6 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
return false;
}
#ifndef CONFIG_USER_ONLY
/*
* CPU_INTERRUPT_POLL is a virtual event which gets converted into a
* "real" interrupt event later. It does not need to be recorded for
@@ -718,19 +698,11 @@ static inline bool need_replay_interrupt(int interrupt_request)
return true;
#endif
}
#endif /* !CONFIG_USER_ONLY */
static inline bool cpu_handle_interrupt(CPUState *cpu,
TranslationBlock **last_tb)
{
/*
* If we have requested custom cflags with CF_NOIRQ we should
* skip checking here. Any pending interrupts will get picked up
* by the next TB we execute under normal cflags.
*/
if (cpu->cflags_next_tb != -1 && cpu->cflags_next_tb & CF_NOIRQ) {
return false;
}
CPUClass *cc = CPU_GET_CLASS(cpu);
/* Clear the interrupt flag now since we're processing
* cpu->interrupt_request and cpu->exit_request.
@@ -753,7 +725,6 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
qemu_mutex_unlock_iothread();
return true;
}
#if !defined(CONFIG_USER_ONLY)
if (replay_mode == REPLAY_MODE_PLAY && !replay_has_interrupt()) {
/* Do nothing */
} else if (interrupt_request & CPU_INTERRUPT_HALT) {
@@ -782,14 +753,12 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
qemu_mutex_unlock_iothread();
return true;
}
#endif /* !TARGET_I386 */
#endif
/* The target hook has 3 exit conditions:
False when the interrupt isn't processed,
True when it is, and we should restart on a new TB,
and via longjmp via cpu_loop_exit. */
else {
CPUClass *cc = CPU_GET_CLASS(cpu);
if (cc->tcg_ops->cpu_exec_interrupt &&
cc->tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) {
if (need_replay_interrupt(interrupt_request)) {
@@ -800,19 +769,14 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
* raised when single-stepping so that GDB doesn't miss the
* next instruction.
*/
if (unlikely(cpu->singlestep_enabled)) {
cpu->exception_index = EXCP_DEBUG;
qemu_mutex_unlock_iothread();
return true;
}
cpu->exception_index = -1;
cpu->exception_index =
(cpu->singlestep_enabled ? EXCP_DEBUG : -1);
*last_tb = NULL;
}
/* The target hook may have updated the 'cpu->interrupt_request';
* reload the 'interrupt_request' value */
interrupt_request = cpu->interrupt_request;
}
#endif /* !CONFIG_USER_ONLY */
if (interrupt_request & CPU_INTERRUPT_EXITTB) {
cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
/* ensure that no TB jump will be modified as
@@ -935,7 +899,6 @@ int cpu_exec(CPUState *cpu)
#endif
#ifndef CONFIG_SOFTMMU
clear_helper_retaddr();
tcg_debug_assert(!have_mmap_lock());
#endif
if (qemu_mutex_iothread_locked()) {
@@ -1048,83 +1011,23 @@ void tcg_exec_unrealizefn(CPUState *cpu)
#ifndef CONFIG_USER_ONLY
static void dump_drift_info(GString *buf)
void dump_drift_info(void)
{
if (!icount_enabled()) {
return;
}
g_string_append_printf(buf, "Host - Guest clock %"PRIi64" ms\n",
(cpu_get_clock() - icount_get()) / SCALE_MS);
qemu_printf("Host - Guest clock %"PRIi64" ms\n",
(cpu_get_clock() - icount_get()) / SCALE_MS);
if (icount_align_option) {
g_string_append_printf(buf, "Max guest delay %"PRIi64" ms\n",
-max_delay / SCALE_MS);
g_string_append_printf(buf, "Max guest advance %"PRIi64" ms\n",
max_advance / SCALE_MS);
qemu_printf("Max guest delay %"PRIi64" ms\n",
-max_delay / SCALE_MS);
qemu_printf("Max guest advance %"PRIi64" ms\n",
max_advance / SCALE_MS);
} else {
g_string_append_printf(buf, "Max guest delay NA\n");
g_string_append_printf(buf, "Max guest advance NA\n");
qemu_printf("Max guest delay NA\n");
qemu_printf("Max guest advance NA\n");
}
}
HumanReadableText *qmp_x_query_jit(Error **errp)
{
g_autoptr(GString) buf = g_string_new("");
if (!tcg_enabled()) {
error_setg(errp, "JIT information is only available with accel=tcg");
return NULL;
}
dump_exec_info(buf);
dump_drift_info(buf);
return human_readable_text_from_str(buf);
}
HumanReadableText *qmp_x_query_opcount(Error **errp)
{
g_autoptr(GString) buf = g_string_new("");
if (!tcg_enabled()) {
error_setg(errp, "Opcode count information is only available with accel=tcg");
return NULL;
}
tcg_dump_op_count(buf);
return human_readable_text_from_str(buf);
}
#ifdef CONFIG_PROFILER
int64_t dev_time;
HumanReadableText *qmp_x_query_profile(Error **errp)
{
g_autoptr(GString) buf = g_string_new("");
static int64_t last_cpu_exec_time;
int64_t cpu_exec_time;
int64_t delta;
cpu_exec_time = tcg_cpu_exec_time();
delta = cpu_exec_time - last_cpu_exec_time;
g_string_append_printf(buf, "async time %" PRId64 " (%0.3f)\n",
dev_time, dev_time / (double)NANOSECONDS_PER_SECOND);
g_string_append_printf(buf, "qemu time %" PRId64 " (%0.3f)\n",
delta, delta / (double)NANOSECONDS_PER_SECOND);
last_cpu_exec_time = cpu_exec_time;
dev_time = 0;
return human_readable_text_from_str(buf);
}
#else
HumanReadableText *qmp_x_query_profile(Error **errp)
{
error_setg(errp, "Internal profiler not compiled");
return NULL;
}
#endif
#endif /* !CONFIG_USER_ONLY */

View File

@@ -34,12 +34,12 @@
#include "qemu/atomic128.h"
#include "exec/translate-all.h"
#include "trace/trace-root.h"
#include "trace/mem.h"
#include "tb-hash.h"
#include "internal.h"
#ifdef CONFIG_PLUGIN
#include "qemu/plugin-memory.h"
#endif
#include "tcg/tcg-ldst.h"
/* DEBUG defines, enable DEBUG_TLB_LOG to log to the CPU_LOG_MMU target */
/* #define DEBUG_TLB */
@@ -783,15 +783,6 @@ static void tlb_flush_range_by_mmuidx_async_0(CPUState *cpu,
}
qemu_spin_unlock(&env_tlb(env)->c.lock);
/*
* If the length is larger than the jump cache size, then it will take
* longer to clear each entry individually than it will to clear it all.
*/
if (d.len >= (TARGET_PAGE_SIZE * TB_JMP_CACHE_SIZE)) {
cpu_tb_jmp_cache_clear(cpu);
return;
}
for (target_ulong i = 0; i < d.len; i += TARGET_PAGE_SIZE) {
tb_flush_jmp_cache(cpu, d.addr + i);
}
@@ -1758,10 +1749,10 @@ bool tlb_plugin_lookup(CPUState *cpu, target_ulong addr, int mmu_idx,
* @prot may be PAGE_READ, PAGE_WRITE, or PAGE_READ|PAGE_WRITE.
*/
static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
MemOpIdx oi, int size, int prot,
TCGMemOpIdx oi, int size, int prot,
uintptr_t retaddr)
{
uintptr_t mmu_idx = get_mmuidx(oi);
size_t mmu_idx = get_mmuidx(oi);
MemOp mop = get_memop(oi);
int a_bits = get_alignment_bits(mop);
uintptr_t index;
@@ -1769,8 +1760,6 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
target_ulong tlb_addr;
void *hostaddr;
tcg_debug_assert(mmu_idx < NB_MMU_MODES);
/* Adjust the given return address. */
retaddr -= GETPC_ADJ;
@@ -1851,25 +1840,6 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
cpu_loop_exit_atomic(env_cpu(env), retaddr);
}
/*
* Verify that we have passed the correct MemOp to the correct function.
*
* In the case of the helper_*_mmu functions, we will have done this by
* using the MemOp to look up the helper during code generation.
*
* In the case of the cpu_*_mmu functions, this is up to the caller.
* We could present one function to target code, and dispatch based on
* the MemOp, but so far we have worked hard to avoid an indirect function
* call along the memory path.
*/
static void validate_memop(MemOpIdx oi, MemOp expected)
{
#ifdef CONFIG_DEBUG_TCG
MemOp have = get_memop(oi) & (MO_SIZE | MO_BSWAP);
assert(have == expected);
#endif
}
/*
* Load Helpers
*
@@ -1880,7 +1850,7 @@ static void validate_memop(MemOpIdx oi, MemOp expected)
*/
typedef uint64_t FullLoadHelper(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr);
TCGMemOpIdx oi, uintptr_t retaddr);
static inline uint64_t QEMU_ALWAYS_INLINE
load_memop(const void *haddr, MemOp op)
@@ -1896,9 +1866,9 @@ load_memop(const void *haddr, MemOp op)
return (uint32_t)ldl_be_p(haddr);
case MO_LEUL:
return (uint32_t)ldl_le_p(haddr);
case MO_BEUQ:
case MO_BEQ:
return ldq_be_p(haddr);
case MO_LEUQ:
case MO_LEQ:
return ldq_le_p(haddr);
default:
qemu_build_not_reached();
@@ -1906,24 +1876,22 @@ load_memop(const void *haddr, MemOp op)
}
static inline uint64_t QEMU_ALWAYS_INLINE
load_helper(CPUArchState *env, target_ulong addr, MemOpIdx oi,
load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
uintptr_t retaddr, MemOp op, bool code_read,
FullLoadHelper *full_load)
{
uintptr_t mmu_idx = get_mmuidx(oi);
uintptr_t index = tlb_index(env, mmu_idx, addr);
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
target_ulong tlb_addr = code_read ? entry->addr_code : entry->addr_read;
const size_t tlb_off = code_read ?
offsetof(CPUTLBEntry, addr_code) : offsetof(CPUTLBEntry, addr_read);
const MMUAccessType access_type =
code_read ? MMU_INST_FETCH : MMU_DATA_LOAD;
const unsigned a_bits = get_alignment_bits(get_memop(oi));
const size_t size = memop_size(op);
uintptr_t mmu_idx = get_mmuidx(oi);
uintptr_t index;
CPUTLBEntry *entry;
target_ulong tlb_addr;
unsigned a_bits = get_alignment_bits(get_memop(oi));
void *haddr;
uint64_t res;
tcg_debug_assert(mmu_idx < NB_MMU_MODES);
size_t size = memop_size(op);
/* Handle CPU specific unaligned behaviour */
if (addr & ((1 << a_bits) - 1)) {
@@ -1931,10 +1899,6 @@ load_helper(CPUArchState *env, target_ulong addr, MemOpIdx oi,
mmu_idx, retaddr);
}
index = tlb_index(env, mmu_idx, addr);
entry = tlb_entry(env, mmu_idx, addr);
tlb_addr = code_read ? entry->addr_code : entry->addr_read;
/* If the TLB entry is for a different page, reload and try again. */
if (!tlb_hit(tlb_addr, addr)) {
if (!victim_tlb_hit(env, mmu_idx, index, tlb_off,
@@ -2027,87 +1991,80 @@ load_helper(CPUArchState *env, target_ulong addr, MemOpIdx oi,
*/
static uint64_t full_ldub_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_UB);
return load_helper(env, addr, oi, retaddr, MO_UB, false, full_ldub_mmu);
}
tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
return full_ldub_mmu(env, addr, oi, retaddr);
}
static uint64_t full_le_lduw_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_LEUW);
return load_helper(env, addr, oi, retaddr, MO_LEUW, false,
full_le_lduw_mmu);
}
tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
return full_le_lduw_mmu(env, addr, oi, retaddr);
}
static uint64_t full_be_lduw_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_BEUW);
return load_helper(env, addr, oi, retaddr, MO_BEUW, false,
full_be_lduw_mmu);
}
tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
return full_be_lduw_mmu(env, addr, oi, retaddr);
}
static uint64_t full_le_ldul_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_LEUL);
return load_helper(env, addr, oi, retaddr, MO_LEUL, false,
full_le_ldul_mmu);
}
tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
return full_le_ldul_mmu(env, addr, oi, retaddr);
}
static uint64_t full_be_ldul_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_BEUL);
return load_helper(env, addr, oi, retaddr, MO_BEUL, false,
full_be_ldul_mmu);
}
tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
return full_be_ldul_mmu(env, addr, oi, retaddr);
}
uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_LEUQ);
return load_helper(env, addr, oi, retaddr, MO_LEUQ, false,
return load_helper(env, addr, oi, retaddr, MO_LEQ, false,
helper_le_ldq_mmu);
}
uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_BEUQ);
return load_helper(env, addr, oi, retaddr, MO_BEUQ, false,
return load_helper(env, addr, oi, retaddr, MO_BEQ, false,
helper_be_ldq_mmu);
}
@@ -2118,31 +2075,31 @@ uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
tcg_target_ulong helper_ret_ldsb_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
return (int8_t)helper_ret_ldub_mmu(env, addr, oi, retaddr);
}
tcg_target_ulong helper_le_ldsw_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
return (int16_t)helper_le_lduw_mmu(env, addr, oi, retaddr);
}
tcg_target_ulong helper_be_ldsw_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
return (int16_t)helper_be_lduw_mmu(env, addr, oi, retaddr);
}
tcg_target_ulong helper_le_ldsl_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
return (int32_t)helper_le_ldul_mmu(env, addr, oi, retaddr);
}
tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
return (int32_t)helper_be_ldul_mmu(env, addr, oi, retaddr);
}
@@ -2152,55 +2109,193 @@ tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
*/
static inline uint64_t cpu_load_helper(CPUArchState *env, abi_ptr addr,
MemOpIdx oi, uintptr_t retaddr,
FullLoadHelper *full_load)
int mmu_idx, uintptr_t retaddr,
MemOp op, FullLoadHelper *full_load)
{
uint16_t meminfo;
TCGMemOpIdx oi;
uint64_t ret;
meminfo = trace_mem_get_info(op, mmu_idx, false);
trace_guest_mem_before_exec(env_cpu(env), addr, meminfo);
op &= ~MO_SIGN;
oi = make_memop_idx(op, mmu_idx);
ret = full_load(env, addr, oi, retaddr);
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, meminfo);
return ret;
}
uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr addr, MemOpIdx oi, uintptr_t ra)
uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
return cpu_load_helper(env, addr, oi, ra, full_ldub_mmu);
return cpu_load_helper(env, addr, mmu_idx, ra, MO_UB, full_ldub_mmu);
}
uint16_t cpu_ldw_be_mmu(CPUArchState *env, abi_ptr addr,
MemOpIdx oi, uintptr_t ra)
int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
return cpu_load_helper(env, addr, oi, ra, full_be_lduw_mmu);
return (int8_t)cpu_load_helper(env, addr, mmu_idx, ra, MO_SB,
full_ldub_mmu);
}
uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr addr,
MemOpIdx oi, uintptr_t ra)
uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
return cpu_load_helper(env, addr, oi, ra, full_be_ldul_mmu);
return cpu_load_helper(env, addr, mmu_idx, ra, MO_BEUW, full_be_lduw_mmu);
}
uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr,
MemOpIdx oi, uintptr_t ra)
int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
return cpu_load_helper(env, addr, oi, ra, helper_be_ldq_mmu);
return (int16_t)cpu_load_helper(env, addr, mmu_idx, ra, MO_BESW,
full_be_lduw_mmu);
}
uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr addr,
MemOpIdx oi, uintptr_t ra)
uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
return cpu_load_helper(env, addr, oi, ra, full_le_lduw_mmu);
return cpu_load_helper(env, addr, mmu_idx, ra, MO_BEUL, full_be_ldul_mmu);
}
uint32_t cpu_ldl_le_mmu(CPUArchState *env, abi_ptr addr,
MemOpIdx oi, uintptr_t ra)
uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
return cpu_load_helper(env, addr, oi, ra, full_le_ldul_mmu);
return cpu_load_helper(env, addr, mmu_idx, ra, MO_BEQ, helper_be_ldq_mmu);
}
uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr addr,
MemOpIdx oi, uintptr_t ra)
uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
return cpu_load_helper(env, addr, oi, ra, helper_le_ldq_mmu);
return cpu_load_helper(env, addr, mmu_idx, ra, MO_LEUW, full_le_lduw_mmu);
}
int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
return (int16_t)cpu_load_helper(env, addr, mmu_idx, ra, MO_LESW,
full_le_lduw_mmu);
}
uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
return cpu_load_helper(env, addr, mmu_idx, ra, MO_LEUL, full_le_ldul_mmu);
}
uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
return cpu_load_helper(env, addr, mmu_idx, ra, MO_LEQ, helper_le_ldq_mmu);
}
uint32_t cpu_ldub_data_ra(CPUArchState *env, target_ulong ptr,
uintptr_t retaddr)
{
return cpu_ldub_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
}
int cpu_ldsb_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr)
{
return cpu_ldsb_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
}
uint32_t cpu_lduw_be_data_ra(CPUArchState *env, target_ulong ptr,
uintptr_t retaddr)
{
return cpu_lduw_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
}
int cpu_ldsw_be_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr)
{
return cpu_ldsw_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
}
uint32_t cpu_ldl_be_data_ra(CPUArchState *env, target_ulong ptr,
uintptr_t retaddr)
{
return cpu_ldl_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
}
uint64_t cpu_ldq_be_data_ra(CPUArchState *env, target_ulong ptr,
uintptr_t retaddr)
{
return cpu_ldq_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
}
uint32_t cpu_lduw_le_data_ra(CPUArchState *env, target_ulong ptr,
uintptr_t retaddr)
{
return cpu_lduw_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
}
int cpu_ldsw_le_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr)
{
return cpu_ldsw_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
}
uint32_t cpu_ldl_le_data_ra(CPUArchState *env, target_ulong ptr,
uintptr_t retaddr)
{
return cpu_ldl_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
}
uint64_t cpu_ldq_le_data_ra(CPUArchState *env, target_ulong ptr,
uintptr_t retaddr)
{
return cpu_ldq_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
}
uint32_t cpu_ldub_data(CPUArchState *env, target_ulong ptr)
{
return cpu_ldub_data_ra(env, ptr, 0);
}
int cpu_ldsb_data(CPUArchState *env, target_ulong ptr)
{
return cpu_ldsb_data_ra(env, ptr, 0);
}
uint32_t cpu_lduw_be_data(CPUArchState *env, target_ulong ptr)
{
return cpu_lduw_be_data_ra(env, ptr, 0);
}
int cpu_ldsw_be_data(CPUArchState *env, target_ulong ptr)
{
return cpu_ldsw_be_data_ra(env, ptr, 0);
}
uint32_t cpu_ldl_be_data(CPUArchState *env, target_ulong ptr)
{
return cpu_ldl_be_data_ra(env, ptr, 0);
}
uint64_t cpu_ldq_be_data(CPUArchState *env, target_ulong ptr)
{
return cpu_ldq_be_data_ra(env, ptr, 0);
}
uint32_t cpu_lduw_le_data(CPUArchState *env, target_ulong ptr)
{
return cpu_lduw_le_data_ra(env, ptr, 0);
}
int cpu_ldsw_le_data(CPUArchState *env, target_ulong ptr)
{
return cpu_ldsw_le_data_ra(env, ptr, 0);
}
uint32_t cpu_ldl_le_data(CPUArchState *env, target_ulong ptr)
{
return cpu_ldl_le_data_ra(env, ptr, 0);
}
uint64_t cpu_ldq_le_data(CPUArchState *env, target_ulong ptr)
{
return cpu_ldq_le_data_ra(env, ptr, 0);
}
/*
@@ -2226,10 +2321,10 @@ store_memop(void *haddr, uint64_t val, MemOp op)
case MO_LEUL:
stl_le_p(haddr, val);
break;
case MO_BEUQ:
case MO_BEQ:
stq_be_p(haddr, val);
break;
case MO_LEUQ:
case MO_LEQ:
stq_le_p(haddr, val);
break;
default:
@@ -2237,9 +2332,6 @@ store_memop(void *haddr, uint64_t val, MemOp op)
}
}
static void full_stb_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr);
static void __attribute__((noinline))
store_helper_unaligned(CPUArchState *env, target_ulong addr, uint64_t val,
uintptr_t retaddr, size_t size, uintptr_t mmu_idx,
@@ -2248,25 +2340,23 @@ store_helper_unaligned(CPUArchState *env, target_ulong addr, uint64_t val,
const size_t tlb_off = offsetof(CPUTLBEntry, addr_write);
uintptr_t index, index2;
CPUTLBEntry *entry, *entry2;
target_ulong page1, page2, tlb_addr, tlb_addr2;
MemOpIdx oi;
target_ulong page2, tlb_addr, tlb_addr2;
TCGMemOpIdx oi;
size_t size2;
int i;
/*
* Ensure the second page is in the TLB. Note that the first page
* is already guaranteed to be filled, and that the second page
* cannot evict the first. An exception to this rule is PAGE_WRITE_INV
* handling: the first page could have evicted itself.
* cannot evict the first.
*/
page1 = addr & TARGET_PAGE_MASK;
page2 = (addr + size) & TARGET_PAGE_MASK;
size2 = (addr + size) & ~TARGET_PAGE_MASK;
index2 = tlb_index(env, mmu_idx, page2);
entry2 = tlb_entry(env, mmu_idx, page2);
tlb_addr2 = tlb_addr_write(entry2);
if (page1 != page2 && !tlb_hit_page(tlb_addr2, page2)) {
if (!tlb_hit_page(tlb_addr2, page2)) {
if (!victim_tlb_hit(env, mmu_idx, index2, tlb_off, page2)) {
tlb_fill(env_cpu(env), page2, size2, MMU_DATA_STORE,
mmu_idx, retaddr);
@@ -2305,31 +2395,29 @@ store_helper_unaligned(CPUArchState *env, target_ulong addr, uint64_t val,
for (i = 0; i < size; ++i) {
/* Big-endian extract. */
uint8_t val8 = val >> (((size - 1) * 8) - (i * 8));
full_stb_mmu(env, addr + i, val8, oi, retaddr);
helper_ret_stb_mmu(env, addr + i, val8, oi, retaddr);
}
} else {
for (i = 0; i < size; ++i) {
/* Little-endian extract. */
uint8_t val8 = val >> (i * 8);
full_stb_mmu(env, addr + i, val8, oi, retaddr);
helper_ret_stb_mmu(env, addr + i, val8, oi, retaddr);
}
}
}
static inline void QEMU_ALWAYS_INLINE
store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr, MemOp op)
TCGMemOpIdx oi, uintptr_t retaddr, MemOp op)
{
const size_t tlb_off = offsetof(CPUTLBEntry, addr_write);
const unsigned a_bits = get_alignment_bits(get_memop(oi));
const size_t size = memop_size(op);
uintptr_t mmu_idx = get_mmuidx(oi);
uintptr_t index;
CPUTLBEntry *entry;
target_ulong tlb_addr;
uintptr_t index = tlb_index(env, mmu_idx, addr);
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
target_ulong tlb_addr = tlb_addr_write(entry);
const size_t tlb_off = offsetof(CPUTLBEntry, addr_write);
unsigned a_bits = get_alignment_bits(get_memop(oi));
void *haddr;
tcg_debug_assert(mmu_idx < NB_MMU_MODES);
size_t size = memop_size(op);
/* Handle CPU specific unaligned behaviour */
if (addr & ((1 << a_bits) - 1)) {
@@ -2337,10 +2425,6 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
mmu_idx, retaddr);
}
index = tlb_index(env, mmu_idx, addr);
entry = tlb_entry(env, mmu_idx, addr);
tlb_addr = tlb_addr_write(entry);
/* If the TLB entry is for a different page, reload and try again. */
if (!tlb_hit(tlb_addr, addr)) {
if (!victim_tlb_hit(env, mmu_idx, index, tlb_off,
@@ -2420,144 +2504,187 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
store_memop(haddr, val, op);
}
static void __attribute__((noinline))
full_stb_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr)
void __attribute__((noinline))
helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
TCGMemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_UB);
store_helper(env, addr, val, oi, retaddr, MO_UB);
}
void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
MemOpIdx oi, uintptr_t retaddr)
void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
TCGMemOpIdx oi, uintptr_t retaddr)
{
full_stb_mmu(env, addr, val, oi, retaddr);
}
static void full_le_stw_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_LEUW);
store_helper(env, addr, val, oi, retaddr, MO_LEUW);
}
void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
MemOpIdx oi, uintptr_t retaddr)
void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
TCGMemOpIdx oi, uintptr_t retaddr)
{
full_le_stw_mmu(env, addr, val, oi, retaddr);
}
static void full_be_stw_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_BEUW);
store_helper(env, addr, val, oi, retaddr, MO_BEUW);
}
void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
MemOpIdx oi, uintptr_t retaddr)
void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
TCGMemOpIdx oi, uintptr_t retaddr)
{
full_be_stw_mmu(env, addr, val, oi, retaddr);
}
static void full_le_stl_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_LEUL);
store_helper(env, addr, val, oi, retaddr, MO_LEUL);
}
void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
MemOpIdx oi, uintptr_t retaddr)
void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
TCGMemOpIdx oi, uintptr_t retaddr)
{
full_le_stl_mmu(env, addr, val, oi, retaddr);
}
static void full_be_stl_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_BEUL);
store_helper(env, addr, val, oi, retaddr, MO_BEUL);
}
void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
MemOpIdx oi, uintptr_t retaddr)
{
full_be_stl_mmu(env, addr, val, oi, retaddr);
}
void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_LEUQ);
store_helper(env, addr, val, oi, retaddr, MO_LEUQ);
store_helper(env, addr, val, oi, retaddr, MO_LEQ);
}
void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_BEUQ);
store_helper(env, addr, val, oi, retaddr, MO_BEUQ);
store_helper(env, addr, val, oi, retaddr, MO_BEQ);
}
/*
* Store Helpers for cpu_ldst.h
*/
typedef void FullStoreHelper(CPUArchState *env, target_ulong addr,
uint64_t val, MemOpIdx oi, uintptr_t retaddr);
static inline void cpu_store_helper(CPUArchState *env, target_ulong addr,
uint64_t val, MemOpIdx oi, uintptr_t ra,
FullStoreHelper *full_store)
static inline void QEMU_ALWAYS_INLINE
cpu_store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
int mmu_idx, uintptr_t retaddr, MemOp op)
{
full_store(env, addr, val, oi, ra);
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
TCGMemOpIdx oi;
uint16_t meminfo;
meminfo = trace_mem_get_info(op, mmu_idx, true);
trace_guest_mem_before_exec(env_cpu(env), addr, meminfo);
oi = make_memop_idx(op, mmu_idx);
store_helper(env, addr, val, oi, retaddr, op);
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, meminfo);
}
void cpu_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
MemOpIdx oi, uintptr_t retaddr)
void cpu_stb_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
int mmu_idx, uintptr_t retaddr)
{
cpu_store_helper(env, addr, val, oi, retaddr, full_stb_mmu);
cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_UB);
}
void cpu_stw_be_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
MemOpIdx oi, uintptr_t retaddr)
void cpu_stw_be_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
int mmu_idx, uintptr_t retaddr)
{
cpu_store_helper(env, addr, val, oi, retaddr, full_be_stw_mmu);
cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_BEUW);
}
void cpu_stl_be_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
MemOpIdx oi, uintptr_t retaddr)
void cpu_stl_be_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
int mmu_idx, uintptr_t retaddr)
{
cpu_store_helper(env, addr, val, oi, retaddr, full_be_stl_mmu);
cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_BEUL);
}
void cpu_stq_be_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr)
void cpu_stq_be_mmuidx_ra(CPUArchState *env, target_ulong addr, uint64_t val,
int mmu_idx, uintptr_t retaddr)
{
cpu_store_helper(env, addr, val, oi, retaddr, helper_be_stq_mmu);
cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_BEQ);
}
void cpu_stw_le_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
MemOpIdx oi, uintptr_t retaddr)
void cpu_stw_le_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
int mmu_idx, uintptr_t retaddr)
{
cpu_store_helper(env, addr, val, oi, retaddr, full_le_stw_mmu);
cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_LEUW);
}
void cpu_stl_le_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
MemOpIdx oi, uintptr_t retaddr)
void cpu_stl_le_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
int mmu_idx, uintptr_t retaddr)
{
cpu_store_helper(env, addr, val, oi, retaddr, full_le_stl_mmu);
cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_LEUL);
}
void cpu_stq_le_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr)
void cpu_stq_le_mmuidx_ra(CPUArchState *env, target_ulong addr, uint64_t val,
int mmu_idx, uintptr_t retaddr)
{
cpu_store_helper(env, addr, val, oi, retaddr, helper_le_stq_mmu);
cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_LEQ);
}
#include "ldst_common.c.inc"
void cpu_stb_data_ra(CPUArchState *env, target_ulong ptr,
uint32_t val, uintptr_t retaddr)
{
cpu_stb_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
}
void cpu_stw_be_data_ra(CPUArchState *env, target_ulong ptr,
uint32_t val, uintptr_t retaddr)
{
cpu_stw_be_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
}
void cpu_stl_be_data_ra(CPUArchState *env, target_ulong ptr,
uint32_t val, uintptr_t retaddr)
{
cpu_stl_be_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
}
void cpu_stq_be_data_ra(CPUArchState *env, target_ulong ptr,
uint64_t val, uintptr_t retaddr)
{
cpu_stq_be_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
}
void cpu_stw_le_data_ra(CPUArchState *env, target_ulong ptr,
uint32_t val, uintptr_t retaddr)
{
cpu_stw_le_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
}
void cpu_stl_le_data_ra(CPUArchState *env, target_ulong ptr,
uint32_t val, uintptr_t retaddr)
{
cpu_stl_le_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
}
void cpu_stq_le_data_ra(CPUArchState *env, target_ulong ptr,
uint64_t val, uintptr_t retaddr)
{
cpu_stq_le_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
}
void cpu_stb_data(CPUArchState *env, target_ulong ptr, uint32_t val)
{
cpu_stb_data_ra(env, ptr, val, 0);
}
void cpu_stw_be_data(CPUArchState *env, target_ulong ptr, uint32_t val)
{
cpu_stw_be_data_ra(env, ptr, val, 0);
}
void cpu_stl_be_data(CPUArchState *env, target_ulong ptr, uint32_t val)
{
cpu_stl_be_data_ra(env, ptr, val, 0);
}
void cpu_stq_be_data(CPUArchState *env, target_ulong ptr, uint64_t val)
{
cpu_stq_be_data_ra(env, ptr, val, 0);
}
void cpu_stw_le_data(CPUArchState *env, target_ulong ptr, uint32_t val)
{
cpu_stw_le_data_ra(env, ptr, val, 0);
}
void cpu_stl_le_data(CPUArchState *env, target_ulong ptr, uint32_t val)
{
cpu_stl_le_data_ra(env, ptr, val, 0);
}
void cpu_stq_le_data(CPUArchState *env, target_ulong ptr, uint64_t val)
{
cpu_stq_le_data_ra(env, ptr, val, 0);
}
/*
* First set of functions passes in OI and RETADDR.
@@ -2568,6 +2695,7 @@ void cpu_stq_le_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
glue(glue(glue(cpu_atomic_ ## X, SUFFIX), END), _mmu)
#define ATOMIC_MMU_CLEANUP
#define ATOMIC_MMU_IDX get_mmuidx(oi)
#include "atomic_common.c.inc"
@@ -2593,49 +2721,49 @@ void cpu_stq_le_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
/* Code access functions. */
static uint64_t full_ldub_code(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, MO_8, true, full_ldub_code);
}
uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr addr)
{
MemOpIdx oi = make_memop_idx(MO_UB, cpu_mmu_index(env, true));
TCGMemOpIdx oi = make_memop_idx(MO_UB, cpu_mmu_index(env, true));
return full_ldub_code(env, addr, oi, 0);
}
static uint64_t full_lduw_code(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, MO_TEUW, true, full_lduw_code);
}
uint32_t cpu_lduw_code(CPUArchState *env, abi_ptr addr)
{
MemOpIdx oi = make_memop_idx(MO_TEUW, cpu_mmu_index(env, true));
TCGMemOpIdx oi = make_memop_idx(MO_TEUW, cpu_mmu_index(env, true));
return full_lduw_code(env, addr, oi, 0);
}
static uint64_t full_ldl_code(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, MO_TEUL, true, full_ldl_code);
}
uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr addr)
{
MemOpIdx oi = make_memop_idx(MO_TEUL, cpu_mmu_index(env, true));
TCGMemOpIdx oi = make_memop_idx(MO_TEUL, cpu_mmu_index(env, true));
return full_ldl_code(env, addr, oi, 0);
}
static uint64_t full_ldq_code(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
TCGMemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, MO_TEUQ, true, full_ldq_code);
return load_helper(env, addr, oi, retaddr, MO_TEQ, true, full_ldq_code);
}
uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr addr)
{
MemOpIdx oi = make_memop_idx(MO_TEUQ, cpu_mmu_index(env, true));
TCGMemOpIdx oi = make_memop_idx(MO_TEQ, cpu_mmu_index(env, true));
return full_ldq_code(env, addr, oi, 0);
}

View File

@@ -1,14 +1,29 @@
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-machine.h"
#include "exec/exec-all.h"
#include "monitor/monitor.h"
#include "sysemu/tcg.h"
static void hmp_info_jit(Monitor *mon, const QDict *qdict)
{
if (!tcg_enabled()) {
error_report("JIT information is only available with accel=tcg");
return;
}
dump_exec_info();
dump_drift_info();
}
static void hmp_info_opcount(Monitor *mon, const QDict *qdict)
{
dump_opcount_info();
}
static void hmp_tcg_register(void)
{
monitor_register_hmp_info_hrt("jit", qmp_x_query_jit);
monitor_register_hmp_info_hrt("opcount", qmp_x_query_opcount);
monitor_register_hmp("jit", true, hmp_info_jit);
monitor_register_hmp("opcount", true, hmp_info_opcount);
}
type_init(hmp_tcg_register);

View File

@@ -14,7 +14,8 @@
TranslationBlock *tb_gen_code(CPUState *cpu, target_ulong pc,
target_ulong cs_base, uint32_t flags,
int cflags);
G_NORETURN void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr);
void QEMU_NORETURN cpu_io_recompile(CPUState *cpu, uintptr_t retaddr);
void page_init(void);
void tb_htable_init(void);

View File

@@ -1,307 +0,0 @@
/*
* Routines common to user and system emulation of load/store.
*
* Copyright (c) 2003 Fabrice Bellard
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
return cpu_ldb_mmu(env, addr, oi, ra);
}
int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
return (int8_t)cpu_ldub_mmuidx_ra(env, addr, mmu_idx, ra);
}
uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_BEUW | MO_UNALN, mmu_idx);
return cpu_ldw_be_mmu(env, addr, oi, ra);
}
int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
return (int16_t)cpu_lduw_be_mmuidx_ra(env, addr, mmu_idx, ra);
}
uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_BEUL | MO_UNALN, mmu_idx);
return cpu_ldl_be_mmu(env, addr, oi, ra);
}
uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_BEUQ | MO_UNALN, mmu_idx);
return cpu_ldq_be_mmu(env, addr, oi, ra);
}
uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_LEUW | MO_UNALN, mmu_idx);
return cpu_ldw_le_mmu(env, addr, oi, ra);
}
int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
return (int16_t)cpu_lduw_le_mmuidx_ra(env, addr, mmu_idx, ra);
}
uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_LEUL | MO_UNALN, mmu_idx);
return cpu_ldl_le_mmu(env, addr, oi, ra);
}
uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_LEUQ | MO_UNALN, mmu_idx);
return cpu_ldq_le_mmu(env, addr, oi, ra);
}
void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
cpu_stb_mmu(env, addr, val, oi, ra);
}
void cpu_stw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_BEUW | MO_UNALN, mmu_idx);
cpu_stw_be_mmu(env, addr, val, oi, ra);
}
void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_BEUL | MO_UNALN, mmu_idx);
cpu_stl_be_mmu(env, addr, val, oi, ra);
}
void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_BEUQ | MO_UNALN, mmu_idx);
cpu_stq_be_mmu(env, addr, val, oi, ra);
}
void cpu_stw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_LEUW | MO_UNALN, mmu_idx);
cpu_stw_le_mmu(env, addr, val, oi, ra);
}
void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_LEUL | MO_UNALN, mmu_idx);
cpu_stl_le_mmu(env, addr, val, oi, ra);
}
void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_LEUQ | MO_UNALN, mmu_idx);
cpu_stq_le_mmu(env, addr, val, oi, ra);
}
/*--------------------------*/
uint32_t cpu_ldub_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
{
return cpu_ldub_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
}
int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
{
return (int8_t)cpu_ldub_data_ra(env, addr, ra);
}
uint32_t cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
{
return cpu_lduw_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
}
int cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
{
return (int16_t)cpu_lduw_be_data_ra(env, addr, ra);
}
uint32_t cpu_ldl_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
{
return cpu_ldl_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
}
uint64_t cpu_ldq_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
{
return cpu_ldq_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
}
uint32_t cpu_lduw_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
{
return cpu_lduw_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
}
int cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
{
return (int16_t)cpu_lduw_le_data_ra(env, addr, ra);
}
uint32_t cpu_ldl_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
{
return cpu_ldl_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
}
uint64_t cpu_ldq_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
{
return cpu_ldq_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
}
void cpu_stb_data_ra(CPUArchState *env, abi_ptr addr,
uint32_t val, uintptr_t ra)
{
cpu_stb_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
}
void cpu_stw_be_data_ra(CPUArchState *env, abi_ptr addr,
uint32_t val, uintptr_t ra)
{
cpu_stw_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
}
void cpu_stl_be_data_ra(CPUArchState *env, abi_ptr addr,
uint32_t val, uintptr_t ra)
{
cpu_stl_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
}
void cpu_stq_be_data_ra(CPUArchState *env, abi_ptr addr,
uint64_t val, uintptr_t ra)
{
cpu_stq_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
}
void cpu_stw_le_data_ra(CPUArchState *env, abi_ptr addr,
uint32_t val, uintptr_t ra)
{
cpu_stw_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
}
void cpu_stl_le_data_ra(CPUArchState *env, abi_ptr addr,
uint32_t val, uintptr_t ra)
{
cpu_stl_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
}
void cpu_stq_le_data_ra(CPUArchState *env, abi_ptr addr,
uint64_t val, uintptr_t ra)
{
cpu_stq_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
}
/*--------------------------*/
uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr addr)
{
return cpu_ldub_data_ra(env, addr, 0);
}
int cpu_ldsb_data(CPUArchState *env, abi_ptr addr)
{
return (int8_t)cpu_ldub_data(env, addr);
}
uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr addr)
{
return cpu_lduw_be_data_ra(env, addr, 0);
}
int cpu_ldsw_be_data(CPUArchState *env, abi_ptr addr)
{
return (int16_t)cpu_lduw_be_data(env, addr);
}
uint32_t cpu_ldl_be_data(CPUArchState *env, abi_ptr addr)
{
return cpu_ldl_be_data_ra(env, addr, 0);
}
uint64_t cpu_ldq_be_data(CPUArchState *env, abi_ptr addr)
{
return cpu_ldq_be_data_ra(env, addr, 0);
}
uint32_t cpu_lduw_le_data(CPUArchState *env, abi_ptr addr)
{
return cpu_lduw_le_data_ra(env, addr, 0);
}
int cpu_ldsw_le_data(CPUArchState *env, abi_ptr addr)
{
return (int16_t)cpu_lduw_le_data(env, addr);
}
uint32_t cpu_ldl_le_data(CPUArchState *env, abi_ptr addr)
{
return cpu_ldl_le_data_ra(env, addr, 0);
}
uint64_t cpu_ldq_le_data(CPUArchState *env, abi_ptr addr)
{
return cpu_ldq_le_data_ra(env, addr, 0);
}
void cpu_stb_data(CPUArchState *env, abi_ptr addr, uint32_t val)
{
cpu_stb_data_ra(env, addr, val, 0);
}
void cpu_stw_be_data(CPUArchState *env, abi_ptr addr, uint32_t val)
{
cpu_stw_be_data_ra(env, addr, val, 0);
}
void cpu_stl_be_data(CPUArchState *env, abi_ptr addr, uint32_t val)
{
cpu_stl_be_data_ra(env, addr, val, 0);
}
void cpu_stq_be_data(CPUArchState *env, abi_ptr addr, uint64_t val)
{
cpu_stq_be_data_ra(env, addr, val, 0);
}
void cpu_stw_le_data(CPUArchState *env, abi_ptr addr, uint32_t val)
{
cpu_stw_le_data_ra(env, addr, val, 0);
}
void cpu_stl_le_data(CPUArchState *env, abi_ptr addr, uint32_t val)
{
cpu_stl_le_data_ra(env, addr, val, 0);
}
void cpu_stq_le_data(CPUArchState *env, abi_ptr addr, uint64_t val)
{
cpu_stq_le_data_ra(env, addr, val, 0);
}

View File

@@ -10,7 +10,7 @@ tcg_ss.add(files(
))
tcg_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user-exec.c'))
tcg_ss.add(when: 'CONFIG_SOFTMMU', if_false: files('user-exec-stub.c'))
tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c')])
tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c'), libdl])
specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files(

View File

@@ -45,6 +45,7 @@
#include "qemu/osdep.h"
#include "tcg/tcg.h"
#include "tcg/tcg-op.h"
#include "trace/mem.h"
#include "exec/exec-all.h"
#include "exec/plugin-gen.h"
#include "exec/translator.h"
@@ -162,7 +163,11 @@ static void gen_empty_mem_helper(void)
static void gen_plugin_cb_start(enum plugin_gen_from from,
enum plugin_gen_cb type, unsigned wr)
{
TCGOp *op;
tcg_gen_plugin_cb_start(from, type, wr);
op = tcg_last_op();
QSIMPLEQ_INSERT_TAIL(&tcg_ctx->plugin_ops, op, plugin_link);
}
static void gen_wrapped(enum plugin_gen_from from,
@@ -206,9 +211,9 @@ static void gen_mem_wrapped(enum plugin_gen_cb type,
const union mem_gen_fn *f, TCGv addr,
uint32_t info, bool is_mem)
{
enum qemu_plugin_mem_rw rw = get_plugin_meminfo_rw(info);
int wr = !!(info & TRACE_MEM_ST);
gen_plugin_cb_start(PLUGIN_GEN_FROM_MEM, type, rw);
gen_plugin_cb_start(PLUGIN_GEN_FROM_MEM, type, wr);
if (is_mem) {
f->mem_fn(addr, info);
} else {
@@ -702,6 +707,62 @@ static void plugin_gen_disable_mem_helper(const struct qemu_plugin_tb *ptb,
inject_mem_disable_helper(insn, begin_op);
}
static void plugin_inject_cb(const struct qemu_plugin_tb *ptb, TCGOp *begin_op,
int insn_idx)
{
enum plugin_gen_from from = begin_op->args[0];
enum plugin_gen_cb type = begin_op->args[1];
switch (from) {
case PLUGIN_GEN_FROM_TB:
switch (type) {
case PLUGIN_GEN_CB_UDATA:
plugin_gen_tb_udata(ptb, begin_op);
return;
case PLUGIN_GEN_CB_INLINE:
plugin_gen_tb_inline(ptb, begin_op);
return;
default:
g_assert_not_reached();
}
case PLUGIN_GEN_FROM_INSN:
switch (type) {
case PLUGIN_GEN_CB_UDATA:
plugin_gen_insn_udata(ptb, begin_op, insn_idx);
return;
case PLUGIN_GEN_CB_INLINE:
plugin_gen_insn_inline(ptb, begin_op, insn_idx);
return;
case PLUGIN_GEN_ENABLE_MEM_HELPER:
plugin_gen_enable_mem_helper(ptb, begin_op, insn_idx);
return;
default:
g_assert_not_reached();
}
case PLUGIN_GEN_FROM_MEM:
switch (type) {
case PLUGIN_GEN_CB_MEM:
plugin_gen_mem_regular(ptb, begin_op, insn_idx);
return;
case PLUGIN_GEN_CB_INLINE:
plugin_gen_mem_inline(ptb, begin_op, insn_idx);
return;
default:
g_assert_not_reached();
}
case PLUGIN_GEN_AFTER_INSN:
switch (type) {
case PLUGIN_GEN_DISABLE_MEM_HELPER:
plugin_gen_disable_mem_helper(ptb, begin_op, insn_idx);
return;
default:
g_assert_not_reached();
}
default:
g_assert_not_reached();
}
}
/* #define DEBUG_PLUGIN_GEN_OPS */
static void pr_ops(void)
{
@@ -759,117 +820,34 @@ static void pr_ops(void)
static void plugin_gen_inject(const struct qemu_plugin_tb *plugin_tb)
{
TCGOp *op;
int insn_idx = -1;
int insn_idx;
pr_ops();
insn_idx = -1;
QSIMPLEQ_FOREACH(op, &tcg_ctx->plugin_ops, plugin_link) {
enum plugin_gen_from from = op->args[0];
enum plugin_gen_cb type = op->args[1];
QTAILQ_FOREACH(op, &tcg_ctx->ops, link) {
switch (op->opc) {
case INDEX_op_insn_start:
tcg_debug_assert(op->opc == INDEX_op_plugin_cb_start);
/* ENABLE_MEM_HELPER is the first callback of an instruction */
if (from == PLUGIN_GEN_FROM_INSN &&
type == PLUGIN_GEN_ENABLE_MEM_HELPER) {
insn_idx++;
break;
case INDEX_op_plugin_cb_start:
{
enum plugin_gen_from from = op->args[0];
enum plugin_gen_cb type = op->args[1];
switch (from) {
case PLUGIN_GEN_FROM_TB:
{
g_assert(insn_idx == -1);
switch (type) {
case PLUGIN_GEN_CB_UDATA:
plugin_gen_tb_udata(plugin_tb, op);
break;
case PLUGIN_GEN_CB_INLINE:
plugin_gen_tb_inline(plugin_tb, op);
break;
default:
g_assert_not_reached();
}
break;
}
case PLUGIN_GEN_FROM_INSN:
{
g_assert(insn_idx >= 0);
switch (type) {
case PLUGIN_GEN_CB_UDATA:
plugin_gen_insn_udata(plugin_tb, op, insn_idx);
break;
case PLUGIN_GEN_CB_INLINE:
plugin_gen_insn_inline(plugin_tb, op, insn_idx);
break;
case PLUGIN_GEN_ENABLE_MEM_HELPER:
plugin_gen_enable_mem_helper(plugin_tb, op, insn_idx);
break;
default:
g_assert_not_reached();
}
break;
}
case PLUGIN_GEN_FROM_MEM:
{
g_assert(insn_idx >= 0);
switch (type) {
case PLUGIN_GEN_CB_MEM:
plugin_gen_mem_regular(plugin_tb, op, insn_idx);
break;
case PLUGIN_GEN_CB_INLINE:
plugin_gen_mem_inline(plugin_tb, op, insn_idx);
break;
default:
g_assert_not_reached();
}
break;
}
case PLUGIN_GEN_AFTER_INSN:
{
g_assert(insn_idx >= 0);
switch (type) {
case PLUGIN_GEN_DISABLE_MEM_HELPER:
plugin_gen_disable_mem_helper(plugin_tb, op, insn_idx);
break;
default:
g_assert_not_reached();
}
break;
}
default:
g_assert_not_reached();
}
break;
}
default:
/* plugins don't care about any other ops */
break;
}
plugin_inject_cb(plugin_tb, op, insn_idx);
}
pr_ops();
}
bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool mem_only)
{
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
bool ret = false;
if (test_bit(QEMU_PLUGIN_EV_VCPU_TB_TRANS, cpu->plugin_mask)) {
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
int i;
/* reset callbacks */
for (i = 0; i < PLUGIN_N_CB_SUBTYPES; i++) {
if (ptb->cbs[i]) {
g_array_set_size(ptb->cbs[i], 0);
}
}
ptb->n = 0;
ret = true;
QSIMPLEQ_INIT(&tcg_ctx->plugin_ops);
ptb->vaddr = tb->pc;
ptb->vaddr2 = -1;
get_page_addr_code_hostp(cpu->env_ptr, tb->pc, &ptb->haddr1);
@@ -878,9 +856,6 @@ bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool mem_onl
plugin_gen_empty_callback(PLUGIN_GEN_FROM_TB);
}
tcg_ctx->plugin_insn = NULL;
return ret;
}
@@ -889,8 +864,9 @@ void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db)
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
struct qemu_plugin_insn *pinsn;
pinsn = qemu_plugin_tb_insn_get(ptb, db->pc_next);
pinsn = qemu_plugin_tb_insn_get(ptb);
tcg_ctx->plugin_insn = pinsn;
pinsn->vaddr = db->pc_next;
plugin_gen_empty_callback(PLUGIN_GEN_FROM_INSN);
/*
@@ -917,19 +893,23 @@ void plugin_gen_insn_end(void)
plugin_gen_empty_callback(PLUGIN_GEN_AFTER_INSN);
}
/*
* There are cases where we never get to finalise a translation - for
* example a page fault during translation. As a result we shouldn't
* do any clean-up here and make sure things are reset in
* plugin_gen_tb_start.
*/
void plugin_gen_tb_end(CPUState *cpu)
{
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
int i;
/* collect instrumentation requests */
qemu_plugin_tb_trans_cb(cpu, ptb);
/* inject the instrumentation at the appropriate places */
plugin_gen_inject(ptb);
/* clean up */
for (i = 0; i < PLUGIN_N_CB_SUBTYPES; i++) {
if (ptb->cbs[i]) {
g_array_set_size(ptb->cbs[i], 0);
}
}
ptb->n = 0;
tcg_ctx->plugin_insn = NULL;
}

View File

@@ -24,8 +24,9 @@
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "sysemu/tcg.h"
#include "sysemu/replay.h"
#include "sysemu/cpu-timers.h"
#include "qemu/main-loop.h"
#include "qemu/guest-random.h"
#include "exec/exec-all.h"
@@ -84,7 +85,8 @@ void icount_handle_deadline(void)
* Don't interrupt cpu thread, when these events are waiting
* (i.e., there is no checkpoint)
*/
if (deadline == 0) {
if (deadline == 0
&& (replay_mode != REPLAY_MODE_PLAY || replay_has_checkpoint())) {
icount_notify_aio_contexts();
}
}
@@ -108,14 +110,8 @@ void icount_prepare_for_run(CPUState *cpu)
replay_mutex_lock();
if (cpu->icount_budget == 0) {
/*
* We're called without the iothread lock, so must take it while
* we're calling timer handlers.
*/
qemu_mutex_lock_iothread();
if (cpu->icount_budget == 0 && replay_has_checkpoint()) {
icount_notify_aio_contexts();
qemu_mutex_unlock_iothread();
}
}

View File

@@ -7,8 +7,8 @@
* See the COPYING file in the top-level directory.
*/
#ifndef TCG_ACCEL_OPS_ICOUNT_H
#define TCG_ACCEL_OPS_ICOUNT_H
#ifndef TCG_CPUS_ICOUNT_H
#define TCG_CPUS_ICOUNT_H
void icount_handle_deadline(void);
void icount_prepare_for_run(CPUState *cpu);
@@ -16,4 +16,4 @@ void icount_process_data(CPUState *cpu);
void icount_handle_interrupt(CPUState *cpu, int mask);
#endif /* TCG_ACCEL_OPS_ICOUNT_H */
#endif /* TCG_CPUS_ICOUNT_H */

View File

@@ -24,11 +24,10 @@
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "sysemu/tcg.h"
#include "sysemu/replay.h"
#include "sysemu/cpu-timers.h"
#include "qemu/main-loop.h"
#include "qemu/notify.h"
#include "qemu/guest-random.h"
#include "exec/exec-all.h"
#include "hw/boards.h"
@@ -36,26 +35,6 @@
#include "tcg-accel-ops.h"
#include "tcg-accel-ops-mttcg.h"
typedef struct MttcgForceRcuNotifier {
Notifier notifier;
CPUState *cpu;
} MttcgForceRcuNotifier;
static void do_nothing(CPUState *cpu, run_on_cpu_data d)
{
}
static void mttcg_force_rcu(Notifier *notify, void *data)
{
CPUState *cpu = container_of(notify, MttcgForceRcuNotifier, notifier)->cpu;
/*
* Called with rcu_registry_lock held, using async_run_on_cpu() ensures
* that there are no deadlocks.
*/
async_run_on_cpu(cpu, do_nothing, RUN_ON_CPU_NULL);
}
/*
* In the multi-threaded case each vCPU has its own thread. The TLS
* variable current_cpu can be used deep in the code to find the
@@ -64,18 +43,12 @@ static void mttcg_force_rcu(Notifier *notify, void *data)
static void *mttcg_cpu_thread_fn(void *arg)
{
MttcgForceRcuNotifier force_rcu;
CPUState *cpu = arg;
assert(tcg_enabled());
g_assert(!icount_enabled());
tcg_cpu_init_cflags(cpu, current_machine->smp.max_cpus > 1);
rcu_register_thread();
force_rcu.notifier.notify = mttcg_force_rcu;
force_rcu.cpu = cpu;
rcu_add_force_rcu_notifier(&force_rcu.notifier);
tcg_register_thread();
qemu_mutex_lock_iothread();
@@ -127,7 +100,6 @@ static void *mttcg_cpu_thread_fn(void *arg)
tcg_cpus_destroy(cpu);
qemu_mutex_unlock_iothread();
rcu_remove_force_rcu_notifier(&force_rcu.notifier);
rcu_unregister_thread();
return NULL;
}
@@ -141,7 +113,10 @@ void mttcg_start_vcpu_thread(CPUState *cpu)
{
char thread_name[VCPU_THREAD_NAME_SIZE];
cpu->thread = g_new0(QemuThread, 1);
g_assert(tcg_enabled());
tcg_cpu_init_cflags(cpu, current_machine->smp.max_cpus > 1);
cpu->thread = g_malloc0(sizeof(QemuThread));
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(cpu->halt_cond);

View File

@@ -7,8 +7,8 @@
* See the COPYING file in the top-level directory.
*/
#ifndef TCG_ACCEL_OPS_MTTCG_H
#define TCG_ACCEL_OPS_MTTCG_H
#ifndef TCG_CPUS_MTTCG_H
#define TCG_CPUS_MTTCG_H
/* kick MTTCG vCPU thread */
void mttcg_kick_vcpu_thread(CPUState *cpu);
@@ -16,4 +16,4 @@ void mttcg_kick_vcpu_thread(CPUState *cpu);
/* start an mttcg vCPU thread */
void mttcg_start_vcpu_thread(CPUState *cpu);
#endif /* TCG_ACCEL_OPS_MTTCG_H */
#endif /* TCG_CPUS_MTTCG_H */

View File

@@ -24,11 +24,10 @@
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "sysemu/tcg.h"
#include "sysemu/replay.h"
#include "sysemu/cpu-timers.h"
#include "qemu/main-loop.h"
#include "qemu/notify.h"
#include "qemu/guest-random.h"
#include "exec/exec-all.h"
@@ -61,6 +60,8 @@ void rr_kick_vcpu_thread(CPUState *unused)
static QEMUTimer *rr_kick_vcpu_timer;
static CPUState *rr_current_cpu;
#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10)
static inline int64_t rr_next_kick_time(void)
{
return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + TCG_KICK_PERIOD;
@@ -134,11 +135,6 @@ static void rr_deal_with_unplugged_cpus(void)
}
}
static void rr_force_rcu(Notifier *notify, void *data)
{
rr_kick_next_cpu();
}
/*
* In the single-threaded case each vCPU is simulated in turn. If
* there is more than a single vCPU we create a simple timer to kick
@@ -149,15 +145,10 @@ static void rr_force_rcu(Notifier *notify, void *data)
static void *rr_cpu_thread_fn(void *arg)
{
Notifier force_rcu;
CPUState *cpu = arg;
g_assert(tcg_enabled());
tcg_cpu_init_cflags(cpu, false);
assert(tcg_enabled());
rcu_register_thread();
force_rcu.notify = rr_force_rcu;
rcu_add_force_rcu_notifier(&force_rcu);
tcg_register_thread();
qemu_mutex_lock_iothread();
@@ -266,7 +257,6 @@ static void *rr_cpu_thread_fn(void *arg)
rr_deal_with_unplugged_cpus();
}
rcu_remove_force_rcu_notifier(&force_rcu);
rcu_unregister_thread();
return NULL;
}
@@ -277,9 +267,12 @@ void rr_start_vcpu_thread(CPUState *cpu)
static QemuCond *single_tcg_halt_cond;
static QemuThread *single_tcg_cpu_thread;
g_assert(tcg_enabled());
tcg_cpu_init_cflags(cpu, false);
if (!single_tcg_cpu_thread) {
cpu->thread = g_new0(QemuThread, 1);
cpu->halt_cond = g_new0(QemuCond, 1);
cpu->thread = g_malloc0(sizeof(QemuThread));
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(cpu->halt_cond);
/* share a single thread for all cpus with TCG */

View File

@@ -7,8 +7,8 @@
* See the COPYING file in the top-level directory.
*/
#ifndef TCG_ACCEL_OPS_RR_H
#define TCG_ACCEL_OPS_RR_H
#ifndef TCG_CPUS_RR_H
#define TCG_CPUS_RR_H
#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10)
@@ -18,4 +18,4 @@ void rr_kick_vcpu_thread(CPUState *unused);
/* start the round robin vcpu thread */
void rr_start_vcpu_thread(CPUState *cpu);
#endif /* TCG_ACCEL_OPS_RR_H */
#endif /* TCG_CPUS_RR_H */

View File

@@ -26,9 +26,9 @@
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "sysemu/tcg.h"
#include "sysemu/replay.h"
#include "sysemu/cpu-timers.h"
#include "qemu/main-loop.h"
#include "qemu/guest-random.h"
#include "exec/exec-all.h"
@@ -97,17 +97,16 @@ static void tcg_accel_ops_init(AccelOpsClass *ops)
ops->create_vcpu_thread = mttcg_start_vcpu_thread;
ops->kick_vcpu_thread = mttcg_kick_vcpu_thread;
ops->handle_interrupt = tcg_handle_interrupt;
} else if (icount_enabled()) {
ops->create_vcpu_thread = rr_start_vcpu_thread;
ops->kick_vcpu_thread = rr_kick_vcpu_thread;
ops->handle_interrupt = icount_handle_interrupt;
ops->get_virtual_clock = icount_get;
ops->get_elapsed_ticks = icount_get;
} else {
ops->create_vcpu_thread = rr_start_vcpu_thread;
ops->kick_vcpu_thread = rr_kick_vcpu_thread;
if (icount_enabled()) {
ops->handle_interrupt = icount_handle_interrupt;
ops->get_virtual_clock = icount_get;
ops->get_elapsed_ticks = icount_get;
} else {
ops->handle_interrupt = tcg_handle_interrupt;
}
ops->handle_interrupt = tcg_handle_interrupt;
}
}

View File

@@ -9,8 +9,8 @@
* See the COPYING file in the top-level directory.
*/
#ifndef TCG_ACCEL_OPS_H
#define TCG_ACCEL_OPS_H
#ifndef TCG_CPUS_H
#define TCG_CPUS_H
#include "sysemu/cpus.h"
@@ -19,4 +19,4 @@ int tcg_cpus_exec(CPUState *cpu);
void tcg_handle_interrupt(CPUState *cpu, int mask);
void tcg_cpu_init_cflags(CPUState *cpu, bool parallel);
#endif /* TCG_ACCEL_OPS_H */
#endif /* TCG_CPUS_H */

View File

@@ -24,6 +24,7 @@
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "sysemu/tcg.h"
#include "sysemu/cpu-timers.h"
#include "tcg/tcg.h"

View File

@@ -18,6 +18,7 @@
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#define NO_CPU_IO_DEFS
#include "trace.h"
@@ -50,7 +51,6 @@
#include "qemu/qemu-print.h"
#include "qemu/timer.h"
#include "qemu/main-loop.h"
#include "qemu/cacheinfo.h"
#include "exec/log.h"
#include "sysemu/cpus.h"
#include "sysemu/cpu-timers.h"
@@ -1297,8 +1297,31 @@ static inline void tb_page_add(PageDesc *p, TranslationBlock *tb,
invalidate_page_bitmap(p);
#if defined(CONFIG_USER_ONLY)
/* translator_loop() must have made all TB pages non-writable */
assert(!(p->flags & PAGE_WRITE));
if (p->flags & PAGE_WRITE) {
target_ulong addr;
PageDesc *p2;
int prot;
/* force the host page as non writable (writes will have a
page fault + mprotect overhead) */
page_addr &= qemu_host_page_mask;
prot = 0;
for (addr = page_addr; addr < page_addr + qemu_host_page_size;
addr += TARGET_PAGE_SIZE) {
p2 = page_find(addr >> TARGET_PAGE_BITS);
if (!p2) {
continue;
}
prot |= p2->flags;
p2->flags &= ~PAGE_WRITE;
}
mprotect(g2h_untagged(page_addr), qemu_host_page_size,
(prot & PAGE_BITS) & ~PAGE_WRITE);
if (DEBUG_TB_INVALIDATE_GATE) {
printf("protecting code page: 0x" TB_PAGE_ADDR_FMT "\n", page_addr);
}
}
#else
/* if some code is already present, then the pages are already
protected. So we handle the case where only the first TB is
@@ -1527,75 +1550,69 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) &&
qemu_log_in_addr_range(tb->pc)) {
FILE *logfile = qemu_log_trylock();
if (logfile) {
int code_size, data_size;
const tcg_target_ulong *rx_data_gen_ptr;
size_t chunk_start;
int insn = 0;
FILE *logfile = qemu_log_lock();
int code_size, data_size;
const tcg_target_ulong *rx_data_gen_ptr;
size_t chunk_start;
int insn = 0;
if (tcg_ctx->data_gen_ptr) {
rx_data_gen_ptr = tcg_splitwx_to_rx(tcg_ctx->data_gen_ptr);
code_size = (const void *)rx_data_gen_ptr - tb->tc.ptr;
data_size = gen_code_size - code_size;
} else {
rx_data_gen_ptr = 0;
code_size = gen_code_size;
data_size = 0;
}
/* Dump header and the first instruction */
fprintf(logfile, "OUT: [size=%d]\n", gen_code_size);
fprintf(logfile,
" -- guest addr 0x" TARGET_FMT_lx " + tb prologue\n",
tcg_ctx->gen_insn_data[insn][0]);
chunk_start = tcg_ctx->gen_insn_end_off[insn];
disas(logfile, tb->tc.ptr, chunk_start);
/*
* Dump each instruction chunk, wrapping up empty chunks into
* the next instruction. The whole array is offset so the
* first entry is the beginning of the 2nd instruction.
*/
while (insn < tb->icount) {
size_t chunk_end = tcg_ctx->gen_insn_end_off[insn];
if (chunk_end > chunk_start) {
fprintf(logfile, " -- guest addr 0x" TARGET_FMT_lx "\n",
tcg_ctx->gen_insn_data[insn][0]);
disas(logfile, tb->tc.ptr + chunk_start,
chunk_end - chunk_start);
chunk_start = chunk_end;
}
insn++;
}
if (chunk_start < code_size) {
fprintf(logfile, " -- tb slow paths + alignment\n");
disas(logfile, tb->tc.ptr + chunk_start,
code_size - chunk_start);
}
/* Finally dump any data we may have after the block */
if (data_size) {
int i;
fprintf(logfile, " data: [size=%d]\n", data_size);
for (i = 0; i < data_size / sizeof(tcg_target_ulong); i++) {
if (sizeof(tcg_target_ulong) == 8) {
fprintf(logfile,
"0x%08" PRIxPTR ": .quad 0x%016" TCG_PRIlx "\n",
(uintptr_t)&rx_data_gen_ptr[i], rx_data_gen_ptr[i]);
} else if (sizeof(tcg_target_ulong) == 4) {
fprintf(logfile,
"0x%08" PRIxPTR ": .long 0x%08" TCG_PRIlx "\n",
(uintptr_t)&rx_data_gen_ptr[i], rx_data_gen_ptr[i]);
} else {
qemu_build_not_reached();
}
}
}
fprintf(logfile, "\n");
qemu_log_unlock(logfile);
if (tcg_ctx->data_gen_ptr) {
rx_data_gen_ptr = tcg_splitwx_to_rx(tcg_ctx->data_gen_ptr);
code_size = (const void *)rx_data_gen_ptr - tb->tc.ptr;
data_size = gen_code_size - code_size;
} else {
rx_data_gen_ptr = 0;
code_size = gen_code_size;
data_size = 0;
}
/* Dump header and the first instruction */
qemu_log("OUT: [size=%d]\n", gen_code_size);
qemu_log(" -- guest addr 0x" TARGET_FMT_lx " + tb prologue\n",
tcg_ctx->gen_insn_data[insn][0]);
chunk_start = tcg_ctx->gen_insn_end_off[insn];
log_disas(tb->tc.ptr, chunk_start);
/*
* Dump each instruction chunk, wrapping up empty chunks into
* the next instruction. The whole array is offset so the
* first entry is the beginning of the 2nd instruction.
*/
while (insn < tb->icount) {
size_t chunk_end = tcg_ctx->gen_insn_end_off[insn];
if (chunk_end > chunk_start) {
qemu_log(" -- guest addr 0x" TARGET_FMT_lx "\n",
tcg_ctx->gen_insn_data[insn][0]);
log_disas(tb->tc.ptr + chunk_start, chunk_end - chunk_start);
chunk_start = chunk_end;
}
insn++;
}
if (chunk_start < code_size) {
qemu_log(" -- tb slow paths + alignment\n");
log_disas(tb->tc.ptr + chunk_start, code_size - chunk_start);
}
/* Finally dump any data we may have after the block */
if (data_size) {
int i;
qemu_log(" data: [size=%d]\n", data_size);
for (i = 0; i < data_size / sizeof(tcg_target_ulong); i++) {
if (sizeof(tcg_target_ulong) == 8) {
qemu_log("0x%08" PRIxPTR ": .quad 0x%016" TCG_PRIlx "\n",
(uintptr_t)&rx_data_gen_ptr[i], rx_data_gen_ptr[i]);
} else if (sizeof(tcg_target_ulong) == 4) {
qemu_log("0x%08" PRIxPTR ": .long 0x%08" TCG_PRIlx "\n",
(uintptr_t)&rx_data_gen_ptr[i], rx_data_gen_ptr[i]);
} else {
qemu_build_not_reached();
}
}
}
qemu_log("\n");
qemu_log_flush();
qemu_log_unlock(logfile);
}
#endif
@@ -1744,7 +1761,7 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
if (current_tb_modified) {
page_collection_unlock(pages);
/* Force execution of one insn next time. */
cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu);
cpu->cflags_next_tb = 1 | curr_cflags(cpu);
mmap_unlock();
cpu_loop_exit_noexc(cpu);
}
@@ -1912,7 +1929,7 @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc)
#ifdef TARGET_HAS_PRECISE_SMC
if (current_tb_modified) {
/* Force execution of one insn next time. */
cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu);
cpu->cflags_next_tb = 1 | curr_cflags(cpu);
return true;
}
#endif
@@ -1997,7 +2014,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
cpu_loop_exit_noexc(cpu);
}
static void print_qht_statistics(struct qht_stats hst, GString *buf)
static void print_qht_statistics(struct qht_stats hst)
{
uint32_t hgram_opts;
size_t hgram_bins;
@@ -2006,11 +2023,9 @@ static void print_qht_statistics(struct qht_stats hst, GString *buf)
if (!hst.head_buckets) {
return;
}
g_string_append_printf(buf, "TB hash buckets %zu/%zu "
"(%0.2f%% head buckets used)\n",
hst.used_head_buckets, hst.head_buckets,
(double)hst.used_head_buckets /
hst.head_buckets * 100);
qemu_printf("TB hash buckets %zu/%zu (%0.2f%% head buckets used)\n",
hst.used_head_buckets, hst.head_buckets,
(double)hst.used_head_buckets / hst.head_buckets * 100);
hgram_opts = QDIST_PR_BORDER | QDIST_PR_LABELS;
hgram_opts |= QDIST_PR_100X | QDIST_PR_PERCENT;
@@ -2018,9 +2033,8 @@ static void print_qht_statistics(struct qht_stats hst, GString *buf)
hgram_opts |= QDIST_PR_NODECIMAL;
}
hgram = qdist_pr(&hst.occupancy, 10, hgram_opts);
g_string_append_printf(buf, "TB hash occupancy %0.2f%% avg chain occ. "
"Histogram: %s\n",
qdist_avg(&hst.occupancy) * 100, hgram);
qemu_printf("TB hash occupancy %0.2f%% avg chain occ. Histogram: %s\n",
qdist_avg(&hst.occupancy) * 100, hgram);
g_free(hgram);
hgram_opts = QDIST_PR_BORDER | QDIST_PR_LABELS;
@@ -2032,9 +2046,8 @@ static void print_qht_statistics(struct qht_stats hst, GString *buf)
hgram_opts |= QDIST_PR_NODECIMAL | QDIST_PR_NOBINRANGE;
}
hgram = qdist_pr(&hst.chain, hgram_bins, hgram_opts);
g_string_append_printf(buf, "TB hash avg chain %0.3f buckets. "
"Histogram: %s\n",
qdist_avg(&hst.chain), hgram);
qemu_printf("TB hash avg chain %0.3f buckets. Histogram: %s\n",
qdist_avg(&hst.chain), hgram);
g_free(hgram);
}
@@ -2071,7 +2084,7 @@ static gboolean tb_tree_stats_iter(gpointer key, gpointer value, gpointer data)
return false;
}
void dump_exec_info(GString *buf)
void dump_exec_info(void)
{
struct tb_tree_stats tst = {};
struct qht_stats hst;
@@ -2080,48 +2093,49 @@ void dump_exec_info(GString *buf)
tcg_tb_foreach(tb_tree_stats_iter, &tst);
nb_tbs = tst.nb_tbs;
/* XXX: avoid using doubles ? */
g_string_append_printf(buf, "Translation buffer state:\n");
qemu_printf("Translation buffer state:\n");
/*
* Report total code size including the padding and TB structs;
* otherwise users might think "-accel tcg,tb-size" is not honoured.
* For avg host size we use the precise numbers from tb_tree_stats though.
*/
g_string_append_printf(buf, "gen code size %zu/%zu\n",
tcg_code_size(), tcg_code_capacity());
g_string_append_printf(buf, "TB count %zu\n", nb_tbs);
g_string_append_printf(buf, "TB avg target size %zu max=%zu bytes\n",
nb_tbs ? tst.target_size / nb_tbs : 0,
tst.max_target_size);
g_string_append_printf(buf, "TB avg host size %zu bytes "
"(expansion ratio: %0.1f)\n",
nb_tbs ? tst.host_size / nb_tbs : 0,
tst.target_size ?
(double)tst.host_size / tst.target_size : 0);
g_string_append_printf(buf, "cross page TB count %zu (%zu%%)\n",
tst.cross_page,
nb_tbs ? (tst.cross_page * 100) / nb_tbs : 0);
g_string_append_printf(buf, "direct jump count %zu (%zu%%) "
"(2 jumps=%zu %zu%%)\n",
tst.direct_jmp_count,
nb_tbs ? (tst.direct_jmp_count * 100) / nb_tbs : 0,
tst.direct_jmp2_count,
nb_tbs ? (tst.direct_jmp2_count * 100) / nb_tbs : 0);
qemu_printf("gen code size %zu/%zu\n",
tcg_code_size(), tcg_code_capacity());
qemu_printf("TB count %zu\n", nb_tbs);
qemu_printf("TB avg target size %zu max=%zu bytes\n",
nb_tbs ? tst.target_size / nb_tbs : 0,
tst.max_target_size);
qemu_printf("TB avg host size %zu bytes (expansion ratio: %0.1f)\n",
nb_tbs ? tst.host_size / nb_tbs : 0,
tst.target_size ? (double)tst.host_size / tst.target_size : 0);
qemu_printf("cross page TB count %zu (%zu%%)\n", tst.cross_page,
nb_tbs ? (tst.cross_page * 100) / nb_tbs : 0);
qemu_printf("direct jump count %zu (%zu%%) (2 jumps=%zu %zu%%)\n",
tst.direct_jmp_count,
nb_tbs ? (tst.direct_jmp_count * 100) / nb_tbs : 0,
tst.direct_jmp2_count,
nb_tbs ? (tst.direct_jmp2_count * 100) / nb_tbs : 0);
qht_statistics_init(&tb_ctx.htable, &hst);
print_qht_statistics(hst, buf);
print_qht_statistics(hst);
qht_statistics_destroy(&hst);
g_string_append_printf(buf, "\nStatistics:\n");
g_string_append_printf(buf, "TB flush count %u\n",
qatomic_read(&tb_ctx.tb_flush_count));
g_string_append_printf(buf, "TB invalidate count %u\n",
qatomic_read(&tb_ctx.tb_phys_invalidate_count));
qemu_printf("\nStatistics:\n");
qemu_printf("TB flush count %u\n",
qatomic_read(&tb_ctx.tb_flush_count));
qemu_printf("TB invalidate count %u\n",
qatomic_read(&tb_ctx.tb_phys_invalidate_count));
tlb_flush_counts(&flush_full, &flush_part, &flush_elide);
g_string_append_printf(buf, "TLB full flushes %zu\n", flush_full);
g_string_append_printf(buf, "TLB partial flushes %zu\n", flush_part);
g_string_append_printf(buf, "TLB elided flushes %zu\n", flush_elide);
tcg_dump_info(buf);
qemu_printf("TLB full flushes %zu\n", flush_full);
qemu_printf("TLB partial flushes %zu\n", flush_part);
qemu_printf("TLB elided flushes %zu\n", flush_elide);
tcg_dump_info();
}
void dump_opcount_info(void)
{
tcg_dump_op_count();
}
#else /* CONFIG_USER_ONLY */
@@ -2256,15 +2270,6 @@ int page_get_flags(target_ulong address)
return p->flags;
}
/*
* Allow the target to decide if PAGE_TARGET_[12] may be reset.
* By default, they are not kept.
*/
#ifndef PAGE_TARGET_STICKY
#define PAGE_TARGET_STICKY 0
#endif
#define PAGE_STICKY (PAGE_ANON | PAGE_TARGET_STICKY)
/* Modify the flags of a page and invalidate the code if necessary.
The flag PAGE_WRITE_ORG is positioned automatically depending
on PAGE_WRITE. The mmap_lock should already be held. */
@@ -2308,38 +2313,12 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
p->target_data = NULL;
p->flags = flags;
} else {
/* Using mprotect on a page does not change sticky bits. */
p->flags = (p->flags & PAGE_STICKY) | flags;
/* Using mprotect on a page does not change MAP_ANON. */
p->flags = (p->flags & PAGE_ANON) | flags;
}
}
}
void page_reset_target_data(target_ulong start, target_ulong end)
{
target_ulong addr, len;
/*
* This function should never be called with addresses outside the
* guest address space. If this assert fires, it probably indicates
* a missing call to h2g_valid.
*/
assert(end - 1 <= GUEST_ADDR_MAX);
assert(start < end);
assert_memory_lock();
start = start & TARGET_PAGE_MASK;
end = TARGET_PAGE_ALIGN(end);
for (addr = start, len = end - start;
len != 0;
len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
g_free(p->target_data);
p->target_data = NULL;
}
}
void *page_get_target_data(target_ulong address)
{
PageDesc *p = page_find(address >> TARGET_PAGE_BITS);
@@ -2415,38 +2394,6 @@ int page_check_range(target_ulong start, target_ulong len, int flags)
return 0;
}
void page_protect(tb_page_addr_t page_addr)
{
target_ulong addr;
PageDesc *p;
int prot;
p = page_find(page_addr >> TARGET_PAGE_BITS);
if (p && (p->flags & PAGE_WRITE)) {
/*
* Force the host page as non writable (writes will have a page fault +
* mprotect overhead).
*/
page_addr &= qemu_host_page_mask;
prot = 0;
for (addr = page_addr; addr < page_addr + qemu_host_page_size;
addr += TARGET_PAGE_SIZE) {
p = page_find(addr >> TARGET_PAGE_BITS);
if (!p) {
continue;
}
prot |= p->flags;
p->flags &= ~PAGE_WRITE;
}
mprotect(g2h_untagged(page_addr), qemu_host_page_size,
(prot & PAGE_BITS) & ~PAGE_WRITE);
if (DEBUG_TB_INVALIDATE_GATE) {
printf("protecting code page: 0x" TB_PAGE_ADDR_FMT "\n", page_addr);
}
}
}
/* called from signal handler: invalidate the code and unprotect the
* page. Return 0 if the fault was not handled, 1 if it was handled,
* and 2 if it was handled but the caller must cause the TB to be

View File

@@ -42,15 +42,6 @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0;
}
static inline void translator_page_protect(DisasContextBase *dcbase,
target_ulong pc)
{
#ifdef CONFIG_USER_ONLY
dcbase->page_protect_end = pc | ~TARGET_PAGE_MASK;
page_protect(pc);
#endif
}
void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
CPUState *cpu, TranslationBlock *tb, int max_insns)
{
@@ -65,7 +56,6 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
db->num_insns = 0;
db->max_insns = max_insns;
db->singlestep_enabled = cflags & CF_SINGLE_STEP;
translator_page_protect(db, db->pc_next);
ops->init_disas_context(db, cpu);
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
@@ -139,42 +129,11 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(db->pc_first)) {
FILE *logfile = qemu_log_trylock();
if (logfile) {
fprintf(logfile, "----------------\n");
ops->disas_log(db, cpu, logfile);
fprintf(logfile, "\n");
qemu_log_unlock(logfile);
}
FILE *logfile = qemu_log_lock();
qemu_log("----------------\n");
ops->disas_log(db, cpu);
qemu_log("\n");
qemu_log_unlock(logfile);
}
#endif
}
static inline void translator_maybe_page_protect(DisasContextBase *dcbase,
target_ulong pc, size_t len)
{
#ifdef CONFIG_USER_ONLY
target_ulong end = pc + len - 1;
if (end > dcbase->page_protect_end) {
translator_page_protect(dcbase, end);
}
#endif
}
#define GEN_TRANSLATOR_LD(fullname, type, load_fn, swap_fn) \
type fullname ## _swap(CPUArchState *env, DisasContextBase *dcbase, \
abi_ptr pc, bool do_swap) \
{ \
translator_maybe_page_protect(dcbase, pc, sizeof(type)); \
type ret = load_fn(env, pc); \
if (do_swap) { \
ret = swap_fn(ret); \
} \
plugin_insn_append(pc, &ret, sizeof(ret)); \
return ret; \
}
FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD)
#undef GEN_TRANSLATOR_LD

File diff suppressed because it is too large Load Diff

View File

@@ -72,7 +72,7 @@ struct alsa_params_obt {
snd_pcm_uframes_t samples;
};
static void G_GNUC_PRINTF (2, 3) alsa_logerr (int err, const char *fmt, ...)
static void GCC_FMT_ATTR (2, 3) alsa_logerr (int err, const char *fmt, ...)
{
va_list ap;
@@ -83,7 +83,7 @@ static void G_GNUC_PRINTF (2, 3) alsa_logerr (int err, const char *fmt, ...)
AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
}
static void G_GNUC_PRINTF (3, 4) alsa_logerr2 (
static void GCC_FMT_ATTR (3, 4) alsa_logerr2 (
int err,
const char *typ,
const char *fmt,
@@ -916,7 +916,6 @@ static struct audio_pcm_ops alsa_pcm_ops = {
.init_out = alsa_init_out,
.fini_out = alsa_fini_out,
.write = alsa_write,
.buffer_get_free = audio_generic_buffer_get_free,
.run_buffer_out = audio_generic_run_buffer_out,
.enable_out = alsa_enable_out,

View File

@@ -32,7 +32,7 @@
#include "qapi/qapi-visit-audio.h"
#include "qemu/cutils.h"
#include "qemu/module.h"
#include "sysemu/sysemu.h"
#include "qemu-common.h"
#include "sysemu/replay.h"
#include "sysemu/runstate.h"
#include "ui/qemu-spice.h"
@@ -72,24 +72,20 @@ void audio_driver_register(audio_driver *drv)
audio_driver *audio_driver_lookup(const char *name)
{
struct audio_driver *d;
Error *local_err = NULL;
int rv;
QLIST_FOREACH(d, &audio_drivers, next) {
if (strcmp(name, d->name) == 0) {
return d;
}
}
rv = audio_module_load(name, &local_err);
if (rv > 0) {
QLIST_FOREACH(d, &audio_drivers, next) {
if (strcmp(name, d->name) == 0) {
return d;
}
audio_module_load_one(name);
QLIST_FOREACH(d, &audio_drivers, next) {
if (strcmp(name, d->name) == 0) {
return d;
}
} else if (rv < 0) {
error_report_err(local_err);
}
return NULL;
}
@@ -121,6 +117,7 @@ int audio_bug (const char *funcname, int cond)
AUD_log (NULL, "I am sorry\n");
}
AUD_log (NULL, "Context:\n");
abort();
}
return cond;
@@ -141,7 +138,7 @@ static inline int audio_bits_to_index (int bits)
default:
audio_bug ("bits_to_index", 1);
AUD_log (NULL, "invalid bits %d\n", bits);
abort();
return 0;
}
}
@@ -159,7 +156,7 @@ void *audio_calloc (const char *funcname, int nmemb, size_t size)
AUD_log (NULL, "%s passed invalid arguments to audio_calloc\n",
funcname);
AUD_log (NULL, "nmemb=%d size=%zu (len=%zu)\n", nmemb, size, len);
abort();
return NULL;
}
return g_malloc0 (len);
@@ -546,50 +543,70 @@ static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw);
if (audio_bug(__func__, live > hw->conv_buf->size)) {
dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
abort();
return 0;
}
return live;
}
static size_t audio_pcm_hw_conv_in(HWVoiceIn *hw, void *pcm_buf, size_t samples)
static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
{
size_t conv = 0;
STSampleBuffer *conv_buf = hw->conv_buf;
size_t clipped = 0;
size_t pos = hw->mix_buf->pos;
while (samples) {
uint8_t *src = advance(pcm_buf, conv * hw->info.bytes_per_frame);
size_t proc = MIN(samples, conv_buf->size - conv_buf->pos);
while (len) {
st_sample *src = hw->mix_buf->samples + pos;
uint8_t *dst = advance(pcm_buf, clipped * hw->info.bytes_per_frame);
size_t samples_till_end_of_buf = hw->mix_buf->size - pos;
size_t samples_to_clip = MIN(len, samples_till_end_of_buf);
hw->conv(conv_buf->samples + conv_buf->pos, src, proc);
conv_buf->pos = (conv_buf->pos + proc) % conv_buf->size;
samples -= proc;
conv += proc;
hw->clip(dst, src, samples_to_clip);
pos = (pos + samples_to_clip) % hw->mix_buf->size;
len -= samples_to_clip;
clipped += samples_to_clip;
}
return conv;
}
/*
* Soft voice (capture)
*/
static size_t audio_pcm_sw_get_rpos_in(SWVoiceIn *sw)
{
HWVoiceIn *hw = sw->hw;
ssize_t live = hw->total_samples_captured - sw->total_hw_samples_acquired;
ssize_t rpos;
if (audio_bug(__func__, live < 0 || live > hw->conv_buf->size)) {
dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
return 0;
}
rpos = hw->conv_buf->pos - live;
if (rpos >= 0) {
return rpos;
} else {
return hw->conv_buf->size + rpos;
}
}
static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)
{
HWVoiceIn *hw = sw->hw;
size_t samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
struct st_sample *src, *dst = sw->buf;
rpos = audio_pcm_sw_get_rpos_in(sw) % hw->conv_buf->size;
live = hw->total_samples_captured - sw->total_hw_samples_acquired;
if (audio_bug(__func__, live > hw->conv_buf->size)) {
dolog("live_in=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
return 0;
}
samples = size / sw->info.bytes_per_frame;
if (!live) {
return 0;
}
if (audio_bug(__func__, live > hw->conv_buf->size)) {
dolog("live_in=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
abort();
}
rpos = audio_ring_posb(hw->conv_buf->pos, live, hw->conv_buf->size);
samples = size / sw->info.bytes_per_frame;
swlim = (live * sw->ratio) >> 32;
swlim = MIN (swlim, samples);
@@ -615,7 +632,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)
total += isamp;
}
if (!hw->pcm_ops->volume_in) {
if (hw->pcm_ops && !hw->pcm_ops->volume_in) {
mixeng_volume (sw->buf, ret, &sw->vol);
}
@@ -659,45 +676,19 @@ static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live)
if (audio_bug(__func__, live > hw->mix_buf->size)) {
dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size);
abort();
return 0;
}
return live;
}
return 0;
}
static size_t audio_pcm_hw_get_free(HWVoiceOut *hw)
{
return (hw->pcm_ops->buffer_get_free ? hw->pcm_ops->buffer_get_free(hw) :
INT_MAX) / hw->info.bytes_per_frame;
}
static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
{
size_t clipped = 0;
size_t pos = hw->mix_buf->pos;
while (len) {
st_sample *src = hw->mix_buf->samples + pos;
uint8_t *dst = advance(pcm_buf, clipped * hw->info.bytes_per_frame);
size_t samples_till_end_of_buf = hw->mix_buf->size - pos;
size_t samples_to_clip = MIN(len, samples_till_end_of_buf);
hw->clip(dst, src, samples_to_clip);
pos = (pos + samples_to_clip) % hw->mix_buf->size;
len -= samples_to_clip;
clipped += samples_to_clip;
}
}
/*
* Soft voice (playback)
*/
static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
{
size_t hwsamples, samples, isamp, osamp, wpos, live, dead, left, blck;
size_t hw_free;
size_t hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
size_t ret = 0, pos = 0, total = 0;
if (!sw) {
@@ -709,7 +700,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
live = sw->total_hw_samples_mixed;
if (audio_bug(__func__, live > hwsamples)) {
dolog("live=%zu hw->mix_buf->size=%zu\n", live, hwsamples);
abort();
return 0;
}
if (live == hwsamples) {
@@ -720,28 +711,27 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
}
wpos = (sw->hw->mix_buf->pos + live) % hwsamples;
samples = size / sw->info.bytes_per_frame;
dead = hwsamples - live;
hw_free = audio_pcm_hw_get_free(sw->hw);
hw_free = hw_free > live ? hw_free - live : 0;
samples = ((int64_t)MIN(dead, hw_free) << 32) / sw->ratio;
samples = MIN(samples, size / sw->info.bytes_per_frame);
if (samples) {
sw->conv(sw->buf, buf, samples);
swlim = ((int64_t) dead << 32) / sw->ratio;
swlim = MIN (swlim, samples);
if (swlim) {
sw->conv (sw->buf, buf, swlim);
if (!sw->hw->pcm_ops->volume_out) {
mixeng_volume(sw->buf, samples, &sw->vol);
if (sw->hw->pcm_ops && !sw->hw->pcm_ops->volume_out) {
mixeng_volume (sw->buf, swlim, &sw->vol);
}
}
while (samples) {
while (swlim) {
dead = hwsamples - live;
left = hwsamples - wpos;
blck = MIN (dead, left);
if (!blck) {
break;
}
isamp = samples;
isamp = swlim;
osamp = blck;
st_rate_flow_mix (
sw->rate,
@@ -751,7 +741,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
&osamp
);
ret += isamp;
samples -= isamp;
swlim -= isamp;
pos += isamp;
live += osamp;
wpos = (wpos + osamp) % hwsamples;
@@ -1001,7 +991,7 @@ static size_t audio_get_avail (SWVoiceIn *sw)
if (audio_bug(__func__, live > sw->hw->conv_buf->size)) {
dolog("live=%zu sw->hw->conv_buf->size=%zu\n", live,
sw->hw->conv_buf->size);
abort();
return 0;
}
ldebug (
@@ -1013,11 +1003,6 @@ static size_t audio_get_avail (SWVoiceIn *sw)
return (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame;
}
static size_t audio_sw_bytes_free(SWVoiceOut *sw, size_t free)
{
return (((int64_t)free << 32) / sw->ratio) * sw->info.bytes_per_frame;
}
static size_t audio_get_free(SWVoiceOut *sw)
{
size_t live, dead;
@@ -1031,17 +1016,19 @@ static size_t audio_get_free(SWVoiceOut *sw)
if (audio_bug(__func__, live > sw->hw->mix_buf->size)) {
dolog("live=%zu sw->hw->mix_buf->size=%zu\n", live,
sw->hw->mix_buf->size);
abort();
return 0;
}
dead = sw->hw->mix_buf->size - live;
#ifdef DEBUG_OUT
dolog("%s: get_free live %zu dead %zu sw_bytes %zu\n",
SW_NAME(sw), live, dead, audio_sw_bytes_free(sw, dead));
dolog ("%s: get_free live %zu dead %zu ret %" PRId64 "\n",
SW_NAME (sw),
live, dead, (((int64_t) dead << 32) / sw->ratio) *
sw->info.bytes_per_frame);
#endif
return dead;
return (((int64_t) dead << 32) / sw->ratio) * sw->info.bytes_per_frame;
}
static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos,
@@ -1145,27 +1132,9 @@ static void audio_run_out (AudioState *s)
}
while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
size_t played, live, prev_rpos;
size_t hw_free = audio_pcm_hw_get_free(hw);
size_t played, live, prev_rpos, free;
int nb_live;
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
if (sw->active) {
size_t sw_free = audio_get_free(sw);
size_t free;
if (hw_free > sw->total_hw_samples_mixed) {
free = audio_sw_bytes_free(sw,
MIN(sw_free, hw_free - sw->total_hw_samples_mixed));
} else {
free = 0;
}
if (free > 0) {
sw->callback.fn(sw->callback.opaque, free);
}
}
}
live = audio_pcm_hw_get_live_out (hw, &nb_live);
if (!nb_live) {
live = 0;
@@ -1173,7 +1142,7 @@ static void audio_run_out (AudioState *s)
if (audio_bug(__func__, live > hw->mix_buf->size)) {
dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size);
abort();
continue;
}
if (hw->pending_disable && !nb_live) {
@@ -1194,6 +1163,14 @@ static void audio_run_out (AudioState *s)
}
if (!live) {
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
if (sw->active) {
free = audio_get_free (sw);
if (free > 0) {
sw->callback.fn (sw->callback.opaque, free);
}
}
}
if (hw->pcm_ops->run_buffer_out) {
hw->pcm_ops->run_buffer_out(hw);
}
@@ -1206,7 +1183,7 @@ static void audio_run_out (AudioState *s)
if (audio_bug(__func__, hw->mix_buf->pos >= hw->mix_buf->size)) {
dolog("hw->mix_buf->pos=%zu hw->mix_buf->size=%zu played=%zu\n",
hw->mix_buf->pos, hw->mix_buf->size, played);
abort();
hw->mix_buf->pos = 0;
}
#ifdef DEBUG_OUT
@@ -1226,7 +1203,7 @@ static void audio_run_out (AudioState *s)
if (audio_bug(__func__, played > sw->total_hw_samples_mixed)) {
dolog("played=%zu sw->total_hw_samples_mixed=%zu\n",
played, sw->total_hw_samples_mixed);
abort();
played = sw->total_hw_samples_mixed;
}
sw->total_hw_samples_mixed -= played;
@@ -1234,6 +1211,13 @@ static void audio_run_out (AudioState *s)
if (!sw->total_hw_samples_mixed) {
sw->empty = 1;
}
if (sw->active) {
free = audio_get_free (sw);
if (free > 0) {
sw->callback.fn (sw->callback.opaque, free);
}
}
}
}
}
@@ -1241,6 +1225,7 @@ static void audio_run_out (AudioState *s)
static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)
{
size_t conv = 0;
STSampleBuffer *conv_buf = hw->conv_buf;
if (hw->pcm_ops->run_buffer_in) {
hw->pcm_ops->run_buffer_in(hw);
@@ -1256,7 +1241,11 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)
break;
}
proc = audio_pcm_hw_conv_in(hw, buf, size / hw->info.bytes_per_frame);
proc = MIN(size / hw->info.bytes_per_frame,
conv_buf->size - conv_buf->pos);
hw->conv(conv_buf->samples + conv_buf->pos, buf, proc);
conv_buf->pos = (conv_buf->pos + proc) % conv_buf->size;
samples -= proc;
conv += proc;
@@ -1349,7 +1338,7 @@ static void audio_run_capture (AudioState *s)
if (audio_bug(__func__, captured > sw->total_hw_samples_mixed)) {
dolog("captured=%zu sw->total_hw_samples_mixed=%zu\n",
captured, sw->total_hw_samples_mixed);
abort();
captured = sw->total_hw_samples_mixed;
}
sw->total_hw_samples_mixed -= captured;
@@ -1405,10 +1394,12 @@ void audio_generic_run_buffer_in(HWVoiceIn *hw)
void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size)
{
size_t start;
ssize_t start = (ssize_t)hw->pos_emul - hw->pending_emul;
start = audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size_emul);
assert(start < hw->size_emul);
if (start < 0) {
start += hw->size_emul;
}
assert(start >= 0 && start < hw->size_emul);
*size = MIN(*size, hw->pending_emul);
*size = MIN(*size, hw->size_emul - start);
@@ -1421,22 +1412,16 @@ void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size)
hw->pending_emul -= size;
}
size_t audio_generic_buffer_get_free(HWVoiceOut *hw)
{
if (hw->buf_emul) {
return hw->size_emul - hw->pending_emul;
} else {
return hw->samples * hw->info.bytes_per_frame;
}
}
void audio_generic_run_buffer_out(HWVoiceOut *hw)
{
while (hw->pending_emul) {
size_t write_len, written, start;
size_t write_len, written;
ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul;
start = audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size_emul);
assert(start < hw->size_emul);
if (start < 0) {
start += hw->size_emul;
}
assert(start >= 0 && start < hw->size_emul);
write_len = MIN(hw->pending_emul, hw->size_emul - start);
@@ -1477,12 +1462,6 @@ size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size)
{
size_t total = 0;
if (hw->pcm_ops->buffer_get_free) {
size_t free = hw->pcm_ops->buffer_get_free(hw);
size = MIN(size, free);
}
while (total < size) {
size_t dst_size = size - total;
size_t copy_size, proc;
@@ -1737,7 +1716,7 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
audio_validate_opts(dev, &error_abort);
}
s = g_new0(AudioState, 1);
s = g_malloc0(sizeof(AudioState));
s->dev = dev;
QLIST_INIT (&s->hw_head_out);
@@ -1842,7 +1821,6 @@ void AUD_remove_card (QEMUSoundCard *card)
g_free (card->name);
}
static struct audio_pcm_ops capture_pcm_ops;
CaptureVoiceOut *AUD_add_capture(
AudioState *s,
@@ -1888,7 +1866,6 @@ CaptureVoiceOut *AUD_add_capture(
hw = &cap->hw;
hw->s = s;
hw->pcm_ops = &capture_pcm_ops;
QLIST_INIT (&hw->sw_head);
QLIST_INIT (&cap->cb_head);
@@ -2023,7 +2000,6 @@ void audio_create_pdos(Audiodev *dev)
CASE(NONE, none, );
CASE(ALSA, alsa, Alsa);
CASE(COREAUDIO, coreaudio, Coreaudio);
CASE(DBUS, dbus, );
CASE(DSOUND, dsound, );
CASE(JACK, jack, Jack);
CASE(OSS, oss, Oss);
@@ -2103,22 +2079,16 @@ static void audio_validate_opts(Audiodev *dev, Error **errp)
void audio_parse_option(const char *opt)
{
AudiodevListEntry *e;
Audiodev *dev = NULL;
Visitor *v = qobject_input_visitor_new_str(opt, "driver", &error_fatal);
visit_type_Audiodev(v, NULL, &dev, &error_fatal);
visit_free(v);
audio_define(dev);
}
void audio_define(Audiodev *dev)
{
AudiodevListEntry *e;
audio_validate_opts(dev, &error_fatal);
e = g_new0(AudiodevListEntry, 1);
e = g_malloc0(sizeof(AudiodevListEntry));
e->dev = dev;
QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next);
}

View File

@@ -32,7 +32,7 @@
typedef void (*audio_callback_fn) (void *opaque, int avail);
#if HOST_BIG_ENDIAN
#ifdef HOST_WORDS_BIGENDIAN
#define AUDIO_HOST_ENDIANNESS 1
#else
#define AUDIO_HOST_ENDIANNESS 0
@@ -91,8 +91,8 @@ typedef struct QEMUAudioTimeStamp {
uint64_t old_ts;
} QEMUAudioTimeStamp;
void AUD_vlog (const char *cap, const char *fmt, va_list ap) G_GNUC_PRINTF(2, 0);
void AUD_log (const char *cap, const char *fmt, ...) G_GNUC_PRINTF(2, 3);
void AUD_vlog (const char *cap, const char *fmt, va_list ap) GCC_FMT_ATTR(2, 0);
void AUD_log (const char *cap, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
void AUD_register_card (const char *name, QEMUSoundCard *card);
void AUD_remove_card (QEMUSoundCard *card);
@@ -168,7 +168,6 @@ void audio_sample_to_uint64(const void *samples, int pos,
void audio_sample_from_uint64(void *samples, int pos,
uint64_t left, uint64_t right);
void audio_define(Audiodev *audio);
void audio_parse_option(const char *opt);
void audio_init_audiodevs(void);
void audio_legacy_help(void);

View File

@@ -31,10 +31,6 @@
#endif
#include "mixeng.h"
#ifdef CONFIG_GIO
#include <gio/gio.h>
#endif
struct audio_pcm_ops;
struct audio_callback {
@@ -144,9 +140,6 @@ struct audio_driver {
const char *descr;
void *(*init) (Audiodev *);
void (*fini) (void *);
#ifdef CONFIG_GIO
void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager);
#endif
struct audio_pcm_ops *pcm_ops;
int can_be_default;
int max_voices_out;
@@ -161,14 +154,10 @@ struct audio_pcm_ops {
void (*fini_out)(HWVoiceOut *hw);
size_t (*write) (HWVoiceOut *hw, void *buf, size_t size);
void (*run_buffer_out)(HWVoiceOut *hw);
/*
* Get the free output buffer size. This is an upper limit. The size
* returned by function get_buffer_out may be smaller.
*/
size_t (*buffer_get_free)(HWVoiceOut *hw);
/*
* get a buffer that after later can be passed to put_buffer_out; optional
* returns the buffer, and writes it's size to size (in bytes)
* this is unrelated to the above buffer_size_out function
*/
void *(*get_buffer_out)(HWVoiceOut *hw, size_t *size);
/*
@@ -194,7 +183,6 @@ void audio_generic_run_buffer_in(HWVoiceIn *hw);
void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size);
void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size);
void audio_generic_run_buffer_out(HWVoiceOut *hw);
size_t audio_generic_buffer_get_free(HWVoiceOut *hw);
void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size);
size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size);
size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size);
@@ -271,19 +259,6 @@ static inline size_t audio_ring_dist(size_t dst, size_t src, size_t len)
return (dst >= src) ? (dst - src) : (len - src + dst);
}
/**
* audio_ring_posb() - returns new position in ringbuffer in backward
* direction at given distance
*
* @pos: current position in ringbuffer
* @dist: distance in ringbuffer to walk in reverse direction
* @len: size of ringbuffer
*/
static inline size_t audio_ring_posb(size_t pos, size_t dist, size_t len)
{
return pos >= dist ? pos - dist : len - dist + pos;
}
#define dolog(fmt, ...) AUD_log(AUDIO_CAP, fmt, ## __VA_ARGS__)
#ifdef DEBUG

View File

@@ -328,8 +328,8 @@ static void handle_per_direction(
static AudiodevListEntry *legacy_opt(const char *drvname)
{
AudiodevListEntry *e = g_new0(AudiodevListEntry, 1);
e->dev = g_new0(Audiodev, 1);
AudiodevListEntry *e = g_malloc0(sizeof(AudiodevListEntry));
e->dev = g_malloc0(sizeof(Audiodev));
e->dev->id = g_strdup(drvname);
e->dev->driver = qapi_enum_parse(
&AudiodevDriver_lookup, drvname, -1, &error_abort);
@@ -508,7 +508,7 @@ static void lv_free(Visitor *v)
static Visitor *legacy_visitor_new(void)
{
LegacyPrintVisitor *lv = g_new0(LegacyPrintVisitor, 1);
LegacyPrintVisitor *lv = g_malloc0(sizeof(LegacyPrintVisitor));
lv->visitor.start_struct = lv_start_struct;
lv->visitor.end_struct = lv_end_struct;

View File

@@ -59,13 +59,12 @@ static void glue(audio_init_nb_voices_, TYPE)(AudioState *s,
if (audio_bug(__func__, !voice_size && max_voices)) {
dolog ("drv=`%s' voice_size=0 max_voices=%d\n",
drv->name, max_voices);
abort();
glue (s->nb_hw_voices_, TYPE) = 0;
}
if (audio_bug(__func__, voice_size && !max_voices)) {
dolog ("drv=`%s' voice_size=%d max_voices=0\n",
drv->name, voice_size);
abort();
}
}
@@ -82,7 +81,6 @@ static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw)
size_t samples = hw->samples;
if (audio_bug(__func__, samples == 0)) {
dolog("Attempted to allocate empty buffer\n");
abort();
}
HWBUF = g_malloc0(sizeof(STSampleBuffer) + sizeof(st_sample) * samples);
@@ -254,12 +252,12 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
if (audio_bug(__func__, !drv)) {
dolog ("No host audio driver\n");
abort();
return NULL;
}
if (audio_bug(__func__, !drv->pcm_ops)) {
dolog ("Host audio driver without pcm_ops\n");
abort();
return NULL;
}
hw = audio_calloc(__func__, 1, glue(drv->voice_size_, TYPE));
@@ -277,13 +275,12 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
QLIST_INIT (&hw->cap_head);
#endif
if (glue (hw->pcm_ops->init_, TYPE) (hw, as, s->drv_opaque)) {
g_free(hw);
return NULL;
goto err0;
}
if (audio_bug(__func__, hw->samples <= 0)) {
dolog("hw->samples=%zd\n", hw->samples);
abort();
goto err1;
}
if (hw->info.is_float) {
@@ -312,6 +309,12 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
audio_attach_capture (hw);
#endif
return hw;
err1:
glue (hw->pcm_ops->fini_, TYPE) (hw);
err0:
g_free (hw);
return NULL;
}
AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev)
@@ -324,8 +327,6 @@ AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev)
case AUDIODEV_DRIVER_COREAUDIO:
return qapi_AudiodevCoreaudioPerDirectionOptions_base(
dev->u.coreaudio.TYPE);
case AUDIODEV_DRIVER_DBUS:
return dev->u.dbus.TYPE;
case AUDIODEV_DRIVER_DSOUND:
return dev->u.dsound.TYPE;
case AUDIODEV_DRIVER_JACK:
@@ -432,7 +433,7 @@ void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw)
if (sw) {
if (audio_bug(__func__, !card)) {
dolog ("card=%p\n", card);
abort();
return;
}
glue (audio_close_, TYPE) (sw);
@@ -454,7 +455,7 @@ SW *glue (AUD_open_, TYPE) (
if (audio_bug(__func__, !card || !name || !callback_fn || !as)) {
dolog ("card=%p name=%p callback_fn=%p as=%p\n",
card, name, callback_fn, as);
abort();
goto fail;
}
s = card->state;
@@ -465,12 +466,12 @@ SW *glue (AUD_open_, TYPE) (
if (audio_bug(__func__, audio_validate_settings(as))) {
audio_print_settings (as);
abort();
goto fail;
}
if (audio_bug(__func__, !s->drv)) {
dolog ("Can not open `%s' (no host audio driver)\n", name);
abort();
goto fail;
}
if (sw && audio_pcm_info_eq (&sw->info, as)) {

View File

@@ -1,6 +1,7 @@
/* public domain */
#include "qemu/osdep.h"
#include "qemu-common.h"
#define AUDIO_CAP "win-int"
#include <windows.h>

View File

@@ -44,15 +44,10 @@ typedef struct coreaudioVoiceOut {
bool enabled;
} coreaudioVoiceOut;
#if !defined(MAC_OS_VERSION_12_0) \
|| (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_12_0)
#define kAudioObjectPropertyElementMain kAudioObjectPropertyElementMaster
#endif
static const AudioObjectPropertyAddress voice_addr = {
kAudioHardwarePropertyDefaultOutputDevice,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMain
kAudioObjectPropertyElementMaster
};
static OSStatus coreaudio_get_voice(AudioDeviceID *id)
@@ -74,7 +69,7 @@ static OSStatus coreaudio_get_framesizerange(AudioDeviceID id,
AudioObjectPropertyAddress addr = {
kAudioDevicePropertyBufferFrameSizeRange,
kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMain
kAudioObjectPropertyElementMaster
};
return AudioObjectGetPropertyData(id,
@@ -91,7 +86,7 @@ static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize)
AudioObjectPropertyAddress addr = {
kAudioDevicePropertyBufferFrameSize,
kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMain
kAudioObjectPropertyElementMaster
};
return AudioObjectGetPropertyData(id,
@@ -108,7 +103,7 @@ static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize)
AudioObjectPropertyAddress addr = {
kAudioDevicePropertyBufferFrameSize,
kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMain
kAudioObjectPropertyElementMaster
};
return AudioObjectSetPropertyData(id,
@@ -126,7 +121,7 @@ static OSStatus coreaudio_set_streamformat(AudioDeviceID id,
AudioObjectPropertyAddress addr = {
kAudioDevicePropertyStreamFormat,
kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMain
kAudioObjectPropertyElementMaster
};
return AudioObjectSetPropertyData(id,
@@ -143,7 +138,7 @@ static OSStatus coreaudio_get_isrunning(AudioDeviceID id, UInt32 *result)
AudioObjectPropertyAddress addr = {
kAudioDevicePropertyDeviceIsRunning,
kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMain
kAudioObjectPropertyElementMaster
};
return AudioObjectGetPropertyData(id,
@@ -211,7 +206,7 @@ static void coreaudio_logstatus (OSStatus status)
AUD_log (AUDIO_CAP, "Reason: %s\n", str);
}
static void G_GNUC_PRINTF (2, 3) coreaudio_logerr (
static void GCC_FMT_ATTR (2, 3) coreaudio_logerr (
OSStatus status,
const char *fmt,
...
@@ -226,7 +221,7 @@ static void G_GNUC_PRINTF (2, 3) coreaudio_logerr (
coreaudio_logstatus (status);
}
static void G_GNUC_PRINTF (3, 4) coreaudio_logerr2 (
static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 (
OSStatus status,
const char *typ,
const char *fmt,
@@ -288,7 +283,6 @@ static int coreaudio_buf_unlock (coreaudioVoiceOut *core, const char *fn_name)
coreaudio_buf_unlock(core, "coreaudio_" #name); \
return ret; \
}
COREAUDIO_WRAPPER_FUNC(buffer_get_free, size_t, (HWVoiceOut *hw), (hw))
COREAUDIO_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size),
(hw, size))
COREAUDIO_WRAPPER_FUNC(put_buffer_out, size_t,
@@ -339,10 +333,12 @@ static OSStatus audioDeviceIOProc(
len = frameCount * hw->info.bytes_per_frame;
while (len) {
size_t write_len, start;
start = audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size_emul);
assert(start < hw->size_emul);
size_t write_len;
ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul;
if (start < 0) {
start += hw->size_emul;
}
assert(start >= 0 && start < hw->size_emul);
write_len = MIN(MIN(hw->pending_emul, len),
hw->size_emul - start);
@@ -545,6 +541,7 @@ static OSStatus handle_voice_change(
const AudioObjectPropertyAddress *in_addresses,
void *in_client_data)
{
OSStatus status;
coreaudioVoiceOut *core = in_client_data;
qemu_mutex_lock_iothread();
@@ -553,12 +550,13 @@ static OSStatus handle_voice_change(
fini_out_device(core);
}
if (!init_out_device(core)) {
status = init_out_device(core);
if (!status) {
update_device_playback_state(core);
}
qemu_mutex_unlock_iothread();
return 0;
return status;
}
static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
@@ -606,8 +604,6 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
coreaudio_playback_logerr(status,
"Could not remove voice property change listener\n");
}
return -1;
}
return 0;
@@ -658,8 +654,6 @@ static struct audio_pcm_ops coreaudio_pcm_ops = {
.fini_out = coreaudio_fini_out,
/* wrapper for audio_generic_write */
.write = coreaudio_write,
/* wrapper for audio_generic_buffer_get_free */
.buffer_get_free = coreaudio_buffer_get_free,
/* wrapper for audio_generic_get_buffer_out */
.get_buffer_out = coreaudio_get_buffer_out,
/* wrapper for audio_generic_put_buffer_out */

View File

@@ -1,654 +0,0 @@
/*
* QEMU DBus audio
*
* Copyright (c) 2021 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qemu/host-utils.h"
#include "qemu/module.h"
#include "qemu/timer.h"
#include "qemu/dbus.h"
#include <gio/gunixfdlist.h>
#include "ui/dbus-display1.h"
#define AUDIO_CAP "dbus"
#include "audio.h"
#include "audio_int.h"
#include "trace.h"
#define DBUS_DISPLAY1_AUDIO_PATH DBUS_DISPLAY1_ROOT "/Audio"
#define DBUS_AUDIO_NSAMPLES 1024 /* could be configured? */
typedef struct DBusAudio {
GDBusObjectManagerServer *server;
GDBusObjectSkeleton *audio;
QemuDBusDisplay1Audio *iface;
GHashTable *out_listeners;
GHashTable *in_listeners;
} DBusAudio;
typedef struct DBusVoiceOut {
HWVoiceOut hw;
bool enabled;
RateCtl rate;
void *buf;
size_t buf_pos;
size_t buf_size;
bool has_volume;
Volume volume;
} DBusVoiceOut;
typedef struct DBusVoiceIn {
HWVoiceIn hw;
bool enabled;
RateCtl rate;
bool has_volume;
Volume volume;
} DBusVoiceIn;
static void *dbus_get_buffer_out(HWVoiceOut *hw, size_t *size)
{
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
if (!vo->buf) {
vo->buf_size = hw->samples * hw->info.bytes_per_frame;
vo->buf = g_malloc(vo->buf_size);
vo->buf_pos = 0;
}
*size = MIN(vo->buf_size - vo->buf_pos, *size);
*size = audio_rate_get_bytes(&hw->info, &vo->rate, *size);
return vo->buf + vo->buf_pos;
}
static size_t dbus_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
{
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
GHashTableIter iter;
QemuDBusDisplay1AudioOutListener *listener = NULL;
g_autoptr(GBytes) bytes = NULL;
g_autoptr(GVariant) v_data = NULL;
assert(buf == vo->buf + vo->buf_pos && vo->buf_pos + size <= vo->buf_size);
vo->buf_pos += size;
trace_dbus_audio_put_buffer_out(size);
if (vo->buf_pos < vo->buf_size) {
return size;
}
bytes = g_bytes_new_take(g_steal_pointer(&vo->buf), vo->buf_size);
v_data = g_variant_new_from_bytes(G_VARIANT_TYPE("ay"), bytes, TRUE);
g_variant_ref_sink(v_data);
g_hash_table_iter_init(&iter, da->out_listeners);
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
qemu_dbus_display1_audio_out_listener_call_write(
listener,
(uintptr_t)hw,
v_data,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
return size;
}
#if HOST_BIG_ENDIAN
#define AUDIO_HOST_BE TRUE
#else
#define AUDIO_HOST_BE FALSE
#endif
static void
dbus_init_out_listener(QemuDBusDisplay1AudioOutListener *listener,
HWVoiceOut *hw)
{
qemu_dbus_display1_audio_out_listener_call_init(
listener,
(uintptr_t)hw,
hw->info.bits,
hw->info.is_signed,
hw->info.is_float,
hw->info.freq,
hw->info.nchannels,
hw->info.bytes_per_frame,
hw->info.bytes_per_second,
hw->info.swap_endianness ? !AUDIO_HOST_BE : AUDIO_HOST_BE,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
static int
dbus_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
{
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
GHashTableIter iter;
QemuDBusDisplay1AudioOutListener *listener = NULL;
audio_pcm_init_info(&hw->info, as);
hw->samples = DBUS_AUDIO_NSAMPLES;
audio_rate_start(&vo->rate);
g_hash_table_iter_init(&iter, da->out_listeners);
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
dbus_init_out_listener(listener, hw);
}
return 0;
}
static void
dbus_fini_out(HWVoiceOut *hw)
{
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
GHashTableIter iter;
QemuDBusDisplay1AudioOutListener *listener = NULL;
g_hash_table_iter_init(&iter, da->out_listeners);
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
qemu_dbus_display1_audio_out_listener_call_fini(
listener,
(uintptr_t)hw,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
g_clear_pointer(&vo->buf, g_free);
}
static void
dbus_enable_out(HWVoiceOut *hw, bool enable)
{
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
GHashTableIter iter;
QemuDBusDisplay1AudioOutListener *listener = NULL;
vo->enabled = enable;
if (enable) {
audio_rate_start(&vo->rate);
}
g_hash_table_iter_init(&iter, da->out_listeners);
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
qemu_dbus_display1_audio_out_listener_call_set_enabled(
listener, (uintptr_t)hw, enable,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
}
static void
dbus_volume_out_listener(HWVoiceOut *hw,
QemuDBusDisplay1AudioOutListener *listener)
{
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
Volume *vol = &vo->volume;
g_autoptr(GBytes) bytes = NULL;
GVariant *v_vol = NULL;
if (!vo->has_volume) {
return;
}
assert(vol->channels < sizeof(vol->vol));
bytes = g_bytes_new(vol->vol, vol->channels);
v_vol = g_variant_new_from_bytes(G_VARIANT_TYPE("ay"), bytes, TRUE);
qemu_dbus_display1_audio_out_listener_call_set_volume(
listener, (uintptr_t)hw, vol->mute, v_vol,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
static void
dbus_volume_out(HWVoiceOut *hw, Volume *vol)
{
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
GHashTableIter iter;
QemuDBusDisplay1AudioOutListener *listener = NULL;
vo->has_volume = true;
vo->volume = *vol;
g_hash_table_iter_init(&iter, da->out_listeners);
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
dbus_volume_out_listener(hw, listener);
}
}
static void
dbus_init_in_listener(QemuDBusDisplay1AudioInListener *listener, HWVoiceIn *hw)
{
qemu_dbus_display1_audio_in_listener_call_init(
listener,
(uintptr_t)hw,
hw->info.bits,
hw->info.is_signed,
hw->info.is_float,
hw->info.freq,
hw->info.nchannels,
hw->info.bytes_per_frame,
hw->info.bytes_per_second,
hw->info.swap_endianness ? !AUDIO_HOST_BE : AUDIO_HOST_BE,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
static int
dbus_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
{
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw);
GHashTableIter iter;
QemuDBusDisplay1AudioInListener *listener = NULL;
audio_pcm_init_info(&hw->info, as);
hw->samples = DBUS_AUDIO_NSAMPLES;
audio_rate_start(&vo->rate);
g_hash_table_iter_init(&iter, da->in_listeners);
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
dbus_init_in_listener(listener, hw);
}
return 0;
}
static void
dbus_fini_in(HWVoiceIn *hw)
{
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
GHashTableIter iter;
QemuDBusDisplay1AudioInListener *listener = NULL;
g_hash_table_iter_init(&iter, da->in_listeners);
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
qemu_dbus_display1_audio_in_listener_call_fini(
listener,
(uintptr_t)hw,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
}
static void
dbus_volume_in_listener(HWVoiceIn *hw,
QemuDBusDisplay1AudioInListener *listener)
{
DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw);
Volume *vol = &vo->volume;
g_autoptr(GBytes) bytes = NULL;
GVariant *v_vol = NULL;
if (!vo->has_volume) {
return;
}
assert(vol->channels < sizeof(vol->vol));
bytes = g_bytes_new(vol->vol, vol->channels);
v_vol = g_variant_new_from_bytes(G_VARIANT_TYPE("ay"), bytes, TRUE);
qemu_dbus_display1_audio_in_listener_call_set_volume(
listener, (uintptr_t)hw, vol->mute, v_vol,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
static void
dbus_volume_in(HWVoiceIn *hw, Volume *vol)
{
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw);
GHashTableIter iter;
QemuDBusDisplay1AudioInListener *listener = NULL;
vo->has_volume = true;
vo->volume = *vol;
g_hash_table_iter_init(&iter, da->in_listeners);
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
dbus_volume_in_listener(hw, listener);
}
}
static size_t
dbus_read(HWVoiceIn *hw, void *buf, size_t size)
{
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
/* DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw); */
GHashTableIter iter;
QemuDBusDisplay1AudioInListener *listener = NULL;
trace_dbus_audio_read(size);
/* size = audio_rate_get_bytes(&hw->info, &vo->rate, size); */
g_hash_table_iter_init(&iter, da->in_listeners);
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
g_autoptr(GVariant) v_data = NULL;
const char *data;
gsize n = 0;
if (qemu_dbus_display1_audio_in_listener_call_read_sync(
listener,
(uintptr_t)hw,
size,
G_DBUS_CALL_FLAGS_NONE, -1,
&v_data, NULL, NULL)) {
data = g_variant_get_fixed_array(v_data, &n, 1);
g_warn_if_fail(n <= size);
size = MIN(n, size);
memcpy(buf, data, size);
break;
}
}
return size;
}
static void
dbus_enable_in(HWVoiceIn *hw, bool enable)
{
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw);
GHashTableIter iter;
QemuDBusDisplay1AudioInListener *listener = NULL;
vo->enabled = enable;
if (enable) {
audio_rate_start(&vo->rate);
}
g_hash_table_iter_init(&iter, da->in_listeners);
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
qemu_dbus_display1_audio_in_listener_call_set_enabled(
listener, (uintptr_t)hw, enable,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
}
static void *
dbus_audio_init(Audiodev *dev)
{
DBusAudio *da = g_new0(DBusAudio, 1);
da->out_listeners = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_object_unref);
da->in_listeners = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_object_unref);
return da;
}
static void
dbus_audio_fini(void *opaque)
{
DBusAudio *da = opaque;
if (da->server) {
g_dbus_object_manager_server_unexport(da->server,
DBUS_DISPLAY1_AUDIO_PATH);
}
g_clear_object(&da->audio);
g_clear_object(&da->iface);
g_clear_pointer(&da->in_listeners, g_hash_table_unref);
g_clear_pointer(&da->out_listeners, g_hash_table_unref);
g_clear_object(&da->server);
g_free(da);
}
static void
listener_out_vanished_cb(GDBusConnection *connection,
gboolean remote_peer_vanished,
GError *error,
DBusAudio *da)
{
char *name = g_object_get_data(G_OBJECT(connection), "name");
g_hash_table_remove(da->out_listeners, name);
}
static void
listener_in_vanished_cb(GDBusConnection *connection,
gboolean remote_peer_vanished,
GError *error,
DBusAudio *da)
{
char *name = g_object_get_data(G_OBJECT(connection), "name");
g_hash_table_remove(da->in_listeners, name);
}
static gboolean
dbus_audio_register_listener(AudioState *s,
GDBusMethodInvocation *invocation,
GUnixFDList *fd_list,
GVariant *arg_listener,
bool out)
{
DBusAudio *da = s->drv_opaque;
const char *sender = g_dbus_method_invocation_get_sender(invocation);
g_autoptr(GDBusConnection) listener_conn = NULL;
g_autoptr(GError) err = NULL;
g_autoptr(GSocket) socket = NULL;
g_autoptr(GSocketConnection) socket_conn = NULL;
g_autofree char *guid = g_dbus_generate_guid();
GHashTable *listeners = out ? da->out_listeners : da->in_listeners;
GObject *listener;
int fd;
trace_dbus_audio_register(sender, out ? "out" : "in");
if (g_hash_table_contains(listeners, sender)) {
g_dbus_method_invocation_return_error(invocation,
DBUS_DISPLAY_ERROR,
DBUS_DISPLAY_ERROR_INVALID,
"`%s` is already registered!",
sender);
return DBUS_METHOD_INVOCATION_HANDLED;
}
fd = g_unix_fd_list_get(fd_list, g_variant_get_handle(arg_listener), &err);
if (err) {
g_dbus_method_invocation_return_error(invocation,
DBUS_DISPLAY_ERROR,
DBUS_DISPLAY_ERROR_FAILED,
"Couldn't get peer fd: %s",
err->message);
return DBUS_METHOD_INVOCATION_HANDLED;
}
socket = g_socket_new_from_fd(fd, &err);
if (err) {
g_dbus_method_invocation_return_error(invocation,
DBUS_DISPLAY_ERROR,
DBUS_DISPLAY_ERROR_FAILED,
"Couldn't make a socket: %s",
err->message);
return DBUS_METHOD_INVOCATION_HANDLED;
}
socket_conn = g_socket_connection_factory_create_connection(socket);
if (out) {
qemu_dbus_display1_audio_complete_register_out_listener(
da->iface, invocation, NULL);
} else {
qemu_dbus_display1_audio_complete_register_in_listener(
da->iface, invocation, NULL);
}
listener_conn =
g_dbus_connection_new_sync(
G_IO_STREAM(socket_conn),
guid,
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,
NULL, NULL, &err);
if (err) {
error_report("Failed to setup peer connection: %s", err->message);
return DBUS_METHOD_INVOCATION_HANDLED;
}
listener = out ?
G_OBJECT(qemu_dbus_display1_audio_out_listener_proxy_new_sync(
listener_conn,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
NULL,
"/org/qemu/Display1/AudioOutListener",
NULL,
&err)) :
G_OBJECT(qemu_dbus_display1_audio_in_listener_proxy_new_sync(
listener_conn,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
NULL,
"/org/qemu/Display1/AudioInListener",
NULL,
&err));
if (!listener) {
error_report("Failed to setup proxy: %s", err->message);
return DBUS_METHOD_INVOCATION_HANDLED;
}
if (out) {
HWVoiceOut *hw;
QLIST_FOREACH(hw, &s->hw_head_out, entries) {
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
QemuDBusDisplay1AudioOutListener *l =
QEMU_DBUS_DISPLAY1_AUDIO_OUT_LISTENER(listener);
dbus_init_out_listener(l, hw);
qemu_dbus_display1_audio_out_listener_call_set_enabled(
l, (uintptr_t)hw, vo->enabled,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
} else {
HWVoiceIn *hw;
QLIST_FOREACH(hw, &s->hw_head_in, entries) {
DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw);
QemuDBusDisplay1AudioInListener *l =
QEMU_DBUS_DISPLAY1_AUDIO_IN_LISTENER(listener);
dbus_init_in_listener(
QEMU_DBUS_DISPLAY1_AUDIO_IN_LISTENER(listener), hw);
qemu_dbus_display1_audio_in_listener_call_set_enabled(
l, (uintptr_t)hw, vo->enabled,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
}
g_object_set_data_full(G_OBJECT(listener_conn), "name",
g_strdup(sender), g_free);
g_hash_table_insert(listeners, g_strdup(sender), listener);
g_object_connect(listener_conn,
"signal::closed",
out ? listener_out_vanished_cb : listener_in_vanished_cb,
da,
NULL);
return DBUS_METHOD_INVOCATION_HANDLED;
}
static gboolean
dbus_audio_register_out_listener(AudioState *s,
GDBusMethodInvocation *invocation,
GUnixFDList *fd_list,
GVariant *arg_listener)
{
return dbus_audio_register_listener(s, invocation,
fd_list, arg_listener, true);
}
static gboolean
dbus_audio_register_in_listener(AudioState *s,
GDBusMethodInvocation *invocation,
GUnixFDList *fd_list,
GVariant *arg_listener)
{
return dbus_audio_register_listener(s, invocation,
fd_list, arg_listener, false);
}
static void
dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server)
{
DBusAudio *da = s->drv_opaque;
g_assert(da);
g_assert(!da->server);
da->server = g_object_ref(server);
da->audio = g_dbus_object_skeleton_new(DBUS_DISPLAY1_AUDIO_PATH);
da->iface = qemu_dbus_display1_audio_skeleton_new();
g_object_connect(da->iface,
"swapped-signal::handle-register-in-listener",
dbus_audio_register_in_listener, s,
"swapped-signal::handle-register-out-listener",
dbus_audio_register_out_listener, s,
NULL);
g_dbus_object_skeleton_add_interface(G_DBUS_OBJECT_SKELETON(da->audio),
G_DBUS_INTERFACE_SKELETON(da->iface));
g_dbus_object_manager_server_export(da->server, da->audio);
}
static struct audio_pcm_ops dbus_pcm_ops = {
.init_out = dbus_init_out,
.fini_out = dbus_fini_out,
.write = audio_generic_write,
.get_buffer_out = dbus_get_buffer_out,
.put_buffer_out = dbus_put_buffer_out,
.enable_out = dbus_enable_out,
.volume_out = dbus_volume_out,
.init_in = dbus_init_in,
.fini_in = dbus_fini_in,
.read = dbus_read,
.run_buffer_in = audio_generic_run_buffer_in,
.enable_in = dbus_enable_in,
.volume_in = dbus_volume_in,
};
static struct audio_driver dbus_audio_driver = {
.name = "dbus",
.descr = "Timer based audio exposed with DBus interface",
.init = dbus_audio_init,
.fini = dbus_audio_fini,
.set_dbus_server = dbus_audio_set_server,
.pcm_ops = &dbus_pcm_ops,
.can_be_default = 1,
.max_voices_out = INT_MAX,
.max_voices_in = INT_MAX,
.voice_size_out = sizeof(DBusVoiceOut),
.voice_size_in = sizeof(DBusVoiceIn)
};
static void register_audio_dbus(void)
{
audio_driver_register(&dbus_audio_driver);
}
type_init(register_audio_dbus);
module_dep("ui-dbus")

View File

@@ -222,7 +222,7 @@ static void dsound_log_hresult (HRESULT hr)
AUD_log (AUDIO_CAP, "Reason: %s\n", str);
}
static void G_GNUC_PRINTF (2, 3) dsound_logerr (
static void GCC_FMT_ATTR (2, 3) dsound_logerr (
HRESULT hr,
const char *fmt,
...
@@ -237,7 +237,7 @@ static void G_GNUC_PRINTF (2, 3) dsound_logerr (
dsound_log_hresult (hr);
}
static void G_GNUC_PRINTF (3, 4) dsound_logerr2 (
static void GCC_FMT_ATTR (3, 4) dsound_logerr2 (
HRESULT hr,
const char *typ,
const char *fmt,
@@ -427,18 +427,22 @@ static void dsound_enable_out(HWVoiceOut *hw, bool enable)
}
}
static size_t dsound_buffer_get_free(HWVoiceOut *hw)
static void *dsound_get_buffer_out(HWVoiceOut *hw, size_t *size)
{
DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
HRESULT hr;
DWORD ppos, wpos;
DWORD ppos, wpos, act_size;
size_t req_size;
int err;
void *ret;
hr = IDirectSoundBuffer_GetCurrentPosition(
dsb, &ppos, ds->first_time ? &wpos : NULL);
if (FAILED(hr)) {
dsound_logerr(hr, "Could not get playback buffer position\n");
return 0;
*size = 0;
return NULL;
}
if (ds->first_time) {
@@ -446,20 +450,13 @@ static size_t dsound_buffer_get_free(HWVoiceOut *hw)
ds->first_time = false;
}
return audio_ring_dist(ppos, hw->pos_emul, hw->size_emul);
}
req_size = audio_ring_dist(ppos, hw->pos_emul, hw->size_emul);
req_size = MIN(req_size, hw->size_emul - hw->pos_emul);
static void *dsound_get_buffer_out(HWVoiceOut *hw, size_t *size)
{
DSoundVoiceOut *ds = (DSoundVoiceOut *)hw;
LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
DWORD act_size;
size_t req_size;
int err;
void *ret;
req_size = MIN(*size, hw->size_emul - hw->pos_emul);
assert(req_size > 0);
if (req_size == 0) {
*size = 0;
return NULL;
}
err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
&act_size, NULL, false, ds->s);
@@ -539,12 +536,13 @@ static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size)
DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
HRESULT hr;
DWORD rpos, act_size;
DWORD cpos, rpos, act_size;
size_t req_size;
int err;
void *ret;
hr = IDirectSoundCaptureBuffer_GetCurrentPosition(dscb, NULL, &rpos);
hr = IDirectSoundCaptureBuffer_GetCurrentPosition(
dscb, &cpos, ds->first_time ? &rpos : NULL);
if (FAILED(hr)) {
dsound_logerr(hr, "Could not get capture buffer position\n");
*size = 0;
@@ -556,7 +554,7 @@ static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size)
ds->first_time = false;
}
req_size = audio_ring_dist(rpos, hw->pos_emul, hw->size_emul);
req_size = audio_ring_dist(cpos, hw->pos_emul, hw->size_emul);
req_size = MIN(*size, MIN(req_size, hw->size_emul - hw->pos_emul));
if (req_size == 0) {
@@ -623,7 +621,7 @@ static void *dsound_audio_init(Audiodev *dev)
{
int err;
HRESULT hr;
dsound *s = g_new0(dsound, 1);
dsound *s = g_malloc0(sizeof(dsound));
AudiodevDsoundOptions *dso;
assert(dev->driver == AUDIODEV_DRIVER_DSOUND);
@@ -702,7 +700,6 @@ static struct audio_pcm_ops dsound_pcm_ops = {
.init_out = dsound_init_out,
.fini_out = dsound_fini_out,
.write = audio_generic_write,
.buffer_get_free = dsound_buffer_get_free,
.get_buffer_out = dsound_get_buffer_out,
.put_buffer_out = dsound_put_buffer_out,
.enable_out = dsound_enable_out,

View File

@@ -97,9 +97,9 @@ static void qjack_buffer_create(QJackBuffer *buffer, int channels, int frames)
buffer->used = 0;
buffer->rptr = 0;
buffer->wptr = 0;
buffer->data = g_new(float *, channels);
buffer->data = g_malloc(channels * sizeof(float *));
for (int i = 0; i < channels; ++i) {
buffer->data[i] = g_new(float, frames);
buffer->data[i] = g_malloc(frames * sizeof(float));
}
}
@@ -453,7 +453,7 @@ static int qjack_client_init(QJackClient *c)
jack_on_shutdown(c->client, qjack_shutdown, c);
/* allocate and register the ports */
c->port = g_new(jack_port_t *, c->nchannels);
c->port = g_malloc(sizeof(jack_port_t *) * c->nchannels);
for (int i = 0; i < c->nchannels; ++i) {
char port_name[16];
@@ -483,8 +483,8 @@ static int qjack_client_init(QJackClient *c)
c->buffersize = 512;
}
/* create a 3 period buffer */
qjack_buffer_create(&c->fifo, c->nchannels, c->buffersize * 3);
/* create a 2 period buffer */
qjack_buffer_create(&c->fifo, c->nchannels, c->buffersize * 2);
qjack_client_connect_ports(c);
c->state = QJACK_STATE_RUNNING;
@@ -622,7 +622,6 @@ static void qjack_enable_in(HWVoiceIn *hw, bool enable)
ji->c.enabled = enable;
}
#if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
static int qjack_thread_creator(jack_native_thread_t *thread,
const pthread_attr_t *attr, void *(*function)(void *), void *arg)
{
@@ -636,7 +635,6 @@ static int qjack_thread_creator(jack_native_thread_t *thread,
return ret;
}
#endif
static void *qjack_init(Audiodev *dev)
{
@@ -652,7 +650,6 @@ static struct audio_pcm_ops jack_pcm_ops = {
.init_out = qjack_init_out,
.fini_out = qjack_fini_out,
.write = qjack_write,
.buffer_get_free = audio_generic_buffer_get_free,
.run_buffer_out = audio_generic_run_buffer_out,
.enable_out = qjack_enable_out,
@@ -690,9 +687,7 @@ static void register_audio_jack(void)
{
qemu_mutex_init(&qjack_shutdown_lock);
audio_driver_register(&jack_driver);
#if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
jack_set_thread_creator(qjack_thread_creator);
#endif
jack_set_error_function(qjack_error);
jack_set_info_function(qjack_info);
}

View File

@@ -7,29 +7,24 @@ softmmu_ss.add(files(
'wavcapture.c',
))
softmmu_ss.add(when: coreaudio, if_true: files('coreaudio.m'))
softmmu_ss.add(when: dsound, if_true: files('dsoundaudio.c', 'audio_win_int.c'))
softmmu_ss.add(when: [coreaudio, 'CONFIG_AUDIO_COREAUDIO'], if_true: files('coreaudio.c'))
softmmu_ss.add(when: [dsound, 'CONFIG_AUDIO_DSOUND'], if_true: files('dsoundaudio.c'))
softmmu_ss.add(when: ['CONFIG_AUDIO_WIN_INT'], if_true: files('audio_win_int.c'))
audio_modules = {}
foreach m : [
['alsa', alsa, files('alsaaudio.c')],
['oss', oss, files('ossaudio.c')],
['pa', pulse, files('paaudio.c')],
['sdl', sdl, files('sdlaudio.c')],
['jack', jack, files('jackaudio.c')],
['spice', spice, files('spiceaudio.c')]
['CONFIG_AUDIO_ALSA', 'alsa', alsa, 'alsaaudio.c'],
['CONFIG_AUDIO_OSS', 'oss', oss, 'ossaudio.c'],
['CONFIG_AUDIO_PA', 'pa', pulse, 'paaudio.c'],
['CONFIG_AUDIO_SDL', 'sdl', sdl, 'sdlaudio.c'],
['CONFIG_AUDIO_JACK', 'jack', jack, 'jackaudio.c'],
['CONFIG_SPICE', 'spice', spice, 'spiceaudio.c']
]
if m[1].found()
if config_host.has_key(m[0])
module_ss = ss.source_set()
module_ss.add(m[1], m[2])
audio_modules += {m[0] : module_ss}
module_ss.add(when: m[2], if_true: files(m[3]))
audio_modules += {m[1] : module_ss}
endif
endforeach
if dbus_display
module_ss = ss.source_set()
module_ss.add(when: gio, if_true: files('dbusaudio.c'))
audio_modules += {'dbus': module_ss}
endif
modules += {'audio': audio_modules}

View File

@@ -342,13 +342,13 @@ f_sample *mixeng_clip_float[2] = {
void audio_sample_to_uint64(const void *samples, int pos,
uint64_t *left, uint64_t *right)
{
const struct st_sample *sample = samples;
sample += pos;
#ifdef FLOAT_MIXENG
error_report(
"Coreaudio and floating point samples are not supported by replay yet");
abort();
#else
const struct st_sample *sample = samples;
sample += pos;
*left = sample->l;
*right = sample->r;
#endif
@@ -357,13 +357,13 @@ void audio_sample_to_uint64(const void *samples, int pos,
void audio_sample_from_uint64(void *samples, int pos,
uint64_t left, uint64_t right)
{
struct st_sample *sample = samples;
sample += pos;
#ifdef FLOAT_MIXENG
error_report(
"Coreaudio and floating point samples are not supported by replay yet");
abort();
#else
struct st_sample *sample = samples;
sample += pos;
sample->l = left;
sample->r = right;
#endif

View File

@@ -118,7 +118,6 @@ static struct audio_pcm_ops no_pcm_ops = {
.init_out = no_init_out,
.fini_out = no_fini_out,
.write = no_write,
.buffer_get_free = audio_generic_buffer_get_free,
.run_buffer_out = audio_generic_run_buffer_out,
.enable_out = no_enable_out,

View File

@@ -63,7 +63,7 @@ struct oss_params {
int fragsize;
};
static void G_GNUC_PRINTF (2, 3) oss_logerr (int err, const char *fmt, ...)
static void GCC_FMT_ATTR (2, 3) oss_logerr (int err, const char *fmt, ...)
{
va_list ap;
@@ -74,7 +74,7 @@ static void G_GNUC_PRINTF (2, 3) oss_logerr (int err, const char *fmt, ...)
AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
}
static void G_GNUC_PRINTF (3, 4) oss_logerr2 (
static void GCC_FMT_ATTR (3, 4) oss_logerr2 (
int err,
const char *typ,
const char *fmt,
@@ -389,23 +389,11 @@ static void oss_run_buffer_out(HWVoiceOut *hw)
}
}
static size_t oss_buffer_get_free(HWVoiceOut *hw)
{
OSSVoiceOut *oss = (OSSVoiceOut *)hw;
if (oss->mmapped) {
return oss_get_available_bytes(oss);
} else {
return audio_generic_buffer_get_free(hw);
}
}
static void *oss_get_buffer_out(HWVoiceOut *hw, size_t *size)
{
OSSVoiceOut *oss = (OSSVoiceOut *)hw;
OSSVoiceOut *oss = (OSSVoiceOut *) hw;
if (oss->mmapped) {
*size = hw->size_emul - hw->pos_emul;
*size = MIN(oss_get_available_bytes(oss), hw->size_emul - hw->pos_emul);
return hw->buf_emul + hw->pos_emul;
} else {
return audio_generic_get_buffer_out(hw, size);
@@ -762,7 +750,6 @@ static struct audio_pcm_ops oss_pcm_ops = {
.init_out = oss_init_out,
.fini_out = oss_fini_out,
.write = oss_write,
.buffer_get_free = oss_buffer_get_free,
.run_buffer_out = oss_run_buffer_out,
.get_buffer_out = oss_get_buffer_out,
.put_buffer_out = oss_put_buffer_out,

View File

@@ -43,7 +43,7 @@ typedef struct {
static void qpa_conn_fini(PAConnection *c);
static void G_GNUC_PRINTF (2, 3) qpa_logerr (int err, const char *fmt, ...)
static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...)
{
va_list ap;
@@ -201,11 +201,13 @@ unlock_and_fail:
return 0;
}
static size_t qpa_buffer_get_free(HWVoiceOut *hw)
static void *qpa_get_buffer_out(HWVoiceOut *hw, size_t *size)
{
PAVoiceOut *p = (PAVoiceOut *)hw;
PAVoiceOut *p = (PAVoiceOut *) hw;
PAConnection *c = p->g->conn;
void *ret;
size_t l;
int r;
pa_threaded_mainloop_lock(c->mainloop);
@@ -214,6 +216,7 @@ static size_t qpa_buffer_get_free(HWVoiceOut *hw)
if (pa_stream_get_state(p->stream) != PA_STREAM_READY) {
/* wait for stream to become ready */
l = 0;
ret = NULL;
goto unlock;
}
@@ -221,33 +224,16 @@ static size_t qpa_buffer_get_free(HWVoiceOut *hw)
CHECK_SUCCESS_GOTO(c, l != (size_t) -1, unlock_and_fail,
"pa_stream_writable_size failed\n");
unlock:
pa_threaded_mainloop_unlock(c->mainloop);
return l;
unlock_and_fail:
pa_threaded_mainloop_unlock(c->mainloop);
return 0;
}
static void *qpa_get_buffer_out(HWVoiceOut *hw, size_t *size)
{
PAVoiceOut *p = (PAVoiceOut *)hw;
PAConnection *c = p->g->conn;
void *ret;
int r;
pa_threaded_mainloop_lock(c->mainloop);
CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail,
"pa_threaded_mainloop_lock failed\n");
*size = -1;
r = pa_stream_begin_write(p->stream, &ret, size);
CHECK_SUCCESS_GOTO(c, r >= 0, unlock_and_fail,
"pa_stream_begin_write failed\n");
unlock:
pa_threaded_mainloop_unlock(c->mainloop);
if (*size > l) {
*size = l;
}
return ret;
unlock_and_fail:
@@ -549,8 +535,11 @@ static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as,
}
audio_pcm_init_info (&hw->info, &obt_as);
/* hw->samples counts in frames */
hw->samples = audio_buffer_frames(
/*
* This is wrong. hw->samples counts in frames. hw->samples will be
* number of channels times larger than expected.
*/
hw->samples = audio_buffer_samples(
qapi_AudiodevPaPerDirectionOptions_base(ppdo), &obt_as, 46440);
return 0;
@@ -598,8 +587,11 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
}
audio_pcm_init_info (&hw->info, &obt_as);
/* hw->samples counts in frames */
hw->samples = audio_buffer_frames(
/*
* This is wrong. hw->samples counts in frames. hw->samples will be
* number of channels times larger than expected.
*/
hw->samples = audio_buffer_samples(
qapi_AudiodevPaPerDirectionOptions_base(ppdo), &obt_as, 46440);
return 0;
@@ -752,7 +744,7 @@ static int qpa_validate_per_direction_opts(Audiodev *dev,
{
if (!pdo->has_latency) {
pdo->has_latency = true;
pdo->latency = 46440;
pdo->latency = 15000;
}
return 1;
}
@@ -760,7 +752,7 @@ static int qpa_validate_per_direction_opts(Audiodev *dev,
/* common */
static void *qpa_conn_init(const char *server)
{
PAConnection *c = g_new0(PAConnection, 1);
PAConnection *c = g_malloc0(sizeof(PAConnection));
QTAILQ_INSERT_TAIL(&pa_conns, c, list);
c->mainloop = pa_threaded_mainloop_new();
@@ -849,7 +841,7 @@ static void *qpa_audio_init(Audiodev *dev)
return NULL;
}
g = g_new0(paaudio, 1);
g = g_malloc0(sizeof(paaudio));
server = popts->has_server ? popts->server : NULL;
g->dev = dev;
@@ -909,7 +901,6 @@ static struct audio_pcm_ops qpa_pcm_ops = {
.init_out = qpa_init_out,
.fini_out = qpa_fini_out,
.write = qpa_write,
.buffer_get_free = qpa_buffer_get_free,
.get_buffer_out = qpa_get_buffer_out,
.put_buffer_out = qpa_put_buffer_out,
.volume_out = qpa_volume_out,

View File

@@ -55,7 +55,7 @@ typedef struct SDLVoiceIn {
SDL_AudioDeviceID devid;
} SDLVoiceIn;
static void G_GNUC_PRINTF (1, 2) sdl_logerr (const char *fmt, ...)
static void GCC_FMT_ATTR (1, 2) sdl_logerr (const char *fmt, ...)
{
va_list ap;
@@ -224,11 +224,12 @@ static void sdl_callback_out(void *opaque, Uint8 *buf, int len)
/* dolog("callback_out: len=%d avail=%zu\n", len, hw->pending_emul); */
while (hw->pending_emul && len) {
size_t write_len, start;
start = audio_ring_posb(hw->pos_emul, hw->pending_emul,
hw->size_emul);
assert(start < hw->size_emul);
size_t write_len;
ssize_t start = (ssize_t)hw->pos_emul - hw->pending_emul;
if (start < 0) {
start += hw->size_emul;
}
assert(start >= 0 && start < hw->size_emul);
write_len = MIN(MIN(hw->pending_emul, len),
hw->size_emul - start);
@@ -309,7 +310,6 @@ static void sdl_callback_in(void *opaque, Uint8 *buf, int len)
SDL_UnlockAudioDevice(sdl->devid); \
}
SDL_WRAPPER_FUNC(buffer_get_free, size_t, (HWVoiceOut *hw), (hw), Out)
SDL_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size),
(hw, size), Out)
SDL_WRAPPER_FUNC(put_buffer_out, size_t,
@@ -347,8 +347,11 @@ static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as,
req.freq = as->freq;
req.format = aud_to_sdlfmt (as->fmt);
req.channels = as->nchannels;
/* SDL samples are QEMU frames */
req.samples = audio_buffer_frames(
/*
* This is wrong. SDL samples are QEMU frames. The buffer size will be
* the requested buffer size multiplied by the number of channels.
*/
req.samples = audio_buffer_samples(
qapi_AudiodevSdlPerDirectionOptions_base(spdo), as, 11610);
req.callback = sdl_callback_out;
req.userdata = sdl;
@@ -469,8 +472,6 @@ static struct audio_pcm_ops sdl_pcm_ops = {
.fini_out = sdl_fini_out,
/* wrapper for audio_generic_write */
.write = sdl_write,
/* wrapper for audio_generic_buffer_get_free */
.buffer_get_free = sdl_buffer_get_free,
/* wrapper for audio_generic_get_buffer_out */
.get_buffer_out = sdl_get_buffer_out,
/* wrapper for audio_generic_put_buffer_out */

View File

@@ -13,11 +13,6 @@ alsa_resume_out(void) "Resuming suspended output stream"
# ossaudio.c
oss_version(int version) "OSS version = 0x%x"
# dbusaudio.c
dbus_audio_register(const char *s, const char *dir) "sender = %s, dir = %s"
dbus_audio_put_buffer_out(size_t len) "len = %zu"
dbus_audio_read(size_t len) "len = %zu"
# audio.c
audio_timer_start(int interval) "interval %d ms"
audio_timer_stop(void) ""

View File

@@ -197,7 +197,6 @@ static struct audio_pcm_ops wav_pcm_ops = {
.init_out = wav_init_out,
.fini_out = wav_fini_out,
.write = wav_write_out,
.buffer_get_free = audio_generic_buffer_get_free,
.run_buffer_out = audio_generic_run_buffer_out,
.enable_out = wav_enable_out,
};

View File

@@ -26,7 +26,6 @@
#include "qapi/error.h"
#include "standard-headers/linux/virtio_crypto.h"
#include "crypto/cipher.h"
#include "crypto/akcipher.h"
#include "qom/object.h"
@@ -43,11 +42,10 @@ typedef struct CryptoDevBackendBuiltinSession {
QCryptoCipher *cipher;
uint8_t direction; /* encryption or decryption */
uint8_t type; /* cipher? hash? aead? */
QCryptoAkCipher *akcipher;
QTAILQ_ENTRY(CryptoDevBackendBuiltinSession) next;
} CryptoDevBackendBuiltinSession;
/* Max number of symmetric/asymmetric sessions */
/* Max number of symmetric sessions */
#define MAX_NUM_SESSIONS 256
#define CRYPTODEV_BUITLIN_MAX_AUTH_KEY_LEN 512
@@ -82,17 +80,15 @@ static void cryptodev_builtin_init(
backend->conf.crypto_services =
1u << VIRTIO_CRYPTO_SERVICE_CIPHER |
1u << VIRTIO_CRYPTO_SERVICE_HASH |
1u << VIRTIO_CRYPTO_SERVICE_MAC |
1u << VIRTIO_CRYPTO_SERVICE_AKCIPHER;
1u << VIRTIO_CRYPTO_SERVICE_MAC;
backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC;
backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1;
backend->conf.akcipher_algo = 1u << VIRTIO_CRYPTO_AKCIPHER_RSA;
/*
* Set the Maximum length of crypto request.
* Why this value? Just avoid to overflow when
* memory allocation for each crypto request.
*/
backend->conf.max_size = LONG_MAX - sizeof(CryptoDevBackendOpInfo);
backend->conf.max_size = LONG_MAX - sizeof(CryptoDevBackendSymOpInfo);
backend->conf.max_cipher_key_len = CRYPTODEV_BUITLIN_MAX_CIPHER_KEY_LEN;
backend->conf.max_auth_key_len = CRYPTODEV_BUITLIN_MAX_AUTH_KEY_LEN;
@@ -152,55 +148,6 @@ err:
return -1;
}
static int cryptodev_builtin_get_rsa_hash_algo(
int virtio_rsa_hash, Error **errp)
{
switch (virtio_rsa_hash) {
case VIRTIO_CRYPTO_RSA_MD5:
return QCRYPTO_HASH_ALG_MD5;
case VIRTIO_CRYPTO_RSA_SHA1:
return QCRYPTO_HASH_ALG_SHA1;
case VIRTIO_CRYPTO_RSA_SHA256:
return QCRYPTO_HASH_ALG_SHA256;
case VIRTIO_CRYPTO_RSA_SHA512:
return QCRYPTO_HASH_ALG_SHA512;
default:
error_setg(errp, "Unsupported rsa hash algo: %d", virtio_rsa_hash);
return -1;
}
}
static int cryptodev_builtin_set_rsa_options(
int virtio_padding_algo,
int virtio_hash_algo,
QCryptoAkCipherOptionsRSA *opt,
Error **errp)
{
if (virtio_padding_algo == VIRTIO_CRYPTO_RSA_PKCS1_PADDING) {
int hash_alg;
hash_alg = cryptodev_builtin_get_rsa_hash_algo(virtio_hash_algo, errp);
if (hash_alg < 0) {
return -1;
}
opt->hash_alg = hash_alg;
opt->padding_alg = QCRYPTO_RSA_PADDING_ALG_PKCS1;
return 0;
}
if (virtio_padding_algo == VIRTIO_CRYPTO_RSA_RAW_PADDING) {
opt->padding_alg = QCRYPTO_RSA_PADDING_ALG_RAW;
return 0;
}
error_setg(errp, "Unsupported rsa padding algo: %d", virtio_padding_algo);
return -1;
}
static int cryptodev_builtin_create_cipher_session(
CryptoDevBackendBuiltin *builtin,
CryptoDevBackendSymSessionInfo *sess_info,
@@ -293,89 +240,26 @@ static int cryptodev_builtin_create_cipher_session(
return index;
}
static int cryptodev_builtin_create_akcipher_session(
CryptoDevBackendBuiltin *builtin,
CryptoDevBackendAsymSessionInfo *sess_info,
Error **errp)
{
CryptoDevBackendBuiltinSession *sess;
QCryptoAkCipher *akcipher;
int index;
QCryptoAkCipherKeyType type;
QCryptoAkCipherOptions opts;
switch (sess_info->algo) {
case VIRTIO_CRYPTO_AKCIPHER_RSA:
opts.alg = QCRYPTO_AKCIPHER_ALG_RSA;
if (cryptodev_builtin_set_rsa_options(sess_info->u.rsa.padding_algo,
sess_info->u.rsa.hash_algo, &opts.u.rsa, errp) != 0) {
return -1;
}
break;
/* TODO support DSA&ECDSA until qemu crypto framework support these */
default:
error_setg(errp, "Unsupported akcipher alg %u", sess_info->algo);
return -1;
}
switch (sess_info->keytype) {
case VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PUBLIC:
type = QCRYPTO_AKCIPHER_KEY_TYPE_PUBLIC;
break;
case VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PRIVATE:
type = QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE;
break;
default:
error_setg(errp, "Unsupported akcipher keytype %u", sess_info->keytype);
return -1;
}
index = cryptodev_builtin_get_unused_session_index(builtin);
if (index < 0) {
error_setg(errp, "Total number of sessions created exceeds %u",
MAX_NUM_SESSIONS);
return -1;
}
akcipher = qcrypto_akcipher_new(&opts, type, sess_info->key,
sess_info->keylen, errp);
if (!akcipher) {
return -1;
}
sess = g_new0(CryptoDevBackendBuiltinSession, 1);
sess->akcipher = akcipher;
builtin->sessions[index] = sess;
return index;
}
static int64_t cryptodev_builtin_create_session(
static int64_t cryptodev_builtin_sym_create_session(
CryptoDevBackend *backend,
CryptoDevBackendSessionInfo *sess_info,
CryptoDevBackendSymSessionInfo *sess_info,
uint32_t queue_index, Error **errp)
{
CryptoDevBackendBuiltin *builtin =
CRYPTODEV_BACKEND_BUILTIN(backend);
CryptoDevBackendSymSessionInfo *sym_sess_info;
CryptoDevBackendAsymSessionInfo *asym_sess_info;
int64_t session_id = -1;
int ret;
switch (sess_info->op_code) {
case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION:
sym_sess_info = &sess_info->u.sym_sess_info;
return cryptodev_builtin_create_cipher_session(
builtin, sym_sess_info, errp);
case VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION:
asym_sess_info = &sess_info->u.asym_sess_info;
return cryptodev_builtin_create_akcipher_session(
builtin, asym_sess_info, errp);
ret = cryptodev_builtin_create_cipher_session(
builtin, sess_info, errp);
if (ret < 0) {
return ret;
} else {
session_id = ret;
}
break;
case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
default:
@@ -384,44 +268,50 @@ static int64_t cryptodev_builtin_create_session(
return -1;
}
return -1;
return session_id;
}
static int cryptodev_builtin_close_session(
static int cryptodev_builtin_sym_close_session(
CryptoDevBackend *backend,
uint64_t session_id,
uint32_t queue_index, Error **errp)
{
CryptoDevBackendBuiltin *builtin =
CRYPTODEV_BACKEND_BUILTIN(backend);
CryptoDevBackendBuiltinSession *session;
assert(session_id < MAX_NUM_SESSIONS && builtin->sessions[session_id]);
session = builtin->sessions[session_id];
if (session->cipher) {
qcrypto_cipher_free(session->cipher);
} else if (session->akcipher) {
qcrypto_akcipher_free(session->akcipher);
}
g_free(session);
qcrypto_cipher_free(builtin->sessions[session_id]->cipher);
g_free(builtin->sessions[session_id]);
builtin->sessions[session_id] = NULL;
return 0;
}
static int cryptodev_builtin_sym_operation(
CryptoDevBackendBuiltinSession *sess,
CryptoDevBackendSymOpInfo *op_info, Error **errp)
CryptoDevBackend *backend,
CryptoDevBackendSymOpInfo *op_info,
uint32_t queue_index, Error **errp)
{
CryptoDevBackendBuiltin *builtin =
CRYPTODEV_BACKEND_BUILTIN(backend);
CryptoDevBackendBuiltinSession *sess;
int ret;
if (op_info->session_id >= MAX_NUM_SESSIONS ||
builtin->sessions[op_info->session_id] == NULL) {
error_setg(errp, "Cannot find a valid session id: %" PRIu64 "",
op_info->session_id);
return -VIRTIO_CRYPTO_INVSESS;
}
if (op_info->op_type == VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING) {
error_setg(errp,
"Algorithm chain is unsupported for cryptdoev-builtin");
return -VIRTIO_CRYPTO_NOTSUPP;
}
sess = builtin->sessions[op_info->session_id];
if (op_info->iv_len > 0) {
ret = qcrypto_cipher_setiv(sess->cipher, op_info->iv,
op_info->iv_len, errp);
@@ -443,99 +333,9 @@ static int cryptodev_builtin_sym_operation(
return -VIRTIO_CRYPTO_ERR;
}
}
return VIRTIO_CRYPTO_OK;
}
static int cryptodev_builtin_asym_operation(
CryptoDevBackendBuiltinSession *sess, uint32_t op_code,
CryptoDevBackendAsymOpInfo *op_info, Error **errp)
{
int ret;
switch (op_code) {
case VIRTIO_CRYPTO_AKCIPHER_ENCRYPT:
ret = qcrypto_akcipher_encrypt(sess->akcipher,
op_info->src, op_info->src_len,
op_info->dst, op_info->dst_len, errp);
break;
case VIRTIO_CRYPTO_AKCIPHER_DECRYPT:
ret = qcrypto_akcipher_decrypt(sess->akcipher,
op_info->src, op_info->src_len,
op_info->dst, op_info->dst_len, errp);
break;
case VIRTIO_CRYPTO_AKCIPHER_SIGN:
ret = qcrypto_akcipher_sign(sess->akcipher,
op_info->src, op_info->src_len,
op_info->dst, op_info->dst_len, errp);
break;
case VIRTIO_CRYPTO_AKCIPHER_VERIFY:
ret = qcrypto_akcipher_verify(sess->akcipher,
op_info->src, op_info->src_len,
op_info->dst, op_info->dst_len, errp);
break;
default:
return -VIRTIO_CRYPTO_ERR;
}
if (ret < 0) {
if (op_code == VIRTIO_CRYPTO_AKCIPHER_VERIFY) {
return -VIRTIO_CRYPTO_KEY_REJECTED;
}
return -VIRTIO_CRYPTO_ERR;
}
/* Buffer is too short, typically the driver should handle this case */
if (unlikely(ret > op_info->dst_len)) {
if (errp && !*errp) {
error_setg(errp, "dst buffer too short");
}
return -VIRTIO_CRYPTO_ERR;
}
op_info->dst_len = ret;
return VIRTIO_CRYPTO_OK;
}
static int cryptodev_builtin_operation(
CryptoDevBackend *backend,
CryptoDevBackendOpInfo *op_info,
uint32_t queue_index, Error **errp)
{
CryptoDevBackendBuiltin *builtin =
CRYPTODEV_BACKEND_BUILTIN(backend);
CryptoDevBackendBuiltinSession *sess;
CryptoDevBackendSymOpInfo *sym_op_info;
CryptoDevBackendAsymOpInfo *asym_op_info;
enum CryptoDevBackendAlgType algtype = op_info->algtype;
int ret = -VIRTIO_CRYPTO_ERR;
if (op_info->session_id >= MAX_NUM_SESSIONS ||
builtin->sessions[op_info->session_id] == NULL) {
error_setg(errp, "Cannot find a valid session id: %" PRIu64 "",
op_info->session_id);
return -VIRTIO_CRYPTO_INVSESS;
}
sess = builtin->sessions[op_info->session_id];
if (algtype == CRYPTODEV_BACKEND_ALG_SYM) {
sym_op_info = op_info->u.sym_op_info;
ret = cryptodev_builtin_sym_operation(sess, sym_op_info, errp);
} else if (algtype == CRYPTODEV_BACKEND_ALG_ASYM) {
asym_op_info = op_info->u.asym_op_info;
ret = cryptodev_builtin_asym_operation(sess, op_info->op_code,
asym_op_info, errp);
}
return ret;
}
static void cryptodev_builtin_cleanup(
CryptoDevBackend *backend,
Error **errp)
@@ -548,7 +348,7 @@ static void cryptodev_builtin_cleanup(
for (i = 0; i < MAX_NUM_SESSIONS; i++) {
if (builtin->sessions[i] != NULL) {
cryptodev_builtin_close_session(backend, i, 0, &error_abort);
cryptodev_builtin_sym_close_session(backend, i, 0, &error_abort);
}
}
@@ -570,9 +370,9 @@ cryptodev_builtin_class_init(ObjectClass *oc, void *data)
bc->init = cryptodev_builtin_init;
bc->cleanup = cryptodev_builtin_cleanup;
bc->create_session = cryptodev_builtin_create_session;
bc->close_session = cryptodev_builtin_close_session;
bc->do_op = cryptodev_builtin_operation;
bc->create_session = cryptodev_builtin_sym_create_session;
bc->close_session = cryptodev_builtin_sym_close_session;
bc->do_sym_op = cryptodev_builtin_sym_operation;
}
static const TypeInfo cryptodev_builtin_info = {

View File

@@ -259,33 +259,7 @@ static int64_t cryptodev_vhost_user_sym_create_session(
return -1;
}
static int64_t cryptodev_vhost_user_create_session(
CryptoDevBackend *backend,
CryptoDevBackendSessionInfo *sess_info,
uint32_t queue_index, Error **errp)
{
uint32_t op_code = sess_info->op_code;
CryptoDevBackendSymSessionInfo *sym_sess_info;
switch (op_code) {
case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION:
case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
case VIRTIO_CRYPTO_AEAD_CREATE_SESSION:
sym_sess_info = &sess_info->u.sym_sess_info;
return cryptodev_vhost_user_sym_create_session(backend, sym_sess_info,
queue_index, errp);
default:
error_setg(errp, "Unsupported opcode :%" PRIu32 "",
sess_info->op_code);
return -1;
}
return -1;
}
static int cryptodev_vhost_user_close_session(
static int cryptodev_vhost_user_sym_close_session(
CryptoDevBackend *backend,
uint64_t session_id,
uint32_t queue_index, Error **errp)
@@ -377,9 +351,9 @@ cryptodev_vhost_user_class_init(ObjectClass *oc, void *data)
bc->init = cryptodev_vhost_user_init;
bc->cleanup = cryptodev_vhost_user_cleanup;
bc->create_session = cryptodev_vhost_user_create_session;
bc->close_session = cryptodev_vhost_user_close_session;
bc->do_op = NULL;
bc->create_session = cryptodev_vhost_user_sym_create_session;
bc->close_session = cryptodev_vhost_user_sym_close_session;
bc->do_sym_op = NULL;
object_class_property_add_str(oc, "chardev",
cryptodev_vhost_user_get_chardev,

View File

@@ -39,7 +39,7 @@ cryptodev_backend_new_client(const char *model,
{
CryptoDevBackendClient *cc;
cc = g_new0(CryptoDevBackendClient, 1);
cc = g_malloc0(sizeof(CryptoDevBackendClient));
cc->model = g_strdup(model);
if (name) {
cc->name = g_strdup(name);
@@ -72,9 +72,9 @@ void cryptodev_backend_cleanup(
}
}
int64_t cryptodev_backend_create_session(
int64_t cryptodev_backend_sym_create_session(
CryptoDevBackend *backend,
CryptoDevBackendSessionInfo *sess_info,
CryptoDevBackendSymSessionInfo *sess_info,
uint32_t queue_index, Error **errp)
{
CryptoDevBackendClass *bc =
@@ -87,7 +87,7 @@ int64_t cryptodev_backend_create_session(
return -1;
}
int cryptodev_backend_close_session(
int cryptodev_backend_sym_close_session(
CryptoDevBackend *backend,
uint64_t session_id,
uint32_t queue_index, Error **errp)
@@ -102,16 +102,16 @@ int cryptodev_backend_close_session(
return -1;
}
static int cryptodev_backend_operation(
static int cryptodev_backend_sym_operation(
CryptoDevBackend *backend,
CryptoDevBackendOpInfo *op_info,
CryptoDevBackendSymOpInfo *op_info,
uint32_t queue_index, Error **errp)
{
CryptoDevBackendClass *bc =
CRYPTODEV_BACKEND_GET_CLASS(backend);
if (bc->do_op) {
return bc->do_op(backend, op_info, queue_index, errp);
if (bc->do_sym_op) {
return bc->do_sym_op(backend, op_info, queue_index, errp);
}
return -VIRTIO_CRYPTO_ERR;
@@ -123,18 +123,20 @@ int cryptodev_backend_crypto_operation(
uint32_t queue_index, Error **errp)
{
VirtIOCryptoReq *req = opaque;
CryptoDevBackendOpInfo *op_info = &req->op_info;
enum CryptoDevBackendAlgType algtype = req->flags;
if ((algtype != CRYPTODEV_BACKEND_ALG_SYM)
&& (algtype != CRYPTODEV_BACKEND_ALG_ASYM)) {
if (req->flags == CRYPTODEV_BACKEND_ALG_SYM) {
CryptoDevBackendSymOpInfo *op_info;
op_info = req->u.sym_op_info;
return cryptodev_backend_sym_operation(backend,
op_info, queue_index, errp);
} else {
error_setg(errp, "Unsupported cryptodev alg type: %" PRIu32 "",
algtype);
return -VIRTIO_CRYPTO_NOTSUPP;
req->flags);
return -VIRTIO_CRYPTO_NOTSUPP;
}
return cryptodev_backend_operation(backend, op_info, queue_index, errp);
return -VIRTIO_CRYPTO_ERR;
}
static void

View File

@@ -114,19 +114,14 @@ dbus_get_proxies(DBusVMState *self, GError **err)
"org.qemu.VMState1",
NULL, err);
if (!proxy) {
if (err != NULL && *err != NULL) {
warn_report("%s: Failed to create proxy: %s",
__func__, (*err)->message);
g_clear_error(err);
}
continue;
return NULL;
}
result = g_dbus_proxy_get_cached_property(proxy, "Id");
if (!result) {
warn_report("%s: VMState Id property is missing.", __func__);
g_clear_object(&proxy);
continue;
g_set_error_literal(err, G_IO_ERROR, G_IO_ERROR_FAILED,
"VMState Id property is missing.");
return NULL;
}
id = g_variant_dup_string(result, &size);

View File

@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<!--
org.qemu.VMState1:
This interface must be implemented at the object path
``/org/qemu/VMState1`` to support helper migration.
-->
<interface name="org.qemu.VMState1">
<!--
Id:
A string that identifies the helper uniquely. (maximum 256 bytes
including terminating NUL byte)
.. note::
The VMState helper ID namespace is its own namespace. In particular,
it is not related to QEMU "id" used in -object/-device objects.
-->
<property name="Id" type="s" access="read"/>
<!--
Load:
@data: data to restore the state.
The method called on destination with the state to restore.
The helper may be initially started in a waiting state (with an
``-incoming`` argument for example), and it may resume on success.
An error may be returned to the caller.
-->
<method name="Load">
<arg type="ay" name="data" direction="in"/>
</method>
<!--
Save:
@data: state data to save for later resume.
The method called on the source to get the current state to be
migrated. The helper should continue to run normally.
An error may be returned to the caller.
-->
<method name="Save">
<arg type="ay" name="data" direction="out"/>
</method>
</interface>
</node>

View File

@@ -1,81 +0,0 @@
/*
* QEMU host SGX EPC memory backend
*
* Copyright (C) 2019 Intel Corporation
*
* Authors:
* Sean Christopherson <sean.j.christopherson@intel.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include <sys/ioctl.h>
#include "qemu/osdep.h"
#include "qom/object_interfaces.h"
#include "qapi/error.h"
#include "sysemu/hostmem.h"
#include "hw/i386/hostmem-epc.h"
static void
sgx_epc_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
{
uint32_t ram_flags;
char *name;
int fd;
if (!backend->size) {
error_setg(errp, "can't create backend with size 0");
return;
}
fd = qemu_open_old("/dev/sgx_vepc", O_RDWR);
if (fd < 0) {
error_setg_errno(errp, errno,
"failed to open /dev/sgx_vepc to alloc SGX EPC");
return;
}
name = object_get_canonical_path(OBJECT(backend));
ram_flags = (backend->share ? RAM_SHARED : 0) | RAM_PROTECTED;
memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
name, backend->size, ram_flags,
fd, 0, errp);
g_free(name);
}
static void sgx_epc_backend_instance_init(Object *obj)
{
HostMemoryBackend *m = MEMORY_BACKEND(obj);
m->share = true;
m->merge = false;
m->dump = false;
}
static void sgx_epc_backend_class_init(ObjectClass *oc, void *data)
{
HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
bc->alloc = sgx_epc_backend_memory_alloc;
}
static const TypeInfo sgx_epc_backed_info = {
.name = TYPE_MEMORY_BACKEND_EPC,
.parent = TYPE_MEMORY_BACKEND,
.instance_init = sgx_epc_backend_instance_init,
.class_init = sgx_epc_backend_class_init,
.instance_size = sizeof(HostMemoryBackendEpc),
};
static void register_types(void)
{
int fd = qemu_open_old("/dev/sgx_vepc", O_RDWR);
if (fd >= 0) {
close(fd);
type_register_static(&sgx_epc_backed_info);
}
}
type_init(register_types);

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