Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Andrea Fioraldi 2022-02-18 10:23:21 +01:00
commit e2f6827b05
508 changed files with 17707 additions and 6160 deletions

View File

@ -32,7 +32,6 @@ 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
.gitignore vendored
View File

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

View File

@ -473,33 +473,6 @@ 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

View File

@ -11,6 +11,6 @@ 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 ctags curl cyrus-sasl dbus diffutils dtc 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'
PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage ctags curl cyrus-sasl dbus diffutils dtc fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 llvm 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'
PYPI_PKGS=''
PYTHON='/usr/local/bin/python3'

View File

@ -11,6 +11,6 @@ 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 ctags curl cyrus-sasl dbus diffutils dtc 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'
PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage ctags curl cyrus-sasl dbus diffutils dtc fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 llvm 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'
PYPI_PKGS=''
PYTHON='/usr/local/bin/python3'

View File

@ -11,6 +11,6 @@ MAKE='/usr/local/bin/gmake'
NINJA='/usr/local/bin/ninja'
PACKAGING_COMMAND='brew'
PIP3='/usr/local/bin/pip3'
PKGS='bash bc bzip2 capstone ccache cpanminus ctags curl dbus diffutils dtc 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'
PKGS='bash bc bzip2 capstone ccache cpanminus ctags curl dbus diffutils dtc gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo 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 virtualenv'
PYTHON='/usr/local/bin/python3'

View File

@ -14,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]*)";
version="$(git describe --match v[0-9]* 2>/dev/null || git rev-parse --short HEAD)";
mv -v qemu-setup*.exe qemu-setup-${version}.exe;
fi

View File

@ -44,7 +44,6 @@ msys2-64bit:
mingw-w64-x86_64-libssh
mingw-w64-x86_64-libtasn1
mingw-w64-x86_64-libusb
mingw-w64-x86_64-libxml2
mingw-w64-x86_64-nettle
mingw-w64-x86_64-ninja
mingw-w64-x86_64-pixman
@ -80,7 +79,6 @@ msys2-32bit:
mingw-w64-i686-libssh
mingw-w64-i686-libtasn1
mingw-w64-i686-libusb
mingw-w64-i686-libxml2
mingw-w64-i686-lzo2
mingw-w64-i686-ninja
mingw-w64-i686-pixman

2
.gitmodules vendored
View File

@ -66,4 +66,4 @@
url = https://gitlab.com/qemu-project/vbootrom.git
[submodule "tests/lcitool/libvirt-ci"]
path = tests/lcitool/libvirt-ci
url = http://gitlab.com/libvirt/libvirt-ci
url = https://gitlab.com/libvirt/libvirt-ci.git

View File

@ -286,6 +286,13 @@ F: include/hw/riscv/
F: linux-user/host/riscv32/
F: linux-user/host/riscv64/
RISC-V XVentanaCondOps extension
M: Philipp Tomsich <philipp.tomsich@vrull.eu>
L: qemu-riscv@nongnu.org
S: Supported
F: target/riscv/XVentanaCondOps.decode
F: target/riscv/insn_trans/trans_xventanacondops.c.inc
RENESAS RX CPUs
R: Yoshinori Sato <ysato@users.sourceforge.jp>
S: Orphan
@ -408,7 +415,7 @@ M: Paolo Bonzini <pbonzini@redhat.com>
M: Marcelo Tosatti <mtosatti@redhat.com>
L: kvm@vger.kernel.org
S: Supported
F: docs/amd-memory-encryption.txt
F: docs/system/i386/amd-memory-encryption.rst
F: docs/system/i386/sgx.rst
F: target/i386/kvm/
F: target/i386/sev*
@ -818,7 +825,6 @@ F: docs/system/arm/palm.rst
Raspberry Pi
M: Peter Maydell <peter.maydell@linaro.org>
R: Andrew Baumann <Andrew.Baumann@microsoft.com>
R: Philippe Mathieu-Daudé <f4bug@amsat.org>
L: qemu-arm@nongnu.org
S: Odd Fixes
@ -958,6 +964,12 @@ F: hw/display/dpcd.c
F: include/hw/display/dpcd.h
F: docs/system/arm/xlnx-versal-virt.rst
Xilinx Versal OSPI
M: Francisco Iglesias <francisco.iglesias@xilinx.com>
S: Maintained
F: hw/ssi/xlnx-versal-ospi.c
F: include/hw/ssi/xlnx-versal-ospi.h
ARM ACPI Subsystem
M: Shannon Zhao <shannon.zhaosl@gmail.com>
L: qemu-arm@nongnu.org
@ -3181,6 +3193,7 @@ R: Kyle Evans <kevans@freebsd.org>
S: Maintained
F: bsd-user/
F: configs/targets/*-bsd-user.mak
F: tests/vm/*bsd
T: git https://github.com/qemu-bsd-user/qemu-bsd-user bsd-user-rebase-3.1
Linux user
@ -3579,6 +3592,7 @@ F: .travis.yml
F: scripts/ci/
F: tests/docker/
F: tests/vm/
F: tests/lcitool/
F: scripts/archive-source.sh
W: https://gitlab.com/qemu-project/qemu/pipelines
W: https://travis-ci.org/qemu/qemu

View File

@ -206,7 +206,8 @@ 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]' \) -type f \
find . \( -name '*.so' -o -name '*.dll' -o \
-name '*.[oda]' -o -name '*.gcno' \) -type f \
! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-aarch64.a \
! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-arm.a \
-exec rm {} +

View File

@ -13,14 +13,6 @@
* See the COPYING file in the top-level directory.
*/
static void atomic_trace_rmw_pre(CPUArchState *env, target_ulong addr,
MemOpIdx oi)
{
CPUState *cpu = env_cpu(env);
trace_guest_rmw_before_exec(cpu, addr, oi);
}
static void atomic_trace_rmw_post(CPUArchState *env, target_ulong addr,
MemOpIdx oi)
{
@ -28,24 +20,12 @@ static void atomic_trace_rmw_post(CPUArchState *env, target_ulong addr,
}
#if HAVE_ATOMIC128
static void atomic_trace_ld_pre(CPUArchState *env, target_ulong addr,
MemOpIdx oi)
{
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
}
static void atomic_trace_ld_post(CPUArchState *env, target_ulong addr,
MemOpIdx oi)
{
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
}
static void atomic_trace_st_pre(CPUArchState *env, target_ulong addr,
MemOpIdx oi)
{
trace_guest_st_before_exec(env_cpu(env), addr, oi);
}
static void atomic_trace_st_post(CPUArchState *env, target_ulong addr,
MemOpIdx oi)
{

View File

@ -77,7 +77,6 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
PAGE_READ | PAGE_WRITE, retaddr);
DATA_TYPE ret;
atomic_trace_rmw_pre(env, addr, oi);
#if DATA_SIZE == 16
ret = atomic16_cmpxchg(haddr, cmpv, newv);
#else
@ -97,7 +96,6 @@ ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr,
PAGE_READ, retaddr);
DATA_TYPE val;
atomic_trace_ld_pre(env, addr, oi);
val = atomic16_read(haddr);
ATOMIC_MMU_CLEANUP;
atomic_trace_ld_post(env, addr, oi);
@ -110,7 +108,6 @@ void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
PAGE_WRITE, retaddr);
atomic_trace_st_pre(env, addr, oi);
atomic16_set(haddr, val);
ATOMIC_MMU_CLEANUP;
atomic_trace_st_post(env, addr, oi);
@ -124,7 +121,6 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
PAGE_READ | PAGE_WRITE, retaddr);
DATA_TYPE ret;
atomic_trace_rmw_pre(env, addr, oi);
ret = qatomic_xchg__nocheck(haddr, val);
ATOMIC_MMU_CLEANUP;
atomic_trace_rmw_post(env, addr, oi);
@ -138,7 +134,6 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
PAGE_READ | PAGE_WRITE, retaddr); \
DATA_TYPE ret; \
atomic_trace_rmw_pre(env, addr, oi); \
ret = qatomic_##X(haddr, val); \
ATOMIC_MMU_CLEANUP; \
atomic_trace_rmw_post(env, addr, oi); \
@ -171,7 +166,6 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
XDATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
PAGE_READ | PAGE_WRITE, retaddr); \
XDATA_TYPE cmp, old, new, val = xval; \
atomic_trace_rmw_pre(env, addr, oi); \
smp_mb(); \
cmp = qatomic_read__nocheck(haddr); \
do { \
@ -216,7 +210,6 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
PAGE_READ | PAGE_WRITE, retaddr);
DATA_TYPE ret;
atomic_trace_rmw_pre(env, addr, oi);
#if DATA_SIZE == 16
ret = atomic16_cmpxchg(haddr, BSWAP(cmpv), BSWAP(newv));
#else
@ -236,7 +229,6 @@ ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr,
PAGE_READ, retaddr);
DATA_TYPE val;
atomic_trace_ld_pre(env, addr, oi);
val = atomic16_read(haddr);
ATOMIC_MMU_CLEANUP;
atomic_trace_ld_post(env, addr, oi);
@ -249,7 +241,6 @@ void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
PAGE_WRITE, retaddr);
atomic_trace_st_pre(env, addr, oi);
val = BSWAP(val);
atomic16_set(haddr, val);
ATOMIC_MMU_CLEANUP;
@ -264,7 +255,6 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
PAGE_READ | PAGE_WRITE, retaddr);
ABI_TYPE ret;
atomic_trace_rmw_pre(env, addr, oi);
ret = qatomic_xchg__nocheck(haddr, BSWAP(val));
ATOMIC_MMU_CLEANUP;
atomic_trace_rmw_post(env, addr, oi);
@ -278,7 +268,6 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
PAGE_READ | PAGE_WRITE, retaddr); \
DATA_TYPE ret; \
atomic_trace_rmw_pre(env, addr, oi); \
ret = qatomic_##X(haddr, BSWAP(val)); \
ATOMIC_MMU_CLEANUP; \
atomic_trace_rmw_post(env, addr, oi); \
@ -308,7 +297,6 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
XDATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
PAGE_READ | PAGE_WRITE, retaddr); \
XDATA_TYPE ldo, ldn, old, new, val = xval; \
atomic_trace_rmw_pre(env, addr, oi); \
smp_mb(); \
ldn = qatomic_read__nocheck(haddr); \
do { \

View File

@ -660,7 +660,8 @@ 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) | 1;
cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT)
| CF_NOIRQ | 1;
}
#endif
return false;

View File

@ -783,6 +783,15 @@ 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);
}
@ -2140,7 +2149,6 @@ static inline uint64_t cpu_load_helper(CPUArchState *env, abi_ptr addr,
{
uint64_t ret;
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
ret = full_load(env, addr, oi, retaddr);
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
return ret;
@ -2487,7 +2495,6 @@ static inline void cpu_store_helper(CPUArchState *env, target_ulong addr,
uint64_t val, MemOpIdx oi, uintptr_t ra,
FullStoreHelper *full_store)
{
trace_guest_st_before_exec(env_cpu(env), addr, oi);
full_store(env, addr, val, oi, ra);
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
}

View File

@ -854,10 +854,20 @@ static void plugin_gen_inject(const struct qemu_plugin_tb *plugin_tb)
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;
ptb->vaddr = tb->pc;
@ -868,6 +878,9 @@ 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;
}
@ -904,23 +917,19 @@ 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

@ -250,7 +250,6 @@ uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr addr,
uint8_t ret;
validate_memop(oi, MO_UB);
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
ret = ldub_p(haddr);
clear_helper_retaddr();
@ -265,7 +264,6 @@ uint16_t cpu_ldw_be_mmu(CPUArchState *env, abi_ptr addr,
uint16_t ret;
validate_memop(oi, MO_BEUW);
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
ret = lduw_be_p(haddr);
clear_helper_retaddr();
@ -280,7 +278,6 @@ uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr addr,
uint32_t ret;
validate_memop(oi, MO_BEUL);
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
ret = ldl_be_p(haddr);
clear_helper_retaddr();
@ -295,7 +292,6 @@ uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr,
uint64_t ret;
validate_memop(oi, MO_BEUQ);
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
ret = ldq_be_p(haddr);
clear_helper_retaddr();
@ -310,7 +306,6 @@ uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr addr,
uint16_t ret;
validate_memop(oi, MO_LEUW);
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
ret = lduw_le_p(haddr);
clear_helper_retaddr();
@ -325,7 +320,6 @@ uint32_t cpu_ldl_le_mmu(CPUArchState *env, abi_ptr addr,
uint32_t ret;
validate_memop(oi, MO_LEUL);
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
ret = ldl_le_p(haddr);
clear_helper_retaddr();
@ -340,7 +334,6 @@ uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr addr,
uint64_t ret;
validate_memop(oi, MO_LEUQ);
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
ret = ldq_le_p(haddr);
clear_helper_retaddr();
@ -354,7 +347,6 @@ void cpu_stb_mmu(CPUArchState *env, abi_ptr addr, uint8_t val,
void *haddr;
validate_memop(oi, MO_UB);
trace_guest_st_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
stb_p(haddr, val);
clear_helper_retaddr();
@ -367,7 +359,6 @@ void cpu_stw_be_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
void *haddr;
validate_memop(oi, MO_BEUW);
trace_guest_st_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
stw_be_p(haddr, val);
clear_helper_retaddr();
@ -380,7 +371,6 @@ void cpu_stl_be_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
void *haddr;
validate_memop(oi, MO_BEUL);
trace_guest_st_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
stl_be_p(haddr, val);
clear_helper_retaddr();
@ -393,7 +383,6 @@ void cpu_stq_be_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
void *haddr;
validate_memop(oi, MO_BEUQ);
trace_guest_st_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
stq_be_p(haddr, val);
clear_helper_retaddr();
@ -406,7 +395,6 @@ void cpu_stw_le_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
void *haddr;
validate_memop(oi, MO_LEUW);
trace_guest_st_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
stw_le_p(haddr, val);
clear_helper_retaddr();
@ -419,7 +407,6 @@ void cpu_stl_le_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
void *haddr;
validate_memop(oi, MO_LEUL);
trace_guest_st_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
stl_le_p(haddr, val);
clear_helper_retaddr();
@ -432,7 +419,6 @@ void cpu_stq_le_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
void *haddr;
validate_memop(oi, MO_LEUQ);
trace_guest_st_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
stq_le_p(haddr, val);
clear_helper_retaddr();

View File

@ -3341,6 +3341,8 @@ int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
int ret;
Transaction *tran = tran_new();
bdrv_drained_begin(bs);
ret = bdrv_set_backing_noperm(bs, backing_hd, tran, errp);
if (ret < 0) {
goto out;
@ -3350,6 +3352,8 @@ int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
out:
tran_finalize(tran, ret);
bdrv_drained_end(bs);
return ret;
}

View File

@ -190,6 +190,7 @@ static void blk_root_activate(BdrvChild *child, Error **errp)
{
BlockBackend *blk = child->opaque;
Error *local_err = NULL;
uint64_t saved_shared_perm;
if (!blk->disable_perm) {
return;
@ -197,12 +198,22 @@ static void blk_root_activate(BdrvChild *child, Error **errp)
blk->disable_perm = false;
/*
* blk->shared_perm contains the permissions we want to share once
* migration is really completely done. For now, we need to share
* all; but we also need to retain blk->shared_perm, which is
* overwritten by a successful blk_set_perm() call. Save it and
* restore it below.
*/
saved_shared_perm = blk->shared_perm;
blk_set_perm(blk, blk->perm, BLK_PERM_ALL, &local_err);
if (local_err) {
error_propagate(errp, local_err);
blk->disable_perm = true;
return;
}
blk->shared_perm = saved_shared_perm;
if (runstate_check(RUN_STATE_INMIGRATE)) {
/* Activation can happen when migration process is still active, for

View File

@ -625,11 +625,33 @@ static void fuse_fallocate(fuse_req_t req, fuse_ino_t inode, int mode,
return;
}
#ifdef CONFIG_FALLOCATE_PUNCH_HOLE
if (mode & FALLOC_FL_KEEP_SIZE) {
length = MIN(length, blk_len - offset);
}
#endif /* CONFIG_FALLOCATE_PUNCH_HOLE */
if (mode & FALLOC_FL_PUNCH_HOLE) {
if (!mode) {
/* We can only fallocate at the EOF with a truncate */
if (offset < blk_len) {
fuse_reply_err(req, EOPNOTSUPP);
return;
}
if (offset > blk_len) {
/* No preallocation needed here */
ret = fuse_do_truncate(exp, offset, true, PREALLOC_MODE_OFF);
if (ret < 0) {
fuse_reply_err(req, -ret);
return;
}
}
ret = fuse_do_truncate(exp, offset + length, true,
PREALLOC_MODE_FALLOC);
}
#ifdef CONFIG_FALLOCATE_PUNCH_HOLE
else if (mode & FALLOC_FL_PUNCH_HOLE) {
if (!(mode & FALLOC_FL_KEEP_SIZE)) {
fuse_reply_err(req, EINVAL);
return;
@ -643,6 +665,7 @@ static void fuse_fallocate(fuse_req_t req, fuse_ino_t inode, int mode,
length -= size;
} while (ret == 0 && length > 0);
}
#endif /* CONFIG_FALLOCATE_PUNCH_HOLE */
#ifdef CONFIG_FALLOCATE_ZERO_RANGE
else if (mode & FALLOC_FL_ZERO_RANGE) {
if (!(mode & FALLOC_FL_KEEP_SIZE) && offset + length > blk_len) {
@ -665,25 +688,7 @@ static void fuse_fallocate(fuse_req_t req, fuse_ino_t inode, int mode,
} while (ret == 0 && length > 0);
}
#endif /* CONFIG_FALLOCATE_ZERO_RANGE */
else if (!mode) {
/* We can only fallocate at the EOF with a truncate */
if (offset < blk_len) {
fuse_reply_err(req, EOPNOTSUPP);
return;
}
if (offset > blk_len) {
/* No preallocation needed here */
ret = fuse_do_truncate(exp, offset, true, PREALLOC_MODE_OFF);
if (ret < 0) {
fuse_reply_err(req, -ret);
return;
}
}
ret = fuse_do_truncate(exp, offset + length, true,
PREALLOC_MODE_FALLOC);
} else {
else {
ret = -EOPNOTSUPP;
}

View File

@ -172,6 +172,7 @@ vu_blk_discard_write_zeroes(VuBlkExport *vexp, struct iovec *iov,
return VIRTIO_BLK_S_IOERR;
}
/* Called with server refcount increased, must decrease before returning */
static void coroutine_fn vu_blk_virtio_process_req(void *opaque)
{
VuBlkReq *req = opaque;
@ -286,10 +287,12 @@ static void coroutine_fn vu_blk_virtio_process_req(void *opaque)
}
vu_blk_req_complete(req);
vhost_user_server_unref(server);
return;
err:
free(req);
vhost_user_server_unref(server);
}
static void vu_blk_process_vq(VuDev *vu_dev, int idx)
@ -310,6 +313,8 @@ static void vu_blk_process_vq(VuDev *vu_dev, int idx)
Coroutine *co =
qemu_coroutine_create(vu_blk_virtio_process_req, req);
vhost_user_server_ref(server);
qemu_coroutine_enter(co);
}
}

View File

@ -2497,8 +2497,12 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
* non-protocol nodes, and then it is never used. However, filling
* the cache requires an RCU update, so double check here to avoid
* such an update if possible.
*
* Check want_zero, because we only want to update the cache when we
* have accurate information about what is zero and what is data.
*/
if (ret == (BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID) &&
if (want_zero &&
ret == (BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID) &&
QLIST_EMPTY(&bs->children))
{
/*

View File

@ -58,8 +58,7 @@ block_ss.add(when: 'CONFIG_QED', if_true: files(
'qed-table.c',
'qed.c',
))
block_ss.add(when: [libxml2, 'CONFIG_PARALLELS'],
if_true: files('parallels.c', 'parallels-ext.c'))
block_ss.add(when: 'CONFIG_PARALLELS', if_true: files('parallels.c', 'parallels-ext.c'))
block_ss.add(when: 'CONFIG_WIN32', if_true: files('file-win32.c', 'win32-aio.c'))
block_ss.add(when: 'CONFIG_POSIX', if_true: [files('file-posix.c'), coref, iokit])
block_ss.add(when: libiscsi, if_true: files('iscsi-opts.c'))

View File

@ -110,6 +110,10 @@ static void nbd_clear_bdrvstate(BlockDriverState *bs)
yank_unregister_instance(BLOCKDEV_YANK_INSTANCE(bs->node_name));
/* Must not leave timers behind that would access freed data */
assert(!s->reconnect_delay_timer);
assert(!s->open_timer);
object_unref(OBJECT(s->tlscreds));
qapi_free_SocketAddress(s->saddr);
s->saddr = NULL;
@ -381,6 +385,13 @@ static coroutine_fn void nbd_reconnect_attempt(BDRVNBDState *s)
}
nbd_co_do_establish_connection(s->bs, NULL);
/*
* The reconnect attempt is done (maybe successfully, maybe not), so
* we no longer need this timer. Delete it so it will not outlive
* this I/O request (so draining removes all timers).
*/
reconnect_delay_timer_del(s);
}
static coroutine_fn int nbd_receive_replies(BDRVNBDState *s, uint64_t handle)
@ -1878,11 +1889,19 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags,
goto fail;
}
/*
* The connect attempt is done, so we no longer need this timer.
* Delete it, because we do not want it to be around when this node
* is drained or closed.
*/
open_timer_del(s);
nbd_client_connection_enable_retry(s->conn);
return 0;
fail:
open_timer_del(s);
nbd_clear_bdrvstate(bs);
return ret;
}
@ -2036,6 +2055,42 @@ static void nbd_cancel_in_flight(BlockDriverState *bs)
nbd_co_establish_connection_cancel(s->conn);
}
static void nbd_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
BDRVNBDState *s = bs->opaque;
/* The open_timer is used only during nbd_open() */
assert(!s->open_timer);
/*
* The reconnect_delay_timer is scheduled in I/O paths when the
* connection is lost, to cancel the reconnection attempt after a
* given time. Once this attempt is done (successfully or not),
* nbd_reconnect_attempt() ensures the timer is deleted before the
* respective I/O request is resumed.
* Since the AioContext can only be changed when a node is drained,
* the reconnect_delay_timer cannot be active here.
*/
assert(!s->reconnect_delay_timer);
if (s->ioc) {
qio_channel_attach_aio_context(s->ioc, new_context);
}
}
static void nbd_detach_aio_context(BlockDriverState *bs)
{
BDRVNBDState *s = bs->opaque;
assert(!s->open_timer);
assert(!s->reconnect_delay_timer);
if (s->ioc) {
qio_channel_detach_aio_context(s->ioc);
}
}
static BlockDriver bdrv_nbd = {
.format_name = "nbd",
.protocol_name = "nbd",
@ -2059,6 +2114,9 @@ static BlockDriver bdrv_nbd = {
.bdrv_dirname = nbd_dirname,
.strong_runtime_opts = nbd_strong_runtime_opts,
.bdrv_cancel_in_flight = nbd_cancel_in_flight,
.bdrv_attach_aio_context = nbd_attach_aio_context,
.bdrv_detach_aio_context = nbd_detach_aio_context,
};
static BlockDriver bdrv_nbd_tcp = {
@ -2084,6 +2142,9 @@ static BlockDriver bdrv_nbd_tcp = {
.bdrv_dirname = nbd_dirname,
.strong_runtime_opts = nbd_strong_runtime_opts,
.bdrv_cancel_in_flight = nbd_cancel_in_flight,
.bdrv_attach_aio_context = nbd_attach_aio_context,
.bdrv_detach_aio_context = nbd_detach_aio_context,
};
static BlockDriver bdrv_nbd_unix = {
@ -2109,6 +2170,9 @@ static BlockDriver bdrv_nbd_unix = {
.bdrv_dirname = nbd_dirname,
.strong_runtime_opts = nbd_strong_runtime_opts,
.bdrv_cancel_in_flight = nbd_cancel_in_flight,
.bdrv_attach_aio_context = nbd_attach_aio_context,
.bdrv_detach_aio_context = nbd_detach_aio_context,
};
static void bdrv_nbd_init(void)

View File

@ -5279,6 +5279,38 @@ static int qcow2_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
return bs->drv->bdrv_co_preadv_part(bs, offset, qiov->size, qiov, 0, 0);
}
static int qcow2_has_compressed_clusters(BlockDriverState *bs)
{
int64_t offset = 0;
int64_t bytes = bdrv_getlength(bs);
if (bytes < 0) {
return bytes;
}
while (bytes != 0) {
int ret;
QCow2SubclusterType type;
unsigned int cur_bytes = MIN(INT_MAX, bytes);
uint64_t host_offset;
ret = qcow2_get_host_offset(bs, offset, &cur_bytes, &host_offset,
&type);
if (ret < 0) {
return ret;
}
if (type == QCOW2_SUBCLUSTER_COMPRESSED) {
return 1;
}
offset += cur_bytes;
bytes -= cur_bytes;
}
return 0;
}
/*
* Downgrades an image's version. To achieve this, any incompatible features
* have to be removed.
@ -5336,9 +5368,10 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
* the first place; if that happens nonetheless, returning -ENOTSUP is the
* best thing to do anyway */
if (s->incompatible_features) {
if (s->incompatible_features & ~QCOW2_INCOMPAT_COMPRESSION) {
error_setg(errp, "Cannot downgrade an image with incompatible features "
"%#" PRIx64 " set", s->incompatible_features);
"0x%" PRIx64 " set",
s->incompatible_features & ~QCOW2_INCOMPAT_COMPRESSION);
return -ENOTSUP;
}
@ -5356,6 +5389,27 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
return ret;
}
if (s->incompatible_features & QCOW2_INCOMPAT_COMPRESSION) {
ret = qcow2_has_compressed_clusters(bs);
if (ret < 0) {
error_setg(errp, "Failed to check block status");
return -EINVAL;
}
if (ret) {
error_setg(errp, "Cannot downgrade an image with zstd compression "
"type and existing compressed clusters");
return -ENOTSUP;
}
/*
* No compressed clusters for now, so just chose default zlib
* compression.
*/
s->incompatible_features &= ~QCOW2_INCOMPAT_COMPRESSION;
s->compression_type = QCOW2_COMPRESSION_TYPE_ZLIB;
}
assert(s->incompatible_features == 0);
s->qcow_version = target_version;
ret = qcow2_update_header(bs);
if (ret < 0) {

View File

@ -1279,11 +1279,11 @@ static int qemu_rbd_diff_iterate_cb(uint64_t offs, size_t len,
RBDDiffIterateReq *req = opaque;
assert(req->offs + req->bytes <= offs);
/*
* we do not diff against a snapshot so we should never receive a callback
* for a hole.
*/
assert(exists);
/* treat a hole like an unallocated area and bail out */
if (!exists) {
return 0;
}
if (!req->exists && offs > req->offs) {
/*
@ -1320,6 +1320,7 @@ static int coroutine_fn qemu_rbd_co_block_status(BlockDriverState *bs,
int status, r;
RBDDiffIterateReq req = { .offs = offset };
uint64_t features, flags;
uint64_t head = 0;
assert(offset + bytes <= s->image_size);
@ -1347,7 +1348,43 @@ static int coroutine_fn qemu_rbd_co_block_status(BlockDriverState *bs,
return status;
}
r = rbd_diff_iterate2(s->image, NULL, offset, bytes, true, true,
#if LIBRBD_VERSION_CODE < LIBRBD_VERSION(1, 17, 0)
/*
* librbd had a bug until early 2022 that affected all versions of ceph that
* supported fast-diff. This bug results in reporting of incorrect offsets
* if the offset parameter to rbd_diff_iterate2 is not object aligned.
* Work around this bug by rounding down the offset to object boundaries.
* This is OK because we call rbd_diff_iterate2 with whole_object = true.
* However, this workaround only works for non cloned images with default
* striping.
*
* See: https://tracker.ceph.com/issues/53784
*/
/* check if RBD image has non-default striping enabled */
if (features & RBD_FEATURE_STRIPINGV2) {
return status;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
/*
* check if RBD image is a clone (= has a parent).
*
* rbd_get_parent_info is deprecated from Nautilus onwards, but the
* replacement rbd_get_parent is not present in Luminous and Mimic.
*/
if (rbd_get_parent_info(s->image, NULL, 0, NULL, 0, NULL, 0) != -ENOENT) {
return status;
}
#pragma GCC diagnostic pop
head = req.offs & (s->object_size - 1);
req.offs -= head;
bytes += head;
#endif
r = rbd_diff_iterate2(s->image, NULL, req.offs, bytes, true, true,
qemu_rbd_diff_iterate_cb, &req);
if (r < 0 && r != QEMU_RBD_EXIT_DIFF_ITERATE2) {
return status;
@ -1366,7 +1403,8 @@ static int coroutine_fn qemu_rbd_co_block_status(BlockDriverState *bs,
status = BDRV_BLOCK_ZERO | BDRV_BLOCK_OFFSET_VALID;
}
*pnum = req.bytes;
assert(req.bytes > head);
*pnum = req.bytes - head;
return status;
}

View File

@ -3530,6 +3530,7 @@ void qmp_blockdev_reopen(BlockdevOptionsList *reopen_list, Error **errp)
{
BlockReopenQueue *queue = NULL;
GSList *drained = NULL;
GSList *p;
/* Add each one of the BDS that we want to reopen to the queue */
for (; reopen_list != NULL; reopen_list = reopen_list->next) {
@ -3579,7 +3580,15 @@ void qmp_blockdev_reopen(BlockdevOptionsList *reopen_list, Error **errp)
fail:
bdrv_reopen_queue_free(queue);
g_slist_free_full(drained, (GDestroyNotify) bdrv_subtree_drained_end);
for (p = drained; p; p = p->next) {
BlockDriverState *bs = p->data;
AioContext *ctx = bdrv_get_aio_context(bs);
aio_context_acquire(ctx);
bdrv_subtree_drained_end(bs);
aio_context_release(ctx);
}
g_slist_free(drained);
}
void qmp_blockdev_del(const char *node_name, Error **errp)

View File

@ -59,19 +59,31 @@ abi_long set_sigtramp_args(CPUARMState *env, int sig,
return 0;
}
static abi_long get_vfpcontext(CPUARMState *env, abi_ulong frame_addr,
struct target_sigframe *frame)
{
/* see sendsig and get_vfpcontext in sys/arm/arm/exec_machdep.c */
target_mcontext_vfp_t *vfp = &frame->sf_vfp;
target_mcontext_t *mcp = &frame->sf_uc.uc_mcontext;
/* Assumes that mcp and vfp are locked */
for (int i = 0; i < 32; i++) {
vfp->mcv_reg[i] = tswap64(*aa32_vfp_dreg(env, i));
}
vfp->mcv_fpscr = tswap32(vfp_get_fpscr(env));
mcp->mc_vfp_size = tswap32(sizeof(*vfp));
mcp->mc_vfp_ptr = tswap32(frame_addr + ((uintptr_t)vfp - (uintptr_t)frame));
return 0;
}
/*
* Compare to arm/arm/machdep.c get_mcontext()
* Compare to arm/arm/exec_machdep.c get_mcontext()
* Assumes that the memory is locked if mcp points to user memory.
*/
abi_long get_mcontext(CPUARMState *env, target_mcontext_t *mcp, int flags)
{
int err = 0;
uint32_t *gr = mcp->__gregs;
if (mcp->mc_vfp_size != 0 && mcp->mc_vfp_size != sizeof(target_mcontext_vfp_t)) {
return -TARGET_EINVAL;
}
gr[TARGET_REG_CPSR] = tswap32(cpsr_read(env));
if (flags & TARGET_MC_GET_CLEAR_RET) {
gr[TARGET_REG_R0] = 0;
@ -97,17 +109,30 @@ abi_long get_mcontext(CPUARMState *env, target_mcontext_t *mcp, int flags)
gr[TARGET_REG_LR] = tswap32(env->regs[14]);
gr[TARGET_REG_PC] = tswap32(env->regs[15]);
if (mcp->mc_vfp_size != 0 && mcp->mc_vfp_ptr != 0) {
/* see get_vfpcontext in sys/arm/arm/exec_machdep.c */
target_mcontext_vfp_t *vfp;
vfp = lock_user(VERIFY_WRITE, mcp->mc_vfp_ptr, sizeof(*vfp), 0);
for (int i = 0; i < 32; i++) {
vfp->mcv_reg[i] = tswap64(*aa32_vfp_dreg(env, i));
/*
* FreeBSD's get_mcontext doesn't save VFP info, but sets the pointer and
* size to zero. Applications that need the VFP state use
* sysarch(ARM_GET_VFPSTATE) and are expected to adjust mcontext after that.
*/
mcp->mc_vfp_size = 0;
mcp->mc_vfp_ptr = 0;
memset(&mcp->mc_spare, 0, sizeof(mcp->mc_spare));
return 0;
}
vfp->mcv_fpscr = tswap32(vfp_get_fpscr(env));
unlock_user(vfp, mcp->mc_vfp_ptr, sizeof(*vfp));
}
return err;
/*
* Compare to arm/arm/exec_machdep.c sendsig()
* Assumes that the memory is locked if frame points to user memory.
*/
abi_long setup_sigframe_arch(CPUARMState *env, abi_ulong frame_addr,
struct target_sigframe *frame, int flags)
{
target_mcontext_t *mcp = &frame->sf_uc.uc_mcontext;
get_mcontext(env, mcp, flags);
get_vfpcontext(env, frame_addr, frame);
return 0;
}
/* Compare to arm/arm/exec_machdep.c set_mcontext() */

View File

@ -21,6 +21,7 @@
#define _TARGET_ARCH_CPU_H_
#include "target_arch.h"
#include "signal-common.h"
#define TARGET_DEFAULT_CPU_MODEL "any"
@ -38,8 +39,7 @@ static inline void target_cpu_init(CPUARMState *env,
static inline void target_cpu_loop(CPUARMState *env)
{
int trapnr;
target_siginfo_t info;
int trapnr, si_signo, si_code;
unsigned int n;
CPUState *cs = env_cpu(env);
@ -50,33 +50,22 @@ static inline void target_cpu_loop(CPUARMState *env)
process_queued_cpu_work(cs);
switch (trapnr) {
case EXCP_UDEF:
{
/* See arm/arm/undefined.c undefinedinstruction(); */
info.si_addr = env->regs[15];
/* illegal instruction */
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPC;
queue_signal(env, info.si_signo, &info);
/* TODO: What about instruction emulation? */
}
case EXCP_NOCP:
case EXCP_INVSTATE:
/*
* See arm/arm/undefined.c undefinedinstruction();
*
* A number of details aren't emulated (they likely don't matter):
* o Misaligned PC generates ILL_ILLADR (these can't come from qemu)
* o Thumb-2 instructions generate ILLADR
* o Both modes implement coprocessor instructions, which we don't
* do here. FreeBSD just implements them for the VFP coprocessor
* and special kernel breakpoints, trace points, dtrace, etc.
*/
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->regs[15]);
break;
case EXCP_SWI:
case EXCP_BKPT:
{
/*
* system call
* See arm/arm/trap.c cpu_fetch_syscall_args()
*/
if (trapnr == EXCP_BKPT) {
if (env->thumb) {
env->regs[15] += 2;
} else {
env->regs[15] += 4;
}
}
n = env->regs[7];
if (bsd_type == target_freebsd) {
int ret;
@ -84,7 +73,7 @@ static inline void target_cpu_loop(CPUARMState *env)
int32_t syscall_nr = n;
int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
/* See arm/arm/trap.c cpu_fetch_syscall_args() */
/* See arm/arm/syscall.c cpu_fetch_syscall_args() */
if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
syscall_nr = env->regs[0];
arg1 = env->regs[1];
@ -160,32 +149,52 @@ static inline void target_cpu_loop(CPUARMState *env)
/* just indicate that signals should be handled asap */
break;
case EXCP_PREFETCH_ABORT:
/* See arm/arm/trap.c prefetch_abort_handler() */
case EXCP_DATA_ABORT:
/* See arm/arm/trap.c data_abort_handler() */
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
/* XXX: check env->error_code */
info.si_code = 0;
info.si_addr = env->exception.vaddress;
queue_signal(env, info.si_signo, &info);
/*
* See arm/arm/trap-v6.c prefetch_abort_handler() and
* data_abort_handler()
*
* However, FreeBSD maps these to a generic value and then uses that
* to maybe fault in pages in vm/vm_fault.c:vm_fault_trap(). I
* believe that the indirection maps the same as Linux, but haven't
* chased down every single possible indirection.
*/
/* For user-only we don't set TTBCR_EAE, so look at the FSR. */
switch (env->exception.fsr & 0x1f) {
case 0x1: /* Alignment */
si_signo = TARGET_SIGBUS;
si_code = TARGET_BUS_ADRALN;
break;
case 0x3: /* Access flag fault, level 1 */
case 0x6: /* Access flag fault, level 2 */
case 0x9: /* Domain fault, level 1 */
case 0xb: /* Domain fault, level 2 */
case 0xd: /* Permission fault, level 1 */
case 0xf: /* Permission fault, level 2 */
si_signo = TARGET_SIGSEGV;
si_code = TARGET_SEGV_ACCERR;
break;
case 0x5: /* Translation fault, level 1 */
case 0x7: /* Translation fault, level 2 */
si_signo = TARGET_SIGSEGV;
si_code = TARGET_SEGV_MAPERR;
break;
default:
g_assert_not_reached();
}
force_sig_fault(si_signo, si_code, env->exception.vaddress);
break;
case EXCP_DEBUG:
{
info.si_signo = TARGET_SIGTRAP;
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
info.si_addr = env->exception.vaddress;
queue_signal(env, info.si_signo, &info);
}
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
case EXCP_BKPT:
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->regs[15]);
break;
case EXCP_YIELD:
/* nothing to do here for user-mode, just resume guest code */
break;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
break;
default:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
@ -204,7 +213,7 @@ static inline void target_cpu_clone_regs(CPUARMState *env, target_ulong newsp)
env->regs[0] = 0;
}
static inline void target_cpu_reset(CPUArchState *cpu)
static inline void target_cpu_reset(CPUArchState *env)
{
}

View File

@ -71,11 +71,24 @@ typedef struct target_siginfo {
int32_t _mqd;
} _mesgp;
/* SIGPOLL */
/* SIGPOLL -- Not really genreated in FreeBSD ??? */
struct {
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
} _poll;
struct {
int _mqd;
} _mesgq;
struct {
/*
* Syscall number for signals delivered as a result of system calls
* denied by Capsicum.
*/
int _syscall;
} _capsicum;
/* Spare for future growth */
struct {
abi_long __spare1__;
int32_t __spare2_[7];

View File

@ -4,6 +4,9 @@
#include "target_os_siginfo.h"
#include "target_arch_signal.h"
abi_long setup_sigframe_arch(CPUArchState *env, abi_ulong frame_addr,
struct target_sigframe *frame, int flags);
/* Compare to sys/signal.h */
#define TARGET_SIGHUP 1 /* hangup */
#define TARGET_SIGINT 2 /* interrupt */

View File

@ -36,9 +36,9 @@ abi_long set_sigtramp_args(CPUArchState *env, int sig,
struct target_sigframe *frame,
abi_ulong frame_addr,
struct target_sigaction *ka);
abi_long get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags);
abi_long set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int srflag);
abi_long get_ucontext_sigreturn(CPUArchState *regs, abi_ulong target_sf,
abi_long get_mcontext(CPUArchState *env, target_mcontext_t *mcp, int flags);
abi_long set_mcontext(CPUArchState *env, target_mcontext_t *mcp, int srflag);
abi_long get_ucontext_sigreturn(CPUArchState *env, abi_ulong target_sf,
abi_ulong *target_uc);
#endif /* TARGET_OS_UCONTEXT_H */

View File

@ -0,0 +1,35 @@
/*
* host-signal.h: signal info dependent on the host architecture
*
* Copyright (c) 2021 Warner Losh
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef ARM_HOST_SIGNAL_H
#define ARM_HOST_SIGNAL_H
#include <sys/ucontext.h>
static inline uintptr_t host_signal_pc(ucontext_t *uc)
{
return uc->uc_mcontext.__gregs[_REG_PC];
}
static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc)
{
uc->uc_mcontext.__gregs[_REG_PC] = pc;
}
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
{
/*
* In the FSR, bit 11 is WnR. FreeBSD returns this as part of the
* si_info.si_trapno.
*/
uint32_t fsr = info->si_trapno;
return extract32(fsr, 11, 1);
}
#endif

View File

@ -0,0 +1,37 @@
/*
* host-signal.h: signal info dependent on the host architecture
*
* Copyright (c) 2021 Warner Losh
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef I386_HOST_SIGNAL_H
#define I386_HOST_SIGNAL_H
#include <sys/ucontext.h>
#include <machine/trap.h>
#include <vm/pmap.h>
#include <machine/pmap.h>
static inline uintptr_t host_signal_pc(ucontext_t *uc)
{
return uc->uc_mcontext.mc_eip;
}
static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc)
{
uc->uc_mcontext.mc_eip = pc;
}
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
{
/*
* Look in sys/i386/i386/trap.c. NOTE: mc_err == tr_err due to type punning
* between a trapframe and mcontext on FreeBSD/i386.
*/
return uc->uc_mcontext.mc_trapno == T_PAGEFLT &&
uc->uc_mcontext.mc_err & PGEX_W;
}
#endif

View File

@ -0,0 +1,37 @@
/*
* host-signal.h: signal info dependent on the host architecture
*
* Copyright (c) 2021 Warner Losh
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef X86_64_HOST_SIGNAL_H
#define X86_64_HOST_SIGNAL_H
#include <sys/ucontext.h>
#include <machine/trap.h>
#include <vm/pmap.h>
#include <machine/pmap.h>
static inline uintptr_t host_signal_pc(ucontext_t *uc)
{
return uc->uc_mcontext.mc_rip;
}
static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc)
{
uc->uc_mcontext.mc_rip = pc;
}
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
{
/*
* Look in sys/amd64/amd64/trap.c. NOTE: mc_err == tr_err due to type
* punning between a trapframe and mcontext on FreeBSD/amd64.
*/
return uc->uc_mcontext.mc_trapno == T_PAGEFLT &&
uc->uc_mcontext.mc_err & PGEX_W;
}
#endif

View File

@ -32,6 +32,19 @@ abi_long set_sigtramp_args(CPUX86State *env, int sig,
return 0;
}
/*
* Compare to i386/i386/exec_machdep.c sendsig()
* Assumes that the memory is locked if frame points to user memory.
*/
abi_long setup_sigframe_arch(CPUX86State *env, abi_ulong frame_addr,
struct target_sigframe *frame, int flags)
{
target_mcontext_t *mcp = &frame->sf_uc.uc_mcontext;
get_mcontext(env, mcp, flags);
return 0;
}
/* Compare to i386/i386/machdep.c get_mcontext() */
abi_long get_mcontext(CPUX86State *regs, target_mcontext_t *mcp, int flags)
{

View File

@ -20,6 +20,7 @@
#define _TARGET_ARCH_CPU_H_
#include "target_arch.h"
#include "signal-common.h"
#define TARGET_DEFAULT_CPU_MODEL "qemu32"
@ -199,9 +200,9 @@ static inline void target_cpu_clone_regs(CPUX86State *env, target_ulong newsp)
env->regs[R_EAX] = 0;
}
static inline void target_cpu_reset(CPUArchState *cpu)
static inline void target_cpu_reset(CPUArchState *env)
{
cpu_reset(env_cpu(cpu));
cpu_reset(env_cpu(env));
}
#endif /* ! _TARGET_ARCH_CPU_H_ */

View File

@ -215,15 +215,13 @@ void qemu_cpu_kick(CPUState *cpu)
}
/* Assumes contents are already zeroed. */
void init_task_state(TaskState *ts)
static void init_task_state(TaskState *ts)
{
int i;
ts->first_free = ts->sigqueue_table;
for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1];
}
ts->sigqueue_table[i].next = NULL;
ts->sigaltstack_used = (struct target_sigaltstack) {
.ss_sp = 0,
.ss_size = 0,
.ss_flags = TARGET_SS_DISABLE,
};
}
void gemu_log(const char *fmt, ...)

View File

@ -70,17 +70,9 @@ struct image_info {
uint32_t elf_flags;
};
#define MAX_SIGQUEUE_SIZE 1024
struct qemu_sigqueue {
struct qemu_sigqueue *next;
target_siginfo_t info;
};
struct emulated_sigtable {
int pending; /* true if signal is pending */
struct qemu_sigqueue *first;
struct qemu_sigqueue info; /* Put first signal info here */
target_siginfo_t info;
};
/*
@ -93,15 +85,39 @@ typedef struct TaskState {
struct bsd_binprm *bprm;
struct image_info *info;
struct emulated_sigtable sync_signal;
/*
* TODO: Since we block all signals while returning to the main CPU
* loop, this needn't be an array
*/
struct emulated_sigtable sigtab[TARGET_NSIG];
struct qemu_sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
struct qemu_sigqueue *first_free; /* first free siginfo queue entry */
int signal_pending; /* non zero if a signal may be pending */
/*
* Nonzero if process_pending_signals() needs to do something (either
* handle a pending signal or unblock signals).
* This flag is written from a signal handler so should be accessed via
* the qatomic_read() and qatomic_set() functions. (It is not accessed
* from multiple threads.)
*/
int signal_pending;
/* True if we're leaving a sigsuspend and sigsuspend_mask is valid. */
bool in_sigsuspend;
/*
* This thread's signal mask, as requested by the guest program.
* The actual signal mask of this thread may differ:
* + we don't let SIGSEGV and SIGBUS be blocked while running guest code
* + sometimes we block all signals to avoid races
*/
sigset_t signal_mask;
/*
* The signal mask imposed by a guest sigsuspend syscall, if we are
* currently in the middle of such a syscall
*/
sigset_t sigsuspend_mask;
uint8_t stack[];
/* This thread's sigaltstack, if it has one */
struct target_sigaltstack sigaltstack_used;
} __attribute__((aligned(16))) TaskState;
void init_task_state(TaskState *ts);
void stop_all_tasks(void);
extern const char *qemu_uname_release;
@ -201,16 +217,18 @@ print_openbsd_syscall(int num,
abi_long arg1, abi_long arg2, abi_long arg3,
abi_long arg4, abi_long arg5, abi_long arg6);
void print_openbsd_syscall_ret(int num, abi_long ret);
/**
* print_taken_signal:
* @target_signum: target signal being taken
* @tinfo: target_siginfo_t which will be passed to the guest for the signal
*
* Print strace output indicating that this signal is being taken by the guest,
* in a format similar to:
* --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
*/
void print_taken_signal(int target_signum, const target_siginfo_t *tinfo);
extern int do_strace;
/* signal.c */
void process_pending_signals(CPUArchState *cpu_env);
void signal_init(void);
long do_sigreturn(CPUArchState *env);
long do_rt_sigreturn(CPUArchState *env);
void queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
/* mmap.c */
int target_mprotect(abi_ulong start, abi_ulong len, int prot);
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
@ -451,4 +469,6 @@ static inline void *lock_user_string(abi_ulong guest_addr)
#include <pthread.h>
#include "user/safe-syscall.h"
#endif /* QEMU_H */

75
bsd-user/signal-common.h Normal file
View File

@ -0,0 +1,75 @@
/*
* Emulation of BSD signals
*
* Copyright (c) 2013 Stacey Son
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef SIGNAL_COMMON_H
#define SIGNAL_COMMON_H
/**
* block_signals: block all signals while handling this guest syscall
*
* Block all signals, and arrange that the signal mask is returned to
* its correct value for the guest before we resume execution of guest code.
* If this function returns non-zero, then the caller should immediately
* return -TARGET_ERESTARTSYS to the main loop, which will take the pending
* signal and restart execution of the syscall.
* If block_signals() returns zero, then the caller can continue with
* emulation of the system call knowing that no signals can be taken
* (and therefore that no race conditions will result).
* This should only be called once, because if it is called a second time
* it will always return non-zero. (Think of it like a mutex that can't
* be recursively locked.)
* Signals will be unblocked again by process_pending_signals().
*
* Return value: non-zero if there was a pending signal, zero if not.
*/
int block_signals(void); /* Returns non zero if signal pending */
long do_rt_sigreturn(CPUArchState *env);
int do_sigaction(int sig, const struct target_sigaction *act,
struct target_sigaction *oact);
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
long do_sigreturn(CPUArchState *env, abi_ulong addr);
void force_sig_fault(int sig, int code, abi_ulong addr);
int host_to_target_signal(int sig);
void host_to_target_sigset(target_sigset_t *d, const sigset_t *s);
void process_pending_signals(CPUArchState *env);
void queue_signal(CPUArchState *env, int sig, int si_type,
target_siginfo_t *info);
void signal_init(void);
int target_to_host_signal(int sig);
void target_to_host_sigset(sigset_t *d, const target_sigset_t *s);
/*
* Within QEMU the top 8 bits of si_code indicate which of the parts of the
* union in target_siginfo is valid. This only applies between
* host_to_target_siginfo_noswap() and tswap_siginfo(); it does not appear
* either within host siginfo_t or in target_siginfo structures which we get
* from the guest userspace program. Linux kenrels use this internally, but BSD
* kernels don't do this, but its a useful abstraction.
*
* The linux-user version of this uses the top 16 bits, but FreeBSD's SI_USER
* and other signal indepenent SI_ codes have bit 16 set, so we only use the top
* byte instead.
*
* For FreeBSD, we have si_pid, si_uid, si_status, and si_addr always. Linux and
* {Open,Net}BSD have a different approach (where their reason field is larger,
* but whose siginfo has fewer fields always).
*
* QEMU_SI_CAPSICUM is currently only FreeBSD 14 current only, so only define
* it where _capsicum is available.
*/
#define QEMU_SI_NOINFO 0 /* nothing other than si_signo valid */
#define QEMU_SI_FAULT 1 /* _fault is valid in _reason */
#define QEMU_SI_TIMER 2 /* _timer is valid in _reason */
#define QEMU_SI_MESGQ 3 /* _mesgq is valid in _reason */
#define QEMU_SI_POLL 4 /* _poll is valid in _reason */
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1400026
#define QEMU_SI_CAPSICUM 5 /* _capsicum is valid in _reason */
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,24 @@ int do_strace;
/*
* Utility functions
*/
static const char *
get_comma(int last)
{
return (last) ? "" : ",";
}
/*
* Prints out raw parameter using given format. Caller needs
* to do byte swapping if needed.
*/
static void
print_raw_param(const char *fmt, abi_long param, int last)
{
char format[64];
(void)snprintf(format, sizeof(format), "%s%s", fmt, get_comma(last));
gemu_log(format, param);
}
static void print_sysctl(const struct syscallname *name, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5,
@ -239,3 +257,82 @@ void print_openbsd_syscall_ret(int num, abi_long ret)
print_syscall_ret(num, ret, openbsd_scnames, ARRAY_SIZE(openbsd_scnames));
}
static void
print_signal(abi_ulong arg, int last)
{
const char *signal_name = NULL;
switch (arg) {
case TARGET_SIGHUP:
signal_name = "SIGHUP";
break;
case TARGET_SIGINT:
signal_name = "SIGINT";
break;
case TARGET_SIGQUIT:
signal_name = "SIGQUIT";
break;
case TARGET_SIGILL:
signal_name = "SIGILL";
break;
case TARGET_SIGABRT:
signal_name = "SIGABRT";
break;
case TARGET_SIGFPE:
signal_name = "SIGFPE";
break;
case TARGET_SIGKILL:
signal_name = "SIGKILL";
break;
case TARGET_SIGSEGV:
signal_name = "SIGSEGV";
break;
case TARGET_SIGPIPE:
signal_name = "SIGPIPE";
break;
case TARGET_SIGALRM:
signal_name = "SIGALRM";
break;
case TARGET_SIGTERM:
signal_name = "SIGTERM";
break;
case TARGET_SIGUSR1:
signal_name = "SIGUSR1";
break;
case TARGET_SIGUSR2:
signal_name = "SIGUSR2";
break;
case TARGET_SIGCHLD:
signal_name = "SIGCHLD";
break;
case TARGET_SIGCONT:
signal_name = "SIGCONT";
break;
case TARGET_SIGSTOP:
signal_name = "SIGSTOP";
break;
case TARGET_SIGTTIN:
signal_name = "SIGTTIN";
break;
case TARGET_SIGTTOU:
signal_name = "SIGTTOU";
break;
}
if (signal_name == NULL) {
print_raw_param("%ld", arg, last);
return;
}
gemu_log("%s%s", signal_name, get_comma(last));
}
void print_taken_signal(int target_signum, const target_siginfo_t *tinfo)
{
/*
* Print the strace output for a signal being taken:
* --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
*/
gemu_log("%d ", getpid());
gemu_log("--- ");
print_signal(target_signum, 1);
gemu_log(" ---\n");
}

View File

@ -21,6 +21,7 @@
#define _SYSCALL_DEFS_H_
#include <sys/syscall.h>
#include <sys/resource.h>
#include "errno_defs.h"

11
bsd-user/trace-events Normal file
View File

@ -0,0 +1,11 @@
# See docs/tracing.txt for syntax documentation.
# bsd-user/signal.c
user_setup_frame(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64
user_setup_rt_frame(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64
user_do_rt_sigreturn(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64
user_do_sigreturn(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64
user_dump_core_and_abort(void *env, int target_sig, int host_sig) "env=%p signal %d (host %d)"
user_handle_signal(void *env, int target_sig) "env=%p signal %d"
user_host_signal(void *env, int host_sig, int target_sig) "env=%p signal %d (target %d("
user_queue_signal(void *env, int target_sig) "env=%p signal %d"

1
bsd-user/trace.h Normal file
View File

@ -0,0 +1 @@
#include "trace/trace-bsd_user.h"

View File

@ -30,6 +30,19 @@ abi_long set_sigtramp_args(CPUX86State *regs,
return 0;
}
/*
* Compare to amd64/amd64/exec_machdep.c sendsig()
* Assumes that the memory is locked if frame points to user memory.
*/
abi_long setup_sigframe_arch(CPUX86State *env, abi_ulong frame_addr,
struct target_sigframe *frame, int flags)
{
target_mcontext_t *mcp = &frame->sf_uc.uc_mcontext;
get_mcontext(env, mcp, flags);
return 0;
}
/* Compare to amd64/amd64/machdep.c get_mcontext() */
abi_long get_mcontext(CPUX86State *regs,
target_mcontext_t *mcp, int flags)

View File

@ -20,6 +20,7 @@
#define _TARGET_ARCH_CPU_H_
#include "target_arch.h"
#include "signal-common.h"
#define TARGET_DEFAULT_CPU_MODEL "qemu64"
@ -237,9 +238,9 @@ static inline void target_cpu_clone_regs(CPUX86State *env, target_ulong newsp)
env->regs[R_EAX] = 0;
}
static inline void target_cpu_reset(CPUArchState *cpu)
static inline void target_cpu_reset(CPUArchState *env)
{
cpu_reset(env_cpu(cpu));
cpu_reset(env_cpu(env));
}
#endif /* ! _TARGET_ARCH_CPU_H_ */

View File

@ -24,7 +24,8 @@
.type safe_syscall_end, @function
#define STACK_BIAS 2047
#define PARAM(N) STACK_BIAS + N*8
#define WINDOW_SIZE 16 * 8
#define PARAM(N) STACK_BIAS + WINDOW_SIZE + N * 8
/*
* This is the entry point for making a system call. The calling
@ -74,7 +75,7 @@ safe_syscall_end:
/* code path for having successfully executed the syscall */
bcs,pn %xcc, 1f
nop
ret
retl
nop
/* code path when we didn't execute the syscall */

View File

@ -1,8 +0,0 @@
TARGET_ARCH=ppc64
TARGET_ABI32=y
TARGET_BASE_ARCH=ppc
TARGET_ABI_DIR=ppc
TARGET_SYSTBL_ABI=common,nospu,32
TARGET_SYSTBL=syscall.tbl
TARGET_WORDS_BIGENDIAN=y
TARGET_XML_FILES= gdb-xml/power64-core.xml gdb-xml/power-fpu.xml gdb-xml/power-altivec.xml gdb-xml/power-spe.xml gdb-xml/power-vsx.xml

35
configure vendored
View File

@ -402,7 +402,7 @@ for opt do
;;
--cross-cc-*[!a-zA-Z0-9_-]*=*) error_exit "Passed bad --cross-cc-FOO option"
;;
--cross-cc-cflags-*) cc_arch=${opt#--cross-cc-flags-}; cc_arch=${cc_arch%%=*}
--cross-cc-cflags-*) cc_arch=${opt#--cross-cc-cflags-}; cc_arch=${cc_arch%%=*}
eval "cross_cc_cflags_${cc_arch}=\$optarg"
cross_cc_vars="$cross_cc_vars cross_cc_cflags_${cc_arch}"
;;
@ -1264,8 +1264,6 @@ if eval test -z "\${cross_cc_$cpu}"; then
fi
default_target_list=""
deprecated_targets_list=ppc64abi32-linux-user
deprecated_features=""
mak_wilds=""
if [ "$linux_user" != no ]; then
@ -1293,16 +1291,6 @@ if [ "$bsd_user" = "yes" ]; then
mak_wilds="${mak_wilds} $source_path/configs/targets/*-bsd-user.mak"
fi
# If the user doesn't explicitly specify a deprecated target we will
# skip it.
if test -z "$target_list"; then
if test -z "$target_list_exclude"; then
target_list_exclude="$deprecated_targets_list"
else
target_list_exclude="$target_list_exclude,$deprecated_targets_list"
fi
fi
for config in $mak_wilds; do
target="$(basename "$config" .mak)"
if echo "$target_list_exclude" | grep -vq "$target"; then
@ -1321,11 +1309,9 @@ Standard options:
--prefix=PREFIX install in PREFIX [$prefix]
--interp-prefix=PREFIX where to find shared libraries, etc.
use %M for cpu name [$interp_prefix]
--target-list=LIST set target list (default: build all non-deprecated)
--target-list=LIST set target list (default: build all)
$(echo Available targets: $default_target_list | \
fold -s -w 53 | sed -e 's/^/ /')
$(echo Deprecated targets: $deprecated_targets_list | \
fold -s -w 53 | sed -e 's/^/ /')
--target-list-exclude=LIST exclude a set of targets from the default target-list
Advanced options (experts only):
@ -1340,7 +1326,7 @@ Advanced options (experts only):
--extra-cxxflags=CXXFLAGS append extra C++ compiler flags CXXFLAGS
--extra-ldflags=LDFLAGS append extra linker flags LDFLAGS
--cross-cc-ARCH=CC use compiler when building ARCH guest test cases
--cross-cc-flags-ARCH= use compiler flags when building ARCH guest tests
--cross-cc-cflags-ARCH= use compiler flags when building ARCH guest tests
--make=MAKE use specified make [$make]
--python=PYTHON use specified python [$python]
--sphinx-build=SPHINX use specified sphinx-build [$sphinx_build]
@ -1809,13 +1795,6 @@ else
done
fi
for target in $target_list; do
# if a deprecated target is enabled we note it here
if echo "$deprecated_targets_list" | grep -q "$target"; then
add_to deprecated_features $target
fi
done
# see if system emulation was really requested
case " $target_list " in
*"-softmmu "*) softmmu=yes
@ -2780,7 +2759,7 @@ cat > $TMPC << EOF
#include <cpuid.h>
int main(void) {
unsigned a, b, c, d;
int max = __get_cpuid_max(0, 0);
unsigned max = __get_cpuid_max(0, 0);
if (max >= 1) {
__cpuid(1, a, b, c, d);
@ -3849,12 +3828,6 @@ else
fi
fi
if test -n "${deprecated_features}"; then
echo "Warning, deprecated features enabled."
echo "Please see docs/about/deprecated.rst"
echo " features: ${deprecated_features}"
fi
# Save the configure command line for later reuse.
cat <<EOD >config.status
#!/bin/sh

View File

@ -20,6 +20,7 @@ NAMES += howvec
NAMES += lockstep
NAMES += hwprofile
NAMES += cache
NAMES += drcov
SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES)))

163
contrib/plugins/drcov.c Normal file
View File

@ -0,0 +1,163 @@
/*
* Copyright (C) 2021, Ivanov Arkady <arkadiy.ivanov@ispras.ru>
*
* Drcov - a DynamoRIO-based tool that collects coverage information
* from a binary. Primary goal this script is to have coverage log
* files that work in Lighthouse.
*
* License: GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include <inttypes.h>
#include <assert.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <glib.h>
#include <qemu-plugin.h>
QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
static char header[] = "DRCOV VERSION: 2\n"
"DRCOV FLAVOR: drcov-64\n"
"Module Table: version 2, count 1\n"
"Columns: id, base, end, entry, path\n";
static FILE *fp;
static const char *file_name = "file.drcov.trace";
static GMutex lock;
typedef struct {
uint32_t start;
uint16_t size;
uint16_t mod_id;
bool exec;
} bb_entry_t;
/* Translated blocks */
static GPtrArray *blocks;
static void printf_header(unsigned long count)
{
fprintf(fp, "%s", header);
const char *path = qemu_plugin_path_to_binary();
uint64_t start_code = qemu_plugin_start_code();
uint64_t end_code = qemu_plugin_end_code();
uint64_t entry = qemu_plugin_entry_code();
fprintf(fp, "0, 0x%lx, 0x%lx, 0x%lx, %s\n",
start_code, end_code, entry, path);
fprintf(fp, "BB Table: %ld bbs\n", count);
}
static void printf_char_array32(uint32_t data)
{
const uint8_t *bytes = (const uint8_t *)(&data);
fwrite(bytes, sizeof(char), sizeof(data), fp);
}
static void printf_char_array16(uint16_t data)
{
const uint8_t *bytes = (const uint8_t *)(&data);
fwrite(bytes, sizeof(char), sizeof(data), fp);
}
static void printf_el(gpointer data, gpointer user_data)
{
bb_entry_t *bb = (bb_entry_t *)data;
if (bb->exec) {
printf_char_array32(bb->start);
printf_char_array16(bb->size);
printf_char_array16(bb->mod_id);
}
g_free(bb);
}
static void count_block(gpointer data, gpointer user_data)
{
unsigned long *count = (unsigned long *) user_data;
bb_entry_t *bb = (bb_entry_t *)data;
if (bb->exec) {
*count = *count + 1;
}
}
static void plugin_exit(qemu_plugin_id_t id, void *p)
{
unsigned long count = 0;
g_mutex_lock(&lock);
g_ptr_array_foreach(blocks, count_block, &count);
/* Print function */
printf_header(count);
g_ptr_array_foreach(blocks, printf_el, NULL);
/* Clear */
g_ptr_array_free(blocks, true);
fclose(fp);
g_mutex_unlock(&lock);
}
static void plugin_init(void)
{
fp = fopen(file_name, "wb");
blocks = g_ptr_array_sized_new(128);
}
static void vcpu_tb_exec(unsigned int cpu_index, void *udata)
{
bb_entry_t *bb = (bb_entry_t *) udata;
g_mutex_lock(&lock);
bb->exec = true;
g_mutex_unlock(&lock);
}
static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
{
uint64_t pc = qemu_plugin_tb_vaddr(tb);
size_t n = qemu_plugin_tb_n_insns(tb);
g_mutex_lock(&lock);
bb_entry_t *bb = g_new0(bb_entry_t, 1);
for (int i = 0; i < n; i++) {
bb->size += qemu_plugin_insn_size(qemu_plugin_tb_get_insn(tb, i));
}
bb->start = pc;
bb->mod_id = 0;
bb->exec = false;
g_ptr_array_add(blocks, bb);
g_mutex_unlock(&lock);
qemu_plugin_register_vcpu_tb_exec_cb(tb, vcpu_tb_exec,
QEMU_PLUGIN_CB_NO_REGS,
(void *)bb);
}
QEMU_PLUGIN_EXPORT
int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info,
int argc, char **argv)
{
for (int i = 0; i < argc; i++) {
g_autofree char **tokens = g_strsplit(argv[i], "=", 2);
if (g_strcmp0(tokens[0], "filename") == 0) {
file_name = g_strdup(tokens[1]);
}
}
plugin_init();
qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
qemu_plugin_register_atexit_cb(id, plugin_exit, NULL);
return 0;
}

22
cpu.c
View File

@ -377,13 +377,33 @@ static Property cpu_common_props[] = {
DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION,
MemoryRegion *),
#endif
DEFINE_PROP_BOOL("start-powered-off", CPUState, start_powered_off, false),
DEFINE_PROP_END_OF_LIST(),
};
static bool cpu_get_start_powered_off(Object *obj, Error **errp)
{
CPUState *cpu = CPU(obj);
return cpu->start_powered_off;
}
static void cpu_set_start_powered_off(Object *obj, bool value, Error **errp)
{
CPUState *cpu = CPU(obj);
cpu->start_powered_off = value;
}
void cpu_class_init_props(DeviceClass *dc)
{
ObjectClass *oc = OBJECT_CLASS(dc);
device_class_set_props(dc, cpu_common_props);
/*
* We can't use DEFINE_PROP_BOOL in the Property array for this
* property, because we want this to be settable after realize.
*/
object_class_property_add_bool(oc, "start-powered-off",
cpu_get_start_powered_off,
cpu_set_start_powered_off);
}
void cpu_exec_initfn(CPUState *cpu)

View File

@ -264,6 +264,19 @@ accepted incorrect commands will return an error. Users should make sure that
all arguments passed to ``device_add`` are consistent with the documented
property types.
``query-sgx`` return value member ``section-size`` (since 7.0)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Member ``section-size`` in return value elements with meta-type ``uint64`` is
deprecated. Use ``sections`` instead.
``query-sgx-capabilities`` return value member ``section-size`` (since 7.0)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Member ``section-size`` in return value elements with meta-type ``uint64`` is
deprecated. Use ``sections`` instead.
System accelerators
-------------------
@ -390,13 +403,6 @@ The above, converted to the current supported format::
linux-user mode CPUs
--------------------
``ppc64abi32`` CPUs (since 5.2)
'''''''''''''''''''''''''''''''
The ``ppc64abi32`` architecture has a number of issues which regularly
trip up our CI testing and is suspected to be quite broken. For that
reason the maintainers strongly suspect no one actually uses it.
MIPS ``I7200`` CPU (since 5.2)
''''''''''''''''''''''''''''''
@ -441,3 +447,20 @@ nanoMIPS ISA
The ``nanoMIPS`` ISA has never been upstreamed to any compiler toolchain.
As it is hard to generate binaries for it, declare it deprecated.
Tools
-----
virtiofsd
'''''''''
There is a new Rust implementation of ``virtiofsd`` at
``https://gitlab.com/virtio-fs/virtiofsd``;
since this is now marked stable, new development should be done on that
rather than the existing C version in the QEMU tree.
The C version will still accept fixes and patches that
are already in development for the moment, but will eventually
be deleted from this tree.
New deployments should use the Rust version, and existing systems
should consider moving to it. The command line and feature set
is very close and moving should be simple.

View File

@ -601,6 +601,27 @@ the upstream Linux kernel in 2018, and it has also been dropped from glibc, so
there is no new Linux development taking place with this architecture. For
running the old binaries, you can use older versions of QEMU.
``ppc64abi32`` CPUs (removed in 7.0)
''''''''''''''''''''''''''''''''''''
The ``ppc64abi32`` architecture has a number of issues which regularly
tripped up the CI testing and was suspected to be quite broken. For that
reason the maintainers strongly suspected no one actually used it.
TCG introspection features
--------------------------
TCG trace-events (since 6.2)
''''''''''''''''''''''''''''
The ability to add new TCG trace points had bit rotted and as the
feature can be replicated with TCG plugins it was removed. If
any user is currently using this feature and needs help with
converting to using TCG plugins they should contact the qemu-devel
mailing list.
System emulator devices
-----------------------

View File

@ -98,7 +98,7 @@ default_role = 'any'
# General information about the project.
project = u'QEMU'
copyright = u'2021, The QEMU Project Developers'
copyright = u'2022, The QEMU Project Developers'
author = u'The QEMU Project Developers'
# The version info for the project you're documenting, acts as replacement for

View File

@ -1630,6 +1630,9 @@ The following files are generated:
``$(prefix)qapi-commands.h``
Function prototypes for the QMP commands specified in the schema
``$(prefix)qapi-commands.trace-events``
Trace event declarations, see :ref:`tracing`.
``$(prefix)qapi-init-commands.h``
Command initialization prototype
@ -1650,6 +1653,13 @@ Example::
void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp);
#endif /* EXAMPLE_QAPI_COMMANDS_H */
$ cat qapi-generated/example-qapi-commands.trace-events
# AUTOMATICALLY GENERATED, DO NOT MODIFY
qmp_enter_my_command(const char *json) "%s"
qmp_exit_my_command(const char *result, bool succeeded) "%s %d"
$ cat qapi-generated/example-qapi-commands.c
[Uninteresting stuff omitted...]
@ -1689,14 +1699,27 @@ Example::
goto out;
}
if (trace_event_get_state_backends(TRACE_QMP_ENTER_MY_COMMAND)) {
g_autoptr(GString) req_json = qobject_to_json(QOBJECT(args));
trace_qmp_enter_my_command(req_json->str);
}
retval = qmp_my_command(arg.arg1, &err);
error_propagate(errp, err);
if (err) {
trace_qmp_exit_my_command(error_get_pretty(err), false);
error_propagate(errp, err);
goto out;
}
qmp_marshal_output_UserDefOne(retval, ret, errp);
if (trace_event_get_state_backends(TRACE_QMP_EXIT_MY_COMMAND)) {
g_autoptr(GString) ret_json = qobject_to_json(*ret);
trace_qmp_exit_my_command(ret_json->str, true);
}
out:
visit_free(v);
v = qapi_dealloc_visitor_new();

View File

@ -12,6 +12,10 @@ patches before submitting.
Formatting and style
********************
The repository includes a ``.editorconfig`` file which can help with
getting the right settings for your preferred $EDITOR. See
`<https://editorconfig.org/>`_ for details.
Whitespace
==========

View File

@ -1324,7 +1324,7 @@ for the architecture in question, for example::
$(configure) --cross-cc-aarch64=aarch64-cc
There is also a ``--cross-cc-flags-ARCH`` flag in case additional
There is also a ``--cross-cc-cflags-ARCH`` flag in case additional
compiler flags are needed to build for a given target.
If you have the ability to run containers as the user the build system

View File

@ -1,3 +1,5 @@
.. _tracing:
=======
Tracing
=======
@ -411,88 +413,3 @@ disabled, this check will have no performance impact.
return ptr;
}
"tcg"
-----
Guest code generated by TCG can be traced by defining an event with the "tcg"
event property. Internally, this property generates two events:
"<eventname>_trans" to trace the event at translation time, and
"<eventname>_exec" to trace the event at execution time.
Instead of using these two events, you should instead use the function
"trace_<eventname>_tcg" during translation (TCG code generation). This function
will automatically call "trace_<eventname>_trans", and will generate the
necessary TCG code to call "trace_<eventname>_exec" during guest code execution.
Events with the "tcg" property can be declared in the "trace-events" file with a
mix of native and TCG types, and "trace_<eventname>_tcg" will gracefully forward
them to the "<eventname>_trans" and "<eventname>_exec" events. Since TCG values
are not known at translation time, these are ignored by the "<eventname>_trans"
event. Because of this, the entry in the "trace-events" file needs two printing
formats (separated by a comma)::
tcg foo(uint8_t a1, TCGv_i32 a2) "a1=%d", "a1=%d a2=%d"
For example::
#include "trace-tcg.h"
void some_disassembly_func (...)
{
uint8_t a1 = ...;
TCGv_i32 a2 = ...;
trace_foo_tcg(a1, a2);
}
This will immediately call::
void trace_foo_trans(uint8_t a1);
and will generate the TCG code to call::
void trace_foo(uint8_t a1, uint32_t a2);
"vcpu"
------
Identifies events that trace vCPU-specific information. It implicitly adds a
"CPUState*" argument, and extends the tracing print format to show the vCPU
information. If used together with the "tcg" property, it adds a second
"TCGv_env" argument that must point to the per-target global TCG register that
points to the vCPU when guest code is executed (usually the "cpu_env" variable).
The "tcg" and "vcpu" properties are currently only honored in the root
./trace-events file.
The following example events::
foo(uint32_t a) "a=%x"
vcpu bar(uint32_t a) "a=%x"
tcg vcpu baz(uint32_t a) "a=%x", "a=%x"
Can be used as::
#include "trace-tcg.h"
CPUArchState *env;
TCGv_ptr cpu_env;
void some_disassembly_func(...)
{
/* trace emitted at this point */
trace_foo(0xd1);
/* trace emitted at this point */
trace_bar(env_cpu(env), 0xd2);
/* trace emitted at this point (env) and when guest code is executed (cpu_env) */
trace_baz_tcg(env_cpu(env), cpu_env, 0xd3);
}
If the translating vCPU has address 0xc1 and code is later executed by vCPU
0xc2, this would be an example output::
// at guest code translation
foo a=0xd1
bar cpu=0xc1 a=0xd2
baz_trans cpu=0xc1 a=0xd3
// at guest code execution
baz_exec cpu=0xc2 a=0xd3

View File

@ -19,10 +19,10 @@ Running a Confidential Guest
To run a confidential guest you need to add two command line parameters:
1. Use "-object" to create a "confidential guest support" object. The
1. Use ``-object`` to create a "confidential guest support" object. The
type and parameters will vary with the specific mechanism to be
used
2. Set the "confidential-guest-support" machine parameter to the ID of
2. Set the ``confidential-guest-support`` machine parameter to the ID of
the object from (1).
Example (for AMD SEV)::
@ -37,13 +37,8 @@ Supported mechanisms
Currently supported confidential guest mechanisms are:
AMD Secure Encrypted Virtualization (SEV)
docs/amd-memory-encryption.txt
POWER Protected Execution Facility (PEF)
docs/papr-pef.txt
s390x Protected Virtualization (PV)
docs/system/s390x/protvirt.rst
* AMD Secure Encrypted Virtualization (SEV) (see :doc:`i386/amd-memory-encryption`)
* POWER Protected Execution Facility (PEF) (see :ref:`power-papr-protected-execution-facility-pef`)
* s390x Protected Virtualization (PV) (see :doc:`s390x/protvirt`)
Other mechanisms may be supported in future.

View File

@ -1,3 +1,6 @@
AMD Secure Encrypted Virtualization (SEV)
=========================================
Secure Encrypted Virtualization (SEV) is a feature found on AMD processors.
SEV is an extension to the AMD-V architecture which supports running encrypted
@ -24,17 +27,18 @@ the hypervisor to satisfy the requested function.
Launching
---------
Boot images (such as bios) must be encrypted before a guest can be booted. The
MEMORY_ENCRYPT_OP ioctl provides commands to encrypt the images: LAUNCH_START,
LAUNCH_UPDATE_DATA, LAUNCH_MEASURE and LAUNCH_FINISH. These four commands
``MEMORY_ENCRYPT_OP`` ioctl provides commands to encrypt the images: ``LAUNCH_START``,
``LAUNCH_UPDATE_DATA``, ``LAUNCH_MEASURE`` and ``LAUNCH_FINISH``. These four commands
together generate a fresh memory encryption key for the VM, encrypt the boot
images and provide a measurement than can be used as an attestation of a
successful launch.
For a SEV-ES guest, the LAUNCH_UPDATE_VMSA command is also used to encrypt the
For a SEV-ES guest, the ``LAUNCH_UPDATE_VMSA`` command is also used to encrypt the
guest register state, or VM save area (VMSA), for all of the guest vCPUs.
LAUNCH_START is called first to create a cryptographic launch context within
``LAUNCH_START`` is called first to create a cryptographic launch context within
the firmware. To create this context, guest owner must provide a guest policy,
its public Diffie-Hellman key (PDH) and session parameters. These inputs
should be treated as a binary blob and must be passed as-is to the SEV firmware.
@ -45,13 +49,13 @@ in bad measurement). The guest policy is a 4-byte data structure containing
several flags that restricts what can be done on a running SEV guest.
See KM Spec section 3 and 6.2 for more details.
The guest policy can be provided via the 'policy' property (see below)
The guest policy can be provided via the ``policy`` property::
# ${QEMU} \
sev-guest,id=sev0,policy=0x1...\
Setting the "SEV-ES required" policy bit (bit 2) will launch the guest as a
SEV-ES guest (see below)
SEV-ES guest::
# ${QEMU} \
sev-guest,id=sev0,policy=0x5...\
@ -60,22 +64,22 @@ The guest owner provided DH certificate and session parameters will be used to
establish a cryptographic session with the guest owner to negotiate keys used
for the attestation.
The DH certificate and session blob can be provided via the 'dh-cert-file' and
'session-file' properties (see below)
The DH certificate and session blob can be provided via the ``dh-cert-file`` and
``session-file`` properties::
# ${QEMU} \
sev-guest,id=sev0,dh-cert-file=<file1>,session-file=<file2>
LAUNCH_UPDATE_DATA encrypts the memory region using the cryptographic context
created via the LAUNCH_START command. If required, this command can be called
``LAUNCH_UPDATE_DATA`` encrypts the memory region using the cryptographic context
created via the ``LAUNCH_START`` command. If required, this command can be called
multiple times to encrypt different memory regions. The command also calculates
the measurement of the memory contents as it encrypts.
LAUNCH_UPDATE_VMSA encrypts all the vCPU VMSAs for a SEV-ES guest using the
cryptographic context created via the LAUNCH_START command. The command also
``LAUNCH_UPDATE_VMSA`` encrypts all the vCPU VMSAs for a SEV-ES guest using the
cryptographic context created via the ``LAUNCH_START`` command. The command also
calculates the measurement of the VMSAs as it encrypts them.
LAUNCH_MEASURE can be used to retrieve the measurement of encrypted memory and,
``LAUNCH_MEASURE`` can be used to retrieve the measurement of encrypted memory and,
for a SEV-ES guest, encrypted VMSAs. This measurement is a signature of the
memory contents and, for a SEV-ES guest, the VMSA contents, that can be sent
to the guest owner as an attestation that the memory and VMSAs were encrypted
@ -85,19 +89,19 @@ Since the guest owner knows the initial contents of the guest at boot, the
attestation measurement can be verified by comparing it to what the guest owner
expects.
LAUNCH_FINISH finalizes the guest launch and destroys the cryptographic
``LAUNCH_FINISH`` finalizes the guest launch and destroys the cryptographic
context.
See SEV KM API Spec [1] 'Launching a guest' usage flow (Appendix A) for the
See SEV KM API Spec ([SEVKM]_) 'Launching a guest' usage flow (Appendix A) for the
complete flow chart.
To launch a SEV guest
To launch a SEV guest::
# ${QEMU} \
-machine ...,confidential-guest-support=sev0 \
-object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1
To launch a SEV-ES guest
To launch a SEV-ES guest::
# ${QEMU} \
-machine ...,confidential-guest-support=sev0 \
@ -106,6 +110,7 @@ To launch a SEV-ES guest
An SEV-ES guest has some restrictions as compared to a SEV guest. Because the
guest register state is encrypted and cannot be updated by the VMM/hypervisor,
a SEV-ES guest:
- Does not support SMM - SMM support requires updating the guest register
state.
- Does not support reboot - a system reset requires updating the guest register
@ -114,35 +119,42 @@ a SEV-ES guest:
manage booting APs.
Debugging
-----------
---------
Since the memory contents of a SEV guest are encrypted, hypervisor access to
the guest memory will return cipher text. If the guest policy allows debugging,
then a hypervisor can use the DEBUG_DECRYPT and DEBUG_ENCRYPT commands to access
the guest memory region for debug purposes. This is not supported in QEMU yet.
Snapshot/Restore
-----------------
----------------
TODO
Live Migration
----------------
---------------
TODO
References
-----------------
----------
AMD Memory Encryption whitepaper:
https://developer.amd.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
`AMD Memory Encryption whitepaper
<https://developer.amd.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf>`_
Secure Encrypted Virtualization Key Management:
[1] http://developer.amd.com/wordpress/media/2017/11/55766_SEV-KM-API_Specification.pdf
.. [SEVKM] `Secure Encrypted Virtualization Key Management
<http://developer.amd.com/wordpress/media/2017/11/55766_SEV-KM-API_Specification.pdf>`_
KVM Forum slides:
http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
https://www.linux-kvm.org/images/9/94/Extending-Secure-Encrypted-Virtualization-with-SEV-ES-Thomas-Lendacky-AMD.pdf
AMD64 Architecture Programmer's Manual:
http://support.amd.com/TechDocs/24593.pdf
SME is section 7.10
SEV is section 15.34
SEV-ES is section 15.35
* `AMDs Virtualization Memory Encryption (2016)
<http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf>`_
* `Extending Secure Encrypted Virtualization With SEV-ES (2018)
<https://www.linux-kvm.org/images/9/94/Extending-Secure-Encrypted-Virtualization-with-SEV-ES-Thomas-Lendacky-AMD.pdf>`_
`AMD64 Architecture Programmer's Manual:
<http://support.amd.com/TechDocs/24593.pdf>`_
* SME is section 7.10
* SEV is section 15.34
* SEV-ES is section 15.35

View File

@ -34,3 +34,4 @@ or Hypervisor.Framework.
targets
security
multi-process
confidential-guest-support

View File

@ -224,6 +224,8 @@ nested. Combinations not shown in the table are not available.
.. [3] Introduced on Power10 machines.
.. _power-papr-protected-execution-facility-pef:
POWER (PAPR) Protected Execution Facility (PEF)
-----------------------------------------------

View File

@ -23,9 +23,9 @@ The ``virt`` machine supports the following devices:
* 1 generic PCIe host bridge
* The fw_cfg device that allows a guest to obtain data from QEMU
Note that the default CPU is a generic RV32GC/RV64GC. Optional extensions
can be enabled via command line parameters, e.g.: ``-cpu rv64,x-h=true``
enables the hypervisor extension for RV64.
The hypervisor extension has been enabled for the default CPU, so virtual
machines with hypervisor extension can simply be used without explicitly
declaring.
Hardware configuration information
----------------------------------

View File

@ -28,6 +28,7 @@ Architectural features
i386/cpu
i386/kvm-pv
i386/sgx
i386/amd-memory-encryption
.. _pcsys_005freq:

View File

@ -463,7 +463,7 @@ Command description:
``--skip-broken-bitmaps`` is also specified to copy only the
consistent bitmaps.
.. option:: create [--object OBJECTDEF] [-q] [-f FMT] [-b BACKING_FILE] [-F BACKING_FMT] [-u] [-o OPTIONS] FILENAME [SIZE]
.. option:: create [--object OBJECTDEF] [-q] [-f FMT] [-b BACKING_FILE [-F BACKING_FMT]] [-u] [-o OPTIONS] FILENAME [SIZE]
Create the new disk image *FILENAME* of size *SIZE* and format
*FMT*. Depending on the file format, you can add one or more *OPTIONS*

View File

@ -76,7 +76,7 @@ Standard options:
.. option:: --export [type=]nbd,id=<id>,node-name=<node-name>[,name=<export-name>][,writable=on|off][,bitmap=<name>]
--export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,addr.type=unix,addr.path=<socket-path>[,writable=on|off][,logical-block-size=<block-size>][,num-queues=<num-queues>]
--export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,addr.type=fd,addr.str=<fd>[,writable=on|off][,logical-block-size=<block-size>][,num-queues=<num-queues>]
--export [type=]fuse,id=<id>,node-name=<node-name>,mountpoint=<file>[,growable=on|off][,writable=on|off]
--export [type=]fuse,id=<id>,node-name=<node-name>,mountpoint=<file>[,growable=on|off][,writable=on|off][,allow-other=on|off|auto]
is a block export definition. ``node-name`` is the block node that should be
exported. ``writable`` determines whether or not the export allows write
@ -103,7 +103,12 @@ Standard options:
mounted). Consequently, applications that have opened the given file before
the export became active will continue to see its original content. If
``growable`` is set, writes after the end of the exported file will grow the
block node to fit.
block node to fit. The ``allow-other`` option controls whether users other
than the user running the process will be allowed to access the export. Note
that enabling this option as a non-root user requires enabling the
user_allow_other option in the global fuse.conf configuration file. Setting
``allow-other`` to auto (the default) will try enabling this option, and on
error fall back to disabling it.
.. option:: --monitor MONITORDEF

View File

@ -166,7 +166,6 @@ Other binaries
- user mode (PowerPC)
* ``qemu-ppc64abi32`` TODO.
* ``qemu-ppc64`` TODO.
* ``qemu-ppc`` TODO.

View File

@ -10,6 +10,7 @@ config ACPI_X86
select ACPI_HMAT
select ACPI_PIIX4
select ACPI_PCIHP
select ACPI_ERST
config ACPI_X86_ICH
bool
@ -60,3 +61,8 @@ config ACPI_HW_REDUCED
select ACPI
select ACPI_MEMORY_HOTPLUG
select ACPI_NVDIMM
config ACPI_ERST
bool
default y
depends on ACPI && PCI

View File

@ -1724,9 +1724,9 @@ void acpi_table_begin(AcpiTable *desc, GArray *array)
build_append_int_noprefix(array, 0, 4); /* Length */
build_append_int_noprefix(array, desc->rev, 1); /* Revision */
build_append_int_noprefix(array, 0, 1); /* Checksum */
build_append_padded_str(array, desc->oem_id, 6, ' '); /* OEMID */
build_append_padded_str(array, desc->oem_id, 6, '\0'); /* OEMID */
/* OEM Table ID */
build_append_padded_str(array, desc->oem_table_id, 8, ' ');
build_append_padded_str(array, desc->oem_table_id, 8, '\0');
build_append_int_noprefix(array, 1, 4); /* OEM Revision */
g_array_append_vals(array, ACPI_BUILD_APPNAME8, 4); /* Creator ID */
build_append_int_noprefix(array, 1, 4); /* Creator Revision */

View File

@ -297,7 +297,6 @@ static const VMStateDescription vmstate_cpuhp_sts = {
.name = "CPU hotplug device state",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_BOOL(is_inserting, AcpiCpuStatus),
VMSTATE_BOOL(is_removing, AcpiCpuStatus),
@ -311,7 +310,6 @@ const VMStateDescription vmstate_cpu_hotplug = {
.name = "CPU hotplug state",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32(selector, CPUHotplugState),
VMSTATE_UINT8(command, CPUHotplugState),

1051
hw/acpi/erst.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -163,7 +163,6 @@ static const VMStateDescription vmstate_memhp_state = {
.name = "ich9_pm/memhp",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.needed = vmstate_test_use_memhp,
.fields = (VMStateField[]) {
VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, ICH9LPCPMRegs),
@ -181,7 +180,6 @@ static const VMStateDescription vmstate_tco_io_state = {
.name = "ich9_pm/tco",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.needed = vmstate_test_use_tco,
.fields = (VMStateField[]) {
VMSTATE_STRUCT(tco_regs, ICH9LPCPMRegs, 1, vmstate_tco_io_sts,
@ -208,7 +206,6 @@ static const VMStateDescription vmstate_cpuhp_state = {
.name = "ich9_pm/cpuhp",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.needed = vmstate_test_use_cpuhp,
.pre_load = vmstate_cpuhp_pre_load,
.fields = (VMStateField[]) {

View File

@ -318,7 +318,6 @@ static const VMStateDescription vmstate_memhp_sts = {
.name = "memory hotplug device state",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_BOOL(is_enabled, MemStatus),
VMSTATE_BOOL(is_inserting, MemStatus),
@ -332,7 +331,6 @@ const VMStateDescription vmstate_memory_hotplug = {
.name = "memory hotplug state",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32(selector, MemHotplugState),
VMSTATE_STRUCT_VARRAY_POINTER_UINT32(devs, MemHotplugState, dev_count,

View File

@ -22,6 +22,7 @@ acpi_ss.add(when: 'CONFIG_ACPI_PCIHP', if_true: files('pcihp.c'))
acpi_ss.add(when: 'CONFIG_ACPI_PCIHP', if_false: files('acpi-pci-hotplug-stub.c'))
acpi_ss.add(when: 'CONFIG_ACPI_VIOT', if_true: files('viot.c'))
acpi_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true: files('ich9.c', 'tco.c'))
acpi_ss.add(when: 'CONFIG_ACPI_ERST', if_true: files('erst.c'))
acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'), if_false: files('ipmi-stub.c'))
acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c'))
acpi_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c'))

View File

@ -230,7 +230,6 @@ static const VMStateDescription vmstate_memhp_state = {
.name = "piix4_pm/memhp",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.needed = vmstate_test_use_memhp,
.fields = (VMStateField[]) {
VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, PIIX4PMState),
@ -255,7 +254,6 @@ static const VMStateDescription vmstate_cpuhp_state = {
.name = "piix4_pm/cpuhp",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.needed = vmstate_test_use_cpuhp,
.pre_load = vmstate_cpuhp_pre_load,
.fields = (VMStateField[]) {

View File

@ -239,7 +239,6 @@ const VMStateDescription vmstate_tco_io_sts = {
.name = "tco io device status",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT16(tco.rld, TCOIORegs),
VMSTATE_UINT8(tco.din, TCOIORegs),

View File

@ -55,3 +55,18 @@ piix4_gpe_writeb(uint64_t addr, unsigned width, uint64_t val) "addr: 0x%" PRIx64
# tco.c
tco_timer_reload(int ticks, int msec) "ticks=%d (%d ms)"
tco_timer_expired(int timeouts_no, bool strap, bool no_reboot) "timeouts_no=%d no_reboot=%d/%d"
# erst.c
acpi_erst_reg_write(uint64_t addr, uint64_t val, unsigned size) "addr: 0x%04" PRIx64 " <== 0x%016" PRIx64 " (size: %u)"
acpi_erst_reg_read(uint64_t addr, uint64_t val, unsigned size) " addr: 0x%04" PRIx64 " ==> 0x%016" PRIx64 " (size: %u)"
acpi_erst_mem_write(uint64_t addr, uint64_t val, unsigned size) "addr: 0x%06" PRIx64 " <== 0x%016" PRIx64 " (size: %u)"
acpi_erst_mem_read(uint64_t addr, uint64_t val, unsigned size) " addr: 0x%06" PRIx64 " ==> 0x%016" PRIx64 " (size: %u)"
acpi_erst_pci_bar_0(uint64_t addr) "BAR0: 0x%016" PRIx64
acpi_erst_pci_bar_1(uint64_t addr) "BAR1: 0x%016" PRIx64
acpi_erst_realizefn_in(void)
acpi_erst_realizefn_out(unsigned size) "total nvram size %u bytes"
acpi_erst_reset_in(unsigned record_count) "record_count %u"
acpi_erst_reset_out(unsigned record_count) "record_count %u"
acpi_erst_post_load(void *header, unsigned slot_size) "header: 0x%p slot_size %u"
acpi_erst_class_init_in(void)
acpi_erst_class_init_out(void)

View File

@ -235,11 +235,10 @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
/* CPUs */
for (i = 0; i < AW_H3_NUM_CPUS; i++) {
/* Provide Power State Coordination Interface */
qdev_prop_set_int32(DEVICE(&s->cpus[i]), "psci-conduit",
QEMU_PSCI_CONDUIT_SMC);
/* Disable secondary CPUs */
/*
* Disable secondary CPUs. Guest EL3 firmware will start
* them via CPU reset control registers.
*/
qdev_prop_set_bit(DEVICE(&s->cpus[i]), "start-powered-off",
i > 0);

View File

@ -520,8 +520,8 @@ static const VMStateDescription vmstate_armv7m = {
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_CLOCK(refclk, SysTickState),
VMSTATE_CLOCK(cpuclk, SysTickState),
VMSTATE_CLOCK(refclk, ARMv7MState),
VMSTATE_CLOCK(cpuclk, ARMv7MState),
VMSTATE_END_OF_LIST()
}
};

View File

@ -431,7 +431,6 @@ static void aspeed_machine_init(MachineState *machine)
aspeed_board_binfo.ram_size = machine->ram_size;
aspeed_board_binfo.loader_start = sc->memmap[ASPEED_DEV_SDRAM];
aspeed_board_binfo.nb_cpus = sc->num_cpus;
if (amc->i2c_init) {
amc->i2c_init(bmc);

View File

@ -29,7 +29,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
[ASPEED_DEV_PWM] = 0x1E610000,
[ASPEED_DEV_FMC] = 0x1E620000,
[ASPEED_DEV_SPI1] = 0x1E630000,
[ASPEED_DEV_SPI2] = 0x1E641000,
[ASPEED_DEV_SPI2] = 0x1E631000,
[ASPEED_DEV_EHCI1] = 0x1E6A1000,
[ASPEED_DEV_EHCI2] = 0x1E6A3000,
[ASPEED_DEV_MII1] = 0x1E650000,

View File

@ -478,12 +478,13 @@ static void fdt_add_psci_node(void *fdt)
}
/*
* If /psci node is present in provided DTB, assume that no fixup
* is necessary and all PSCI configuration should be taken as-is
* A pre-existing /psci node might specify function ID values
* that don't match QEMU's PSCI implementation. Delete the whole
* node and put our own in instead.
*/
rc = fdt_path_offset(fdt, "/psci");
if (rc >= 0) {
return;
qemu_fdt_nop_node(fdt, "/psci");
}
qemu_fdt_add_subnode(fdt, "/psci");
@ -804,7 +805,7 @@ static void do_cpu_reset(void *opaque)
set_kernel_args(info, as);
}
}
} else {
} else if (info->secondary_cpu_reset_hook) {
info->secondary_cpu_reset_hook(cpu, info);
}
}
@ -1030,16 +1031,6 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
elf_machine = EM_ARM;
}
if (!info->secondary_cpu_reset_hook) {
info->secondary_cpu_reset_hook = default_reset_secondary;
}
if (!info->write_secondary_boot) {
info->write_secondary_boot = default_write_secondary;
}
if (info->nb_cpus == 0)
info->nb_cpus = 1;
/* Assume that raw images are linux kernels, and ELF images are not. */
kernel_size = arm_load_elf(info, &elf_entry, &image_low_addr,
&image_high_addr, elf_machine, as);
@ -1216,9 +1207,6 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
write_bootloader("bootloader", info->loader_start,
primary_loader, fixupcontext, as);
if (info->nb_cpus > 1) {
info->write_secondary_boot(cpu, info);
}
if (info->write_board_setup) {
info->write_board_setup(cpu, info);
}
@ -1299,6 +1287,9 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
{
CPUState *cs;
AddressSpace *as = arm_boot_address_space(cpu, info);
int boot_el;
CPUARMState *env = &cpu->env;
int nb_cpus = 0;
/*
* CPU objects (unlike devices) are not automatically reset on system
@ -1308,6 +1299,7 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
*/
for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
nb_cpus++;
}
/*
@ -1329,6 +1321,87 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
arm_setup_direct_kernel_boot(cpu, info);
}
/*
* Disable the PSCI conduit if it is set up to target the same
* or a lower EL than the one we're going to start the guest code in.
* This logic needs to agree with the code in do_cpu_reset() which
* decides whether we're going to boot the guest in the highest
* supported exception level or in a lower one.
*/
/*
* If PSCI is enabled, then SMC calls all go to the PSCI handler and
* are never emulated to trap into guest code. It therefore does not
* make sense for the board to have a setup code fragment that runs
* in Secure, because this will probably need to itself issue an SMC of some
* kind as part of its operation.
*/
assert(info->psci_conduit == QEMU_PSCI_CONDUIT_DISABLED ||
!info->secure_board_setup);
/* Boot into highest supported EL ... */
if (arm_feature(env, ARM_FEATURE_EL3)) {
boot_el = 3;
} else if (arm_feature(env, ARM_FEATURE_EL2)) {
boot_el = 2;
} else {
boot_el = 1;
}
/* ...except that if we're booting Linux we adjust the EL we boot into */
if (info->is_linux && !info->secure_boot) {
boot_el = arm_feature(env, ARM_FEATURE_EL2) ? 2 : 1;
}
if ((info->psci_conduit == QEMU_PSCI_CONDUIT_HVC && boot_el >= 2) ||
(info->psci_conduit == QEMU_PSCI_CONDUIT_SMC && boot_el == 3)) {
info->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
}
if (info->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
Object *cpuobj = OBJECT(cs);
object_property_set_int(cpuobj, "psci-conduit", info->psci_conduit,
&error_abort);
/*
* Secondary CPUs start in PSCI powered-down state. Like the
* code in do_cpu_reset(), we assume first_cpu is the primary
* CPU.
*/
if (cs != first_cpu) {
object_property_set_bool(cpuobj, "start-powered-off", true,
&error_abort);
}
}
}
if (info->psci_conduit == QEMU_PSCI_CONDUIT_DISABLED &&
info->is_linux && nb_cpus > 1) {
/*
* We're booting Linux but not using PSCI, so for SMP we need
* to write a custom secondary CPU boot loader stub, and arrange
* for the secondary CPU reset to make the accompanying initialization.
*/
if (!info->secondary_cpu_reset_hook) {
info->secondary_cpu_reset_hook = default_reset_secondary;
}
if (!info->write_secondary_boot) {
info->write_secondary_boot = default_write_secondary;
}
info->write_secondary_boot(cpu, info);
} else {
/*
* No secondary boot stub; don't use the reset hook that would
* have set the CPU up to call it
*/
info->write_secondary_boot = NULL;
info->secondary_cpu_reset_hook = NULL;
}
/*
* arm_load_dtb() may add a PSCI node so it must be called after we have
* decided whether to enable PSCI and set the psci-conduit CPU properties.
*/
if (!info->skip_dtb_autoload && have_dtb(info)) {
if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as, ms) < 0) {
exit(1);

View File

@ -67,7 +67,6 @@ static unsigned long exynos4_board_ram_size[EXYNOS4_NUM_OF_BOARDS] = {
static struct arm_boot_info exynos4_board_binfo = {
.loader_start = EXYNOS4210_BASE_BOOT_ADDR,
.smp_loader_start = EXYNOS4210_SMP_BOOT_ADDR,
.nb_cpus = EXYNOS4210_NCPUS,
.write_secondary_boot = exynos4210_write_secondary,
};

View File

@ -166,8 +166,6 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
return;
}
object_property_set_int(OBJECT(&s->cpu), "psci-conduit",
QEMU_PSCI_CONDUIT_SMC, &error_abort);
qdev_realize(DEVICE(&s->cpu), NULL, &error_abort);
/*

View File

@ -159,9 +159,6 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
for (i = 0; i < smp_cpus; i++) {
o = OBJECT(&s->cpu[i]);
object_property_set_int(o, "psci-conduit", QEMU_PSCI_CONDUIT_SMC,
&error_abort);
/* On uniprocessor, the CBAR is set to 0 */
if (smp_cpus > 1) {
object_property_set_int(o, "reset-cbar", FSL_IMX7_A7MPCORE_ADDR,
@ -169,7 +166,10 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
}
if (i) {
/* Secondary CPUs start in PSCI powered-down state */
/*
* Secondary CPUs start in powered-down state (and can be
* powered up via the SRC system reset controller)
*/
object_property_set_bool(o, "start-powered-off", true,
&error_abort);
}

View File

@ -48,66 +48,6 @@
/* Board init. */
static void hb_write_board_setup(ARMCPU *cpu,
const struct arm_boot_info *info)
{
arm_write_secure_board_setup_dummy_smc(cpu, info, MVBAR_ADDR);
}
static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
{
int n;
uint32_t smpboot[] = {
0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */
0xe210000f, /* ands r0, r0, #0x0f */
0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
0xe0830200, /* add r0, r3, r0, lsl #4 */
0xe59f2024, /* ldr r2, privbase */
0xe3a01001, /* mov r1, #1 */
0xe5821100, /* str r1, [r2, #256] - set GICC_CTLR.Enable */
0xe3a010ff, /* mov r1, #0xff */
0xe5821104, /* str r1, [r2, #260] - set GICC_PMR.Priority to 0xff */
0xf57ff04f, /* dsb */
0xe320f003, /* wfi */
0xe5901000, /* ldr r1, [r0] */
0xe1110001, /* tst r1, r1 */
0x0afffffb, /* beq <wfi> */
0xe12fff11, /* bx r1 */
MPCORE_PERIPHBASE /* privbase: MPCore peripheral base address. */
};
for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
smpboot[n] = tswap32(smpboot[n]);
}
rom_add_blob_fixed_as("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR,
arm_boot_address_space(cpu, info));
}
static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
{
CPUARMState *env = &cpu->env;
switch (info->nb_cpus) {
case 4:
address_space_stl_notdirty(&address_space_memory,
SMP_BOOT_REG + 0x30, 0,
MEMTXATTRS_UNSPECIFIED, NULL);
/* fallthrough */
case 3:
address_space_stl_notdirty(&address_space_memory,
SMP_BOOT_REG + 0x20, 0,
MEMTXATTRS_UNSPECIFIED, NULL);
/* fallthrough */
case 2:
address_space_stl_notdirty(&address_space_memory,
SMP_BOOT_REG + 0x10, 0,
MEMTXATTRS_UNSPECIFIED, NULL);
env->regs[15] = SMP_BOOT_ADDR;
break;
default:
break;
}
}
#define NUM_REGS 0x200
static void hb_regs_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
@ -271,12 +211,6 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
object_property_set_int(cpuobj, "psci-conduit", QEMU_PSCI_CONDUIT_SMC,
&error_abort);
if (n) {
/* Secondary CPUs start in PSCI powered-down state */
object_property_set_bool(cpuobj, "start-powered-off", true,
&error_abort);
}
if (object_property_find(cpuobj, "reset-cbar")) {
object_property_set_int(cpuobj, "reset-cbar", MPCORE_PERIPHBASE,
&error_abort);
@ -390,13 +324,9 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
* clear that the value is meaningless.
*/
highbank_binfo.board_id = -1;
highbank_binfo.nb_cpus = smp_cpus;
highbank_binfo.loader_start = 0;
highbank_binfo.write_secondary_boot = hb_write_secondary;
highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR;
highbank_binfo.write_board_setup = hb_write_board_setup;
highbank_binfo.secure_board_setup = true;
highbank_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
arm_load_kernel(ARM_CPU(first_cpu), machine, &highbank_binfo);
}

View File

@ -114,8 +114,7 @@ static void imx25_pdk_init(MachineState *machine)
imx25_pdk_binfo.ram_size = machine->ram_size;
imx25_pdk_binfo.loader_start = FSL_IMX25_SDRAM0_ADDR;
imx25_pdk_binfo.board_id = 1771,
imx25_pdk_binfo.nb_cpus = 1;
imx25_pdk_binfo.board_id = 1771;
for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
BusState *bus;

View File

@ -124,7 +124,6 @@ static void kzm_init(MachineState *machine)
}
kzm_binfo.ram_size = machine->ram_size;
kzm_binfo.nb_cpus = 1;
if (!qtest_enabled()) {
arm_load_kernel(&s->soc.cpu, machine, &kzm_binfo);

View File

@ -34,7 +34,7 @@ static void mcimx6ul_evk_init(MachineState *machine)
.loader_start = FSL_IMX6UL_MMDC_ADDR,
.board_id = -1,
.ram_size = machine->ram_size,
.nb_cpus = machine->smp.cpus,
.psci_conduit = QEMU_PSCI_CONDUIT_SMC,
};
s = FSL_IMX6UL(object_new(TYPE_FSL_IMX6UL));

View File

@ -36,7 +36,7 @@ static void mcimx7d_sabre_init(MachineState *machine)
.loader_start = FSL_IMX7_MMDC_ADDR,
.board_id = -1,
.ram_size = machine->ram_size,
.nb_cpus = machine->smp.cpus,
.psci_conduit = QEMU_PSCI_CONDUIT_SMC,
};
s = FSL_IMX7(object_new(TYPE_FSL_IMX7));

View File

@ -355,10 +355,7 @@ static struct arm_boot_info npcm7xx_binfo = {
void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
{
NPCM7xxClass *sc = NPCM7XX_GET_CLASS(soc);
npcm7xx_binfo.ram_size = machine->ram_size;
npcm7xx_binfo.nb_cpus = sc->num_cpus;
arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
}

View File

@ -21,7 +21,6 @@
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
#include "exec/address-spaces.h"
#include "hw/hw.h"
@ -35,6 +34,7 @@
#include "sysemu/qtest.h"
#include "sysemu/reset.h"
#include "sysemu/runstate.h"
#include "sysemu/rtc.h"
#include "qemu/range.h"
#include "hw/sysbus.h"
#include "qemu/cutils.h"

View File

@ -25,9 +25,7 @@
#include "hw/qdev-properties.h"
#include "hw/arm/allwinner-h3.h"
static struct arm_boot_info orangepi_binfo = {
.nb_cpus = AW_H3_NUM_CPUS,
};
static struct arm_boot_info orangepi_binfo;
static void orangepi_init(MachineState *machine)
{
@ -105,6 +103,7 @@ static void orangepi_init(MachineState *machine)
}
orangepi_binfo.loader_start = h3->memmap[AW_H3_DEV_SDRAM];
orangepi_binfo.ram_size = machine->ram_size;
orangepi_binfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
arm_load_kernel(ARM_CPU(first_cpu), machine, &orangepi_binfo);
}

View File

@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
#include "qapi/error.h"
@ -27,6 +26,7 @@
#include "chardev/char-fe.h"
#include "sysemu/blockdev.h"
#include "sysemu/qtest.h"
#include "sysemu/rtc.h"
#include "qemu/cutils.h"
#include "qemu/log.h"
#include "qom/object.h"

View File

@ -204,7 +204,6 @@ static void setup_boot(MachineState *machine, RaspiProcessorId processor_id,
s->binfo.board_id = MACH_TYPE_BCM2708;
s->binfo.ram_size = ram_size;
s->binfo.nb_cpus = machine->smp.cpus;
if (processor_id <= PROCESSOR_ID_BCM2836) {
/*

View File

@ -363,7 +363,6 @@ static void realview_init(MachineState *machine,
memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
realview_binfo.ram_size = ram_size;
realview_binfo.nb_cpus = smp_cpus;
realview_binfo.board_id = realview_board_id[board_type];
realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
arm_load_kernel(ARM_CPU(first_cpu), machine, &realview_binfo);

View File

@ -93,7 +93,6 @@ static void sabrelite_init(MachineState *machine)
}
sabrelite_binfo.ram_size = machine->ram_size;
sabrelite_binfo.nb_cpus = machine->smp.cpus;
sabrelite_binfo.secure_boot = true;
sabrelite_binfo.write_secondary_boot = sabrelite_write_secondary;
sabrelite_binfo.secondary_cpu_reset_hook = sabrelite_reset_secondary;

View File

@ -776,7 +776,6 @@ static void sbsa_ref_init(MachineState *machine)
create_secure_ec(secure_sysmem);
sms->bootinfo.ram_size = machine->ram_size;
sms->bootinfo.nb_cpus = smp_cpus;
sms->bootinfo.board_id = -1;
sms->bootinfo.loader_start = sbsa_ref_memmap[SBSA_MEM].base;
sms->bootinfo.get_dtb = sbsa_ref_dtb;

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